aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/Makefile156
-rw-r--r--main/abstract_jb.c822
-rw-r--r--main/acl.c590
-rw-r--r--main/aescrypt.c317
-rw-r--r--main/aeskey.c469
-rw-r--r--main/aesopt.h1029
-rw-r--r--main/aestab.c232
-rw-r--r--main/alaw.c101
-rw-r--r--main/app.c1452
-rw-r--r--main/ast_expr2.c2859
-rw-r--r--main/ast_expr2.fl414
-rw-r--r--main/ast_expr2.h112
-rw-r--r--main/ast_expr2.y1045
-rw-r--r--main/ast_expr2f.c3349
-rw-r--r--main/asterisk.c3223
-rw-r--r--main/astmm.c498
-rw-r--r--main/astobj2.c771
-rw-r--r--main/audiohook.c721
-rw-r--r--main/autoservice.c319
-rw-r--r--main/buildinfo.c33
-rw-r--r--main/callerid.c1117
-rw-r--r--main/cdr.c1499
-rw-r--r--main/channel.c4876
-rw-r--r--main/chanvars.c87
-rw-r--r--main/cli.c2037
-rw-r--r--main/coef_in.h13
-rw-r--r--main/coef_out.h4
-rw-r--r--main/config.c1520
-rw-r--r--main/cryptostub.c95
-rw-r--r--main/db.c592
-rw-r--r--main/db1-ast/Makefile71
-rw-r--r--main/db1-ast/btree/bt_close.c182
-rw-r--r--main/db1-ast/btree/bt_conv.c221
-rw-r--r--main/db1-ast/btree/bt_debug.c329
-rw-r--r--main/db1-ast/btree/bt_delete.c657
-rw-r--r--main/db1-ast/btree/bt_get.c105
-rw-r--r--main/db1-ast/btree/bt_open.c458
-rw-r--r--main/db1-ast/btree/bt_overflow.c228
-rw-r--r--main/db1-ast/btree/bt_page.c100
-rw-r--r--main/db1-ast/btree/bt_put.c321
-rw-r--r--main/db1-ast/btree/bt_search.c213
-rw-r--r--main/db1-ast/btree/bt_seq.c460
-rw-r--r--main/db1-ast/btree/bt_split.c829
-rw-r--r--main/db1-ast/btree/bt_utils.c260
-rw-r--r--main/db1-ast/btree/btree.h391
-rw-r--r--main/db1-ast/btree/extern.h70
-rw-r--r--main/db1-ast/db/db.c103
-rw-r--r--main/db1-ast/hash/README72
-rw-r--r--main/db1-ast/hash/extern.h65
-rw-r--r--main/db1-ast/hash/hash.c999
-rw-r--r--main/db1-ast/hash/hash.h293
-rw-r--r--main/db1-ast/hash/hash_bigkey.c668
-rw-r--r--main/db1-ast/hash/hash_buf.c355
-rw-r--r--main/db1-ast/hash/hash_func.c225
-rw-r--r--main/db1-ast/hash/hash_log2.c56
-rw-r--r--main/db1-ast/hash/hash_page.c946
-rw-r--r--main/db1-ast/hash/hsearch.c107
-rw-r--r--main/db1-ast/hash/ndbm.c235
-rw-r--r--main/db1-ast/hash/page.h92
-rw-r--r--main/db1-ast/hash/search.h51
-rw-r--r--main/db1-ast/include/circ-queue.h131
-rw-r--r--main/db1-ast/include/compat.h49
-rw-r--r--main/db1-ast/include/db.h250
-rw-r--r--main/db1-ast/include/mpool.h115
-rw-r--r--main/db1-ast/include/ndbm.h79
-rw-r--r--main/db1-ast/libdb.map11
-rw-r--r--main/db1-ast/mpool/README7
-rw-r--r--main/db1-ast/mpool/mpool.c498
-rw-r--r--main/db1-ast/recno/extern.h54
-rw-r--r--main/db1-ast/recno/rec_close.c183
-rw-r--r--main/db1-ast/recno/rec_delete.c197
-rw-r--r--main/db1-ast/recno/rec_get.c311
-rw-r--r--main/db1-ast/recno/rec_open.c241
-rw-r--r--main/db1-ast/recno/rec_put.c280
-rw-r--r--main/db1-ast/recno/rec_search.c126
-rw-r--r--main/db1-ast/recno/rec_seq.c131
-rw-r--r--main/db1-ast/recno/rec_utils.c122
-rw-r--r--main/db1-ast/recno/recno.h39
-rw-r--r--main/devicestate.c369
-rw-r--r--main/dial.c894
-rw-r--r--main/dns.c292
-rw-r--r--main/dnsmgr.c424
-rw-r--r--main/dsp.c1819
-rw-r--r--main/ecdisa.h15
-rw-r--r--main/editline/CHANGES42
-rw-r--r--main/editline/INSTALL64
-rw-r--r--main/editline/Makefile.in234
-rw-r--r--main/editline/PLATFORMS13
-rw-r--r--main/editline/README11
-rw-r--r--main/editline/TEST/test.c268
-rw-r--r--main/editline/chared.c695
-rw-r--r--main/editline/chared.h159
-rw-r--r--main/editline/common.c951
-rwxr-xr-xmain/editline/config.guess1449
-rw-r--r--main/editline/config.h.in21
-rwxr-xr-xmain/editline/config.sub1412
-rwxr-xr-xmain/editline/configure2459
-rw-r--r--main/editline/configure.in278
-rw-r--r--main/editline/editline.3646
-rw-r--r--main/editline/editrc.5491
-rw-r--r--main/editline/el.c509
-rw-r--r--main/editline/el.h145
-rw-r--r--main/editline/emacs.c488
-rw-r--r--main/editline/hist.c197
-rw-r--r--main/editline/hist.h80
-rw-r--r--main/editline/histedit.h197
-rw-r--r--main/editline/history.c875
-rwxr-xr-xmain/editline/install-sh250
-rw-r--r--main/editline/key.c687
-rw-r--r--main/editline/key.h79
-rw-r--r--main/editline/makelist.in254
-rw-r--r--main/editline/map.c1418
-rw-r--r--main/editline/map.h79
-rw-r--r--main/editline/np/fgetln.c88
-rw-r--r--main/editline/np/strlcat.c75
-rw-r--r--main/editline/np/strlcpy.c75
-rw-r--r--main/editline/np/unvis.c322
-rw-r--r--main/editline/np/vis.c348
-rw-r--r--main/editline/np/vis.h96
-rw-r--r--main/editline/parse.c259
-rw-r--r--main/editline/parse.h52
-rw-r--r--main/editline/prompt.c174
-rw-r--r--main/editline/prompt.h62
-rw-r--r--main/editline/read.c558
-rw-r--r--main/editline/read.h55
-rw-r--r--main/editline/readline.c1664
-rw-r--r--main/editline/readline/readline.h118
-rw-r--r--main/editline/refresh.c1104
-rw-r--r--main/editline/refresh.h63
-rw-r--r--main/editline/search.c649
-rw-r--r--main/editline/search.h70
-rw-r--r--main/editline/sig.c198
-rw-r--r--main/editline/sig.h72
-rw-r--r--main/editline/sys.h133
-rw-r--r--main/editline/term.c1587
-rw-r--r--main/editline/term.h124
-rw-r--r--main/editline/tokenizer.c397
-rw-r--r--main/editline/tokenizer.h54
-rw-r--r--main/editline/tty.c1182
-rw-r--r--main/editline/tty.h484
-rw-r--r--main/editline/vi.c941
-rw-r--r--main/enum.c671
-rw-r--r--main/file.c1392
-rw-r--r--main/fixedjitterbuf.c351
-rw-r--r--main/fixedjitterbuf.h92
-rw-r--r--main/frame.c1607
-rw-r--r--main/fskmodem.c309
-rw-r--r--main/global_datastores.c113
-rw-r--r--main/http.c752
-rw-r--r--main/image.c225
-rw-r--r--main/indications.c597
-rw-r--r--main/io.c371
-rw-r--r--main/jitterbuf.c839
-rw-r--r--main/loader.c1001
-rw-r--r--main/logger.c939
-rw-r--r--main/manager.c3198
-rw-r--r--main/md5.c267
-rw-r--r--main/netsock.c217
-rw-r--r--main/pbx.c6401
-rw-r--r--main/plc.c251
-rw-r--r--main/poll.c306
-rw-r--r--main/privacy.c119
-rw-r--r--main/rtp.c3833
-rw-r--r--main/say.c7394
-rw-r--r--main/sched.c404
-rw-r--r--main/sha1.c385
-rw-r--r--main/slinfactory.c177
-rw-r--r--main/srv.c246
-rw-r--r--main/stdtime/Makefile29
-rw-r--r--main/stdtime/localtime.c1651
-rw-r--r--main/stdtime/private.h358
-rw-r--r--main/stdtime/test.c21
-rw-r--r--main/stdtime/tzfile.h184
-rw-r--r--main/strcompat.c472
-rw-r--r--main/tdd.c328
-rw-r--r--main/term.c303
-rw-r--r--main/threadstorage.c245
-rw-r--r--main/translate.c986
-rw-r--r--main/udptl.c1247
-rw-r--r--main/ulaw.c106
-rw-r--r--main/utils.c1414
181 files changed, 0 insertions, 111407 deletions
diff --git a/main/Makefile b/main/Makefile
deleted file mode 100644
index 53274ea4a..000000000
--- a/main/Makefile
+++ /dev/null
@@ -1,156 +0,0 @@
-#
-# Asterisk -- A telephony toolkit for Linux.
-#
-# Makefile to build main Asterisk binary
-#
-# Copyright (C) 1999-2006, Digium, Inc.
-#
-# Mark Spencer <markster@digium.com>
-#
-# This program is free software, distributed under the terms of
-# the GNU General Public License
-#
-
--include $(ASTTOPDIR)/menuselect.makeopts $(ASTTOPDIR)/menuselect.makedeps $(ASTTOPDIR)/makeopts.embed_rules
-
-all: asterisk
-
-include $(ASTTOPDIR)/Makefile.moddir_rules
-
-OBJS= io.o sched.o logger.o frame.o loader.o config.o channel.o \
- translate.o file.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 udptl.o manager.o asterisk.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 plc.o jitterbuf.o dnsmgr.o devicestate.o \
- netsock.o slinfactory.o ast_expr2.o ast_expr2f.o \
- cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \
- strcompat.o threadstorage.o dial.o astobj2.o global_datastores.o \
- audiohook.o
-
-# we need to link in the objects statically, not as a library, because
-# otherwise modules will not have them available if none of the static
-# objects use it.
-OBJS+=stdtime/localtime.o
-
-# At the moment say.o is an optional component which can be overridden
-# by a module.
-OBJS+=say.o
-
-ifneq ($(findstring darwin,$(OSARCH)),)
- OBJS+=poll.o
- ASTCFLAGS+=-DPOLLCOMPAT
-else
- ifeq ($(wildcard /usr/include/sys/poll.h),)
- OBJS+=poll.o
- ASTCFLAGS+=-DPOLLCOMPAT
- endif
-endif
-
-ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc linux-gnueabi ),)
- ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
- AST_LIBS+=-ldl
- endif
- ifneq (x$(CAP_LIB),x)
- AST_LIBS+=$(CAP_LIB)
- endif
- AST_LIBS+=-lpthread $(EDITLINE_LIB) -lm -lresolv
-else
- AST_LIBS+=$(EDITLINE_LIB) -lm
-endif
-
-ifneq ($(findstring darwin,$(OSARCH)),)
- AST_LIBS+=-lresolv
- ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
- ASTLINK=-Wl,-dynamic
- endif
-else
-# These are used for all but Darwin
- ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
- ASTLINK+=-Wl,--export-dynamic
- else
- ASTLINK+=${GC_LDFLAGS}
- endif
- ifneq ($(findstring BSD,$(OSARCH)),)
- LDFLAGS+=-L/usr/local/lib
- endif
-endif
-
-ifeq ($(OSARCH),FreeBSD)
- AST_LIBS+=-lcrypto
-endif
-
-ifeq ($(OSARCH),NetBSD)
- AST_LIBS+=-lpthread -lcrypto -lm -L/usr/pkg/lib $(EDITLINE_LIB)
-endif
-
-ifeq ($(OSARCH),OpenBSD)
- AST_LIBS+=-lcrypto -lpthread -lm $(EDITLINE_LIB)
-endif
-
-ifeq ($(OSARCH),SunOS)
- AST_LIBS+=-lpthread -ldl -lnsl -lsocket -lresolv -L/opt/ssl/lib -L/usr/local/ssl/lib
- ASTLINK=
-endif
-
-editline/libedit.a:
- cd editline && test -f config.h || CFLAGS="$(PTHREAD_CFLAGS) $(subst $(ASTTOPDIR),../../,$(ASTCFLAGS:-Werror=))" LDFLAGS="$(ASTLDFLAGS)" ./configure --build=$(BUILD_PLATFORM) --host=$(HOST_PLATFORM) --with-ncurses=$(NCURSES_DIR) --with-curses=$(CURSES_DIR) --with-termcap=$(TERMCAP_DIR) --with-tinfo=$(TINFO_DIR)
- $(MAKE) -C editline libedit.a
-
-db1-ast/libdb1.a:
- CFLAGS="$(subst $(ASTTOPDIR),../../,$(ASTCFLAGS))" LDFLAGS="$(ASTLDFLAGS)" $(MAKE) -C db1-ast libdb1.a
-
-ast_expr2.c ast_expr2.h:
- bison -o $@ -d --name-prefix=ast_yy ast_expr2.y
-
-ast_expr2f.c:
- flex -o $@ --full ast_expr2.fl # moved the correction of yyfree into the flex input file itself.
- sed 's@#if __STDC_VERSION__ >= 199901L@#if !defined __STDC_VERSION__ || __STDC_VERSION__ >= 199901L@' ast_expr2f.c > zz
- mv zz ast_expr2f.c
-
-ast_expr2f.o: ASTCFLAGS+=-Wno-unused
-
-testexpr2: ast_expr2f.c ast_expr2.c ast_expr2.h
- $(CC) -g -c -Iinclude -DSTANDALONE ast_expr2f.c
- $(CC) -g -c -Iinclude -DSTANDALONE ast_expr2.c
- $(CC) -g -o testexpr2 ast_expr2f.o ast_expr2.o
- rm ast_expr2.o ast_expr2f.o
-
-asterisk.o channel.o: ASTCFLAGS+=$(ZAPTEL_INCLUDE) $(DAHDI_INCLUDE)
-
-stdtime/localtime.o: ASTCFLAGS+=$(AST_NO_STRICT_OVERFLOW)
-
-AST_EMBED_LDSCRIPTS:=$(sort $(EMBED_LDSCRIPTS))
-AST_EMBED_LDFLAGS:=$(foreach dep,$(EMBED_LDFLAGS),$(value $(dep)))
-AST_EMBED_LIBS:=$(foreach dep,$(EMBED_LIBS),$(value $(dep)))
-OBJS:=$(sort $(OBJS))
-
-ifneq ($(wildcard ../channels/h323/Makefile.ast),)
- include ../channels/h323/Makefile.ast
-else
- H323LDFLAGS=
- H323LDLIBS=
-endif
-
-asterisk: $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS)
- @$(ASTTOPDIR)/build_tools/make_build_h > $(ASTTOPDIR)/include/asterisk/build.h.tmp
- @if cmp -s $(ASTTOPDIR)/include/asterisk/build.h.tmp $(ASTTOPDIR)/include/asterisk/build.h ; then echo ; else \
- mv $(ASTTOPDIR)/include/asterisk/build.h.tmp $(ASTTOPDIR)/include/asterisk/build.h ; \
- fi
- @rm -f $(ASTTOPDIR)/include/asterisk/build.h.tmp
- @$(CC) -c -o buildinfo.o $(ASTCFLAGS) buildinfo.c
- $(ECHO_PREFIX) echo " [LD] $^ -> $@"
-ifneq ($(findstring chan_h323,$(MENUSELECT_CHANNELS)),)
- $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS)
-else
- $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS)
-endif
- $(CMD_PREFIX) $(ASTTOPDIR)/build_tools/strip_nonapi $@ || rm $@
-
-clean::
- rm -f asterisk
- rm -f db1-ast/.*.d
- @if [ -f editline/Makefile ]; then $(MAKE) -C editline distclean ; fi
- @$(MAKE) -C db1-ast clean
- @$(MAKE) -C stdtime clean
diff --git a/main/abstract_jb.c b/main/abstract_jb.c
deleted file mode 100644
index 226df462b..000000000
--- a/main/abstract_jb.c
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
- * abstract_jb: common implementation-independent jitterbuffer stuff
- *
- * Copyright (C) 2005, Attractel OOD
- *
- * Contributors:
- * Slav Klenov <slav@securax.org>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- *
- * A license has been granted to Digium (via disclaimer) for the use of
- * this code.
- */
-
-/*! \file
- *
- * \brief Common implementation-independent jitterbuffer stuff.
- *
- * \author Slav Klenov <slav@securax.org>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "asterisk/frame.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/term.h"
-#include "asterisk/options.h"
-#include "asterisk/utils.h"
-
-#include "asterisk/abstract_jb.h"
-#include "fixedjitterbuf.h"
-#include "jitterbuf.h"
-
-/*! Internal jb flags */
-enum {
- JB_USE = (1 << 0),
- JB_TIMEBASE_INITIALIZED = (1 << 1),
- JB_CREATED = (1 << 2)
-};
-
-/* Hooks for the abstract jb implementation */
-
-/*! \brief Create */
-typedef void * (*jb_create_impl)(struct ast_jb_conf *general_config, long resynch_threshold);
-/*! \brief Destroy */
-typedef void (*jb_destroy_impl)(void *jb);
-/*! \brief Put first frame */
-typedef int (*jb_put_first_impl)(void *jb, struct ast_frame *fin, long now);
-/*! \brief Put frame */
-typedef int (*jb_put_impl)(void *jb, struct ast_frame *fin, long now);
-/*! \brief Get frame for now */
-typedef int (*jb_get_impl)(void *jb, struct ast_frame **fout, long now, long interpl);
-/*! \brief Get next */
-typedef long (*jb_next_impl)(void *jb);
-/*! \brief Remove first frame */
-typedef int (*jb_remove_impl)(void *jb, struct ast_frame **fout);
-/*! \brief Force resynch */
-typedef void (*jb_force_resynch_impl)(void *jb);
-/*! \brief Empty and reset jb */
-typedef void (*jb_empty_and_reset_impl)(void *jb);
-
-/*!
- * \brief Jitterbuffer implementation private struct.
- */
-struct ast_jb_impl
-{
- char name[AST_JB_IMPL_NAME_SIZE];
- jb_create_impl create;
- jb_destroy_impl destroy;
- jb_put_first_impl put_first;
- jb_put_impl put;
- jb_get_impl get;
- jb_next_impl next;
- jb_remove_impl remove;
- jb_force_resynch_impl force_resync;
- jb_empty_and_reset_impl empty_and_reset;
-};
-
-/* Implementation functions */
-/* fixed */
-static void * jb_create_fixed(struct ast_jb_conf *general_config, long resynch_threshold);
-static void jb_destroy_fixed(void *jb);
-static int jb_put_first_fixed(void *jb, struct ast_frame *fin, long now);
-static int jb_put_fixed(void *jb, struct ast_frame *fin, long now);
-static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interpl);
-static long jb_next_fixed(void *jb);
-static int jb_remove_fixed(void *jb, struct ast_frame **fout);
-static void jb_force_resynch_fixed(void *jb);
-static void jb_empty_and_reset_fixed(void *jb);
-/* adaptive */
-static void * jb_create_adaptive(struct ast_jb_conf *general_config, long resynch_threshold);
-static void jb_destroy_adaptive(void *jb);
-static int jb_put_first_adaptive(void *jb, struct ast_frame *fin, long now);
-static int jb_put_adaptive(void *jb, struct ast_frame *fin, long now);
-static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long interpl);
-static long jb_next_adaptive(void *jb);
-static int jb_remove_adaptive(void *jb, struct ast_frame **fout);
-static void jb_force_resynch_adaptive(void *jb);
-static void jb_empty_and_reset_adaptive(void *jb);
-
-/* Available jb implementations */
-static struct ast_jb_impl avail_impl[] =
-{
- {
- .name = "fixed",
- .create = jb_create_fixed,
- .destroy = jb_destroy_fixed,
- .put_first = jb_put_first_fixed,
- .put = jb_put_fixed,
- .get = jb_get_fixed,
- .next = jb_next_fixed,
- .remove = jb_remove_fixed,
- .force_resync = jb_force_resynch_fixed,
- .empty_and_reset = jb_empty_and_reset_fixed,
- },
- {
- .name = "adaptive",
- .create = jb_create_adaptive,
- .destroy = jb_destroy_adaptive,
- .put_first = jb_put_first_adaptive,
- .put = jb_put_adaptive,
- .get = jb_get_adaptive,
- .next = jb_next_adaptive,
- .remove = jb_remove_adaptive,
- .force_resync = jb_force_resynch_adaptive,
- .empty_and_reset = jb_empty_and_reset_adaptive,
- }
-};
-
-static int default_impl = 0;
-
-
-/*! Abstract return codes */
-enum {
- JB_IMPL_OK,
- JB_IMPL_DROP,
- JB_IMPL_INTERP,
- JB_IMPL_NOFRAME
-};
-
-/* Translations between impl and abstract return codes */
-static int fixed_to_abstract_code[] =
- {JB_IMPL_OK, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME};
-static int adaptive_to_abstract_code[] =
- {JB_IMPL_OK, JB_IMPL_NOFRAME, JB_IMPL_NOFRAME, JB_IMPL_INTERP, JB_IMPL_DROP, JB_IMPL_OK};
-
-/* JB_GET actions (used only for the frames log) */
-static char *jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"};
-
-/*! \brief Macros for the frame log files */
-#define jb_framelog(...) do { \
- if (jb->logfile) { \
- fprintf(jb->logfile, __VA_ARGS__); \
- fflush(jb->logfile); \
- } \
-} while (0)
-
-
-/* Internal utility functions */
-static void jb_choose_impl(struct ast_channel *chan);
-static void jb_get_and_deliver(struct ast_channel *chan);
-static int create_jb(struct ast_channel *chan, struct ast_frame *first_frame);
-static long get_now(struct ast_jb *jb, struct timeval *tv);
-
-
-/* Interface ast jb functions impl */
-
-
-static void jb_choose_impl(struct ast_channel *chan)
-{
- struct ast_jb *jb = &chan->jb;
- struct ast_jb_conf *jbconf = &jb->conf;
- struct ast_jb_impl *test_impl;
- int i, avail_impl_count = sizeof(avail_impl) / sizeof(avail_impl[0]);
-
- jb->impl = &avail_impl[default_impl];
-
- if (ast_strlen_zero(jbconf->impl))
- return;
-
- for (i = 0; i < avail_impl_count; i++) {
- test_impl = &avail_impl[i];
- if (!strcasecmp(jbconf->impl, test_impl->name)) {
- jb->impl = test_impl;
- return;
- }
- }
-}
-
-int ast_jb_do_usecheck(struct ast_channel *c0, struct ast_channel *c1)
-{
- struct ast_jb *jb0 = &c0->jb;
- struct ast_jb *jb1 = &c1->jb;
- struct ast_jb_conf *conf0 = &jb0->conf;
- struct ast_jb_conf *conf1 = &jb1->conf;
- int c0_wants_jitter = c0->tech->properties & AST_CHAN_TP_WANTSJITTER;
- int c0_creates_jitter = c0->tech->properties & AST_CHAN_TP_CREATESJITTER;
- int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED);
- int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED);
- int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED);
- int c0_jb_created = ast_test_flag(jb0, JB_CREATED);
- int c1_wants_jitter = c1->tech->properties & AST_CHAN_TP_WANTSJITTER;
- int c1_creates_jitter = c1->tech->properties & AST_CHAN_TP_CREATESJITTER;
- int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED);
- int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED);
- int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED);
- int c1_jb_created = ast_test_flag(jb1, JB_CREATED);
- int inuse = 0;
-
- /* Determine whether audio going to c0 needs a jitter buffer */
- if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
- ast_set_flag(jb0, JB_USE);
- if (!c0_jb_timebase_initialized) {
- if (c1_jb_timebase_initialized) {
- memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval));
- } else {
- gettimeofday(&jb0->timebase, NULL);
- }
- ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED);
- }
-
- if (!c0_jb_created) {
- jb_choose_impl(c0);
- }
-
- inuse = 1;
- }
-
- /* Determine whether audio going to c1 needs a jitter buffer */
- if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
- ast_set_flag(jb1, JB_USE);
- if (!c1_jb_timebase_initialized) {
- if (c0_jb_timebase_initialized) {
- memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval));
- } else {
- gettimeofday(&jb1->timebase, NULL);
- }
- ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED);
- }
-
- if (!c1_jb_created) {
- jb_choose_impl(c1);
- }
-
- inuse = 1;
- }
-
- return inuse;
-}
-
-int ast_jb_get_when_to_wakeup(struct ast_channel *c0, struct ast_channel *c1, int time_left)
-{
- struct ast_jb *jb0 = &c0->jb;
- struct ast_jb *jb1 = &c1->jb;
- int c0_use_jb = ast_test_flag(jb0, JB_USE);
- int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
- int c1_use_jb = ast_test_flag(jb1, JB_USE);
- int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
- int wait, wait0, wait1;
- struct timeval tv_now;
-
- if (time_left == 0) {
- /* No time left - the bridge will be retried */
- /* TODO: Test disable this */
- /*return 0;*/
- }
-
- if (time_left < 0) {
- time_left = INT_MAX;
- }
-
- gettimeofday(&tv_now, NULL);
-
- wait0 = (c0_use_jb && c0_jb_is_created) ? jb0->next - get_now(jb0, &tv_now) : time_left;
- wait1 = (c1_use_jb && c1_jb_is_created) ? jb1->next - get_now(jb1, &tv_now) : time_left;
-
- wait = wait0 < wait1 ? wait0 : wait1;
- wait = wait < time_left ? wait : time_left;
-
- if (wait == INT_MAX) {
- wait = -1;
- } else if (wait < 1) {
- /* don't let wait=0, because this can cause the pbx thread to loop without any sleeping at all */
- wait = 1;
- }
-
- return wait;
-}
-
-
-int ast_jb_put(struct ast_channel *chan, struct ast_frame *f)
-{
- struct ast_jb *jb = &chan->jb;
- struct ast_jb_impl *jbimpl = jb->impl;
- void *jbobj = jb->jbobj;
- struct ast_frame *frr;
- long now = 0;
-
- if (!ast_test_flag(jb, JB_USE))
- return -1;
-
- if (f->frametype != AST_FRAME_VOICE) {
- if (f->frametype == AST_FRAME_DTMF && ast_test_flag(jb, JB_CREATED)) {
- jb_framelog("JB_PUT {now=%ld}: Received DTMF frame. Force resynching jb...\n", now);
- jbimpl->force_resync(jbobj);
- }
-
- return -1;
- }
-
- /* We consider an enabled jitterbuffer should receive frames with valid timing info. */
- if (!ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) {
- ast_log(LOG_WARNING, "%s recieved frame with invalid timing info: "
- "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n",
- chan->name, ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO), f->len, f->ts, f->src);
- return -1;
- }
-
- frr = ast_frdup(f);
-
- if (!frr) {
- ast_log(LOG_ERROR, "Failed to isolate frame for the jitterbuffer on channel '%s'\n", chan->name);
- return -1;
- }
-
- if (!ast_test_flag(jb, JB_CREATED)) {
- if (create_jb(chan, frr)) {
- ast_frfree(frr);
- /* Disable the jitterbuffer */
- ast_clear_flag(jb, JB_USE);
- return -1;
- }
-
- ast_set_flag(jb, JB_CREATED);
- return 0;
- } else {
- now = get_now(jb, NULL);
- if (jbimpl->put(jbobj, frr, now) != JB_IMPL_OK) {
- jb_framelog("JB_PUT {now=%ld}: Dropped frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
- ast_frfree(frr);
- /*return -1;*/
- /* TODO: Check this fix - should return 0 here, because the dropped frame shouldn't
- be delivered at all */
- return 0;
- }
-
- jb->next = jbimpl->next(jbobj);
-
- jb_framelog("JB_PUT {now=%ld}: Queued frame with ts=%ld and len=%ld\n", now, frr->ts, frr->len);
-
- return 0;
- }
-}
-
-
-void ast_jb_get_and_deliver(struct ast_channel *c0, struct ast_channel *c1)
-{
- struct ast_jb *jb0 = &c0->jb;
- struct ast_jb *jb1 = &c1->jb;
- int c0_use_jb = ast_test_flag(jb0, JB_USE);
- int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
- int c1_use_jb = ast_test_flag(jb1, JB_USE);
- int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
-
- if (c0_use_jb && c0_jb_is_created)
- jb_get_and_deliver(c0);
-
- if (c1_use_jb && c1_jb_is_created)
- jb_get_and_deliver(c1);
-}
-
-
-static void jb_get_and_deliver(struct ast_channel *chan)
-{
- struct ast_jb *jb = &chan->jb;
- struct ast_jb_impl *jbimpl = jb->impl;
- void *jbobj = jb->jbobj;
- struct ast_frame *f, finterp;
- long now;
- int interpolation_len, res;
-
- now = get_now(jb, NULL);
- jb->next = jbimpl->next(jbobj);
- if (now < jb->next) {
- jb_framelog("\tJB_GET {now=%ld}: now < next=%ld\n", now, jb->next);
- return;
- }
-
- while (now >= jb->next) {
- interpolation_len = ast_codec_interp_len(jb->last_format);
-
- res = jbimpl->get(jbobj, &f, now, interpolation_len);
-
- switch(res) {
- case JB_IMPL_OK:
- /* deliver the frame */
- ast_write(chan, f);
- case JB_IMPL_DROP:
- jb_framelog("\tJB_GET {now=%ld}: %s frame with ts=%ld and len=%ld\n",
- now, jb_get_actions[res], f->ts, f->len);
- jb->last_format = f->subclass;
- ast_frfree(f);
- break;
- case JB_IMPL_INTERP:
- /* interpolate a frame */
- f = &finterp;
- f->frametype = AST_FRAME_VOICE;
- f->subclass = jb->last_format;
- f->datalen = 0;
- f->samples = interpolation_len * 8;
- f->mallocd = 0;
- f->src = "JB interpolation";
- f->data = NULL;
- f->delivery = ast_tvadd(jb->timebase, ast_samp2tv(jb->next, 1000));
- f->offset = AST_FRIENDLY_OFFSET;
- /* deliver the interpolated frame */
- ast_write(chan, f);
- jb_framelog("\tJB_GET {now=%ld}: Interpolated frame with len=%d\n", now, interpolation_len);
- break;
- case JB_IMPL_NOFRAME:
- ast_log(LOG_WARNING,
- "JB_IMPL_NOFRAME is retuned from the %s jb when now=%ld >= next=%ld, jbnext=%ld!\n",
- jbimpl->name, now, jb->next, jbimpl->next(jbobj));
- jb_framelog("\tJB_GET {now=%ld}: No frame for now!?\n", now);
- return;
- default:
- ast_log(LOG_ERROR, "This should never happen!\n");
- ast_assert("JB type unknown" == NULL);
- break;
- }
-
- jb->next = jbimpl->next(jbobj);
- }
-}
-
-
-static int create_jb(struct ast_channel *chan, struct ast_frame *frr)
-{
- struct ast_jb *jb = &chan->jb;
- struct ast_jb_conf *jbconf = &jb->conf;
- struct ast_jb_impl *jbimpl = jb->impl;
- void *jbobj;
- struct ast_channel *bridged;
- long now;
- char logfile_pathname[20 + AST_JB_IMPL_NAME_SIZE + 2*AST_CHANNEL_NAME + 1];
- char name1[AST_CHANNEL_NAME], name2[AST_CHANNEL_NAME], *tmp;
- int res;
-
- jbobj = jb->jbobj = jbimpl->create(jbconf, jbconf->resync_threshold);
- if (!jbobj) {
- ast_log(LOG_WARNING, "Failed to create jitterbuffer on channel '%s'\n", chan->name);
- return -1;
- }
-
- now = get_now(jb, NULL);
- res = jbimpl->put_first(jbobj, frr, now);
-
- /* The result of putting the first frame should not differ from OK. However, its possible
- some implementations (i.e. adaptive's when resynch_threshold is specified) to drop it. */
- if (res != JB_IMPL_OK) {
- ast_log(LOG_WARNING, "Failed to put first frame in the jitterbuffer on channel '%s'\n", chan->name);
- /*
- jbimpl->destroy(jbobj);
- return -1;
- */
- }
-
- /* Init next */
- jb->next = jbimpl->next(jbobj);
-
- /* Init last format for a first time. */
- jb->last_format = frr->subclass;
-
- /* Create a frame log file */
- if (ast_test_flag(jbconf, AST_JB_LOG)) {
- snprintf(name2, sizeof(name2), "%s", chan->name);
- tmp = strchr(name2, '/');
- if (tmp)
- *tmp = '#';
-
- bridged = ast_bridged_channel(chan);
- /* We should always have bridged chan if a jitterbuffer is in use */
- ast_assert(bridged != NULL);
-
- snprintf(name1, sizeof(name1), "%s", bridged->name);
- tmp = strchr(name1, '/');
- if (tmp)
- *tmp = '#';
-
- snprintf(logfile_pathname, sizeof(logfile_pathname),
- "/tmp/ast_%s_jb_%s--%s.log", jbimpl->name, name1, name2);
- jb->logfile = fopen(logfile_pathname, "w+b");
-
- if (!jb->logfile)
- ast_log(LOG_WARNING, "Failed to create frame log file with pathname '%s'\n", logfile_pathname);
-
- if (res == JB_IMPL_OK)
- jb_framelog("JB_PUT_FIRST {now=%ld}: Queued frame with ts=%ld and len=%ld\n",
- now, frr->ts, frr->len);
- else
- jb_framelog("JB_PUT_FIRST {now=%ld}: Dropped frame with ts=%ld and len=%ld\n",
- now, frr->ts, frr->len);
- }
-
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "%s jitterbuffer created on channel %s\n", jbimpl->name, chan->name);
-
- /* Free the frame if it has not been queued in the jb */
- if (res != JB_IMPL_OK)
- ast_frfree(frr);
-
- return 0;
-}
-
-
-void ast_jb_destroy(struct ast_channel *chan)
-{
- struct ast_jb *jb = &chan->jb;
- struct ast_jb_impl *jbimpl = jb->impl;
- void *jbobj = jb->jbobj;
- struct ast_frame *f;
-
- if (jb->logfile) {
- fclose(jb->logfile);
- jb->logfile = NULL;
- }
-
- if (ast_test_flag(jb, JB_CREATED)) {
- /* Remove and free all frames still queued in jb */
- while (jbimpl->remove(jbobj, &f) == JB_IMPL_OK) {
- ast_frfree(f);
- }
-
- jbimpl->destroy(jbobj);
- jb->jbobj = NULL;
-
- ast_clear_flag(jb, JB_CREATED);
-
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, chan->name);
- }
-}
-
-
-static long get_now(struct ast_jb *jb, struct timeval *tv)
-{
- struct timeval now;
-
- if (!tv) {
- tv = &now;
- gettimeofday(tv, NULL);
- }
-
- return ast_tvdiff_ms(*tv, jb->timebase);
-}
-
-
-int ast_jb_read_conf(struct ast_jb_conf *conf, char *varname, char *value)
-{
- int prefixlen = sizeof(AST_JB_CONF_PREFIX) - 1;
- char *name;
- int tmp;
-
- if (strncasecmp(AST_JB_CONF_PREFIX, varname, prefixlen))
- return -1;
-
- name = varname + prefixlen;
-
- if (!strcasecmp(name, AST_JB_CONF_ENABLE)) {
- ast_set2_flag(conf, ast_true(value), AST_JB_ENABLED);
- } else if (!strcasecmp(name, AST_JB_CONF_FORCE)) {
- ast_set2_flag(conf, ast_true(value), AST_JB_FORCED);
- } else if (!strcasecmp(name, AST_JB_CONF_MAX_SIZE)) {
- if ((tmp = atoi(value)) > 0)
- conf->max_size = tmp;
- } else if (!strcasecmp(name, AST_JB_CONF_RESYNCH_THRESHOLD)) {
- if ((tmp = atoi(value)) > 0)
- conf->resync_threshold = tmp;
- } else if (!strcasecmp(name, AST_JB_CONF_IMPL)) {
- if (!ast_strlen_zero(value))
- snprintf(conf->impl, sizeof(conf->impl), "%s", value);
- } else if (!strcasecmp(name, AST_JB_CONF_LOG)) {
- ast_set2_flag(conf, ast_true(value), AST_JB_LOG);
- } else {
- return -1;
- }
-
- return 0;
-}
-
-
-void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
-{
- memcpy(&chan->jb.conf, conf, sizeof(*conf));
-}
-
-
-void ast_jb_get_config(const struct ast_channel *chan, struct ast_jb_conf *conf)
-{
- memcpy(conf, &chan->jb.conf, sizeof(*conf));
-}
-
-void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1)
-{
- struct ast_jb *jb0 = &c0->jb;
- struct ast_jb *jb1 = &c1->jb;
- int c0_use_jb = ast_test_flag(jb0, JB_USE);
- int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
- int c1_use_jb = ast_test_flag(jb1, JB_USE);
- int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);
-
- if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) {
- jb0->impl->empty_and_reset(jb0->jbobj);
- }
-
- if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) {
- jb1->impl->empty_and_reset(jb1->jbobj);
- }
-}
-
-/* Implementation functions */
-
-/* fixed */
-static void * jb_create_fixed(struct ast_jb_conf *general_config, long resynch_threshold)
-{
- struct fixed_jb_conf conf;
-
- conf.jbsize = general_config->max_size;
- conf.resync_threshold = resynch_threshold;
-
- return fixed_jb_new(&conf);
-}
-
-static void jb_destroy_fixed(void *jb)
-{
- struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
-
- /* destroy the jb */
- fixed_jb_destroy(fixedjb);
-}
-
-
-static int jb_put_first_fixed(void *jb, struct ast_frame *fin, long now)
-{
- struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
- int res;
-
- res = fixed_jb_put_first(fixedjb, fin, fin->len, fin->ts, now);
-
- return fixed_to_abstract_code[res];
-}
-
-
-static int jb_put_fixed(void *jb, struct ast_frame *fin, long now)
-{
- struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
- int res;
-
- res = fixed_jb_put(fixedjb, fin, fin->len, fin->ts, now);
-
- return fixed_to_abstract_code[res];
-}
-
-
-static int jb_get_fixed(void *jb, struct ast_frame **fout, long now, long interpl)
-{
- struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
- struct fixed_jb_frame frame;
- int res;
-
- res = fixed_jb_get(fixedjb, &frame, now, interpl);
- *fout = frame.data;
-
- return fixed_to_abstract_code[res];
-}
-
-
-static long jb_next_fixed(void *jb)
-{
- struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
-
- return fixed_jb_next(fixedjb);
-}
-
-
-static int jb_remove_fixed(void *jb, struct ast_frame **fout)
-{
- struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
- struct fixed_jb_frame frame;
- int res;
-
- res = fixed_jb_remove(fixedjb, &frame);
- *fout = frame.data;
-
- return fixed_to_abstract_code[res];
-}
-
-
-static void jb_force_resynch_fixed(void *jb)
-{
- struct fixed_jb *fixedjb = (struct fixed_jb *) jb;
-
- fixed_jb_set_force_resynch(fixedjb);
-}
-
-static void jb_empty_and_reset_fixed(void *jb)
-{
- struct fixed_jb *fixedjb = jb;
- struct fixed_jb_frame f;
-
- while (fixed_jb_remove(fixedjb, &f) == FIXED_JB_OK) {
- ast_frfree(f.data);
- }
-}
-
-/* adaptive */
-
-static void *jb_create_adaptive(struct ast_jb_conf *general_config, long resynch_threshold)
-{
- jb_conf jbconf;
- jitterbuf *adaptivejb;
-
- adaptivejb = jb_new();
- if (adaptivejb) {
- jbconf.max_jitterbuf = general_config->max_size;
- jbconf.resync_threshold = general_config->resync_threshold;
- jbconf.max_contig_interp = 10;
- jb_setconf(adaptivejb, &jbconf);
- }
-
- return adaptivejb;
-}
-
-
-static void jb_destroy_adaptive(void *jb)
-{
- jitterbuf *adaptivejb = (jitterbuf *) jb;
-
- jb_destroy(adaptivejb);
-}
-
-
-static int jb_put_first_adaptive(void *jb, struct ast_frame *fin, long now)
-{
- return jb_put_adaptive(jb, fin, now);
-}
-
-
-static int jb_put_adaptive(void *jb, struct ast_frame *fin, long now)
-{
- jitterbuf *adaptivejb = (jitterbuf *) jb;
- int res;
-
- res = jb_put(adaptivejb, fin, JB_TYPE_VOICE, fin->len, fin->ts, now);
-
- return adaptive_to_abstract_code[res];
-}
-
-
-static int jb_get_adaptive(void *jb, struct ast_frame **fout, long now, long interpl)
-{
- jitterbuf *adaptivejb = (jitterbuf *) jb;
- jb_frame frame;
- int res;
-
- res = jb_get(adaptivejb, &frame, now, interpl);
- *fout = frame.data;
-
- return adaptive_to_abstract_code[res];
-}
-
-
-static long jb_next_adaptive(void *jb)
-{
- jitterbuf *adaptivejb = (jitterbuf *) jb;
-
- return jb_next(adaptivejb);
-}
-
-
-static int jb_remove_adaptive(void *jb, struct ast_frame **fout)
-{
- jitterbuf *adaptivejb = (jitterbuf *) jb;
- jb_frame frame;
- int res;
-
- res = jb_getall(adaptivejb, &frame);
- *fout = frame.data;
-
- return adaptive_to_abstract_code[res];
-}
-
-
-static void jb_force_resynch_adaptive(void *jb)
-{
-}
-
-static void jb_empty_and_reset_adaptive(void *jb)
-{
- jitterbuf *adaptivejb = jb;
- jb_frame f;
-
- while (jb_getall(adaptivejb, &f) == JB_OK) {
- ast_frfree(f.data);
- }
-
- jb_reset(adaptivejb);
-}
diff --git a/main/acl.c b/main/acl.c
deleted file mode 100644
index 4a5e16485..000000000
--- a/main/acl.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Various sorts of access control
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <net/if.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <sys/ioctl.h>
-
-#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
-#include <fcntl.h>
-#include <net/route.h>
-#endif
-
-#if defined(SOLARIS)
-#include <sys/sockio.h>
-#include <net/if.h>
-#elif defined(HAVE_GETIFADDRS)
-#include <ifaddrs.h>
-#endif
-
-/* netinet/ip.h may not define the following (See RFCs 791 and 1349) */
-#if !defined(IPTOS_LOWCOST)
-#define IPTOS_LOWCOST 0x02
-#endif
-
-#if !defined(IPTOS_MINCOST)
-#define IPTOS_MINCOST IPTOS_LOWCOST
-#endif
-
-#include "asterisk/acl.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/options.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/srv.h"
-
-struct ast_ha {
- /* Host access rule */
- struct in_addr netaddr;
- struct in_addr netmask;
- int sense;
- struct ast_ha *next;
-};
-
-/* Default IP - if not otherwise set, don't breathe garbage */
-static struct in_addr __ourip = { .s_addr = 0x00000000, };
-
-struct my_ifreq {
- char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "eth0", "ppp0", etc. */
- struct sockaddr_in ifru_addr;
-};
-
-#if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
-static int get_local_address(struct in_addr *ourip)
-{
- return -1;
-}
-#else
-static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score)
-{
- const char *address;
- int score;
-
- address = ast_inet_ntoa(sin->sin_addr);
-
- /* RFC 1700 alias for the local network */
- if (address[0] == '0')
- score = -25;
- /* RFC 1700 localnet */
- else if (strncmp(address, "127", 3) == 0)
- score = -20;
- /* RFC 1918 non-public address space */
- else if (strncmp(address, "10.", 3) == 0)
- score = -5;
- /* RFC 1918 non-public address space */
- else if (strncmp(address, "172", 3) == 0) {
- /* 172.16.0.0 - 172.19.255.255, but not 172.160.0.0 - 172.169.255.255 */
- if (address[4] == '1' && address[5] >= '6' && address[6] == '.')
- score = -5;
- /* 172.20.0.0 - 172.29.255.255, but not 172.200.0.0 - 172.255.255.255 nor 172.2.0.0 - 172.2.255.255 */
- else if (address[4] == '2' && address[6] == '.')
- score = -5;
- /* 172.30.0.0 - 172.31.255.255 */
- else if (address[4] == '3' && address[5] <= '1')
- score = -5;
- /* All other 172 addresses are public */
- else
- score = 0;
- /* RFC 2544 Benchmark test range */
- } else if (strncmp(address, "198.1", 5) == 0 && address[5] >= '8' && address[6] == '.')
- score = -10;
- /* RFC 1918 non-public address space */
- else if (strncmp(address, "192.168", 7) == 0)
- score = -5;
- /* RFC 3330 Zeroconf network */
- else if (strncmp(address, "169.254", 7) == 0)
- /*!\note Better score than a test network, but not quite as good as RFC 1918
- * address space. The reason is that some Linux distributions automatically
- * configure a Zeroconf address before trying DHCP, so we want to prefer a
- * DHCP lease to a Zeroconf address.
- */
- score = -10;
- /* RFC 3330 Test network */
- else if (strncmp(address, "192.0.2.", 8) == 0)
- score = -15;
- /* Every other address should be publically routable */
- else
- score = 0;
-
- if (score > *best_score) {
- *best_score = score;
- memcpy(best_addr, &sin->sin_addr, sizeof(*best_addr));
- }
-}
-
-static int get_local_address(struct in_addr *ourip)
-{
- int s, res = -1;
-#ifdef SOLARIS
- struct lifreq *ifr = NULL;
- struct lifnum ifn;
- struct lifconf ifc;
- struct sockaddr_in *sa;
- char *buf = NULL;
- int bufsz, x;
-#endif /* SOLARIS */
-#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
- struct ifaddrs *ifap, *ifaphead;
- int rtnerr;
- const struct sockaddr_in *sin;
-#endif /* BSD_OR_LINUX */
- struct in_addr best_addr;
- int best_score = -100;
- memset(&best_addr, 0, sizeof(best_addr));
-
-#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
- rtnerr = getifaddrs(&ifaphead);
- if (rtnerr) {
- perror(NULL);
- return -1;
- }
-#endif /* BSD_OR_LINUX */
-
- s = socket(AF_INET, SOCK_STREAM, 0);
-
- if (s > 0) {
-#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
- for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
-
- if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) {
- sin = (const struct sockaddr_in *) ifap->ifa_addr;
- score_address(sin, &best_addr, &best_score);
- res = 0;
-
- if (best_score == 0)
- break;
- }
- }
-#endif /* BSD_OR_LINUX */
-
- /* There is no reason whatsoever that this shouldn't work on Linux or BSD also. */
-#ifdef SOLARIS
- /* Get a count of interfaces on the machine */
- ifn.lifn_family = AF_INET;
- ifn.lifn_flags = 0;
- ifn.lifn_count = 0;
- if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
- close(s);
- return -1;
- }
-
- bufsz = ifn.lifn_count * sizeof(struct lifreq);
- if (!(buf = malloc(bufsz))) {
- close(s);
- return -1;
- }
- memset(buf, 0, bufsz);
-
- /* Get a list of interfaces on the machine */
- ifc.lifc_len = bufsz;
- ifc.lifc_buf = buf;
- ifc.lifc_family = AF_INET;
- ifc.lifc_flags = 0;
- if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
- close(s);
- free(buf);
- return -1;
- }
-
- for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) {
- sa = (struct sockaddr_in *)&(ifr->lifr_addr);
- score_address(sa, &best_addr, &best_score);
- res = 0;
-
- if (best_score == 0)
- break;
- }
-
- free(buf);
-#endif /* SOLARIS */
-
- close(s);
- }
-#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
- freeifaddrs(ifaphead);
-#endif /* BSD_OR_LINUX */
-
- if (res == 0 && ourip)
- memcpy(ourip, &best_addr, sizeof(*ourip));
- return res;
-}
-#endif /* HAVE_GETIFADDRS */
-
-/* Free HA structure */
-void ast_free_ha(struct ast_ha *ha)
-{
- struct ast_ha *hal;
- while (ha) {
- hal = ha;
- ha = ha->next;
- free(hal);
- }
-}
-
-/* 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;
-
- if ((new_ha = ast_malloc(sizeof(*new_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;
- char *nm = "255.255.255.255";
- char tmp[256];
- struct ast_ha *prev = NULL;
- struct ast_ha *ret;
- int x, z;
- unsigned int y;
-
- ret = path;
- while (path) {
- prev = path;
- path = path->next;
- }
- if ((ha = ast_malloc(sizeof(*ha)))) {
- ast_copy_string(tmp, stuff, sizeof(tmp));
- nm = strchr(tmp, '/');
- if (!nm) {
- nm = "255.255.255.255";
- } else {
- *nm = '\0';
- nm++;
- }
- if (!strchr(nm, '.')) {
- if ((sscanf(nm, "%d", &x) == 1) && (x >= 0) && (x <= 32)) {
- y = 0;
- for (z = 0; z < x; z++) {
- y >>= 1;
- y |= 0x80000000;
- }
- ha->netmask.s_addr = htonl(y);
- }
- } else if (!inet_aton(nm, &ha->netmask)) {
- ast_log(LOG_WARNING, "%s is not a valid netmask\n", nm);
- free(ha);
- return ret;
- }
- if (!inet_aton(tmp, &ha->netaddr)) {
- ast_log(LOG_WARNING, "%s is not a valid IP\n", tmp);
- free(ha);
- return ret;
- }
- ha->netaddr.s_addr &= ha->netmask.s_addr;
- if (!strncasecmp(sense, "p", 1)) {
- ha->sense = AST_SENSE_ALLOW;
- } else {
- ha->sense = AST_SENSE_DENY;
- }
- ha->next = NULL;
- if (prev) {
- prev->next = ha;
- } else {
- ret = ha;
- }
- }
- if (option_debug)
- ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n", stuff, nm);
- return ret;
-}
-
-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_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf));
- ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
- if (option_debug)
- ast_log(LOG_DEBUG, "##### Testing %s with %s\n", iabuf, iabuf2);
- /* 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)
- res = ha->sense;
- ha = ha->next;
- }
- return res;
-}
-
-int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service)
-{
- struct hostent *hp;
- struct ast_hostent ahp;
- char srv[256];
- char host[256];
- int tportno = ntohs(sin->sin_port);
- if (inet_aton(value, &sin->sin_addr))
- return 0;
- if (service) {
- snprintf(srv, sizeof(srv), "%s.%s", service, value);
- if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) {
- sin->sin_port = htons(tportno);
- value = host;
- }
- }
- hp = ast_gethostbyname(value, &ahp);
- if (hp) {
- memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
- } else {
- ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
- return -1;
- }
- return 0;
-}
-
-struct dscp_codepoint {
- char *name;
- unsigned int space;
-};
-
-/* IANA registered DSCP codepoints */
-
-static const struct dscp_codepoint dscp_pool1[] = {
- { "CS0", 0x00 },
- { "CS1", 0x08 },
- { "CS2", 0x10 },
- { "CS3", 0x18 },
- { "CS4", 0x20 },
- { "CS5", 0x28 },
- { "CS6", 0x30 },
- { "CS7", 0x38 },
- { "AF11", 0x0A },
- { "AF12", 0x0C },
- { "AF13", 0x0E },
- { "AF21", 0x12 },
- { "AF22", 0x14 },
- { "AF23", 0x16 },
- { "AF31", 0x1A },
- { "AF32", 0x1C },
- { "AF33", 0x1E },
- { "AF41", 0x22 },
- { "AF42", 0x24 },
- { "AF43", 0x26 },
- { "EF", 0x2E },
-};
-
-int ast_str2tos(const char *value, unsigned int *tos)
-{
- int fval;
- unsigned int x;
-
- if (sscanf(value, "%i", &fval) == 1) {
- *tos = fval & 0xFF;
- return 0;
- }
-
- for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) {
- if (!strcasecmp(value, dscp_pool1[x].name)) {
- *tos = dscp_pool1[x].space << 2;
- return 0;
- }
- }
-
- if (!strcasecmp(value, "lowdelay"))
- *tos = IPTOS_LOWDELAY;
- else if (!strcasecmp(value, "throughput"))
- *tos = IPTOS_THROUGHPUT;
- else if (!strcasecmp(value, "reliability"))
- *tos = IPTOS_RELIABILITY;
- else if (!strcasecmp(value, "mincost"))
- *tos = IPTOS_MINCOST;
- else if (!strcasecmp(value, "none"))
- *tos = 0;
- else
- return -1;
-
- ast_log(LOG_WARNING, "TOS value %s is deprecated. Please see doc/ip-tos.txt for more information.\n", value);
-
- return 0;
-}
-
-const char *ast_tos2str(unsigned int tos)
-{
- unsigned int x;
-
- switch (tos) {
- case 0:
- return "none";
- case IPTOS_LOWDELAY:
- return "lowdelay";
- case IPTOS_THROUGHPUT:
- return "throughput";
- case IPTOS_RELIABILITY:
- return "reliability";
- case IPTOS_MINCOST:
- return "mincost";
- default:
- for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) {
- if (dscp_pool1[x].space == (tos >> 2))
- return dscp_pool1[x].name;
- }
- }
-
- return "unknown";
-}
-
-int ast_get_ip(struct sockaddr_in *sin, const char *value)
-{
- return ast_get_ip_or_srv(sin, value, NULL);
-}
-
-/* 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;
- struct my_ifreq ifreq;
-
- memset(&ifreq, 0, sizeof(ifreq));
- ast_copy_string(ifreq.ifrn_name, iface, sizeof(ifreq.ifrn_name));
-
- mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
- res = ioctl(mysock, SIOCGIFADDR, &ifreq);
-
- close(mysock);
- if (res < 0) {
- ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
- memcpy((char *)address, (char *)&__ourip, sizeof(__ourip));
- return -1;
- } else {
- memcpy((char *)address, (char *)&ifreq.ifru_addr.sin_addr, sizeof(ifreq.ifru_addr.sin_addr));
- return 0;
- }
-}
-
-int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
-{
- int s;
- struct sockaddr_in sin;
- socklen_t slen;
-
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- ast_log(LOG_WARNING, "Cannot create socket\n");
- return -1;
- }
- sin.sin_family = AF_INET;
- sin.sin_port = 5060;
- sin.sin_addr = *them;
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) {
- ast_log(LOG_WARNING, "Cannot connect\n");
- close(s);
- return -1;
- }
- slen = sizeof(sin);
- if (getsockname(s, (struct sockaddr *)&sin, &slen)) {
- ast_log(LOG_WARNING, "Cannot get socket name\n");
- close(s);
- return -1;
- }
- close(s);
- *us = sin.sin_addr;
- return 0;
-}
-
-int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
-{
- char ourhost[MAXHOSTNAMELEN] = "";
- 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) - 1)) {
- 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 get_local_address(ourip);
-}
-
diff --git a/main/aescrypt.c b/main/aescrypt.c
deleted file mode 100644
index 1ccddf3f5..000000000
--- a/main/aescrypt.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- ---------------------------------------------------------------------------
- Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
- All rights reserved.
-
- LICENSE TERMS
-
- The free distribution and use of this software in both source and binary
- form is allowed (with or without changes) provided that:
-
- 1. distributions of this source code include the above copyright
- notice, this list of conditions and the following disclaimer;
-
- 2. distributions in binary form include the above copyright
- notice, this list of conditions and the following disclaimer
- in the documentation and/or other associated materials;
-
- 3. the copyright holder's name is not used to endorse products
- built using this software without specific written permission.
-
- ALTERNATIVELY, provided that this notice is retained in full, this product
- may be distributed under the terms of the GNU General Public License (GPL),
- in which case the provisions of the GPL apply INSTEAD OF those given above.
-
- DISCLAIMER
-
- This software is provided 'as is' with no explicit or implied warranties
- in respect of its properties, including, but not limited to, correctness
- and/or fitness for purpose.
- ---------------------------------------------------------------------------
- Issue Date: 26/08/2003
-
-*/
-
-/*! \file
- *
- * \brief This file contains the code for implementing encryption and decryption
- * for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
- * can optionally be replaced by code written in assembler using NASM. For
- * further details see the file aesopt.h
- *
- * \author Dr Brian Gladman <brg@gladman.me.uk>
- */
-
-#include "aesopt.h"
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
-#define so(y,x,c) word_out(y, c, s(x,c))
-
-#if defined(ARRAYS)
-#define locals(y,x) x[4],y[4]
-#else
-#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
-#endif
-
-#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
- s(y,2) = s(x,2); s(y,3) = s(x,3);
-#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
-#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
-#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
-
-#if defined(ENCRYPTION) && !defined(AES_ASM)
-
-/* Visual C++ .Net v7.1 provides the fastest encryption code when using
- Pentium optimiation with small code but this is poor for decryption
- so we need to control this with the following VC++ pragmas
-*/
-
-#if defined(_MSC_VER)
-#pragma optimize( "s", on )
-#endif
-
-/* Given the column (c) of the output state variable, the following
- macros give the input state variables which are needed in its
- computation for each row (r) of the state. All the alternative
- macros give the same end values but expand into different ways
- of calculating these values. In particular the complex macro
- used for dynamically variable block sizes is designed to expand
- to a compile time constant whenever possible but will expand to
- conditional clauses on some branches (I am grateful to Frank
- Yellin for this construction)
-*/
-
-#define fwd_var(x,r,c)\
- ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
- : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
- : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
- : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
-
-#if defined(FT4_SET)
-#undef dec_fmvars
-#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
-#elif defined(FT1_SET)
-#undef dec_fmvars
-#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c))
-#else
-#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c)))
-#endif
-
-#if defined(FL4_SET)
-#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))
-#elif defined(FL1_SET)
-#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c))
-#else
-#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))
-#endif
-
-aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1])
-{ aes_32t locals(b0, b1);
- const aes_32t *kp = cx->ks;
-#ifdef dec_fmvars
- dec_fmvars; /* declare variables for fwd_mcol() if needed */
-#endif
-
- aes_32t nr = (kp[45] ^ kp[52] ^ kp[53] ? kp[52] : 14);
-
-#ifdef AES_ERR_CHK
- if( (nr != 10 || !(kp[0] | kp[3] | kp[4]))
- && (nr != 12 || !(kp[0] | kp[5] | kp[6]))
- && (nr != 14 || !(kp[0] | kp[7] | kp[8])) )
- return aes_error;
-#endif
-
- state_in(b0, in_blk, kp);
-
-#if (ENC_UNROLL == FULL)
-
- switch(nr)
- {
- case 14:
- round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
- kp += 2 * N_COLS;
- case 12:
- round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
- kp += 2 * N_COLS;
- case 10:
- round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
- round(fwd_rnd, b1, b0, kp + 3 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 4 * N_COLS);
- round(fwd_rnd, b1, b0, kp + 5 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 6 * N_COLS);
- round(fwd_rnd, b1, b0, kp + 7 * N_COLS);
- round(fwd_rnd, b0, b1, kp + 8 * N_COLS);
- round(fwd_rnd, b1, b0, kp + 9 * N_COLS);
- round(fwd_lrnd, b0, b1, kp +10 * N_COLS);
- }
-
-#else
-
-#if (ENC_UNROLL == PARTIAL)
- { aes_32t rnd;
- for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
- {
- kp += N_COLS;
- round(fwd_rnd, b1, b0, kp);
- kp += N_COLS;
- round(fwd_rnd, b0, b1, kp);
- }
- kp += N_COLS;
- round(fwd_rnd, b1, b0, kp);
-#else
- { aes_32t rnd;
- for(rnd = 0; rnd < nr - 1; ++rnd)
- {
- kp += N_COLS;
- round(fwd_rnd, b1, b0, kp);
- l_copy(b0, b1);
- }
-#endif
- kp += N_COLS;
- round(fwd_lrnd, b0, b1, kp);
- }
-#endif
-
- state_out(out_blk, b0);
-#ifdef AES_ERR_CHK
- return aes_good;
-#endif
-}
-
-#endif
-
-#if defined(DECRYPTION) && !defined(AES_ASM)
-
-/* Visual C++ .Net v7.1 provides the fastest encryption code when using
- Pentium optimiation with small code but this is poor for decryption
- so we need to control this with the following VC++ pragmas
-*/
-
-#if defined(_MSC_VER)
-#pragma optimize( "t", on )
-#endif
-
-/* Given the column (c) of the output state variable, the following
- macros give the input state variables which are needed in its
- computation for each row (r) of the state. All the alternative
- macros give the same end values but expand into different ways
- of calculating these values. In particular the complex macro
- used for dynamically variable block sizes is designed to expand
- to a compile time constant whenever possible but will expand to
- conditional clauses on some branches (I am grateful to Frank
- Yellin for this construction)
-*/
-
-#define inv_var(x,r,c)\
- ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
- : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
- : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
- : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
-
-#if defined(IT4_SET)
-#undef dec_imvars
-#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
-#elif defined(IT1_SET)
-#undef dec_imvars
-#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))
-#else
-#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)))
-#endif
-
-#if defined(IL4_SET)
-#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
-#elif defined(IL1_SET)
-#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))
-#else
-#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))
-#endif
-
-aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1])
-{ aes_32t locals(b0, b1);
-#ifdef dec_imvars
- dec_imvars; /* declare variables for inv_mcol() if needed */
-#endif
-
- aes_32t nr = (cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] ? cx->ks[52] : 14);
- const aes_32t *kp = cx->ks + nr * N_COLS;
-
-#ifdef AES_ERR_CHK
- if( (nr != 10 || !(cx->ks[0] | cx->ks[3] | cx->ks[4]))
- && (nr != 12 || !(cx->ks[0] | cx->ks[5] | cx->ks[6]))
- && (nr != 14 || !(cx->ks[0] | cx->ks[7] | cx->ks[8])) )
- return aes_error;
-#endif
-
- state_in(b0, in_blk, kp);
-
-#if (DEC_UNROLL == FULL)
-
- switch(nr)
- {
- case 14:
- round(inv_rnd, b1, b0, kp - 1 * N_COLS);
- round(inv_rnd, b0, b1, kp - 2 * N_COLS);
- kp -= 2 * N_COLS;
- case 12:
- round(inv_rnd, b1, b0, kp - 1 * N_COLS);
- round(inv_rnd, b0, b1, kp - 2 * N_COLS);
- kp -= 2 * N_COLS;
- case 10:
- round(inv_rnd, b1, b0, kp - 1 * N_COLS);
- round(inv_rnd, b0, b1, kp - 2 * N_COLS);
- round(inv_rnd, b1, b0, kp - 3 * N_COLS);
- round(inv_rnd, b0, b1, kp - 4 * N_COLS);
- round(inv_rnd, b1, b0, kp - 5 * N_COLS);
- round(inv_rnd, b0, b1, kp - 6 * N_COLS);
- round(inv_rnd, b1, b0, kp - 7 * N_COLS);
- round(inv_rnd, b0, b1, kp - 8 * N_COLS);
- round(inv_rnd, b1, b0, kp - 9 * N_COLS);
- round(inv_lrnd, b0, b1, kp - 10 * N_COLS);
- }
-
-#else
-
-#if (DEC_UNROLL == PARTIAL)
- { aes_32t rnd;
- for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
- {
- kp -= N_COLS;
- round(inv_rnd, b1, b0, kp);
- kp -= N_COLS;
- round(inv_rnd, b0, b1, kp);
- }
- kp -= N_COLS;
- round(inv_rnd, b1, b0, kp);
-#else
- { aes_32t rnd;
- for(rnd = 0; rnd < nr - 1; ++rnd)
- {
- kp -= N_COLS;
- round(inv_rnd, b1, b0, kp);
- l_copy(b0, b1);
- }
-#endif
- kp -= N_COLS;
- round(inv_lrnd, b0, b1, kp);
- }
-#endif
-
- state_out(out_blk, b0);
-#ifdef AES_ERR_CHK
- return aes_good;
-#endif
-}
-
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/main/aeskey.c b/main/aeskey.c
deleted file mode 100644
index d34badc6b..000000000
--- a/main/aeskey.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- ---------------------------------------------------------------------------
- Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
- All rights reserved.
-
- LICENSE TERMS
-
- The free distribution and use of this software in both source and binary
- form is allowed (with or without changes) provided that:
-
- 1. distributions of this source code include the above copyright
- notice, this list of conditions and the following disclaimer;
-
- 2. distributions in binary form include the above copyright
- notice, this list of conditions and the following disclaimer
- in the documentation and/or other associated materials;
-
- 3. the copyright holder's name is not used to endorse products
- built using this software without specific written permission.
-
- ALTERNATIVELY, provided that this notice is retained in full, this product
- may be distributed under the terms of the GNU General Public License (GPL),
- in which case the provisions of the GPL apply INSTEAD OF those given above.
-
- DISCLAIMER
-
- This software is provided 'as is' with no explicit or implied warranties
- in respect of its properties, including, but not limited to, correctness
- and/or fitness for purpose.
- ---------------------------------------------------------------------------
- Issue Date: 26/08/2003
-
-*/
-
-/*! \file
- *
- * \brief This file contains the code for implementing the key schedule for AES
- * (Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h
- * for further details including optimisation.
- *
- * \author Dr Brian Gladman <brg@gladman.me.uk>
- */
-
-#include "aesopt.h"
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-/* Initialise the key schedule from the user supplied key. The key
- length can be specified in bytes, with legal values of 16, 24
- and 32, or in bits, with legal values of 128, 192 and 256. These
- values correspond with Nk values of 4, 6 and 8 respectively.
-
- The following macros implement a single cycle in the key
- schedule generation process. The number of cycles needed
- for each cx->n_col and nk value is:
-
- nk = 4 5 6 7 8
- ------------------------------
- cx->n_col = 4 10 9 8 7 7
- cx->n_col = 5 14 11 10 9 9
- cx->n_col = 6 19 15 12 11 11
- cx->n_col = 7 21 19 16 13 14
- cx->n_col = 8 29 23 19 17 14
-*/
-
-#define ke4(k,i) \
-{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
- k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
-}
-#define kel4(k,i) \
-{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
- k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
-}
-
-#define ke6(k,i) \
-{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
- k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
- k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \
-}
-#define kel6(k,i) \
-{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
- k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
-}
-
-#define ke8(k,i) \
-{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
- k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
- k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \
- k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \
-}
-#define kel8(k,i) \
-{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
- k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
-}
-
-#if defined(ENCRYPTION_KEY_SCHEDULE)
-
-#if defined(AES_128) || defined(AES_VAR)
-
-aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1])
-{ aes_32t ss[4];
-
- cx->ks[0] = ss[0] = word_in(in_key, 0);
- cx->ks[1] = ss[1] = word_in(in_key, 1);
- cx->ks[2] = ss[2] = word_in(in_key, 2);
- cx->ks[3] = ss[3] = word_in(in_key, 3);
-
-#if ENC_UNROLL == NONE
- { aes_32t i;
-
- for(i = 0; i < ((11 * N_COLS - 1) / 4); ++i)
- ke4(cx->ks, i);
- }
-#else
- ke4(cx->ks, 0); ke4(cx->ks, 1);
- ke4(cx->ks, 2); ke4(cx->ks, 3);
- ke4(cx->ks, 4); ke4(cx->ks, 5);
- ke4(cx->ks, 6); ke4(cx->ks, 7);
- ke4(cx->ks, 8); kel4(cx->ks, 9);
-#endif
-
- /* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
- /* key and must be non-zero for 128 and 192 bits keys */
- cx->ks[53] = cx->ks[45] = 0;
- cx->ks[52] = 10;
-#ifdef AES_ERR_CHK
- return aes_good;
-#endif
-}
-
-#endif
-
-#if defined(AES_192) || defined(AES_VAR)
-
-aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1])
-{ aes_32t ss[6];
-
- cx->ks[0] = ss[0] = word_in(in_key, 0);
- cx->ks[1] = ss[1] = word_in(in_key, 1);
- cx->ks[2] = ss[2] = word_in(in_key, 2);
- cx->ks[3] = ss[3] = word_in(in_key, 3);
- cx->ks[4] = ss[4] = word_in(in_key, 4);
- cx->ks[5] = ss[5] = word_in(in_key, 5);
-
-#if ENC_UNROLL == NONE
- { aes_32t i;
-
- for(i = 0; i < (13 * N_COLS - 1) / 6; ++i)
- ke6(cx->ks, i);
- }
-#else
- ke6(cx->ks, 0); ke6(cx->ks, 1);
- ke6(cx->ks, 2); ke6(cx->ks, 3);
- ke6(cx->ks, 4); ke6(cx->ks, 5);
- ke6(cx->ks, 6); kel6(cx->ks, 7);
-#endif
-
- /* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
- /* key and must be non-zero for 128 and 192 bits keys */
- cx->ks[53] = cx->ks[45];
- cx->ks[52] = 12;
-#ifdef AES_ERR_CHK
- return aes_good;
-#endif
-}
-
-#endif
-
-#if defined(AES_256) || defined(AES_VAR)
-
-aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1])
-{ aes_32t ss[8];
-
- cx->ks[0] = ss[0] = word_in(in_key, 0);
- cx->ks[1] = ss[1] = word_in(in_key, 1);
- cx->ks[2] = ss[2] = word_in(in_key, 2);
- cx->ks[3] = ss[3] = word_in(in_key, 3);
- cx->ks[4] = ss[4] = word_in(in_key, 4);
- cx->ks[5] = ss[5] = word_in(in_key, 5);
- cx->ks[6] = ss[6] = word_in(in_key, 6);
- cx->ks[7] = ss[7] = word_in(in_key, 7);
-
-#if ENC_UNROLL == NONE
- { aes_32t i;
-
- for(i = 0; i < (15 * N_COLS - 1) / 8; ++i)
- ke8(cx->ks, i);
- }
-#else
- ke8(cx->ks, 0); ke8(cx->ks, 1);
- ke8(cx->ks, 2); ke8(cx->ks, 3);
- ke8(cx->ks, 4); ke8(cx->ks, 5);
- kel8(cx->ks, 6);
-#endif
-#ifdef AES_ERR_CHK
- return aes_good;
-#endif
-}
-
-#endif
-
-#if defined(AES_VAR)
-
-aes_rval aes_encrypt_key(const void *in_key, int key_len, aes_encrypt_ctx cx[1])
-{
- switch(key_len)
- {
-#ifdef AES_ERR_CHK
- case 16: case 128: return aes_encrypt_key128(in_key, cx);
- case 24: case 192: return aes_encrypt_key192(in_key, cx);
- case 32: case 256: return aes_encrypt_key256(in_key, cx);
- default: return aes_error;
-#else
- case 16: case 128: aes_encrypt_key128(in_key, cx); return;
- case 24: case 192: aes_encrypt_key192(in_key, cx); return;
- case 32: case 256: aes_encrypt_key256(in_key, cx); return;
-#endif
- }
-}
-
-#endif
-
-#endif
-
-#if defined(DECRYPTION_KEY_SCHEDULE)
-
-#if DEC_ROUND == NO_TABLES
-#define ff(x) (x)
-#else
-#define ff(x) inv_mcol(x)
-#ifdef dec_imvars
-#define d_vars dec_imvars
-#endif
-#endif
-
-#if 1
-#define kdf4(k,i) \
-{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \
- ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
- ss[4] ^= k[4*(i)]; k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \
- ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \
-}
-#define kd4(k,i) \
-{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \
- k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \
- k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \
-}
-#define kdl4(k,i) \
-{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
- k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \
- k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \
-}
-#else
-#define kdf4(k,i) \
-{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \
- ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \
-}
-#define kd4(k,i) \
-{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \
- ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \
- ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \
- ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \
- ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \
-}
-#define kdl4(k,i) \
-{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \
- ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \
-}
-#endif
-
-#define kdf6(k,i) \
-{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \
- ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \
- ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \
-}
-#define kd6(k,i) \
-{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \
- ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \
- ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \
- ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \
- ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \
- ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \
- ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \
-}
-#define kdl6(k,i) \
-{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \
- ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \
-}
-
-#define kdf8(k,i) \
-{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \
- ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \
- ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \
- ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \
-}
-#define kd8(k,i) \
-{ aes_32t g = ls_box(ss[7],3) ^ t_use(r,c)[i]; \
- ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \
- ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \
- ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \
- ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \
- g = ls_box(ss[3],0); \
- ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \
- ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \
- ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \
- ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \
-}
-#define kdl8(k,i) \
-{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \
- ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \
-}
-
-#if defined(AES_128) || defined(AES_VAR)
-
-aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1])
-{ aes_32t ss[5];
-#ifdef d_vars
- d_vars;
-#endif
- cx->ks[0] = ss[0] = word_in(in_key, 0);
- cx->ks[1] = ss[1] = word_in(in_key, 1);
- cx->ks[2] = ss[2] = word_in(in_key, 2);
- cx->ks[3] = ss[3] = word_in(in_key, 3);
-
-#if DEC_UNROLL == NONE
- { aes_32t i;
-
- for(i = 0; i < (11 * N_COLS - 1) / 4; ++i)
- ke4(cx->ks, i);
-#if !(DEC_ROUND == NO_TABLES)
- for(i = N_COLS; i < 10 * N_COLS; ++i)
- cx->ks[i] = inv_mcol(cx->ks[i]);
-#endif
- }
-#else
- kdf4(cx->ks, 0); kd4(cx->ks, 1);
- kd4(cx->ks, 2); kd4(cx->ks, 3);
- kd4(cx->ks, 4); kd4(cx->ks, 5);
- kd4(cx->ks, 6); kd4(cx->ks, 7);
- kd4(cx->ks, 8); kdl4(cx->ks, 9);
-#endif
-
- /* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
- /* key and must be non-zero for 128 and 192 bits keys */
- cx->ks[53] = cx->ks[45] = 0;
- cx->ks[52] = 10;
-#ifdef AES_ERR_CHK
- return aes_good;
-#endif
-}
-
-#endif
-
-#if defined(AES_192) || defined(AES_VAR)
-
-aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1])
-{ aes_32t ss[7];
-#ifdef d_vars
- d_vars;
-#endif
- cx->ks[0] = ss[0] = word_in(in_key, 0);
- cx->ks[1] = ss[1] = word_in(in_key, 1);
- cx->ks[2] = ss[2] = word_in(in_key, 2);
- cx->ks[3] = ss[3] = word_in(in_key, 3);
-
-#if DEC_UNROLL == NONE
- cx->ks[4] = ss[4] = word_in(in_key, 4);
- cx->ks[5] = ss[5] = word_in(in_key, 5);
- { aes_32t i;
-
- for(i = 0; i < (13 * N_COLS - 1) / 6; ++i)
- ke6(cx->ks, i);
-#if !(DEC_ROUND == NO_TABLES)
- for(i = N_COLS; i < 12 * N_COLS; ++i)
- cx->ks[i] = inv_mcol(cx->ks[i]);
-#endif
- }
-#else
- cx->ks[4] = ff(ss[4] = word_in(in_key, 4));
- cx->ks[5] = ff(ss[5] = word_in(in_key, 5));
- kdf6(cx->ks, 0); kd6(cx->ks, 1);
- kd6(cx->ks, 2); kd6(cx->ks, 3);
- kd6(cx->ks, 4); kd6(cx->ks, 5);
- kd6(cx->ks, 6); kdl6(cx->ks, 7);
-#endif
-
- /* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
- /* key and must be non-zero for 128 and 192 bits keys */
- cx->ks[53] = cx->ks[45];
- cx->ks[52] = 12;
-#ifdef AES_ERR_CHK
- return aes_good;
-#endif
-}
-
-#endif
-
-#if defined(AES_256) || defined(AES_VAR)
-
-aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1])
-{ aes_32t ss[8];
-#ifdef d_vars
- d_vars;
-#endif
- cx->ks[0] = ss[0] = word_in(in_key, 0);
- cx->ks[1] = ss[1] = word_in(in_key, 1);
- cx->ks[2] = ss[2] = word_in(in_key, 2);
- cx->ks[3] = ss[3] = word_in(in_key, 3);
-
-#if DEC_UNROLL == NONE
- cx->ks[4] = ss[4] = word_in(in_key, 4);
- cx->ks[5] = ss[5] = word_in(in_key, 5);
- cx->ks[6] = ss[6] = word_in(in_key, 6);
- cx->ks[7] = ss[7] = word_in(in_key, 7);
- { aes_32t i;
-
- for(i = 0; i < (15 * N_COLS - 1) / 8; ++i)
- ke8(cx->ks, i);
-#if !(DEC_ROUND == NO_TABLES)
- for(i = N_COLS; i < 14 * N_COLS; ++i)
- cx->ks[i] = inv_mcol(cx->ks[i]);
-#endif
- }
-#else
- cx->ks[4] = ff(ss[4] = word_in(in_key, 4));
- cx->ks[5] = ff(ss[5] = word_in(in_key, 5));
- cx->ks[6] = ff(ss[6] = word_in(in_key, 6));
- cx->ks[7] = ff(ss[7] = word_in(in_key, 7));
- kdf8(cx->ks, 0); kd8(cx->ks, 1);
- kd8(cx->ks, 2); kd8(cx->ks, 3);
- kd8(cx->ks, 4); kd8(cx->ks, 5);
- kdl8(cx->ks, 6);
-#endif
-#ifdef AES_ERR_CHK
- return aes_good;
-#endif
-}
-
-#endif
-
-#if defined(AES_VAR)
-
-aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1])
-{
- switch(key_len)
- {
-#ifdef AES_ERR_CHK
- case 16: case 128: return aes_decrypt_key128(in_key, cx);
- case 24: case 192: return aes_decrypt_key192(in_key, cx);
- case 32: case 256: return aes_decrypt_key256(in_key, cx);
- default: return aes_error;
-#else
- case 16: case 128: aes_decrypt_key128(in_key, cx); return;
- case 24: case 192: aes_decrypt_key192(in_key, cx); return;
- case 32: case 256: aes_decrypt_key256(in_key, cx); return;
-#endif
- }
-}
-
-#endif
-
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/main/aesopt.h b/main/aesopt.h
deleted file mode 100644
index bb4f05a0b..000000000
--- a/main/aesopt.h
+++ /dev/null
@@ -1,1029 +0,0 @@
-/*
- ---------------------------------------------------------------------------
- Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
- All rights reserved.
-
- LICENSE TERMS
-
- The free distribution and use of this software in both source and binary
- form is allowed (with or without changes) provided that:
-
- 1. distributions of this source code include the above copyright
- notice, this list of conditions and the following disclaimer;
-
- 2. distributions in binary form include the above copyright
- notice, this list of conditions and the following disclaimer
- in the documentation and/or other associated materials;
-
- 3. the copyright holder's name is not used to endorse products
- built using this software without specific written permission.
-
- ALTERNATIVELY, provided that this notice is retained in full, this product
- may be distributed under the terms of the GNU General Public License (GPL),
- in which case the provisions of the GPL apply INSTEAD OF those given above.
-
- DISCLAIMER
-
- This software is provided 'as is' with no explicit or implied warranties
- in respect of its properties, including, but not limited to, correctness
- and/or fitness for purpose.
- ---------------------------------------------------------------------------
- Issue Date: 26/08/2003
-
- My thanks go to Dag Arne Osvik for devising the schemes used here for key
- length derivation from the form of the key schedule
-
- This file contains the compilation options for AES (Rijndael) and code
- that is common across encryption, key scheduling and table generation.
-
- OPERATION
-
- These source code files implement the AES algorithm Rijndael designed by
- Joan Daemen and Vincent Rijmen. This version is designed for the standard
- block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24
- and 32 bytes).
-
- This version is designed for flexibility and speed using operations on
- 32-bit words rather than operations on bytes. It can be compiled with
- either big or little endian internal byte order but is faster when the
- native byte order for the processor is used.
-
- THE CIPHER INTERFACE
-
- The cipher interface is implemented as an array of bytes in which lower
- AES bit sequence indexes map to higher numeric significance within bytes.
-
- aes_08t (an unsigned 8-bit type)
- aes_32t (an unsigned 32-bit type)
- struct aes_encrypt_ctx (structure for the cipher encryption context)
- struct aes_decrypt_ctx (structure for the cipher decryption context)
- aes_rval the function return type
-
- C subroutine calls:
-
- aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1]);
- aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1]);
- aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1]);
- aes_rval aes_encrypt(const void *in_blk,
- void *out_blk, const aes_encrypt_ctx cx[1]);
-
- aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1]);
- aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1]);
- aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1]);
- aes_rval aes_decrypt(const void *in_blk,
- void *out_blk, const aes_decrypt_ctx cx[1]);
-
- IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that
- you call genTabs() before AES is used so that the tables are initialised.
-
- C++ aes class subroutines:
-
- Class AESencrypt for encryption
-
- Construtors:
- AESencrypt(void)
- AESencrypt(const void *in_key) - 128 bit key
- Members:
- void key128(const void *in_key)
- void key192(const void *in_key)
- void key256(const void *in_key)
- void encrypt(const void *in_blk, void *out_blk) const
-
- Class AESdecrypt for encryption
- Construtors:
- AESdecrypt(void)
- AESdecrypt(const void *in_key) - 128 bit key
- Members:
- void key128(const void *in_key)
- void key192(const void *in_key)
- void key256(const void *in_key)
- void decrypt(const void *in_blk, void *out_blk) const
-
- COMPILATION
-
- The files used to provide AES (Rijndael) are
-
- a. aes.h for the definitions needed for use in C.
- b. aescpp.h for the definitions needed for use in C++.
- c. aesopt.h for setting compilation options (also includes common code).
- d. aescrypt.c for encryption and decrytpion, or
- e. aeskey.c for key scheduling.
- f. aestab.c for table loading or generation.
- g. aescrypt.asm for encryption and decryption using assembler code.
- h. aescrypt.mmx.asm for encryption and decryption using MMX assembler.
-
- To compile AES (Rijndael) for use in C code use aes.h and set the
- defines here for the facilities you need (key lengths, encryption
- and/or decryption). Do not define AES_DLL or AES_CPP. Set the options
- for optimisations and table sizes here.
-
- To compile AES (Rijndael) for use in in C++ code use aescpp.h but do
- not define AES_DLL
-
- To compile AES (Rijndael) in C as a Dynamic Link Library DLL) use
- aes.h and include the AES_DLL define.
-
- CONFIGURATION OPTIONS (here and in aes.h)
-
- a. set AES_DLL in aes.h if AES (Rijndael) is to be compiled as a DLL
- b. You may need to set PLATFORM_BYTE_ORDER to define the byte order.
- c. If you want the code to run in a specific internal byte order, then
- ALGORITHM_BYTE_ORDER must be set accordingly.
- d. set other configuration options decribed below.
-*/
-
-#ifndef _AESOPT_H
-#define _AESOPT_H
-
-#include "asterisk/aes.h"
-#include "asterisk/endian.h"
-
-/* CONFIGURATION - USE OF DEFINES
-
- Later in this section there are a number of defines that control the
- operation of the code. In each section, the purpose of each define is
- explained so that the relevant form can be included or excluded by
- setting either 1's or 0's respectively on the branches of the related
- #if clauses.
-*/
-
-/* BYTE ORDER IN 32-BIT WORDS
-
- To obtain the highest speed on processors with 32-bit words, this code
- needs to determine the byte order of the target machine. The following
- block of code is an attempt to capture the most obvious ways in which
- various environemnts define byte order. It may well fail, in which case
- the definitions will need to be set by editing at the points marked
- **** EDIT HERE IF NECESSARY **** below. My thanks to Peter Gutmann for
- some of these defines (from cryptlib).
-*/
-
-#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
-#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
-
-#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
- defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
- defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
- defined( vax ) || defined( vms ) || defined( VMS ) || \
- defined( __VMS )
-
-#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
-
-#endif
-
-#if defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
- defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
- defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
- defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
- defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
- defined( __TANDEM ) || defined( THINK_C ) || defined( __VMCMS__ )
-
-#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
-
-#endif
-
-/* if the platform is still not known, try to find its byte order */
-/* from commonly used definitions in the headers included earlier */
-
-#if !defined(PLATFORM_BYTE_ORDER)
-
-#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN)
-# if defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
-# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
-# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
-# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
-# elif defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
-# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
-# elif defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
-# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
-# endif
-
-#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)
-# if defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
-# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
-# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
-# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
-# elif defined(_BYTE_ORDER) && (_BYTE_ORDER == _LITTLE_ENDIAN)
-# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
-# elif defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)
-# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
-# endif
-
-#elif defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__)
-# if defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
-# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
-# elif !defined(__LITTLE_ENDIAN__) && defined(__BIG_ENDIAN__)
-# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
-# elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __LITTLE_ENDIAN__)
-# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
-# elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)
-# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
-# endif
-
-#elif 0 /* **** EDIT HERE IF NECESSARY **** */
-#define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN
-
-#elif 0 /* **** EDIT HERE IF NECESSARY **** */
-#define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN
-
-#else
-#error Please edit aesopt.h (line 235 or 238) to set the platform byte order
-#endif
-
-#endif
-
-/* SOME LOCAL DEFINITIONS */
-
-#define NO_TABLES 0
-#define ONE_TABLE 1
-#define FOUR_TABLES 4
-#define NONE 0
-#define PARTIAL 1
-#define FULL 2
-
-#if defined(bswap32)
-#define aes_sw32 bswap32
-#elif defined(bswap_32)
-#define aes_sw32 bswap_32
-#else
-#define brot(x,n) (((aes_32t)(x) << n) | ((aes_32t)(x) >> (32 - n)))
-#define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00))
-#endif
-
-/* 1. FUNCTIONS REQUIRED
-
- This implementation provides subroutines for encryption, decryption
- and for setting the three key lengths (separately) for encryption
- and decryption. When the assembler code is not being used the following
- definition blocks allow the selection of the routines that are to be
- included in the compilation.
-*/
-#ifdef AES_ENCRYPT
-#define ENCRYPTION
-#define ENCRYPTION_KEY_SCHEDULE
-#endif
-
-#ifdef AES_DECRYPT
-#define DECRYPTION
-#define DECRYPTION_KEY_SCHEDULE
-#endif
-
-/* 2. ASSEMBLER SUPPORT
-
- This define (which can be on the command line) enables the use of the
- assembler code routines for encryption and decryption with the C code
- only providing key scheduling
-*/
-#if 0
-#define AES_ASM
-#endif
-
-/* 3. BYTE ORDER WITHIN 32 BIT WORDS
-
- The fundamental data processing units in Rijndael are 8-bit bytes. The
- input, output and key input are all enumerated arrays of bytes in which
- bytes are numbered starting at zero and increasing to one less than the
- number of bytes in the array in question. This enumeration is only used
- for naming bytes and does not imply any adjacency or order relationship
- from one byte to another. When these inputs and outputs are considered
- as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to
- byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte.
- In this implementation bits are numbered from 0 to 7 starting at the
- numerically least significant end of each byte (bit n represents 2^n).
-
- However, Rijndael can be implemented more efficiently using 32-bit
- words by packing bytes into words so that bytes 4*n to 4*n+3 are placed
- into word[n]. While in principle these bytes can be assembled into words
- in any positions, this implementation only supports the two formats in
- which bytes in adjacent positions within words also have adjacent byte
- numbers. This order is called big-endian if the lowest numbered bytes
- in words have the highest numeric significance and little-endian if the
- opposite applies.
-
- This code can work in either order irrespective of the order used by the
- machine on which it runs. Normally the internal byte order will be set
- to the order of the processor on which the code is to be run but this
- define can be used to reverse this in special situations
-
- NOTE: Assembler code versions rely on PLATFORM_BYTE_ORDER being set
-*/
-#if 1 || defined(AES_ASM)
-#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER
-#elif 0
-#define ALGORITHM_BYTE_ORDER BRG_LITTLE_ENDIAN
-#elif 0
-#define ALGORITHM_BYTE_ORDER BRG_BIG_ENDIAN
-#else
-#error The algorithm byte order is not defined
-#endif
-
-/* 4. FAST INPUT/OUTPUT OPERATIONS.
-
- On some machines it is possible to improve speed by transferring the
- bytes in the input and output arrays to and from the internal 32-bit
- variables by addressing these arrays as if they are arrays of 32-bit
- words. On some machines this will always be possible but there may
- be a large performance penalty if the byte arrays are not aligned on
- the normal word boundaries. On other machines this technique will
- lead to memory access errors when such 32-bit word accesses are not
- properly aligned. The option SAFE_IO avoids such problems but will
- often be slower on those machines that support misaligned access
- (especially so if care is taken to align the input and output byte
- arrays on 32-bit word boundaries). If SAFE_IO is not defined it is
- assumed that access to byte arrays as if they are arrays of 32-bit
- words will not cause problems when such accesses are misaligned.
-*/
-#if 1 && !defined(_MSC_VER)
-#define SAFE_IO
-#endif
-
-/* 5. LOOP UNROLLING
-
- The code for encryption and decrytpion cycles through a number of rounds
- that can be implemented either in a loop or by expanding the code into a
- long sequence of instructions, the latter producing a larger program but
- one that will often be much faster. The latter is called loop unrolling.
- There are also potential speed advantages in expanding two iterations in
- a loop with half the number of iterations, which is called partial loop
- unrolling. The following options allow partial or full loop unrolling
- to be set independently for encryption and decryption
-*/
-#if 1
-#define ENC_UNROLL FULL
-#elif 0
-#define ENC_UNROLL PARTIAL
-#else
-#define ENC_UNROLL NONE
-#endif
-
-#if 1
-#define DEC_UNROLL FULL
-#elif 0
-#define DEC_UNROLL PARTIAL
-#else
-#define DEC_UNROLL NONE
-#endif
-
-/* 6. FAST FINITE FIELD OPERATIONS
-
- If this section is included, tables are used to provide faster finite
- field arithmetic (this has no effect if FIXED_TABLES is defined).
-*/
-#if 1
-#define FF_TABLES
-#endif
-
-/* 7. INTERNAL STATE VARIABLE FORMAT
-
- The internal state of Rijndael is stored in a number of local 32-bit
- word varaibles which can be defined either as an array or as individual
- names variables. Include this section if you want to store these local
- varaibles in arrays. Otherwise individual local variables will be used.
-*/
-#if 1
-#define ARRAYS
-#endif
-
-/* In this implementation the columns of the state array are each held in
- 32-bit words. The state array can be held in various ways: in an array
- of words, in a number of individual word variables or in a number of
- processor registers. The following define maps a variable name x and
- a column number c to the way the state array variable is to be held.
- The first define below maps the state into an array x[c] whereas the
- second form maps the state into a number of individual variables x0,
- x1, etc. Another form could map individual state colums to machine
- register names.
-*/
-
-#if defined(ARRAYS)
-#define s(x,c) x[c]
-#else
-#define s(x,c) x##c
-#endif
-
-/* 8. FIXED OR DYNAMIC TABLES
-
- When this section is included the tables used by the code are compiled
- statically into the binary file. Otherwise the subroutine gen_tabs()
- must be called to compute them before the code is first used.
-*/
-#if 1
-#define FIXED_TABLES
-#endif
-
-/* 9. TABLE ALIGNMENT
-
- On some sytsems speed will be improved by aligning the AES large lookup
- tables on particular boundaries. This define should be set to a power of
- two giving the desired alignment. It can be left undefined if alignment
- is not needed. This option is specific to the Microsft VC++ compiler -
- it seems to sometimes cause trouble for the VC++ version 6 compiler.
-*/
-
-#if 0 && defined(_MSC_VER) && (_MSC_VER >= 1300)
-#define TABLE_ALIGN 64
-#endif
-
-/* 10. INTERNAL TABLE CONFIGURATION
-
- This cipher proceeds by repeating in a number of cycles known as 'rounds'
- which are implemented by a round function which can optionally be speeded
- up using tables. The basic tables are each 256 32-bit words, with either
- one or four tables being required for each round function depending on
- how much speed is required. The encryption and decryption round functions
- are different and the last encryption and decrytpion round functions are
- different again making four different round functions in all.
-
- This means that:
- 1. Normal encryption and decryption rounds can each use either 0, 1
- or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
- 2. The last encryption and decryption rounds can also use either 0, 1
- or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
-
- Include or exclude the appropriate definitions below to set the number
- of tables used by this implementation.
-*/
-
-#if 1 /* set tables for the normal encryption round */
-#define ENC_ROUND FOUR_TABLES
-#elif 0
-#define ENC_ROUND ONE_TABLE
-#else
-#define ENC_ROUND NO_TABLES
-#endif
-
-#if 1 /* set tables for the last encryption round */
-#define LAST_ENC_ROUND FOUR_TABLES
-#elif 0
-#define LAST_ENC_ROUND ONE_TABLE
-#else
-#define LAST_ENC_ROUND NO_TABLES
-#endif
-
-#if 1 /* set tables for the normal decryption round */
-#define DEC_ROUND FOUR_TABLES
-#elif 0
-#define DEC_ROUND ONE_TABLE
-#else
-#define DEC_ROUND NO_TABLES
-#endif
-
-#if 1 /* set tables for the last decryption round */
-#define LAST_DEC_ROUND FOUR_TABLES
-#elif 0
-#define LAST_DEC_ROUND ONE_TABLE
-#else
-#define LAST_DEC_ROUND NO_TABLES
-#endif
-
-/* The decryption key schedule can be speeded up with tables in the same
- way that the round functions can. Include or exclude the following
- defines to set this requirement.
-*/
-#if 1
-#define KEY_SCHED FOUR_TABLES
-#elif 0
-#define KEY_SCHED ONE_TABLE
-#else
-#define KEY_SCHED NO_TABLES
-#endif
-
-/* END OF CONFIGURATION OPTIONS */
-
-#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2))
-
-/* Disable or report errors on some combinations of options */
-
-#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES
-#undef LAST_ENC_ROUND
-#define LAST_ENC_ROUND NO_TABLES
-#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES
-#undef LAST_ENC_ROUND
-#define LAST_ENC_ROUND ONE_TABLE
-#endif
-
-#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE
-#undef ENC_UNROLL
-#define ENC_UNROLL NONE
-#endif
-
-#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES
-#undef LAST_DEC_ROUND
-#define LAST_DEC_ROUND NO_TABLES
-#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES
-#undef LAST_DEC_ROUND
-#define LAST_DEC_ROUND ONE_TABLE
-#endif
-
-#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE
-#undef DEC_UNROLL
-#define DEC_UNROLL NONE
-#endif
-
-/* upr(x,n): rotates bytes within words by n positions, moving bytes to
- higher index positions with wrap around into low positions
- ups(x,n): moves bytes by n positions to higher index positions in
- words but without wrap around
- bval(x,n): extracts a byte from a word
-
- NOTE: The definitions given here are intended only for use with
- unsigned variables and with shift counts that are compile
- time constants
-*/
-
-#if (ALGORITHM_BYTE_ORDER == BRG_LITTLE_ENDIAN)
-#define upr(x,n) (((aes_32t)(x) << (8 * (n))) | ((aes_32t)(x) >> (32 - 8 * (n))))
-#define ups(x,n) ((aes_32t) (x) << (8 * (n)))
-#define bval(x,n) ((aes_08t)((x) >> (8 * (n))))
-#define bytes2word(b0, b1, b2, b3) \
- (((aes_32t)(b3) << 24) | ((aes_32t)(b2) << 16) | ((aes_32t)(b1) << 8) | (b0))
-#endif
-
-#if (ALGORITHM_BYTE_ORDER == BRG_BIG_ENDIAN)
-#define upr(x,n) (((aes_32t)(x) >> (8 * (n))) | ((aes_32t)(x) << (32 - 8 * (n))))
-#define ups(x,n) ((aes_32t) (x) >> (8 * (n))))
-#define bval(x,n) ((aes_08t)((x) >> (24 - 8 * (n))))
-#define bytes2word(b0, b1, b2, b3) \
- (((aes_32t)(b0) << 24) | ((aes_32t)(b1) << 16) | ((aes_32t)(b2) << 8) | (b3))
-#endif
-
-#if defined(SAFE_IO)
-
-#define word_in(x,c) bytes2word(((aes_08t*)(x)+4*c)[0], ((aes_08t*)(x)+4*c)[1], \
- ((aes_08t*)(x)+4*c)[2], ((aes_08t*)(x)+4*c)[3])
-#define word_out(x,c,v) { ((aes_08t*)(x)+4*c)[0] = bval(v,0); ((aes_08t*)(x)+4*c)[1] = bval(v,1); \
- ((aes_08t*)(x)+4*c)[2] = bval(v,2); ((aes_08t*)(x)+4*c)[3] = bval(v,3); }
-
-#elif (ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER)
-
-#define word_in(x,c) (*((aes_32t*)(x)+(c)))
-#define word_out(x,c,v) (*((aes_32t*)(x)+(c)) = (v))
-
-#else
-
-#define word_in(x,c) aes_sw32(*((aes_32t*)(x)+(c)))
-#define word_out(x,c,v) (*((aes_32t*)(x)+(c)) = aes_sw32(v))
-
-#endif
-
-/* the finite field modular polynomial and elements */
-
-#define WPOLY 0x011b
-#define BPOLY 0x1b
-
-/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
-
-#define m1 0x80808080
-#define m2 0x7f7f7f7f
-#define gf_mulx(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY))
-
-/* The following defines provide alternative definitions of gf_mulx that might
- give improved performance if a fast 32-bit multiply is not available. Note
- that a temporary variable u needs to be defined where gf_mulx is used.
-
-#define gf_mulx(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6))
-#define m4 (0x01010101 * BPOLY)
-#define gf_mulx(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4)
-*/
-
-/* Work out which tables are needed for the different options */
-
-#ifdef AES_ASM
-#ifdef ENC_ROUND
-#undef ENC_ROUND
-#endif
-#define ENC_ROUND FOUR_TABLES
-#ifdef LAST_ENC_ROUND
-#undef LAST_ENC_ROUND
-#endif
-#define LAST_ENC_ROUND FOUR_TABLES
-#ifdef DEC_ROUND
-#undef DEC_ROUND
-#endif
-#define DEC_ROUND FOUR_TABLES
-#ifdef LAST_DEC_ROUND
-#undef LAST_DEC_ROUND
-#endif
-#define LAST_DEC_ROUND FOUR_TABLES
-#ifdef KEY_SCHED
-#undef KEY_SCHED
-#define KEY_SCHED FOUR_TABLES
-#endif
-#endif
-
-#if defined(ENCRYPTION) || defined(AES_ASM)
-#if ENC_ROUND == ONE_TABLE
-#define FT1_SET
-#elif ENC_ROUND == FOUR_TABLES
-#define FT4_SET
-#else
-#define SBX_SET
-#endif
-#if LAST_ENC_ROUND == ONE_TABLE
-#define FL1_SET
-#elif LAST_ENC_ROUND == FOUR_TABLES
-#define FL4_SET
-#elif !defined(SBX_SET)
-#define SBX_SET
-#endif
-#endif
-
-#if defined(DECRYPTION) || defined(AES_ASM)
-#if DEC_ROUND == ONE_TABLE
-#define IT1_SET
-#elif DEC_ROUND == FOUR_TABLES
-#define IT4_SET
-#else
-#define ISB_SET
-#endif
-#if LAST_DEC_ROUND == ONE_TABLE
-#define IL1_SET
-#elif LAST_DEC_ROUND == FOUR_TABLES
-#define IL4_SET
-#elif !defined(ISB_SET)
-#define ISB_SET
-#endif
-#endif
-
-#if defined(ENCRYPTION_KEY_SCHEDULE) || defined(DECRYPTION_KEY_SCHEDULE)
-#if KEY_SCHED == ONE_TABLE
-#define LS1_SET
-#define IM1_SET
-#elif KEY_SCHED == FOUR_TABLES
-#define LS4_SET
-#define IM4_SET
-#elif !defined(SBX_SET)
-#define SBX_SET
-#endif
-#endif
-
-/* generic definitions of Rijndael macros that use tables */
-
-#define no_table(x,box,vf,rf,c) bytes2word( \
- box[bval(vf(x,0,c),rf(0,c))], \
- box[bval(vf(x,1,c),rf(1,c))], \
- box[bval(vf(x,2,c),rf(2,c))], \
- box[bval(vf(x,3,c),rf(3,c))])
-
-#define one_table(x,op,tab,vf,rf,c) \
- ( tab[bval(vf(x,0,c),rf(0,c))] \
- ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \
- ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \
- ^ op(tab[bval(vf(x,3,c),rf(3,c))],3))
-
-#define four_tables(x,tab,vf,rf,c) \
- ( tab[0][bval(vf(x,0,c),rf(0,c))] \
- ^ tab[1][bval(vf(x,1,c),rf(1,c))] \
- ^ tab[2][bval(vf(x,2,c),rf(2,c))] \
- ^ tab[3][bval(vf(x,3,c),rf(3,c))])
-
-#define vf1(x,r,c) (x)
-#define rf1(r,c) (r)
-#define rf2(r,c) ((8+r-c)&3)
-
-/* perform forward and inverse column mix operation on four bytes in long word x in */
-/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */
-
-#if defined(FM4_SET) /* not currently used */
-#define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0)
-#elif defined(FM1_SET) /* not currently used */
-#define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0)
-#else
-#define dec_fmvars aes_32t g2
-#define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1))
-#endif
-
-#if defined(IM4_SET)
-#define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0)
-#elif defined(IM1_SET)
-#define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0)
-#else
-#define dec_imvars aes_32t g2, g4, g9
-#define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \
- (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1))
-#endif
-
-#if defined(FL4_SET)
-#define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c)
-#elif defined(LS4_SET)
-#define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c)
-#elif defined(FL1_SET)
-#define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c)
-#elif defined(LS1_SET)
-#define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c)
-#else
-#define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c)
-#endif
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-/* If there are no global variables, the definitions here can be
- used to put the AES tables in a structure so that a pointer
- can then be added to the AES context to pass them to the AES
- routines that need them. If this facility is used, the calling
- program has to ensure that this pointer is managed appropriately.
- In particular, the value of the t_dec(in,it) item in the table
- structure must be set to zero in order to ensure that the tables
- are initialised. In practice the three code sequences in aeskey.c
- that control the calls to gen_tabs() and the gen_tabs() routine
- itself will have to be changed for a specific implementation. If
- global variables are available it will generally be preferable to
- use them with the precomputed FIXED_TABLES option that uses static
- global tables.
-
- The following defines can be used to control the way the tables
- are defined, initialised and used in embedded environments that
- require special features for these purposes
-
- the 't_dec' construction is used to declare fixed table arrays
- the 't_set' construction is used to set fixed table values
- the 't_use' construction is used to access fixed table values
-
- 256 byte tables:
-
- t_xxx(s,box) => forward S box
- t_xxx(i,box) => inverse S box
-
- 256 32-bit word OR 4 x 256 32-bit word tables:
-
- t_xxx(f,n) => forward normal round
- t_xxx(f,l) => forward last round
- t_xxx(i,n) => inverse normal round
- t_xxx(i,l) => inverse last round
- t_xxx(l,s) => key schedule table
- t_xxx(i,m) => key schedule table
-
- Other variables and tables:
-
- t_xxx(r,c) => the rcon table
-*/
-
-#define t_dec(m,n) t_##m##n
-#define t_set(m,n) t_##m##n
-#define t_use(m,n) t_##m##n
-
-#if defined(DO_TABLES) /* declare and instantiate tables */
-
-/* finite field arithmetic operations for table generation */
-
-#if defined(FIXED_TABLES) || !defined(FF_TABLES)
-
-#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY))
-#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))
-#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \
- ^ (((x>>5) & 4) * WPOLY))
-#define f3(x) (f2(x) ^ x)
-#define f9(x) (f8(x) ^ x)
-#define fb(x) (f8(x) ^ f2(x) ^ x)
-#define fd(x) (f8(x) ^ f4(x) ^ x)
-#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
-
-#else
-
-#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
-#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
-#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
-#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
-#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
-#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
-#define fi(x) ((x) ? pow[ 255 - log[x]] : 0)
-
-#endif
-
-#if defined(FIXED_TABLES) /* declare and set values for static tables */
-
-#define sb_data(w) \
- w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
- w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
- w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
- w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
- w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
- w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
- w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
- w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
- w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
- w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
- w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
- w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
- w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
- w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
- w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
- w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
- w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
- w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
- w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
- w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
- w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
- w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
- w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
- w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
- w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
- w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
- w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
- w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
- w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
- w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
- w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
- w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16)
-
-#define isb_data(w) \
- w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
- w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
- w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
- w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
- w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
- w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
- w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
- w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
- w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
- w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
- w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
- w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
- w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
- w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
- w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
- w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
- w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
- w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
- w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
- w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
- w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
- w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
- w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
- w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
- w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
- w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
- w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
- w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
- w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
- w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
- w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
- w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d),
-
-#define mm_data(w) \
- w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
- w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
- w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
- w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
- w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
- w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
- w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
- w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
- w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
- w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
- w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
- w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
- w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
- w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
- w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
- w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
- w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
- w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
- w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
- w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
- w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
- w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
- w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
- w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
- w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
- w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
- w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
- w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
- w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
- w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
- w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
- w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff)
-
-#define h0(x) (x)
-
-/* These defines are used to ensure tables are generated in the
- right format depending on the internal byte order required
-*/
-
-#define w0(p) bytes2word(p, 0, 0, 0)
-#define w1(p) bytes2word(0, p, 0, 0)
-#define w2(p) bytes2word(0, 0, p, 0)
-#define w3(p) bytes2word(0, 0, 0, p)
-
-#define u0(p) bytes2word(f2(p), p, p, f3(p))
-#define u1(p) bytes2word(f3(p), f2(p), p, p)
-#define u2(p) bytes2word(p, f3(p), f2(p), p)
-#define u3(p) bytes2word(p, p, f3(p), f2(p))
-
-#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p))
-#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p))
-#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p))
-#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p))
-
-const aes_32t t_dec(r,c)[RC_LENGTH] =
-{
- w0(0x01), w0(0x02), w0(0x04), w0(0x08), w0(0x10),
- w0(0x20), w0(0x40), w0(0x80), w0(0x1b), w0(0x36)
-};
-
-#define d_1(t,n,b,v) const t n[256] = { b(v##0) }
-#define d_4(t,n,b,v) const t n[4][256] = { { b(v##0) }, { b(v##1) }, { b(v##2) }, { b(v##3) } }
-
-#else /* declare and instantiate tables for dynamic value generation in in tab.c */
-
-aes_32t t_dec(r,c)[RC_LENGTH];
-
-#define d_1(t,n,b,v) t n[256]
-#define d_4(t,n,b,v) t n[4][256]
-
-#endif
-
-#else /* declare tables without instantiation */
-
-#if defined(FIXED_TABLES)
-
-extern const aes_32t t_dec(r,c)[RC_LENGTH];
-
-#if defined(_MSC_VER) && defined(TABLE_ALIGN)
-#define d_1(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) const t n[256]
-#define d_4(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) const t n[4][256]
-#else
-#define d_1(t,n,b,v) extern const t n[256]
-#define d_4(t,n,b,v) extern const t n[4][256]
-#endif
-#else
-
-extern aes_32t t_dec(r,c)[RC_LENGTH];
-
-#if defined(_MSC_VER) && defined(TABLE_ALIGN)
-#define d_1(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) t n[256]
-#define d_4(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) t n[4][256]
-#else
-#define d_1(t,n,b,v) extern t n[256]
-#define d_4(t,n,b,v) extern t n[4][256]
-#endif
-#endif
-
-#endif
-
-#ifdef SBX_SET
- d_1(aes_08t, t_dec(s,box), sb_data, h);
-#endif
-#ifdef ISB_SET
- d_1(aes_08t, t_dec(i,box), isb_data, h);
-#endif
-
-#ifdef FT1_SET
- d_1(aes_32t, t_dec(f,n), sb_data, u);
-#endif
-#ifdef FT4_SET
- d_4(aes_32t, t_dec(f,n), sb_data, u);
-#endif
-
-#ifdef FL1_SET
- d_1(aes_32t, t_dec(f,l), sb_data, w);
-#endif
-#ifdef FL4_SET
- d_4(aes_32t, t_dec(f,l), sb_data, w);
-#endif
-
-#ifdef IT1_SET
- d_1(aes_32t, t_dec(i,n), isb_data, v);
-#endif
-#ifdef IT4_SET
- d_4(aes_32t, t_dec(i,n), isb_data, v);
-#endif
-
-#ifdef IL1_SET
- d_1(aes_32t, t_dec(i,l), isb_data, w);
-#endif
-#ifdef IL4_SET
- d_4(aes_32t, t_dec(i,l), isb_data, w);
-#endif
-
-#ifdef LS1_SET
-#ifdef FL1_SET
-#undef LS1_SET
-#else
- d_1(aes_32t, t_dec(l,s), sb_data, w);
-#endif
-#endif
-
-#ifdef LS4_SET
-#ifdef FL4_SET
-#undef LS4_SET
-#else
- d_4(aes_32t, t_dec(l,s), sb_data, w);
-#endif
-#endif
-
-#ifdef IM1_SET
- d_1(aes_32t, t_dec(i,m), mm_data, v);
-#endif
-#ifdef IM4_SET
- d_4(aes_32t, t_dec(i,m), mm_data, v);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif
diff --git a/main/aestab.c b/main/aestab.c
deleted file mode 100644
index c84a480af..000000000
--- a/main/aestab.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- ---------------------------------------------------------------------------
- Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
- All rights reserved.
-
- LICENSE TERMS
-
- The free distribution and use of this software in both source and binary
- form is allowed (with or without changes) provided that:
-
- 1. distributions of this source code include the above copyright
- notice, this list of conditions and the following disclaimer;
-
- 2. distributions in binary form include the above copyright
- notice, this list of conditions and the following disclaimer
- in the documentation and/or other associated materials;
-
- 3. the copyright holder's name is not used to endorse products
- built using this software without specific written permission.
-
- ALTERNATIVELY, provided that this notice is retained in full, this product
- may be distributed under the terms of the GNU General Public License (GPL),
- in which case the provisions of the GPL apply INSTEAD OF those given above.
-
- DISCLAIMER
-
- This software is provided 'as is' with no explicit or implied warranties
- in respect of its properties, including, but not limited to, correctness
- and/or fitness for purpose.
- ---------------------------------------------------------------------------
- Issue Date: 26/08/2003
-
-*/
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-#define DO_TABLES
-
-#include "aesopt.h"
-
-#if defined(FIXED_TABLES)
-
-/* implemented in case of wrong call for fixed tables */
-
-void gen_tabs(void)
-{
-}
-
-#else /* dynamic table generation */
-
-#if !defined(FF_TABLES)
-
-/* Generate the tables for the dynamic table option
-
- It will generally be sensible to use tables to compute finite
- field multiplies and inverses but where memory is scarse this
- code might sometimes be better. But it only has effect during
- initialisation so its pretty unimportant in overall terms.
-*/
-
-/* return 2 ^ (n - 1) where n is the bit number of the highest bit
- set in x with x in the range 1 < x < 0x00000200. This form is
- used so that locals within fi can be bytes rather than words
-*/
-
-static aes_08t hibit(const aes_32t x)
-{ aes_08t r = (aes_08t)((x >> 1) | (x >> 2));
-
- r |= (r >> 2);
- r |= (r >> 4);
- return (r + 1) >> 1;
-}
-
-/* return the inverse of the finite field element x */
-
-static aes_08t fi(const aes_08t x)
-{ aes_08t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
-
- if(x < 2) return x;
-
- for(;;)
- {
- if(!n1) return v1;
-
- while(n2 >= n1)
- {
- n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2);
- }
-
- if(!n2) return v2;
-
- while(n1 >= n2)
- {
- n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1);
- }
- }
-}
-
-#endif
-
-/* The forward and inverse affine transformations used in the S-box */
-
-#define fwd_affine(x) \
- (w = (aes_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(aes_08t)(w^(w>>8)))
-
-#define inv_affine(x) \
- (w = (aes_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(aes_08t)(w^(w>>8)))
-
-static int init = 0;
-
-void gen_tabs(void)
-{ aes_32t i, w;
-
-#if defined(FF_TABLES)
-
- aes_08t pow[512], log[256];
-
- if(init) return;
- /* log and power tables for GF(2^8) finite field with
- WPOLY as modular polynomial - the simplest primitive
- root is 0x03, used here to generate the tables
- */
-
- i = 0; w = 1;
- do
- {
- pow[i] = (aes_08t)w;
- pow[i + 255] = (aes_08t)w;
- log[w] = (aes_08t)i++;
- w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0);
- }
- while (w != 1);
-
-#else
- if(init) return;
-#endif
-
- for(i = 0, w = 1; i < RC_LENGTH; ++i)
- {
- t_set(r,c)[i] = bytes2word(w, 0, 0, 0);
- w = f2(w);
- }
-
- for(i = 0; i < 256; ++i)
- { aes_08t b;
-
- b = fwd_affine(fi((aes_08t)i));
- w = bytes2word(f2(b), b, b, f3(b));
-
-#ifdef SBX_SET
- t_set(s,box)[i] = b;
-#endif
-
-#ifdef FT1_SET /* tables for a normal encryption round */
- t_set(f,n)[i] = w;
-#endif
-#ifdef FT4_SET
- t_set(f,n)[0][i] = w;
- t_set(f,n)[1][i] = upr(w,1);
- t_set(f,n)[2][i] = upr(w,2);
- t_set(f,n)[3][i] = upr(w,3);
-#endif
- w = bytes2word(b, 0, 0, 0);
-
-#ifdef FL1_SET /* tables for last encryption round (may also */
- t_set(f,l)[i] = w; /* be used in the key schedule) */
-#endif
-#ifdef FL4_SET
- t_set(f,l)[0][i] = w;
- t_set(f,l)[1][i] = upr(w,1);
- t_set(f,l)[2][i] = upr(w,2);
- t_set(f,l)[3][i] = upr(w,3);
-#endif
-
-#ifdef LS1_SET /* table for key schedule if t_set(f,l) above is */
- t_set(l,s)[i] = w; /* not of the required form */
-#endif
-#ifdef LS4_SET
- t_set(l,s)[0][i] = w;
- t_set(l,s)[1][i] = upr(w,1);
- t_set(l,s)[2][i] = upr(w,2);
- t_set(l,s)[3][i] = upr(w,3);
-#endif
-
- b = fi(inv_affine((aes_08t)i));
- w = bytes2word(fe(b), f9(b), fd(b), fb(b));
-
-#ifdef IM1_SET /* tables for the inverse mix column operation */
- t_set(i,m)[b] = w;
-#endif
-#ifdef IM4_SET
- t_set(i,m)[0][b] = w;
- t_set(i,m)[1][b] = upr(w,1);
- t_set(i,m)[2][b] = upr(w,2);
- t_set(i,m)[3][b] = upr(w,3);
-#endif
-
-#ifdef ISB_SET
- t_set(i,box)[i] = b;
-#endif
-#ifdef IT1_SET /* tables for a normal decryption round */
- t_set(i,n)[i] = w;
-#endif
-#ifdef IT4_SET
- t_set(i,n)[0][i] = w;
- t_set(i,n)[1][i] = upr(w,1);
- t_set(i,n)[2][i] = upr(w,2);
- t_set(i,n)[3][i] = upr(w,3);
-#endif
- w = bytes2word(b, 0, 0, 0);
-#ifdef IL1_SET /* tables for last decryption round */
- t_set(i,l)[i] = w;
-#endif
-#ifdef IL4_SET
- t_set(i,l)[0][i] = w;
- t_set(i,l)[1][i] = upr(w,1);
- t_set(i,l)[2][i] = upr(w,2);
- t_set(i,l)[3][i] = upr(w,3);
-#endif
- }
- init = 1;
-}
-
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
-
diff --git a/main/alaw.c b/main/alaw.c
deleted file mode 100644
index b94772ea6..000000000
--- a/main/alaw.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief u-Law to Signed linear conversion
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/alaw.h"
-
-#define AMI_MASK 0x55
-
-static inline unsigned char linear2alaw (short int linear)
-{
- int mask;
- int seg;
- int pcm_val;
- static int seg_end[8] =
- {
- 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
- };
-
- pcm_val = linear;
- if (pcm_val >= 0)
- {
- /* Sign (7th) bit = 1 */
- mask = AMI_MASK | 0x80;
- }
- else
- {
- /* Sign bit = 0 */
- mask = AMI_MASK;
- pcm_val = -pcm_val;
- }
-
- /* Convert the scaled magnitude to segment number. */
- for (seg = 0; seg < 8; seg++)
- {
- if (pcm_val <= seg_end[seg])
- break;
- }
- /* Combine the sign, segment, and quantization bits. */
- return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask;
-}
-/*- End of function --------------------------------------------------------*/
-
-static inline short int alaw2linear (unsigned char alaw)
-{
- int i;
- int seg;
-
- alaw ^= AMI_MASK;
- i = ((alaw & 0x0F) << 4) + 8 /* rounding error */;
- seg = (((int) alaw & 0x70) >> 4);
- if (seg)
- i = (i + 0x100) << (seg - 1);
- return (short int) ((alaw & 0x80) ? i : -i);
-}
-
-unsigned char __ast_lin2a[8192];
-short __ast_alaw[256];
-
-void ast_alaw_init(void)
-{
- int i;
- /*
- * Set up mu-law conversion table
- */
- for(i = 0;i < 256;i++)
- {
- __ast_alaw[i] = alaw2linear(i);
- }
- /* set up the reverse (mu-law) conversion table */
- for(i = -32768; i < 32768; i++)
- {
- __ast_lin2a[((unsigned short)i) >> 3] = linear2alaw(i);
- }
-
-}
-
diff --git a/main/app.c b/main/app.c
deleted file mode 100644
index bcecff568..000000000
--- a/main/app.c
+++ /dev/null
@@ -1,1452 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Convenient Application Routines
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <regex.h>
-
-#include "asterisk/channel.h"
-#include "asterisk/pbx.h"
-#include "asterisk/file.h"
-#include "asterisk/app.h"
-#include "asterisk/dsp.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/indications.h"
-#include "asterisk/linkedlists.h"
-
-#define MAX_OTHER_FORMATS 10
-
-static AST_LIST_HEAD_STATIC(groups, ast_group_info);
-
-/* !
-This function presents a dialtone and reads an extension into 'collect'
-which must be a pointer to a **pre-initialized** array of char having a
-size of 'size' suitable for writing to. It will collect no more than the smaller
-of 'maxlen' or 'size' minus the original strlen() of collect digits.
-\return 0 if extension does not exist, 1 if extension exists
-*/
-int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
-{
- struct tone_zone_sound *ts;
- int res=0, x=0;
-
- if (maxlen > size)
- maxlen = size;
-
- if (!timeout && chan->pbx)
- timeout = chan->pbx->dtimeout;
- else if (!timeout)
- timeout = 5;
-
- ts = ast_get_indication_tone(chan->zone,"dial");
- if (ts && ts->data[0])
- res = ast_playtones_start(chan, 0, ts->data, 0);
- else
- ast_log(LOG_NOTICE,"Huh....? no dial for indications?\n");
-
- for (x = strlen(collect); x < maxlen; ) {
- res = ast_waitfordigit(chan, timeout);
- if (!ast_ignore_pattern(context, collect))
- ast_playtones_stop(chan);
- if (res < 1)
- break;
- if (res == '#')
- break;
- collect[x++] = res;
- if (!ast_matchmore_extension(chan, context, collect, 1, chan->cid.cid_num))
- break;
- }
- if (res >= 0)
- res = ast_exists_extension(chan, context, collect, 1, chan->cid.cid_num) ? 1 : 0;
- return res;
-}
-
-/*! \param c The channel to read from
- * \param prompt The file to stream to the channel
- * \param s The string to read in to. Must be at least the size of your length
- * \param maxlen How many digits to read (maximum)
- * \param timeout 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)
- return res;
- }
- fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
- to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
-
- if (timeout > 0)
- fto = to = timeout;
- if (timeout < 0)
- fto = to = 1000000000;
- res = ast_readstring(c, s, maxlen, to, fto, "#");
- return res;
-}
-
-
-int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
-{
- int res, to, fto;
- if (prompt) {
- res = ast_streamfile(c, prompt, c->language);
- if (res < 0)
- return res;
- }
- fto = 6000;
- to = 2000;
- if (timeout > 0)
- fto = to = timeout;
- if (timeout < 0)
- fto = to = 1000000000;
- res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
- return res;
-}
-
-static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL;
-static int (*ast_inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL;
-static int (*ast_messagecount_func)(const char *context, const char *mailbox, const char *folder) = NULL;
-
-void ast_install_vm_functions(int (*has_voicemail_func)(const char *mailbox, const char *folder),
- int (*inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs),
- int (*messagecount_func)(const char *context, const char *mailbox, const char *folder))
-{
- ast_has_voicemail_func = has_voicemail_func;
- ast_inboxcount_func = inboxcount_func;
- ast_messagecount_func = messagecount_func;
-}
-
-void ast_uninstall_vm_functions(void)
-{
- ast_has_voicemail_func = NULL;
- ast_inboxcount_func = NULL;
- ast_messagecount_func = NULL;
-}
-
-int ast_app_has_voicemail(const char *mailbox, const char *folder)
-{
- static int warned = 0;
- if (ast_has_voicemail_func)
- return ast_has_voicemail_func(mailbox, folder);
-
- if ((option_verbose > 2) && !warned) {
- ast_verbose(VERBOSE_PREFIX_3 "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX");
- warned++;
- }
- return 0;
-}
-
-
-int ast_app_inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
-{
- static int warned = 0;
- if (newmsgs)
- *newmsgs = 0;
- if (oldmsgs)
- *oldmsgs = 0;
- if (ast_inboxcount_func)
- return ast_inboxcount_func(mailbox, newmsgs, oldmsgs);
-
- if (!warned && (option_verbose > 2)) {
- warned++;
- ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox);
- }
-
- return 0;
-}
-
-int ast_app_messagecount(const char *context, const char *mailbox, const char *folder)
-{
- static int warned = 0;
- if (ast_messagecount_func)
- return ast_messagecount_func(context, mailbox, folder);
-
- if (!warned && (option_verbose > 2)) {
- warned++;
- ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s@%s/%s but voicemail not loaded.\n", mailbox, context, folder);
- }
-
- return 0;
-}
-
-int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between)
-{
- const char *ptr;
- int res = 0;
- struct ast_silence_generator *silgen = NULL;
-
- if (!between)
- between = 100;
-
- if (peer)
- res = ast_autoservice_start(peer);
-
- if (!res)
- res = ast_waitfor(chan, 100);
-
- /* ast_waitfor will return the number of remaining ms on success */
- if (res < 0) {
- if (peer) {
- ast_autoservice_stop(peer);
- }
- return res;
- }
-
- if (ast_opt_transmit_silence) {
- silgen = ast_channel_start_silence_generator(chan);
- }
-
- for (ptr = digits; *ptr; ptr++) {
- if (*ptr == 'w') {
- /* 'w' -- wait half a second */
- if ((res = ast_safe_sleep(chan, 500)))
- break;
- } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
- /* Character represents valid DTMF */
- if (*ptr == 'f' || *ptr == 'F') {
- /* ignore return values if not supported by channel */
- ast_indicate(chan, AST_CONTROL_FLASH);
- } else
- ast_senddigit(chan, *ptr);
- /* pause between digits */
- if ((res = ast_safe_sleep(chan, between)))
- break;
- } else
- ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
- }
-
- if (peer) {
- /* Stop autoservice on the peer channel, but don't overwrite any error condition
- that has occurred previously while acting on the primary channel */
- if (ast_autoservice_stop(peer) && !res)
- res = -1;
- }
-
- if (silgen) {
- ast_channel_stop_silence_generator(chan, silgen);
- }
-
- 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)
- ast_set_flag(chan, AST_FLAG_WRITE_INT);
- else
- ast_clear_flag(chan, AST_FLAG_WRITE_INT);
- 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 (ast_strlen_zero(filename))
- return -1;
- autoclose = 1;
- if (filename[0] == '/')
- ast_copy_string(tmpf, filename, sizeof(tmpf));
- else
- snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_DATA_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;
- }
- }
- if ((lin = ast_calloc(1, 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, const char *file,
- const char *fwd, const char *rev,
- const char *stop, const char *pause,
- const char *restart, int skipms)
-{
- char *breaks = NULL;
- char *end = NULL;
- int blen = 2;
- int res;
- long pause_restart_point = 0;
-
- if (stop)
- blen += strlen(stop);
- if (pause)
- blen += strlen(pause);
- if (restart)
- blen += strlen(restart);
-
- if (blen > 2) {
- breaks = alloca(blen + 1);
- breaks[0] = '\0';
- if (stop)
- strcat(breaks, stop);
- if (pause)
- strcat(breaks, pause);
- if (restart)
- strcat(breaks, restart);
- }
- if (chan->_state != AST_STATE_UP)
- res = ast_answer(chan);
-
- if (file) {
- if ((end = strchr(file,':'))) {
- if (!strcasecmp(end, ":end")) {
- *end = '\0';
- end++;
- }
- }
- }
-
- for (;;) {
- ast_stopstream(chan);
- res = ast_streamfile(chan, file, chan->language);
- if (!res) {
- if (pause_restart_point) {
- ast_seekstream(chan->stream, pause_restart_point, SEEK_SET);
- pause_restart_point = 0;
- }
- else if (end) {
- ast_seekstream(chan->stream, 0, SEEK_END);
- end = NULL;
- };
- res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
- }
-
- if (res < 1)
- break;
-
- /* We go at next loop if we got the restart char */
- if (restart && strchr(restart, res)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "we'll restart the stream here at next loop\n");
- pause_restart_point = 0;
- continue;
- }
-
- if (pause && strchr(pause, res)) {
- pause_restart_point = ast_tellstream(chan->stream);
- for (;;) {
- ast_stopstream(chan);
- res = ast_waitfordigit(chan, 1000);
- if (!res)
- 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))
- break;
- }
-
- /* If we are returning a digit cast it as char */
- if (res > 0 || chan->stream)
- res = (char)res;
-
- ast_stopstream(chan);
-
- return res;
-}
-
-int ast_play_and_wait(struct ast_channel *chan, const 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;
-
-/*! Optionally play a sound file or a beep, then record audio and video from the channel.
- * @param chan Channel to playback to/record from.
- * @param playfile Filename of sound to play before recording begins.
- * @param recordfile Filename to record to.
- * @param maxtime Maximum length of recording (in milliseconds).
- * @param fmt Format(s) to record message in. Multiple formats may be specified by separating them with a '|'.
- * @param duration Where to store actual length of the recorded message (in milliseconds).
- * @param beep Whether to play a beep before starting to record.
- * @param silencethreshold
- * @param maxsilence Length of silence that will end a recording (in milliseconds).
- * @param path Optional filesystem path to unlock.
- * @param prepend If true, prepend the recorded audio to an existing file.
- * @param acceptdtmf DTMF digits that will end the recording.
- * @param canceldtmf DTMF digits that will cancel the recording.
- */
-
-static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf)
-{
- int d = 0;
- char *fmts;
- char comment[256];
- int x, fmtcnt = 1, res = -1, outmsg = 0;
- 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 rfmt = 0;
- struct ast_silence_generator *silgen = NULL;
- 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_record called without duration pointer\n");
- return -1;
- }
-
- if (option_debug)
- 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 || beep) {
- if (!beep)
- d = ast_play_and_wait(chan, playfile);
- if (d > -1)
- d = ast_stream_and_wait(chan, "beep", chan->language, "");
- if (d < 0)
- return -1;
- }
-
- if (prepend) {
- ast_copy_string(prependfile, recordfile, sizeof(prependfile));
- strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
- }
-
- fmts = ast_strdupa(fmt);
-
- stringp = fmts;
- strsep(&stringp, "|");
- if (option_debug)
- 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.c\n");
- break;
- }
- sfmt[fmtcnt++] = ast_strdupa(fmt);
- }
-
- end = start = time(NULL); /* 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(prepend ? prependfile : recordfile, sfmt[x], comment, O_TRUNC, 0, 0777);
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, prepend ? prependfile : 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 (!prepend) {
- /* Request a video update */
- ast_indicate(chan, AST_CONTROL_VIDUPDATE);
-
- if (ast_opt_transmit_silence)
- silgen = ast_channel_start_silence_generator(chan);
- }
-
- if (x == fmtcnt) {
- /* Loop forever, writing the packets we read to the writer(s), until
- we read a digit or get a hangup */
- struct ast_frame *f;
- for (;;) {
- res = ast_waitfor(chan, 2000);
- if (!res) {
- if (option_debug)
- 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 (prepend && !others[x])
- break;
- res = ast_writestream(others[x], f);
- }
-
- /* Silence Detection */
- if (maxsilence > 0) {
- int 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);
- res = 'S';
- outmsg = 2;
- break;
- }
- }
- /* Exit on any error */
- if (res) {
- ast_log(LOG_WARNING, "Error writing frame\n");
- break;
- }
- } else if (f->frametype == AST_FRAME_VIDEO) {
- /* Write only once */
- ast_writestream(others[0], f);
- } else if (f->frametype == AST_FRAME_DTMF) {
- if (prepend) {
- /* 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;
- break;
- }
- if (strchr(acceptdtmf, f->subclass)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
- res = f->subclass;
- outmsg = 2;
- break;
- }
- if (strchr(canceldtmf, f->subclass)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "User cancelled message by pressing %c\n", f->subclass);
- res = f->subclass;
- outmsg = 0;
- break;
- }
- }
- if (maxtime) {
- end = time(NULL);
- if (maxtime < (end - start)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
- res = 't';
- outmsg = 2;
- break;
- }
- }
- ast_frfree(f);
- }
- if (!f) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "User hung up\n");
- res = -1;
- outmsg = 1;
- } else {
- ast_frfree(f);
- }
- } else {
- ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
- }
-
- if (!prepend) {
- if (silgen)
- ast_channel_stop_silence_generator(chan, silgen);
- }
-
- /*!\note
- * Instead of asking how much time passed (end - start), calculate the number
- * of seconds of audio which actually went into the file. This fixes a
- * problem where audio is stopped up on the network and never gets to us.
- *
- * Note that we still want to use the number of seconds passed for the max
- * message, otherwise we could get a situation where this stream is never
- * closed (which would create a resource leak).
- */
- *duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0;
-
- if (!prepend) {
- for (x = 0; x < fmtcnt; x++) {
- if (!others[x])
- break;
- /*!\note
- * If we ended with silence, trim all but the first 200ms of silence
- * off the recording. However, if we ended with '#', we don't want
- * to trim ANY part of the recording.
- */
- if (res > 0 && totalsilence)
- ast_stream_rewind(others[x], totalsilence - 200);
- ast_truncstream(others[x]);
- ast_closestream(others[x]);
- }
- }
-
- if (prepend && outmsg) {
- struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
- 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;
- /*!\note Same logic as above. */
- if (totalsilence)
- ast_stream_rewind(others[x], totalsilence - 200);
- ast_truncstream(others[x]);
- /* add the original file too */
- while ((fr = ast_readframe(realfiles[x]))) {
- ast_writestream(others[x], fr);
- ast_frfree(fr);
- }
- ast_closestream(others[x]);
- ast_closestream(realfiles[x]);
- ast_filerename(prependfile, recordfile, sfmt[x]);
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_4 "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
- ast_filedelete(prependfile, sfmt[x]);
- }
- }
- if (rfmt && 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 == 2) {
- ast_stream_and_wait(chan, "auth-thankyou", chan->language, "");
- }
- if (sildet)
- ast_dsp_free(sildet);
- return res;
-}
-
-static char default_acceptdtmf[] = "#";
-static char default_canceldtmf[] = "";
-
-int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf)
-{
- return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, default_acceptdtmf), S_OR(canceldtmf, default_canceldtmf));
-}
-
-int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
-{
- return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf);
-}
-
-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)
-{
- return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf);
-}
-
-/* Channel group core functions */
-
-int ast_app_group_split_group(const char *data, char *group, int group_max, char *category, int category_max)
-{
- int res=0;
- char tmp[256];
- char *grp=NULL, *cat=NULL;
-
- if (!ast_strlen_zero(data)) {
- ast_copy_string(tmp, data, sizeof(tmp));
- grp = tmp;
- cat = strchr(tmp, '@');
- if (cat) {
- *cat = '\0';
- cat++;
- }
- }
-
- if (!ast_strlen_zero(grp))
- ast_copy_string(group, grp, group_max);
- else
- *group = '\0';
-
- if (!ast_strlen_zero(cat))
- ast_copy_string(category, cat, category_max);
-
- return res;
-}
-
-int ast_app_group_set_channel(struct ast_channel *chan, const char *data)
-{
- int res = 0;
- char group[80] = "", category[80] = "";
- struct ast_group_info *gi = NULL;
- size_t len = 0;
-
- if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category)))
- return -1;
-
- /* Calculate memory we will need if this is new */
- len = sizeof(*gi) + strlen(group) + 1;
- if (!ast_strlen_zero(category))
- len += strlen(category) + 1;
-
- AST_LIST_LOCK(&groups);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
- if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
- AST_LIST_REMOVE_CURRENT(&groups, list);
- free(gi);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- if (ast_strlen_zero(group)) {
- /* Enable unsetting the group */
- } else if ((gi = calloc(1, len))) {
- gi->chan = chan;
- gi->group = (char *) gi + sizeof(*gi);
- strcpy(gi->group, group);
- if (!ast_strlen_zero(category)) {
- gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1;
- strcpy(gi->category, category);
- }
- AST_LIST_INSERT_TAIL(&groups, gi, list);
- } else {
- res = -1;
- }
-
- AST_LIST_UNLOCK(&groups);
-
- return res;
-}
-
-int ast_app_group_get_count(const char *group, const char *category)
-{
- struct ast_group_info *gi = NULL;
- int count = 0;
-
- if (ast_strlen_zero(group))
- return 0;
-
- AST_LIST_LOCK(&groups);
- AST_LIST_TRAVERSE(&groups, gi, list) {
- if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category))))
- count++;
- }
- AST_LIST_UNLOCK(&groups);
-
- return count;
-}
-
-int ast_app_group_match_get_count(const char *groupmatch, const char *category)
-{
- struct ast_group_info *gi = NULL;
- regex_t regexbuf;
- int count = 0;
-
- if (ast_strlen_zero(groupmatch))
- return 0;
-
- /* if regex compilation fails, return zero matches */
- if (regcomp(&regexbuf, groupmatch, REG_EXTENDED | REG_NOSUB))
- return 0;
-
- AST_LIST_LOCK(&groups);
- AST_LIST_TRAVERSE(&groups, gi, list) {
- if (!regexec(&regexbuf, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category))))
- count++;
- }
- AST_LIST_UNLOCK(&groups);
-
- regfree(&regexbuf);
-
- return count;
-}
-
-int ast_app_group_update(struct ast_channel *old, struct ast_channel *new)
-{
- struct ast_group_info *gi = NULL;
-
- AST_LIST_LOCK(&groups);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
- if (gi->chan == old) {
- gi->chan = new;
- } else if (gi->chan == new) {
- AST_LIST_REMOVE_CURRENT(&groups, list);
- free(gi);
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&groups);
-
- return 0;
-}
-
-int ast_app_group_discard(struct ast_channel *chan)
-{
- struct ast_group_info *gi = NULL;
-
- AST_LIST_LOCK(&groups);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
- if (gi->chan == chan) {
- AST_LIST_REMOVE_CURRENT(&groups, list);
- free(gi);
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&groups);
-
- return 0;
-}
-
-int ast_app_group_list_lock(void)
-{
- return AST_LIST_LOCK(&groups);
-}
-
-struct ast_group_info *ast_app_group_list_head(void)
-{
- return AST_LIST_FIRST(&groups);
-}
-
-int ast_app_group_list_unlock(void)
-{
- return AST_LIST_UNLOCK(&groups);
-}
-
-unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen)
-{
- int argc;
- char *scan, *wasdelim = NULL;
- int paren = 0, quote = 0;
-
- if (!buf || !array || !arraylen)
- return 0;
-
- memset(array, 0, arraylen * sizeof(*array));
-
- scan = buf;
-
- for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
- array[argc] = scan;
- for (; *scan; scan++) {
- if (*scan == '(')
- paren++;
- else if (*scan == ')') {
- if (paren)
- paren--;
- } else if (*scan == '"' && delim != '"') {
- quote = quote ? 0 : 1;
- /* Remove quote character from argument */
- memmove(scan, scan + 1, strlen(scan));
- scan--;
- } else if (*scan == '\\') {
- /* Literal character, don't parse */
- memmove(scan, scan + 1, strlen(scan));
- } else if ((*scan == delim) && !paren && !quote) {
- wasdelim = scan;
- *scan++ = '\0';
- break;
- }
- }
- }
-
- /* If the last character in the original string was the delimiter, then
- * there is one additional argument. */
- if (*scan || (scan > buf && (scan - 1) == wasdelim)) {
- array[argc++] = scan;
- }
-
- return argc;
-}
-
-enum AST_LOCK_RESULT ast_lock_path(const char *path)
-{
- char *s;
- char *fs;
- int res;
- int fd;
- int lp = strlen(path);
- time_t start;
-
- if (!(s = alloca(lp + 10)) || !(fs = alloca(lp + 20))) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- return AST_LOCK_FAILURE;
- }
-
- snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, ast_random());
- fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
- if (fd < 0) {
- ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
- return AST_LOCK_PATH_NOT_FOUND;
- }
- close(fd);
-
- snprintf(s, strlen(path) + 9, "%s/.lock", path);
- start = time(NULL);
- while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
- usleep(1);
-
- unlink(fs);
-
- if (res) {
- ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
- return AST_LOCK_TIMEOUT;
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
- return AST_LOCK_SUCCESS;
- }
-}
-
-int ast_unlock_path(const char *path)
-{
- char *s;
- int res;
-
- if (!(s = alloca(strlen(path) + 10))) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- return -1;
- }
-
- snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
-
- if ((res = unlink(s)))
- ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
- else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
- }
-
- return res;
-}
-
-int ast_record_review(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
-{
- int silencethreshold = 128;
- int maxsilence=0;
- int res = 0;
- int cmd = 0;
- int max_attempts = 3;
- int attempts = 0;
- int recorded = 0;
- int message_exists = 0;
- /* Note that urgent and private are for flagging messages as such in the future */
-
- /* barf if no pointer passed to store duration in */
- if (duration == NULL) {
- ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
- return -1;
- }
-
- cmd = '3'; /* Want to start by recording */
-
- while ((cmd >= 0) && (cmd != 't')) {
- switch (cmd) {
- case '1':
- if (!message_exists) {
- /* In this case, 1 is to record a message */
- cmd = '3';
- break;
- } else {
- ast_stream_and_wait(chan, "vm-msgsaved", chan->language, "");
- cmd = 't';
- return res;
- }
- case '2':
- /* Review */
- ast_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n");
- cmd = ast_stream_and_wait(chan, recordfile, chan->language, AST_DIGIT_ANY);
- break;
- case '3':
- message_exists = 0;
- /* Record */
- if (recorded == 1)
- ast_verbose(VERBOSE_PREFIX_3 "Re-recording\n");
- else
- ast_verbose(VERBOSE_PREFIX_3 "Recording\n");
- recorded = 1;
- cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path);
- if (cmd == -1) {
- /* User has hung up, no options to give */
- return cmd;
- }
- if (cmd == '0') {
- break;
- } else if (cmd == '*') {
- break;
- }
- else {
- /* If all is well, a message exists */
- message_exists = 1;
- cmd = 0;
- }
- break;
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '*':
- case '#':
- cmd = ast_play_and_wait(chan, "vm-sorry");
- break;
- default:
- if (message_exists) {
- cmd = ast_play_and_wait(chan, "vm-review");
- }
- else {
- cmd = ast_play_and_wait(chan, "vm-torerecord");
- if (!cmd)
- cmd = ast_waitfordigit(chan, 600);
- }
-
- if (!cmd)
- cmd = ast_waitfordigit(chan, 6000);
- if (!cmd) {
- attempts++;
- }
- if (attempts > max_attempts) {
- cmd = 't';
- }
- }
- }
- if (cmd == 't')
- cmd = 0;
- return cmd;
-}
-
-#define RES_UPONE (1 << 16)
-#define RES_EXIT (1 << 17)
-#define RES_REPEAT (1 << 18)
-#define RES_RESTART ((1 << 19) | RES_REPEAT)
-
-static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata);
-
-static int ivr_dispatch(struct ast_channel *chan, struct ast_ivr_option *option, char *exten, void *cbdata)
-{
- int res;
- int (*ivr_func)(struct ast_channel *, void *);
- char *c;
- char *n;
-
- switch(option->action) {
- case AST_ACTION_UPONE:
- return RES_UPONE;
- case AST_ACTION_EXIT:
- return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
- case AST_ACTION_REPEAT:
- return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
- case AST_ACTION_RESTART:
- return RES_RESTART ;
- case AST_ACTION_NOOP:
- return 0;
- case AST_ACTION_BACKGROUND:
- res = ast_stream_and_wait(chan, (char *)option->adata, chan->language, AST_DIGIT_ANY);
- if (res < 0) {
- ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
- res = 0;
- }
- return res;
- case AST_ACTION_PLAYBACK:
- res = ast_stream_and_wait(chan, (char *)option->adata, chan->language, "");
- if (res < 0) {
- ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
- res = 0;
- }
- return res;
- case AST_ACTION_MENU:
- res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata);
- /* Do not pass entry errors back up, treaat ast though ti was an "UPONE" */
- if (res == -2)
- res = 0;
- return res;
- case AST_ACTION_WAITOPTION:
- res = ast_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10));
- if (!res)
- return 't';
- return res;
- case AST_ACTION_CALLBACK:
- ivr_func = option->adata;
- res = ivr_func(chan, cbdata);
- return res;
- case AST_ACTION_TRANSFER:
- res = ast_parseable_goto(chan, option->adata);
- return 0;
- case AST_ACTION_PLAYLIST:
- case AST_ACTION_BACKLIST:
- res = 0;
- c = ast_strdupa(option->adata);
- while ((n = strsep(&c, ";"))) {
- if ((res = ast_stream_and_wait(chan, n, chan->language,
- (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : "")))
- break;
- }
- ast_stopstream(chan);
- return res;
- default:
- ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action);
- return 0;
- };
- return -1;
-}
-
-static int option_exists(struct ast_ivr_menu *menu, char *option)
-{
- int x;
- for (x = 0; menu->options[x].option; x++)
- if (!strcasecmp(menu->options[x].option, option))
- return x;
- return -1;
-}
-
-static int option_matchmore(struct ast_ivr_menu *menu, char *option)
-{
- int x;
- for (x = 0; menu->options[x].option; x++)
- if ((!strncasecmp(menu->options[x].option, option, strlen(option))) &&
- (menu->options[x].option[strlen(option)]))
- return x;
- return -1;
-}
-
-static int read_newoption(struct ast_channel *chan, struct ast_ivr_menu *menu, char *exten, int maxexten)
-{
- int res=0;
- int ms;
- while (option_matchmore(menu, exten)) {
- ms = chan->pbx ? chan->pbx->dtimeout : 5000;
- if (strlen(exten) >= maxexten - 1)
- break;
- res = ast_waitfordigit(chan, ms);
- if (res < 1)
- break;
- exten[strlen(exten) + 1] = '\0';
- exten[strlen(exten)] = res;
- }
- return res > 0 ? 0 : res;
-}
-
-static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
-{
- /* Execute an IVR menu structure */
- int res=0;
- int pos = 0;
- int retries = 0;
- char exten[AST_MAX_EXTENSION] = "s";
- if (option_exists(menu, "s") < 0) {
- strcpy(exten, "g");
- if (option_exists(menu, "g") < 0) {
- ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
- return -1;
- }
- }
- while(!res) {
- while(menu->options[pos].option) {
- if (!strcasecmp(menu->options[pos].option, exten)) {
- res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
- if (option_debug)
- ast_log(LOG_DEBUG, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
- if (res < 0)
- break;
- else if (res & RES_UPONE)
- return 0;
- else if (res & RES_EXIT)
- return res;
- else if (res & RES_REPEAT) {
- int maxretries = res & 0xffff;
- if ((res & RES_RESTART) == RES_RESTART) {
- retries = 0;
- } else
- retries++;
- if (!maxretries)
- maxretries = 3;
- if ((maxretries > 0) && (retries >= maxretries)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Max retries %d exceeded\n", maxretries);
- return -2;
- } else {
- if (option_exists(menu, "g") > -1)
- strcpy(exten, "g");
- else if (option_exists(menu, "s") > -1)
- strcpy(exten, "s");
- }
- pos = 0;
- continue;
- } else if (res && strchr(AST_DIGIT_ANY, res)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Got start of extension, %c\n", res);
- exten[1] = '\0';
- exten[0] = res;
- if ((res = read_newoption(chan, menu, exten, sizeof(exten))))
- break;
- if (option_exists(menu, exten) < 0) {
- if (option_exists(menu, "i")) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Invalid extension entered, going to 'i'!\n");
- strcpy(exten, "i");
- pos = 0;
- continue;
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Aborting on invalid entry, with no 'i' option!\n");
- res = -2;
- break;
- }
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "New existing extension: %s\n", exten);
- pos = 0;
- continue;
- }
- }
- }
- pos++;
- }
- if (option_debug)
- ast_log(LOG_DEBUG, "Stopping option '%s', res is %d\n", exten, res);
- pos = 0;
- if (!strcasecmp(exten, "s"))
- strcpy(exten, "g");
- else
- break;
- }
- return res;
-}
-
-int ast_ivr_menu_run(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
-{
- int res = ast_ivr_menu_run_internal(chan, menu, cbdata);
- /* Hide internal coding */
- return res > 0 ? 0 : res;
-}
-
-char *ast_read_textfile(const char *filename)
-{
- int fd;
- char *output = NULL;
- struct stat filesize;
- int count = 0;
- int res;
- if (stat(filename, &filesize) == -1) {
- ast_log(LOG_WARNING, "Error can't stat %s\n", filename);
- return NULL;
- }
- count = filesize.st_size + 1;
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
- return NULL;
- }
- if ((output = ast_malloc(count))) {
- res = read(fd, output, count - 1);
- if (res == count - 1) {
- output[res] = '\0';
- } else {
- ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno));
- free(output);
- output = NULL;
- }
- }
- close(fd);
- return output;
-}
-
-void ast_app_options2str(const struct ast_app_option *options, struct ast_flags *flags, char *buf, size_t len)
-{
- unsigned int i, found = 0;
-
- for (i = 32; i < 128 && found < len;i++) {
- if (ast_test_flag(flags, options[i].flag)) {
- buf[found++] = i;
- }
- }
- buf[found] = '\0';
-}
-
-int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
-{
- char *s;
- int curarg;
- unsigned int argloc;
- char *arg;
- int res = 0;
-
- ast_clear_flag(flags, AST_FLAGS_ALL);
-
- if (!optstr)
- return 0;
-
- s = optstr;
- while (*s) {
- curarg = *s++ & 0x7f; /* the array (in app.h) has 128 entries */
- argloc = options[curarg].arg_index;
- if (*s == '(') {
- /* Has argument */
- arg = ++s;
- if ((s = strchr(s, ')'))) {
- if (argloc)
- args[argloc - 1] = arg;
- *s++ = '\0';
- } else {
- ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
- res = -1;
- break;
- }
- } else if (argloc) {
- args[argloc - 1] = "";
- }
- ast_set_flag(flags, options[curarg].flag);
- }
-
- return res;
-}
-
diff --git a/main/ast_expr2.c b/main/ast_expr2.c
deleted file mode 100644
index 66a680b56..000000000
--- a/main/ast_expr2.c
+++ /dev/null
@@ -1,2859 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.1a. */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
- simplifying the original so-called "semantic" parser. */
-
-/* All symbols defined below should begin with yy or YY, to avoid
- infringing on user name space. This should be done even for local
- variables, as they might otherwise be expanded by user macros.
- There are some unavoidable exceptions within include files to
- define necessary library symbols; they are noted "INFRINGES ON
- USER NAME SPACE" below. */
-
-/* Identify Bison output. */
-#define YYBISON 1
-
-/* Bison version. */
-#define YYBISON_VERSION "2.1a"
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 1
-
-/* Using locations. */
-#define YYLSP_NEEDED 1
-
-/* Substitute the variable and function names. */
-#define yyparse ast_yyparse
-#define yylex ast_yylex
-#define yyerror ast_yyerror
-#define yylval ast_yylval
-#define yychar ast_yychar
-#define yydebug ast_yydebug
-#define yynerrs ast_yynerrs
-#define yylloc ast_yylloc
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- TOK_COLONCOLON = 258,
- TOK_COND = 259,
- TOK_OR = 260,
- TOK_AND = 261,
- TOK_NE = 262,
- TOK_LE = 263,
- TOK_GE = 264,
- TOK_LT = 265,
- TOK_GT = 266,
- TOK_EQ = 267,
- TOK_MINUS = 268,
- TOK_PLUS = 269,
- TOK_MOD = 270,
- TOK_DIV = 271,
- TOK_MULT = 272,
- TOK_COMPL = 273,
- TOK_EQTILDE = 274,
- TOK_COLON = 275,
- TOK_LP = 276,
- TOK_RP = 277,
- TOKEN = 278
- };
-#endif
-/* Tokens. */
-#define TOK_COLONCOLON 258
-#define TOK_COND 259
-#define TOK_OR 260
-#define TOK_AND 261
-#define TOK_NE 262
-#define TOK_LE 263
-#define TOK_GE 264
-#define TOK_LT 265
-#define TOK_GT 266
-#define TOK_EQ 267
-#define TOK_MINUS 268
-#define TOK_PLUS 269
-#define TOK_MOD 270
-#define TOK_DIV 271
-#define TOK_MULT 272
-#define TOK_COMPL 273
-#define TOK_EQTILDE 274
-#define TOK_COLON 275
-#define TOK_LP 276
-#define TOK_RP 277
-#define TOKEN 278
-
-
-
-
-/* Copy the first part of user declarations. */
-#line 1 "ast_expr2.y"
-
-/* Written by Pace Willisson (pace@blitz.com)
- * and placed in the public domain.
- *
- * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
- *
- * And then overhauled twice by Steve Murphy (murf@digium.com)
- * to add double-quoted strings, allow mult. spaces, improve
- * error messages, and then to fold in a flex scanner for the
- * yylex operation.
- *
- * $FreeBSD: src/bin/expr/expr.y,v 1.16 2000/07/22 10:59:36 se Exp $
- */
-
-#include "asterisk.h"
-
-#if !defined(STANDALONE_AEL)
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#endif
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <locale.h>
-#include <unistd.h>
-#include <ctype.h>
-#if !defined(SOLARIS) && !defined(__CYGWIN__)
-/* #include <err.h> */
-#else
-#define quad_t int64_t
-#endif
-#include <errno.h>
-#include <regex.h>
-#include <limits.h>
-
-#include "asterisk/ast_expr.h"
-#include "asterisk/logger.h"
-
-#if defined(LONG_LONG_MIN) && !defined(QUAD_MIN)
-#define QUAD_MIN LONG_LONG_MIN
-#endif
-#if defined(LONG_LONG_MAX) && !defined(QUAD_MAX)
-#define QUAD_MAX LONG_LONG_MAX
-#endif
-
-# if ! defined(QUAD_MIN)
-# define QUAD_MIN (-0x7fffffffffffffffLL-1)
-# endif
-# if ! defined(QUAD_MAX)
-# define QUAD_MAX (0x7fffffffffffffffLL)
-# endif
-
-#define YYPARSE_PARAM parseio
-#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
-#define YYERROR_VERBOSE 1
-extern char extra_error_message[4095];
-extern int extra_error_message_supplied;
-
-enum valtype {
- AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
-} ;
-
-#ifdef STANDALONE
-void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__((format(printf,5,6)));
-#endif
-
-struct val {
- enum valtype type;
- union {
- char *s;
- quad_t i;
- } u;
-} ;
-
-typedef void *yyscan_t;
-
-struct parse_io
-{
- char *string;
- struct val *val;
- yyscan_t scanner;
-};
-
-static int chk_div __P((quad_t, quad_t));
-static int chk_minus __P((quad_t, quad_t, quad_t));
-static int chk_plus __P((quad_t, quad_t, quad_t));
-static int chk_times __P((quad_t, quad_t, quad_t));
-static void free_value __P((struct val *));
-static int is_zero_or_null __P((struct val *));
-static int isstring __P((struct val *));
-static struct val *make_integer __P((quad_t));
-static struct val *make_str __P((const char *));
-static struct val *op_and __P((struct val *, struct val *));
-static struct val *op_colon __P((struct val *, struct val *));
-static struct val *op_eqtilde __P((struct val *, struct val *));
-static struct val *op_div __P((struct val *, struct val *));
-static struct val *op_eq __P((struct val *, struct val *));
-static struct val *op_ge __P((struct val *, struct val *));
-static struct val *op_gt __P((struct val *, struct val *));
-static struct val *op_le __P((struct val *, struct val *));
-static struct val *op_lt __P((struct val *, struct val *));
-static struct val *op_cond __P((struct val *, struct val *, struct val *));
-static struct val *op_minus __P((struct val *, struct val *));
-static struct val *op_negate __P((struct val *));
-static struct val *op_compl __P((struct val *));
-static struct val *op_ne __P((struct val *, struct val *));
-static struct val *op_or __P((struct val *, struct val *));
-static struct val *op_plus __P((struct val *, struct val *));
-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
-
-/* we will get warning about no prototype for yylex! But we can't
- define it here, we have no definition yet for YYSTYPE. */
-
-int ast_yyerror(const char *,YYLTYPE *, struct parse_io *);
-
-/* I wanted to add args to the yyerror routine, so I could print out
- some useful info about the error. Not as easy as it looks, but it
- is possible. */
-#define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio)
-#define DESTROY(x) {if((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) free((x)->u.s); (x)->u.s = 0; free(x);}
-
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 147 "ast_expr2.y"
-{
- struct val *val;
-}
-/* Line 198 of yacc.c. */
-#line 283 "ast_expr2.c"
- YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
-{
- int first_line;
- int first_column;
- int last_line;
- int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-
-/* Copy the second part of user declarations. */
-#line 151 "ast_expr2.y"
-
-extern int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
-
-
-/* Line 221 of yacc.c. */
-#line 311 "ast_expr2.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-# define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# else
-# define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if YYENABLE_NLS
-# if ENABLE_NLS
-# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
-# endif
-# endif
-# ifndef YY_
-# define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E. */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
- int i;
-#endif
-{
- return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# elif defined __BUILTIN_VA_ARG_INCR
-# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-# elif defined _AIX
-# define YYSTACK_ALLOC __alloca
-# elif defined _MSC_VER
-# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-# define alloca _alloca
-# else
-# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
-# endif
-# endif
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-# ifndef YYSTACK_ALLOC_MAXIMUM
- /* The OS might guarantee only one guard page at the bottom of the stack,
- and a page size can be as small as 4096 bytes. So we cannot safely
- invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
- to allow for a few compiler-allocated temporary stack slots. */
-# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-# endif
-# else
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# ifndef YYSTACK_ALLOC_MAXIMUM
-# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-# endif
-# ifdef __cplusplus
-extern "C" {
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# ifndef YYFREE
-# define YYFREE free
-# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# ifdef __cplusplus
-}
-# endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
- && (! defined __cplusplus \
- || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
- && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member. */
-union yyalloc
-{
- yytype_int16 yyss;
- YYSTYPE yyvs;
- YYLTYPE yyls;
-};
-
-/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
- N elements. */
-# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
- + 2 * YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
-
-/* Relocate STACK from its old location to the new one. The
- local variables YYSIZE and YYSTACKSIZE give the old and new number of
- elements in the stack, and YYPTR gives the new location of the
- stack. Advance YYPTR to a properly aligned location for the next
- stack. */
-# define YYSTACK_RELOCATE(Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 10
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 140
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 24
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 3
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 23
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 46
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
-#define YYUNDEFTOK 2
-#define YYMAXUTOK 278
-
-#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const yytype_uint8 yytranslate[] =
-{
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint8 yyprhs[] =
-{
- 0, 0, 3, 5, 6, 8, 12, 16, 20, 24,
- 28, 32, 36, 40, 44, 48, 52, 55, 58, 62,
- 66, 70, 74, 78
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int8 yyrhs[] =
-{
- 25, 0, -1, 26, -1, -1, 23, -1, 21, 26,
- 22, -1, 26, 5, 26, -1, 26, 6, 26, -1,
- 26, 12, 26, -1, 26, 11, 26, -1, 26, 10,
- 26, -1, 26, 9, 26, -1, 26, 8, 26, -1,
- 26, 7, 26, -1, 26, 14, 26, -1, 26, 13,
- 26, -1, 13, 26, -1, 18, 26, -1, 26, 17,
- 26, -1, 26, 16, 26, -1, 26, 15, 26, -1,
- 26, 20, 26, -1, 26, 19, 26, -1, 26, 4,
- 26, 3, 26, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const yytype_uint16 yyrline[] =
-{
- 0, 175, 175, 183, 190, 191, 195, 199, 203, 207,
- 211, 215, 219, 223, 227, 231, 235, 239, 243, 247,
- 251, 255, 259, 263
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
- "$end", "error", "$undefined", "TOK_COLONCOLON", "TOK_COND", "TOK_OR",
- "TOK_AND", "TOK_NE", "TOK_LE", "TOK_GE", "TOK_LT", "TOK_GT", "TOK_EQ",
- "TOK_MINUS", "TOK_PLUS", "TOK_MOD", "TOK_DIV", "TOK_MULT", "TOK_COMPL",
- "TOK_EQTILDE", "TOK_COLON", "TOK_LP", "TOK_RP", "TOKEN", "$accept",
- "start", "expr", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const yytype_uint16 yytoknum[] =
-{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
- 275, 276, 277, 278
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
-{
- 0, 24, 25, 25, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
-{
- 0, 2, 1, 0, 1, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 2, 2, 3, 3,
- 3, 3, 3, 5
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const yytype_uint8 yydefact[] =
-{
- 3, 0, 0, 0, 4, 0, 2, 16, 17, 0,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 5, 0, 6,
- 7, 13, 12, 11, 10, 9, 8, 15, 14, 20,
- 19, 18, 22, 21, 0, 23
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int8 yydefgoto[] =
-{
- -1, 5, 6
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -13
-static const yytype_int8 yypact[] =
-{
- 109, 109, 109, 109, -13, 6, 59, 106, 106, 22,
- -13, 109, 109, 109, 109, 109, 109, 109, 109, 109,
- 109, 109, 109, 109, 109, 109, 109, -13, 42, 90,
- 104, 120, 120, 120, 120, 120, 120, -12, -12, 106,
- 106, 106, -13, -13, 109, 75
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int8 yypgoto[] =
-{
- -13, -13, -1
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -1
-static const yytype_uint8 yytable[] =
-{
- 7, 8, 9, 22, 23, 24, 10, 25, 26, 0,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 0, 25, 26, 45, 27, 44, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 0, 25, 26, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 0, 25, 26,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 0, 25, 26, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 0, 25,
- 26, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 1, 25, 26, 25, 26, 2, 0, 0,
- 3, 0, 4, 20, 21, 22, 23, 24, 0, 25,
- 26
-};
-
-static const yytype_int8 yycheck[] =
-{
- 1, 2, 3, 15, 16, 17, 0, 19, 20, -1,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- -1, 19, 20, 44, 22, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- -1, 19, 20, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, -1, 19, 20,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, -1, 19, 20, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, -1, 19,
- 20, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 13, 19, 20, 19, 20, 18, -1, -1,
- 21, -1, 23, 13, 14, 15, 16, 17, -1, 19,
- 20
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
-{
- 0, 13, 18, 21, 23, 25, 26, 26, 26, 26,
- 0, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 19, 20, 22, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 3, 26
-};
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
-
-#define YYFAIL goto yyerrlab
-
-#define YYRECOVERING() (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK (1); \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (YYID (0))
-
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
- This macro was not mandated originally: define only if we know
- we won't break user code: when these are the locations we know. */
-
-#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
-# define YY_LOCATION_PRINT(File, Loc) \
- fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
-# else
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval, &yylloc)
-#endif
-
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-# define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Type, Value, Location); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, const YYSTYPE * const yyvaluep, const YYLTYPE * const yylocationp)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
- FILE *yyoutput;
- int yytype;
- const YYSTYPE * const yyvaluep;
- const YYLTYPE * const yylocationp;
-#endif
-{
- if (!yyvaluep)
- return;
- YYUSE (yylocationp);
-# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
-# endif
- switch (yytype)
- {
- default:
- break;
- }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, const YYSTYPE * const yyvaluep, const YYLTYPE * const yylocationp)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
- FILE *yyoutput;
- int yytype;
- const YYSTYPE * const yyvaluep;
- const YYLTYPE * const yylocationp;
-#endif
-{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
- YY_LOCATION_PRINT (yyoutput, *yylocationp);
- YYFPRINTF (yyoutput, ": ");
- yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp);
- YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
- yytype_int16 *bottom;
- yytype_int16 *top;
-#endif
-{
- YYFPRINTF (stderr, "Stack now");
- for (; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
- YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yylsp, yyrule
- )
- YYSTYPE *yyvsp;
- YYLTYPE *yylsp;
- int yyrule;
-#endif
-{
- int yynrhs = yyr2[yyrule];
- int yyi;
- unsigned long int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
- yyrule - 1, yylno);
- /* The symbols being reduced. */
- for (yyi = 0; yyi < yynrhs; yyi++)
- {
- fprintf (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &(yyvsp[(yyi + 1) - (yynrhs)])
- , &(yylsp[(yyi + 1) - (yynrhs)]) );
- fprintf (stderr, "\n");
- }
-}
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyvsp, yylsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
-
- Do not make this value too large; the results are undefined if
- YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
-/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
-{
- YYSIZE_T yylen;
- for (yylen = 0; yystr[yylen]; yylen++)
- continue;
- return yylen;
-}
-# endif
-# endif
-
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
- YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
-{
- char *yyd = yydest;
- const char *yys = yysrc;
-
- while ((*yyd++ = *yys++) != '\0')
- continue;
-
- return yyd - 1;
-}
-# endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
- quotes and backslashes, so that it's suitable for yyerror. The
- heuristic is that double-quoting is unnecessary unless the string
- contains an apostrophe, a comma, or backslash (other than
- backslash-backslash). YYSTR is taken from yytname. If YYRES is
- null, do not copy; instead, return the length of what the result
- would have been. */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
- if (*yystr == '"')
- {
- size_t yyn = 0;
- char const *yyp = yystr;
-
- for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
- do_not_strip_quotes: ;
- }
-
- if (! yyres)
- return yystrlen (yystr);
-
- return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
- YYCHAR while in state YYSTATE. Return the number of bytes copied,
- including the terminating null byte. If YYRESULT is null, do not
- copy anything; just return the number of bytes that would be
- copied. As a special case, return 0 if an ordinary "syntax error"
- message will do. Return YYSIZE_MAXIMUM if overflow occurs during
- size calculation. */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
- int yyn = yypact[yystate];
-
- if (! (YYPACT_NINF < yyn && yyn < YYLAST))
- return 0;
- else
- {
- int yytype = YYTRANSLATE (yychar);
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- int yysize_overflow = 0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- int yyx;
-
-# if 0
- /* This is so xgettext sees the translatable formats that are
- constructed on the fly. */
- YY_("syntax error, unexpected %s");
- YY_("syntax error, unexpected %s, expecting %s");
- YY_("syntax error, unexpected %s, expecting %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
- char *yyfmt;
- char const *yyf;
- static char const yyunexpected[] = "syntax error, unexpected %s";
- static char const yyexpecting[] = ", expecting %s";
- static char const yyor[] = " or %s";
- char yyformat[sizeof yyunexpected
- + sizeof yyexpecting - 1
- + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
- * (sizeof yyor - 1))];
- char const *yyprefix = yyexpecting;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 1;
-
- yyarg[0] = yytname[yytype];
- yyfmt = yystpcpy (yyformat, yyunexpected);
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- yyformat[sizeof yyunexpected - 1] = '\0';
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
- yyfmt = yystpcpy (yyfmt, yyprefix);
- yyprefix = yyor;
- }
-
- yyf = YY_(yyformat);
- yysize1 = yysize + yystrlen (yyf);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
-
- if (yysize_overflow)
- return YYSIZE_MAXIMUM;
-
- if (yyresult)
- {
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- char *yyp = yyresult;
- int yyi = 0;
- while ((*yyp = *yyf) != '\0')
- {
- if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyf += 2;
- }
- else
- {
- yyp++;
- yyf++;
- }
- }
- }
- return yysize;
- }
-}
-#endif /* YYERROR_VERBOSE */
-
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, yylocationp)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
- YYLTYPE *yylocationp;
-#endif
-{
- YYUSE (yyvaluep);
- YYUSE (yylocationp);
-
- if (!yymsg)
- yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
- switch (yytype)
- {
- case 3: /* "TOK_COLONCOLON" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1257 "ast_expr2.c"
- break;
- case 4: /* "TOK_COND" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1262 "ast_expr2.c"
- break;
- case 5: /* "TOK_OR" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1267 "ast_expr2.c"
- break;
- case 6: /* "TOK_AND" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1272 "ast_expr2.c"
- break;
- case 7: /* "TOK_NE" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1277 "ast_expr2.c"
- break;
- case 8: /* "TOK_LE" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1282 "ast_expr2.c"
- break;
- case 9: /* "TOK_GE" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1287 "ast_expr2.c"
- break;
- case 10: /* "TOK_LT" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1292 "ast_expr2.c"
- break;
- case 11: /* "TOK_GT" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1297 "ast_expr2.c"
- break;
- case 12: /* "TOK_EQ" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1302 "ast_expr2.c"
- break;
- case 13: /* "TOK_MINUS" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1307 "ast_expr2.c"
- break;
- case 14: /* "TOK_PLUS" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1312 "ast_expr2.c"
- break;
- case 15: /* "TOK_MOD" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1317 "ast_expr2.c"
- break;
- case 16: /* "TOK_DIV" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1322 "ast_expr2.c"
- break;
- case 17: /* "TOK_MULT" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1327 "ast_expr2.c"
- break;
- case 18: /* "TOK_COMPL" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1332 "ast_expr2.c"
- break;
- case 19: /* "TOK_EQTILDE" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1337 "ast_expr2.c"
- break;
- case 20: /* "TOK_COLON" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1342 "ast_expr2.c"
- break;
- case 21: /* "TOK_LP" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1347 "ast_expr2.c"
- break;
- case 22: /* "TOK_RP" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1352 "ast_expr2.c"
- break;
- case 23: /* "TOKEN" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1357 "ast_expr2.c"
- break;
- case 26: /* "expr" */
-#line 169 "ast_expr2.y"
- { free_value((yyvaluep->val)); };
-#line 1362 "ast_expr2.c"
- break;
-
- default:
- break;
- }
-}
-
-
-/* Prevent warnings from -Wmissing-prototypes. */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-
-
-
-/*----------.
-| yyparse. |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
- /* The look-ahead symbol. */
-int yychar;
-
-/* The semantic value of the look-ahead symbol. */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far. */
-int yynerrs;
-/* Location data for the look-ahead symbol. */
-YYLTYPE yylloc;
-
- int yystate;
- int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Look-ahead token as an internal (translated) token number. */
- int yytoken = 0;
-#if YYERROR_VERBOSE
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
-
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss = yyssa;
- yytype_int16 *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp;
-
- /* The location stack. */
- YYLTYPE yylsa[YYINITDEPTH];
- YYLTYPE *yyls = yylsa;
- YYLTYPE *yylsp;
- /* The locations where the error started and ended. */
- YYLTYPE yyerror_range[2];
-
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
-
- YYSIZE_T yystacksize = YYINITDEPTH;
-
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
- YYLTYPE yyloc;
-
- /* The number of symbols on the RHS of the reduced rule.
- Keep to zero when no symbol should be popped. */
- int yylen = 0;
-
- YYDPRINTF ((stderr, "Starting parse\n"));
-
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
-
- yyssp = yyss;
- yyvsp = yyvs;
- yylsp = yyls;
-#if YYLTYPE_IS_TRIVIAL
- /* Initialize the default location before parsing starts. */
- yylloc.first_line = yylloc.last_line = 1;
- yylloc.first_column = yylloc.last_column = 0;
-#endif
-
- goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
-`------------------------------------------------------------*/
- yynewstate:
- /* In all cases, when you get here, the value and location stacks
- have just been pushed. So pushing a state here evens the stacks. */
- yyssp++;
-
- yysetstate:
- *yyssp = yystate;
-
- if (yyss + yystacksize - 1 <= yyssp)
- {
- /* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- {
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
- YYLTYPE *yyls1 = yyls;
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
- &yyls1, yysize * sizeof (*yylsp),
- &yystacksize);
- yyls = yyls1;
- yyss = yyss1;
- yyvs = yyvs1;
- }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- yytype_int16 *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
- YYSTACK_RELOCATE (yyls);
-# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
- }
-# endif
-#endif /* no yyoverflow */
-
- yyssp = yyss + yysize - 1;
- yyvsp = yyvs + yysize - 1;
- yylsp = yyls + yysize - 1;
-
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
-
- if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
- }
-
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
- goto yybackup;
-
-/*-----------.
-| yybackup. |
-`-----------*/
-yybackup:
-
- /* Do appropriate processing given the current state. Read a
- look-ahead token if we need one and don't already have one. */
-
- /* First try to decide what to do without reference to look-ahead token. */
- yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
- goto yydefault;
-
- /* Not known => get a look-ahead token if don't already have one. */
-
- /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
- if (yychar == YYEMPTY)
- {
- YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
- }
-
- if (yychar <= YYEOF)
- {
- yychar = yytoken = YYEOF;
- YYDPRINTF ((stderr, "Now at end of input.\n"));
- }
- else
- {
- yytoken = YYTRANSLATE (yychar);
- YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
- goto yydefault;
- yyn = yytable[yyn];
- if (yyn <= 0)
- {
- if (yyn == 0 || yyn == YYTABLE_NINF)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- /* Shift the look-ahead token. */
- YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the shifted token unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- yystate = yyn;
- *++yyvsp = yylval;
- *++yylsp = yylloc;
- goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
-
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
-
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. Assigning to YYVAL
- unconditionally makes the parser a bit smaller, and it avoids a
- GCC warning that YYVAL may be used uninitialized. */
- yyval = yyvsp[1-yylen];
-
- /* Default location. */
- YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 2:
-#line 175 "ast_expr2.y"
- { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
- ((struct parse_io *)parseio)->val->type = (yyvsp[(1) - (1)].val)->type;
- if( (yyvsp[(1) - (1)].val)->type == AST_EXPR_integer )
- ((struct parse_io *)parseio)->val->u.i = (yyvsp[(1) - (1)].val)->u.i;
- else
- ((struct parse_io *)parseio)->val->u.s = (yyvsp[(1) - (1)].val)->u.s;
- free((yyvsp[(1) - (1)].val));
- ;}
- break;
-
- case 3:
-#line 183 "ast_expr2.y"
- {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
- ((struct parse_io *)parseio)->val->type = AST_EXPR_string;
- ((struct parse_io *)parseio)->val->u.s = strdup("");
- ;}
- break;
-
- case 4:
-#line 190 "ast_expr2.y"
- { (yyval.val)= (yyvsp[(1) - (1)].val);;}
- break;
-
- case 5:
-#line 191 "ast_expr2.y"
- { (yyval.val) = (yyvsp[(2) - (3)].val);
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;
- DESTROY((yyvsp[(1) - (3)].val)); DESTROY((yyvsp[(3) - (3)].val)); ;}
- break;
-
- case 6:
-#line 195 "ast_expr2.y"
- { (yyval.val) = op_or ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 7:
-#line 199 "ast_expr2.y"
- { (yyval.val) = op_and ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 8:
-#line 203 "ast_expr2.y"
- { (yyval.val) = op_eq ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 9:
-#line 207 "ast_expr2.y"
- { (yyval.val) = op_gt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 10:
-#line 211 "ast_expr2.y"
- { (yyval.val) = op_lt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 11:
-#line 215 "ast_expr2.y"
- { (yyval.val) = op_ge ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 12:
-#line 219 "ast_expr2.y"
- { (yyval.val) = op_le ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 13:
-#line 223 "ast_expr2.y"
- { (yyval.val) = op_ne ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 14:
-#line 227 "ast_expr2.y"
- { (yyval.val) = op_plus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 15:
-#line 231 "ast_expr2.y"
- { (yyval.val) = op_minus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 16:
-#line 235 "ast_expr2.y"
- { (yyval.val) = op_negate ((yyvsp[(2) - (2)].val));
- DESTROY((yyvsp[(1) - (2)].val));
- (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 17:
-#line 239 "ast_expr2.y"
- { (yyval.val) = op_compl ((yyvsp[(2) - (2)].val));
- DESTROY((yyvsp[(1) - (2)].val));
- (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 18:
-#line 243 "ast_expr2.y"
- { (yyval.val) = op_times ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 19:
-#line 247 "ast_expr2.y"
- { (yyval.val) = op_div ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 20:
-#line 251 "ast_expr2.y"
- { (yyval.val) = op_rem ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 21:
-#line 255 "ast_expr2.y"
- { (yyval.val) = op_colon ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 22:
-#line 259 "ast_expr2.y"
- { (yyval.val) = op_eqtilde ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
- DESTROY((yyvsp[(2) - (3)].val));
- (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
- case 23:
-#line 263 "ast_expr2.y"
- { (yyval.val) = op_cond ((yyvsp[(1) - (5)].val), (yyvsp[(3) - (5)].val), (yyvsp[(5) - (5)].val));
- DESTROY((yyvsp[(2) - (5)].val));
- DESTROY((yyvsp[(4) - (5)].val));
- (yyloc).first_column = (yylsp[(1) - (5)]).first_column; (yyloc).last_column = (yylsp[(3) - (5)]).last_column;
- (yyloc).first_line=0; (yyloc).last_line=0;;}
- break;
-
-
-/* Line 1270 of yacc.c. */
-#line 1864 "ast_expr2.c"
- default: break;
- }
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
-
- *++yyvsp = yyval;
- *++yylsp = yyloc;
-
- /* Now `shift' the result of the reduction. Determine what state
- that goes to, based on the state we popped back to and the rule
- number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
-
- goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus)
- {
- ++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (YY_("syntax error"));
-#else
- {
- YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
- if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
- {
- YYSIZE_T yyalloc = 2 * yysize;
- if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
- yyalloc = YYSTACK_ALLOC_MAXIMUM;
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yyalloc);
- if (yymsg)
- yymsg_alloc = yyalloc;
- else
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- }
- }
-
- if (0 < yysize && yysize <= yymsg_alloc)
- {
- (void) yysyntax_error (yymsg, yystate, yychar);
- yyerror (yymsg);
- }
- else
- {
- yyerror (YY_("syntax error"));
- if (yysize != 0)
- goto yyexhaustedlab;
- }
- }
-#endif
- }
-
- yyerror_range[0] = yylloc;
-
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse look-ahead token after an
- error, discard it. */
-
- if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
- else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval, &yylloc);
- yychar = YYEMPTY;
- }
- }
-
- /* Else will try to reuse look-ahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
-
- yyerror_range[0] = yylsp[1-yylen];
- /* Do not reclaim the symbols of the rule which action triggered
- this YYERROR. */
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
- yystate = *yyssp;
- goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR. |
-`-------------------------------------------------------------*/
-yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
-
- for (;;)
- {
- yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
-
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
-
- yyerror_range[0] = *yylsp;
- yydestruct ("Error: popping",
- yystos[yystate], yyvsp, yylsp);
- YYPOPSTACK (1);
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- *++yyvsp = yylval;
-
- yyerror_range[1] = yylloc;
- /* Using YYLLOC is tempting, but would change the location of
- the look-ahead. YYLOC is available though. */
- YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
- *++yylsp = yyloc;
-
- /* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
-yyexhaustedlab:
- yyerror (YY_("memory exhausted"));
- yyresult = 2;
- /* Fall through. */
-#endif
-
-yyreturn:
- if (yychar != YYEOF && yychar != YYEMPTY)
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval, &yylloc);
- /* Do not reclaim the symbols of the rule which action triggered
- this YYABORT or YYACCEPT. */
- YYPOPSTACK (yylen);
- YY_STACK_PRINT (yyss, yyssp);
- while (yyssp != yyss)
- {
- yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp, yylsp);
- YYPOPSTACK (1);
- }
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
-#endif
- return yyresult;
-}
-
-
-#line 270 "ast_expr2.y"
-
-
-static struct val *
-make_integer (quad_t i)
-{
- struct val *vp;
-
- vp = (struct val *) malloc (sizeof (*vp));
- if (vp == NULL) {
- ast_log(LOG_WARNING, "malloc() failed\n");
- return(NULL);
- }
-
- vp->type = AST_EXPR_integer;
- vp->u.i = i;
- return vp;
-}
-
-static struct val *
-make_str (const char *s)
-{
- struct val *vp;
- size_t i;
- int isint;
-
- vp = (struct val *) malloc (sizeof (*vp));
- if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
- ast_log(LOG_WARNING,"malloc() failed\n");
- return(NULL);
- }
-
- for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
- isint && i < strlen(s);
- i++)
- {
- if(!isdigit(s[i]))
- isint = 0;
- }
-
- if (isint)
- vp->type = AST_EXPR_numeric_string;
- else
- vp->type = AST_EXPR_string;
-
- return vp;
-}
-
-
-static void
-free_value (struct val *vp)
-{
- if (vp==NULL) {
- return;
- }
- if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
- free (vp->u.s);
- free(vp);
-}
-
-
-static quad_t
-to_integer (struct val *vp)
-{
- quad_t i;
-
- if (vp == NULL) {
- ast_log(LOG_WARNING,"vp==NULL in to_integer()\n");
- return(0);
- }
-
- if (vp->type == AST_EXPR_integer)
- return 1;
-
- if (vp->type == AST_EXPR_string)
- return 0;
-
- /* vp->type == AST_EXPR_numeric_string, make it numeric */
- errno = 0;
- i = strtoll(vp->u.s, (char**)NULL, 10);
- if (errno != 0) {
- ast_log(LOG_WARNING,"Conversion of %s to integer under/overflowed!\n", vp->u.s);
- free(vp->u.s);
- vp->u.s = 0;
- return(0);
- }
- free (vp->u.s);
- vp->u.i = i;
- vp->type = AST_EXPR_integer;
- return 1;
-}
-
-static void
-strip_quotes(struct val *vp)
-{
- if (vp->type != AST_EXPR_string && vp->type != AST_EXPR_numeric_string)
- return;
-
- if( vp->u.s[0] == '"' && vp->u.s[strlen(vp->u.s)-1] == '"' )
- {
- char *f, *t;
- f = vp->u.s;
- t = vp->u.s;
-
- while( *f )
- {
- if( *f && *f != '"' )
- *t++ = *f++;
- else
- f++;
- }
- *t = *f;
- }
-}
-
-static void
-to_string (struct val *vp)
-{
- char *tmp;
-
- if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
- return;
-
- tmp = malloc ((size_t)25);
- if (tmp == NULL) {
- ast_log(LOG_WARNING,"malloc() failed\n");
- return;
- }
-
- sprintf(tmp, "%ld", (long int) vp->u.i);
- vp->type = AST_EXPR_string;
- vp->u.s = tmp;
-}
-
-
-static int
-isstring (struct val *vp)
-{
- /* only TRUE if this string is not a valid integer */
- return (vp->type == AST_EXPR_string);
-}
-
-
-static int
-is_zero_or_null (struct val *vp)
-{
- if (vp->type == AST_EXPR_integer) {
- return (vp->u.i == 0);
- } else {
- return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
- }
- /* NOTREACHED */
-}
-
-#ifdef STANDALONE
-
-void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
-{
- va_list vars;
- va_start(vars,fmt);
-
- printf("LOG: lev:%d file:%s line:%d func: %s ",
- level, file, line, function);
- vprintf(fmt, vars);
- fflush(stdout);
- va_end(vars);
-}
-
-
-int main(int argc,char **argv) {
- char s[4096];
- char out[4096];
- FILE *infile;
-
- if( !argv[1] )
- exit(20);
-
- if( access(argv[1],F_OK)== 0 )
- {
- int ret;
-
- infile = fopen(argv[1],"r");
- if( !infile )
- {
- printf("Sorry, couldn't open %s for reading!\n", argv[1]);
- exit(10);
- }
- while( fgets(s,sizeof(s),infile) )
- {
- if( s[strlen(s)-1] == '\n' )
- s[strlen(s)-1] = 0;
-
- ret = ast_expr(s, out, sizeof(out));
- printf("Expression: %s Result: [%d] '%s'\n",
- s, ret, out);
- }
- fclose(infile);
- }
- else
- {
- if (ast_expr(argv[1], s, sizeof(s)))
- printf("=====%s======\n",s);
- else
- printf("No result\n");
- }
-}
-
-#endif
-
-#undef ast_yyerror
-#define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parse_io *parseio)
-
-/* I put the ast_yyerror func in the flex input file,
- because it refers to the buffer state. Best to
- let it access the BUFFER stuff there and not trying
- define all the structs, macros etc. in this file! */
-
-
-static struct val *
-op_or (struct val *a, struct val *b)
-{
- if (is_zero_or_null (a)) {
- free_value (a);
- return (b);
- } else {
- free_value (b);
- return (a);
- }
-}
-
-static struct val *
-op_and (struct val *a, struct val *b)
-{
- if (is_zero_or_null (a) || is_zero_or_null (b)) {
- free_value (a);
- free_value (b);
- return (make_integer ((quad_t)0));
- } else {
- free_value (b);
- return (a);
- }
-}
-
-static struct val *
-op_eq (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
- } else {
-#ifdef DEBUG_FOR_CONVERSIONS
- char buffer[2000];
- sprintf(buffer,"Converting '%s' and '%s' ", a->u.s, b->u.s);
-#endif
- (void)to_integer(a);
- (void)to_integer(b);
-#ifdef DEBUG_FOR_CONVERSIONS
- ast_log(LOG_WARNING,"%s to '%lld' and '%lld'\n", buffer, a->u.i, b->u.i);
-#endif
- r = make_integer ((quad_t)(a->u.i == b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_gt (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i > b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_lt (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i < b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_ge (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i >= b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_le (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i <= b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_cond (struct val *a, struct val *b, struct val *c)
-{
- struct val *r;
-
- if( isstring(a) )
- {
- if( strlen(a->u.s) && strcmp(a->u.s, "\"\"") != 0 && strcmp(a->u.s,"0") != 0 )
- {
- free_value(a);
- free_value(c);
- r = b;
- }
- else
- {
- free_value(a);
- free_value(b);
- r = c;
- }
- }
- else
- {
- (void)to_integer(a);
- if( a->u.i )
- {
- free_value(a);
- free_value(c);
- r = b;
- }
- else
- {
- free_value(a);
- free_value(b);
- r = c;
- }
- }
- return r;
-}
-
-static struct val *
-op_ne (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i != b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static int
-chk_plus (quad_t a, quad_t b, quad_t r)
-{
- /* sum of two positive numbers must be positive */
- if (a > 0 && b > 0 && r <= 0)
- return 1;
- /* sum of two negative numbers must be negative */
- if (a < 0 && b < 0 && r >= 0)
- return 1;
- /* all other cases are OK */
- return 0;
-}
-
-static struct val *
-op_plus (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a)) {
- if( !extra_error_message_supplied )
- 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(b);
- return (a);
- }
-
- 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 r;
-}
-
-static int
-chk_minus (quad_t a, quad_t b, quad_t r)
-{
- /* special case subtraction of QUAD_MIN */
- if (b == QUAD_MIN) {
- if (a >= 0)
- return 1;
- else
- return 0;
- }
- /* this is allowed for b != QUAD_MIN */
- return chk_plus (a, -b, r);
-}
-
-static struct val *
-op_minus (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a)) {
- if( !extra_error_message_supplied )
- 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)) {
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- free_value(b);
- return (a);
- }
-
- 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);
- return r;
-}
-
-static struct val *
-op_negate (struct val *a)
-{
- struct val *r;
-
- if (!to_integer (a) ) {
- free_value(a);
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- return make_integer(0);
- }
-
- r = make_integer (/*(quad_t)*/(- a->u.i));
- if (chk_minus (0, a->u.i, r->u.i)) {
- ast_log(LOG_WARNING, "overflow\n");
- }
- free_value (a);
- return r;
-}
-
-static struct val *
-op_compl (struct val *a)
-{
- int v1 = 1;
- struct val *r;
-
- if( !a )
- {
- v1 = 0;
- }
- else
- {
- switch( a->type )
- {
- case AST_EXPR_integer:
- if( a->u.i == 0 )
- v1 = 0;
- break;
-
- case AST_EXPR_string:
- if( a->u.s == 0 )
- v1 = 0;
- else
- {
- if( a->u.s[0] == 0 )
- v1 = 0;
- else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
- v1 = 0;
- }
- break;
-
- case AST_EXPR_numeric_string:
- if( a->u.s == 0 )
- v1 = 0;
- else
- {
- if( a->u.s[0] == 0 )
- v1 = 0;
- else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
- v1 = 0;
- }
- break;
- }
- }
-
- r = make_integer (!v1);
- free_value (a);
- return r;
-}
-
-static int
-chk_times (quad_t a, quad_t b, quad_t r)
-{
- /* special case: first operand is 0, no overflow possible */
- if (a == 0)
- return 0;
- /* cerify that result of division matches second operand */
- if (r / a != b)
- return 1;
- return 0;
-}
-
-static struct val *
-op_times (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a) || !to_integer (b)) {
- free_value(a);
- free_value(b);
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- return(make_integer(0));
- }
-
- 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 (r);
-}
-
-static int
-chk_div (quad_t a, quad_t b)
-{
- /* div by zero has been taken care of before */
- /* only QUAD_MIN / -1 causes overflow */
- if (a == QUAD_MIN && b == -1)
- return 1;
- /* everything else is OK */
- return 0;
-}
-
-static struct val *
-op_div (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a)) {
- free_value(a);
- free_value(b);
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- return make_integer(0);
- } else if (!to_integer (b)) {
- free_value(a);
- free_value(b);
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- return make_integer(INT_MAX);
- }
-
- if (b->u.i == 0) {
- ast_log(LOG_WARNING, "division by zero\n");
- free_value(a);
- free_value(b);
- return make_integer(INT_MAX);
- }
-
- 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 r;
-}
-
-static struct val *
-op_rem (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a) || !to_integer (b)) {
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- free_value(a);
- free_value(b);
- return make_integer(0);
- }
-
- if (b->u.i == 0) {
- ast_log(LOG_WARNING, "div by zero\n");
- free_value(a);
- return(b);
- }
-
- r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
- /* chk_rem necessary ??? */
- free_value (a);
- free_value (b);
- return r;
-}
-
-
-static struct val *
-op_colon (struct val *a, struct val *b)
-{
- regex_t rp;
- regmatch_t rm[2];
- char errbuf[256];
- int eval;
- struct val *v;
-
- /* coerce to both arguments to strings */
- to_string(a);
- to_string(b);
- /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
- strip_quotes(a);
- strip_quotes(b);
- /* compile regular expression */
- if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
- regerror (eval, &rp, errbuf, sizeof(errbuf));
- ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
- free_value(a);
- free_value(b);
- return make_str("");
- }
-
- /* compare string against pattern */
- /* remember that patterns are anchored to the beginning of the line */
- if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
- if (rm[1].rm_so >= 0) {
- *(a->u.s + rm[1].rm_eo) = '\0';
- v = make_str (a->u.s + rm[1].rm_so);
-
- } else {
- v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
- }
- } else {
- if (rp.re_nsub == 0) {
- v = make_integer ((quad_t)0);
- } else {
- v = make_str ("");
- }
- }
-
- /* free arguments and pattern buffer */
- free_value (a);
- free_value (b);
- regfree (&rp);
-
- return v;
-}
-
-
-static struct val *
-op_eqtilde (struct val *a, struct val *b)
-{
- regex_t rp;
- regmatch_t rm[2];
- char errbuf[256];
- int eval;
- struct val *v;
-
- /* coerce to both arguments to strings */
- to_string(a);
- to_string(b);
- /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
- strip_quotes(a);
- strip_quotes(b);
- /* compile regular expression */
- if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
- regerror (eval, &rp, errbuf, sizeof(errbuf));
- ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
- free_value(a);
- free_value(b);
- return make_str("");
- }
-
- /* compare string against pattern */
- /* remember that patterns are anchored to the beginning of the line */
- if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 ) {
- if (rm[1].rm_so >= 0) {
- *(a->u.s + rm[1].rm_eo) = '\0';
- v = make_str (a->u.s + rm[1].rm_so);
-
- } else {
- v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
- }
- } else {
- if (rp.re_nsub == 0) {
- v = make_integer ((quad_t)0);
- } else {
- v = make_str ("");
- }
- }
-
- /* free arguments and pattern buffer */
- free_value (a);
- free_value (b);
- regfree (&rp);
-
- return v;
-}
-
diff --git a/main/ast_expr2.fl b/main/ast_expr2.fl
deleted file mode 100644
index 67dd3aa6a..000000000
--- a/main/ast_expr2.fl
+++ /dev/null
@@ -1,414 +0,0 @@
-%{
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Dialplan Expression Lexical Scanner
- */
-
-#include "asterisk.h"
-
-#if !defined(STANDALONE_AEL)
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#endif
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <locale.h>
-#include <ctype.h>
-#if !defined(SOLARIS) && !defined(__CYGWIN__)
-/* #include <err.h> */
-#else
-#define quad_t int64_t
-#endif
-#include <errno.h>
-#include <regex.h>
-#include <limits.h>
-
-#include "asterisk/ast_expr.h"
-#include "asterisk/logger.h"
-#include "asterisk/strings.h"
-
-enum valtype {
- AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
-} ;
-
-struct val {
- enum valtype type;
- union {
- char *s;
- quad_t i;
- } u;
-} ;
-
-#include "ast_expr2.h" /* the o/p of the bison on ast_expr2.y */
-
-#define SET_COLUMNS do { \
- yylloc_param->first_column = (int)(yyg->yytext_r - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf); \
- yylloc_param->last_column += yyleng - 1; \
- yylloc_param->first_line = yylloc_param->last_line = 1; \
- } while (0)
-
-#define SET_STRING do { \
- yylval_param->val = calloc(1, sizeof(struct val)); \
- yylval_param->val->type = AST_EXPR_string; \
- yylval_param->val->u.s = strdup(yytext); \
- } while (0)
-
-#define SET_NUMERIC_STRING do { \
- yylval_param->val = calloc(1, sizeof(struct val)); \
- yylval_param->val->type = AST_EXPR_numeric_string; \
- yylval_param->val->u.s = strdup(yytext); \
- } while (0)
-
-struct parse_io
-{
- char *string;
- struct val *val;
- yyscan_t scanner;
-};
-
-void ast_yyset_column(int column_no, yyscan_t yyscanner);
-int ast_yyget_column(yyscan_t yyscanner);
-static int curlycount = 0;
-static char *expr2_token_subst(const char *mess);
-%}
-
-%option prefix="ast_yy"
-%option batch
-%option outfile="ast_expr2f.c"
-%option reentrant
-%option bison-bridge
-%option bison-locations
-%option noyywrap
-%option noyyfree
-%x var trail
-
-%%
-
-\| { SET_COLUMNS; SET_STRING; return TOK_OR;}
-\& { SET_COLUMNS; SET_STRING; return TOK_AND;}
-\= { SET_COLUMNS; SET_STRING; return TOK_EQ;}
-\|\| { SET_COLUMNS; SET_STRING; return TOK_OR;}
-\&\& { SET_COLUMNS; SET_STRING; return TOK_AND;}
-\=\= { SET_COLUMNS; SET_STRING; return TOK_EQ;}
-\=~ { SET_COLUMNS; SET_STRING; return TOK_EQTILDE;}
-\> { SET_COLUMNS; SET_STRING; return TOK_GT;}
-\< { SET_COLUMNS; SET_STRING; return TOK_LT;}
-\>\= { SET_COLUMNS; SET_STRING; return TOK_GE;}
-\<\= { SET_COLUMNS; SET_STRING; return TOK_LE;}
-\!\= { SET_COLUMNS; SET_STRING; return TOK_NE;}
-\+ { SET_COLUMNS; SET_STRING; return TOK_PLUS;}
-\- { SET_COLUMNS; SET_STRING; return TOK_MINUS;}
-\* { SET_COLUMNS; SET_STRING; return TOK_MULT;}
-\/ { SET_COLUMNS; SET_STRING; return TOK_DIV;}
-\% { SET_COLUMNS; SET_STRING; return TOK_MOD;}
-\? { SET_COLUMNS; SET_STRING; return TOK_COND;}
-\! { SET_COLUMNS; SET_STRING; return TOK_COMPL;}
-\: { SET_COLUMNS; SET_STRING; return TOK_COLON;}
-\:\: { SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
-\( { SET_COLUMNS; SET_STRING; return TOK_LP;}
-\) { SET_COLUMNS; SET_STRING; return TOK_RP;}
-\$\{ {
- /* gather the contents of ${} expressions, with trailing stuff,
- * into a single TOKEN.
- * They are much more complex now than they used to be
- */
- curlycount = 0;
- BEGIN(var);
- yymore();
- }
-
-[ \t\r] {}
-\"[^"]*\" {SET_COLUMNS; SET_STRING; return TOKEN;}
-
-[\n] {/* what to do with eol */}
-[0-9]+ {
- SET_COLUMNS;
- /* the original behavior of the expression parser was
- * to bring in numbers as a numeric string
- */
- SET_NUMERIC_STRING;
- return TOKEN;
- }
-
-[a-zA-Z0-9,.';\\_^$#@]+ {
- SET_COLUMNS;
- SET_STRING;
- return TOKEN;
- }
-
-
-<var>[^{}]*\} {
- curlycount--;
- if (curlycount < 0) {
- BEGIN(trail);
- yymore();
- } else {
- yymore();
- }
- }
-
-<var>[^{}]*\{ {
- curlycount++;
- yymore();
- }
-
-
-<trail>[^-\t\r \n$():?%/+=*<>!|&]* {
- BEGIN(0);
- SET_COLUMNS;
- SET_STRING;
- return TOKEN;
- }
-
-<trail>[-\t\r \n$():?%/+=*<>!|&] {
- char c = yytext[yyleng-1];
- BEGIN(0);
- unput(c);
- SET_COLUMNS;
- SET_STRING;
- return TOKEN;
- }
-
-<trail>\$\{ {
- curlycount = 0;
- BEGIN(var);
- yymore();
- }
-
-<trail><<EOF>> {
- BEGIN(0);
- SET_COLUMNS;
- SET_STRING;
- return TOKEN;
- /*actually, if an expr is only a variable ref, this could happen a LOT */
- }
-
-%%
-
-/* I'm putting the interface routine to the whole parse here in the flexer input file
- mainly because of all the flexer initialization that has to be done. Shouldn't matter
- where it is, as long as it's somewhere. I didn't want to define a prototype for the
- ast_yy_scan_string in the .y file, because then, I'd have to define YY_BUFFER_STATE there...
- UGH! that would be inappropriate. */
-
-int ast_yyparse(void *); /* need to/should define this prototype for the call to yyparse */
-int ast_yyerror(const char *, YYLTYPE *, struct parse_io *); /* likewise */
-
-void ast_yyfree(void *ptr, yyscan_t yyscanner)
-{
- if (ptr) /* the normal generated yyfree func just frees its first arg;
- this get complaints on some systems, as sometimes this
- arg is a nil ptr! It's usually not fatal, but is irritating! */
- free( (char *) ptr );
-}
-
-int ast_expr(char *expr, char *buf, int length)
-{
- struct parse_io io;
- int return_value = 0;
-
- memset(&io, 0, sizeof(io));
- io.string = expr; /* to pass to the error routine */
-
- ast_yylex_init(&io.scanner);
-
- ast_yy_scan_string(expr, io.scanner);
-
- ast_yyparse ((void *) &io);
-
- ast_yylex_destroy(io.scanner);
-
- if (!io.val) {
- if (length > 1) {
- strcpy(buf, "0");
- return_value = 1;
- }
- } else {
- if (io.val->type == AST_EXPR_integer) {
- int res_length;
-
- res_length = snprintf(buf, length, "%ld", (long int) io.val->u.i);
- return_value = (res_length <= length) ? res_length : length;
- } else {
-#if defined(STANDALONE) || defined(LOW_MEMORY) || defined(STANDALONE_AEL)
- strncpy(buf, io.val->u.s, length - 1);
-#else /* !STANDALONE && !LOW_MEMORY */
- ast_copy_string(buf, io.val->u.s, length);
-#endif /* STANDALONE || LOW_MEMORY */
- return_value = strlen(buf);
- free(io.val->u.s);
- }
- free(io.val);
- }
- return return_value;
-}
-
-
-char extra_error_message[4095];
-int extra_error_message_supplied = 0;
-void ast_expr_register_extra_error_info(char *message);
-void ast_expr_clear_extra_error_info(void);
-
-void ast_expr_register_extra_error_info(char *message)
-{
- extra_error_message_supplied=1;
- strcpy(extra_error_message, message);
-}
-
-void ast_expr_clear_extra_error_info(void)
-{
- extra_error_message_supplied=0;
- extra_error_message[0] = 0;
-}
-
-static char *expr2_token_equivs1[] =
-{
- "TOKEN",
- "TOK_COND",
- "TOK_COLONCOLON",
- "TOK_OR",
- "TOK_AND",
- "TOK_EQ",
- "TOK_GT",
- "TOK_LT",
- "TOK_GE",
- "TOK_LE",
- "TOK_NE",
- "TOK_PLUS",
- "TOK_MINUS",
- "TOK_MULT",
- "TOK_DIV",
- "TOK_MOD",
- "TOK_COMPL",
- "TOK_COLON",
- "TOK_EQTILDE",
- "TOK_RP",
- "TOK_LP"
-};
-
-static char *expr2_token_equivs2[] =
-{
- "<token>",
- "?",
- "::",
- "|",
- "&",
- "=",
- ">",
- "<",
- ">=",
- "<=",
- "!=",
- "+",
- "-",
- "*",
- "/",
- "%",
- "!",
- ":",
- "=~",
- ")",
- "("
-};
-
-
-static char *expr2_token_subst(const char *mess)
-{
- /* calc a length, malloc, fill, and return; yyerror had better free it! */
- int len=0,i;
- const char *p;
- char *res, *s,*t;
- int expr2_token_equivs_entries = sizeof(expr2_token_equivs1)/sizeof(char*);
-
- for (p=mess; *p; p++) {
- for (i=0; i<expr2_token_equivs_entries; i++) {
- if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 )
- {
- len+=strlen(expr2_token_equivs2[i])+2;
- p += strlen(expr2_token_equivs1[i])-1;
- break;
- }
- }
- len++;
- }
- res = (char*)malloc(len+1);
- res[0] = 0;
- s = res;
- for (p=mess; *p;) {
- int found = 0;
- for (i=0; i<expr2_token_equivs_entries; i++) {
- if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 ) {
- *s++ = '\'';
- for (t=expr2_token_equivs2[i]; *t;) {
- *s++ = *t++;
- }
- *s++ = '\'';
- p += strlen(expr2_token_equivs1[i]);
- found = 1;
- break;
- }
- }
- if( !found )
- *s++ = *p++;
- }
- *s++ = 0;
- return res;
-}
-
-int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio )
-{
- struct yyguts_t * yyg = (struct yyguts_t*)(parseio->scanner);
- char spacebuf[8000]; /* best safe than sorry */
- char spacebuf2[8000]; /* best safe than sorry */
- int i=0;
- char *s2 = expr2_token_subst(s);
- spacebuf[0] = 0;
-
- for(i=0;i< (int)(yytext - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);i++) spacebuf2[i] = ' '; /* uh... assuming yyg is defined, then I can use the yycolumn macro,
- which is the same thing as... get this:
- yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]->yy_bs_column
- I was tempted to just use yy_buf_pos in the STATE, but..., well:
- a. the yy_buf_pos is the current position in the buffer, which
- may not relate to the entire string/buffer because of the
- buffering.
- b. but, analysis of the situation is that when you use the
- yy_scan_string func, it creates a single buffer the size of
- string, so the two would be the same...
- so, in the end, the yycolumn macro is available, shorter, therefore easier. */
- spacebuf2[i++]='^';
- spacebuf2[i]= 0;
-
-#ifdef STANDALONE3
- /* easier to read in the standalone version */
- printf("ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n",
- (extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2);
-#else
- ast_log(LOG_WARNING,"ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n",
- (extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2);
-#endif
-#ifndef STANDALONE
- ast_log(LOG_WARNING,"If you have questions, please refer to doc/channelvariables.txt in the asterisk source.\n");
-#endif
- free(s2);
- return(0);
-}
diff --git a/main/ast_expr2.h b/main/ast_expr2.h
deleted file mode 100644
index d4490512e..000000000
--- a/main/ast_expr2.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.1a. */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- TOK_COLONCOLON = 258,
- TOK_COND = 259,
- TOK_OR = 260,
- TOK_AND = 261,
- TOK_NE = 262,
- TOK_LE = 263,
- TOK_GE = 264,
- TOK_LT = 265,
- TOK_GT = 266,
- TOK_EQ = 267,
- TOK_MINUS = 268,
- TOK_PLUS = 269,
- TOK_MOD = 270,
- TOK_DIV = 271,
- TOK_MULT = 272,
- TOK_COMPL = 273,
- TOK_EQTILDE = 274,
- TOK_COLON = 275,
- TOK_LP = 276,
- TOK_RP = 277,
- TOKEN = 278
- };
-#endif
-/* Tokens. */
-#define TOK_COLONCOLON 258
-#define TOK_COND 259
-#define TOK_OR 260
-#define TOK_AND 261
-#define TOK_NE 262
-#define TOK_LE 263
-#define TOK_GE 264
-#define TOK_LT 265
-#define TOK_GT 266
-#define TOK_EQ 267
-#define TOK_MINUS 268
-#define TOK_PLUS 269
-#define TOK_MOD 270
-#define TOK_DIV 271
-#define TOK_MULT 272
-#define TOK_COMPL 273
-#define TOK_EQTILDE 274
-#define TOK_COLON 275
-#define TOK_LP 276
-#define TOK_RP 277
-#define TOKEN 278
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 147 "ast_expr2.y"
-{
- struct val *val;
-}
-/* Line 1536 of yacc.c. */
-#line 89 "ast_expr2.h"
- YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
-{
- int first_line;
- int first_column;
- int last_line;
- int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-
diff --git a/main/ast_expr2.y b/main/ast_expr2.y
deleted file mode 100644
index b2faf374d..000000000
--- a/main/ast_expr2.y
+++ /dev/null
@@ -1,1045 +0,0 @@
-%{
-/* Written by Pace Willisson (pace@blitz.com)
- * and placed in the public domain.
- *
- * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
- *
- * And then overhauled twice by Steve Murphy (murf@digium.com)
- * to add double-quoted strings, allow mult. spaces, improve
- * error messages, and then to fold in a flex scanner for the
- * yylex operation.
- *
- * $FreeBSD: src/bin/expr/expr.y,v 1.16 2000/07/22 10:59:36 se Exp $
- */
-
-#include "asterisk.h"
-
-#if !defined(STANDALONE_AEL)
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#endif
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <locale.h>
-#include <unistd.h>
-#include <ctype.h>
-#if !defined(SOLARIS) && !defined(__CYGWIN__)
-/* #include <err.h> */
-#else
-#define quad_t int64_t
-#endif
-#include <errno.h>
-#include <regex.h>
-#include <limits.h>
-
-#include "asterisk/ast_expr.h"
-#include "asterisk/logger.h"
-
-#if defined(LONG_LONG_MIN) && !defined(QUAD_MIN)
-#define QUAD_MIN LONG_LONG_MIN
-#endif
-#if defined(LONG_LONG_MAX) && !defined(QUAD_MAX)
-#define QUAD_MAX LONG_LONG_MAX
-#endif
-
-# if ! defined(QUAD_MIN)
-# define QUAD_MIN (-0x7fffffffffffffffLL-1)
-# endif
-# if ! defined(QUAD_MAX)
-# define QUAD_MAX (0x7fffffffffffffffLL)
-# endif
-
-#define YYPARSE_PARAM parseio
-#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
-#define YYERROR_VERBOSE 1
-extern char extra_error_message[4095];
-extern int extra_error_message_supplied;
-
-enum valtype {
- AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
-} ;
-
-#ifdef STANDALONE
-void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
-#endif
-
-struct val {
- enum valtype type;
- union {
- char *s;
- quad_t i;
- } u;
-} ;
-
-typedef void *yyscan_t;
-
-struct parse_io
-{
- char *string;
- struct val *val;
- yyscan_t scanner;
-};
-
-static int chk_div __P((quad_t, quad_t));
-static int chk_minus __P((quad_t, quad_t, quad_t));
-static int chk_plus __P((quad_t, quad_t, quad_t));
-static int chk_times __P((quad_t, quad_t, quad_t));
-static void free_value __P((struct val *));
-static int is_zero_or_null __P((struct val *));
-static int isstring __P((struct val *));
-static struct val *make_integer __P((quad_t));
-static struct val *make_str __P((const char *));
-static struct val *op_and __P((struct val *, struct val *));
-static struct val *op_colon __P((struct val *, struct val *));
-static struct val *op_eqtilde __P((struct val *, struct val *));
-static struct val *op_div __P((struct val *, struct val *));
-static struct val *op_eq __P((struct val *, struct val *));
-static struct val *op_ge __P((struct val *, struct val *));
-static struct val *op_gt __P((struct val *, struct val *));
-static struct val *op_le __P((struct val *, struct val *));
-static struct val *op_lt __P((struct val *, struct val *));
-static struct val *op_cond __P((struct val *, struct val *, struct val *));
-static struct val *op_minus __P((struct val *, struct val *));
-static struct val *op_negate __P((struct val *));
-static struct val *op_compl __P((struct val *));
-static struct val *op_ne __P((struct val *, struct val *));
-static struct val *op_or __P((struct val *, struct val *));
-static struct val *op_plus __P((struct val *, struct val *));
-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
-
-/* we will get warning about no prototype for yylex! But we can't
- define it here, we have no definition yet for YYSTYPE. */
-
-int ast_yyerror(const char *,YYLTYPE *, struct parse_io *);
-
-/* I wanted to add args to the yyerror routine, so I could print out
- some useful info about the error. Not as easy as it looks, but it
- is possible. */
-#define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio)
-#define DESTROY(x) {if((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) free((x)->u.s); (x)->u.s = 0; free(x);}
-%}
-
-%pure-parser
-%locations
-/* %debug for when you are having big problems */
-
-/* %name-prefix="ast_yy" */
-
-%union
-{
- struct val *val;
-}
-
-%{
-extern int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
-%}
-%left <val> TOK_COND TOK_COLONCOLON
-%left <val> TOK_OR
-%left <val> TOK_AND
-%left <val> TOK_EQ TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE
-%left <val> TOK_PLUS TOK_MINUS
-%left <val> TOK_MULT TOK_DIV TOK_MOD
-%right <val> TOK_COMPL
-%left <val> TOK_COLON TOK_EQTILDE
-%left <val> TOK_RP TOK_LP
-
-
-%token <val> TOKEN
-%type <val> start expr
-
-
-%destructor { free_value($$); } expr TOKEN TOK_COND TOK_COLONCOLON TOK_OR TOK_AND TOK_EQ
- TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE TOK_PLUS TOK_MINUS TOK_MULT TOK_DIV TOK_MOD TOK_COMPL TOK_COLON TOK_EQTILDE
- TOK_RP TOK_LP
-
-%%
-
-start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
- ((struct parse_io *)parseio)->val->type = $1->type;
- if( $1->type == AST_EXPR_integer )
- ((struct parse_io *)parseio)->val->u.i = $1->u.i;
- else
- ((struct parse_io *)parseio)->val->u.s = $1->u.s;
- free($1);
- }
- | {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
- ((struct parse_io *)parseio)->val->type = AST_EXPR_string;
- ((struct parse_io *)parseio)->val->u.s = strdup("");
- }
-
- ;
-
-expr: TOKEN { $$= $1;}
- | TOK_LP expr TOK_RP { $$ = $2;
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;
- DESTROY($1); DESTROY($3); }
- | expr TOK_OR expr { $$ = op_or ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_AND expr { $$ = op_and ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_EQ expr { $$ = op_eq ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_GT expr { $$ = op_gt ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_LT expr { $$ = op_lt ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_GE expr { $$ = op_ge ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_LE expr { $$ = op_le ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_NE expr { $$ = op_ne ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_PLUS expr { $$ = op_plus ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_MINUS expr { $$ = op_minus ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | TOK_MINUS expr %prec TOK_COMPL { $$ = op_negate ($2);
- DESTROY($1);
- @$.first_column = @1.first_column; @$.last_column = @2.last_column;
- @$.first_line=0; @$.last_line=0;}
- | TOK_COMPL expr { $$ = op_compl ($2);
- DESTROY($1);
- @$.first_column = @1.first_column; @$.last_column = @2.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_MULT expr { $$ = op_times ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_DIV expr { $$ = op_div ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_MOD expr { $$ = op_rem ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_COLON expr { $$ = op_colon ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_EQTILDE expr { $$ = op_eqtilde ($1, $3);
- DESTROY($2);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- | expr TOK_COND expr TOK_COLONCOLON expr { $$ = op_cond ($1, $3, $5);
- DESTROY($2);
- DESTROY($4);
- @$.first_column = @1.first_column; @$.last_column = @3.last_column;
- @$.first_line=0; @$.last_line=0;}
- ;
-
-%%
-
-static struct val *
-make_integer (quad_t i)
-{
- struct val *vp;
-
- vp = (struct val *) malloc (sizeof (*vp));
- if (vp == NULL) {
- ast_log(LOG_WARNING, "malloc() failed\n");
- return(NULL);
- }
-
- vp->type = AST_EXPR_integer;
- vp->u.i = i;
- return vp;
-}
-
-static struct val *
-make_str (const char *s)
-{
- struct val *vp;
- size_t i;
- int isint;
-
- vp = (struct val *) malloc (sizeof (*vp));
- if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
- ast_log(LOG_WARNING,"malloc() failed\n");
- return(NULL);
- }
-
- for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
- isint && i < strlen(s);
- i++)
- {
- if(!isdigit(s[i]))
- isint = 0;
- }
-
- if (isint)
- vp->type = AST_EXPR_numeric_string;
- else
- vp->type = AST_EXPR_string;
-
- return vp;
-}
-
-
-static void
-free_value (struct val *vp)
-{
- if (vp==NULL) {
- return;
- }
- if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
- free (vp->u.s);
- free(vp);
-}
-
-
-static quad_t
-to_integer (struct val *vp)
-{
- quad_t i;
-
- if (vp == NULL) {
- ast_log(LOG_WARNING,"vp==NULL in to_integer()\n");
- return(0);
- }
-
- if (vp->type == AST_EXPR_integer)
- return 1;
-
- if (vp->type == AST_EXPR_string)
- return 0;
-
- /* vp->type == AST_EXPR_numeric_string, make it numeric */
- errno = 0;
- i = strtoll(vp->u.s, (char**)NULL, 10);
- if (errno != 0) {
- ast_log(LOG_WARNING,"Conversion of %s to integer under/overflowed!\n", vp->u.s);
- free(vp->u.s);
- vp->u.s = 0;
- return(0);
- }
- free (vp->u.s);
- vp->u.i = i;
- vp->type = AST_EXPR_integer;
- return 1;
-}
-
-static void
-strip_quotes(struct val *vp)
-{
- if (vp->type != AST_EXPR_string && vp->type != AST_EXPR_numeric_string)
- return;
-
- if( vp->u.s[0] == '"' && vp->u.s[strlen(vp->u.s)-1] == '"' )
- {
- char *f, *t;
- f = vp->u.s;
- t = vp->u.s;
-
- while( *f )
- {
- if( *f && *f != '"' )
- *t++ = *f++;
- else
- f++;
- }
- *t = *f;
- }
-}
-
-static void
-to_string (struct val *vp)
-{
- char *tmp;
-
- if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
- return;
-
- tmp = malloc ((size_t)25);
- if (tmp == NULL) {
- ast_log(LOG_WARNING,"malloc() failed\n");
- return;
- }
-
- sprintf(tmp, "%ld", (long int) vp->u.i);
- vp->type = AST_EXPR_string;
- vp->u.s = tmp;
-}
-
-
-static int
-isstring (struct val *vp)
-{
- /* only TRUE if this string is not a valid integer */
- return (vp->type == AST_EXPR_string);
-}
-
-
-static int
-is_zero_or_null (struct val *vp)
-{
- if (vp->type == AST_EXPR_integer) {
- return (vp->u.i == 0);
- } else {
- return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
- }
- /* NOTREACHED */
-}
-
-#ifdef STANDALONE
-
-void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
-{
- va_list vars;
- va_start(vars,fmt);
-
- printf("LOG: lev:%d file:%s line:%d func: %s ",
- level, file, line, function);
- vprintf(fmt, vars);
- fflush(stdout);
- va_end(vars);
-}
-
-
-int main(int argc,char **argv) {
- char s[4096];
- char out[4096];
- FILE *infile;
-
- if( !argv[1] )
- exit(20);
-
- if( access(argv[1],F_OK)== 0 )
- {
- int ret;
-
- infile = fopen(argv[1],"r");
- if( !infile )
- {
- printf("Sorry, couldn't open %s for reading!\n", argv[1]);
- exit(10);
- }
- while( fgets(s,sizeof(s),infile) )
- {
- if( s[strlen(s)-1] == '\n' )
- s[strlen(s)-1] = 0;
-
- ret = ast_expr(s, out, sizeof(out));
- printf("Expression: %s Result: [%d] '%s'\n",
- s, ret, out);
- }
- fclose(infile);
- }
- else
- {
- if (ast_expr(argv[1], s, sizeof(s)))
- printf("=====%s======\n",s);
- else
- printf("No result\n");
- }
-}
-
-#endif
-
-#undef ast_yyerror
-#define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parse_io *parseio)
-
-/* I put the ast_yyerror func in the flex input file,
- because it refers to the buffer state. Best to
- let it access the BUFFER stuff there and not trying
- define all the structs, macros etc. in this file! */
-
-
-static struct val *
-op_or (struct val *a, struct val *b)
-{
- if (is_zero_or_null (a)) {
- free_value (a);
- return (b);
- } else {
- free_value (b);
- return (a);
- }
-}
-
-static struct val *
-op_and (struct val *a, struct val *b)
-{
- if (is_zero_or_null (a) || is_zero_or_null (b)) {
- free_value (a);
- free_value (b);
- return (make_integer ((quad_t)0));
- } else {
- free_value (b);
- return (a);
- }
-}
-
-static struct val *
-op_eq (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
- } else {
-#ifdef DEBUG_FOR_CONVERSIONS
- char buffer[2000];
- sprintf(buffer,"Converting '%s' and '%s' ", a->u.s, b->u.s);
-#endif
- (void)to_integer(a);
- (void)to_integer(b);
-#ifdef DEBUG_FOR_CONVERSIONS
- ast_log(LOG_WARNING,"%s to '%lld' and '%lld'\n", buffer, a->u.i, b->u.i);
-#endif
- r = make_integer ((quad_t)(a->u.i == b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_gt (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i > b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_lt (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i < b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_ge (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i >= b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_le (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i <= b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static struct val *
-op_cond (struct val *a, struct val *b, struct val *c)
-{
- struct val *r;
-
- if( isstring(a) )
- {
- if( strlen(a->u.s) && strcmp(a->u.s, "\"\"") != 0 && strcmp(a->u.s,"0") != 0 )
- {
- free_value(a);
- free_value(c);
- r = b;
- }
- else
- {
- free_value(a);
- free_value(b);
- r = c;
- }
- }
- else
- {
- (void)to_integer(a);
- if( a->u.i )
- {
- free_value(a);
- free_value(c);
- r = b;
- }
- else
- {
- free_value(a);
- free_value(b);
- r = c;
- }
- }
- return r;
-}
-
-static struct val *
-op_ne (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (isstring (a) || isstring (b)) {
- to_string (a);
- to_string (b);
- r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
- } else {
- (void)to_integer(a);
- (void)to_integer(b);
- r = make_integer ((quad_t)(a->u.i != b->u.i));
- }
-
- free_value (a);
- free_value (b);
- return r;
-}
-
-static int
-chk_plus (quad_t a, quad_t b, quad_t r)
-{
- /* sum of two positive numbers must be positive */
- if (a > 0 && b > 0 && r <= 0)
- return 1;
- /* sum of two negative numbers must be negative */
- if (a < 0 && b < 0 && r >= 0)
- return 1;
- /* all other cases are OK */
- return 0;
-}
-
-static struct val *
-op_plus (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a)) {
- if( !extra_error_message_supplied )
- 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(b);
- return (a);
- }
-
- 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 r;
-}
-
-static int
-chk_minus (quad_t a, quad_t b, quad_t r)
-{
- /* special case subtraction of QUAD_MIN */
- if (b == QUAD_MIN) {
- if (a >= 0)
- return 1;
- else
- return 0;
- }
- /* this is allowed for b != QUAD_MIN */
- return chk_plus (a, -b, r);
-}
-
-static struct val *
-op_minus (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a)) {
- if( !extra_error_message_supplied )
- 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)) {
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- free_value(b);
- return (a);
- }
-
- 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);
- return r;
-}
-
-static struct val *
-op_negate (struct val *a)
-{
- struct val *r;
-
- if (!to_integer (a) ) {
- free_value(a);
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- return make_integer(0);
- }
-
- r = make_integer (/*(quad_t)*/(- a->u.i));
- if (chk_minus (0, a->u.i, r->u.i)) {
- ast_log(LOG_WARNING, "overflow\n");
- }
- free_value (a);
- return r;
-}
-
-static struct val *
-op_compl (struct val *a)
-{
- int v1 = 1;
- struct val *r;
-
- if( !a )
- {
- v1 = 0;
- }
- else
- {
- switch( a->type )
- {
- case AST_EXPR_integer:
- if( a->u.i == 0 )
- v1 = 0;
- break;
-
- case AST_EXPR_string:
- if( a->u.s == 0 )
- v1 = 0;
- else
- {
- if( a->u.s[0] == 0 )
- v1 = 0;
- else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
- v1 = 0;
- }
- break;
-
- case AST_EXPR_numeric_string:
- if( a->u.s == 0 )
- v1 = 0;
- else
- {
- if( a->u.s[0] == 0 )
- v1 = 0;
- else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
- v1 = 0;
- }
- break;
- }
- }
-
- r = make_integer (!v1);
- free_value (a);
- return r;
-}
-
-static int
-chk_times (quad_t a, quad_t b, quad_t r)
-{
- /* special case: first operand is 0, no overflow possible */
- if (a == 0)
- return 0;
- /* cerify that result of division matches second operand */
- if (r / a != b)
- return 1;
- return 0;
-}
-
-static struct val *
-op_times (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a) || !to_integer (b)) {
- free_value(a);
- free_value(b);
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- return(make_integer(0));
- }
-
- 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 (r);
-}
-
-static int
-chk_div (quad_t a, quad_t b)
-{
- /* div by zero has been taken care of before */
- /* only QUAD_MIN / -1 causes overflow */
- if (a == QUAD_MIN && b == -1)
- return 1;
- /* everything else is OK */
- return 0;
-}
-
-static struct val *
-op_div (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a)) {
- free_value(a);
- free_value(b);
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- return make_integer(0);
- } else if (!to_integer (b)) {
- free_value(a);
- free_value(b);
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- return make_integer(INT_MAX);
- }
-
- if (b->u.i == 0) {
- ast_log(LOG_WARNING, "division by zero\n");
- free_value(a);
- free_value(b);
- return make_integer(INT_MAX);
- }
-
- 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 r;
-}
-
-static struct val *
-op_rem (struct val *a, struct val *b)
-{
- struct val *r;
-
- if (!to_integer (a) || !to_integer (b)) {
- if( !extra_error_message_supplied )
- ast_log(LOG_WARNING, "non-numeric argument\n");
- free_value(a);
- free_value(b);
- return make_integer(0);
- }
-
- if (b->u.i == 0) {
- ast_log(LOG_WARNING, "div by zero\n");
- free_value(a);
- return(b);
- }
-
- r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
- /* chk_rem necessary ??? */
- free_value (a);
- free_value (b);
- return r;
-}
-
-
-static struct val *
-op_colon (struct val *a, struct val *b)
-{
- regex_t rp;
- regmatch_t rm[2];
- char errbuf[256];
- int eval;
- struct val *v;
-
- /* coerce to both arguments to strings */
- to_string(a);
- to_string(b);
- /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
- strip_quotes(a);
- strip_quotes(b);
- /* compile regular expression */
- if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
- regerror (eval, &rp, errbuf, sizeof(errbuf));
- ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
- free_value(a);
- free_value(b);
- return make_str("");
- }
-
- /* compare string against pattern */
- /* remember that patterns are anchored to the beginning of the line */
- if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
- if (rm[1].rm_so >= 0) {
- *(a->u.s + rm[1].rm_eo) = '\0';
- v = make_str (a->u.s + rm[1].rm_so);
-
- } else {
- v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
- }
- } else {
- if (rp.re_nsub == 0) {
- v = make_integer ((quad_t)0);
- } else {
- v = make_str ("");
- }
- }
-
- /* free arguments and pattern buffer */
- free_value (a);
- free_value (b);
- regfree (&rp);
-
- return v;
-}
-
-
-static struct val *
-op_eqtilde (struct val *a, struct val *b)
-{
- regex_t rp;
- regmatch_t rm[2];
- char errbuf[256];
- int eval;
- struct val *v;
-
- /* coerce to both arguments to strings */
- to_string(a);
- to_string(b);
- /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
- strip_quotes(a);
- strip_quotes(b);
- /* compile regular expression */
- if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
- regerror (eval, &rp, errbuf, sizeof(errbuf));
- ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
- free_value(a);
- free_value(b);
- return make_str("");
- }
-
- /* compare string against pattern */
- /* remember that patterns are anchored to the beginning of the line */
- if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 ) {
- if (rm[1].rm_so >= 0) {
- *(a->u.s + rm[1].rm_eo) = '\0';
- v = make_str (a->u.s + rm[1].rm_so);
-
- } else {
- v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
- }
- } else {
- if (rp.re_nsub == 0) {
- v = make_integer ((quad_t)0);
- } else {
- v = make_str ("");
- }
- }
-
- /* free arguments and pattern buffer */
- free_value (a);
- free_value (b);
- regfree (&rp);
-
- return v;
-}
diff --git a/main/ast_expr2f.c b/main/ast_expr2f.c
deleted file mode 100644
index 8cc75cfd5..000000000
--- a/main/ast_expr2f.c
+++ /dev/null
@@ -1,3349 +0,0 @@
-#line 2 "ast_expr2f.c"
-
-#line 4 "ast_expr2f.c"
-
-#define YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index. If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
- are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Enter a start condition. This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yyg->yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state. The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yyg->yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE ast_yyrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
- #define YY_LESS_LINENO(n)
-
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- int yyless_macro_arg = (n); \
- YY_LESS_LINENO(yyless_macro_arg);\
- *yy_cp = yyg->yy_hold_char; \
- YY_RESTORE_YY_MORE_OFFSET \
- yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
- YY_DO_BEFORE_ACTION; /* set up yytext again */ \
- } \
- while ( 0 )
-
-#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
- {
- FILE *yy_input_file;
-
- char *yy_ch_buf; /* input buffer */
- char *yy_buf_pos; /* current position in input buffer */
-
- /* Size of input buffer in bytes, not including room for EOB
- * characters.
- */
- yy_size_t yy_buf_size;
-
- /* Number of characters read into yy_ch_buf, not including EOB
- * characters.
- */
- int yy_n_chars;
-
- /* Whether we "own" the buffer - i.e., we know we created it,
- * and can realloc() it to grow it, and should free() it to
- * delete it.
- */
- int yy_is_our_buffer;
-
- /* Whether this is an "interactive" input source; if so, and
- * if we're using stdio for input, then we want to use getc()
- * instead of fread(), to make sure we stop fetching input after
- * each newline.
- */
- int yy_is_interactive;
-
- /* Whether we're considered to be at the beginning of a line.
- * If so, '^' rules will be active on the next match, otherwise
- * not.
- */
- int yy_at_bol;
-
- int yy_bs_lineno; /**< The line count. */
- int yy_bs_column; /**< The column count. */
-
- /* Whether to try to fill the input buffer when we reach the
- * end of it.
- */
- int yy_fill_buffer;
-
- int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
- /* When an EOF's been seen but there's still some text to process
- * then we mark the buffer as YY_EOF_PENDING, to indicate that we
- * shouldn't try reading from the input source any more. We might
- * still have a bunch of tokens to match, though, because of
- * possible backing-up.
- *
- * When we actually see the EOF, we change the status to "new"
- * (via ast_yyrestart()), so that the user can continue scanning by
- * just pointing yyin at a new input file.
- */
-#define YY_BUFFER_EOF_PENDING 2
-
- };
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
- ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
- : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-
-void ast_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void ast_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE ast_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void ast_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void ast_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void ast_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void ast_yypop_buffer_state (yyscan_t yyscanner );
-
-static void ast_yyensure_buffer_stack (yyscan_t yyscanner );
-static void ast_yy_load_buffer_state (yyscan_t yyscanner );
-static void ast_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER ast_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE ast_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE ast_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE ast_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-
-void *ast_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *ast_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void ast_yyfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer ast_yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
- { \
- if ( ! YY_CURRENT_BUFFER ){ \
- ast_yyensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
- ast_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
- } \
- YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
- }
-
-#define yy_set_bol(at_bol) \
- { \
- if ( ! YY_CURRENT_BUFFER ){\
- ast_yyensure_buffer_stack (yyscanner); \
- YY_CURRENT_BUFFER_LVALUE = \
- ast_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
- } \
- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
- }
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define ast_yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef char YY_CHAR;
-
-typedef int yy_state_type;
-
-#define yytext_ptr yytext_r
-static yyconst flex_int16_t yy_nxt[][128] =
- {
- {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- },
-
- {
- 7, 8, 8, 8, 8, 8, 8, 8, 8, 9,
- 10, 8, 8, 9, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 9, 11, 12, 13, 14, 15, 16, 13,
- 17, 18, 19, 20, 13, 21, 13, 22, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 24, 13,
- 25, 26, 27, 28, 13, 13, 13, 13, 13, 13,
-
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 8, 13, 8, 13, 13, 8, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 8, 29, 8, 8, 8
- },
-
- {
- 7, 8, 8, 8, 8, 8, 8, 8, 8, 9,
- 10, 8, 8, 9, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 9, 11, 12, 13, 14, 15, 16, 13,
-
- 17, 18, 19, 20, 13, 21, 13, 22, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 24, 13,
- 25, 26, 27, 28, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 8, 13, 8, 13, 13, 8, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 8, 29, 8, 8, 8
- },
-
- {
- 7, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 31, 30, 32, 30, 30
- },
-
- {
- 7, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 31, 30, 32, 30, 30
- },
-
- {
- 7, 33, 33, 33, 33, 33, 33, 33, 33, 34,
- 34, 33, 33, 34, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 34, 34, 33, 33, 35, 34, 34, 33,
- 34, 34, 34, 34, 33, 34, 33, 34, 33, 33,
-
- 33, 33, 33, 33, 33, 33, 33, 33, 34, 33,
- 34, 34, 34, 34, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 34, 33, 33, 33
- },
-
- {
- 7, 33, 33, 33, 33, 33, 33, 33, 33, 34,
- 34, 33, 33, 34, 33, 33, 33, 33, 33, 33,
-
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 34, 34, 33, 33, 35, 34, 34, 33,
- 34, 34, 34, 34, 33, 34, 33, 34, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 34, 33,
- 34, 34, 34, 34, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
-
- 33, 33, 33, 33, 34, 33, 33, 33
- },
-
- {
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
-
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
- -7, -7, -7, -7, -7, -7, -7, -7
- },
-
- {
- 7, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
-
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, -8, -8
- },
-
- {
- 7, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
-
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
- -9, -9, -9, -9, -9, -9, -9, -9
-
- },
-
- {
- 7, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
-
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
- -10, -10, -10, -10, -10, -10, -10, -10
- },
-
- {
- 7, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, 36, -11, -11, -11, -11, -11, -11, -11, -11,
-
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11, -11, -11,
- -11, -11, -11, -11, -11, -11, -11, -11
- },
-
- {
- 7, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 38, 37, 37, 37, 37, 37,
-
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37
- },
-
- {
- 7, -13, -13, -13, -13, -13, -13, -13, -13, -13,
-
- -13, -13, -13, -13, -13, -13, -13, -13, -13, -13,
- -13, -13, -13, -13, -13, -13, -13, -13, -13, -13,
- -13, -13, -13, -13, -13, 39, 39, -13, -13, 39,
- -13, -13, -13, -13, 39, -13, 39, -13, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, -13, 39,
- -13, -13, -13, -13, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, -13, 39, -13, 39, 39, -13, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
-
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, -13, -13, -13, -13, -13
- },
-
- {
- 7, -14, -14, -14, -14, -14, -14, -14, -14, -14,
- -14, -14, -14, -14, -14, -14, -14, -14, -14, -14,
- -14, -14, -14, -14, -14, -14, -14, -14, -14, -14,
- -14, -14, -14, -14, -14, 39, 39, -14, -14, 39,
- -14, -14, -14, -14, 39, -14, 39, -14, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, -14, 39,
- -14, -14, -14, -14, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
-
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, -14, 39, -14, 39, 39, -14, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 40, -14, -14, -14, -14
- },
-
- {
- 7, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
-
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
- -15, -15, -15, -15, -15, -15, -15, -15
- },
-
- {
- 7, -16, -16, -16, -16, -16, -16, -16, -16, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
-
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, 41, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
- -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
-
- -16, -16, -16, -16, -16, -16, -16, -16
- },
-
- {
- 7, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
-
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17, -17, -17,
- -17, -17, -17, -17, -17, -17, -17, -17
- },
-
- {
- 7, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
-
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18, -18, -18,
- -18, -18, -18, -18, -18, -18, -18, -18
- },
-
- {
- 7, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
-
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
- -19, -19, -19, -19, -19, -19, -19, -19
-
- },
-
- {
- 7, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
-
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
- -20, -20, -20, -20, -20, -20, -20, -20
- },
-
- {
- 7, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
-
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21, -21, -21,
- -21, -21, -21, -21, -21, -21, -21, -21
- },
-
- {
- 7, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
-
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22, -22, -22,
- -22, -22, -22, -22, -22, -22, -22, -22
- },
-
- {
- 7, -23, -23, -23, -23, -23, -23, -23, -23, -23,
-
- -23, -23, -23, -23, -23, -23, -23, -23, -23, -23,
- -23, -23, -23, -23, -23, -23, -23, -23, -23, -23,
- -23, -23, -23, -23, -23, 39, 39, -23, -23, 39,
- -23, -23, -23, -23, 39, -23, 39, -23, 42, 42,
- 42, 42, 42, 42, 42, 42, 42, 42, -23, 39,
- -23, -23, -23, -23, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, -23, 39, -23, 39, 39, -23, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
-
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, -23, -23, -23, -23, -23
- },
-
- {
- 7, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, 43, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
-
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
- -24, -24, -24, -24, -24, -24, -24, -24
- },
-
- {
- 7, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
-
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, 44, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
- -25, -25, -25, -25, -25, -25, -25, -25
- },
-
- {
- 7, -26, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
-
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, 45, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
- -26, -26, -26, -26, -26, -26, -26, -26, -26, -26,
-
- -26, -26, -26, -26, -26, -26, 46, -26
- },
-
- {
- 7, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, 47, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
-
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27, -27, -27,
- -27, -27, -27, -27, -27, -27, -27, -27
- },
-
- {
- 7, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
-
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28, -28, -28,
- -28, -28, -28, -28, -28, -28, -28, -28
- },
-
- {
- 7, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
-
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, -29, -29, -29, -29, -29, -29,
- -29, -29, -29, -29, 48, -29, -29, -29
-
- },
-
- {
- 7, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 50, 49, 51, 49, 49
- },
-
- {
- 7, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
-
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31, -31, -31,
- -31, -31, -31, -31, -31, -31, -31, -31
- },
-
- {
- 7, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
-
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
- -32, -32, -32, -32, -32, -32, -32, -32
- },
-
- {
- 7, 52, 52, 52, 52, 52, 52, 52, 52, -33,
-
- -33, 52, 52, -33, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, -33, -33, 52, 52, -33, -33, -33, 52,
- -33, -33, -33, -33, 52, -33, 52, -33, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, -33, 52,
- -33, -33, -33, -33, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, -33, 52, 52, 52
- },
-
- {
- 7, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
-
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34, -34, -34,
- -34, -34, -34, -34, -34, -34, -34, -34
- },
-
- {
- 7, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
-
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -35,
- -35, -35, -35, 53, -35, -35, -35, -35
- },
-
- {
- 7, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
-
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
- -36, -36, -36, -36, -36, -36, -36, -36, -36, -36,
-
- -36, -36, -36, -36, -36, -36, -36, -36
- },
-
- {
- 7, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 38, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37
- },
-
- {
- 7, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
-
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38, -38, -38,
- -38, -38, -38, -38, -38, -38, -38, -38
- },
-
- {
- 7, -39, -39, -39, -39, -39, -39, -39, -39, -39,
- -39, -39, -39, -39, -39, -39, -39, -39, -39, -39,
- -39, -39, -39, -39, -39, -39, -39, -39, -39, -39,
-
- -39, -39, -39, -39, -39, 39, 39, -39, -39, 39,
- -39, -39, -39, -39, 39, -39, 39, -39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, -39, 39,
- -39, -39, -39, -39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, -39, 39, -39, 39, 39, -39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, -39, -39, -39, -39, -39
-
- },
-
- {
- 7, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
-
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40, -40, -40,
- -40, -40, -40, -40, -40, -40, -40, -40
- },
-
- {
- 7, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
-
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41, -41, -41,
- -41, -41, -41, -41, -41, -41, -41, -41
- },
-
- {
- 7, -42, -42, -42, -42, -42, -42, -42, -42, -42,
- -42, -42, -42, -42, -42, -42, -42, -42, -42, -42,
- -42, -42, -42, -42, -42, -42, -42, -42, -42, -42,
- -42, -42, -42, -42, -42, 39, 39, -42, -42, 39,
-
- -42, -42, -42, -42, 39, -42, 39, -42, 42, 42,
- 42, 42, 42, 42, 42, 42, 42, 42, -42, 39,
- -42, -42, -42, -42, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, -42, 39, -42, 39, 39, -42, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, -42, -42, -42, -42, -42
- },
-
- {
- 7, -43, -43, -43, -43, -43, -43, -43, -43, -43,
-
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
-
- -43, -43, -43, -43, -43, -43, -43, -43, -43, -43,
- -43, -43, -43, -43, -43, -43, -43, -43
- },
-
- {
- 7, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
-
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44, -44, -44,
- -44, -44, -44, -44, -44, -44, -44, -44
- },
-
- {
- 7, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
-
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45, -45, -45,
- -45, -45, -45, -45, -45, -45, -45, -45
- },
-
- {
- 7, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
-
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
- -46, -46, -46, -46, -46, -46, -46, -46, -46, -46,
-
- -46, -46, -46, -46, -46, -46, -46, -46
- },
-
- {
- 7, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
-
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
- -47, -47, -47, -47, -47, -47, -47, -47
- },
-
- {
- 7, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
-
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48, -48, -48,
- -48, -48, -48, -48, -48, -48, -48, -48
- },
-
- {
- 7, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 50, 49, 51, 49, 49
-
- },
-
- {
- 7, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
-
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50, -50, -50,
- -50, -50, -50, -50, -50, -50, -50, -50
- },
-
- {
- 7, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
-
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
- -51, -51, -51, -51, -51, -51, -51, -51
- },
-
- {
- 7, 52, 52, 52, 52, 52, 52, 52, 52, -52,
- -52, 52, 52, -52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, -52, -52, 52, 52, -52, -52, -52, 52,
-
- -52, -52, -52, -52, 52, -52, 52, -52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, -52, 52,
- -52, -52, -52, -52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, -52, 52, 52, 52
- },
-
- {
- 7, -53, -53, -53, -53, -53, -53, -53, -53, -53,
-
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
-
- -53, -53, -53, -53, -53, -53, -53, -53, -53, -53,
- -53, -53, -53, -53, -53, -53, -53, -53
- },
-
- } ;
-
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
- yyg->yytext_ptr = yy_bp; \
- yyg->yytext_ptr -= yyg->yy_more_len; \
- yyleng = (size_t) (yy_cp - yyg->yytext_ptr); \
- yyg->yy_hold_char = *yy_cp; \
- *yy_cp = '\0'; \
- yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 35
-#define YY_END_OF_BUFFER 36
-/* This struct is not used in this scanner,
- but its presence is necessary. */
-struct yy_trans_info
- {
- flex_int32_t yy_verify;
- flex_int32_t yy_nxt;
- };
-static yyconst flex_int16_t yy_accept[54] =
- { 0,
- 0, 0, 0, 0, 32, 32, 36, 35, 25, 27,
- 19, 35, 29, 29, 17, 2, 22, 23, 15, 13,
- 14, 16, 28, 20, 9, 3, 8, 18, 1, 35,
- 31, 30, 32, 33, 33, 12, 0, 26, 29, 24,
- 5, 28, 21, 11, 6, 7, 10, 4, 0, 31,
- 30, 32, 34
- } ;
-
-static yyconst yy_state_type yy_NUL_trans[54] =
- { 0,
- 8, 8, 30, 30, 33, 33, 0, 0, 0, 0,
- 0, 37, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 49,
- 0, 0, 52, 0, 0, 0, 37, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 49, 0,
- 0, 52, 0
- } ;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() (yyg->yy_more_flag = 1)
-#define YY_MORE_ADJ yyg->yy_more_len
-#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "ast_expr2.fl"
-#line 2 "ast_expr2.fl"
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Dialplan Expression Lexical Scanner
- */
-
-#include "asterisk.h"
-
-#if !defined(STANDALONE_AEL)
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#endif
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <locale.h>
-#include <ctype.h>
-#if !defined(SOLARIS) && !defined(__CYGWIN__)
-/* #include <err.h> */
-#else
-#define quad_t int64_t
-#endif
-#include <errno.h>
-#include <regex.h>
-#include <limits.h>
-
-#include "asterisk/ast_expr.h"
-#include "asterisk/logger.h"
-#include "asterisk/strings.h"
-
-enum valtype {
- AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
-} ;
-
-struct val {
- enum valtype type;
- union {
- char *s;
- quad_t i;
- } u;
-} ;
-
-#include "ast_expr2.h" /* the o/p of the bison on ast_expr2.y */
-
-#define SET_COLUMNS do { \
- yylloc_param->first_column = (int)(yyg->yytext_r - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf); \
- yylloc_param->last_column += yyleng - 1; \
- yylloc_param->first_line = yylloc_param->last_line = 1; \
- } while (0)
-
-#define SET_STRING do { \
- yylval_param->val = calloc(1, sizeof(struct val)); \
- yylval_param->val->type = AST_EXPR_string; \
- yylval_param->val->u.s = strdup(yytext); \
- } while (0)
-
-#define SET_NUMERIC_STRING do { \
- yylval_param->val = calloc(1, sizeof(struct val)); \
- yylval_param->val->type = AST_EXPR_numeric_string; \
- yylval_param->val->u.s = strdup(yytext); \
- } while (0)
-
-struct parse_io
-{
- char *string;
- struct val *val;
- yyscan_t scanner;
-};
-
-void ast_yyset_column(int column_no, yyscan_t yyscanner);
-int ast_yyget_column(yyscan_t yyscanner);
-static int curlycount = 0;
-static char *expr2_token_subst(const char *mess);
-
-#line 1422 "ast_expr2f.c"
-
-#define INITIAL 0
-#define var 1
-#define trail 2
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-/* Holds the entire state of the reentrant scanner. */
-struct yyguts_t
- {
-
- /* User-defined. Not touched by flex. */
- YY_EXTRA_TYPE yyextra_r;
-
- /* The rest are the same as the globals declared in the non-reentrant scanner. */
- FILE *yyin_r, *yyout_r;
- size_t yy_buffer_stack_top; /**< index of top of stack. */
- size_t yy_buffer_stack_max; /**< capacity of stack. */
- YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
- char yy_hold_char;
- int yy_n_chars;
- int yyleng_r;
- char *yy_c_buf_p;
- int yy_init;
- int yy_start;
- int yy_did_buffer_switch_on_eof;
- int yy_start_stack_ptr;
- int yy_start_stack_depth;
- int *yy_start_stack;
- yy_state_type yy_last_accepting_state;
- char* yy_last_accepting_cpos;
-
- int yylineno_r;
- int yy_flex_debug_r;
-
- char *yytext_r;
- int yy_more_flag;
- int yy_more_len;
-
- YYSTYPE * yylval_r;
-
- YYLTYPE * yylloc_r;
-
- }; /* end struct yyguts_t */
-
-static int yy_init_globals (yyscan_t yyscanner );
-
- /* This must go here because YYSTYPE and YYLTYPE are included
- * from bison output in section 1.*/
- # define yylval yyg->yylval_r
-
- # define yylloc yyg->yylloc_r
-
-int ast_yylex_init (yyscan_t* scanner);
-
-int ast_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
- These are made visible to non-reentrant scanners for convenience. */
-
-int ast_yylex_destroy (yyscan_t yyscanner );
-
-int ast_yyget_debug (yyscan_t yyscanner );
-
-void ast_yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE ast_yyget_extra (yyscan_t yyscanner );
-
-void ast_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *ast_yyget_in (yyscan_t yyscanner );
-
-void ast_yyset_in (FILE * in_str ,yyscan_t yyscanner );
-
-FILE *ast_yyget_out (yyscan_t yyscanner );
-
-void ast_yyset_out (FILE * out_str ,yyscan_t yyscanner );
-
-int ast_yyget_leng (yyscan_t yyscanner );
-
-char *ast_yyget_text (yyscan_t yyscanner );
-
-int ast_yyget_lineno (yyscan_t yyscanner );
-
-void ast_yyset_lineno (int line_number ,yyscan_t yyscanner );
-
-YYSTYPE * ast_yyget_lval (yyscan_t yyscanner );
-
-void ast_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
-
- YYLTYPE *ast_yyget_lloc (yyscan_t yyscanner );
-
- void ast_yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int ast_yywrap (yyscan_t yyscanner );
-#else
-extern int ast_yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
- static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
-#else
-static int input (yyscan_t yyscanner );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
- errno=0; \
- while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
- { \
- if( errno != EINTR) \
- { \
- YY_FATAL_ERROR( "input in flex scanner failed" ); \
- break; \
- } \
- errno=0; \
- clearerr(yyin); \
- }\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int ast_yylex \
- (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
-
-#define YY_DECL int ast_yylex \
- (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
- YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-#line 105 "ast_expr2.fl"
-
-
-#line 1652 "ast_expr2f.c"
-
- yylval = yylval_param;
-
- yylloc = yylloc_param;
-
- if ( !yyg->yy_init )
- {
- yyg->yy_init = 1;
-
-#ifdef YY_USER_INIT
- YY_USER_INIT;
-#endif
-
- if ( ! yyg->yy_start )
- yyg->yy_start = 1; /* first start state */
-
- if ( ! yyin )
- yyin = stdin;
-
- if ( ! yyout )
- yyout = stdout;
-
- if ( ! YY_CURRENT_BUFFER ) {
- ast_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- ast_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- ast_yy_load_buffer_state(yyscanner );
- }
-
- while ( 1 ) /* loops until end-of-file is reached */
- {
- yyg->yy_more_len = 0;
- if ( yyg->yy_more_flag )
- {
- yyg->yy_more_len = yyg->yy_c_buf_p - yyg->yytext_ptr;
- yyg->yy_more_flag = 0;
- }
- yy_cp = yyg->yy_c_buf_p;
-
- /* Support of yytext. */
- *yy_cp = yyg->yy_hold_char;
-
- /* yy_bp points to the position in yy_ch_buf of the start of
- * the current run.
- */
- yy_bp = yy_cp;
-
- yy_current_state = yyg->yy_start;
-yy_match:
- while ( (yy_current_state = yy_nxt[yy_current_state][ YY_SC_TO_UI(*yy_cp) ]) > 0 )
- {
- if ( yy_accept[yy_current_state] )
- {
- yyg->yy_last_accepting_state = yy_current_state;
- yyg->yy_last_accepting_cpos = yy_cp;
- }
-
- ++yy_cp;
- }
-
- yy_current_state = -yy_current_state;
-
-yy_find_action:
- yy_act = yy_accept[yy_current_state];
-
- YY_DO_BEFORE_ACTION;
-
-do_action: /* This label is used only to access EOF actions. */
-
- switch ( yy_act )
- { /* beginning of action switch */
- case 0: /* must back up */
- /* undo the effects of YY_DO_BEFORE_ACTION */
- *yy_cp = yyg->yy_hold_char;
- yy_cp = yyg->yy_last_accepting_cpos + 1;
- yy_current_state = yyg->yy_last_accepting_state;
- goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 107 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_OR;}
- YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 108 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_AND;}
- YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 109 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_EQ;}
- YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 110 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_OR;}
- YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 111 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_AND;}
- YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 112 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_EQ;}
- YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 113 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_EQTILDE;}
- YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 114 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_GT;}
- YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 115 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_LT;}
- YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 116 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_GE;}
- YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 117 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_LE;}
- YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 118 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_NE;}
- YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 119 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_PLUS;}
- YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 120 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_MINUS;}
- YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 121 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_MULT;}
- YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 122 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_DIV;}
- YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 123 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_MOD;}
- YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 124 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_COND;}
- YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 125 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_COMPL;}
- YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 126 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_COLON;}
- YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 127 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
- YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 128 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_LP;}
- YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 129 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_RP;}
- YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 130 "ast_expr2.fl"
-{
- /* gather the contents of ${} expressions, with trailing stuff,
- * into a single TOKEN.
- * They are much more complex now than they used to be
- */
- curlycount = 0;
- BEGIN(var);
- yymore();
- }
- YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 140 "ast_expr2.fl"
-{}
- YY_BREAK
-case 26:
-/* rule 26 can match eol */
-YY_RULE_SETUP
-#line 141 "ast_expr2.fl"
-{SET_COLUMNS; SET_STRING; return TOKEN;}
- YY_BREAK
-case 27:
-/* rule 27 can match eol */
-YY_RULE_SETUP
-#line 143 "ast_expr2.fl"
-{/* what to do with eol */}
- YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 144 "ast_expr2.fl"
-{
- SET_COLUMNS;
- /* the original behavior of the expression parser was
- * to bring in numbers as a numeric string
- */
- SET_NUMERIC_STRING;
- return TOKEN;
- }
- YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 153 "ast_expr2.fl"
-{
- SET_COLUMNS;
- SET_STRING;
- return TOKEN;
- }
- YY_BREAK
-case 30:
-/* rule 30 can match eol */
-YY_RULE_SETUP
-#line 160 "ast_expr2.fl"
-{
- curlycount--;
- if (curlycount < 0) {
- BEGIN(trail);
- yymore();
- } else {
- yymore();
- }
- }
- YY_BREAK
-case 31:
-/* rule 31 can match eol */
-YY_RULE_SETUP
-#line 170 "ast_expr2.fl"
-{
- curlycount++;
- yymore();
- }
- YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 176 "ast_expr2.fl"
-{
- BEGIN(0);
- SET_COLUMNS;
- SET_STRING;
- return TOKEN;
- }
- YY_BREAK
-case 33:
-/* rule 33 can match eol */
-YY_RULE_SETUP
-#line 183 "ast_expr2.fl"
-{
- char c = yytext[yyleng-1];
- BEGIN(0);
- unput(c);
- SET_COLUMNS;
- SET_STRING;
- return TOKEN;
- }
- YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 192 "ast_expr2.fl"
-{
- curlycount = 0;
- BEGIN(var);
- yymore();
- }
- YY_BREAK
-case YY_STATE_EOF(trail):
-#line 198 "ast_expr2.fl"
-{
- BEGIN(0);
- SET_COLUMNS;
- SET_STRING;
- return TOKEN;
- /*actually, if an expr is only a variable ref, this could happen a LOT */
- }
- YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 206 "ast_expr2.fl"
-ECHO;
- YY_BREAK
-#line 1969 "ast_expr2f.c"
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(var):
- yyterminate();
-
- case YY_END_OF_BUFFER:
- {
- /* Amount of text matched not including the EOB char. */
- int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
-
- /* Undo the effects of YY_DO_BEFORE_ACTION. */
- *yy_cp = yyg->yy_hold_char;
- YY_RESTORE_YY_MORE_OFFSET
-
- if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
- {
- /* We're scanning a new file or input source. It's
- * possible that this happened because the user
- * just pointed yyin at a new source and called
- * ast_yylex(). If so, then we have to assure
- * consistency between YY_CURRENT_BUFFER and our
- * globals. Here is the right place to do so, because
- * this is the first action (other than possibly a
- * back-up) that will match for the new input source.
- */
- yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
- YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
- YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
- }
-
- /* Note that here we test for yy_c_buf_p "<=" to the position
- * of the first EOB in the buffer, since yy_c_buf_p will
- * already have been incremented past the NUL character
- * (since all states make transitions on EOB to the
- * end-of-buffer state). Contrast this with the test
- * in input().
- */
- if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
- { /* This was really a NUL. */
- yy_state_type yy_next_state;
-
- yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
- yy_current_state = yy_get_previous_state( yyscanner );
-
- /* Okay, we're now positioned to make the NUL
- * transition. We couldn't have
- * yy_get_previous_state() go ahead and do it
- * for us because it doesn't know how to deal
- * with the possibility of jamming (and we don't
- * want to build jamming into it because then it
- * will run more slowly).
- */
-
- yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
-
- yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-
- if ( yy_next_state )
- {
- /* Consume the NUL. */
- yy_cp = ++yyg->yy_c_buf_p;
- yy_current_state = yy_next_state;
- goto yy_match;
- }
-
- else
- {
- yy_cp = yyg->yy_c_buf_p;
- goto yy_find_action;
- }
- }
-
- else switch ( yy_get_next_buffer( yyscanner ) )
- {
- case EOB_ACT_END_OF_FILE:
- {
- yyg->yy_did_buffer_switch_on_eof = 0;
-
- if ( ast_yywrap(yyscanner ) )
- {
- /* Note: because we've taken care in
- * yy_get_next_buffer() to have set up
- * yytext, we can now set up
- * yy_c_buf_p so that if some total
- * hoser (like flex itself) wants to
- * call the scanner after we return the
- * YY_NULL, it'll still work - another
- * YY_NULL will get returned.
- */
- yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
-
- yy_act = YY_STATE_EOF(YY_START);
- goto do_action;
- }
-
- else
- {
- if ( ! yyg->yy_did_buffer_switch_on_eof )
- YY_NEW_FILE;
- }
- break;
- }
-
- case EOB_ACT_CONTINUE_SCAN:
- yyg->yy_c_buf_p =
- yyg->yytext_ptr + yy_amount_of_matched_text;
-
- yy_current_state = yy_get_previous_state( yyscanner );
-
- yy_cp = yyg->yy_c_buf_p;
- yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
- goto yy_match;
-
- case EOB_ACT_LAST_MATCH:
- yyg->yy_c_buf_p =
- &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
-
- yy_current_state = yy_get_previous_state( yyscanner );
-
- yy_cp = yyg->yy_c_buf_p;
- yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
- goto yy_find_action;
- }
- break;
- }
-
- default:
- YY_FATAL_ERROR(
- "fatal flex scanner internal error--no action found" );
- } /* end of action switch */
- } /* end of scanning one token */
-} /* end of ast_yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- * EOB_ACT_LAST_MATCH -
- * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- * EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = yyg->yytext_ptr;
- register int number_to_move, i;
- int ret_val;
-
- if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
- YY_FATAL_ERROR(
- "fatal flex scanner internal error--end of buffer missed" );
-
- if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
- { /* Don't try to fill the buffer, so this is an EOF. */
- if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
- {
- /* We matched a single character, the EOB, so
- * treat this as a final EOF.
- */
- return EOB_ACT_END_OF_FILE;
- }
-
- else
- {
- /* We matched some text prior to the EOB, first
- * process it.
- */
- return EOB_ACT_LAST_MATCH;
- }
- }
-
- /* Try to read more data. */
-
- /* First move last chars to start of buffer. */
- number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
-
- for ( i = 0; i < number_to_move; ++i )
- *(dest++) = *(source++);
-
- if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
- /* don't do the read, it's not guaranteed to return an EOF,
- * just force an EOF
- */
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
-
- else
- {
- int num_to_read =
- YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
- while ( num_to_read <= 0 )
- { /* Not enough room in the buffer - grow it. */
-
- /* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
- int yy_c_buf_p_offset =
- (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
-
- if ( b->yy_is_our_buffer )
- {
- int new_size = b->yy_buf_size * 2;
-
- if ( new_size <= 0 )
- b->yy_buf_size += b->yy_buf_size / 8;
- else
- b->yy_buf_size *= 2;
-
- b->yy_ch_buf = (char *)
- /* Include room in for 2 EOB chars. */
- ast_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
- }
- else
- /* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
-
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR(
- "fatal error - scanner input buffer overflow" );
-
- yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
- num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
- number_to_move - 1;
-
- }
-
- if ( num_to_read > YY_READ_BUF_SIZE )
- num_to_read = YY_READ_BUF_SIZE;
-
- /* Read in more data. */
- YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
- yyg->yy_n_chars, (size_t) num_to_read );
-
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
- }
-
- if ( yyg->yy_n_chars == 0 )
- {
- if ( number_to_move == YY_MORE_ADJ )
- {
- ret_val = EOB_ACT_END_OF_FILE;
- ast_yyrestart(yyin ,yyscanner);
- }
-
- else
- {
- ret_val = EOB_ACT_LAST_MATCH;
- YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
- YY_BUFFER_EOF_PENDING;
- }
- }
-
- else
- ret_val = EOB_ACT_CONTINUE_SCAN;
-
- if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
- /* Extend the array by 50%, plus the number we really need. */
- yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) ast_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
- if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
- }
-
- yyg->yy_n_chars += number_to_move;
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
- yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
- return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
- static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
-{
- register yy_state_type yy_current_state;
- register char *yy_cp;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- yy_current_state = yyg->yy_start;
-
- for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
- {
- if ( *yy_cp )
- {
- yy_current_state = yy_nxt[yy_current_state][YY_SC_TO_UI(*yy_cp)];
- }
- else
- yy_current_state = yy_NUL_trans[yy_current_state];
- if ( yy_accept[yy_current_state] )
- {
- yyg->yy_last_accepting_state = yy_current_state;
- yyg->yy_last_accepting_cpos = yy_cp;
- }
- }
-
- return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- * next_state = yy_try_NUL_trans( current_state );
- */
- static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
-{
- register int yy_is_jam;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
- register char *yy_cp = yyg->yy_c_buf_p;
-
- yy_current_state = yy_NUL_trans[yy_current_state];
- yy_is_jam = (yy_current_state == 0);
-
- if ( ! yy_is_jam )
- {
- if ( yy_accept[yy_current_state] )
- {
- yyg->yy_last_accepting_state = yy_current_state;
- yyg->yy_last_accepting_cpos = yy_cp;
- }
- }
-
- return yy_is_jam ? 0 : yy_current_state;
-}
-
- static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
-{
- register char *yy_cp;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- yy_cp = yyg->yy_c_buf_p;
-
- /* undo effects of setting up yytext */
- *yy_cp = yyg->yy_hold_char;
-
- if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
- { /* need to shift things up to make room */
- /* +2 for EOB chars. */
- register int number_to_move = yyg->yy_n_chars + 2;
- register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
- YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
- register char *source =
- &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
- while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
- *--dest = *--source;
-
- yy_cp += (int) (dest - source);
- yy_bp += (int) (dest - source);
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
- yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
- if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
- YY_FATAL_ERROR( "flex scanner push-back overflow" );
- }
-
- *--yy_cp = (char) c;
-
- yyg->yytext_ptr = yy_bp;
- yyg->yy_hold_char = *yy_cp;
- yyg->yy_c_buf_p = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
- static int yyinput (yyscan_t yyscanner)
-#else
- static int input (yyscan_t yyscanner)
-#endif
-
-{
- int c;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- *yyg->yy_c_buf_p = yyg->yy_hold_char;
-
- if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
- {
- /* yy_c_buf_p now points to the character we want to return.
- * If this occurs *before* the EOB characters, then it's a
- * valid NUL; if not, then we've hit the end of the buffer.
- */
- if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
- /* This was really a NUL. */
- *yyg->yy_c_buf_p = '\0';
-
- else
- { /* need more input */
- int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
- ++yyg->yy_c_buf_p;
-
- switch ( yy_get_next_buffer( yyscanner ) )
- {
- case EOB_ACT_LAST_MATCH:
- /* This happens because yy_g_n_b()
- * sees that we've accumulated a
- * token and flags that we need to
- * try matching the token before
- * proceeding. But for input(),
- * there's no matching to consider.
- * So convert the EOB_ACT_LAST_MATCH
- * to EOB_ACT_END_OF_FILE.
- */
-
- /* Reset buffer status. */
- ast_yyrestart(yyin ,yyscanner);
-
- /*FALLTHROUGH*/
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( ast_yywrap(yyscanner ) )
- return EOF;
-
- if ( ! yyg->yy_did_buffer_switch_on_eof )
- YY_NEW_FILE;
-#ifdef __cplusplus
- return yyinput(yyscanner);
-#else
- return input(yyscanner);
-#endif
- }
-
- case EOB_ACT_CONTINUE_SCAN:
- yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
- break;
- }
- }
- }
-
- c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
- *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
- yyg->yy_hold_char = *++yyg->yy_c_buf_p;
-
- return c;
-}
-#endif /* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * @param yyscanner The scanner object.
- * @note This function does not reset the start condition to @c INITIAL .
- */
- void ast_yyrestart (FILE * input_file , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if ( ! YY_CURRENT_BUFFER ){
- ast_yyensure_buffer_stack (yyscanner);
- YY_CURRENT_BUFFER_LVALUE =
- ast_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
- }
-
- ast_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- ast_yy_load_buffer_state(yyscanner );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
- void ast_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- /* TODO. We should be able to replace this entire function body
- * with
- * ast_yypop_buffer_state();
- * ast_yypush_buffer_state(new_buffer);
- */
- ast_yyensure_buffer_stack (yyscanner);
- if ( YY_CURRENT_BUFFER == new_buffer )
- return;
-
- if ( YY_CURRENT_BUFFER )
- {
- /* Flush out information for old buffer. */
- *yyg->yy_c_buf_p = yyg->yy_hold_char;
- YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
- }
-
- YY_CURRENT_BUFFER_LVALUE = new_buffer;
- ast_yy_load_buffer_state(yyscanner );
-
- /* We don't actually know whether we did this switch during
- * EOF (ast_yywrap()) processing, but the only time this flag
- * is looked at is after ast_yywrap() is called, so it's safe
- * to go ahead and always set it.
- */
- yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void ast_yy_load_buffer_state (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
- yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
- yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
- yyg->yy_hold_char = *yyg->yy_c_buf_p;
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * @param yyscanner The scanner object.
- * @return the allocated buffer state.
- */
- YY_BUFFER_STATE ast_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
-{
- YY_BUFFER_STATE b;
-
- b = (YY_BUFFER_STATE) ast_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in ast_yy_create_buffer()" );
-
- b->yy_buf_size = size;
-
- /* yy_ch_buf has to be 2 characters longer than the size given because
- * we need to put in 2 end-of-buffer characters.
- */
- b->yy_ch_buf = (char *) ast_yyalloc(b->yy_buf_size + 2 ,yyscanner );
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in ast_yy_create_buffer()" );
-
- b->yy_is_our_buffer = 1;
-
- ast_yy_init_buffer(b,file ,yyscanner);
-
- return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with ast_yy_create_buffer()
- * @param yyscanner The scanner object.
- */
- void ast_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if ( ! b )
- return;
-
- if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
- YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
- if ( b->yy_is_our_buffer )
- ast_yyfree((void *) b->yy_ch_buf ,yyscanner );
-
- ast_yyfree((void *) b ,yyscanner );
-}
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a ast_yyrestart() or at EOF.
- */
- static void ast_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
-
-{
- int oerrno = errno;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- ast_yy_flush_buffer(b ,yyscanner);
-
- b->yy_input_file = file;
- b->yy_fill_buffer = 1;
-
- /* If b is the current buffer, then ast_yy_init_buffer was _probably_
- * called from ast_yyrestart() or through yy_get_next_buffer.
- * In that case, we don't want to reset the lineno or column.
- */
- if (b != YY_CURRENT_BUFFER){
- b->yy_bs_lineno = 1;
- b->yy_bs_column = 0;
- }
-
- b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-
- errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * @param yyscanner The scanner object.
- */
- void ast_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if ( ! b )
- return;
-
- b->yy_n_chars = 0;
-
- /* We always need two end-of-buffer characters. The first causes
- * a transition to the end-of-buffer state. The second causes
- * a jam in that state.
- */
- b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
- b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
- b->yy_buf_pos = &b->yy_ch_buf[0];
-
- b->yy_at_bol = 1;
- b->yy_buffer_status = YY_BUFFER_NEW;
-
- if ( b == YY_CURRENT_BUFFER )
- ast_yy_load_buffer_state(yyscanner );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- * the current state. This function will allocate the stack
- * if necessary.
- * @param new_buffer The new state.
- * @param yyscanner The scanner object.
- */
-void ast_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if (new_buffer == NULL)
- return;
-
- ast_yyensure_buffer_stack(yyscanner);
-
- /* This block is copied from ast_yy_switch_to_buffer. */
- if ( YY_CURRENT_BUFFER )
- {
- /* Flush out information for old buffer. */
- *yyg->yy_c_buf_p = yyg->yy_hold_char;
- YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
- }
-
- /* Only push if top exists. Otherwise, replace top. */
- if (YY_CURRENT_BUFFER)
- yyg->yy_buffer_stack_top++;
- YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
- /* copied from ast_yy_switch_to_buffer. */
- ast_yy_load_buffer_state(yyscanner );
- yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- * The next element becomes the new top.
- * @param yyscanner The scanner object.
- */
-void ast_yypop_buffer_state (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- if (!YY_CURRENT_BUFFER)
- return;
-
- ast_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
- YY_CURRENT_BUFFER_LVALUE = NULL;
- if (yyg->yy_buffer_stack_top > 0)
- --yyg->yy_buffer_stack_top;
-
- if (YY_CURRENT_BUFFER) {
- ast_yy_load_buffer_state(yyscanner );
- yyg->yy_did_buffer_switch_on_eof = 1;
- }
-}
-
-/* Allocates the stack if it does not exist.
- * Guarantees space for at least one push.
- */
-static void ast_yyensure_buffer_stack (yyscan_t yyscanner)
-{
- int num_to_alloc;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if (!yyg->yy_buffer_stack) {
-
- /* First allocation is just for 2 elements, since we don't know if this
- * scanner will even need a stack. We use 2 instead of 1 to avoid an
- * immediate realloc on the next call.
- */
- num_to_alloc = 1;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)ast_yyalloc
- (num_to_alloc * sizeof(struct yy_buffer_state*)
- , yyscanner);
- if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in ast_yyensure_buffer_stack()" );
-
- memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
- yyg->yy_buffer_stack_max = num_to_alloc;
- yyg->yy_buffer_stack_top = 0;
- return;
- }
-
- if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
-
- /* Increase the buffer to prepare for a possible push. */
- int grow_size = 8 /* arbitrary grow size */;
-
- num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)ast_yyrealloc
- (yyg->yy_buffer_stack,
- num_to_alloc * sizeof(struct yy_buffer_state*)
- , yyscanner);
- if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in ast_yyensure_buffer_stack()" );
-
- /* zero only the new slots.*/
- memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
- yyg->yy_buffer_stack_max = num_to_alloc;
- }
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE ast_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
-{
- YY_BUFFER_STATE b;
-
- if ( size < 2 ||
- base[size-2] != YY_END_OF_BUFFER_CHAR ||
- base[size-1] != YY_END_OF_BUFFER_CHAR )
- /* They forgot to leave room for the EOB's. */
- return 0;
-
- b = (YY_BUFFER_STATE) ast_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in ast_yy_scan_buffer()" );
-
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
- b->yy_buf_pos = b->yy_ch_buf = base;
- b->yy_is_our_buffer = 0;
- b->yy_input_file = 0;
- b->yy_n_chars = b->yy_buf_size;
- b->yy_is_interactive = 0;
- b->yy_at_bol = 1;
- b->yy_fill_buffer = 0;
- b->yy_buffer_status = YY_BUFFER_NEW;
-
- ast_yy_switch_to_buffer(b ,yyscanner );
-
- return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to ast_yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- * ast_yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE ast_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-
- return ast_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to ast_yylex() will
- * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE ast_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
-{
- YY_BUFFER_STATE b;
- char *buf;
- yy_size_t n;
- int i;
-
- /* Get memory for full buffer, including space for trailing EOB's. */
- n = _yybytes_len + 2;
- buf = (char *) ast_yyalloc(n ,yyscanner );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in ast_yy_scan_bytes()" );
-
- for ( i = 0; i < _yybytes_len; ++i )
- buf[i] = yybytes[i];
-
- buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
- b = ast_yy_scan_buffer(buf,n ,yyscanner);
- if ( ! b )
- YY_FATAL_ERROR( "bad buffer in ast_yy_scan_bytes()" );
-
- /* It's okay to grow etc. this buffer, and we should throw it
- * away when we're done.
- */
- b->yy_is_our_buffer = 1;
-
- return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
-{
- (void) fprintf( stderr, "%s\n", msg );
- exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- int yyless_macro_arg = (n); \
- YY_LESS_LINENO(yyless_macro_arg);\
- yytext[yyleng] = yyg->yy_hold_char; \
- yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
- yyg->yy_hold_char = *yyg->yy_c_buf_p; \
- *yyg->yy_c_buf_p = '\0'; \
- yyleng = yyless_macro_arg; \
- } \
- while ( 0 )
-
-/* Accessor methods (get/set functions) to struct members. */
-
-/** Get the user-defined data for this scanner.
- * @param yyscanner The scanner object.
- */
-YY_EXTRA_TYPE ast_yyget_extra (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yyextra;
-}
-
-/** Get the current line number.
- * @param yyscanner The scanner object.
- */
-int ast_yyget_lineno (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if (! YY_CURRENT_BUFFER)
- return 0;
-
- return yylineno;
-}
-
-/** Get the current column number.
- * @param yyscanner The scanner object.
- */
-int ast_yyget_column (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- if (! YY_CURRENT_BUFFER)
- return 0;
-
- return yycolumn;
-}
-
-/** Get the input stream.
- * @param yyscanner The scanner object.
- */
-FILE *ast_yyget_in (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yyin;
-}
-
-/** Get the output stream.
- * @param yyscanner The scanner object.
- */
-FILE *ast_yyget_out (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yyout;
-}
-
-/** Get the length of the current token.
- * @param yyscanner The scanner object.
- */
-int ast_yyget_leng (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yyleng;
-}
-
-/** Get the current token.
- * @param yyscanner The scanner object.
- */
-
-char *ast_yyget_text (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yytext;
-}
-
-/** Set the user-defined data. This data is never touched by the scanner.
- * @param user_defined The data to be associated with this scanner.
- * @param yyscanner The scanner object.
- */
-void ast_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyextra = user_defined ;
-}
-
-/** Set the current line number.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void ast_yyset_lineno (int line_number , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- /* lineno is only valid if an input buffer exists. */
- if (! YY_CURRENT_BUFFER )
- yy_fatal_error( "ast_yyset_lineno called with no buffer" , yyscanner);
-
- yylineno = line_number;
-}
-
-/** Set the current column.
- * @param line_number
- * @param yyscanner The scanner object.
- */
-void ast_yyset_column (int column_no , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- /* column is only valid if an input buffer exists. */
- if (! YY_CURRENT_BUFFER )
- yy_fatal_error( "ast_yyset_column called with no buffer" , yyscanner);
-
- yycolumn = column_no;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * @param yyscanner The scanner object.
- * @see ast_yy_switch_to_buffer
- */
-void ast_yyset_in (FILE * in_str , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyin = in_str ;
-}
-
-void ast_yyset_out (FILE * out_str , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yyout = out_str ;
-}
-
-int ast_yyget_debug (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yy_flex_debug;
-}
-
-void ast_yyset_debug (int bdebug , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yy_flex_debug = bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-YYSTYPE * ast_yyget_lval (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yylval;
-}
-
-void ast_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yylval = yylval_param;
-}
-
-YYLTYPE *ast_yyget_lloc (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- return yylloc;
-}
-
-void ast_yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- yylloc = yylloc_param;
-}
-
-/* User-visible API */
-
-/* ast_yylex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int ast_yylex_init(yyscan_t* ptr_yy_globals)
-
-{
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) ast_yyalloc ( sizeof( struct yyguts_t ), NULL );
-
- if (*ptr_yy_globals == NULL){
- errno = ENOMEM;
- return 1;
- }
-
- /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
- memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
- return yy_init_globals ( *ptr_yy_globals );
-}
-
-/* ast_yylex_init_extra has the same functionality as ast_yylex_init, but follows the
- * convention of taking the scanner as the last argument. Note however, that
- * this is a *pointer* to a scanner, as it will be allocated by this call (and
- * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to ast_yyalloc in
- * the yyextra field.
- */
-
-int ast_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
-{
- struct yyguts_t dummy_yyguts;
-
- ast_yyset_extra (yy_user_defined, &dummy_yyguts);
-
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) ast_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-
- if (*ptr_yy_globals == NULL){
- errno = ENOMEM;
- return 1;
- }
-
- /* By setting to 0xAA, we expose bugs in
- yy_init_globals. Leave at 0x00 for releases. */
- memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
- ast_yyset_extra (yy_user_defined, *ptr_yy_globals);
-
- return yy_init_globals ( *ptr_yy_globals );
-}
-
-static int yy_init_globals (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- /* Initialization is the same as for the non-reentrant scanner.
- * This function is called from ast_yylex_destroy(), so don't allocate here.
- */
-
- yyg->yy_buffer_stack = 0;
- yyg->yy_buffer_stack_top = 0;
- yyg->yy_buffer_stack_max = 0;
- yyg->yy_c_buf_p = (char *) 0;
- yyg->yy_init = 0;
- yyg->yy_start = 0;
-
- yyg->yy_start_stack_ptr = 0;
- yyg->yy_start_stack_depth = 0;
- yyg->yy_start_stack = NULL;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
- yyin = stdin;
- yyout = stdout;
-#else
- yyin = (FILE *) 0;
- yyout = (FILE *) 0;
-#endif
-
- /* For future reference: Set errno on error, since we are called by
- * ast_yylex_init()
- */
- return 0;
-}
-
-/* ast_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int ast_yylex_destroy (yyscan_t yyscanner)
-{
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
- /* Pop the buffer stack, destroying each element. */
- while(YY_CURRENT_BUFFER){
- ast_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
- YY_CURRENT_BUFFER_LVALUE = NULL;
- ast_yypop_buffer_state(yyscanner);
- }
-
- /* Destroy the stack itself. */
- ast_yyfree(yyg->yy_buffer_stack ,yyscanner);
- yyg->yy_buffer_stack = NULL;
-
- /* Destroy the start condition stack. */
- ast_yyfree(yyg->yy_start_stack ,yyscanner );
- yyg->yy_start_stack = NULL;
-
- /* Reset the globals. This is important in a non-reentrant scanner so the next time
- * ast_yylex() is called, initialization will occur. */
- yy_init_globals( yyscanner);
-
- /* Destroy the main struct (reentrant only). */
- ast_yyfree ( yyscanner , yyscanner );
- yyscanner = NULL;
- return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
- register int i;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
- register int n;
- for ( n = 0; s[n]; ++n )
- ;
-
- return n;
-}
-#endif
-
-void *ast_yyalloc (yy_size_t size , yyscan_t yyscanner)
-{
- return (void *) malloc( size );
-}
-
-void *ast_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
-{
- /* The cast to (char *) in the following accommodates both
- * implementations that use char* generic pointers, and those
- * that use void* generic pointers. It works with the latter
- * because both ANSI C and C++ allow castless assignment from
- * any pointer type to void*, and deal with argument conversions
- * as though doing an assignment.
- */
- return (void *) realloc( (char *) ptr, size );
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 206 "ast_expr2.fl"
-
-
-
-/* I'm putting the interface routine to the whole parse here in the flexer input file
- mainly because of all the flexer initialization that has to be done. Shouldn't matter
- where it is, as long as it's somewhere. I didn't want to define a prototype for the
- ast_yy_scan_string in the .y file, because then, I'd have to define YY_BUFFER_STATE there...
- UGH! that would be inappropriate. */
-
-int ast_yyparse(void *); /* need to/should define this prototype for the call to yyparse */
-int ast_yyerror(const char *, YYLTYPE *, struct parse_io *); /* likewise */
-
-void ast_yyfree(void *ptr, yyscan_t yyscanner)
-{
- if (ptr) /* the normal generated ast_yyfree func just frees its first arg;
- this get complaints on some systems, as sometimes this
- arg is a nil ptr! It's usually not fatal, but is irritating! */
- free( (char *) ptr );
-}
-
-int ast_expr(char *expr, char *buf, int length)
-{
- struct parse_io io;
- int return_value = 0;
-
- memset(&io, 0, sizeof(io));
- io.string = expr; /* to pass to the error routine */
-
- ast_yylex_init(&io.scanner);
-
- ast_yy_scan_string(expr, io.scanner);
-
- ast_yyparse ((void *) &io);
-
- ast_yylex_destroy(io.scanner);
-
- if (!io.val) {
- if (length > 1) {
- strcpy(buf, "0");
- return_value = 1;
- }
- } else {
- if (io.val->type == AST_EXPR_integer) {
- int res_length;
-
- res_length = snprintf(buf, length, "%ld", (long int) io.val->u.i);
- return_value = (res_length <= length) ? res_length : length;
- } else {
-#if defined(STANDALONE) || defined(LOW_MEMORY) || defined(STANDALONE_AEL)
- strncpy(buf, io.val->u.s, length - 1);
-#else /* !STANDALONE && !LOW_MEMORY */
- ast_copy_string(buf, io.val->u.s, length);
-#endif /* STANDALONE || LOW_MEMORY */
- return_value = strlen(buf);
- free(io.val->u.s);
- }
- free(io.val);
- }
- return return_value;
-}
-
-
-char extra_error_message[4095];
-int extra_error_message_supplied = 0;
-void ast_expr_register_extra_error_info(char *message);
-void ast_expr_clear_extra_error_info(void);
-
-void ast_expr_register_extra_error_info(char *message)
-{
- extra_error_message_supplied=1;
- strcpy(extra_error_message, message);
-}
-
-void ast_expr_clear_extra_error_info(void)
-{
- extra_error_message_supplied=0;
- extra_error_message[0] = 0;
-}
-
-static char *expr2_token_equivs1[] =
-{
- "TOKEN",
- "TOK_COND",
- "TOK_COLONCOLON",
- "TOK_OR",
- "TOK_AND",
- "TOK_EQ",
- "TOK_GT",
- "TOK_LT",
- "TOK_GE",
- "TOK_LE",
- "TOK_NE",
- "TOK_PLUS",
- "TOK_MINUS",
- "TOK_MULT",
- "TOK_DIV",
- "TOK_MOD",
- "TOK_COMPL",
- "TOK_COLON",
- "TOK_EQTILDE",
- "TOK_RP",
- "TOK_LP"
-};
-
-static char *expr2_token_equivs2[] =
-{
- "<token>",
- "?",
- "::",
- "|",
- "&",
- "=",
- ">",
- "<",
- ">=",
- "<=",
- "!=",
- "+",
- "-",
- "*",
- "/",
- "%",
- "!",
- ":",
- "=~",
- ")",
- "("
-};
-
-
-static char *expr2_token_subst(const char *mess)
-{
- /* calc a length, malloc, fill, and return; yyerror had better free it! */
- int len=0,i;
- const char *p;
- char *res, *s,*t;
- int expr2_token_equivs_entries = sizeof(expr2_token_equivs1)/sizeof(char*);
-
- for (p=mess; *p; p++) {
- for (i=0; i<expr2_token_equivs_entries; i++) {
- if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 )
- {
- len+=strlen(expr2_token_equivs2[i])+2;
- p += strlen(expr2_token_equivs1[i])-1;
- break;
- }
- }
- len++;
- }
- res = (char*)malloc(len+1);
- res[0] = 0;
- s = res;
- for (p=mess; *p;) {
- int found = 0;
- for (i=0; i<expr2_token_equivs_entries; i++) {
- if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 ) {
- *s++ = '\'';
- for (t=expr2_token_equivs2[i]; *t;) {
- *s++ = *t++;
- }
- *s++ = '\'';
- p += strlen(expr2_token_equivs1[i]);
- found = 1;
- break;
- }
- }
- if( !found )
- *s++ = *p++;
- }
- *s++ = 0;
- return res;
-}
-
-int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio )
-{
- struct yyguts_t * yyg = (struct yyguts_t*)(parseio->scanner);
- char spacebuf[8000]; /* best safe than sorry */
- char spacebuf2[8000]; /* best safe than sorry */
- int i=0;
- char *s2 = expr2_token_subst(s);
- spacebuf[0] = 0;
-
- for(i=0;i< (int)(yytext - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);i++) spacebuf2[i] = ' '; /* uh... assuming yyg is defined, then I can use the yycolumn macro,
- which is the same thing as... get this:
- yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]->yy_bs_column
- I was tempted to just use yy_buf_pos in the STATE, but..., well:
- a. the yy_buf_pos is the current position in the buffer, which
- may not relate to the entire string/buffer because of the
- buffering.
- b. but, analysis of the situation is that when you use the
- ast_yy_scan_string func, it creates a single buffer the size of
- string, so the two would be the same...
- so, in the end, the yycolumn macro is available, shorter, therefore easier. */
- spacebuf2[i++]='^';
- spacebuf2[i]= 0;
-
-#ifdef STANDALONE3
- /* easier to read in the standalone version */
- printf("ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n",
- (extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2);
-#else
- ast_log(LOG_WARNING,"ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n",
- (extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2);
-#endif
-#ifndef STANDALONE
- ast_log(LOG_WARNING,"If you have questions, please refer to doc/channelvariables.txt in the asterisk source.\n");
-#endif
- free(s2);
- return(0);
-}
-
diff --git a/main/asterisk.c b/main/asterisk.c
deleted file mode 100644
index 8ef99c683..000000000
--- a/main/asterisk.c
+++ /dev/null
@@ -1,3223 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2008, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-
-/* Doxygenified Copyright Header */
-/*!
- * \mainpage Asterisk -- An Open Source Telephony Toolkit
- *
- * \par Developer Documentation for Asterisk
- * This is the main developer documentation for Asterisk. It is
- * generated by running "make progdocs".
- * \par Additional documentation
- * \arg \ref Licensing
- * \arg \ref DevDoc
- * \arg \ref ConfigFiles
- *
- * \section copyright Copyright and author
- *
- * Copyright (C) 1999 - 2008, Digium, Inc.
- * Asterisk is a trademark registered by Digium, Inc.
- *
- * \author Mark Spencer <markster@digium.com>
- * Also see \ref AstCREDITS
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- */
-
-/*! \file
- \brief Top level source file for Asterisk - the Open Source PBX. Implementation
- of PBX core functions and CLI interface.
-
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#undef sched_setscheduler
-#undef setpriority
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <signal.h>
-#include <sched.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <sys/resource.h>
-#include <grp.h>
-#include <pwd.h>
-#include <sys/stat.h>
-
-#if defined(HAVE_ZAPTEL) || defined (HAVE_DAHDI)
-#include <sys/ioctl.h>
-#include "asterisk/dahdi_compat.h"
-#endif
-
-#ifdef linux
-#include <sys/prctl.h>
-#ifdef HAVE_CAP
-#include <sys/capability.h>
-#endif /* HAVE_CAP */
-#endif /* linux */
-#include <regex.h>
-
-#if defined(__FreeBSD__) || defined( __NetBSD__ ) || defined(SOLARIS)
-#include <netdb.h>
-#if defined(SOLARIS)
-int daemon(int, int); /* defined in libresolv of all places */
-#endif
-#endif
-
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/cli.h"
-#include "asterisk/channel.h"
-#include "asterisk/ulaw.h"
-#include "asterisk/alaw.h"
-#include "asterisk/callerid.h"
-#include "asterisk/image.h"
-#include "asterisk/tdd.h"
-#include "asterisk/term.h"
-#include "asterisk/manager.h"
-#include "asterisk/cdr.h"
-#include "asterisk/pbx.h"
-#include "asterisk/enum.h"
-#include "asterisk/rtp.h"
-#include "asterisk/http.h"
-#include "asterisk/udptl.h"
-#include "asterisk/app.h"
-#include "asterisk/lock.h"
-#include "asterisk/utils.h"
-#include "asterisk/file.h"
-#include "asterisk/io.h"
-#include "asterisk/lock.h"
-#include "editline/histedit.h"
-#include "asterisk/config.h"
-#include "asterisk/version.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/devicestate.h"
-#include "asterisk/module.h"
-
-#include "asterisk/doxyref.h" /* Doxygen documentation */
-
-#include "../defaults.h"
-
-#ifndef AF_LOCAL
-#define AF_LOCAL AF_UNIX
-#define PF_LOCAL PF_UNIX
-#endif
-
-#define AST_MAX_CONNECTS 128
-#define NUM_MSGS 64
-
-/*! \brief Welcome message when starting a CLI interface */
-#define WELCOME_MESSAGE \
- ast_verbose("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2008 Digium, Inc. and others.\n"); \
- ast_verbose("Created by Mark Spencer <markster@digium.com>\n"); \
- ast_verbose("Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n"); \
- ast_verbose("This is free software, with components licensed under the GNU General Public\n"); \
- ast_verbose("License version 2 and other licenses; you are welcome to redistribute it under\n"); \
- ast_verbose("certain conditions. Type 'core show license' for details.\n"); \
- ast_verbose("=========================================================================\n")
-
-/*! \defgroup main_options Main Configuration Options
- \brief Main configuration options from \ref Config_ast "asterisk.conf" or
- the operating system command line when starting Asterisk
- Some of them can be changed in the CLI
- */
-/*! @{ */
-
-struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
-
-int option_verbose; /*!< Verbosity level */
-int option_debug; /*!< Debug level */
-
-double option_maxload; /*!< Max load avg on system */
-int option_maxcalls; /*!< Max number of active calls */
-
-/*! @} */
-
-char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR;
-char debug_filename[AST_FILENAME_MAX] = "";
-#ifdef HAVE_ZAPTEL
-static char _dahdi_chan_name[AST_CHANNEL_NAME] = "Zap";
-static size_t _dahdi_chan_name_len = 3;
-static enum dahdi_chan_modes _dahdi_chan_mode = CHAN_ZAP_MODE;
-#else
-static char _dahdi_chan_name[AST_CHANNEL_NAME] = "DAHDI";
-static size_t _dahdi_chan_name_len = 5;
-static enum dahdi_chan_modes _dahdi_chan_mode = CHAN_DAHDI_PLUS_ZAP_MODE;
-#endif
-const char *dahdi_chan_name;
-const size_t *dahdi_chan_name_len;
-const enum dahdi_chan_modes *dahdi_chan_mode;
-
-static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */
-static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */
-pid_t ast_mainpid;
-struct console {
- int fd; /*!< File descriptor */
- int p[2]; /*!< Pipe */
- pthread_t t; /*!< Thread of handler */
- int mute; /*!< Is the console muted for logs */
-};
-
-struct ast_atexit {
- void (*func)(void);
- AST_LIST_ENTRY(ast_atexit) list;
-};
-
-static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
-
-time_t ast_startuptime;
-time_t ast_lastreloadtime;
-
-static History *el_hist;
-static EditLine *el;
-static char *remotehostname;
-
-struct console consoles[AST_MAX_CONNECTS];
-
-char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
-
-static int ast_el_add_history(char *);
-static int ast_el_read_history(char *);
-static int ast_el_write_history(char *);
-
-char ast_config_AST_CONFIG_DIR[PATH_MAX];
-char ast_config_AST_CONFIG_FILE[PATH_MAX];
-char ast_config_AST_MODULE_DIR[PATH_MAX];
-char ast_config_AST_SPOOL_DIR[PATH_MAX];
-char ast_config_AST_MONITOR_DIR[PATH_MAX];
-char ast_config_AST_VAR_DIR[PATH_MAX];
-char ast_config_AST_DATA_DIR[PATH_MAX];
-char ast_config_AST_LOG_DIR[PATH_MAX];
-char ast_config_AST_AGI_DIR[PATH_MAX];
-char ast_config_AST_DB[PATH_MAX];
-char ast_config_AST_KEY_DIR[PATH_MAX];
-char ast_config_AST_PID[PATH_MAX];
-char ast_config_AST_SOCKET[PATH_MAX];
-char ast_config_AST_RUN_DIR[PATH_MAX];
-char ast_config_AST_RUN_USER[PATH_MAX];
-char ast_config_AST_RUN_GROUP[PATH_MAX];
-char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
-char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
-char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
-char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
-char ast_config_AST_SYSTEM_NAME[20] = "";
-
-extern const char *ast_build_hostname;
-extern const char *ast_build_kernel;
-extern const char *ast_build_machine;
-extern const char *ast_build_os;
-extern const char *ast_build_date;
-extern const char *ast_build_user;
-
-static char *_argv[256];
-static int shuttingdown;
-static int restartnow;
-static pthread_t consolethread = AST_PTHREADT_NULL;
-
-static char randompool[256];
-
-static int sig_alert_pipe[2] = { -1, -1 };
-static struct {
- unsigned int need_reload:1;
- unsigned int need_quit:1;
-} sig_flags;
-
-#if !defined(LOW_MEMORY)
-struct file_version {
- AST_LIST_ENTRY(file_version) list;
- const char *file;
- char *version;
-};
-
-static AST_LIST_HEAD_STATIC(file_versions, file_version);
-
-void ast_register_file_version(const char *file, const char *version)
-{
- struct file_version *new;
- char *work;
- size_t version_length;
-
- work = ast_strdupa(version);
- work = ast_strip(ast_strip_quoted(work, "$", "$"));
- version_length = strlen(work) + 1;
-
- if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
- return;
-
- new->file = file;
- new->version = (char *) new + sizeof(*new);
- memcpy(new->version, work, version_length);
- AST_LIST_LOCK(&file_versions);
- AST_LIST_INSERT_HEAD(&file_versions, new, list);
- AST_LIST_UNLOCK(&file_versions);
-}
-
-void ast_unregister_file_version(const char *file)
-{
- struct file_version *find;
-
- AST_LIST_LOCK(&file_versions);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
- if (!strcasecmp(find->file, file)) {
- AST_LIST_REMOVE_CURRENT(&file_versions, list);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&file_versions);
- if (find)
- free(find);
-}
-
-struct thread_list_t {
- AST_LIST_ENTRY(thread_list_t) list;
- char *name;
- pthread_t id;
-};
-
-static AST_LIST_HEAD_STATIC(thread_list, thread_list_t);
-
-static char show_threads_help[] =
-"Usage: core show threads\n"
-" List threads currently active in the system.\n";
-
-void ast_register_thread(char *name)
-{
- struct thread_list_t *new = ast_calloc(1, sizeof(*new));
-
- if (!new)
- return;
- new->id = pthread_self();
- new->name = name; /* steal the allocated memory for the thread name */
- AST_LIST_LOCK(&thread_list);
- AST_LIST_INSERT_HEAD(&thread_list, new, list);
- AST_LIST_UNLOCK(&thread_list);
-}
-
-void ast_unregister_thread(void *id)
-{
- struct thread_list_t *x;
-
- AST_LIST_LOCK(&thread_list);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
- if ((void *) x->id == id) {
- AST_LIST_REMOVE_CURRENT(&thread_list, list);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&thread_list);
- if (x) {
- free(x->name);
- free(x);
- }
-}
-
-static int handle_show_threads(int fd, int argc, char *argv[])
-{
- int count = 0;
- struct thread_list_t *cur;
-
- AST_LIST_LOCK(&thread_list);
- AST_LIST_TRAVERSE(&thread_list, cur, list) {
- ast_cli(fd, "%p %s\n", (void *)cur->id, cur->name);
- count++;
- }
- AST_LIST_UNLOCK(&thread_list);
- ast_cli(fd, "%d threads listed.\n", count);
- return 0;
-}
-
-struct profile_entry {
- const char *name;
- uint64_t scale; /* if non-zero, values are scaled by this */
- int64_t mark;
- int64_t value;
- int64_t events;
-};
-
-struct profile_data {
- int entries;
- int max_size;
- struct profile_entry e[0];
-};
-
-static struct profile_data *prof_data;
-
-/*! \brief allocates a counter with a given name and scale.
- * \return Returns the identifier of the counter.
- */
-int ast_add_profile(const char *name, uint64_t scale)
-{
- int l = sizeof(struct profile_data);
- int n = 10; /* default entries */
-
- if (prof_data == NULL) {
- prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
- if (prof_data == NULL)
- return -1;
- prof_data->entries = 0;
- prof_data->max_size = n;
- }
- if (prof_data->entries >= prof_data->max_size) {
- void *p;
- n = prof_data->max_size + 20;
- p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
- if (p == NULL)
- return -1;
- prof_data = p;
- prof_data->max_size = n;
- }
- n = prof_data->entries++;
- prof_data->e[n].name = ast_strdup(name);
- prof_data->e[n].value = 0;
- prof_data->e[n].events = 0;
- prof_data->e[n].mark = 0;
- prof_data->e[n].scale = scale;
- return n;
-}
-
-int64_t ast_profile(int i, int64_t delta)
-{
- if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
- return 0;
- if (prof_data->e[i].scale > 1)
- delta /= prof_data->e[i].scale;
- prof_data->e[i].value += delta;
- prof_data->e[i].events++;
- return prof_data->e[i].value;
-}
-
-/* The RDTSC instruction was introduced on the Pentium processor and is not
- * implemented on certain clones, like the Cyrix 586. Hence, the previous
- * expectation of __i386__ was in error. */
-#if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
-#if defined(__FreeBSD__)
-#include <machine/cpufunc.h>
-#elif defined(linux)
-static __inline uint64_t
-rdtsc(void)
-{
- uint64_t rv;
-
- __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
- return (rv);
-}
-#endif
-#else /* supply a dummy function on other platforms */
-static __inline uint64_t
-rdtsc(void)
-{
- return 0;
-}
-#endif
-
-int64_t ast_mark(int i, int startstop)
-{
- if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
- return 0;
- if (startstop == 1)
- prof_data->e[i].mark = rdtsc();
- else {
- prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
- if (prof_data->e[i].scale > 1)
- prof_data->e[i].mark /= prof_data->e[i].scale;
- prof_data->e[i].value += prof_data->e[i].mark;
- prof_data->e[i].events++;
- }
- return prof_data->e[i].mark;
-}
-
-static int handle_show_profile_deprecated(int fd, int argc, char *argv[])
-{
- int i, min, max;
- char *search = NULL;
-
- if (prof_data == NULL)
- return 0;
-
- min = 0;
- max = prof_data->entries;
- if (argc >= 3) { /* specific entries */
- if (isdigit(argv[2][0])) {
- min = atoi(argv[2]);
- if (argc == 4 && strcmp(argv[3], "-"))
- max = atoi(argv[3]);
- } else
- search = argv[2];
- }
- if (max > prof_data->entries)
- max = prof_data->entries;
- if (!strcmp(argv[0], "clear")) {
- for (i= min; i < max; i++) {
- if (!search || strstr(prof_data->e[i].name, search)) {
- prof_data->e[i].value = 0;
- prof_data->e[i].events = 0;
- }
- }
- return 0;
- }
- ast_cli(fd, "profile values (%d, allocated %d)\n-------------------\n",
- prof_data->entries, prof_data->max_size);
- ast_cli(fd, "%6s %8s %10s %12s %12s %s\n", "ID", "Scale", "Events",
- "Value", "Average", "Name");
- for (i = min; i < max; i++) {
- struct profile_entry *e = &prof_data->e[i];
- if (!search || strstr(prof_data->e[i].name, search))
- ast_cli(fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
- i,
- (long)e->scale,
- (long)e->events, (long long)e->value,
- (long long)(e->events ? e->value / e->events : e->value),
- e->name);
- }
- return 0;
-}
-
-static int handle_show_profile(int fd, int argc, char *argv[])
-{
- int i, min, max;
- char *search = NULL;
-
- if (prof_data == NULL)
- return 0;
-
- min = 0;
- max = prof_data->entries;
- if (argc > 3) { /* specific entries */
- if (isdigit(argv[3][0])) {
- min = atoi(argv[3]);
- if (argc == 5 && strcmp(argv[4], "-"))
- max = atoi(argv[4]);
- } else
- search = argv[3];
- }
- if (max > prof_data->entries)
- max = prof_data->entries;
- if (!strcmp(argv[1], "clear")) {
- for (i= min; i < max; i++) {
- if (!search || strstr(prof_data->e[i].name, search)) {
- prof_data->e[i].value = 0;
- prof_data->e[i].events = 0;
- }
- }
- return 0;
- }
- ast_cli(fd, "profile values (%d, allocated %d)\n-------------------\n",
- prof_data->entries, prof_data->max_size);
- ast_cli(fd, "%6s %8s %10s %12s %12s %s\n", "ID", "Scale", "Events",
- "Value", "Average", "Name");
- for (i = min; i < max; i++) {
- struct profile_entry *e = &prof_data->e[i];
- if (!search || strstr(prof_data->e[i].name, search))
- ast_cli(fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
- i,
- (long)e->scale,
- (long)e->events, (long long)e->value,
- (long long)(e->events ? e->value / e->events : e->value),
- e->name);
- }
- return 0;
-}
-
-static char show_version_files_help[] =
-"Usage: core show file version [like <pattern>]\n"
-" Lists the revision numbers of the files used to build this copy of Asterisk.\n"
-" Optional regular expression pattern is used to filter the file list.\n";
-
-/*! \brief CLI command to list module versions */
-static int handle_show_version_files_deprecated(int fd, int argc, char *argv[])
-{
-#define FORMAT "%-25.25s %-40.40s\n"
- struct file_version *iterator;
- regex_t regexbuf;
- int havepattern = 0;
- int havename = 0;
- int count_files = 0;
-
- switch (argc) {
- case 5:
- if (!strcasecmp(argv[3], "like")) {
- if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
- return RESULT_SHOWUSAGE;
- havepattern = 1;
- } else
- return RESULT_SHOWUSAGE;
- break;
- case 4:
- havename = 1;
- break;
- case 3:
- break;
- default:
- return RESULT_SHOWUSAGE;
- }
-
- ast_cli(fd, FORMAT, "File", "Revision");
- ast_cli(fd, FORMAT, "----", "--------");
- AST_LIST_LOCK(&file_versions);
- AST_LIST_TRAVERSE(&file_versions, iterator, list) {
- if (havename && strcasecmp(iterator->file, argv[3]))
- continue;
-
- if (havepattern && regexec(&regexbuf, iterator->file, 0, NULL, 0))
- continue;
-
- ast_cli(fd, FORMAT, iterator->file, iterator->version);
- count_files++;
- if (havename)
- break;
- }
- AST_LIST_UNLOCK(&file_versions);
- if (!havename) {
- ast_cli(fd, "%d files listed.\n", count_files);
- }
-
- if (havepattern)
- regfree(&regexbuf);
-
- return RESULT_SUCCESS;
-#undef FORMAT
-}
-
-static int handle_show_version_files(int fd, int argc, char *argv[])
-{
-#define FORMAT "%-25.25s %-40.40s\n"
- struct file_version *iterator;
- regex_t regexbuf;
- int havepattern = 0;
- int havename = 0;
- int count_files = 0;
-
- switch (argc) {
- case 6:
- if (!strcasecmp(argv[4], "like")) {
- if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
- return RESULT_SHOWUSAGE;
- havepattern = 1;
- } else
- return RESULT_SHOWUSAGE;
- break;
- case 5:
- havename = 1;
- break;
- case 4:
- break;
- default:
- return RESULT_SHOWUSAGE;
- }
-
- ast_cli(fd, FORMAT, "File", "Revision");
- ast_cli(fd, FORMAT, "----", "--------");
- AST_LIST_LOCK(&file_versions);
- AST_LIST_TRAVERSE(&file_versions, iterator, list) {
- if (havename && strcasecmp(iterator->file, argv[4]))
- continue;
-
- if (havepattern && regexec(&regexbuf, iterator->file, 0, NULL, 0))
- continue;
-
- ast_cli(fd, FORMAT, iterator->file, iterator->version);
- count_files++;
- if (havename)
- break;
- }
- AST_LIST_UNLOCK(&file_versions);
- if (!havename) {
- ast_cli(fd, "%d files listed.\n", count_files);
- }
-
- if (havepattern)
- regfree(&regexbuf);
-
- return RESULT_SUCCESS;
-#undef FORMAT
-}
-
-static char *complete_show_version_files_deprecated(const char *line, const char *word, int pos, int state)
-{
- struct file_version *find;
- int which = 0;
- char *ret = NULL;
- int matchlen = strlen(word);
-
- if (pos != 3)
- return NULL;
-
- AST_LIST_LOCK(&file_versions);
- AST_LIST_TRAVERSE(&file_versions, find, list) {
- if (!strncasecmp(word, find->file, matchlen) && ++which > state) {
- ret = ast_strdup(find->file);
- break;
- }
- }
- AST_LIST_UNLOCK(&file_versions);
-
- return ret;
-}
-
-static char *complete_show_version_files(const char *line, const char *word, int pos, int state)
-{
- struct file_version *find;
- int which = 0;
- char *ret = NULL;
- int matchlen = strlen(word);
-
- if (pos != 4)
- return NULL;
-
- AST_LIST_LOCK(&file_versions);
- AST_LIST_TRAVERSE(&file_versions, find, list) {
- if (!strncasecmp(word, find->file, matchlen) && ++which > state) {
- ret = ast_strdup(find->file);
- break;
- }
- }
- AST_LIST_UNLOCK(&file_versions);
-
- return ret;
-}
-
-#endif /* ! LOW_MEMORY */
-
-int ast_register_atexit(void (*func)(void))
-{
- struct ast_atexit *ae;
-
- if (!(ae = ast_calloc(1, sizeof(*ae))))
- return -1;
-
- ae->func = func;
-
- ast_unregister_atexit(func);
-
- AST_LIST_LOCK(&atexits);
- AST_LIST_INSERT_HEAD(&atexits, ae, list);
- AST_LIST_UNLOCK(&atexits);
-
- return 0;
-}
-
-void ast_unregister_atexit(void (*func)(void))
-{
- struct ast_atexit *ae = NULL;
-
- AST_LIST_LOCK(&atexits);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
- if (ae->func == func) {
- AST_LIST_REMOVE_CURRENT(&atexits, list);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&atexits);
-
- if (ae)
- free(ae);
-}
-
-/* Sending commands from consoles back to the daemon requires a terminating NULL */
-static int fdsend(int fd, const char *s)
-{
- return write(fd, s, strlen(s) + 1);
-}
-
-/* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
-static int fdprint(int fd, const char *s)
-{
- return write(fd, s, strlen(s));
-}
-
-/*! \brief NULL handler so we can collect the child exit status */
-static void null_sig_handler(int signal)
-{
-
-}
-
-AST_MUTEX_DEFINE_STATIC(safe_system_lock);
-/*! \brief Keep track of how many threads are currently trying to wait*() on
- * a child process */
-static unsigned int safe_system_level = 0;
-static void *safe_system_prev_handler;
-
-void ast_replace_sigchld(void)
-{
- unsigned int level;
-
- ast_mutex_lock(&safe_system_lock);
- level = safe_system_level++;
-
- /* only replace the handler if it has not already been done */
- if (level == 0)
- safe_system_prev_handler = signal(SIGCHLD, null_sig_handler);
-
- ast_mutex_unlock(&safe_system_lock);
-}
-
-void ast_unreplace_sigchld(void)
-{
- unsigned int level;
-
- ast_mutex_lock(&safe_system_lock);
- level = --safe_system_level;
-
- /* only restore the handler if we are the last one */
- if (level == 0)
- signal(SIGCHLD, safe_system_prev_handler);
-
- ast_mutex_unlock(&safe_system_lock);
-}
-
-int ast_safe_system(const char *s)
-{
- pid_t pid;
-#ifdef HAVE_WORKING_FORK
- int x;
-#endif
- int res;
- struct rusage rusage;
- int status;
-
-#if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
- ast_replace_sigchld();
-
-#ifdef HAVE_WORKING_FORK
- pid = fork();
-#else
- pid = vfork();
-#endif
-
- if (pid == 0) {
-#ifdef HAVE_WORKING_FORK
- if (ast_opt_high_priority)
- ast_set_priority(0);
- /* Close file descriptors and launch system command */
- for (x = STDERR_FILENO + 1; x < 4096; x++)
- close(x);
-#endif
- execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
- _exit(1);
- } else if (pid > 0) {
- for(;;) {
- res = wait4(pid, &status, 0, &rusage);
- if (res > -1) {
- res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
- break;
- } else if (errno != EINTR)
- break;
- }
- } else {
- ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
- res = -1;
- }
-
- ast_unreplace_sigchld();
-#else
- res = -1;
-#endif
-
- return res;
-}
-
-/*!
- * \brief mute or unmute a console from logging
- */
-void ast_console_toggle_mute(int fd, int silent) {
- int x;
- for (x = 0;x < AST_MAX_CONNECTS; x++) {
- if (fd == consoles[x].fd) {
- if (consoles[x].mute) {
- consoles[x].mute = 0;
- if (!silent)
- ast_cli(fd, "Console is not muted anymore.\n");
- } else {
- consoles[x].mute = 1;
- if (!silent)
- ast_cli(fd, "Console is muted.\n");
- }
- return;
- }
- }
- ast_cli(fd, "Couldn't find remote console.\n");
-}
-
-/*!
- * \brief log the string to all attached console clients
- */
-static void ast_network_puts_mutable(const char *string)
-{
- int x;
- for (x = 0;x < AST_MAX_CONNECTS; x++) {
- if (consoles[x].mute)
- continue;
- if (consoles[x].fd > -1)
- fdprint(consoles[x].p[1], string);
- }
-}
-
-/*!
- * \brief log the string to the console, and all attached
- * console clients
- */
-void ast_console_puts_mutable(const char *string)
-{
- fputs(string, stdout);
- fflush(stdout);
- ast_network_puts_mutable(string);
-}
-
-/*!
- * \brief write the string to all attached console clients
- */
-static void ast_network_puts(const char *string)
-{
- int x;
- for (x=0; x < AST_MAX_CONNECTS; x++) {
- if (consoles[x].fd > -1)
- fdprint(consoles[x].p[1], string);
- }
-}
-
-/*!
- * write the string to the console, and all attached
- * console clients
- */
-void ast_console_puts(const char *string)
-{
- fputs(string, stdout);
- fflush(stdout);
- ast_network_puts(string);
-}
-
-static void network_verboser(const char *s)
-{
- ast_network_puts_mutable(s);
-}
-
-static pthread_t lthread;
-
-static void *netconsole(void *vconsole)
-{
- struct console *con = vconsole;
- char hostname[MAXHOSTNAMELEN] = "";
- char tmp[512];
- int res;
- struct pollfd fds[2];
-
- if (gethostname(hostname, sizeof(hostname)-1))
- ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
- snprintf(tmp, sizeof(tmp), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ASTERISK_VERSION);
- fdprint(con->fd, tmp);
- for(;;) {
- fds[0].fd = con->fd;
- fds[0].events = POLLIN;
- fds[0].revents = 0;
- fds[1].fd = con->p[0];
- fds[1].events = POLLIN;
- fds[1].revents = 0;
-
- res = poll(fds, 2, -1);
- if (res < 0) {
- if (errno != EINTR)
- ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
- continue;
- }
- if (fds[0].revents) {
- res = read(con->fd, tmp, sizeof(tmp));
- if (res < 1) {
- break;
- }
- tmp[res] = 0;
- ast_cli_command_multiple(con->fd, res, tmp);
- }
- if (fds[1].revents) {
- res = read(con->p[0], tmp, sizeof(tmp));
- if (res < 1) {
- ast_log(LOG_ERROR, "read returned %d\n", res);
- break;
- }
- res = write(con->fd, tmp, res);
- if (res < 1)
- break;
- }
- }
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n");
- close(con->fd);
- close(con->p[0]);
- close(con->p[1]);
- con->fd = -1;
-
- return NULL;
-}
-
-static void *listener(void *unused)
-{
- struct sockaddr_un sunaddr;
- int s;
- socklen_t len;
- int x;
- int flags;
- struct pollfd fds[1];
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- for (;;) {
- if (ast_socket < 0)
- return NULL;
- fds[0].fd = ast_socket;
- fds[0].events = POLLIN;
- s = poll(fds, 1, -1);
- pthread_testcancel();
- if (s < 0) {
- if (errno != EINTR)
- ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
- continue;
- }
- len = sizeof(sunaddr);
- s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
- if (s < 0) {
- if (errno != EINTR)
- ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
- } else {
- for (x = 0; x < AST_MAX_CONNECTS; x++) {
- if (consoles[x].fd < 0) {
- if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
- ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
- consoles[x].fd = -1;
- fdprint(s, "Server failed to create pipe\n");
- close(s);
- break;
- }
- flags = fcntl(consoles[x].p[1], F_GETFL);
- fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
- consoles[x].fd = s;
- consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
- if (ast_pthread_create_background(&consoles[x].t, &attr, netconsole, &consoles[x])) {
- ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
- close(consoles[x].p[0]);
- close(consoles[x].p[1]);
- consoles[x].fd = -1;
- fdprint(s, "Server failed to spawn thread\n");
- close(s);
- }
- break;
- }
- }
- if (x >= AST_MAX_CONNECTS) {
- fdprint(s, "No more connections allowed\n");
- ast_log(LOG_WARNING, "No more connections allowed\n");
- close(s);
- } else if (consoles[x].fd > -1) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n");
- }
- }
- }
- return NULL;
-}
-
-static int ast_makesocket(void)
-{
- struct sockaddr_un sunaddr;
- int res;
- int x;
- uid_t uid = -1;
- gid_t gid = -1;
-
- for (x = 0; x < AST_MAX_CONNECTS; x++)
- consoles[x].fd = -1;
- unlink(ast_config_AST_SOCKET);
- ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
- if (ast_socket < 0) {
- ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
- return -1;
- }
- memset(&sunaddr, 0, sizeof(sunaddr));
- sunaddr.sun_family = AF_LOCAL;
- ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
- res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
- if (res) {
- ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
- close(ast_socket);
- ast_socket = -1;
- return -1;
- }
- res = listen(ast_socket, 2);
- if (res < 0) {
- ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
- close(ast_socket);
- ast_socket = -1;
- return -1;
- }
- ast_register_verbose(network_verboser);
- ast_pthread_create_background(&lthread, NULL, listener, NULL);
-
- if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
- struct passwd *pw;
- if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL) {
- ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
- } else {
- uid = pw->pw_uid;
- }
- }
-
- if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
- struct group *grp;
- if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL) {
- ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
- } else {
- gid = grp->gr_gid;
- }
- }
-
- if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
- ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
-
- if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
- int p1;
- mode_t p;
- sscanf(ast_config_AST_CTL_PERMISSIONS, "%o", &p1);
- p = p1;
- if ((chmod(ast_config_AST_SOCKET, p)) < 0)
- ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
- }
-
- return 0;
-}
-
-static int ast_tryconnect(void)
-{
- struct sockaddr_un sunaddr;
- int res;
- ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
- if (ast_consock < 0) {
- ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
- return 0;
- }
- memset(&sunaddr, 0, sizeof(sunaddr));
- sunaddr.sun_family = AF_LOCAL;
- ast_copy_string(sunaddr.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
- res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
- if (res) {
- close(ast_consock);
- ast_consock = -1;
- return 0;
- } else
- return 1;
-}
-
-/*! \brief Urgent handler
-
- Called by soft_hangup to interrupt the poll, read, or other
- system call. We don't actually need to do anything though.
- Remember: Cannot EVER ast_log from within a signal handler
- */
-static void urg_handler(int num)
-{
- signal(num, urg_handler);
- return;
-}
-
-static void hup_handler(int num)
-{
- int a = 0;
- if (option_verbose > 1)
- printf("Received HUP signal -- Reloading configs\n");
- if (restartnow)
- execvp(_argv[0], _argv);
- sig_flags.need_reload = 1;
- if (sig_alert_pipe[1] != -1) {
- if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
- fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
- }
- }
- signal(num, hup_handler);
-}
-
-static void child_handler(int sig)
-{
- /* Must not ever ast_log or ast_verbose within signal handler */
- int n, status;
-
- /*
- * Reap all dead children -- not just one
- */
- for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
- ;
- if (n == 0 && option_debug)
- printf("Huh? Child handler, but nobody there?\n");
- signal(sig, child_handler);
-}
-
-/*! \brief Set an X-term or screen title */
-static void set_title(char *text)
-{
- if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
- fprintf(stdout, "\033]2;%s\007", text);
-}
-
-static void set_icon(char *text)
-{
- if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
- fprintf(stdout, "\033]1;%s\007", text);
-}
-
-/*! \brief We set ourselves to a high priority, that we might pre-empt everything
- else. If your PBX has heavy activity on it, this is a good thing. */
-int ast_set_priority(int pri)
-{
- struct sched_param sched;
- memset(&sched, 0, sizeof(sched));
-#ifdef __linux__
- if (pri) {
- sched.sched_priority = 10;
- if (sched_setscheduler(0, SCHED_RR, &sched)) {
- ast_log(LOG_WARNING, "Unable to set high priority\n");
- return -1;
- } else
- if (option_verbose)
- ast_verbose("Set to realtime thread\n");
- } else {
- sched.sched_priority = 0;
- /* According to the manpage, these parameters can never fail. */
- sched_setscheduler(0, SCHED_OTHER, &sched);
- }
-#else
- if (pri) {
- if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
- ast_log(LOG_WARNING, "Unable to set high priority\n");
- return -1;
- } else
- if (option_verbose)
- ast_verbose("Set to high priority\n");
- } else {
- /* According to the manpage, these parameters can never fail. */
- setpriority(PRIO_PROCESS, 0, 0);
- }
-#endif
- return 0;
-}
-
-static void ast_run_atexits(void)
-{
- struct ast_atexit *ae;
- AST_LIST_LOCK(&atexits);
- AST_LIST_TRAVERSE(&atexits, ae, list) {
- if (ae->func)
- ae->func();
- }
- AST_LIST_UNLOCK(&atexits);
-}
-
-static void quit_handler(int num, int nice, int safeshutdown, int restart)
-{
- char filename[80] = "";
- time_t s,e;
- int x;
- /* Try to get as many CDRs as possible submitted to the backend engines (if in batch mode) */
- ast_cdr_engine_term();
- if (safeshutdown) {
- shuttingdown = 1;
- if (!nice) {
- /* Begin shutdown routine, hanging up active channels */
- ast_begin_shutdown(1);
- if (option_verbose && ast_opt_console)
- ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
- time(&s);
- for (;;) {
- time(&e);
- /* Wait up to 15 seconds for all channels to go away */
- if ((e - s) > 15)
- break;
- if (!ast_active_channels())
- break;
- if (!shuttingdown)
- break;
- /* Sleep 1/10 of a second */
- usleep(100000);
- }
- } else {
- if (nice < 2)
- ast_begin_shutdown(0);
- if (option_verbose && ast_opt_console)
- ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
- for (;;) {
- if (!ast_active_channels())
- break;
- if (!shuttingdown)
- break;
- sleep(1);
- }
- }
-
- if (!shuttingdown) {
- if (option_verbose && ast_opt_console)
- ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
- return;
- }
-
- if (nice)
- ast_module_shutdown();
- }
- if (ast_opt_console || ast_opt_remote) {
- if (getenv("HOME"))
- snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
- if (!ast_strlen_zero(filename))
- ast_el_write_history(filename);
- if (el != NULL)
- el_end(el);
- if (el_hist != NULL)
- history_end(el_hist);
- }
- if (option_verbose)
- ast_verbose("Executing last minute cleanups\n");
- ast_run_atexits();
- /* Called on exit */
- if (option_verbose && ast_opt_console)
- ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
- if (option_debug)
- ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
- manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
- if (ast_socket > -1) {
- pthread_cancel(lthread);
- close(ast_socket);
- ast_socket = -1;
- unlink(ast_config_AST_SOCKET);
- }
- if (ast_consock > -1)
- close(ast_consock);
- if (!ast_opt_remote)
- unlink(ast_config_AST_PID);
- printf("%s", term_quit());
- if (restart) {
- if (option_verbose || ast_opt_console)
- ast_verbose("Preparing for Asterisk restart...\n");
- /* Mark all FD's for closing on exec */
- for (x=3; x < 32768; x++) {
- fcntl(x, F_SETFD, FD_CLOEXEC);
- }
- if (option_verbose || ast_opt_console)
- ast_verbose("Asterisk is now restarting...\n");
- restartnow = 1;
-
- /* close logger */
- close_logger();
-
- /* If there is a consolethread running send it a SIGHUP
- so it can execvp, otherwise we can do it ourselves */
- if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
- pthread_kill(consolethread, SIGHUP);
- /* Give the signal handler some time to complete */
- sleep(2);
- } else
- execvp(_argv[0], _argv);
-
- } else {
- /* close logger */
- close_logger();
- }
- exit(0);
-}
-
-static void __quit_handler(int num)
-{
- int a = 0;
- sig_flags.need_quit = 1;
- if (sig_alert_pipe[1] != -1) {
- if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
- fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
- }
- }
- /* There is no need to restore the signal handler here, since the app
- * is going to exit */
-}
-
-static void __remote_quit_handler(int num)
-{
- sig_flags.need_quit = 1;
-}
-
-static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
-{
- const char *c;
-
- /* Check for verboser preamble */
- if (*s == 127) {
- s++;
- }
-
- if (!strncmp(s, cmp, strlen(cmp))) {
- c = s + strlen(cmp);
- term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
- return c;
- }
- return NULL;
-}
-
-static void console_verboser(const char *s)
-{
- char tmp[80];
- const char *c = NULL;
-
- if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
- (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
- (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
- (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1))) {
- fputs(tmp, stdout);
- fputs(c, stdout);
- } else {
- if (*s == 127) {
- s++;
- }
- fputs(s, stdout);
- }
-
- fflush(stdout);
-
- /* Wake up a poll()ing console */
- if (ast_opt_console && consolethread != AST_PTHREADT_NULL)
- pthread_kill(consolethread, SIGURG);
-}
-
-static int ast_all_zeros(char *s)
-{
- while (*s) {
- if (*s > 32)
- return 0;
- s++;
- }
- return 1;
-}
-
-static void consolehandler(char *s)
-{
- printf("%s", term_end());
- fflush(stdout);
-
- /* Called when readline data is available */
- if (!ast_all_zeros(s))
- ast_el_add_history(s);
- /* The real handler for bang */
- if (s[0] == '!') {
- if (s[1])
- ast_safe_system(s+1);
- else
- ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
- } else
- ast_cli_command(STDOUT_FILENO, s);
-}
-
-static int remoteconsolehandler(char *s)
-{
- int ret = 0;
-
- /* Called when readline data is available */
- if (!ast_all_zeros(s))
- ast_el_add_history(s);
- /* The real handler for bang */
- if (s[0] == '!') {
- if (s[1])
- ast_safe_system(s+1);
- else
- ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
- ret = 1;
- }
- if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
- (s[4] == '\0' || isspace(s[4]))) {
- quit_handler(0, 0, 0, 0);
- ret = 1;
- }
-
- return ret;
-}
-
-static char abort_halt_help[] =
-"Usage: abort shutdown\n"
-" Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
-" call operations.\n";
-
-static char shutdown_now_help[] =
-"Usage: stop now\n"
-" Shuts down a running Asterisk immediately, hanging up all active calls .\n";
-
-static char shutdown_gracefully_help[] =
-"Usage: stop gracefully\n"
-" Causes Asterisk to not accept new calls, and exit when all\n"
-" active calls have terminated normally.\n";
-
-static char shutdown_when_convenient_help[] =
-"Usage: stop when convenient\n"
-" Causes Asterisk to perform a shutdown when all active calls have ended.\n";
-
-static char restart_now_help[] =
-"Usage: restart now\n"
-" Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
-" restart.\n";
-
-static char restart_gracefully_help[] =
-"Usage: restart gracefully\n"
-" Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
-" restart when all active calls have ended.\n";
-
-static char restart_when_convenient_help[] =
-"Usage: restart when convenient\n"
-" Causes Asterisk to perform a cold restart when all active calls have ended.\n";
-
-static char bang_help[] =
-"Usage: !<command>\n"
-" Executes a given shell command\n";
-
-static char show_warranty_help[] =
-"Usage: core show warranty\n"
-" Shows the warranty (if any) for this copy of Asterisk.\n";
-
-static char show_license_help[] =
-"Usage: core show license\n"
-" Shows the license(s) for this copy of Asterisk.\n";
-
-static char version_help[] =
-"Usage: core show version\n"
-" Shows Asterisk version information.\n";
-
-static int handle_version_deprecated(int fd, int argc, char *argv[])
-{
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- ast_cli(fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
- ASTERISK_VERSION, ast_build_user, ast_build_hostname,
- ast_build_machine, ast_build_os, ast_build_date);
- return RESULT_SUCCESS;
-}
-
-static int handle_version(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_cli(fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
- ASTERISK_VERSION, ast_build_user, ast_build_hostname,
- ast_build_machine, ast_build_os, ast_build_date);
- return RESULT_SUCCESS;
-}
-
-#if 0
-static int handle_quit(int fd, int argc, char *argv[])
-{
- if (argc != 1)
- return RESULT_SHOWUSAGE;
- quit_handler(0, 0, 1, 0);
- return RESULT_SUCCESS;
-}
-#endif
-
-static int handle_shutdown_now(int fd, int argc, char *argv[])
-{
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- quit_handler(0, 0 /* Not nice */, 1 /* safely */, 0 /* not restart */);
- return RESULT_SUCCESS;
-}
-
-static int handle_shutdown_gracefully(int fd, int argc, char *argv[])
-{
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- quit_handler(0, 1 /* nicely */, 1 /* safely */, 0 /* no restart */);
- return RESULT_SUCCESS;
-}
-
-static int handle_shutdown_when_convenient(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_cli(fd, "Waiting for inactivity to perform halt\n");
- quit_handler(0, 2 /* really nicely */, 1 /* safely */, 0 /* don't restart */);
- return RESULT_SUCCESS;
-}
-
-static int handle_restart_now(int fd, int argc, char *argv[])
-{
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- quit_handler(0, 0 /* not nicely */, 1 /* safely */, 1 /* restart */);
- return RESULT_SUCCESS;
-}
-
-static int handle_restart_gracefully(int fd, int argc, char *argv[])
-{
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- quit_handler(0, 1 /* nicely */, 1 /* safely */, 1 /* restart */);
- return RESULT_SUCCESS;
-}
-
-static int handle_restart_when_convenient(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_cli(fd, "Waiting for inactivity to perform restart\n");
- quit_handler(0, 2 /* really nicely */, 1 /* safely */, 1 /* restart */);
- return RESULT_SUCCESS;
-}
-
-static int handle_abort_halt(int fd, int argc, char *argv[])
-{
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- ast_cancel_shutdown();
- shuttingdown = 0;
- return RESULT_SUCCESS;
-}
-
-static int handle_bang(int fd, int argc, char *argv[])
-{
- return RESULT_SUCCESS;
-}
-static const char *warranty_lines[] = {
- "\n",
- " NO WARRANTY\n",
- "\n",
- "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n",
- "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n",
- "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n",
- "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n",
- "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n",
- "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n",
- "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n",
- "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n",
- "REPAIR OR CORRECTION.\n",
- "\n",
- "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n",
- "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n",
- "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n",
- "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n",
- "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n",
- "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n",
- "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n",
- "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n",
- "POSSIBILITY OF SUCH DAMAGES.\n",
-};
-
-static int show_warranty(int fd, int argc, char *argv[])
-{
- int x;
-
- for (x = 0; x < ARRAY_LEN(warranty_lines); x++)
- ast_cli(fd, "%s", (char *) warranty_lines[x]);
-
- return RESULT_SUCCESS;
-}
-
-static const char *license_lines[] = {
- "\n",
- "This program is free software; you can redistribute it and/or modify\n",
- "it under the terms of the GNU General Public License version 2 as\n",
- "published by the Free Software Foundation.\n",
- "\n",
- "This program also contains components licensed under other licenses.\n",
- "They include:\n",
- "\n",
- "This program is distributed in the hope that it will be useful,\n",
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n",
- "GNU General Public License for more details.\n",
- "\n",
- "You should have received a copy of the GNU General Public License\n",
- "along with this program; if not, write to the Free Software\n",
- "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n",
-};
-
-static int show_license(int fd, int argc, char *argv[])
-{
- int x;
-
- for (x = 0; x < ARRAY_LEN(license_lines); x++)
- ast_cli(fd, "%s", (char *) license_lines[x]);
-
- return RESULT_SUCCESS;
-}
-
-#define ASTERISK_PROMPT "*CLI> "
-
-#define ASTERISK_PROMPT2 "%s*CLI> "
-
-static struct ast_cli_entry cli_show_version_deprecated = {
- { "show", "version", NULL },
- handle_version_deprecated, "Display version info",
- version_help };
-
-#if !defined(LOW_MEMORY)
-static struct ast_cli_entry cli_show_version_files_deprecated = {
- { "show", "version", "files", NULL },
- handle_show_version_files_deprecated, NULL,
- NULL, complete_show_version_files_deprecated };
-
-static struct ast_cli_entry cli_show_profile_deprecated = {
- { "show", "profile", NULL },
- handle_show_profile_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_clear_profile_deprecated = {
- { "clear", "profile", NULL },
- handle_show_profile_deprecated, NULL,
- NULL };
-#endif /* ! LOW_MEMORY */
-
-static struct ast_cli_entry cli_asterisk[] = {
- { { "abort", "halt", NULL },
- handle_abort_halt, "Cancel a running halt",
- abort_halt_help },
-
- { { "stop", "now", NULL },
- handle_shutdown_now, "Shut down Asterisk immediately",
- shutdown_now_help },
-
- { { "stop", "gracefully", NULL },
- handle_shutdown_gracefully, "Gracefully shut down Asterisk",
- shutdown_gracefully_help },
-
- { { "stop", "when", "convenient", NULL },
- handle_shutdown_when_convenient, "Shut down Asterisk at empty call volume",
- shutdown_when_convenient_help },
-
- { { "restart", "now", NULL },
- handle_restart_now, "Restart Asterisk immediately", restart_now_help },
-
- { { "restart", "gracefully", NULL },
- handle_restart_gracefully, "Restart Asterisk gracefully",
- restart_gracefully_help },
-
- { { "restart", "when", "convenient", NULL },
- handle_restart_when_convenient, "Restart Asterisk at empty call volume",
- restart_when_convenient_help },
-
- { { "core", "show", "warranty", NULL },
- show_warranty, "Show the warranty (if any) for this copy of Asterisk",
- show_warranty_help },
-
- { { "core", "show", "license", NULL },
- show_license, "Show the license(s) for this copy of Asterisk",
- show_license_help },
-
- { { "core", "show", "version", NULL },
- handle_version, "Display version info",
- version_help, NULL, &cli_show_version_deprecated },
-
- { { "!", NULL },
- handle_bang, "Execute a shell command",
- bang_help },
-
-#if !defined(LOW_MEMORY)
- { { "core", "show", "file", "version", NULL },
- handle_show_version_files, "List versions of files used to build Asterisk",
- show_version_files_help, complete_show_version_files, &cli_show_version_files_deprecated },
-
- { { "core", "show", "threads", NULL },
- handle_show_threads, "Show running threads",
- show_threads_help },
-
- { { "core", "show", "profile", NULL },
- handle_show_profile, "Display profiling info",
- NULL, NULL, &cli_show_profile_deprecated },
-
- { { "core", "clear", "profile", NULL },
- handle_show_profile, "Clear profiling info",
- NULL, NULL, &cli_clear_profile_deprecated },
-#endif /* ! LOW_MEMORY */
-};
-
-static int ast_el_read_char(EditLine *el, char *cp)
-{
- int num_read = 0;
- int lastpos = 0;
- struct pollfd fds[2];
- int res;
- int max;
-#define EL_BUF_SIZE 512
- char buf[EL_BUF_SIZE];
-
- for (;;) {
- max = 1;
- fds[0].fd = ast_consock;
- fds[0].events = POLLIN;
- if (!ast_opt_exec) {
- fds[1].fd = STDIN_FILENO;
- fds[1].events = POLLIN;
- max++;
- }
- res = poll(fds, max, -1);
- if (res < 0) {
- if (sig_flags.need_quit)
- break;
- if (errno == EINTR)
- continue;
- ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
- break;
- }
-
- if (!ast_opt_exec && fds[1].revents) {
- num_read = read(STDIN_FILENO, cp, 1);
- if (num_read < 1) {
- break;
- } else
- return (num_read);
- }
- if (fds[0].revents) {
- char *tmp;
- res = read(ast_consock, buf, sizeof(buf) - 1);
- /* if the remote side disappears exit */
- if (res < 1) {
- fprintf(stderr, "\nDisconnected from Asterisk server\n");
- if (!ast_opt_reconnect) {
- quit_handler(0, 0, 0, 0);
- } else {
- int tries;
- int reconnects_per_second = 20;
- fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
- for (tries=0; tries < 30 * reconnects_per_second; tries++) {
- if (ast_tryconnect()) {
- fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
- printf("%s", term_quit());
- WELCOME_MESSAGE;
- if (!ast_opt_mute)
- fdsend(ast_consock, "logger mute silent");
- else
- printf("log and verbose output currently muted ('logger mute' to unmute)\n");
- break;
- } else {
- usleep(1000000 / reconnects_per_second);
- }
- }
- if (tries >= 30 * reconnects_per_second) {
- fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
- quit_handler(0, 0, 0, 0);
- }
- }
- }
-
- buf[res] = '\0';
-
- /* Strip preamble from asynchronous events, too */
- for (tmp = buf; *tmp; tmp++) {
- if (*tmp == 127) {
- memmove(tmp, tmp + 1, strlen(tmp));
- tmp--;
- }
- }
-
- /* Write over the CLI prompt */
- if (!ast_opt_exec && !lastpos) {
- if (write(STDOUT_FILENO, "\r", 1) < 0) {
- }
- }
- if (write(STDOUT_FILENO, buf, res) < 0) {
- }
- if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
- *cp = CC_REFRESH;
- return(1);
- } else {
- lastpos = 1;
- }
- }
- }
-
- *cp = '\0';
- return (0);
-}
-
-static char *cli_prompt(EditLine *el)
-{
- static char prompt[200];
- char *pfmt;
- int color_used = 0;
- char term_code[20];
-
- if ((pfmt = getenv("ASTERISK_PROMPT"))) {
- char *t = pfmt, *p = prompt;
- memset(prompt, 0, sizeof(prompt));
- while (*t != '\0' && *p < sizeof(prompt)) {
- if (*t == '%') {
- char hostname[MAXHOSTNAMELEN]="";
- int i;
- time_t ts;
- struct tm tm;
-#ifdef linux
- FILE *LOADAVG;
-#endif
- int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
-
- t++;
- switch (*t) {
- case 'C': /* color */
- t++;
- if (sscanf(t, "%d;%d%n", &fgcolor, &bgcolor, &i) == 2) {
- strncat(p, term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
- t += i - 1;
- } else if (sscanf(t, "%d%n", &fgcolor, &i) == 1) {
- strncat(p, term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
- t += i - 1;
- }
-
- /* If the color has been reset correctly, then there's no need to reset it later */
- if ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) {
- color_used = 0;
- } else {
- color_used = 1;
- }
- break;
- case 'd': /* date */
- memset(&tm, 0, sizeof(tm));
- time(&ts);
- if (ast_localtime(&ts, &tm, NULL)) {
- strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
- }
- break;
- case 'h': /* hostname */
- if (!gethostname(hostname, sizeof(hostname) - 1)) {
- strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
- } else {
- strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
- }
- break;
- case 'H': /* short hostname */
- if (!gethostname(hostname, sizeof(hostname) - 1)) {
- for (i = 0; i < sizeof(hostname); i++) {
- if (hostname[i] == '.') {
- hostname[i] = '\0';
- break;
- }
- }
- strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
- } else {
- strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
- }
- break;
-#ifdef linux
- case 'l': /* load avg */
- t++;
- if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
- float avg1, avg2, avg3;
- int actproc, totproc, npid, which;
-
- if (fscanf(LOADAVG, "%f %f %f %d/%d %d",
- &avg1, &avg2, &avg3, &actproc, &totproc, &npid) != 6) {
- ast_log(LOG_WARNING, "parsing /proc/loadavg failed\n");
- fclose(LOADAVG);
- break;
- }
- if (sscanf(t, "%d", &which) == 1) {
- switch (which) {
- case 1:
- snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1);
- break;
- case 2:
- snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2);
- break;
- case 3:
- snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3);
- break;
- case 4:
- snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc);
- break;
- case 5:
- snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid);
- break;
- }
- }
- fclose(LOADAVG);
- }
- break;
-#endif
- case 's': /* Asterisk system name (from asterisk.conf) */
- strncat(p, ast_config_AST_SYSTEM_NAME, sizeof(prompt) - strlen(prompt) - 1);
- break;
- case 't': /* time */
- memset(&tm, 0, sizeof(tm));
- time(&ts);
- if (ast_localtime(&ts, &tm, NULL)) {
- strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
- }
- break;
- case '#': /* process console or remote? */
- if (!ast_opt_remote) {
- strncat(p, "#", sizeof(prompt) - strlen(prompt) - 1);
- } else {
- strncat(p, ">", sizeof(prompt) - strlen(prompt) - 1);
- }
- break;
- case '%': /* literal % */
- strncat(p, "%", sizeof(prompt) - strlen(prompt) - 1);
- break;
- case '\0': /* % is last character - prevent bug */
- t--;
- break;
- }
- while (*p != '\0') {
- p++;
- }
- t++;
- } else {
- *p = *t;
- p++;
- t++;
- }
- }
- if (color_used) {
- /* Force colors back to normal at end */
- term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code));
- if (strlen(term_code) > sizeof(prompt) - strlen(prompt) - 1) {
- ast_copy_string(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code) + 1);
- } else {
- /* This looks wrong, but we've already checked the length of term_code to ensure it's safe */
- strncat(p, term_code, sizeof(term_code));
- }
- }
- } else if (remotehostname)
- snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
- else
- snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT);
-
- return(prompt);
-}
-
-static char **ast_el_strtoarr(char *buf)
-{
- char **match_list = NULL, *retstr;
- size_t match_list_len;
- int matches = 0;
-
- match_list_len = 1;
- while ( (retstr = strsep(&buf, " ")) != NULL) {
-
- if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
- break;
- if (matches + 1 >= match_list_len) {
- match_list_len <<= 1;
- if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(char *)))) {
- /* TODO: Handle memory allocation failure */
- }
- }
-
- match_list[matches++] = strdup(retstr);
- }
-
- if (!match_list)
- return (char **) NULL;
-
- if (matches >= match_list_len) {
- if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *)))) {
- /* TODO: Handle memory allocation failure */
- }
- }
-
- match_list[matches] = (char *) NULL;
-
- return match_list;
-}
-
-static int ast_el_sort_compare(const void *i1, const void *i2)
-{
- char *s1, *s2;
-
- s1 = ((char **)i1)[0];
- s2 = ((char **)i2)[0];
-
- return strcasecmp(s1, s2);
-}
-
-static int ast_cli_display_match_list(char **matches, int len, int max)
-{
- int i, idx, limit, count;
- int screenwidth = 0;
- int numoutput = 0, numoutputline = 0;
-
- screenwidth = ast_get_termcols(STDOUT_FILENO);
-
- /* find out how many entries can be put on one line, with two spaces between strings */
- limit = screenwidth / (max + 2);
- if (limit == 0)
- limit = 1;
-
- /* how many lines of output */
- count = len / limit;
- if (count * limit < len)
- count++;
-
- idx = 1;
-
- qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
-
- for (; count > 0; count--) {
- numoutputline = 0;
- for (i=0; i < limit && matches[idx]; i++, idx++) {
-
- /* Don't print dupes */
- if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
- i--;
- free(matches[idx]);
- matches[idx] = NULL;
- continue;
- }
-
- numoutput++;
- numoutputline++;
- fprintf(stdout, "%-*s ", max, matches[idx]);
- free(matches[idx]);
- matches[idx] = NULL;
- }
- if (numoutputline > 0)
- fprintf(stdout, "\n");
- }
-
- return numoutput;
-}
-
-
-static char *cli_complete(EditLine *el, int ch)
-{
- int len = 0;
- char *ptr;
- int nummatches = 0;
- char **matches;
- int retval = CC_ERROR;
- char buf[2048];
- int res;
-
- LineInfo *lf = (LineInfo *)el_line(el);
-
- *(char *)lf->cursor = '\0';
- ptr = (char *)lf->cursor;
- if (ptr) {
- while (ptr > lf->buffer) {
- if (isspace(*ptr)) {
- ptr++;
- break;
- }
- ptr--;
- }
- }
-
- len = lf->cursor - ptr;
-
- if (ast_opt_remote) {
- snprintf(buf, sizeof(buf),"_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
- fdsend(ast_consock, buf);
- res = read(ast_consock, buf, sizeof(buf));
- buf[res] = '\0';
- nummatches = atoi(buf);
-
- if (nummatches > 0) {
- char *mbuf;
- int mlen = 0, maxmbuf = 2048;
- /* Start with a 2048 byte buffer */
- if (!(mbuf = ast_malloc(maxmbuf)))
- return (char *)(CC_ERROR);
- snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
- fdsend(ast_consock, buf);
- res = 0;
- mbuf[0] = '\0';
- while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
- if (mlen + 1024 > maxmbuf) {
- /* Every step increment buffer 1024 bytes */
- maxmbuf += 1024;
- if (!(mbuf = ast_realloc(mbuf, maxmbuf)))
- return (char *)(CC_ERROR);
- }
- /* Only read 1024 bytes at a time */
- res = read(ast_consock, mbuf + mlen, 1024);
- if (res > 0)
- mlen += res;
- }
- mbuf[mlen] = '\0';
-
- matches = ast_el_strtoarr(mbuf);
- free(mbuf);
- } else
- matches = (char **) NULL;
- } else {
- char **p, *oldbuf=NULL;
- nummatches = 0;
- matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
- for (p = matches; p && *p; p++) {
- if (!oldbuf || strcmp(*p,oldbuf))
- nummatches++;
- oldbuf = *p;
- }
- }
-
- if (matches) {
- int i;
- int matches_num, maxlen, match_len;
-
- if (matches[0][0] != '\0') {
- el_deletestr(el, (int) len);
- el_insertstr(el, matches[0]);
- retval = CC_REFRESH;
- }
-
- if (nummatches == 1) {
- /* Found an exact match */
- el_insertstr(el, " ");
- retval = CC_REFRESH;
- } else {
- /* Must be more than one match */
- for (i=1, maxlen=0; matches[i]; i++) {
- match_len = strlen(matches[i]);
- if (match_len > maxlen)
- maxlen = match_len;
- }
- matches_num = i - 1;
- if (matches_num >1) {
- fprintf(stdout, "\n");
- ast_cli_display_match_list(matches, nummatches, maxlen);
- retval = CC_REDISPLAY;
- } else {
- el_insertstr(el," ");
- retval = CC_REFRESH;
- }
- }
- for (i = 0; matches[i]; i++)
- free(matches[i]);
- free(matches);
- }
-
- return (char *)(long)retval;
-}
-
-static int ast_el_initialize(void)
-{
- HistEvent ev;
- char *editor = getenv("AST_EDITOR");
-
- if (el != NULL)
- el_end(el);
- if (el_hist != NULL)
- history_end(el_hist);
-
- el = el_init("asterisk", stdin, stdout, stderr);
- el_set(el, EL_PROMPT, cli_prompt);
-
- el_set(el, EL_EDITMODE, 1);
- el_set(el, EL_EDITOR, editor ? editor : "emacs");
- el_hist = history_init();
- if (!el || !el_hist)
- return -1;
-
- /* setup history with 100 entries */
- history(el_hist, &ev, H_SETSIZE, 100);
-
- el_set(el, EL_HIST, history, el_hist);
-
- el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
- /* Bind <tab> to command completion */
- el_set(el, EL_BIND, "^I", "ed-complete", NULL);
- /* Bind ? to command completion */
- el_set(el, EL_BIND, "?", "ed-complete", NULL);
- /* Bind ^D to redisplay */
- el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
-
- return 0;
-}
-
-static int ast_el_add_history(char *buf)
-{
- HistEvent ev;
-
- if (el_hist == NULL || el == NULL)
- ast_el_initialize();
- if (strlen(buf) > 256)
- return 0;
- return (history(el_hist, &ev, H_ENTER, buf));
-}
-
-static int ast_el_write_history(char *filename)
-{
- HistEvent ev;
-
- if (el_hist == NULL || el == NULL)
- ast_el_initialize();
-
- return (history(el_hist, &ev, H_SAVE, filename));
-}
-
-static int ast_el_read_history(char *filename)
-{
- char buf[256];
- FILE *f;
- int ret = -1;
-
- if (el_hist == NULL || el == NULL)
- ast_el_initialize();
-
- if ((f = fopen(filename, "r")) == NULL)
- return ret;
-
- while (!feof(f)) {
- if (!fgets(buf, sizeof(buf), f)) {
- continue;
- }
- if (!strcmp(buf, "_HiStOrY_V2_\n"))
- continue;
- if (ast_all_zeros(buf))
- continue;
- if ((ret = ast_el_add_history(buf)) == -1)
- break;
- }
- fclose(f);
-
- return ret;
-}
-
-static void ast_remotecontrol(char *data)
-{
- char buf[80];
- int res;
- char filename[80] = "";
- char *hostname;
- char *cpid;
- char *version;
- int pid;
- char tmp[80];
- char *stringp = NULL;
-
- char *ebuf;
- int num = 0;
-
- memset(&sig_flags, 0, sizeof(sig_flags));
- signal(SIGINT, __remote_quit_handler);
- signal(SIGTERM, __remote_quit_handler);
- signal(SIGHUP, __remote_quit_handler);
-
- if (read(ast_consock, buf, sizeof(buf)) < 0) {
- ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
- return;
- }
- if (data) {
- if (write(ast_consock, data, strlen(data) + 1) < 0) {
- ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
- if (sig_flags.need_quit == 1) {
- return;
- }
- }
- }
- stringp = buf;
- hostname = strsep(&stringp, "/");
- cpid = strsep(&stringp, "/");
- version = strsep(&stringp, "\n");
- if (!version)
- version = "<Version Unknown>";
- stringp = hostname;
- strsep(&stringp, ".");
- if (cpid)
- pid = atoi(cpid);
- else
- pid = -1;
- if (!data) {
- snprintf(tmp, sizeof(tmp), "core set verbose atleast %d", option_verbose);
- fdsend(ast_consock, tmp);
- snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug);
- fdsend(ast_consock, tmp);
- if (!ast_opt_mute)
- fdsend(ast_consock, "logger mute silent");
- else
- printf("log and verbose output currently muted ('logger mute' to unmute)\n");
- }
- ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
- remotehostname = hostname;
- if (getenv("HOME"))
- snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
- if (el_hist == NULL || el == NULL)
- ast_el_initialize();
-
- el_set(el, EL_GETCFN, ast_el_read_char);
-
- if (!ast_strlen_zero(filename))
- ast_el_read_history(filename);
-
- if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */
- struct pollfd fds;
- fds.fd = ast_consock;
- fds.events = POLLIN;
- fds.revents = 0;
- while (poll(&fds, 1, 500) > 0) {
- char buf[512] = "", *curline = buf, *nextline;
- int not_written = 1;
-
- if (sig_flags.need_quit == 1) {
- break;
- }
-
- if (read(ast_consock, buf, sizeof(buf) - 1) <= 0) {
- break;
- }
-
- do {
- if ((nextline = strchr(curline, '\n'))) {
- nextline++;
- } else {
- nextline = strchr(curline, '\0');
- }
-
- /* Skip verbose lines */
- if (*curline != 127) {
- not_written = 0;
- if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
- ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
- }
- }
- curline = nextline;
- } while (!ast_strlen_zero(curline));
-
- /* No non-verbose output in 500ms */
- if (not_written) {
- break;
- }
- }
- return;
- }
- for (;;) {
- ebuf = (char *)el_gets(el, &num);
-
- if (sig_flags.need_quit == 1) {
- break;
- }
-
- if (!ebuf && write(1, "", 1) < 0)
- break;
-
- if (!ast_strlen_zero(ebuf)) {
- if (ebuf[strlen(ebuf)-1] == '\n')
- ebuf[strlen(ebuf)-1] = '\0';
- if (!remoteconsolehandler(ebuf)) {
- /* Strip preamble from output */
- char *tmp;
- for (tmp = ebuf; *tmp; tmp++) {
- if (*tmp == 127) {
- memmove(tmp, tmp + 1, strlen(tmp));
- tmp--;
- }
- }
- res = write(ast_consock, ebuf, strlen(ebuf) + 1);
- if (res < 1) {
- ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
- break;
- }
- }
- }
- }
- printf("\nDisconnected from Asterisk server\n");
-}
-
-static int show_version(void)
-{
- printf("Asterisk " ASTERISK_VERSION "\n");
- return 0;
-}
-
-static int show_cli_help(void) {
- printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2008, Digium, Inc. and others.\n");
- printf("Usage: asterisk [OPTIONS]\n");
- printf("Valid Options:\n");
- printf(" -V Display version number and exit\n");
- printf(" -C <configfile> Use an alternate configuration file\n");
- printf(" -G <group> Run as a group other than the caller\n");
- printf(" -U <user> Run as a user other than the caller\n");
- printf(" -c Provide console CLI\n");
- printf(" -d Enable extra debugging\n");
-#if HAVE_WORKING_FORK
- printf(" -f Do not fork\n");
- printf(" -F Always fork\n");
-#endif
- printf(" -g Dump core in case of a crash\n");
- printf(" -h This help screen\n");
- printf(" -i Initialize crypto keys at startup\n");
- printf(" -I Enable internal timing if %s timer is available\n", dahdi_chan_name);
- printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
- printf(" -M <value> Limit the maximum number of calls to the specified value\n");
- printf(" -m Mute debugging and console output on the console\n");
- printf(" -n Disable console colorization\n");
- printf(" -p Run as pseudo-realtime thread\n");
- printf(" -q Quiet mode (suppress output)\n");
- printf(" -r Connect to Asterisk on this machine\n");
- printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
- printf(" -t Record soundfiles in /var/tmp and move them where they\n");
- printf(" belong after they are done\n");
- printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
- printf(" of output to the CLI\n");
- printf(" -v Increase verbosity (multiple v's = more verbose)\n");
- printf(" -x <cmd> Execute command <cmd> (only valid with -r)\n");
- printf("\n");
- return 0;
-}
-
-static void ast_readconfig(void)
-{
- struct ast_config *cfg;
- struct ast_variable *v;
- char *config = AST_CONFIG_FILE;
-
- if (ast_opt_override_config) {
- cfg = ast_config_load(ast_config_AST_CONFIG_FILE);
- if (!cfg)
- ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
- } else {
- cfg = ast_config_load(config);
- }
-
- /* init with buildtime config */
- ast_copy_string(ast_config_AST_CONFIG_DIR, AST_CONFIG_DIR, sizeof(ast_config_AST_CONFIG_DIR));
- ast_copy_string(ast_config_AST_SPOOL_DIR, AST_SPOOL_DIR, sizeof(ast_config_AST_SPOOL_DIR));
- ast_copy_string(ast_config_AST_MODULE_DIR, AST_MODULE_DIR, sizeof(ast_config_AST_MODULE_DIR));
- snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", ast_config_AST_SPOOL_DIR);
- ast_copy_string(ast_config_AST_VAR_DIR, AST_VAR_DIR, sizeof(ast_config_AST_VAR_DIR));
- ast_copy_string(ast_config_AST_DATA_DIR, AST_DATA_DIR, sizeof(ast_config_AST_DATA_DIR));
- ast_copy_string(ast_config_AST_LOG_DIR, AST_LOG_DIR, sizeof(ast_config_AST_LOG_DIR));
- ast_copy_string(ast_config_AST_AGI_DIR, AST_AGI_DIR, sizeof(ast_config_AST_AGI_DIR));
- ast_copy_string(ast_config_AST_DB, AST_DB, sizeof(ast_config_AST_DB));
- ast_copy_string(ast_config_AST_KEY_DIR, AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR));
- ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
- ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
- ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
-
- /* no asterisk.conf? no problem, use buildtime config! */
- if (!cfg) {
- return;
- }
-
- for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
- if (!strcasecmp(v->name, "astctlpermissions")) {
- ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
- } else if (!strcasecmp(v->name, "astctlowner")) {
- ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
- } else if (!strcasecmp(v->name, "astctlgroup")) {
- ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
- } else if (!strcasecmp(v->name, "astctl")) {
- ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
- }
- }
-
- for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
- if (!strcasecmp(v->name, "astetcdir")) {
- ast_copy_string(ast_config_AST_CONFIG_DIR, v->value, sizeof(ast_config_AST_CONFIG_DIR));
- } else if (!strcasecmp(v->name, "astspooldir")) {
- ast_copy_string(ast_config_AST_SPOOL_DIR, v->value, sizeof(ast_config_AST_SPOOL_DIR));
- snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", v->value);
- } else if (!strcasecmp(v->name, "astvarlibdir")) {
- ast_copy_string(ast_config_AST_VAR_DIR, v->value, sizeof(ast_config_AST_VAR_DIR));
- snprintf(ast_config_AST_DB, sizeof(ast_config_AST_DB), "%s/astdb", v->value);
- } else if (!strcasecmp(v->name, "astdatadir")) {
- ast_copy_string(ast_config_AST_DATA_DIR, v->value, sizeof(ast_config_AST_DATA_DIR));
- snprintf(ast_config_AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR), "%s/keys", v->value);
- } else if (!strcasecmp(v->name, "astlogdir")) {
- ast_copy_string(ast_config_AST_LOG_DIR, v->value, sizeof(ast_config_AST_LOG_DIR));
- } else if (!strcasecmp(v->name, "astagidir")) {
- ast_copy_string(ast_config_AST_AGI_DIR, v->value, sizeof(ast_config_AST_AGI_DIR));
- } else if (!strcasecmp(v->name, "astrundir")) {
- snprintf(ast_config_AST_PID, sizeof(ast_config_AST_PID), "%s/%s", v->value, "asterisk.pid");
- snprintf(ast_config_AST_SOCKET, sizeof(ast_config_AST_SOCKET), "%s/%s", v->value, ast_config_AST_CTL);
- ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
- } else if (!strcasecmp(v->name, "astmoddir")) {
- ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
- }
- }
-
- for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
- /* verbose level (-v at startup) */
- if (!strcasecmp(v->name, "verbose")) {
- option_verbose = atoi(v->value);
- /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
- } else if (!strcasecmp(v->name, "timestamp")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
- /* whether or not to support #exec in config files */
- } else if (!strcasecmp(v->name, "execincludes")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
- /* debug level (-d at startup) */
- } else if (!strcasecmp(v->name, "debug")) {
- option_debug = 0;
- if (sscanf(v->value, "%d", &option_debug) != 1) {
- option_debug = ast_true(v->value);
- }
-#if HAVE_WORKING_FORK
- /* Disable forking (-f at startup) */
- } else if (!strcasecmp(v->name, "nofork")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
- /* Always fork, even if verbose or debug are enabled (-F at startup) */
- } else if (!strcasecmp(v->name, "alwaysfork")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
-#endif
- /* Run quietly (-q at startup ) */
- } else if (!strcasecmp(v->name, "quiet")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
- /* Run as console (-c at startup, implies nofork) */
- } else if (!strcasecmp(v->name, "console")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CONSOLE);
- /* Run with high priority if the O/S permits (-p at startup) */
- } else if (!strcasecmp(v->name, "highpriority")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
- /* Initialize RSA auth keys (IAX2) (-i at startup) */
- } else if (!strcasecmp(v->name, "initcrypto")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
- /* Disable ANSI colors for console (-c at startup) */
- } else if (!strcasecmp(v->name, "nocolor")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
- /* Disable some usage warnings for picky people :p */
- } else if (!strcasecmp(v->name, "dontwarn")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
- /* Dump core in case of crash (-g) */
- } else if (!strcasecmp(v->name, "dumpcore")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
- /* Cache recorded sound files to another directory during recording */
- } else if (!strcasecmp(v->name, "cache_record_files")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
- /* Specify cache directory */
- } else if (!strcasecmp(v->name, "record_cache_dir")) {
- ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
- /* Build transcode paths via SLINEAR, instead of directly */
- } else if (!strcasecmp(v->name, "transcode_via_sln")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
- /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
- } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
- /* Enable internal timing */
- } else if (!strcasecmp(v->name, "internal_timing")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INTERNAL_TIMING);
- } else if (!strcasecmp(v->name, "maxcalls")) {
- if ((sscanf(v->value, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
- option_maxcalls = 0;
- }
- } else if (!strcasecmp(v->name, "maxload")) {
- double test[1];
-
- if (getloadavg(test, 1) == -1) {
- ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
- option_maxload = 0.0;
- } else if ((sscanf(v->value, "%lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
- option_maxload = 0.0;
- }
- /* What user to run as */
- } else if (!strcasecmp(v->name, "runuser")) {
- ast_copy_string(ast_config_AST_RUN_USER, v->value, sizeof(ast_config_AST_RUN_USER));
- /* What group to run as */
- } else if (!strcasecmp(v->name, "rungroup")) {
- ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
- } else if (!strcasecmp(v->name, "systemname")) {
- ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
- } else if (!strcasecmp(v->name, "languageprefix")) {
- ast_language_is_prefix = ast_true(v->value);
- } else if (!strcasecmp(v->name, "dahdichanname")) {
-#ifdef HAVE_ZAPTEL
- if (ast_true(v->value)) {
- strcpy(_dahdi_chan_name, "DAHDI");
- _dahdi_chan_name_len = 5;
- _dahdi_chan_mode = CHAN_DAHDI_PLUS_ZAP_MODE;
- }
-#else
- if (ast_false(v->value)) {
- strcpy(_dahdi_chan_name, "Zap");
- _dahdi_chan_name_len = 3;
- _dahdi_chan_mode = CHAN_ZAP_MODE;
- }
-#endif
- }
- }
- ast_config_destroy(cfg);
-}
-
-static void *monitor_sig_flags(void *unused)
-{
- for (;;) {
- struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
- int a;
- poll(&p, 1, -1);
- if (sig_flags.need_reload) {
- sig_flags.need_reload = 0;
- ast_module_reload(NULL);
- }
- if (sig_flags.need_quit) {
- sig_flags.need_quit = 0;
- quit_handler(0, 0, 1, 0);
- }
- if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) {
- }
- }
-
- return NULL;
-}
-
-int main(int argc, char *argv[])
-{
- int c;
- char filename[80] = "";
- char hostname[MAXHOSTNAMELEN] = "";
- char tmp[80];
- char * xarg = NULL;
- int x;
- FILE *f;
- sigset_t sigs;
- int num;
- int isroot = 1;
- char *buf;
- char *runuser = NULL, *rungroup = NULL;
-
- /* Remember original args for restart */
- if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
- fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
- argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
- }
- for (x=0; x<argc; x++)
- _argv[x] = argv[x];
- _argv[x] = NULL;
-
- if (geteuid() != 0)
- isroot = 0;
-
- /* if the progname is rasterisk consider it a remote console */
- if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
- ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
- }
- if (gethostname(hostname, sizeof(hostname)-1))
- ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
- ast_mainpid = getpid();
- ast_ulaw_init();
- ast_alaw_init();
- callerid_init();
- ast_builtins_init();
- ast_utils_init();
- tdd_init();
-
- if (getenv("HOME"))
- snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
- /* Check for options */
- while ((c = getopt(argc, argv, "mtThfFdvVqprRgciInx:U:G:C:L:M:")) != -1) {
- switch (c) {
-#if HAVE_WORKING_FORK
- case 'F':
- ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
- break;
- case 'f':
- ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
- break;
-#endif
- case 'd':
- option_debug++;
- ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
- break;
- case 'c':
- ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
- break;
- case 'n':
- ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
- break;
- case 'r':
- ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
- break;
- case 'R':
- ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
- break;
- case 'p':
- ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
- break;
- case 'v':
- option_verbose++;
- ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
- break;
- case 'm':
- ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
- break;
- case 'M':
- if ((sscanf(optarg, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0))
- option_maxcalls = 0;
- break;
- case 'L':
- if ((sscanf(optarg, "%lf", &option_maxload) != 1) || (option_maxload < 0.0))
- option_maxload = 0.0;
- break;
- case 'q':
- ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
- break;
- case 't':
- ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
- break;
- case 'T':
- ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
- break;
- case 'x':
- ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC);
- xarg = ast_strdupa(optarg);
- break;
- case 'C':
- ast_copy_string(ast_config_AST_CONFIG_FILE, optarg, sizeof(ast_config_AST_CONFIG_FILE));
- ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
- break;
- case 'I':
- ast_set_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING);
- break;
- case 'i':
- ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
- break;
- case 'g':
- ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
- break;
- case 'h':
- show_cli_help();
- exit(0);
- case 'V':
- show_version();
- exit(0);
- case 'U':
- runuser = ast_strdupa(optarg);
- break;
- case 'G':
- rungroup = ast_strdupa(optarg);
- break;
- case '?':
- exit(1);
- }
- }
-
- if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
- ast_register_verbose(console_verboser);
- WELCOME_MESSAGE;
- }
-
- if (ast_opt_console && !option_verbose)
- ast_verbose("[ Booting...\n");
-
- /* For remote connections, change the name of the remote connection.
- * We do this for the benefit of init scripts (which need to know if/when
- * the main asterisk process has died yet). */
- if (ast_opt_remote) {
- strcpy(argv[0], "rasterisk");
- for (x = 1; x < argc; x++) {
- argv[x] = argv[0] + 10;
- }
- }
-
- if (ast_opt_console && !option_verbose) {
- ast_verbose("[ Reading Master Configuration ]\n");
- }
-
- ast_readconfig();
-
- if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
- ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
- ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
- }
-
- if (ast_opt_dump_core) {
- struct rlimit l;
- memset(&l, 0, sizeof(l));
- l.rlim_cur = RLIM_INFINITY;
- l.rlim_max = RLIM_INFINITY;
- if (setrlimit(RLIMIT_CORE, &l)) {
- ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
- }
- }
-
- if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
- rungroup = ast_config_AST_RUN_GROUP;
- if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
- runuser = ast_config_AST_RUN_USER;
-
-#ifndef __CYGWIN__
-
- if (isroot)
- ast_set_priority(ast_opt_high_priority);
-
- if (isroot && rungroup) {
- struct group *gr;
- gr = getgrnam(rungroup);
- if (!gr) {
- ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
- exit(1);
- }
- if (setgid(gr->gr_gid)) {
- ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
- exit(1);
- }
- if (setgroups(0, NULL)) {
- ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
- exit(1);
- }
- if (option_verbose)
- ast_verbose("Running as group '%s'\n", rungroup);
- }
-
- if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
-#ifdef HAVE_CAP
- int has_cap = 1;
-#endif /* HAVE_CAP */
- struct passwd *pw;
- pw = getpwnam(runuser);
- if (!pw) {
- ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
- exit(1);
- }
-#ifdef HAVE_CAP
- if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
- ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
- has_cap = 0;
- }
-#endif /* HAVE_CAP */
- if (!isroot && pw->pw_uid != geteuid()) {
- ast_log(LOG_ERROR, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
- exit(1);
- }
- if (!rungroup) {
- if (setgid(pw->pw_gid)) {
- ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
- exit(1);
- }
- if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
- ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
- exit(1);
- }
- }
- if (setuid(pw->pw_uid)) {
- ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
- exit(1);
- }
- if (option_verbose)
- ast_verbose("Running as user '%s'\n", runuser);
-#ifdef HAVE_CAP
- if (has_cap) {
- cap_t cap;
-
- cap = cap_from_text("cap_net_admin=ep");
-
- if (cap_set_proc(cap))
- ast_log(LOG_WARNING, "Unable to install capabilities.\n");
-
- if (cap_free(cap))
- ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
- }
-#endif /* HAVE_CAP */
- }
-
-#endif /* __CYGWIN__ */
-
-#ifdef linux
- if (geteuid() && ast_opt_dump_core) {
- if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
- ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
- }
- }
-#endif
-
- ast_term_init();
- printf("%s", term_end());
- fflush(stdout);
-
- if (ast_opt_console && !option_verbose)
- ast_verbose("[ Initializing Custom Configuration Options ]\n");
- /* custom config setup */
- register_config_cli();
- read_config_maps();
-
- if (ast_opt_console) {
- if (el_hist == NULL || el == NULL)
- ast_el_initialize();
-
- if (!ast_strlen_zero(filename))
- ast_el_read_history(filename);
- }
-
- if (ast_tryconnect()) {
- /* One is already running */
- if (ast_opt_remote) {
- if (ast_opt_exec) {
- ast_remotecontrol(xarg);
- quit_handler(0, 0, 0, 0);
- exit(0);
- }
- printf("%s", term_quit());
- ast_remotecontrol(NULL);
- quit_handler(0, 0, 0, 0);
- exit(0);
- } else {
- ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
- printf("%s", term_quit());
- exit(1);
- }
- } else if (ast_opt_remote || ast_opt_exec) {
- ast_log(LOG_ERROR, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
- printf("%s", term_quit());
- exit(1);
- }
- /* Blindly write pid file since we couldn't connect */
- unlink(ast_config_AST_PID);
- f = fopen(ast_config_AST_PID, "w");
- if (f) {
- fprintf(f, "%ld\n", (long)getpid());
- fclose(f);
- } else
- ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
-
-#if HAVE_WORKING_FORK
- if (ast_opt_always_fork || !ast_opt_no_fork) {
-#ifndef HAVE_SBIN_LAUNCHD
- if (daemon(1, 0) < 0) {
- ast_log(LOG_ERROR, "daemon() failed: %s\n", strerror(errno));
- }
- ast_mainpid = getpid();
- /* Blindly re-write pid file since we are forking */
- unlink(ast_config_AST_PID);
- f = fopen(ast_config_AST_PID, "w");
- if (f) {
- fprintf(f, "%ld\n", (long)ast_mainpid);
- fclose(f);
- } else
- ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
-#else
- ast_log(LOG_WARNING, "Mac OS X detected. Use '/sbin/launchd -d' to launch with the nofork option.\n");
-#endif
- }
-#endif
-
- ast_makesocket();
- sigemptyset(&sigs);
- sigaddset(&sigs, SIGHUP);
- sigaddset(&sigs, SIGTERM);
- sigaddset(&sigs, SIGINT);
- sigaddset(&sigs, SIGPIPE);
- sigaddset(&sigs, SIGWINCH);
- pthread_sigmask(SIG_BLOCK, &sigs, NULL);
- signal(SIGURG, urg_handler);
- signal(SIGINT, __quit_handler);
- signal(SIGTERM, __quit_handler);
- signal(SIGHUP, hup_handler);
- signal(SIGCHLD, child_handler);
- signal(SIGPIPE, SIG_IGN);
-
- /* ensure that the random number generators are seeded with a different value every time
- Asterisk is started
- */
- srand((unsigned int) getpid() + (unsigned int) time(NULL));
- initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
-
- if (init_logger()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- dahdi_chan_name = _dahdi_chan_name;
- dahdi_chan_name_len = &_dahdi_chan_name_len;
- dahdi_chan_mode = &_dahdi_chan_mode;
-
-#ifdef HAVE_DAHDI
- {
- int fd;
- int x = 160;
- fd = open(DAHDI_FILE_TIMER, O_RDWR);
- if (fd >= 0) {
- if (ioctl(fd, DAHDI_TIMERCONFIG, &x)) {
- ast_log(LOG_ERROR, "You have " DAHDI_NAME
- " built and drivers loaded, but the "
- DAHDI_NAME " timer test failed to set DAHDI_TIMERCONFIG to %d.\n", x);
- exit(1);
- }
- if ((x = ast_wait_for_input(fd, 300)) < 0) {
- ast_log(LOG_ERROR, "You have " DAHDI_NAME
- "built and drivers loaded, but the "
- DAHDI_NAME " timer could not be polled during the "
- DAHDI_NAME " timer test.\n");
- exit(1);
- }
- if (!x) {
- const char dahdi_timer_error[] = {
- "Asterisk has detected a problem with your " DAHDI_NAME
- " configuration and will shutdown for your protection. You have options:"
- "\n\t1. You only have to compile " DAHDI_NAME
- " support into Asterisk if you need it. One option is to recompile without "
- DAHDI_NAME " support."
- "\n\t2. You only have to load " DAHDI_NAME " drivers if you want to take advantage of "
- DAHDI_NAME " services. One option is to unload "
- DAHDI_NAME " modules if you don't need them."
- "\n\t3. If you need Zaptel services, you must correctly configure " DAHDI_NAME "."
- };
- ast_log(LOG_ERROR, "%s\n", dahdi_timer_error);
- exit(1);
- }
- close(fd);
- }
- }
-#endif
- threadstorage_init();
-
- astobj2_init();
-
- ast_autoservice_init();
-
- if (load_modules(1)) {
- printf("%s", term_quit());
- exit(1);
- }
-
- if (dnsmgr_init()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- ast_http_init();
-
- ast_channels_init();
-
- if (ast_cdr_engine_init()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- if (ast_device_state_engine_init()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- ast_rtp_init();
-
- ast_udptl_init();
-
- if (ast_image_init()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- if (ast_file_init()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- if (load_pbx()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- if (init_framer()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- if (astdb_init()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- if (ast_enum_init()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- if (load_modules(0)) {
- printf("%s", term_quit());
- exit(1);
- }
-
- /* AMI is initialized after loading modules because of a potential
- * conflict between issuing a module reload from manager and
- * registering manager actions. This will cause reversed locking
- * order between the module list and manager actions list. */
- if (init_manager()) {
- printf("%s", term_quit());
- exit(1);
- }
-
- dnsmgr_start_refresh();
-
- /* We might have the option of showing a console, but for now just
- do nothing... */
- if (ast_opt_console && !option_verbose)
- ast_verbose(" ]\n");
- if (option_verbose || ast_opt_console)
- ast_verbose("%s", term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
- if (ast_opt_no_fork)
- consolethread = pthread_self();
-
- if (pipe(sig_alert_pipe))
- sig_alert_pipe[0] = sig_alert_pipe[1] = -1;
-
- ast_set_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED);
- pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
-
-#ifdef __AST_DEBUG_MALLOC
- __ast_mm_init();
-#endif
-
- time(&ast_startuptime);
- ast_cli_register_multiple(cli_asterisk, sizeof(cli_asterisk) / sizeof(struct ast_cli_entry));
-
- if (ast_opt_console) {
- /* Console stuff now... */
- /* Register our quit function */
- char title[256];
- pthread_attr_t attr;
- pthread_t dont_care;
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- ast_pthread_create(&dont_care, &attr, monitor_sig_flags, NULL);
- pthread_attr_destroy(&attr);
-
- set_icon("Asterisk");
- snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
- set_title(title);
-
- for (;;) {
- buf = (char *)el_gets(el, &num);
-
- if (!buf && write(1, "", 1) < 0)
- goto lostterm;
-
- if (buf) {
- if (buf[strlen(buf)-1] == '\n')
- buf[strlen(buf)-1] = '\0';
-
- consolehandler((char *)buf);
- } else if (ast_opt_remote && (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
- strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0)) {
- /* Whoa, stdout disappeared from under us... Make /dev/null's */
- int fd;
- fd = open("/dev/null", O_RDWR);
- if (fd > -1) {
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDIN_FILENO);
- } else
- ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
- break;
- }
- }
- }
-
- monitor_sig_flags(NULL);
-
-lostterm:
- return 0;
-}
diff --git a/main/astmm.c b/main/astmm.c
deleted file mode 100644
index b0eb51bf5..000000000
--- a/main/astmm.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Memory Management
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-#ifdef __AST_DEBUG_MALLOC
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <time.h>
-
-#include "asterisk/cli.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/lock.h"
-#include "asterisk/strings.h"
-#include "asterisk/unaligned.h"
-
-#define SOME_PRIME 563
-
-enum func_type {
- FUNC_CALLOC = 1,
- FUNC_MALLOC,
- FUNC_REALLOC,
- FUNC_STRDUP,
- FUNC_STRNDUP,
- FUNC_VASPRINTF,
- FUNC_ASPRINTF
-};
-
-/* Undefine all our macros */
-#undef malloc
-#undef calloc
-#undef realloc
-#undef strdup
-#undef strndup
-#undef free
-#undef vasprintf
-#undef asprintf
-
-#define FENCE_MAGIC 0xdeadbeef
-
-static FILE *mmlog;
-
-/* NOTE: Be EXTREMELY careful with modifying this structure; the total size of this structure
- must result in 'automatic' alignment so that the 'fence' field lands exactly at the end of
- the structure in memory (and thus immediately before the allocated region the fence is
- supposed to be used to monitor). In other words, we cannot allow the compiler to insert
- any padding between this structure and anything following it, so add up the sizes of all the
- fields and compare to sizeof(struct ast_region)... if they don't match, then the compiler
- is padding the structure and either the fields need to be rearranged to eliminate internal
- padding, or a dummy field will need to be inserted before the 'fence' field to push it to
- the end of the actual space it will consume. Note that this must be checked for both 32-bit
- and 64-bit platforms, as the sizes of pointers and 'size_t' differ on these platforms.
-*/
-
-static struct ast_region {
- struct ast_region *next;
- size_t len;
- char file[40];
- char func[40];
- unsigned int lineno;
- enum func_type which;
- unsigned int cache; /* region was allocated as part of a cache pool */
- unsigned int fence;
- unsigned char data[0];
-} *regions[SOME_PRIME];
-
-#define HASH(a) \
- (((unsigned long)(a)) % SOME_PRIME)
-
-AST_MUTEX_DEFINE_STATIC_NOTRACKING(reglock);
-
-#define astmm_log(...) \
- do { \
- fprintf(stderr, __VA_ARGS__); \
- if (mmlog) { \
- fprintf(mmlog, __VA_ARGS__); \
- fflush(mmlog); \
- } \
- } while (0)
-
-static inline void *__ast_alloc_region(size_t size, const enum func_type which, const char *file, int lineno, const char *func, unsigned int cache)
-{
- struct ast_region *reg;
- void *ptr = NULL;
- unsigned int *fence;
- int hash;
-
- if (!(reg = malloc(size + sizeof(*reg) + sizeof(*fence)))) {
- astmm_log("Memory Allocation Failure - '%d' bytes in function %s "
- "at line %d of %s\n", (int) size, func, lineno, file);
- }
-
- ast_copy_string(reg->file, file, sizeof(reg->file));
- ast_copy_string(reg->func, func, sizeof(reg->func));
- reg->lineno = lineno;
- reg->len = size;
- reg->which = which;
- reg->cache = cache;
- ptr = reg->data;
- hash = HASH(ptr);
- reg->fence = FENCE_MAGIC;
- fence = (ptr + reg->len);
- put_unaligned_uint32(fence, FENCE_MAGIC);
-
- ast_mutex_lock(&reglock);
- reg->next = regions[hash];
- regions[hash] = reg;
- ast_mutex_unlock(&reglock);
-
- return ptr;
-}
-
-static inline size_t __ast_sizeof_region(void *ptr)
-{
- int hash = HASH(ptr);
- struct ast_region *reg;
- size_t len = 0;
-
- ast_mutex_lock(&reglock);
- for (reg = regions[hash]; reg; reg = reg->next) {
- if (reg->data == ptr) {
- len = reg->len;
- break;
- }
- }
- ast_mutex_unlock(&reglock);
-
- return len;
-}
-
-static void __ast_free_region(void *ptr, const char *file, int lineno, const char *func)
-{
- int hash = HASH(ptr);
- struct ast_region *reg, *prev = NULL;
- unsigned int *fence;
-
- ast_mutex_lock(&reglock);
- for (reg = regions[hash]; reg; reg = reg->next) {
- if (reg->data == ptr) {
- if (prev)
- prev->next = reg->next;
- else
- regions[hash] = reg->next;
- break;
- }
- prev = reg;
- }
- ast_mutex_unlock(&reglock);
-
- if (reg) {
- fence = (unsigned int *)(reg->data + reg->len);
- if (reg->fence != FENCE_MAGIC) {
- astmm_log("WARNING: Low fence violation at %p, in %s of %s, "
- "line %d\n", reg->data, reg->func, reg->file, reg->lineno);
- }
- if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
- astmm_log("WARNING: High fence violation at %p, in %s of %s, "
- "line %d\n", reg->data, reg->func, reg->file, reg->lineno);
- }
- free(reg);
- } else {
- astmm_log("WARNING: Freeing unused memory at %p, in %s of %s, line %d\n",
- ptr, func, file, lineno);
- }
-}
-
-void *__ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
-{
- void *ptr;
-
- if ((ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 0)))
- memset(ptr, 0, size * nmemb);
-
- return ptr;
-}
-
-void *__ast_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
-{
- void *ptr;
-
- if ((ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1)))
- memset(ptr, 0, size * nmemb);
-
- return ptr;
-}
-
-void *__ast_malloc(size_t size, const char *file, int lineno, const char *func)
-{
- return __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func, 0);
-}
-
-void __ast_free(void *ptr, const char *file, int lineno, const char *func)
-{
- __ast_free_region(ptr, file, lineno, func);
-}
-
-void *__ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
-{
- void *tmp;
- size_t len = 0;
-
- if (ptr && !(len = __ast_sizeof_region(ptr))) {
- astmm_log("WARNING: Realloc of unalloced memory at %p, in %s of %s, "
- "line %d\n", ptr, func, file, lineno);
- return NULL;
- }
-
- if (!(tmp = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func, 0)))
- return NULL;
-
- if (len > size)
- len = size;
- if (ptr) {
- memcpy(tmp, ptr, len);
- __ast_free_region(ptr, file, lineno, func);
- }
-
- return tmp;
-}
-
-char *__ast_strdup(const char *s, const char *file, int lineno, const char *func)
-{
- size_t len;
- void *ptr;
-
- if (!s)
- return NULL;
-
- len = strlen(s) + 1;
- if ((ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func, 0)))
- strcpy(ptr, s);
-
- return ptr;
-}
-
-char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
-{
- size_t len;
- void *ptr;
-
- if (!s)
- return NULL;
-
- len = strlen(s) + 1;
- if (len > n)
- len = n;
- if ((ptr = __ast_alloc_region(len, FUNC_STRNDUP, file, lineno, func, 0)))
- strcpy(ptr, s);
-
- return ptr;
-}
-
-int __ast_asprintf(const char *file, int lineno, const char *func, char **strp, const char *fmt, ...)
-{
- int size;
- va_list ap, ap2;
- char s;
-
- *strp = NULL;
- va_start(ap, fmt);
- va_copy(ap2, ap);
- size = vsnprintf(&s, 1, fmt, ap2);
- va_end(ap2);
- if (!(*strp = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func, 0))) {
- va_end(ap);
- return -1;
- }
- vsnprintf(*strp, size + 1, fmt, ap);
- va_end(ap);
-
- return size;
-}
-
-int __ast_vasprintf(char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func)
-{
- int size;
- va_list ap2;
- char s;
-
- *strp = NULL;
- va_copy(ap2, ap);
- size = vsnprintf(&s, 1, fmt, ap2);
- va_end(ap2);
- if (!(*strp = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func, 0))) {
- va_end(ap);
- return -1;
- }
- vsnprintf(*strp, size + 1, fmt, ap);
-
- return size;
-}
-
-static int handle_show_memory(int fd, int argc, char *argv[])
-{
- char *fn = NULL;
- struct ast_region *reg;
- unsigned int x;
- unsigned int len = 0;
- unsigned int cache_len = 0;
- unsigned int count = 0;
- unsigned int *fence;
-
- if (argc > 3)
- fn = argv[3];
-
- ast_mutex_lock(&reglock);
- for (x = 0; x < SOME_PRIME; x++) {
- for (reg = regions[x]; reg; reg = reg->next) {
- if (!fn || !strcasecmp(fn, reg->file) || !strcasecmp(fn, "anomolies")) {
- fence = (unsigned int *)(reg->data + reg->len);
- if (reg->fence != FENCE_MAGIC) {
- astmm_log("WARNING: Low fence violation at %p, "
- "in %s of %s, line %d\n", reg->data,
- reg->func, reg->file, reg->lineno);
- }
- if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
- astmm_log("WARNING: High fence violation at %p, in %s of %s, "
- "line %d\n", reg->data, reg->func, reg->file, reg->lineno);
- }
- }
- if (!fn || !strcasecmp(fn, reg->file)) {
- ast_cli(fd, "%10d bytes allocated%s in %20s at line %5d of %s\n",
- (int) reg->len, reg->cache ? " (cache)" : "",
- reg->func, reg->lineno, reg->file);
- len += reg->len;
- if (reg->cache)
- cache_len += reg->len;
- count++;
- }
- }
- }
- ast_mutex_unlock(&reglock);
-
- if (cache_len)
- ast_cli(fd, "%d bytes allocated (%d in caches) in %d allocations\n", len, cache_len, count);
- else
- ast_cli(fd, "%d bytes allocated in %d allocations\n", len, count);
-
- return RESULT_SUCCESS;
-}
-
-static int handle_show_memory_summary(int fd, int argc, char *argv[])
-{
- char *fn = NULL;
- int x;
- struct ast_region *reg;
- unsigned int len = 0;
- unsigned int cache_len = 0;
- int count = 0;
- struct file_summary {
- char fn[80];
- int len;
- int cache_len;
- int count;
- struct file_summary *next;
- } *list = NULL, *cur;
-
- if (argc > 3)
- fn = argv[3];
-
- ast_mutex_lock(&reglock);
- for (x = 0; x < SOME_PRIME; x++) {
- for (reg = regions[x]; reg; reg = reg->next) {
- if (fn && strcasecmp(fn, reg->file))
- continue;
-
- for (cur = list; cur; cur = cur->next) {
- if ((!fn && !strcmp(cur->fn, reg->file)) || (fn && !strcmp(cur->fn, reg->func)))
- break;
- }
- if (!cur) {
- cur = alloca(sizeof(*cur));
- memset(cur, 0, sizeof(*cur));
- ast_copy_string(cur->fn, fn ? reg->func : reg->file, sizeof(cur->fn));
- cur->next = list;
- list = cur;
- }
-
- cur->len += reg->len;
- if (reg->cache)
- cur->cache_len += reg->len;
- cur->count++;
- }
- }
- ast_mutex_unlock(&reglock);
-
- /* Dump the whole list */
- for (cur = list; cur; cur = cur->next) {
- len += cur->len;
- cache_len += cur->cache_len;
- count += cur->count;
- if (cur->cache_len) {
- if (fn) {
- ast_cli(fd, "%10d bytes (%10d cache) in %d allocations in function '%s' of '%s'\n",
- cur->len, cur->cache_len, cur->count, cur->fn, fn);
- } else {
- ast_cli(fd, "%10d bytes (%10d cache) in %d allocations in file '%s'\n",
- cur->len, cur->cache_len, cur->count, cur->fn);
- }
- } else {
- if (fn) {
- ast_cli(fd, "%10d bytes in %d allocations in function '%s' of '%s'\n",
- cur->len, cur->count, cur->fn, fn);
- } else {
- ast_cli(fd, "%10d bytes in %d allocations in file '%s'\n",
- cur->len, cur->count, cur->fn);
- }
- }
- }
-
- if (cache_len)
- ast_cli(fd, "%d bytes allocated (%d in caches) in %d allocations\n", len, cache_len, count);
- else
- ast_cli(fd, "%d bytes allocated in %d allocations\n", len, count);
-
- return RESULT_SUCCESS;
-}
-
-static char show_memory_help[] =
-"Usage: memory show allocations [<file>]\n"
-" Dumps a list of all segments of allocated memory, optionally\n"
-"limited to those from a specific file\n";
-
-static char show_memory_summary_help[] =
-"Usage: memory show summary [<file>]\n"
-" Summarizes heap memory allocations by file, or optionally\n"
-"by function, if a file is specified\n";
-
-static struct ast_cli_entry cli_show_memory_allocations_deprecated = {
- { "show", "memory", "allocations", NULL },
- handle_show_memory, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_memory_summary_deprecated = {
- { "show", "memory", "summary", NULL },
- handle_show_memory_summary, NULL,
- NULL };
-
-static struct ast_cli_entry cli_memory[] = {
- { { "memory", "show", "allocations", NULL },
- handle_show_memory, "Display outstanding memory allocations",
- show_memory_help, NULL, &cli_show_memory_allocations_deprecated },
-
- { { "memory", "show", "summary", NULL },
- handle_show_memory_summary, "Summarize outstanding memory allocations",
- show_memory_summary_help, NULL, &cli_show_memory_summary_deprecated },
-};
-
-void __ast_mm_init(void)
-{
- char filename[PATH_MAX];
- size_t pad = sizeof(struct ast_region) - offsetof(struct ast_region, data);
-
- if (pad) {
- ast_log(LOG_ERROR, "struct ast_region has %d bytes of padding! This must be eliminated for low-fence checking to work properly!\n", (int) pad);
- }
-
- ast_cli_register_multiple(cli_memory, sizeof(cli_memory) / sizeof(struct ast_cli_entry));
-
- snprintf(filename, sizeof(filename), "%s/mmlog", (char *)ast_config_AST_LOG_DIR);
-
- if (option_verbose)
- ast_verbose("Asterisk Malloc Debugger Started (see %s))\n", filename);
-
- if ((mmlog = fopen(filename, "a+"))) {
- fprintf(mmlog, "%ld - New session\n", (long)time(NULL));
- fflush(mmlog);
- }
-}
-
-#endif
diff --git a/main/astobj2.c b/main/astobj2.c
deleted file mode 100644
index 56ab75a21..000000000
--- a/main/astobj2.c
+++ /dev/null
@@ -1,771 +0,0 @@
-/*
- * astobj2 - replacement containers for asterisk data structures.
- *
- * Copyright (C) 2006 Marta Carbone, Luigi Rizzo - Univ. di Pisa, Italy
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*
- * Function implementing astobj2 objects.
- */
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/astobj2.h"
-#include "asterisk/utils.h"
-#include "asterisk/cli.h"
-
-/*!
- * astobj2 objects are always prepended this data structure,
- * which contains a lock, a reference counter,
- * the flags and a pointer to a destructor.
- * The refcount is used to decide when it is time to
- * invoke the destructor.
- * The magic number is used for consistency check.
- * XXX the lock is not always needed, and its initialization may be
- * expensive. Consider making it external.
- */
-struct __priv_data {
- ast_mutex_t lock;
- int ref_counter;
- ao2_destructor_fn destructor_fn;
- /*! for stats */
- size_t data_size;
- /*! magic number. This is used to verify that a pointer passed in is a
- * valid astobj2 */
- uint32_t magic;
-};
-
-#define AO2_MAGIC 0xa570b123
-
-/*!
- * What an astobj2 object looks like: fixed-size private data
- * followed by variable-size user data.
- */
-struct astobj2 {
- struct __priv_data priv_data;
- void *user_data[0];
-};
-
-#ifdef AST_DEVMODE
-#define AO2_DEBUG 1
-#endif
-
-#ifdef AO2_DEBUG
-struct ao2_stats {
- volatile int total_objects;
- volatile int total_mem;
- volatile int total_containers;
- volatile int total_refs;
- volatile int total_locked;
-};
-
-static struct ao2_stats ao2;
-#endif
-
-#ifndef HAVE_BKTR /* backtrace support */
-void ao2_bt(void) {}
-#else
-#include <execinfo.h> /* for backtrace */
-
-void ao2_bt(void)
-{
- int c, i;
-#define N1 20
- void *addresses[N1];
- char **strings;
-
- c = backtrace(addresses, N1);
- strings = backtrace_symbols(addresses,c);
- ast_verbose("backtrace returned: %d\n", c);
- for(i = 0; i < c; i++) {
- ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
- }
- free(strings);
-}
-#endif
-
-/*!
- * \brief convert from a pointer _p to a user-defined object
- *
- * \return the pointer to the astobj2 structure
- */
-static inline struct astobj2 *INTERNAL_OBJ(void *user_data)
-{
- struct astobj2 *p;
-
- if (!user_data) {
- ast_log(LOG_ERROR, "user_data is NULL\n");
- return NULL;
- }
-
- p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
- if (AO2_MAGIC != (p->priv_data.magic) ) {
- ast_log(LOG_ERROR, "bad magic number 0x%x for %p\n", p->priv_data.magic, p);
- p = NULL;
- }
-
- return p;
-}
-
-/*!
- * \brief convert from a pointer _p to an astobj2 object
- *
- * \return the pointer to the user-defined portion.
- */
-#define EXTERNAL_OBJ(_p) ((_p) == NULL ? NULL : (_p)->user_data)
-
-#ifndef DEBUG_THREADS
-int ao2_lock(void *user_data)
-#else
-int _ao2_lock(void *user_data, const char *file, const char *func, int line, const char *var)
-#endif
-{
- struct astobj2 *p = INTERNAL_OBJ(user_data);
-
- if (p == NULL)
- return -1;
-
-#ifdef AO2_DEBUG
- ast_atomic_fetchadd_int(&ao2.total_locked, 1);
-#endif
-
-#ifndef DEBUG_THREADS
- return ast_mutex_lock(&p->priv_data.lock);
-#else
- return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock);
-#endif
-}
-
-#ifndef DEBUG_THREADS
-int ao2_trylock(void *user_data)
-#else
-int _ao2_trylock(void *user_data, const char *file, const char *func, int line, const char *var)
-#endif
-{
- struct astobj2 *p = INTERNAL_OBJ(user_data);
- int res;
-
- if (p == NULL)
- return -1;
-
-#ifndef DEBUG_THREADS
- res = ast_mutex_trylock(&p->priv_data.lock);
-#else
- res = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock);
-#endif
-
-#ifdef AO2_DEBUG
- if (!res) {
- ast_atomic_fetchadd_int(&ao2.total_locked, 1);
- }
-#endif
-
- return res;
-}
-
-#ifndef DEBUG_THREADS
-int ao2_unlock(void *user_data)
-#else
-int _ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
-#endif
-{
- struct astobj2 *p = INTERNAL_OBJ(user_data);
-
- if (p == NULL)
- return -1;
-
-#ifdef AO2_DEBUG
- ast_atomic_fetchadd_int(&ao2.total_locked, -1);
-#endif
-
-#ifndef DEBUG_THREADS
- return ast_mutex_unlock(&p->priv_data.lock);
-#else
- return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock);
-#endif
-}
-
-/*
- * The argument is a pointer to the user portion.
- */
-int ao2_ref(void *user_data, const int delta)
-{
- int current_value;
- int ret;
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
-
- if (obj == NULL)
- return -1;
-
- /* if delta is 0, just return the refcount */
- if (delta == 0)
- return (obj->priv_data.ref_counter);
-
- /* we modify with an atomic operation the reference counter */
- ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
- current_value = ret + delta;
-
-#ifdef AO2_DEBUG
- ast_atomic_fetchadd_int(&ao2.total_refs, delta);
-#endif
-
- /* this case must never happen */
- if (current_value < 0)
- ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);
-
- if (current_value <= 0) { /* last reference, destroy the object */
- if (obj->priv_data.destructor_fn != NULL)
- obj->priv_data.destructor_fn(user_data);
-
- ast_mutex_destroy(&obj->priv_data.lock);
-#ifdef AO2_DEBUG
- ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
- ast_atomic_fetchadd_int(&ao2.total_objects, -1);
-#endif
- /* for safety, zero-out the astobj2 header and also the
- * first word of the user-data, which we make sure is always
- * allocated. */
- bzero(obj, sizeof(struct astobj2 *) + sizeof(void *) );
- free(obj);
- }
-
- return ret;
-}
-
-/*
- * We always alloc at least the size of a void *,
- * for debugging purposes.
- */
-void *ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn)
-{
- /* allocation */
- struct astobj2 *obj;
-
- if (data_size < sizeof(void *))
- data_size = sizeof(void *);
-
- obj = ast_calloc(1, sizeof(*obj) + data_size);
-
- if (obj == NULL)
- return NULL;
-
- ast_mutex_init(&obj->priv_data.lock);
- obj->priv_data.magic = AO2_MAGIC;
- obj->priv_data.data_size = data_size;
- obj->priv_data.ref_counter = 1;
- obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */
-
-#ifdef AO2_DEBUG
- ast_atomic_fetchadd_int(&ao2.total_objects, 1);
- ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
- ast_atomic_fetchadd_int(&ao2.total_refs, 1);
-#endif
-
- /* return a pointer to the user data */
- return EXTERNAL_OBJ(obj);
-}
-
-/* internal callback to destroy a container. */
-static void container_destruct(void *c);
-
-/* each bucket in the container is a tailq. */
-AST_LIST_HEAD_NOLOCK(bucket, bucket_list);
-
-/*!
- * A container; stores the hash and callback functions, information on
- * the size, the hash bucket heads, and a version number, starting at 0
- * (for a newly created, empty container)
- * and incremented every time an object is inserted or deleted.
- * The assumption is that an object is never moved in a container,
- * but removed and readded with the new number.
- * The version number is especially useful when implementing iterators.
- * In fact, we can associate a unique, monotonically increasing number to
- * each object, which means that, within an iterator, we can store the
- * version number of the current object, and easily look for the next one,
- * which is the next one in the list with a higher number.
- * Since all objects have a version >0, we can use 0 as a marker for
- * 'we need the first object in the bucket'.
- *
- * \todo Linking and unlink objects is typically expensive, as it
- * involves a malloc() of a small object which is very inefficient.
- * To optimize this, we allocate larger arrays of bucket_list's
- * when we run out of them, and then manage our own freelist.
- * This will be more efficient as we can do the freelist management while
- * we hold the lock (that we need anyways).
- */
-struct ao2_container {
- ao2_hash_fn hash_fn;
- ao2_callback_fn cmp_fn;
- int n_buckets;
- /*! Number of elements in the container */
- int elements;
- /*! described above */
- int version;
- /*! variable size */
- struct bucket buckets[0];
-};
-
-/*!
- * \brief always zero hash function
- *
- * it is convenient to have a hash function that always returns 0.
- * This is basically used when we want to have a container that is
- * a simple linked list.
- *
- * \returns 0
- */
-static int hash_zero(const void *user_obj, const int flags)
-{
- return 0;
-}
-
-/*
- * A container is just an object, after all!
- */
-struct ao2_container *
-ao2_container_alloc(const unsigned int n_buckets, ao2_hash_fn hash_fn,
- ao2_callback_fn cmp_fn)
-{
- /* XXX maybe consistency check on arguments ? */
- /* compute the container size */
- size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
-
- struct ao2_container *c = ao2_alloc(container_size, container_destruct);
-
- if (!c)
- return NULL;
-
- c->version = 1; /* 0 is a reserved value here */
- c->n_buckets = n_buckets;
- c->hash_fn = hash_fn ? hash_fn : hash_zero;
- c->cmp_fn = cmp_fn;
-
-#ifdef AO2_DEBUG
- ast_atomic_fetchadd_int(&ao2.total_containers, 1);
-#endif
-
- return c;
-}
-
-/*!
- * return the number of elements in the container
- */
-int ao2_container_count(struct ao2_container *c)
-{
- return c->elements;
-}
-
-/*!
- * A structure to create a linked list of entries,
- * used within a bucket.
- * XXX \todo this should be private to the container code
- */
-struct bucket_list {
- AST_LIST_ENTRY(bucket_list) entry;
- int version;
- struct astobj2 *astobj; /* pointer to internal data */
-};
-
-/*
- * link an object to a container
- */
-void *__ao2_link(struct ao2_container *c, void *user_data, int iax2_hack)
-{
- int i;
- /* create a new list entry */
- struct bucket_list *p;
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
-
- if (!obj)
- return NULL;
-
- if (INTERNAL_OBJ(c) == NULL)
- return NULL;
-
- p = ast_calloc(1, sizeof(*p));
- if (!p)
- return NULL;
-
- i = c->hash_fn(user_data, OBJ_POINTER);
-
- ao2_lock(c);
- i %= c->n_buckets;
- p->astobj = obj;
- p->version = ast_atomic_fetchadd_int(&c->version, 1);
- if (iax2_hack)
- AST_LIST_INSERT_HEAD(&c->buckets[i], p, entry);
- else
- AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
- ast_atomic_fetchadd_int(&c->elements, 1);
- ao2_ref(user_data, +1);
- ao2_unlock(c);
-
- return p;
-}
-
-/*!
- * \brief another convenience function is a callback that matches on address
- */
-int ao2_match_by_addr(void *user_data, void *arg, int flags)
-{
- return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
-}
-
-/*
- * Unlink an object from the container
- * and destroy the associated * ao2_bucket_list structure.
- */
-void *ao2_unlink(struct ao2_container *c, void *user_data)
-{
- if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */
- return NULL;
-
- ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
-
- return NULL;
-}
-
-/*!
- * \brief special callback that matches all
- */
-static int cb_true(void *user_data, void *arg, int flags)
-{
- return CMP_MATCH;
-}
-
-/*!
- * Browse the container using different stategies accoding the flags.
- * \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is
- * specified.
- */
-void *ao2_callback(struct ao2_container *c,
- const enum search_flags flags,
- ao2_callback_fn cb_fn, void *arg)
-{
- int i, last; /* search boundaries */
- void *ret = NULL;
-
- if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */
- return NULL;
-
- if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
- ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags);
- return NULL;
- }
-
- /* override the match function if necessary */
-#if 0
- /* Removing this slightly changes the meaning of OBJ_POINTER, but makes it
- * do what I want it to. I'd like to hint to ao2_callback that the arg is
- * of the same object type, so it can be passed to the hash function.
- * However, I don't want to imply that this is the object being searched for. */
- if (flags & OBJ_POINTER)
- cb_fn = match_by_addr;
- else
-#endif
- if (cb_fn == NULL) /* if NULL, match everything */
- cb_fn = cb_true;
- /*
- * XXX this can be optimized.
- * If we have a hash function and lookup by pointer,
- * run the hash function. Otherwise, scan the whole container
- * (this only for the time being. We need to optimize this.)
- */
- if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
- i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
- else /* don't know, let's scan all buckets */
- i = -1; /* XXX this must be fixed later. */
-
- /* determine the search boundaries: i..last-1 */
- if (i < 0) {
- i = 0;
- last = c->n_buckets;
- } else {
- last = i + 1;
- }
-
- ao2_lock(c); /* avoid modifications to the content */
-
- for (; i < last ; i++) {
- /* scan the list with prev-cur pointers */
- struct bucket_list *cur;
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
- int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP);
-
- /* we found the object, performing operations according flags */
- if (match == 0) { /* no match, no stop, continue */
- continue;
- } else if (match == CMP_STOP) { /* no match but stop, we are done */
- i = last;
- break;
- }
- /* we have a match (CMP_MATCH) here */
- if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */
- /* it is important to handle this case before the unlink */
- ret = EXTERNAL_OBJ(cur->astobj);
- ao2_ref(ret, 1);
- }
-
- if (flags & OBJ_UNLINK) { /* must unlink */
- struct bucket_list *x = cur;
-
- /* we are going to modify the container, so update version */
- ast_atomic_fetchadd_int(&c->version, 1);
- AST_LIST_REMOVE_CURRENT(&c->buckets[i], entry);
- /* update number of elements and version */
- ast_atomic_fetchadd_int(&c->elements, -1);
- ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
- free(x); /* free the link record */
- }
-
- if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) {
- /* We found the only match we need */
- i = last; /* force exit from outer loop */
- break;
- }
- if (!(flags & OBJ_NODATA)) {
-#if 0 /* XXX to be completed */
- /*
- * This is the multiple-return case. We need to link
- * the object in a list. The refcount is already increased.
- */
-#endif
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- }
- ao2_unlock(c);
- return ret;
-}
-
-/*!
- * the find function just invokes the default callback with some reasonable flags.
- */
-void *ao2_find(struct ao2_container *c, void *arg, enum search_flags flags)
-{
- return ao2_callback(c, flags, c->cmp_fn, arg);
-}
-
-/*!
- * initialize an iterator so we start from the first object
- */
-struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
-{
- struct ao2_iterator a = {
- .c = c,
- .flags = flags
- };
-
- return a;
-}
-
-/*
- * move to the next element in the container.
- */
-void * ao2_iterator_next(struct ao2_iterator *a)
-{
- int lim;
- struct bucket_list *p = NULL;
- void *ret = NULL;
-
- if (INTERNAL_OBJ(a->c) == NULL)
- return NULL;
-
- if (!(a->flags & F_AO2I_DONTLOCK))
- ao2_lock(a->c);
-
- /* optimization. If the container is unchanged and
- * we have a pointer, try follow it
- */
- if (a->c->version == a->c_version && (p = a->obj) ) {
- if ( (p = AST_LIST_NEXT(p, entry)) )
- goto found;
- /* nope, start from the next bucket */
- a->bucket++;
- a->version = 0;
- a->obj = NULL;
- }
-
- lim = a->c->n_buckets;
-
- /* Browse the buckets array, moving to the next
- * buckets if we don't find the entry in the current one.
- * Stop when we find an element with version number greater
- * than the current one (we reset the version to 0 when we
- * switch buckets).
- */
- for (; a->bucket < lim; a->bucket++, a->version = 0) {
- /* scan the current bucket */
- AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
- if (p->version > a->version)
- goto found;
- }
- }
-
-found:
- if (p) {
- a->version = p->version;
- a->obj = p;
- a->c_version = a->c->version;
- ret = EXTERNAL_OBJ(p->astobj);
- /* inc refcount of returned object */
- ao2_ref(ret, 1);
- }
-
- if (!(a->flags & F_AO2I_DONTLOCK))
- ao2_unlock(a->c);
-
- return ret;
-}
-
-/* callback for destroying container.
- * we can make it simple as we know what it does
- */
-static int cd_cb(void *obj, void *arg, int flag)
-{
- ao2_ref(obj, -1);
- return 0;
-}
-
-static void container_destruct(void *_c)
-{
- struct ao2_container *c = _c;
- int i;
-
- ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
-
- for (i = 0; i < c->n_buckets; i++) {
- struct bucket_list *cur;
-
- while ((cur = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
- ast_free(cur);
- }
- }
-
-#ifdef AO2_DEBUG
- ast_atomic_fetchadd_int(&ao2.total_containers, -1);
-#endif
-}
-
-#ifdef AO2_DEBUG
-static int print_cb(void *obj, void *arg, int flag)
-{
- int *fd = arg;
- char *s = (char *)obj;
-
- ast_cli(*fd, "string <%s>\n", s);
- return 0;
-}
-
-/*
- * Print stats
- */
-static int handle_astobj2_stats(int fd, int argc, char *argv[])
-{
- ast_cli(fd, "Objects : %d\n", ao2.total_objects);
- ast_cli(fd, "Containers : %d\n", ao2.total_containers);
- ast_cli(fd, "Memory : %d\n", ao2.total_mem);
- ast_cli(fd, "Locked : %d\n", ao2.total_locked);
- ast_cli(fd, "Refs : %d\n", ao2.total_refs);
- return 0;
-}
-
-/*
- * This is testing code for astobj
- */
-static int handle_astobj2_test(int fd, int argc, char *argv[])
-{
- struct ao2_container *c1;
- int i, lim;
- char *obj;
- static int prof_id = -1;
-
- if (prof_id == -1)
- prof_id = ast_add_profile("ao2_alloc", 0);
-
- ast_cli(fd, "argc %d argv %s %s %s\n", argc, argv[0], argv[1], argv[2]);
- lim = atoi(argv[2]);
- ast_cli(fd, "called astobj_test\n");
-
- handle_astobj2_stats(fd, 0, NULL);
- /*
- * allocate a container with no default callback, and no hash function.
- * No hash means everything goes in the same bucket.
- */
- c1 = ao2_container_alloc(100, NULL /* no callback */, NULL /* no hash */);
- ast_cli(fd, "container allocated as %p\n", c1);
-
- /*
- * fill the container with objects.
- * ao2_alloc() gives us a reference which we pass to the
- * container when we do the insert.
- */
- for (i = 0; i < lim; i++) {
- ast_mark(prof_id, 1 /* start */);
- obj = ao2_alloc(80, NULL);
- ast_mark(prof_id, 0 /* stop */);
- ast_cli(fd, "object %d allocated as %p\n", i, obj);
- sprintf(obj, "-- this is obj %d --", i);
- ao2_link(c1, obj);
- }
- ast_cli(fd, "testing callbacks\n");
- ao2_callback(c1, 0, print_cb, &fd);
-
- ast_cli(fd, "testing iterators, remove every second object\n");
- {
- struct ao2_iterator ai;
- int x = 0;
-
- ai = ao2_iterator_init(c1, 0);
- while ( (obj = ao2_iterator_next(&ai)) ) {
- ast_cli(fd, "iterator on <%s>\n", obj);
- if (x++ & 1)
- ao2_unlink(c1, obj);
- ao2_ref(obj, -1);
- }
- ast_cli(fd, "testing iterators again\n");
- ai = ao2_iterator_init(c1, 0);
- while ( (obj = ao2_iterator_next(&ai)) ) {
- ast_cli(fd, "iterator on <%s>\n", obj);
- ao2_ref(obj, -1);
- }
- }
- ast_cli(fd, "testing callbacks again\n");
- ao2_callback(c1, 0, print_cb, &fd);
-
- ast_verbose("now you should see an error message:\n");
- ao2_ref(&i, -1); /* i is not a valid object so we print an error here */
-
- ast_cli(fd, "destroy container\n");
- ao2_ref(c1, -1); /* destroy container */
- handle_astobj2_stats(fd, 0, NULL);
- return 0;
-}
-
-static struct ast_cli_entry cli_astobj2[] = {
- { { "astobj2", "stats", NULL },
- handle_astobj2_stats, "Print astobj2 statistics", },
- { { "astobj2", "test", NULL } , handle_astobj2_test, "Test astobj2", },
-};
-#endif /* AO2_DEBUG */
-
-int astobj2_init(void)
-{
-#ifdef AO2_DEBUG
- ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
-#endif
-
- return 0;
-}
diff --git a/main/audiohook.c b/main/audiohook.c
deleted file mode 100644
index cd5b7ca8a..000000000
--- a/main/audiohook.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2007, Digium, Inc.
- *
- * Joshua Colp <jcolp@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Audiohooks Architecture
- *
- * \author Joshua Colp <jcolp@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/options.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/audiohook.h"
-#include "asterisk/slinfactory.h"
-#include "asterisk/frame.h"
-#include "asterisk/translate.h"
-
-struct ast_audiohook_translate {
- struct ast_trans_pvt *trans_pvt;
- int format;
-};
-
-struct ast_audiohook_list {
- struct ast_audiohook_translate in_translate[2];
- struct ast_audiohook_translate out_translate[2];
- AST_LIST_HEAD_NOLOCK(, ast_audiohook) spy_list;
- AST_LIST_HEAD_NOLOCK(, ast_audiohook) whisper_list;
- AST_LIST_HEAD_NOLOCK(, ast_audiohook) manipulate_list;
-};
-
-/*! \brief Initialize an audiohook structure
- * \param audiohook Audiohook structure
- * \param type
- * \param source
- * \return Returns 0 on success, -1 on failure
- */
-int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source)
-{
- /* Need to keep the type and source */
- audiohook->type = type;
- audiohook->source = source;
-
- /* Initialize lock that protects our audiohook */
- ast_mutex_init(&audiohook->lock);
- ast_cond_init(&audiohook->trigger, NULL);
-
- /* Setup the factories that are needed for this audiohook type */
- switch (type) {
- case AST_AUDIOHOOK_TYPE_SPY:
- ast_slinfactory_init(&audiohook->read_factory);
- case AST_AUDIOHOOK_TYPE_WHISPER:
- ast_slinfactory_init(&audiohook->write_factory);
- break;
- default:
- break;
- }
-
- /* Since we are just starting out... this audiohook is new */
- audiohook->status = AST_AUDIOHOOK_STATUS_NEW;
-
- return 0;
-}
-
-/*! \brief Destroys an audiohook structure
- * \param audiohook Audiohook structure
- * \return Returns 0 on success, -1 on failure
- */
-int ast_audiohook_destroy(struct ast_audiohook *audiohook)
-{
- /* Drop the factories used by this audiohook type */
- switch (audiohook->type) {
- case AST_AUDIOHOOK_TYPE_SPY:
- ast_slinfactory_destroy(&audiohook->read_factory);
- case AST_AUDIOHOOK_TYPE_WHISPER:
- ast_slinfactory_destroy(&audiohook->write_factory);
- break;
- default:
- break;
- }
-
- /* Destroy translation path if present */
- if (audiohook->trans_pvt)
- ast_translator_free_path(audiohook->trans_pvt);
-
- /* Lock and trigger be gone! */
- ast_cond_destroy(&audiohook->trigger);
- ast_mutex_destroy(&audiohook->lock);
-
- return 0;
-}
-
-/*! \brief Writes a frame into the audiohook structure
- * \param audiohook Audiohook structure
- * \param direction Direction the audio frame came from
- * \param frame Frame to write in
- * \return Returns 0 on success, -1 on failure
- */
-int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, struct ast_frame *frame)
-{
- struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
- struct ast_slinfactory *other_factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->write_factory : &audiohook->read_factory);
- struct timeval *time = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_time : &audiohook->write_time), previous_time = *time;
- int our_factory_ms;
- int other_factory_samples;
- int other_factory_ms;
-
- /* Update last feeding time to be current */
- *time = ast_tvnow();
-
- our_factory_ms = ast_tvdiff_ms(*time, previous_time) + (ast_slinfactory_available(factory) / 8);
- other_factory_samples = ast_slinfactory_available(other_factory);
- other_factory_ms = other_factory_samples / 8;
-
- /* If we are using a sync trigger and this factory suddenly got audio fed in after a lapse, then flush both factories to ensure they remain in sync */
- if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC) && other_factory_samples && (our_factory_ms - other_factory_ms > AST_AUDIOHOOK_SYNC_TOLERANCE)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Flushing audiohook %p so it remains in sync\n", audiohook);
- ast_slinfactory_flush(factory);
- ast_slinfactory_flush(other_factory);
- }
-
- /* Write frame out to respective factory */
- ast_slinfactory_feed(factory, frame);
-
- /* If we need to notify the respective handler of this audiohook, do so */
- if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) {
- ast_cond_signal(&audiohook->trigger);
- } else if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) {
- ast_cond_signal(&audiohook->trigger);
- } else if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC)) {
- ast_cond_signal(&audiohook->trigger);
- }
-
- return 0;
-}
-
-static struct ast_frame *audiohook_read_frame_single(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction)
-{
- struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
- int vol = (direction == AST_AUDIOHOOK_DIRECTION_READ ? audiohook->options.read_volume : audiohook->options.write_volume);
- short buf[samples];
- struct ast_frame frame = {
- .frametype = AST_FRAME_VOICE,
- .subclass = AST_FORMAT_SLINEAR,
- .data = buf,
- .datalen = sizeof(buf),
- .samples = samples,
- };
-
- /* Ensure the factory is able to give us the samples we want */
- if (samples > ast_slinfactory_available(factory))
- return NULL;
-
- /* Read data in from factory */
- if (!ast_slinfactory_read(factory, buf, samples))
- return NULL;
-
- /* If a volume adjustment needs to be applied apply it */
- if (vol)
- ast_frame_adjust_volume(&frame, vol);
-
- return ast_frdup(&frame);
-}
-
-static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audiohook, size_t samples)
-{
- int i = 0, usable_read, usable_write;
- short buf1[samples], buf2[samples], *read_buf = NULL, *write_buf = NULL, *final_buf = NULL, *data1 = NULL, *data2 = NULL;
- struct ast_frame frame = {
- .frametype = AST_FRAME_VOICE,
- .subclass = AST_FORMAT_SLINEAR,
- .data = NULL,
- .datalen = sizeof(buf1),
- .samples = samples,
- };
-
- /* Make sure both factories have the required samples */
- usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
- usable_write = (ast_slinfactory_available(&audiohook->write_factory) >= samples ? 1 : 0);
-
- if (!usable_read && !usable_write) {
- /* If both factories are unusable bail out */
- if (option_debug)
- ast_log(LOG_DEBUG, "Read factory %p and write factory %p both fail to provide %zd samples\n", &audiohook->read_factory, &audiohook->write_factory, samples);
- return NULL;
- }
-
- /* If we want to provide only a read factory make sure we aren't waiting for other audio */
- if (usable_read && !usable_write && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)) {
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "Write factory %p was pretty quick last time, waiting for them.\n", &audiohook->write_factory);
- return NULL;
- }
-
- /* If we want to provide only a write factory make sure we aren't waiting for other audio */
- if (usable_write && !usable_read && (ast_tvdiff_ms(ast_tvnow(), audiohook->read_time) < (samples/8)*2)) {
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "Read factory %p was pretty quick last time, waiting for them.\n", &audiohook->read_factory);
- return NULL;
- }
-
- /* Start with the read factory... if there are enough samples, read them in */
- if (usable_read) {
- if (ast_slinfactory_read(&audiohook->read_factory, buf1, samples)) {
- read_buf = buf1;
- /* Adjust read volume if need be */
- if (audiohook->options.read_volume) {
- int count = 0;
- short adjust_value = abs(audiohook->options.read_volume);
- for (count = 0; count < samples; count++) {
- if (audiohook->options.read_volume > 0)
- ast_slinear_saturated_multiply(&buf1[count], &adjust_value);
- else if (audiohook->options.read_volume < 0)
- ast_slinear_saturated_divide(&buf1[count], &adjust_value);
- }
- }
- }
- } else if (option_debug)
- ast_log(LOG_DEBUG, "Failed to get %zd samples from read factory %p\n", samples, &audiohook->read_factory);
-
- /* Move on to the write factory... if there are enough samples, read them in */
- if (usable_write) {
- if (ast_slinfactory_read(&audiohook->write_factory, buf2, samples)) {
- write_buf = buf2;
- /* Adjust write volume if need be */
- if (audiohook->options.write_volume) {
- int count = 0;
- short adjust_value = abs(audiohook->options.write_volume);
- for (count = 0; count < samples; count++) {
- if (audiohook->options.write_volume > 0)
- ast_slinear_saturated_multiply(&buf2[count], &adjust_value);
- else if (audiohook->options.write_volume < 0)
- ast_slinear_saturated_divide(&buf2[count], &adjust_value);
- }
- }
- }
- } else if (option_debug)
- ast_log(LOG_DEBUG, "Failed to get %zd samples from write factory %p\n", samples, &audiohook->write_factory);
-
- /* Basically we figure out which buffer to use... and if mixing can be done here */
- if (!read_buf && !write_buf)
- return NULL;
- else if (read_buf && write_buf) {
- for (i = 0, data1 = read_buf, data2 = write_buf; i < samples; i++, data1++, data2++)
- ast_slinear_saturated_add(data1, data2);
- final_buf = buf1;
- } else if (read_buf)
- final_buf = buf1;
- else if (write_buf)
- final_buf = buf2;
-
- /* Make the final buffer part of the frame, so it gets duplicated fine */
- frame.data = final_buf;
-
- /* Yahoo, a combined copy of the audio! */
- return ast_frdup(&frame);
-}
-
-/*! \brief Reads a frame in from the audiohook structure
- * \param audiohook Audiohook structure
- * \param samples Number of samples wanted
- * \param direction Direction the audio frame came from
- * \param format Format of frame remote side wants back
- * \return Returns frame on success, NULL on failure
- */
-struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, int format)
-{
- struct ast_frame *read_frame = NULL, *final_frame = NULL;
-
- if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ? audiohook_read_frame_both(audiohook, samples) : audiohook_read_frame_single(audiohook, samples, direction))))
- return NULL;
-
- /* If they don't want signed linear back out, we'll have to send it through the translation path */
- if (format != AST_FORMAT_SLINEAR) {
- /* Rebuild translation path if different format then previously */
- if (audiohook->format != format) {
- if (audiohook->trans_pvt) {
- ast_translator_free_path(audiohook->trans_pvt);
- audiohook->trans_pvt = NULL;
- }
- /* Setup new translation path for this format... if we fail we can't very well return signed linear so free the frame and return nothing */
- if (!(audiohook->trans_pvt = ast_translator_build_path(format, AST_FORMAT_SLINEAR))) {
- ast_frfree(read_frame);
- return NULL;
- }
- }
- /* Convert to requested format, and allow the read in frame to be freed */
- final_frame = ast_translate(audiohook->trans_pvt, read_frame, 1);
- } else {
- final_frame = read_frame;
- }
-
- return final_frame;
-}
-
-/*! \brief Attach audiohook to channel
- * \param chan Channel
- * \param audiohook Audiohook structure
- * \return Returns 0 on success, -1 on failure
- */
-int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
-{
- ast_channel_lock(chan);
-
- if (!chan->audiohooks) {
- /* Whoops... allocate a new structure */
- if (!(chan->audiohooks = ast_calloc(1, sizeof(*chan->audiohooks)))) {
- ast_channel_unlock(chan);
- return -1;
- }
- AST_LIST_HEAD_INIT_NOLOCK(&chan->audiohooks->spy_list);
- AST_LIST_HEAD_INIT_NOLOCK(&chan->audiohooks->whisper_list);
- AST_LIST_HEAD_INIT_NOLOCK(&chan->audiohooks->manipulate_list);
- }
-
- /* Drop into respective list */
- if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY)
- AST_LIST_INSERT_TAIL(&chan->audiohooks->spy_list, audiohook, list);
- else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER)
- AST_LIST_INSERT_TAIL(&chan->audiohooks->whisper_list, audiohook, list);
- else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE)
- AST_LIST_INSERT_TAIL(&chan->audiohooks->manipulate_list, audiohook, list);
-
- /* Change status over to running since it is now attached */
- audiohook->status = AST_AUDIOHOOK_STATUS_RUNNING;
-
- ast_channel_unlock(chan);
-
- return 0;
-}
-
-/*! \brief Detach audiohook from channel
- * \param audiohook Audiohook structure
- * \return Returns 0 on success, -1 on failure
- */
-int ast_audiohook_detach(struct ast_audiohook *audiohook)
-{
- if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
- return 0;
-
- audiohook->status = AST_AUDIOHOOK_STATUS_SHUTDOWN;
-
- while (audiohook->status != AST_AUDIOHOOK_STATUS_DONE)
- ast_audiohook_trigger_wait(audiohook);
-
- return 0;
-}
-
-/*! \brief Detach audiohooks from list and destroy said list
- * \param audiohook_list List of audiohooks
- * \return Returns 0 on success, -1 on failure
- */
-int ast_audiohook_detach_list(struct ast_audiohook_list *audiohook_list)
-{
- int i = 0;
- struct ast_audiohook *audiohook = NULL;
-
- /* Drop any spies */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
- ast_audiohook_lock(audiohook);
- AST_LIST_REMOVE_CURRENT(&audiohook_list->spy_list, list);
- audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
- ast_cond_signal(&audiohook->trigger);
- ast_audiohook_unlock(audiohook);
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- /* Drop any whispering sources */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
- ast_audiohook_lock(audiohook);
- AST_LIST_REMOVE_CURRENT(&audiohook_list->whisper_list, list);
- audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
- ast_cond_signal(&audiohook->trigger);
- ast_audiohook_unlock(audiohook);
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- /* Drop any manipulaters */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
- ast_audiohook_lock(audiohook);
- AST_LIST_REMOVE_CURRENT(&audiohook_list->manipulate_list, list);
- audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
- ast_audiohook_unlock(audiohook);
- audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- /* Drop translation paths if present */
- for (i = 0; i < 2; i++) {
- if (audiohook_list->in_translate[i].trans_pvt)
- ast_translator_free_path(audiohook_list->in_translate[i].trans_pvt);
- if (audiohook_list->out_translate[i].trans_pvt)
- ast_translator_free_path(audiohook_list->out_translate[i].trans_pvt);
- }
-
- /* Free ourselves */
- ast_free(audiohook_list);
-
- return 0;
-}
-
-static struct ast_audiohook *find_audiohook_by_source(struct ast_audiohook_list *audiohook_list, const char *source)
-{
- struct ast_audiohook *audiohook = NULL;
-
- AST_LIST_TRAVERSE(&audiohook_list->spy_list, audiohook, list) {
- if (!strcasecmp(audiohook->source, source))
- return audiohook;
- }
-
- AST_LIST_TRAVERSE(&audiohook_list->whisper_list, audiohook, list) {
- if (!strcasecmp(audiohook->source, source))
- return audiohook;
- }
-
- AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, audiohook, list) {
- if (!strcasecmp(audiohook->source, source))
- return audiohook;
- }
-
- return NULL;
-}
-
-void ast_audiohook_move_by_source (struct ast_channel *old_chan, struct ast_channel *new_chan, const char *source)
-{
- struct ast_audiohook *audiohook = find_audiohook_by_source(old_chan->audiohooks, source);
-
- if (!audiohook) {
- return;
- }
-
- /* By locking both channels and the audiohook, we can assure that
- * another thread will not have a chance to read the audiohook's status
- * as done, even though ast_audiohook_remove signals the trigger
- * condition
- */
- ast_audiohook_lock(audiohook);
- ast_audiohook_remove(old_chan, audiohook);
- ast_audiohook_attach(new_chan, audiohook);
- ast_audiohook_unlock(audiohook);
-}
-
-/*! \brief Detach specified source audiohook from channel
- * \param chan Channel to detach from
- * \param source Name of source to detach
- * \return Returns 0 on success, -1 on failure
- */
-int ast_audiohook_detach_source(struct ast_channel *chan, const char *source)
-{
- struct ast_audiohook *audiohook = NULL;
-
- ast_channel_lock(chan);
-
- /* Ensure the channel has audiohooks on it */
- if (!chan->audiohooks) {
- ast_channel_unlock(chan);
- return -1;
- }
-
- audiohook = find_audiohook_by_source(chan->audiohooks, source);
-
- ast_channel_unlock(chan);
-
- if (audiohook && audiohook->status != AST_AUDIOHOOK_STATUS_DONE)
- audiohook->status = AST_AUDIOHOOK_STATUS_SHUTDOWN;
-
- return (audiohook ? 0 : -1);
-}
-
-/*!
- * \brief Remove an audiohook from a specified channel
- *
- * \param chan Channel to remove from
- * \param audiohook Audiohook to remove
- *
- * \return Returns 0 on success, -1 on failure
- *
- * \note The channel does not need to be locked before calling this function
- */
-int ast_audiohook_remove(struct ast_channel *chan, struct ast_audiohook *audiohook)
-{
- ast_channel_lock(chan);
-
- if (!chan->audiohooks) {
- ast_channel_unlock(chan);
- return -1;
- }
-
- if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY)
- AST_LIST_REMOVE(&chan->audiohooks->spy_list, audiohook, list);
- else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER)
- AST_LIST_REMOVE(&chan->audiohooks->whisper_list, audiohook, list);
- else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE)
- AST_LIST_REMOVE(&chan->audiohooks->manipulate_list, audiohook, list);
-
- ast_audiohook_lock(audiohook);
- audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
- ast_cond_signal(&audiohook->trigger);
- ast_audiohook_unlock(audiohook);
-
- ast_channel_unlock(chan);
-
- return 0;
-}
-
-/*! \brief Pass a DTMF frame off to be handled by the audiohook core
- * \param chan Channel that the list is coming off of
- * \param audiohook_list List of audiohooks
- * \param direction Direction frame is coming in from
- * \param frame The frame itself
- * \return Return frame on success, NULL on failure
- */
-static struct ast_frame *dtmf_audiohook_write_list(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
-{
- struct ast_audiohook *audiohook = NULL;
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
- ast_audiohook_lock(audiohook);
- if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
- AST_LIST_REMOVE_CURRENT(&audiohook_list->manipulate_list, list);
- audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
- ast_audiohook_unlock(audiohook);
- audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
- continue;
- }
- if (ast_test_flag(audiohook, AST_AUDIOHOOK_WANTS_DTMF))
- audiohook->manipulate_callback(audiohook, chan, frame, direction);
- ast_audiohook_unlock(audiohook);
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- return frame;
-}
-
-/*! \brief Pass an AUDIO frame off to be handled by the audiohook core
- * \param chan Channel that the list is coming off of
- * \param audiohook_list List of audiohooks
- * \param direction Direction frame is coming in from
- * \param frame The frame itself
- * \return Return frame on success, NULL on failure
- */
-static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
-{
- struct ast_audiohook_translate *in_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->in_translate[0] : &audiohook_list->in_translate[1]);
- struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
- struct ast_frame *start_frame = frame, *middle_frame = frame, *end_frame = frame;
- struct ast_audiohook *audiohook = NULL;
- int samples = frame->samples;
-
- /* If the frame coming in is not signed linear we have to send it through the in_translate path */
- if (frame->subclass != AST_FORMAT_SLINEAR) {
- if (in_translate->format != frame->subclass) {
- if (in_translate->trans_pvt)
- ast_translator_free_path(in_translate->trans_pvt);
- if (!(in_translate->trans_pvt = ast_translator_build_path(AST_FORMAT_SLINEAR, frame->subclass)))
- return frame;
- in_translate->format = frame->subclass;
- }
- if (!(middle_frame = ast_translate(in_translate->trans_pvt, frame, 0)))
- return frame;
- }
-
- /* Queue up signed linear frame to each spy */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
- ast_audiohook_lock(audiohook);
- if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
- AST_LIST_REMOVE_CURRENT(&audiohook_list->spy_list, list);
- audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
- ast_cond_signal(&audiohook->trigger);
- ast_audiohook_unlock(audiohook);
- continue;
- }
- ast_audiohook_write_frame(audiohook, direction, middle_frame);
- ast_audiohook_unlock(audiohook);
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- /* If this frame is being written out to the channel then we need to use whisper sources */
- if (direction == AST_AUDIOHOOK_DIRECTION_WRITE && !AST_LIST_EMPTY(&audiohook_list->whisper_list)) {
- int i = 0;
- short read_buf[samples], combine_buf[samples], *data1 = NULL, *data2 = NULL;
- memset(&combine_buf, 0, sizeof(combine_buf));
- AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
- ast_audiohook_lock(audiohook);
- if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
- AST_LIST_REMOVE_CURRENT(&audiohook_list->whisper_list, list);
- audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
- ast_cond_signal(&audiohook->trigger);
- ast_audiohook_unlock(audiohook);
- continue;
- }
- if (ast_slinfactory_available(&audiohook->write_factory) >= samples && ast_slinfactory_read(&audiohook->write_factory, read_buf, samples)) {
- /* Take audio from this whisper source and combine it into our main buffer */
- for (i = 0, data1 = combine_buf, data2 = read_buf; i < samples; i++, data1++, data2++)
- ast_slinear_saturated_add(data1, data2);
- }
- ast_audiohook_unlock(audiohook);
- }
- AST_LIST_TRAVERSE_SAFE_END
- /* We take all of the combined whisper sources and combine them into the audio being written out */
- for (i = 0, data1 = middle_frame->data, data2 = combine_buf; i < samples; i++, data1++, data2++)
- ast_slinear_saturated_add(data1, data2);
- end_frame = middle_frame;
- }
-
- /* Pass off frame to manipulate audiohooks */
- if (!AST_LIST_EMPTY(&audiohook_list->manipulate_list)) {
- AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
- ast_audiohook_lock(audiohook);
- if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
- AST_LIST_REMOVE_CURRENT(&audiohook_list->manipulate_list, list);
- audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
- ast_audiohook_unlock(audiohook);
- /* We basically drop all of our links to the manipulate audiohook and prod it to do it's own destructive things */
- audiohook->manipulate_callback(audiohook, chan, NULL, direction);
- continue;
- }
- /* Feed in frame to manipulation */
- audiohook->manipulate_callback(audiohook, chan, middle_frame, direction);
- ast_audiohook_unlock(audiohook);
- }
- AST_LIST_TRAVERSE_SAFE_END
- end_frame = middle_frame;
- }
-
- /* Now we figure out what to do with our end frame (whether to transcode or not) */
- if (middle_frame == end_frame) {
- /* Middle frame was modified and became the end frame... let's see if we need to transcode */
- if (end_frame->subclass != start_frame->subclass) {
- if (out_translate->format != start_frame->subclass) {
- if (out_translate->trans_pvt)
- ast_translator_free_path(out_translate->trans_pvt);
- if (!(out_translate->trans_pvt = ast_translator_build_path(start_frame->subclass, AST_FORMAT_SLINEAR))) {
- /* We can't transcode this... drop our middle frame and return the original */
- ast_frfree(middle_frame);
- return start_frame;
- }
- out_translate->format = start_frame->subclass;
- }
- /* Transcode from our middle (signed linear) frame to new format of the frame that came in */
- if (!(end_frame = ast_translate(out_translate->trans_pvt, middle_frame, 0))) {
- /* Failed to transcode the frame... drop it and return the original */
- ast_frfree(middle_frame);
- return start_frame;
- }
- /* Here's the scoop... middle frame is no longer of use to us */
- ast_frfree(middle_frame);
- }
- } else {
- /* No frame was modified, we can just drop our middle frame and pass the frame we got in out */
- ast_frfree(middle_frame);
- }
-
- return end_frame;
-}
-
-/*! \brief Pass a frame off to be handled by the audiohook core
- * \param chan Channel that the list is coming off of
- * \param audiohook_list List of audiohooks
- * \param direction Direction frame is coming in from
- * \param frame The frame itself
- * \return Return frame on success, NULL on failure
- */
-struct ast_frame *ast_audiohook_write_list(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
-{
- /* Pass off frame to it's respective list write function */
- if (frame->frametype == AST_FRAME_VOICE)
- return audio_audiohook_write_list(chan, audiohook_list, direction, frame);
- else if (frame->frametype == AST_FRAME_DTMF)
- return dtmf_audiohook_write_list(chan, audiohook_list, direction, frame);
- else
- return frame;
-}
-
-
-/*! \brief Wait for audiohook trigger to be triggered
- * \param audiohook Audiohook to wait on
- */
-void ast_audiohook_trigger_wait(struct ast_audiohook *audiohook)
-{
- struct timeval tv;
- struct timespec ts;
-
- tv = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000));
- ts.tv_sec = tv.tv_sec;
- ts.tv_nsec = tv.tv_usec * 1000;
-
- ast_cond_timedwait(&audiohook->trigger, &audiohook->lock, &ts);
-
- return;
-}
diff --git a/main/autoservice.c b/main/autoservice.c
deleted file mode 100644
index 1150c4c7f..000000000
--- a/main/autoservice.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2008, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- * Russell Bryant <russell@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Automatic channel service routines
- *
- * \author Mark Spencer <markster@digium.com>
- * \author Russell Bryant <russell@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "asterisk/pbx.h"
-#include "asterisk/frame.h"
-#include "asterisk/sched.h"
-#include "asterisk/options.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/file.h"
-#include "asterisk/translate.h"
-#include "asterisk/manager.h"
-#include "asterisk/chanvars.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/indications.h"
-#include "asterisk/lock.h"
-#include "asterisk/utils.h"
-
-#define MAX_AUTOMONS 1500
-
-struct asent {
- struct ast_channel *chan;
- /*! This gets incremented each time autoservice gets started on the same
- * channel. It will ensure that it doesn't actually get stopped until
- * it gets stopped for the last time. */
- unsigned int use_count;
- unsigned int orig_end_dtmf_flag:1;
- /*! Frames go on at the head of deferred_frames, so we have the frames
- * from newest to oldest. As we put them at the head of the readq, we'll
- * end up with them in the right order for the channel's readq. */
- AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
- AST_LIST_ENTRY(asent) list;
-};
-
-static AST_LIST_HEAD_STATIC(aslist, asent);
-static ast_cond_t as_cond;
-
-static pthread_t asthread = AST_PTHREADT_NULL;
-
-static int as_chan_list_state;
-
-static void *autoservice_run(void *ign)
-{
- for (;;) {
- struct ast_channel *mons[MAX_AUTOMONS];
- struct asent *ents[MAX_AUTOMONS];
- struct ast_channel *chan;
- struct asent *as;
- int i, x = 0, ms = 50;
- struct ast_frame *f = NULL;
- struct ast_frame *defer_frame = NULL;
-
- AST_LIST_LOCK(&aslist);
-
- /* At this point, we know that no channels that have been removed are going
- * to get used again. */
- as_chan_list_state++;
-
- if (AST_LIST_EMPTY(&aslist)) {
- ast_cond_wait(&as_cond, &aslist.lock);
- }
-
- AST_LIST_TRAVERSE(&aslist, as, list) {
- if (!as->chan->_softhangup) {
- if (x < MAX_AUTOMONS) {
- ents[x] = as;
- mons[x++] = as->chan;
- } else {
- ast_log(LOG_WARNING, "Exceeded maximum number of automatic monitoring events. Fix autoservice.c\n");
- }
- }
- }
-
- AST_LIST_UNLOCK(&aslist);
-
- if (!x) {
- continue;
- }
-
- chan = ast_waitfor_n(mons, x, &ms);
- if (!chan) {
- continue;
- }
-
- f = ast_read(chan);
-
- if (!f) {
- struct ast_frame hangup_frame = { 0, };
- /* No frame means the channel has been hung up.
- * A hangup frame needs to be queued here as ast_waitfor() may
- * never return again for the condition to be detected outside
- * of autoservice. So, we'll leave a HANGUP queued up so the
- * thread in charge of this channel will know. */
-
- hangup_frame.frametype = AST_FRAME_CONTROL;
- hangup_frame.subclass = AST_CONTROL_HANGUP;
-
- defer_frame = &hangup_frame;
- } else {
-
- /* Do not add a default entry in this switch statement. Each new
- * frame type should be addressed directly as to whether it should
- * be queued up or not. */
-
- switch (f->frametype) {
- /* Save these frames */
- case AST_FRAME_DTMF_END:
- case AST_FRAME_CONTROL:
- case AST_FRAME_TEXT:
- case AST_FRAME_IMAGE:
- case AST_FRAME_HTML:
- defer_frame = f;
- break;
-
- /* Throw these frames away */
- case AST_FRAME_DTMF_BEGIN:
- case AST_FRAME_VOICE:
- case AST_FRAME_VIDEO:
- case AST_FRAME_NULL:
- case AST_FRAME_IAX:
- case AST_FRAME_CNG:
- case AST_FRAME_MODEM:
- break;
- }
- }
-
- if (defer_frame) {
- for (i = 0; i < x; i++) {
- struct ast_frame *dup_f;
-
- if (mons[i] != chan) {
- continue;
- }
-
- if ((dup_f = ast_frdup(defer_frame))) {
- AST_LIST_INSERT_HEAD(&ents[i]->deferred_frames, dup_f, frame_list);
- }
-
- break;
- }
- }
-
- if (f) {
- ast_frfree(f);
- }
- }
-
- asthread = AST_PTHREADT_NULL;
-
- return NULL;
-}
-
-int ast_autoservice_start(struct ast_channel *chan)
-{
- int res = 0;
- struct asent *as;
-
- /* Check if the channel already has autoservice */
- AST_LIST_LOCK(&aslist);
- AST_LIST_TRAVERSE(&aslist, as, list) {
- if (as->chan == chan) {
- as->use_count++;
- break;
- }
- }
- AST_LIST_UNLOCK(&aslist);
-
- if (as) {
- /* Entry exists, autoservice is already handling this channel */
- return 0;
- }
-
- if (!(as = ast_calloc(1, sizeof(*as))))
- return -1;
-
- /* New entry created */
- as->chan = chan;
- as->use_count = 1;
-
- ast_channel_lock(chan);
- as->orig_end_dtmf_flag = ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY) ? 1 : 0;
- if (!as->orig_end_dtmf_flag)
- ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
- ast_channel_unlock(chan);
-
- AST_LIST_LOCK(&aslist);
-
- if (AST_LIST_EMPTY(&aslist) && asthread != AST_PTHREADT_NULL) {
- ast_cond_signal(&as_cond);
- }
-
- AST_LIST_INSERT_HEAD(&aslist, as, list);
-
- if (asthread == AST_PTHREADT_NULL) { /* need start the thread */
- if (ast_pthread_create_background(&asthread, NULL, autoservice_run, NULL)) {
- ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
- /* There will only be a single member in the list at this point,
- the one we just added. */
- AST_LIST_REMOVE(&aslist, as, list);
- free(as);
- asthread = AST_PTHREADT_NULL;
- res = -1;
- } else {
- pthread_kill(asthread, SIGURG);
- }
- }
-
- AST_LIST_UNLOCK(&aslist);
-
- return res;
-}
-
-int ast_autoservice_stop(struct ast_channel *chan)
-{
- int res = -1;
- struct asent *as, *removed = NULL;
- struct ast_frame *f;
- int chan_list_state;
-
- AST_LIST_LOCK(&aslist);
-
- /* Save the autoservice channel list state. We _must_ verify that the channel
- * list has been rebuilt before we return. Because, after we return, the channel
- * could get destroyed and we don't want our poor autoservice thread to step on
- * it after its gone! */
- chan_list_state = as_chan_list_state;
-
- /* Find the entry, but do not free it because it still can be in the
- autoservice thread array */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&aslist, as, list) {
- if (as->chan == chan) {
- as->use_count--;
- if (as->use_count < 1) {
- AST_LIST_REMOVE_CURRENT(&aslist, list);
- removed = as;
- }
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- if (removed && asthread != AST_PTHREADT_NULL) {
- pthread_kill(asthread, SIGURG);
- }
-
- AST_LIST_UNLOCK(&aslist);
-
- if (!removed) {
- return 0;
- }
-
- /* Wait while autoservice thread rebuilds its list. */
- while (chan_list_state == as_chan_list_state) {
- usleep(1000);
- }
-
- /* Now autoservice thread should have no references to our entry
- and we can safely destroy it */
-
- if (!chan->_softhangup) {
- res = 0;
- }
-
- if (!as->orig_end_dtmf_flag) {
- ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
- }
-
- ast_channel_lock(chan);
- while ((f = AST_LIST_REMOVE_HEAD(&as->deferred_frames, frame_list))) {
- ast_queue_frame_head(chan, f);
- ast_frfree(f);
- }
- ast_channel_unlock(chan);
-
- free(as);
-
- return res;
-}
-
-void ast_autoservice_init(void)
-{
- ast_cond_init(&as_cond, NULL);
-}
diff --git a/main/buildinfo.c b/main/buildinfo.c
deleted file mode 100644
index 964e06eb3..000000000
--- a/main/buildinfo.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2005, Digium, Inc.
- *
- * Kevin P. Fleming <kpfleming@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Build timestamp variables
- *
- * \author Kevin P. Fleming <kpfleming@digium.com>
- */
-
-#include "asterisk/build.h"
-
-const char *ast_build_hostname = BUILD_HOSTNAME;
-const char *ast_build_kernel = BUILD_KERNEL;
-const char *ast_build_machine = BUILD_MACHINE;
-const char *ast_build_os = BUILD_OS;
-const char *ast_build_date = BUILD_DATE;
-const char *ast_build_user = BUILD_USER;
diff --git a/main/callerid.c b/main/callerid.c
deleted file mode 100644
index d446ecbb8..000000000
--- a/main/callerid.c
+++ /dev/null
@@ -1,1117 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief CallerID Generation support
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <time.h>
-#include <string.h>
-#include <stdio.h>
-#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/channel.h"
-#include "asterisk/callerid.h"
-#include "asterisk/logger.h"
-#include "asterisk/fskmodem.h"
-#include "asterisk/options.h"
-#include "asterisk/utils.h"
-
-struct callerid_state {
- fsk_data fskd;
- char rawdata[256];
- short oldstuff[160];
- int oldlen;
- int pos;
- int type;
- int cksum;
- char name[64];
- char number[64];
- int flags;
- int sawflag;
- int len;
-
- int skipflag;
- unsigned short crc;
-};
-
-
-float cid_dr[4], cid_di[4];
-float clidsb = 8000.0 / 1200.0;
-float sasdr, sasdi;
-float casdr1, casdi1, casdr2, casdi2;
-
-#define CALLERID_SPACE 2200.0 /*!< 2200 hz for "0" */
-#define CALLERID_MARK 1200.0 /*!< 1200 hz for "1" */
-#define SAS_FREQ 440.0
-#define CAS_FREQ1 2130.0
-#define CAS_FREQ2 2750.0
-
-#define AST_CALLERID_UNKNOWN "<unknown>"
-
-static inline void gen_tones(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2)
-{
- int x;
- float t;
- for (x=0;x<len;x++) {
- t = *cr1 * ddr1 - *ci1 * ddi1;
- *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
- *cr1 = t;
- t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
- *cr1 *= t;
- *ci1 *= t;
-
- t = *cr2 * ddr2 - *ci2 * ddi2;
- *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
- *cr2 = t;
- t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
- *cr2 *= t;
- *ci2 *= t;
- buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
- }
-}
-
-static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
-{
- int x;
- float t;
- for (x=0;x<len;x++) {
- t = *cr1 * ddr1 - *ci1 * ddi1;
- *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
- *cr1 = t;
- t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
- *cr1 *= t;
- *ci1 *= t;
- buf[x] = AST_LIN2X(*cr1 * 8192.0);
- }
-}
-
-/*! \brief Initialize stuff for inverse FFT */
-void callerid_init(void)
-{
- cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
- cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
- cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
- cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
- sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
- sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
- casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
- casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
- casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
- casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
-}
-
-struct callerid_state *callerid_new(int cid_signalling)
-{
- struct callerid_state *cid;
-
- if ((cid = ast_calloc(1, sizeof(*cid)))) {
- cid->fskd.spb = 7.0; /* 1200 baud */
- /* cid->fskd.hdlc = 0; */ /* Async */
- cid->fskd.nbit = 8; /* 8 bits */
- cid->fskd.nstop = 1.0; /* 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.pcola = 0; */ /* No clue */
- /* cid->fskd.cont = 0.0; */ /* Digital PLL reset */
- /* cid->fskd.x0 = 0.0; */
- /* cid->fskd.state = 0; */
- cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
- /* cid->pos = 0; */
- }
-
- return cid;
-}
-
-void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
-{
- *flags = cid->flags;
- if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NAME))
- *name = NULL;
- else
- *name = cid->name;
- if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
- *number = NULL;
- else
- *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;
- int saslen=2400;
- float cr1 = 1.0;
- float ci1 = 0.0;
- float cr2 = 1.0;
- float ci2 = 0.0;
- if (sendsas) {
- if (len < saslen)
- return -1;
- gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
- len -= saslen;
- pos += saslen;
- cr2 = cr1;
- ci2 = ci1;
- }
- gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
- return 0;
-}
-
-static unsigned short calc_crc(unsigned short crc, unsigned char data)
-{
- unsigned int i, j, org, dst;
- org = data;
- dst = 0;
-
- for (i=0; i < CHAR_BIT; i++) {
- org <<= 1;
- dst >>= 1;
- if (org & 0x100) {
- dst |= 0x80;
- }
- }
- data = (unsigned char)dst;
- crc ^= (unsigned int)data << (16 - CHAR_BIT);
- for ( j=0; j<CHAR_BIT; j++ ) {
- if ( crc & 0x8000U )
- crc = (crc << 1) ^ 0x1021U ;
- else
- crc <<= 1 ;
- }
- return crc;
-}
-
-int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
-{
- int mylen = len;
- int olen;
- int b = 'X';
- int b2 ;
- int res;
- int x;
- short *buf;
- short *obuf;
-
- if (!(buf = ast_calloc(1, 2 * len + cid->oldlen))) {
- return -1;
- }
-
- obuf = buf;
- memcpy(buf, cid->oldstuff, cid->oldlen);
- mylen += cid->oldlen/2;
-
- for (x=0;x<len;x++)
- buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
-
- while (mylen >= 160) {
- b = b2 = 0;
- olen = mylen;
- res = fsk_serie(&cid->fskd, buf, &mylen, &b);
-
- if (mylen < 0) {
- ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
- free(obuf);
- return -1;
- }
-
- buf += (olen - mylen);
-
- if (res < 0) {
- ast_log(LOG_NOTICE, "fsk_serie failed\n");
- free(obuf);
- return -1;
- }
-
- if (res == 1) {
-
- b2 = b ;
- b = b & 0x7f ;
-
- /* crc checksum calculation */
- if ( cid->sawflag > 1 ) {
- cid->crc = calc_crc(cid->crc, (unsigned char)b2);
- }
-
- /* Ignore invalid bytes */
- if (b > 0xff) {
- continue;
- }
-
- /* skip DLE if needed */
- if ( cid->sawflag > 0 ) {
- if ( cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10 ) {
- cid->skipflag = 1 ;
- continue ;
- }
- }
- if ( cid->skipflag == 1 ) {
- cid->skipflag = 0 ;
- }
-
- /* caller id retrieval */
- switch(cid->sawflag) {
- case 0: /* DLE */
- if (b == 0x10) {
- cid->sawflag = 1;
- cid->skipflag = 0;
- cid->crc = 0;
- }
- break;
- case 1: /* SOH */
- if (b == 0x01) {
- cid->sawflag = 2;
- }
- break ;
- case 2: /* HEADER */
- if (b == 0x07) {
- cid->sawflag = 3;
- }
- break;
- case 3: /* STX */
- if (b == 0x02) {
- cid->sawflag = 4;
- }
- break;
- case 4: /* SERVICE TYPE */
- if (b == 0x40) {
- cid->sawflag = 5;
- }
- break;
- case 5: /* Frame Length */
- cid->sawflag = 6;
- break;
- case 6: /* NUMBER TYPE */
- cid->sawflag = 7;
- cid->pos = 0;
- cid->rawdata[cid->pos++] = b;
- break;
- case 7: /* NUMBER LENGTH */
- cid->sawflag = 8;
- cid->len = b;
- if ( (cid->len+2) >= sizeof( cid->rawdata ) ) {
- ast_log(LOG_WARNING, "too long caller id string\n" ) ;
- free(obuf);
- return -1;
- }
- cid->rawdata[cid->pos++] = b;
- break;
- case 8: /* Retrieve message */
- cid->rawdata[cid->pos++] = b;
- cid->len--;
- if (cid->len<=0) {
- cid->rawdata[cid->pos] = '\0';
- cid->sawflag = 9;
- }
- break;
- case 9: /* ETX */
- cid->sawflag = 10;
- break;
- case 10: /* CRC Checksum 1 */
- cid->sawflag = 11;
- break;
- case 11: /* CRC Checksum 2 */
- cid->sawflag = 12;
- if ( cid->crc != 0 ) {
- ast_log(LOG_WARNING, "crc checksum error\n" ) ;
- free(obuf);
- return -1;
- }
- /* extract caller id data */
- for (x=0; x<cid->pos; ) {
- switch (cid->rawdata[x++]) {
- case 0x02: /* caller id number */
- cid->number[0] = '\0';
- cid->name[0] = '\0';
- cid->flags = 0;
- res = cid->rawdata[x++];
- ast_copy_string(cid->number, &cid->rawdata[x], res+1 );
- x += res;
- break;
- case 0x21: /* additional information */
- /* length */
- x++;
- /* number type */
- switch (cid->rawdata[x]) {
- case 0x00: /* unknown */
- case 0x01: /* international number */
- case 0x02: /* domestic number */
- case 0x03: /* network */
- case 0x04: /* local call */
- case 0x06: /* short dial number */
- case 0x07: /* reserved */
- default: /* reserved */
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "cid info:#1=%X\n", cid->rawdata[x]);
- break ;
- }
- x++;
- /* numbering plan octed 4 */
- x++;
- /* numbering plan octed 5 */
- switch (cid->rawdata[x]) {
- case 0x00: /* unknown */
- case 0x01: /* recommendation E.164 ISDN */
- case 0x03: /* recommendation X.121 */
- case 0x04: /* telex dial plan */
- case 0x08: /* domestic dial plan */
- case 0x09: /* private dial plan */
- case 0x05: /* reserved */
- default: /* reserved */
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "cid info:#2=%X\n", cid->rawdata[x]);
- break ;
- }
- x++;
- break ;
- case 0x04: /* no callerid reason */
- /* length */
- x++;
- /* no callerid reason code */
- switch (cid->rawdata[x]) {
- case 'P': /* caller id denied by user */
- case 'O': /* service not available */
- case 'C': /* pay phone */
- case 'S': /* service congested */
- cid->flags |= CID_UNKNOWN_NUMBER;
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "no cid reason:%c\n",cid->rawdata[x]);
- break ;
- }
- x++;
- break ;
- case 0x09: /* dialed number */
- /* length */
- res = cid->rawdata[x++];
- /* dialed number */
- x += res;
- break ;
- case 0x22: /* dialed number additional information */
- /* length */
- x++;
- /* number type */
- switch (cid->rawdata[x]) {
- case 0x00: /* unknown */
- case 0x01: /* international number */
- case 0x02: /* domestic number */
- case 0x03: /* network */
- case 0x04: /* local call */
- case 0x06: /* short dial number */
- case 0x07: /* reserved */
- default: /* reserved */
- if (option_debug > 1)
- ast_log(LOG_NOTICE, "did info:#1=%X\n", cid->rawdata[x]);
- break ;
- }
- x++;
- /* numbering plan octed 4 */
- x++;
- /* numbering plan octed 5 */
- switch (cid->rawdata[x]) {
- case 0x00: /* unknown */
- case 0x01: /* recommendation E.164 ISDN */
- case 0x03: /* recommendation X.121 */
- case 0x04: /* telex dial plan */
- case 0x08: /* domestic dial plan */
- case 0x09: /* private dial plan */
- case 0x05: /* reserved */
- default: /* reserved */
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "did info:#2=%X\n", cid->rawdata[x]);
- break ;
- }
- x++;
- break ;
- }
- }
- free(obuf);
- return 1;
- break;
- default:
- ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag);
- }
- }
- }
- if (mylen) {
- memcpy(cid->oldstuff, buf, mylen * 2);
- cid->oldlen = mylen * 2;
- } else
- cid->oldlen = 0;
- free(obuf);
- return 0;
-}
-
-
-int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
-{
- int mylen = len;
- int olen;
- int b = 'X';
- int res;
- int x;
- short *buf;
- short *obuf;
-
- if (!(buf = ast_calloc(1, 2 * len + cid->oldlen))) {
- return -1;
- }
-
- obuf = buf;
- memcpy(buf, cid->oldstuff, cid->oldlen);
- mylen += cid->oldlen/2;
-
- for (x=0;x<len;x++)
- buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
- while(mylen >= 160) {
- olen = mylen;
- res = fsk_serie(&cid->fskd, buf, &mylen, &b);
- if (mylen < 0) {
- ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
- free(obuf);
- return -1;
- }
- buf += (olen - mylen);
- if (res < 0) {
- ast_log(LOG_NOTICE, "fsk_serie failed\n");
- free(obuf);
- return -1;
- }
- if (res == 1) {
- /* Ignore invalid bytes */
- if (b > 0xff)
- continue;
- switch(cid->sawflag) {
- case 0: /* Look for flag */
- if (b == 'U')
- cid->sawflag = 2;
- break;
- case 2: /* Get lead-in */
- if ((b == 0x04) || (b == 0x80)) {
- cid->type = b;
- cid->sawflag = 3;
- cid->cksum = b;
- }
- break;
- case 3: /* Get length */
- /* Not a lead in. We're ready */
- cid->sawflag = 4;
- cid->len = b;
- cid->pos = 0;
- cid->cksum += b;
- break;
- case 4: /* Retrieve message */
- if (cid->pos >= 128) {
- ast_log(LOG_WARNING, "Caller ID too long???\n");
- free(obuf);
- return -1;
- }
- cid->rawdata[cid->pos++] = b;
- cid->len--;
- cid->cksum += b;
- if (!cid->len) {
- cid->rawdata[cid->pos] = '\0';
- cid->sawflag = 5;
- }
- break;
- case 5: /* Check checksum */
- if (b != (256 - (cid->cksum & 0xff))) {
- ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
- /* Try again */
- cid->sawflag = 0;
- break;
- }
-
- cid->number[0] = '\0';
- cid->name[0] = '\0';
- /* If we get this far we're fine. */
- if (cid->type == 0x80) {
- /* MDMF */
- /* Go through each element and process */
- for (x=0;x< cid->pos;) {
- switch(cid->rawdata[x++]) {
- case 1:
- /* Date */
- break;
- case 2: /* Number */
- case 3: /* Number (for Zebble) */
- case 4: /* Number */
- res = cid->rawdata[x];
- if (res > 32) {
- 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) */
- break;
- case 7: /* Name */
- case 8: /* Name */
- res = cid->rawdata[x];
- if (res > 32) {
- ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
- res = 32;
- }
- 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:
- ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
- }
- res = cid->rawdata[x];
- if (0 > res){ /* Negative offset in the CID Spill */
- ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
- /* Try again */
- cid->sawflag = 0;
- break; /* Exit the loop */
- }
- x += cid->rawdata[x];
- x++;
- }
- } else {
- /* SDMF */
- ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
- }
- /* Update flags */
- cid->flags = 0;
- if (!strcmp(cid->number, "P")) {
- strcpy(cid->number, "");
- cid->flags |= CID_PRIVATE_NUMBER;
- } else if (!strcmp(cid->number, "O") || ast_strlen_zero(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)) {
- strcpy(cid->name, "");
- cid->flags |= CID_UNKNOWN_NAME;
- }
- free(obuf);
- return 1;
- break;
- default:
- ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
- }
- }
- }
- if (mylen) {
- memcpy(cid->oldstuff, buf, mylen * 2);
- cid->oldlen = mylen * 2;
- } else
- cid->oldlen = 0;
- free(obuf);
- return 0;
-}
-
-void callerid_free(struct callerid_state *cid)
-{
- free(cid);
-}
-
-static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
-{
- time_t t;
- struct tm tm;
- char *ptr;
- int res;
- int i,x;
- /* Get the time */
- time(&t);
- ast_localtime(&t, &tm, NULL);
-
- ptr = msg;
-
- /* Format time and message header */
- res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
- tm.tm_mday, tm.tm_hour, tm.tm_min);
- size -= res;
- ptr += res;
- if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
- /* Indicate number not known */
- res = snprintf(ptr, size, "\004\001O");
- size -= res;
- ptr += res;
- } else if (flags & CID_PRIVATE_NUMBER) {
- /* Indicate number is private */
- res = snprintf(ptr, size, "\004\001P");
- size -= res;
- ptr += res;
- } else {
- /* Send up to 16 digits of number MAX */
- i = strlen(number);
- if (i > 16) i = 16;
- res = snprintf(ptr, size, "\002%c", i);
- size -= res;
- ptr += res;
- for (x = 0; x < i; x++)
- ptr[x] = number[x];
- ptr[i] = '\0';
- ptr += i;
- size -= i;
- }
-
- if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
- /* Indicate name not known */
- res = snprintf(ptr, size, "\010\001O");
- size -= res;
- ptr += res;
- } else if (flags & CID_PRIVATE_NAME) {
- /* Indicate name is private */
- res = snprintf(ptr, size, "\010\001P");
- size -= res;
- ptr += res;
- } else {
- /* Send up to 16 digits of name MAX */
- i = strlen(name);
- if (i > 16) i = 16;
- res = snprintf(ptr, size, "\007%c", i);
- size -= res;
- ptr += res;
- for (x=0;x<i;x++)
- ptr[x] = name[x];
- ptr[i] = '\0';
- ptr += i;
- size -= i;
- }
- return (ptr - msg);
-
-}
-
-int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
-{
- unsigned char msg[256];
- int len=0;
- int sum;
- int x;
- int bytes = 0;
- float cr = 1.0;
- float ci = 0.0;
- float scont = 0.0;
- if (mdmf) {
- /* MDMF Message waiting */
- msg[len++] = 0x82;
- /* Length is 3 */
- msg[len++] = 3;
- /* IE is "Message Waiting Parameter" */
- msg[len++] = 0xb;
- /* Length of IE is one */
- msg[len++] = 1;
- /* Active or not */
- if (active)
- msg[len++] = 0xff;
- else
- msg[len++] = 0x00;
- } else {
- /* SDMF Message waiting */
- msg[len++] = 0x6;
- /* Length is 3 */
- msg[len++] = 3;
- if (active) {
- msg[len++] = 0x42;
- msg[len++] = 0x42;
- msg[len++] = 0x42;
- } else {
- msg[len++] = 0x6f;
- msg[len++] = 0x6f;
- msg[len++] = 0x6f;
- }
- }
- sum = 0;
- for (x=0; x<len; x++)
- 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);
- /* Send 170ms of callerid marks */
- for (x=0; x<170; x++)
- PUT_CLID_MARKMS;
- for (x=0; x<len; x++) {
- PUT_CLID(msg[x]);
- }
- /* Send 50 more ms of marks */
- for (x=0; x<50; x++)
- PUT_CLID_MARKMS;
- return bytes;
-}
-
-int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec)
-{
- int bytes=0;
- int x, sum;
- int len;
-
- /* Initial carriers (real/imaginary) */
- float cr = 1.0;
- float ci = 0.0;
- float scont = 0.0;
- char msg[256];
- len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
- if (!callwaiting) {
- /* 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);
- }
- /* Send 150ms of callerid marks */
- for (x=0; x<150; x++)
- PUT_CLID_MARKMS;
- /* Send 0x80 indicating MDMF format */
- PUT_CLID(0x80);
- /* Put length of whole message */
- PUT_CLID(len);
- sum = 0x80 + strlen(msg);
- /* Put each character of message and update checksum */
- for (x=0; x<len; x++) {
- PUT_CLID(msg[x]);
- sum += msg[x];
- }
- /* Send 2's compliment of sum */
- PUT_CLID(256 - (sum & 255));
-
- /* Send 50 more ms of marks */
- for (x=0; x<50; x++)
- PUT_CLID_MARKMS;
-
- return bytes;
-}
-
-/*! \brief Clean up phone string
- * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
- * Basically, remove anything that could be invalid in a pattern.
- */
-void ast_shrink_phone_number(char *n)
-{
- int x, y=0;
- int bracketed = 0;
-
- for (x=0; n[x]; x++) {
- switch(n[x]) {
- case '[':
- bracketed++;
- n[y++] = n[x];
- break;
- case ']':
- bracketed--;
- n[y++] = n[x];
- break;
- case '-':
- if (bracketed)
- n[y++] = n[x];
- break;
- case '.':
- if (!n[x+1])
- n[y++] = n[x];
- break;
- default:
- if (!strchr("( )", n[x]))
- n[y++] = n[x];
- }
- }
- n[y] = '\0';
-}
-
-/*! \brief Checks if phone number consists of valid characters
- \param exten String that needs to be checked
- \param valid Valid characters in string
- \return 1 if valid string, 0 if string contains invalid characters
-*/
-static int ast_is_valid_string(const char *exten, const char *valid)
-{
- int x;
-
- if (ast_strlen_zero(exten))
- return 0;
- for (x=0; exten[x]; x++)
- if (!strchr(valid, exten[x]))
- return 0;
- return 1;
-}
-
-/*! \brief checks if string consists only of digits and * \# and +
- \return 1 if string is valid AST phone number
- \return 0 if not
-*/
-int ast_isphonenumber(const char *n)
-{
- return ast_is_valid_string(n, "0123456789*#+");
-}
-
-/*! \brief checks if string consists only of digits and ( ) - * \# and +
- Pre-qualifies the string for ast_shrink_phone_number()
- \return 1 if string is valid AST shrinkable phone number
- \return 0 if not
-*/
-int ast_is_shrinkable_phonenumber(const char *exten)
-{
- return ast_is_valid_string(exten, "0123456789*#+()-.");
-}
-
-/*!
- * \brief Destructively parse instr for caller id information
- * \return always returns 0, as the code always returns something.
- * \note XXX 'name' is not parsed consistently e.g. we have
- * input location name
- * " foo bar " <123> 123 ' foo bar ' (with spaces around)
- * " foo bar " NULL 'foo bar' (without spaces around)
- * The parsing of leading and trailing space/quotes should be more consistent.
- */
-int ast_callerid_parse(char *instr, char **name, char **location)
-{
- char *ns, *ne, *ls, *le;
-
- /* Try "name" <location> format or name <location> format */
- if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
- *ls = *le = '\0'; /* location found, trim off the brackets */
- *location = ls + 1; /* and this is the result */
- if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
- *ns = *ne = '\0'; /* trim off the quotes */
- *name = ns + 1; /* and this is the name */
- } else if (ns) {
- /* An opening quote was found but no closing quote was. The closing
- * quote may actually be after the end of the bracketed number
- */
- if (strchr(le + 1, '\"')) {
- *ns = '\0';
- *name = ns + 1;
- ast_trim_blanks(*name);
- }
- } else { /* no quotes, trim off leading and trailing spaces */
- *name = ast_skip_blanks(instr);
- ast_trim_blanks(*name);
- }
- } else { /* no valid brackets */
- char tmp[256];
-
- ast_copy_string(tmp, instr, sizeof(tmp));
- ast_shrink_phone_number(tmp);
- if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
- *name = NULL;
- strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
- *location = instr;
- } else { /* Assume it's just a name. */
- *location = NULL;
- if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
- *ns = *ne = '\0'; /* trim off the quotes */
- *name = ns + 1; /* and this is the name */
- } else { /* no quotes, trim off leading and trailing spaces */
- *name = ast_skip_blanks(instr);
- ast_trim_blanks(*name);
- }
- }
- }
- return 0;
-}
-
-static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, int codec)
-{
- if (ast_strlen_zero(name))
- name = NULL;
- if (ast_strlen_zero(number))
- number = NULL;
- return callerid_generate(buf, number, name, 0, callwaiting, codec);
-}
-
-int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec)
-{
- return __ast_callerid_generate(buf, name, number, 0, codec);
-}
-
-int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec)
-{
- return __ast_callerid_generate(buf, name, number, 1, codec);
-}
-
-char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
-{
- if (!unknown)
- unknown = "<unknown>";
- if (name && num)
- snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
- else if (name)
- ast_copy_string(buf, name, bufsiz);
- else if (num)
- ast_copy_string(buf, num, bufsiz);
- else
- ast_copy_string(buf, unknown, bufsiz);
- return buf;
-}
-
-int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
-{
- char *tmp;
- char *l = NULL, *n = NULL;
-
- tmp = ast_strdupa(buf);
- ast_callerid_parse(tmp, &n, &l);
- if (n)
- ast_copy_string(name, n, namelen);
- else
- name[0] = '\0';
- if (l) {
- ast_shrink_phone_number(l);
- ast_copy_string(num, l, numlen);
- } else
- num[0] = '\0';
- return 0;
-}
-
-/*! \brief Translation table for Caller ID Presentation settings */
-static struct {
- int val;
- char *name;
- char *description;
-} pres_types[] = {
- { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
- { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
- { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
- { AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
- { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
- { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
- { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
- { AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
- { AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
-};
-
-/*! \brief Convert caller ID text code to value
- used in config file parsing
- \param data text string
- \return value AST_PRES_ from callerid.h
-*/
-int ast_parse_caller_presentation(const char *data)
-{
- int i;
-
- for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
- if (!strcasecmp(pres_types[i].name, data))
- return pres_types[i].val;
- }
-
- return -1;
-}
-
-/*! \brief Convert caller ID pres value to explanatory string
- \param data value (see callerid.h AST_PRES_ )
- \return string for human presentation
-*/
-const char *ast_describe_caller_presentation(int data)
-{
- int i;
-
- for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
- if (pres_types[i].val == data)
- return pres_types[i].description;
- }
-
- return "unknown";
-}
diff --git a/main/cdr.c b/main/cdr.c
deleted file mode 100644
index 39045c9ed..000000000
--- a/main/cdr.c
+++ /dev/null
@@ -1,1499 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Call Detail Record API
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * \note Includes code and algorithms from the Zapata library.
- *
- * \note 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
- * or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR
- * isn't properly generated and posted.
- */
-
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <signal.h>
-
-#include "asterisk/lock.h"
-#include "asterisk/channel.h"
-#include "asterisk/cdr.h"
-#include "asterisk/logger.h"
-#include "asterisk/callerid.h"
-#include "asterisk/causes.h"
-#include "asterisk/options.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/utils.h"
-#include "asterisk/sched.h"
-#include "asterisk/config.h"
-#include "asterisk/cli.h"
-#include "asterisk/stringfields.h"
-
-/*! Default AMA flag for billing records (CDR's) */
-int ast_default_amaflags = AST_CDR_DOCUMENTATION;
-char ast_default_accountcode[AST_MAX_ACCOUNT_CODE];
-
-struct ast_cdr_beitem {
- char name[20];
- char desc[80];
- ast_cdrbe be;
- AST_LIST_ENTRY(ast_cdr_beitem) list;
-};
-
-static AST_LIST_HEAD_STATIC(be_list, ast_cdr_beitem);
-
-struct ast_cdr_batch_item {
- struct ast_cdr *cdr;
- struct ast_cdr_batch_item *next;
-};
-
-static struct ast_cdr_batch {
- int size;
- struct ast_cdr_batch_item *head;
- struct ast_cdr_batch_item *tail;
-} *batch = NULL;
-
-static struct sched_context *sched;
-static int cdr_sched = -1;
-static pthread_t cdr_thread = AST_PTHREADT_NULL;
-
-#define BATCH_SIZE_DEFAULT 100
-#define BATCH_TIME_DEFAULT 300
-#define BATCH_SCHEDULER_ONLY_DEFAULT 0
-#define BATCH_SAFE_SHUTDOWN_DEFAULT 1
-
-static int enabled; /*! Is the CDR subsystem enabled ? */
-static int unanswered;
-static int batchmode;
-static int batchsize;
-static int batchtime;
-static int batchscheduleronly;
-static int batchsafeshutdown;
-
-AST_MUTEX_DEFINE_STATIC(cdr_batch_lock);
-
-/* these are used to wake up the CDR thread when there's work to do */
-AST_MUTEX_DEFINE_STATIC(cdr_pending_lock);
-static ast_cond_t cdr_pending_cond;
-
-
-/*! Register a CDR driver. Each registered CDR driver generates a CDR
- \return 0 on success, -1 on failure
-*/
-int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
-{
- struct ast_cdr_beitem *i;
-
- if (!name)
- return -1;
- if (!be) {
- ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
- return -1;
- }
-
- AST_LIST_LOCK(&be_list);
- AST_LIST_TRAVERSE(&be_list, i, list) {
- if (!strcasecmp(name, i->name))
- break;
- }
- AST_LIST_UNLOCK(&be_list);
-
- if (i) {
- ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
- return -1;
- }
-
- if (!(i = ast_calloc(1, sizeof(*i))))
- return -1;
-
- i->be = be;
- ast_copy_string(i->name, name, sizeof(i->name));
- ast_copy_string(i->desc, desc, sizeof(i->desc));
-
- AST_LIST_LOCK(&be_list);
- AST_LIST_INSERT_HEAD(&be_list, i, list);
- AST_LIST_UNLOCK(&be_list);
-
- return 0;
-}
-
-/*! unregister a CDR driver */
-void ast_cdr_unregister(const char *name)
-{
- struct ast_cdr_beitem *i = NULL;
-
- AST_LIST_LOCK(&be_list);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) {
- if (!strcasecmp(name, i->name)) {
- AST_LIST_REMOVE_CURRENT(&be_list, list);
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s' CDR backend\n", name);
- free(i);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&be_list);
-}
-
-int ast_cdr_isset_unanswered(void)
-{
- return unanswered;
-}
-
-/*! Duplicate a CDR record
- \returns Pointer to new CDR record
-*/
-struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
-{
- struct ast_cdr *newcdr;
-
- if (!cdr) /* don't die if we get a null cdr pointer */
- return NULL;
- newcdr = ast_cdr_alloc();
- if (!newcdr)
- return NULL;
-
- memcpy(newcdr, cdr, sizeof(*newcdr));
- /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */
- memset(&newcdr->varshead, 0, sizeof(newcdr->varshead));
- ast_cdr_copy_vars(newcdr, cdr);
- newcdr->next = NULL;
-
- return newcdr;
-}
-
-static const char *ast_cdr_getvar_internal(struct ast_cdr *cdr, const char *name, int recur)
-{
- if (ast_strlen_zero(name))
- return NULL;
-
- for (; cdr; cdr = recur ? cdr->next : NULL) {
- struct ast_var_t *variables;
- struct varshead *headp = &cdr->varshead;
- AST_LIST_TRAVERSE(headp, variables, entries) {
- if (!strcasecmp(name, ast_var_name(variables)))
- return ast_var_value(variables);
- }
- }
-
- return NULL;
-}
-
-static void cdr_get_tv(struct timeval tv, const char *fmt, char *buf, int bufsize)
-{
- if (fmt == NULL) { /* raw mode */
- snprintf(buf, bufsize, "%ld.%06ld", (long)tv.tv_sec, (long)tv.tv_usec);
- } else {
- time_t t = tv.tv_sec;
- if (t) {
- struct tm tm;
-
- ast_localtime(&t, &tm, NULL);
- strftime(buf, bufsize, fmt, &tm);
- }
- }
-}
-
-/*! CDR channel variable retrieval */
-void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw)
-{
- const char *fmt = "%Y-%m-%d %T";
- const char *varbuf;
-
- if (!cdr) /* don't die if the cdr is null */
- return;
-
- *ret = NULL;
- /* special vars (the ones from the struct ast_cdr when requested by name)
- I'd almost say we should convert all the stringed vals to vars */
-
- if (!strcasecmp(name, "clid"))
- ast_copy_string(workspace, cdr->clid, workspacelen);
- else if (!strcasecmp(name, "src"))
- ast_copy_string(workspace, cdr->src, workspacelen);
- else if (!strcasecmp(name, "dst"))
- ast_copy_string(workspace, cdr->dst, workspacelen);
- else if (!strcasecmp(name, "dcontext"))
- ast_copy_string(workspace, cdr->dcontext, workspacelen);
- else if (!strcasecmp(name, "channel"))
- ast_copy_string(workspace, cdr->channel, workspacelen);
- else if (!strcasecmp(name, "dstchannel"))
- ast_copy_string(workspace, cdr->dstchannel, workspacelen);
- else if (!strcasecmp(name, "lastapp"))
- ast_copy_string(workspace, cdr->lastapp, workspacelen);
- else if (!strcasecmp(name, "lastdata"))
- ast_copy_string(workspace, cdr->lastdata, workspacelen);
- else if (!strcasecmp(name, "start"))
- cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
- else if (!strcasecmp(name, "answer"))
- cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
- else if (!strcasecmp(name, "end"))
- cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
- else if (!strcasecmp(name, "duration"))
- snprintf(workspace, workspacelen, "%ld", cdr->duration);
- else if (!strcasecmp(name, "billsec"))
- snprintf(workspace, workspacelen, "%ld", cdr->billsec);
- else if (!strcasecmp(name, "disposition")) {
- if (raw) {
- snprintf(workspace, workspacelen, "%ld", cdr->disposition);
- } else {
- ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
- }
- } else if (!strcasecmp(name, "amaflags")) {
- if (raw) {
- snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
- } else {
- ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen);
- }
- } else if (!strcasecmp(name, "accountcode"))
- ast_copy_string(workspace, cdr->accountcode, workspacelen);
- else if (!strcasecmp(name, "uniqueid"))
- ast_copy_string(workspace, cdr->uniqueid, workspacelen);
- else if (!strcasecmp(name, "userfield"))
- ast_copy_string(workspace, cdr->userfield, workspacelen);
- else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur)))
- ast_copy_string(workspace, varbuf, workspacelen);
- else
- workspace[0] = '\0';
-
- if (!ast_strlen_zero(workspace))
- *ret = workspace;
-}
-
-/* readonly cdr variables */
-static const char *cdr_readonly_vars[] = { "clid", "src", "dst", "dcontext", "channel", "dstchannel",
- "lastapp", "lastdata", "start", "answer", "end", "duration",
- "billsec", "disposition", "amaflags", "accountcode", "uniqueid",
- "userfield", NULL };
-/*! Set a CDR channel variable
- \note You can't set the CDR variables that belong to the actual CDR record, like "billsec".
-*/
-int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur)
-{
- struct ast_var_t *newvariable;
- struct varshead *headp;
- int x;
-
- if (!cdr) /* don't die if the cdr is null */
- return -1;
-
- for(x = 0; cdr_readonly_vars[x]; x++) {
- if (!strcasecmp(name, cdr_readonly_vars[x])) {
- ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name);
- return -1;
- }
- }
-
- if (!cdr) {
- ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n");
- return -1;
- }
-
- for (; cdr; cdr = recur ? cdr->next : NULL) {
- if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
- continue;
- headp = &cdr->varshead;
- AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
- if (!strcasecmp(ast_var_name(newvariable), name)) {
- /* there is already such a variable, delete it */
- AST_LIST_REMOVE_CURRENT(headp, entries);
- ast_var_delete(newvariable);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- if (value) {
- newvariable = ast_var_assign(name, value);
- AST_LIST_INSERT_HEAD(headp, newvariable, entries);
- }
- }
-
- return 0;
-}
-
-int ast_cdr_copy_vars(struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
-{
- struct ast_var_t *variables, *newvariable = NULL;
- struct varshead *headpa, *headpb;
- const char *var, *val;
- int x = 0;
-
- if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */
- return 0;
-
- headpa = &from_cdr->varshead;
- headpb = &to_cdr->varshead;
-
- AST_LIST_TRAVERSE(headpa,variables,entries) {
- if (variables &&
- (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
- !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
- newvariable = ast_var_assign(var, val);
- AST_LIST_INSERT_HEAD(headpb, newvariable, entries);
- x++;
- }
- }
-
- return x;
-}
-
-int ast_cdr_serialize_variables(struct ast_cdr *cdr, char *buf, size_t size, char delim, char sep, int recur)
-{
- struct ast_var_t *variables;
- const char *var, *val;
- char *tmp;
- char workspace[256];
- int total = 0, x = 0, i;
-
- memset(buf, 0, size);
-
- for (; cdr; cdr = recur ? cdr->next : NULL) {
- if (++x > 1)
- ast_build_string(&buf, &size, "\n");
-
- AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
- if (variables &&
- (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
- !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
- if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, var, delim, val, sep)) {
- ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
- break;
- } else
- total++;
- } else
- break;
- }
-
- for (i = 0; cdr_readonly_vars[i]; i++) {
- workspace[0] = 0; /* null out the workspace, because the cdr_get_tv() won't write anything if time is NULL, so you get old vals */
- ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0);
- if (!tmp)
- continue;
-
- if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep)) {
- ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
- break;
- } else
- total++;
- }
- }
-
- return total;
-}
-
-
-void ast_cdr_free_vars(struct ast_cdr *cdr, int recur)
-{
-
- /* clear variables */
- for (; cdr; cdr = recur ? cdr->next : NULL) {
- struct ast_var_t *vardata;
- struct varshead *headp = &cdr->varshead;
- while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
- ast_var_delete(vardata);
- }
-}
-
-/*! \brief print a warning if cdr already posted */
-static void check_post(struct ast_cdr *cdr)
-{
- if (!cdr)
- return;
- if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
- ast_log(LOG_NOTICE, "CDR on channel '%s' already posted\n", S_OR(cdr->channel, "<unknown>"));
-}
-
-void ast_cdr_free(struct ast_cdr *cdr)
-{
-
- while (cdr) {
- struct ast_cdr *next = cdr->next;
- char *chan = S_OR(cdr->channel, "<unknown>");
- if (option_verbose > 1 && !ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
- ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' not posted\n", chan);
- if (option_verbose > 1 && ast_tvzero(cdr->end))
- ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' lacks end\n", chan);
- if (option_verbose > 1 && ast_tvzero(cdr->start))
- ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' lacks start\n", chan);
-
- ast_cdr_free_vars(cdr, 0);
- free(cdr);
- cdr = next;
- }
-}
-
-/*! \brief the same as a cdr_free call, only with no checks; just get rid of it */
-void ast_cdr_discard(struct ast_cdr *cdr)
-{
- while (cdr) {
- struct ast_cdr *next = cdr->next;
-
- ast_cdr_free_vars(cdr, 0);
- free(cdr);
- cdr = next;
- }
-}
-
-struct ast_cdr *ast_cdr_alloc(void)
-{
- struct ast_cdr *x = ast_calloc(1, sizeof(struct ast_cdr));
- if (!x)
- ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n");
- return x;
-}
-
-static void cdr_merge_vars(struct ast_cdr *to, struct ast_cdr *from)
-{
- struct ast_var_t *variablesfrom,*variablesto;
- struct varshead *headpfrom = &to->varshead;
- struct varshead *headpto = &from->varshead;
- AST_LIST_TRAVERSE_SAFE_BEGIN(headpfrom, variablesfrom, entries) {
- /* for every var in from, stick it in to */
- const char *fromvarname = NULL, *fromvarval = NULL;
- const char *tovarname = NULL, *tovarval = NULL;
- fromvarname = ast_var_name(variablesfrom);
- fromvarval = ast_var_value(variablesfrom);
- tovarname = 0;
-
- /* now, quick see if that var is in the 'to' cdr already */
- AST_LIST_TRAVERSE(headpto, variablesto, entries) {
-
- /* now, quick see if that var is in the 'to' cdr already */
- if ( strcasecmp(fromvarname, ast_var_name(variablesto)) == 0 ) {
- tovarname = ast_var_name(variablesto);
- tovarval = ast_var_value(variablesto);
- break;
- }
- }
- if (tovarname && strcasecmp(fromvarval,tovarval) != 0) { /* this message here to see how irritating the userbase finds it */
- ast_log(LOG_NOTICE, "Merging CDR's: variable %s value %s dropped in favor of value %s\n", tovarname, fromvarval, tovarval);
- continue;
- } else if (tovarname && strcasecmp(fromvarval,tovarval) == 0) /* if they are the same, the job is done */
- continue;
-
- /*rip this var out of the from cdr, and stick it in the to cdr */
- AST_LIST_REMOVE_CURRENT(headpfrom, entries);
- AST_LIST_INSERT_HEAD(headpto, variablesfrom, entries);
- }
- AST_LIST_TRAVERSE_SAFE_END;
-}
-
-void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from)
-{
- struct ast_cdr *zcdr;
- struct ast_cdr *lto = NULL;
- struct ast_cdr *lfrom = NULL;
- int discard_from = 0;
-
- if (!to || !from)
- return;
-
- /* don't merge into locked CDR's -- it's bad business */
- if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) {
- zcdr = to; /* safety valve? */
- while (to->next) {
- lto = to;
- to = to->next;
- }
-
- if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) {
- ast_log(LOG_WARNING, "Merging into locked CDR... no choice.");
- to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */
- lto = NULL;
- }
- }
-
- if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) {
- discard_from = 1;
- if (lto) {
- struct ast_cdr *llfrom = NULL;
- /* insert the from stuff after lto */
- lto->next = from;
- lfrom = from;
- while (lfrom && lfrom->next) {
- if (!lfrom->next->next)
- llfrom = lfrom;
- lfrom = lfrom->next;
- }
- /* rip off the last entry and put a copy of the to at the end */
- llfrom->next = to;
- from = lfrom;
- } else {
- /* save copy of the current *to cdr */
- struct ast_cdr tcdr;
- struct ast_cdr *llfrom = NULL;
- memcpy(&tcdr, to, sizeof(tcdr));
- /* copy in the locked from cdr */
- memcpy(to, from, sizeof(*to));
- lfrom = from;
- while (lfrom && lfrom->next) {
- if (!lfrom->next->next)
- llfrom = lfrom;
- lfrom = lfrom->next;
- }
- from->next = NULL;
- /* rip off the last entry and put a copy of the to at the end */
- if (llfrom == from)
- to = to->next = ast_cdr_dup(&tcdr);
- else
- to = llfrom->next = ast_cdr_dup(&tcdr);
- from = lfrom;
- }
- }
-
- if (!ast_tvzero(from->start)) {
- if (!ast_tvzero(to->start)) {
- if (ast_tvcmp(to->start, from->start) > 0 ) {
- to->start = from->start; /* use the earliest time */
- from->start = ast_tv(0,0); /* we actively "steal" these values */
- }
- /* else nothing to do */
- } else {
- to->start = from->start;
- from->start = ast_tv(0,0); /* we actively "steal" these values */
- }
- }
- if (!ast_tvzero(from->answer)) {
- if (!ast_tvzero(to->answer)) {
- if (ast_tvcmp(to->answer, from->answer) > 0 ) {
- to->answer = from->answer; /* use the earliest time */
- from->answer = ast_tv(0,0); /* we actively "steal" these values */
- }
- /* we got the earliest answer time, so we'll settle for that? */
- } else {
- to->answer = from->answer;
- from->answer = ast_tv(0,0); /* we actively "steal" these values */
- }
- }
- if (!ast_tvzero(from->end)) {
- if (!ast_tvzero(to->end)) {
- if (ast_tvcmp(to->end, from->end) < 0 ) {
- to->end = from->end; /* use the latest time */
- from->end = ast_tv(0,0); /* we actively "steal" these values */
- to->duration = to->end.tv_sec - to->start.tv_sec; /* don't forget to update the duration, billsec, when we set end */
- to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec;
- }
- /* else, nothing to do */
- } else {
- to->end = from->end;
- from->end = ast_tv(0,0); /* we actively "steal" these values */
- to->duration = to->end.tv_sec - to->start.tv_sec;
- to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec;
- }
- }
- if (to->disposition < from->disposition) {
- to->disposition = from->disposition;
- from->disposition = AST_CDR_NOANSWER;
- }
- if (ast_strlen_zero(to->lastapp) && !ast_strlen_zero(from->lastapp)) {
- ast_copy_string(to->lastapp, from->lastapp, sizeof(to->lastapp));
- from->lastapp[0] = 0; /* theft */
- }
- if (ast_strlen_zero(to->lastdata) && !ast_strlen_zero(from->lastdata)) {
- ast_copy_string(to->lastdata, from->lastdata, sizeof(to->lastdata));
- from->lastdata[0] = 0; /* theft */
- }
- if (ast_strlen_zero(to->dcontext) && !ast_strlen_zero(from->dcontext)) {
- ast_copy_string(to->dcontext, from->dcontext, sizeof(to->dcontext));
- from->dcontext[0] = 0; /* theft */
- }
- if (ast_strlen_zero(to->dstchannel) && !ast_strlen_zero(from->dstchannel)) {
- ast_copy_string(to->dstchannel, from->dstchannel, sizeof(to->dstchannel));
- from->dstchannel[0] = 0; /* theft */
- }
- if (!ast_strlen_zero(from->channel) && (ast_strlen_zero(to->channel) || !strncasecmp(from->channel, "Agent/", 6))) {
- ast_copy_string(to->channel, from->channel, sizeof(to->channel));
- from->channel[0] = 0; /* theft */
- }
- if (ast_strlen_zero(to->src) && !ast_strlen_zero(from->src)) {
- ast_copy_string(to->src, from->src, sizeof(to->src));
- from->src[0] = 0; /* theft */
- }
- if (ast_strlen_zero(to->clid) && !ast_strlen_zero(from->clid)) {
- ast_copy_string(to->clid, from->clid, sizeof(to->clid));
- from->clid[0] = 0; /* theft */
- }
- if (ast_strlen_zero(to->dst) && !ast_strlen_zero(from->dst)) {
- ast_copy_string(to->dst, from->dst, sizeof(to->dst));
- from->dst[0] = 0; /* theft */
- }
- if (!to->amaflags)
- to->amaflags = AST_CDR_DOCUMENTATION;
- if (!from->amaflags)
- from->amaflags = AST_CDR_DOCUMENTATION; /* make sure both amaflags are set to something (DOC is default) */
- if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) {
- to->amaflags = from->amaflags;
- }
- if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) {
- ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode));
- }
- if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) {
- ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield));
- }
- /* flags, varsead, ? */
- cdr_merge_vars(from, to);
-
- if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS))
- ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS);
- if (ast_test_flag(from, AST_CDR_FLAG_POSTED))
- ast_set_flag(to, AST_CDR_FLAG_POSTED);
- if (ast_test_flag(from, AST_CDR_FLAG_LOCKED))
- ast_set_flag(to, AST_CDR_FLAG_LOCKED);
- if (ast_test_flag(from, AST_CDR_FLAG_CHILD))
- ast_set_flag(to, AST_CDR_FLAG_CHILD);
- if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED))
- ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED);
-
- /* last, but not least, we need to merge any forked CDRs to the 'to' cdr */
- while (from->next) {
- /* just rip 'em off the 'from' and insert them on the 'to' */
- zcdr = from->next;
- from->next = zcdr->next;
- zcdr->next = NULL;
- /* zcdr is now ripped from the current list; */
- ast_cdr_append(to, zcdr);
- }
- if (discard_from)
- ast_cdr_discard(from);
-}
-
-void ast_cdr_start(struct ast_cdr *cdr)
-{
- char *chan;
-
- for (; cdr; cdr = cdr->next) {
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- chan = S_OR(cdr->channel, "<unknown>");
- check_post(cdr);
- cdr->start = ast_tvnow();
- }
- }
-}
-
-void ast_cdr_answer(struct ast_cdr *cdr)
-{
-
- for (; cdr; cdr = cdr->next) {
- if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED))
- continue;
- if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
- continue;
- check_post(cdr);
- if (cdr->disposition < AST_CDR_ANSWERED)
- cdr->disposition = AST_CDR_ANSWERED;
- if (ast_tvzero(cdr->answer))
- cdr->answer = ast_tvnow();
- }
-}
-
-void ast_cdr_busy(struct ast_cdr *cdr)
-{
-
- for (; cdr; cdr = cdr->next) {
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- check_post(cdr);
- if (cdr->disposition < AST_CDR_BUSY)
- cdr->disposition = AST_CDR_BUSY;
- }
- }
-}
-
-void ast_cdr_failed(struct ast_cdr *cdr)
-{
- for (; cdr; cdr = cdr->next) {
- check_post(cdr);
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- if (cdr->disposition < AST_CDR_FAILED)
- cdr->disposition = AST_CDR_FAILED;
- }
- }
-}
-
-void ast_cdr_noanswer(struct ast_cdr *cdr)
-{
- char *chan;
-
- while (cdr) {
- chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
- if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
- ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- if (cdr->disposition < AST_CDR_NOANSWER)
- cdr->disposition = AST_CDR_NOANSWER;
- }
- cdr = cdr->next;
- }
-}
-
-/* everywhere ast_cdr_disposition is called, it will call ast_cdr_failed()
- if ast_cdr_disposition returns a non-zero value */
-
-int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
-{
- int res = 0;
-
- for (; cdr; cdr = cdr->next) {
- switch(cause) { /* handle all the non failure, busy cases, return 0 not to set disposition,
- return -1 to set disposition to FAILED */
- case AST_CAUSE_BUSY:
- ast_cdr_busy(cdr);
- break;
- case AST_CAUSE_NO_ANSWER:
- ast_cdr_noanswer(cdr);
- break;
- case AST_CAUSE_NORMAL:
- break;
- default:
- res = -1;
- }
- }
- return res;
-}
-
-void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chann)
-{
- for (; cdr; cdr = cdr->next) {
- check_post(cdr);
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
- ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel));
- }
-}
-
-void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data)
-{
-
- for (; cdr; cdr = cdr->next) {
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- check_post(cdr);
- ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp));
- ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata));
- }
- }
-}
-
-/* set cid info for one record */
-static void set_one_cid(struct ast_cdr *cdr, struct ast_channel *c)
-{
- /* Grab source from ANI or normal Caller*ID */
- const char *num = S_OR(c->cid.cid_ani, c->cid.cid_num);
- if (!cdr)
- return;
- if (!ast_strlen_zero(c->cid.cid_name)) {
- if (!ast_strlen_zero(num)) /* both name and number */
- snprintf(cdr->clid, sizeof(cdr->clid), "\"%s\" <%s>", c->cid.cid_name, num);
- else /* only name */
- ast_copy_string(cdr->clid, c->cid.cid_name, sizeof(cdr->clid));
- } else if (!ast_strlen_zero(num)) { /* only number */
- ast_copy_string(cdr->clid, num, sizeof(cdr->clid));
- } else { /* nothing known */
- cdr->clid[0] = '\0';
- }
- ast_copy_string(cdr->src, S_OR(num, ""), sizeof(cdr->src));
-
-}
-int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c)
-{
- for (; cdr; cdr = cdr->next) {
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
- set_one_cid(cdr, c);
- }
- return 0;
-}
-
-int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
-{
- char *chan;
-
- for ( ; cdr ; cdr = cdr->next) {
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- chan = S_OR(cdr->channel, "<unknown>");
- ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
- set_one_cid(cdr, c);
-
- cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL;
- cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags;
- ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
- /* Destination information */
- ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst));
- ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext));
- /* Unique call identifier */
- ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid));
- }
- }
- return 0;
-}
-
-/* Three routines were "fixed" via 10668, and later shown that
- users were depending on this behavior. ast_cdr_end,
- ast_cdr_setvar and ast_cdr_answer are the three routines.
- While most of the other routines would not touch
- LOCKED cdr's, these three routines were designed to
- operate on locked CDR's as a matter of course.
- I now appreciate how this plays with the ForkCDR app,
- which forms these cdr chains in the first place.
- cdr_end is pretty key: all cdrs created are closed
- together. They only vary by start time. Arithmetically,
- users can calculate the subintervals they wish to track. */
-
-void ast_cdr_end(struct ast_cdr *cdr)
-{
- for ( ; cdr ; cdr = cdr->next) {
- if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
- continue;
- check_post(cdr);
- if (ast_tvzero(cdr->end))
- cdr->end = ast_tvnow();
- if (ast_tvzero(cdr->start)) {
- ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>"));
- cdr->disposition = AST_CDR_FAILED;
- } else
- cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
- if (ast_tvzero(cdr->answer)) {
- if (cdr->disposition == AST_CDR_ANSWERED) {
- ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>"));
- cdr->disposition = AST_CDR_FAILED;
- }
- } else
- cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
- }
-}
-
-char *ast_cdr_disp2str(int disposition)
-{
- switch (disposition) {
- case AST_CDR_NULL:
- return "NO ANSWER"; /* by default, for backward compatibility */
- case AST_CDR_NOANSWER:
- return "NO ANSWER";
- case AST_CDR_FAILED:
- return "FAILED";
- case AST_CDR_BUSY:
- return "BUSY";
- case AST_CDR_ANSWERED:
- return "ANSWERED";
- }
- return "UNKNOWN";
-}
-
-/*! Converts AMA flag to printable string */
-char *ast_cdr_flags2str(int flag)
-{
- switch(flag) {
- case AST_CDR_OMIT:
- return "OMIT";
- case AST_CDR_BILLING:
- return "BILLING";
- case AST_CDR_DOCUMENTATION:
- return "DOCUMENTATION";
- }
- return "Unknown";
-}
-
-int ast_cdr_setaccount(struct ast_channel *chan, const char *account)
-{
- struct ast_cdr *cdr = chan->cdr;
-
- ast_string_field_set(chan, accountcode, account);
- for ( ; cdr ; cdr = cdr->next) {
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode));
- }
- }
- return 0;
-}
-
-int ast_cdr_setamaflags(struct ast_channel *chan, const char *flag)
-{
- struct ast_cdr *cdr;
- int newflag = ast_cdr_amaflags2int(flag);
- if (newflag) {
- for (cdr = chan->cdr; cdr; cdr = cdr->next) {
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- cdr->amaflags = newflag;
- }
- }
- }
-
- return 0;
-}
-
-int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield)
-{
- struct ast_cdr *cdr = chan->cdr;
-
- for ( ; cdr ; cdr = cdr->next) {
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
- ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield));
- }
-
- return 0;
-}
-
-int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield)
-{
- struct ast_cdr *cdr = chan->cdr;
-
- for ( ; cdr ; cdr = cdr->next) {
- int len = strlen(cdr->userfield);
-
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
- ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len);
- }
-
- return 0;
-}
-
-int ast_cdr_update(struct ast_channel *c)
-{
- struct ast_cdr *cdr = c->cdr;
-
- for ( ; cdr ; cdr = cdr->next) {
- if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- set_one_cid(cdr, c);
-
- /* Copy account code et-al */
- ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
-
- /* Destination information */ /* XXX privilege macro* ? */
- ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst));
- ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext));
- }
- }
-
- return 0;
-}
-
-int ast_cdr_amaflags2int(const char *flag)
-{
- if (!strcasecmp(flag, "default"))
- return 0;
- if (!strcasecmp(flag, "omit"))
- return AST_CDR_OMIT;
- if (!strcasecmp(flag, "billing"))
- return AST_CDR_BILLING;
- if (!strcasecmp(flag, "documentation"))
- return AST_CDR_DOCUMENTATION;
- return -1;
-}
-
-static void post_cdr(struct ast_cdr *cdr)
-{
- char *chan;
- struct ast_cdr_beitem *i;
-
- for ( ; cdr ; cdr = cdr->next) {
- if (!unanswered && cdr->disposition < AST_CDR_ANSWERED && (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) {
- /* For people, who don't want to see unanswered single-channel events */
- ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
- continue;
- }
-
- chan = S_OR(cdr->channel, "<unknown>");
- check_post(cdr);
- if (option_verbose > 1 && ast_tvzero(cdr->end))
- ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' lacks end\n", chan);
- if (option_verbose > 1 && ast_tvzero(cdr->start))
- ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' lacks start\n", chan);
- ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
- if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
- continue;
- AST_LIST_LOCK(&be_list);
- AST_LIST_TRAVERSE(&be_list, i, list) {
- i->be(cdr);
- }
- AST_LIST_UNLOCK(&be_list);
- }
-}
-
-void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *_flags)
-{
- struct ast_cdr *dup;
- struct ast_flags flags = { 0 };
-
- if (_flags)
- ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
-
- for ( ; cdr ; cdr = cdr->next) {
- /* Detach if post is requested */
- if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
- if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
- ast_cdr_end(cdr);
- if ((dup = ast_cdr_dup(cdr))) {
- ast_cdr_detach(dup);
- }
- ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
- }
-
- /* clear variables */
- if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
- ast_cdr_free_vars(cdr, 0);
- }
-
- /* Reset to initial state */
- ast_clear_flag(cdr, AST_FLAGS_ALL);
- 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_NULL;
- }
- }
-}
-
-void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *_flags)
-{
- struct ast_flags flags = { 0 };
-
- if (_flags)
- ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
-
- /* Reset to initial state */
- if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) { /* But do NOT lose the NoCDR() setting */
- ast_clear_flag(cdr, AST_FLAGS_ALL);
- ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
- } else {
- ast_clear_flag(cdr, AST_FLAGS_ALL);
- }
-
- 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_NULL;
-}
-
-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;
- }
-
- return ret;
-}
-
-/*! \note Don't call without cdr_batch_lock */
-static void reset_batch(void)
-{
- batch->size = 0;
- batch->head = NULL;
- batch->tail = NULL;
-}
-
-/*! \note Don't call without cdr_batch_lock */
-static int init_batch(void)
-{
- /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
- if (!(batch = ast_malloc(sizeof(*batch))))
- return -1;
-
- reset_batch();
-
- return 0;
-}
-
-static void *do_batch_backend_process(void *data)
-{
- struct ast_cdr_batch_item *processeditem;
- struct ast_cdr_batch_item *batchitem = data;
-
- /* Push each CDR into storage mechanism(s) and free all the memory */
- while (batchitem) {
- post_cdr(batchitem->cdr);
- ast_cdr_free(batchitem->cdr);
- processeditem = batchitem;
- batchitem = batchitem->next;
- free(processeditem);
- }
-
- return NULL;
-}
-
-void ast_cdr_submit_batch(int shutdown)
-{
- struct ast_cdr_batch_item *oldbatchitems = NULL;
- pthread_attr_t attr;
- pthread_t batch_post_thread = AST_PTHREADT_NULL;
-
- /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
- if (!batch || !batch->head)
- return;
-
- /* move the old CDRs aside, and prepare a new CDR batch */
- ast_mutex_lock(&cdr_batch_lock);
- oldbatchitems = batch->head;
- reset_batch();
- ast_mutex_unlock(&cdr_batch_lock);
-
- /* if configured, spawn a new thread to post these CDRs,
- also try to save as much as possible if we are shutting down safely */
- if (batchscheduleronly || shutdown) {
- if (option_debug)
- ast_log(LOG_DEBUG, "CDR single-threaded batch processing begins now\n");
- do_batch_backend_process(oldbatchitems);
- } else {
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (ast_pthread_create_background(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) {
- ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
- do_batch_backend_process(oldbatchitems);
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n");
- }
- pthread_attr_destroy(&attr);
- }
-}
-
-static int submit_scheduled_batch(const void *data)
-{
- ast_cdr_submit_batch(0);
- /* manually reschedule from this point in time */
- cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
- /* returning zero so the scheduler does not automatically reschedule */
- return 0;
-}
-
-static void submit_unscheduled_batch(void)
-{
- /* this is okay since we are not being called from within the scheduler */
- AST_SCHED_DEL(sched, cdr_sched);
- /* schedule the submission to occur ASAP (1 ms) */
- cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
- /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
- ast_mutex_lock(&cdr_pending_lock);
- ast_cond_signal(&cdr_pending_cond);
- ast_mutex_unlock(&cdr_pending_lock);
-}
-
-void ast_cdr_detach(struct ast_cdr *cdr)
-{
- struct ast_cdr_batch_item *newtail;
- int curr;
-
- if (!cdr)
- return;
-
- /* maybe they disabled CDR stuff completely, so just drop it */
- if (!enabled) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Dropping CDR !\n");
- ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
- ast_cdr_free(cdr);
- return;
- }
-
- /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
- if (!batchmode) {
- post_cdr(cdr);
- ast_cdr_free(cdr);
- return;
- }
-
- /* otherwise, each CDR gets put into a batch list (at the end) */
- if (option_debug)
- ast_log(LOG_DEBUG, "CDR detaching from this thread\n");
-
- /* we'll need a new tail for every CDR */
- if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
- post_cdr(cdr);
- ast_cdr_free(cdr);
- return;
- }
-
- /* don't traverse a whole list (just keep track of the tail) */
- ast_mutex_lock(&cdr_batch_lock);
- if (!batch)
- init_batch();
- if (!batch->head) {
- /* new batch is empty, so point the head at the new tail */
- batch->head = newtail;
- } else {
- /* already got a batch with something in it, so just append a new tail */
- batch->tail->next = newtail;
- }
- newtail->cdr = cdr;
- batch->tail = newtail;
- curr = batch->size++;
- ast_mutex_unlock(&cdr_batch_lock);
-
- /* if we have enough stuff to post, then do it */
- if (curr >= (batchsize - 1))
- submit_unscheduled_batch();
-}
-
-static void *do_cdr(void *data)
-{
- struct timespec timeout;
- int schedms;
- int numevents = 0;
-
- for(;;) {
- struct timeval now;
- schedms = ast_sched_wait(sched);
- /* this shouldn't happen, but provide a 1 second default just in case */
- if (schedms <= 0)
- schedms = 1000;
- now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
- timeout.tv_sec = now.tv_sec;
- timeout.tv_nsec = now.tv_usec * 1000;
- /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
- ast_mutex_lock(&cdr_pending_lock);
- ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
- numevents = ast_sched_runq(sched);
- ast_mutex_unlock(&cdr_pending_lock);
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "Processed %d scheduled CDR batches from the run queue\n", numevents);
- }
-
- return NULL;
-}
-
-static int handle_cli_status(int fd, int argc, char *argv[])
-{
- struct ast_cdr_beitem *beitem=NULL;
- int cnt=0;
- long nextbatchtime=0;
-
- if (argc > 2)
- return RESULT_SHOWUSAGE;
-
- ast_cli(fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled");
- ast_cli(fd, "CDR mode: %s\n", batchmode ? "batch" : "simple");
- if (enabled) {
- ast_cli(fd, "CDR output unanswered calls: %s\n", unanswered ? "yes" : "no");
- if (batchmode) {
- if (batch)
- cnt = batch->size;
- if (cdr_sched > -1)
- nextbatchtime = ast_sched_when(sched, cdr_sched);
- ast_cli(fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled");
- ast_cli(fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads");
- ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, (cnt != 1) ? "s" : "");
- ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, (batchsize != 1) ? "s" : "");
- ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, (batchtime != 1) ? "s" : "");
- ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, (nextbatchtime != 1) ? "s" : "");
- }
- AST_LIST_LOCK(&be_list);
- AST_LIST_TRAVERSE(&be_list, beitem, list) {
- ast_cli(fd, "CDR registered backend: %s\n", beitem->name);
- }
- AST_LIST_UNLOCK(&be_list);
- }
-
- return 0;
-}
-
-static int handle_cli_submit(int fd, int argc, char *argv[])
-{
- if (argc > 2)
- return RESULT_SHOWUSAGE;
-
- submit_unscheduled_batch();
- ast_cli(fd, "Submitted CDRs to backend engines for processing. This may take a while.\n");
-
- return 0;
-}
-
-static struct ast_cli_entry cli_submit = {
- { "cdr", "submit", NULL },
- handle_cli_submit, "Posts all pending batched CDR data",
- "Usage: cdr submit\n"
- " Posts all pending batched CDR data to the configured CDR backend engine modules.\n"
-};
-
-static struct ast_cli_entry cli_status = {
- { "cdr", "status", NULL },
- handle_cli_status, "Display the CDR status",
- "Usage: cdr status\n"
- " Displays the Call Detail Record engine system status.\n"
-};
-
-static int do_reload(void)
-{
- struct ast_config *config;
- const char *enabled_value;
- const char *unanswered_value;
- const char *batched_value;
- const char *scheduleronly_value;
- const char *batchsafeshutdown_value;
- const char *size_value;
- const char *time_value;
- const char *end_before_h_value;
- int cfg_size;
- int cfg_time;
- int was_enabled;
- int was_batchmode;
- int res=0;
-
- ast_mutex_lock(&cdr_batch_lock);
-
- batchsize = BATCH_SIZE_DEFAULT;
- batchtime = BATCH_TIME_DEFAULT;
- batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT;
- batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT;
- was_enabled = enabled;
- was_batchmode = batchmode;
- enabled = 1;
- batchmode = 0;
-
- /* don't run the next scheduled CDR posting while reloading */
- AST_SCHED_DEL(sched, cdr_sched);
-
- if ((config = ast_config_load("cdr.conf"))) {
- if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
- enabled = ast_true(enabled_value);
- }
- if ((unanswered_value = ast_variable_retrieve(config, "general", "unanswered"))) {
- unanswered = ast_true(unanswered_value);
- }
- if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) {
- batchmode = ast_true(batched_value);
- }
- if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) {
- batchscheduleronly = ast_true(scheduleronly_value);
- }
- if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) {
- batchsafeshutdown = ast_true(batchsafeshutdown_value);
- }
- if ((size_value = ast_variable_retrieve(config, "general", "size"))) {
- if (sscanf(size_value, "%d", &cfg_size) < 1)
- ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value);
- else if (cfg_size < 0)
- ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size);
- else
- batchsize = cfg_size;
- }
- if ((time_value = ast_variable_retrieve(config, "general", "time"))) {
- if (sscanf(time_value, "%d", &cfg_time) < 1)
- ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value);
- else if (cfg_time < 0)
- ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time);
- else
- batchtime = cfg_time;
- }
- if ((end_before_h_value = ast_variable_retrieve(config, "general", "endbeforehexten")))
- ast_set2_flag(&ast_options, ast_true(end_before_h_value), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN);
- }
-
- if (enabled && !batchmode) {
- ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
- } else if (enabled && batchmode) {
- cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
- ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime);
- } else {
- ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n");
- }
-
- /* if this reload enabled the CDR batch mode, create the background thread
- if it does not exist */
- if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) {
- ast_cond_init(&cdr_pending_cond, NULL);
- if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) {
- ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
- AST_SCHED_DEL(sched, cdr_sched);
- } else {
- ast_cli_register(&cli_submit);
- ast_register_atexit(ast_cdr_engine_term);
- res = 0;
- }
- /* if this reload disabled the CDR and/or batch mode and there is a background thread,
- kill it */
- } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) {
- /* wake up the thread so it will exit */
- pthread_cancel(cdr_thread);
- pthread_kill(cdr_thread, SIGURG);
- pthread_join(cdr_thread, NULL);
- cdr_thread = AST_PTHREADT_NULL;
- ast_cond_destroy(&cdr_pending_cond);
- ast_cli_unregister(&cli_submit);
- ast_unregister_atexit(ast_cdr_engine_term);
- res = 0;
- /* if leaving batch mode, then post the CDRs in the batch,
- and don't reschedule, since we are stopping CDR logging */
- if (!batchmode && was_batchmode) {
- ast_cdr_engine_term();
- }
- } else {
- res = 0;
- }
-
- ast_mutex_unlock(&cdr_batch_lock);
- ast_config_destroy(config);
-
- return res;
-}
-
-int ast_cdr_engine_init(void)
-{
- int res;
-
- sched = sched_context_create();
- if (!sched) {
- ast_log(LOG_ERROR, "Unable to create schedule context.\n");
- return -1;
- }
-
- ast_cli_register(&cli_status);
-
- res = do_reload();
- if (res) {
- ast_mutex_lock(&cdr_batch_lock);
- res = init_batch();
- ast_mutex_unlock(&cdr_batch_lock);
- }
-
- return res;
-}
-
-/* \note This actually gets called a couple of times at shutdown. Once, before we start
- hanging up channels, and then again, after the channel hangup timeout expires */
-void ast_cdr_engine_term(void)
-{
- ast_cdr_submit_batch(batchsafeshutdown);
-}
-
-int ast_cdr_engine_reload(void)
-{
- return do_reload();
-}
-
diff --git a/main/channel.c b/main/channel.c
deleted file mode 100644
index 88ede049e..000000000
--- a/main/channel.c
+++ /dev/null
@@ -1,4876 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Channel Management
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <math.h>
-
-#if defined(HAVE_DAHDI)
-#include <sys/ioctl.h>
-#include "asterisk/dahdi_compat.h"
-#endif
-
-#include "asterisk/pbx.h"
-#include "asterisk/frame.h"
-#include "asterisk/sched.h"
-#include "asterisk/options.h"
-#include "asterisk/channel.h"
-#include "asterisk/audiohook.h"
-#include "asterisk/musiconhold.h"
-#include "asterisk/logger.h"
-#include "asterisk/say.h"
-#include "asterisk/file.h"
-#include "asterisk/cli.h"
-#include "asterisk/translate.h"
-#include "asterisk/manager.h"
-#include "asterisk/chanvars.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/indications.h"
-#include "asterisk/monitor.h"
-#include "asterisk/causes.h"
-#include "asterisk/callerid.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/app.h"
-#include "asterisk/transcap.h"
-#include "asterisk/devicestate.h"
-#include "asterisk/sha1.h"
-#include "asterisk/threadstorage.h"
-#include "asterisk/slinfactory.h"
-
-/* uncomment if you have problems with 'monitoring' synchronized files */
-#if 0
-#define MONITOR_CONSTANT_DELAY
-#define MONITOR_DELAY 150 * 8 /* 150 ms of MONITORING DELAY */
-#endif
-
-/*! Prevent new channel allocation if shutting down. */
-static int shutting_down;
-
-static int uniqueint;
-
-unsigned long global_fin, global_fout;
-
-AST_THREADSTORAGE(state2str_threadbuf, state2str_threadbuf_init);
-#define STATE2STR_BUFSIZE 32
-
-/*! Default amount of time to use when emulating a digit as a begin and end
- * 100ms */
-#define AST_DEFAULT_EMULATE_DTMF_DURATION 100
-
-/*! Minimum allowed digit length - 80ms */
-#define AST_MIN_DTMF_DURATION 80
-
-/*! Minimum amount of time between the end of the last digit and the beginning
- * of a new one - 45ms */
-#define AST_MIN_DTMF_GAP 45
-
-struct chanlist {
- const struct ast_channel_tech *tech;
- AST_LIST_ENTRY(chanlist) list;
-};
-
-/*! the list of registered channel types */
-static AST_LIST_HEAD_NOLOCK_STATIC(backends, chanlist);
-
-/*! the list of channels we have. Note that the lock for this list is used for
- both the channels list and the backends list. */
-static AST_LIST_HEAD_STATIC(channels, ast_channel);
-
-/*! map AST_CAUSE's to readable string representations */
-const struct ast_cause {
- int cause;
- const char *name;
- const char *desc;
-} causes[] = {
- { AST_CAUSE_UNALLOCATED, "UNALLOCATED", "Unallocated (unassigned) number" },
- { AST_CAUSE_NO_ROUTE_TRANSIT_NET, "NO_ROUTE_TRANSIT_NET", "No route to specified transmit network" },
- { AST_CAUSE_NO_ROUTE_DESTINATION, "NO_ROUTE_DESTINATION", "No route to destination" },
- { AST_CAUSE_CHANNEL_UNACCEPTABLE, "CHANNEL_UNACCEPTABLE", "Channel unacceptable" },
- { AST_CAUSE_CALL_AWARDED_DELIVERED, "CALL_AWARDED_DELIVERED", "Call awarded and being delivered in an established channel" },
- { AST_CAUSE_NORMAL_CLEARING, "NORMAL_CLEARING", "Normal Clearing" },
- { AST_CAUSE_USER_BUSY, "USER_BUSY", "User busy" },
- { AST_CAUSE_NO_USER_RESPONSE, "NO_USER_RESPONSE", "No user responding" },
- { AST_CAUSE_NO_ANSWER, "NO_ANSWER", "User alerting, no answer" },
- { AST_CAUSE_CALL_REJECTED, "CALL_REJECTED", "Call Rejected" },
- { AST_CAUSE_NUMBER_CHANGED, "NUMBER_CHANGED", "Number changed" },
- { AST_CAUSE_DESTINATION_OUT_OF_ORDER, "DESTINATION_OUT_OF_ORDER", "Destination out of order" },
- { AST_CAUSE_INVALID_NUMBER_FORMAT, "INVALID_NUMBER_FORMAT", "Invalid number format" },
- { AST_CAUSE_FACILITY_REJECTED, "FACILITY_REJECTED", "Facility rejected" },
- { AST_CAUSE_RESPONSE_TO_STATUS_ENQUIRY, "RESPONSE_TO_STATUS_ENQUIRY", "Response to STATus ENQuiry" },
- { AST_CAUSE_NORMAL_UNSPECIFIED, "NORMAL_UNSPECIFIED", "Normal, unspecified" },
- { AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, "NORMAL_CIRCUIT_CONGESTION", "Circuit/channel congestion" },
- { AST_CAUSE_NETWORK_OUT_OF_ORDER, "NETWORK_OUT_OF_ORDER", "Network out of order" },
- { AST_CAUSE_NORMAL_TEMPORARY_FAILURE, "NORMAL_TEMPORARY_FAILURE", "Temporary failure" },
- { AST_CAUSE_SWITCH_CONGESTION, "SWITCH_CONGESTION", "Switching equipment congestion" },
- { AST_CAUSE_ACCESS_INFO_DISCARDED, "ACCESS_INFO_DISCARDED", "Access information discarded" },
- { AST_CAUSE_REQUESTED_CHAN_UNAVAIL, "REQUESTED_CHAN_UNAVAIL", "Requested channel not available" },
- { AST_CAUSE_PRE_EMPTED, "PRE_EMPTED", "Pre-empted" },
- { AST_CAUSE_FACILITY_NOT_SUBSCRIBED, "FACILITY_NOT_SUBSCRIBED", "Facility not subscribed" },
- { AST_CAUSE_OUTGOING_CALL_BARRED, "OUTGOING_CALL_BARRED", "Outgoing call barred" },
- { AST_CAUSE_INCOMING_CALL_BARRED, "INCOMING_CALL_BARRED", "Incoming call barred" },
- { AST_CAUSE_BEARERCAPABILITY_NOTAUTH, "BEARERCAPABILITY_NOTAUTH", "Bearer capability not authorized" },
- { AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, "BEARERCAPABILITY_NOTAVAIL", "Bearer capability not available" },
- { AST_CAUSE_BEARERCAPABILITY_NOTIMPL, "BEARERCAPABILITY_NOTIMPL", "Bearer capability not implemented" },
- { AST_CAUSE_CHAN_NOT_IMPLEMENTED, "CHAN_NOT_IMPLEMENTED", "Channel not implemented" },
- { AST_CAUSE_FACILITY_NOT_IMPLEMENTED, "FACILITY_NOT_IMPLEMENTED", "Facility not implemented" },
- { AST_CAUSE_INVALID_CALL_REFERENCE, "INVALID_CALL_REFERENCE", "Invalid call reference value" },
- { AST_CAUSE_INCOMPATIBLE_DESTINATION, "INCOMPATIBLE_DESTINATION", "Incompatible destination" },
- { AST_CAUSE_INVALID_MSG_UNSPECIFIED, "INVALID_MSG_UNSPECIFIED", "Invalid message unspecified" },
- { AST_CAUSE_MANDATORY_IE_MISSING, "MANDATORY_IE_MISSING", "Mandatory information element is missing" },
- { AST_CAUSE_MESSAGE_TYPE_NONEXIST, "MESSAGE_TYPE_NONEXIST", "Message type nonexist." },
- { AST_CAUSE_WRONG_MESSAGE, "WRONG_MESSAGE", "Wrong message" },
- { AST_CAUSE_IE_NONEXIST, "IE_NONEXIST", "Info. element nonexist or not implemented" },
- { AST_CAUSE_INVALID_IE_CONTENTS, "INVALID_IE_CONTENTS", "Invalid information element contents" },
- { AST_CAUSE_WRONG_CALL_STATE, "WRONG_CALL_STATE", "Message not compatible with call state" },
- { AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, "RECOVERY_ON_TIMER_EXPIRE", "Recover on timer expiry" },
- { AST_CAUSE_MANDATORY_IE_LENGTH_ERROR, "MANDATORY_IE_LENGTH_ERROR", "Mandatory IE length error" },
- { AST_CAUSE_PROTOCOL_ERROR, "PROTOCOL_ERROR", "Protocol error, unspecified" },
- { AST_CAUSE_INTERWORKING, "INTERWORKING", "Interworking, unspecified" },
-};
-
-struct ast_variable *ast_channeltype_list(void)
-{
- struct chanlist *cl;
- struct ast_variable *var=NULL, *prev = NULL;
- AST_LIST_TRAVERSE(&backends, cl, list) {
- if (prev) {
- if ((prev->next = ast_variable_new(cl->tech->type, cl->tech->description)))
- prev = prev->next;
- } else {
- var = ast_variable_new(cl->tech->type, cl->tech->description);
- prev = var;
- }
- }
- return var;
-}
-
-static int show_channeltypes(int fd, int argc, char *argv[])
-{
-#define FORMAT "%-10.10s %-40.40s %-12.12s %-12.12s %-12.12s\n"
- struct chanlist *cl;
- int count_chan = 0;
-
- ast_cli(fd, FORMAT, "Type", "Description", "Devicestate", "Indications", "Transfer");
- ast_cli(fd, FORMAT, "----------", "-----------", "-----------", "-----------", "--------");
- if (AST_LIST_LOCK(&channels)) {
- ast_log(LOG_WARNING, "Unable to lock channel list\n");
- return -1;
- }
- AST_LIST_TRAVERSE(&backends, cl, list) {
- ast_cli(fd, FORMAT, cl->tech->type, cl->tech->description,
- (cl->tech->devicestate) ? "yes" : "no",
- (cl->tech->indicate) ? "yes" : "no",
- (cl->tech->transfer) ? "yes" : "no");
- count_chan++;
- }
- AST_LIST_UNLOCK(&channels);
- ast_cli(fd, "----------\n%d channel drivers registered.\n", count_chan);
- return RESULT_SUCCESS;
-
-#undef FORMAT
-
-}
-
-static int show_channeltype_deprecated(int fd, int argc, char *argv[])
-{
- struct chanlist *cl = NULL;
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
-
- if (AST_LIST_LOCK(&channels)) {
- ast_log(LOG_WARNING, "Unable to lock channel list\n");
- return RESULT_FAILURE;
- }
-
- AST_LIST_TRAVERSE(&backends, cl, list) {
- if (!strncasecmp(cl->tech->type, argv[2], strlen(cl->tech->type))) {
- break;
- }
- }
-
-
- if (!cl) {
- ast_cli(fd, "\n%s is not a registered channel driver.\n", argv[2]);
- AST_LIST_UNLOCK(&channels);
- return RESULT_FAILURE;
- }
-
- ast_cli(fd,
- "-- Info about channel driver: %s --\n"
- " Device State: %s\n"
- " Indication: %s\n"
- " Transfer : %s\n"
- " Capabilities: %d\n"
- " Digit Begin: %s\n"
- " Digit End: %s\n"
- " Send HTML : %s\n"
- " Image Support: %s\n"
- " Text Support: %s\n",
- cl->tech->type,
- (cl->tech->devicestate) ? "yes" : "no",
- (cl->tech->indicate) ? "yes" : "no",
- (cl->tech->transfer) ? "yes" : "no",
- (cl->tech->capabilities) ? cl->tech->capabilities : -1,
- (cl->tech->send_digit_begin) ? "yes" : "no",
- (cl->tech->send_digit_end) ? "yes" : "no",
- (cl->tech->send_html) ? "yes" : "no",
- (cl->tech->send_image) ? "yes" : "no",
- (cl->tech->send_text) ? "yes" : "no"
-
- );
-
- AST_LIST_UNLOCK(&channels);
- return RESULT_SUCCESS;
-}
-
-static int show_channeltype(int fd, int argc, char *argv[])
-{
- struct chanlist *cl = NULL;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- if (AST_LIST_LOCK(&channels)) {
- ast_log(LOG_WARNING, "Unable to lock channel list\n");
- return RESULT_FAILURE;
- }
-
- AST_LIST_TRAVERSE(&backends, cl, list) {
- if (!strncasecmp(cl->tech->type, argv[3], strlen(cl->tech->type))) {
- break;
- }
- }
-
-
- if (!cl) {
- ast_cli(fd, "\n%s is not a registered channel driver.\n", argv[3]);
- AST_LIST_UNLOCK(&channels);
- return RESULT_FAILURE;
- }
-
- ast_cli(fd,
- "-- Info about channel driver: %s --\n"
- " Device State: %s\n"
- " Indication: %s\n"
- " Transfer : %s\n"
- " Capabilities: %d\n"
- " Digit Begin: %s\n"
- " Digit End: %s\n"
- " Send HTML : %s\n"
- " Image Support: %s\n"
- " Text Support: %s\n",
- cl->tech->type,
- (cl->tech->devicestate) ? "yes" : "no",
- (cl->tech->indicate) ? "yes" : "no",
- (cl->tech->transfer) ? "yes" : "no",
- (cl->tech->capabilities) ? cl->tech->capabilities : -1,
- (cl->tech->send_digit_begin) ? "yes" : "no",
- (cl->tech->send_digit_end) ? "yes" : "no",
- (cl->tech->send_html) ? "yes" : "no",
- (cl->tech->send_image) ? "yes" : "no",
- (cl->tech->send_text) ? "yes" : "no"
-
- );
-
- AST_LIST_UNLOCK(&channels);
- return RESULT_SUCCESS;
-}
-
-static char *complete_channeltypes_deprecated(const char *line, const char *word, int pos, int state)
-{
- struct chanlist *cl;
- int which = 0;
- int wordlen;
- char *ret = NULL;
-
- if (pos != 2)
- return NULL;
-
- wordlen = strlen(word);
-
- AST_LIST_TRAVERSE(&backends, cl, list) {
- if (!strncasecmp(word, cl->tech->type, wordlen) && ++which > state) {
- ret = strdup(cl->tech->type);
- break;
- }
- }
-
- return ret;
-}
-
-static char *complete_channeltypes(const char *line, const char *word, int pos, int state)
-{
- struct chanlist *cl;
- int which = 0;
- int wordlen;
- char *ret = NULL;
-
- if (pos != 3)
- return NULL;
-
- wordlen = strlen(word);
-
- AST_LIST_TRAVERSE(&backends, cl, list) {
- if (!strncasecmp(word, cl->tech->type, wordlen) && ++which > state) {
- ret = strdup(cl->tech->type);
- break;
- }
- }
-
- return ret;
-}
-
-static char show_channeltypes_usage[] =
-"Usage: core show channeltypes\n"
-" Lists available channel types registered in your Asterisk server.\n";
-
-static char show_channeltype_usage[] =
-"Usage: core show channeltype <name>\n"
-" Show details about the specified channel type, <name>.\n";
-
-static struct ast_cli_entry cli_show_channeltypes_deprecated = {
- { "show", "channeltypes", NULL },
- show_channeltypes, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_channeltype_deprecated = {
- { "show", "channeltype", NULL },
- show_channeltype_deprecated, NULL,
- NULL, complete_channeltypes_deprecated };
-
-static struct ast_cli_entry cli_channel[] = {
- { { "core", "show", "channeltypes", NULL },
- show_channeltypes, "List available channel types",
- show_channeltypes_usage, NULL, &cli_show_channeltypes_deprecated },
-
- { { "core", "show", "channeltype", NULL },
- show_channeltype, "Give more details on that channel type",
- show_channeltype_usage, complete_channeltypes, &cli_show_channeltype_deprecated },
-};
-
-/*! \brief Checks to see if a channel is needing hang up */
-int ast_check_hangup(struct ast_channel *chan)
-{
- if (chan->_softhangup) /* yes if soft hangup flag set */
- return 1;
- if (!chan->tech_pvt) /* yes if no technology private data */
- return 1;
- if (!chan->whentohangup) /* no if no hangup scheduled */
- return 0;
- if (chan->whentohangup > time(NULL)) /* no if hangup time has not come yet. */
- return 0;
- chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; /* record event */
- return 1;
-}
-
-static int ast_check_hangup_locked(struct ast_channel *chan)
-{
- int res;
- ast_channel_lock(chan);
- res = ast_check_hangup(chan);
- ast_channel_unlock(chan);
- return res;
-}
-
-/*! \brief printf the string into a correctly sized mallocd buffer, and return the buffer */
-char *ast_safe_string_alloc(const char *fmt, ...)
-{
- char *b2, buf[1];
- int len;
- va_list args;
-
- va_start(args, fmt);
- len = vsnprintf(buf, 1, fmt, args);
- va_end(args);
-
- if (!(b2 = ast_malloc(len + 1)))
- return NULL;
-
- va_start(args, fmt);
- vsnprintf(b2, len + 1, fmt, args);
- va_end(args);
-
- return b2;
-}
-
-/*! \brief Initiate system shutdown */
-void ast_begin_shutdown(int hangup)
-{
- struct ast_channel *c;
- shutting_down = 1;
- if (hangup) {
- AST_LIST_LOCK(&channels);
- AST_LIST_TRAVERSE(&channels, c, chan_list)
- ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
- AST_LIST_UNLOCK(&channels);
- }
-}
-
-/*! \brief returns number of active/allocated channels */
-int ast_active_channels(void)
-{
- struct ast_channel *c;
- int cnt = 0;
- AST_LIST_LOCK(&channels);
- AST_LIST_TRAVERSE(&channels, c, chan_list)
- cnt++;
- AST_LIST_UNLOCK(&channels);
- return cnt;
-}
-
-/*! \brief Cancel a shutdown in progress */
-void ast_cancel_shutdown(void)
-{
- shutting_down = 0;
-}
-
-/*! \brief Returns non-zero if Asterisk is being shut down */
-int ast_shutting_down(void)
-{
- return shutting_down;
-}
-
-/*! \brief Set when to hangup channel */
-void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
-{
- chan->whentohangup = offset ? time(NULL) + offset : 0;
- ast_queue_frame(chan, &ast_null_frame);
- return;
-}
-
-/*! \brief Compare a offset with when to hangup channel */
-int ast_channel_cmpwhentohangup(struct ast_channel *chan, time_t offset)
-{
- time_t whentohangup;
-
- if (chan->whentohangup == 0) {
- return (offset == 0) ? 0 : -1;
- } else {
- if (offset == 0) /* XXX why is this special ? */
- return (1);
- else {
- whentohangup = offset + time (NULL);
- if (chan->whentohangup < whentohangup)
- return (1);
- else if (chan->whentohangup == whentohangup)
- return (0);
- else
- return (-1);
- }
- }
-}
-
-/*! \brief Register a new telephony channel in Asterisk */
-int ast_channel_register(const struct ast_channel_tech *tech)
-{
- struct chanlist *chan;
-
- AST_LIST_LOCK(&channels);
-
- AST_LIST_TRAVERSE(&backends, chan, list) {
- if (!strcasecmp(tech->type, chan->tech->type)) {
- ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", tech->type);
- AST_LIST_UNLOCK(&channels);
- return -1;
- }
- }
-
- if (!(chan = ast_calloc(1, sizeof(*chan)))) {
- AST_LIST_UNLOCK(&channels);
- return -1;
- }
- chan->tech = tech;
- AST_LIST_INSERT_HEAD(&backends, chan, list);
-
- if (option_debug)
- ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->tech->type, chan->tech->description);
-
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->tech->type,
- chan->tech->description);
-
- AST_LIST_UNLOCK(&channels);
- return 0;
-}
-
-void ast_channel_unregister(const struct ast_channel_tech *tech)
-{
- struct chanlist *chan;
-
- if (option_debug)
- ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", tech->type);
-
- AST_LIST_LOCK(&channels);
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&backends, chan, list) {
- if (chan->tech == tech) {
- AST_LIST_REMOVE_CURRENT(&backends, list);
- free(chan);
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", tech->type);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- AST_LIST_UNLOCK(&channels);
-}
-
-const struct ast_channel_tech *ast_get_channel_tech(const char *name)
-{
- struct chanlist *chanls;
- const struct ast_channel_tech *ret = NULL;
-
- if (AST_LIST_LOCK(&channels)) {
- ast_log(LOG_WARNING, "Unable to lock channel tech list\n");
- return NULL;
- }
-
- AST_LIST_TRAVERSE(&backends, chanls, list) {
- if (!strcasecmp(name, chanls->tech->type)) {
- ret = chanls->tech;
- break;
- }
- }
-
- AST_LIST_UNLOCK(&channels);
-
- return ret;
-}
-
-/*! \brief Gives the string form of a given hangup cause */
-const char *ast_cause2str(int cause)
-{
- int x;
-
- for (x=0; x < sizeof(causes) / sizeof(causes[0]); x++) {
- if (causes[x].cause == cause)
- return causes[x].desc;
- }
-
- return "Unknown";
-}
-
-/*! \brief Convert a symbolic hangup cause to number */
-int ast_str2cause(const char *name)
-{
- int x;
-
- for (x = 0; x < sizeof(causes) / sizeof(causes[0]); x++)
- if (strncasecmp(causes[x].name, name, strlen(causes[x].name)) == 0)
- return causes[x].cause;
-
- return -1;
-}
-
-/*! \brief Gives the string form of a given channel state */
-char *ast_state2str(enum ast_channel_state state)
-{
- char *buf;
-
- switch(state) {
- case AST_STATE_DOWN:
- return "Down";
- case AST_STATE_RESERVED:
- return "Rsrvd";
- case AST_STATE_OFFHOOK:
- return "OffHook";
- case AST_STATE_DIALING:
- return "Dialing";
- case AST_STATE_RING:
- return "Ring";
- case AST_STATE_RINGING:
- return "Ringing";
- case AST_STATE_UP:
- return "Up";
- case AST_STATE_BUSY:
- return "Busy";
- case AST_STATE_DIALING_OFFHOOK:
- return "Dialing Offhook";
- case AST_STATE_PRERING:
- return "Pre-ring";
- default:
- if (!(buf = ast_threadstorage_get(&state2str_threadbuf, STATE2STR_BUFSIZE)))
- return "Unknown";
- snprintf(buf, STATE2STR_BUFSIZE, "Unknown (%d)", state);
- return buf;
- }
-}
-
-/*! \brief Gives the string form of a given transfer capability */
-char *ast_transfercapability2str(int transfercapability)
-{
- switch(transfercapability) {
- case AST_TRANS_CAP_SPEECH:
- return "SPEECH";
- case AST_TRANS_CAP_DIGITAL:
- return "DIGITAL";
- case AST_TRANS_CAP_RESTRICTED_DIGITAL:
- return "RESTRICTED_DIGITAL";
- case AST_TRANS_CAP_3_1K_AUDIO:
- return "3K1AUDIO";
- case AST_TRANS_CAP_DIGITAL_W_TONES:
- return "DIGITAL_W_TONES";
- case AST_TRANS_CAP_VIDEO:
- return "VIDEO";
- default:
- return "UNKNOWN";
- }
-}
-
-/*! \brief Pick the best audio codec */
-int ast_best_codec(int fmts)
-{
- /* This just our opinion, expressed in code. We are asked to choose
- the best codec to use, given no information */
- int x;
- static int prefs[] =
- {
- /*! Okay, ulaw is used by all telephony equipment, so start with it */
- AST_FORMAT_ULAW,
- /*! Unless of course, you're a silly European, so then prefer ALAW */
- AST_FORMAT_ALAW,
- /*! G.722 is better then all below, but not as common as the above... so give ulaw and alaw priority */
- AST_FORMAT_G722,
- /*! Okay, well, signed linear is easy to translate into other stuff */
- AST_FORMAT_SLINEAR,
- /*! G.726 is standard ADPCM, in RFC3551 packing order */
- AST_FORMAT_G726,
- /*! G.726 is standard ADPCM, in AAL2 packing order */
- AST_FORMAT_G726_AAL2,
- /*! ADPCM has great sound quality and is still pretty easy to translate */
- AST_FORMAT_ADPCM,
- /*! Okay, we're down to vocoders now, so pick GSM because it's small and easier to
- translate and sounds pretty good */
- AST_FORMAT_GSM,
- /*! iLBC is not too bad */
- AST_FORMAT_ILBC,
- /*! Speex is free, but computationally more expensive than GSM */
- AST_FORMAT_SPEEX,
- /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough
- to use it */
- AST_FORMAT_LPC10,
- /*! G.729a is faster than 723 and slightly less expensive */
- AST_FORMAT_G729A,
- /*! Down to G.723.1 which is proprietary but at least designed for voice */
- AST_FORMAT_G723_1,
- };
-
- /* Strip out video */
- fmts &= AST_FORMAT_AUDIO_MASK;
-
- /* Find the first preferred codec in the format given */
- for (x=0; x < (sizeof(prefs) / sizeof(prefs[0]) ); x++)
- if (fmts & prefs[x])
- return prefs[x];
- ast_log(LOG_WARNING, "Don't know any of 0x%x formats\n", fmts);
- return 0;
-}
-
-static const struct ast_channel_tech null_tech = {
- .type = "NULL",
- .description = "Null channel (should not see this)",
-};
-
-/*! \brief Create a new channel structure */
-struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt, ...)
-{
- struct ast_channel *tmp;
- int x;
- int flags;
- struct varshead *headp;
- va_list ap1, ap2;
-
- /* If shutting down, don't allocate any new channels */
- if (shutting_down) {
- ast_log(LOG_WARNING, "Channel allocation failed: Refusing due to active shutdown\n");
- return NULL;
- }
-
- if (!(tmp = ast_calloc(1, sizeof(*tmp))))
- return NULL;
-
- if (!(tmp->sched = sched_context_create())) {
- ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n");
- free(tmp);
- return NULL;
- }
-
- if ((ast_string_field_init(tmp, 128))) {
- sched_context_destroy(tmp->sched);
- free(tmp);
- return NULL;
- }
-
- /* Don't bother initializing the last two FD here, because they
- will *always* be set just a few lines down (AST_TIMING_FD,
- AST_ALERT_FD). */
- for (x = 0; x < AST_MAX_FDS - 2; x++)
- tmp->fds[x] = -1;
-
-#ifdef HAVE_DAHDI
-
- tmp->timingfd = open(DAHDI_FILE_TIMER, O_RDWR);
-
- if (tmp->timingfd > -1) {
- /* Check if timing interface supports new
- ping/pong scheme */
- flags = 1;
- if (!ioctl(tmp->timingfd, DAHDI_TIMERPONG, &flags))
- needqueue = 0;
- }
-#else
- tmp->timingfd = -1;
-#endif
-
- if (needqueue) {
- if (pipe(tmp->alertpipe)) {
- ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe!\n");
-alertpipe_failed:
-#ifdef HAVE_DAHDI
- if (tmp->timingfd > -1)
- close(tmp->timingfd);
-#endif
- sched_context_destroy(tmp->sched);
- ast_string_field_free_memory(tmp);
- free(tmp);
- return NULL;
- } else {
- flags = fcntl(tmp->alertpipe[0], F_GETFL);
- if (fcntl(tmp->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
- ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
- close(tmp->alertpipe[0]);
- close(tmp->alertpipe[1]);
- goto alertpipe_failed;
- }
- flags = fcntl(tmp->alertpipe[1], F_GETFL);
- if (fcntl(tmp->alertpipe[1], F_SETFL, flags | O_NONBLOCK) < 0) {
- ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
- close(tmp->alertpipe[0]);
- close(tmp->alertpipe[1]);
- goto alertpipe_failed;
- }
- }
- } else /* Make sure we've got it done right if they don't */
- tmp->alertpipe[0] = tmp->alertpipe[1] = -1;
-
- /* Always watch the alertpipe */
- tmp->fds[AST_ALERT_FD] = tmp->alertpipe[0];
- /* And timing pipe */
- tmp->fds[AST_TIMING_FD] = tmp->timingfd;
- ast_string_field_set(tmp, name, "**Unknown**");
-
- /* Initial state */
- tmp->_state = state;
-
- tmp->streamid = -1;
-
- tmp->fin = global_fin;
- tmp->fout = global_fout;
-
- if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
- ast_string_field_build(tmp, uniqueid, "%li.%d", (long) time(NULL),
- ast_atomic_fetchadd_int(&uniqueint, 1));
- } else {
- ast_string_field_build(tmp, uniqueid, "%s-%li.%d", ast_config_AST_SYSTEM_NAME,
- (long) time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
- }
-
- tmp->cid.cid_name = ast_strdup(cid_name);
- tmp->cid.cid_num = ast_strdup(cid_num);
-
- if (!ast_strlen_zero(name_fmt)) {
- /* Almost every channel is calling this function, and setting the name via the ast_string_field_build() call.
- * And they all use slightly different formats for their name string.
- * This means, to set the name here, we have to accept variable args, and call the string_field_build from here.
- * This means, that the stringfields must have a routine that takes the va_lists directly, and
- * uses them to build the string, instead of forming the va_lists internally from the vararg ... list.
- * This new function was written so this can be accomplished.
- */
- va_start(ap1, name_fmt);
- va_start(ap2, name_fmt);
- ast_string_field_build_va(tmp, name, name_fmt, ap1, ap2);
- va_end(ap1);
- va_end(ap2);
- }
-
- /* Reminder for the future: under what conditions do we NOT want to track cdrs on channels? */
-
- /* These 4 variables need to be set up for the cdr_init() to work right */
- if (amaflag)
- tmp->amaflags = amaflag;
- else
- tmp->amaflags = ast_default_amaflags;
-
- if (!ast_strlen_zero(acctcode))
- ast_string_field_set(tmp, accountcode, acctcode);
- else
- ast_string_field_set(tmp, accountcode, ast_default_accountcode);
-
- if (!ast_strlen_zero(context))
- ast_copy_string(tmp->context, context, sizeof(tmp->context));
- else
- strcpy(tmp->context, "default");
-
- if (!ast_strlen_zero(exten))
- ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
- else
- strcpy(tmp->exten, "s");
-
- tmp->priority = 1;
-
- tmp->cdr = ast_cdr_alloc();
- ast_cdr_init(tmp->cdr, tmp);
- ast_cdr_start(tmp->cdr);
-
- headp = &tmp->varshead;
- AST_LIST_HEAD_INIT_NOLOCK(headp);
-
- ast_mutex_init(&tmp->lock);
-
- AST_LIST_HEAD_INIT_NOLOCK(&tmp->datastores);
-
- ast_string_field_set(tmp, language, defaultlanguage);
-
- tmp->tech = &null_tech;
-
- AST_LIST_LOCK(&channels);
- AST_LIST_INSERT_HEAD(&channels, tmp, chan_list);
- AST_LIST_UNLOCK(&channels);
-
- /*\!note
- * and now, since the channel structure is built, and has its name, let's
- * call the manager event generator with this Newchannel event. This is the
- * proper and correct place to make this call, but you sure do have to pass
- * a lot of data into this func to do it here!
- */
- if (!ast_strlen_zero(name_fmt)) {
- manager_event(EVENT_FLAG_CALL, "Newchannel",
- "Channel: %s\r\n"
- "State: %s\r\n"
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "Uniqueid: %s\r\n",
- tmp->name, ast_state2str(state),
- S_OR(cid_num, "<unknown>"),
- S_OR(cid_name, "<unknown>"),
- tmp->uniqueid);
- }
-
- return tmp;
-}
-
-/*! \brief Queue an outgoing media frame */
-static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int head)
-{
- struct ast_frame *f;
- struct ast_frame *cur;
- int blah = 1;
- int qlen = 0;
-
- /* Build us a copy and free the original one */
- if (!(f = ast_frdup(fin))) {
- return -1;
- }
-
- ast_channel_lock(chan);
-
- /* See if the last frame on the queue is a hangup, if so don't queue anything */
- if ((cur = AST_LIST_LAST(&chan->readq)) && (cur->frametype == AST_FRAME_CONTROL) && (cur->subclass == AST_CONTROL_HANGUP)) {
- ast_frfree(f);
- ast_channel_unlock(chan);
- return 0;
- }
-
- /* Count how many frames exist on the queue */
- AST_LIST_TRAVERSE(&chan->readq, cur, frame_list) {
- qlen++;
- }
-
- /* Allow up to 96 voice frames outstanding, and up to 128 total frames */
- if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen > 128)) {
- if (fin->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
- ast_assert(fin->frametype == AST_FRAME_VOICE);
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name);
- ast_frfree(f);
- ast_channel_unlock(chan);
- return 0;
- }
- }
-
- if (head) {
- AST_LIST_INSERT_HEAD(&chan->readq, f, frame_list);
- } else {
- AST_LIST_INSERT_TAIL(&chan->readq, f, frame_list);
- }
-
- if (chan->alertpipe[1] > -1) {
- if (write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) {
- ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
- chan->name, f->frametype, f->subclass, qlen, strerror(errno));
- }
-#ifdef HAVE_DAHDI
- } else if (chan->timingfd > -1) {
- ioctl(chan->timingfd, DAHDI_TIMERPING, &blah);
-#endif
- } else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) {
- pthread_kill(chan->blocker, SIGURG);
- }
-
- ast_channel_unlock(chan);
-
- return 0;
-}
-
-int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin)
-{
- return __ast_queue_frame(chan, fin, 0);
-}
-
-int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *fin)
-{
- return __ast_queue_frame(chan, fin, 1);
-}
-
-/*! \brief Queue a hangup frame for channel */
-int ast_queue_hangup(struct ast_channel *chan)
-{
- struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
- /* Yeah, let's not change a lock-critical value without locking */
- if (!ast_channel_trylock(chan)) {
- chan->_softhangup |= AST_SOFTHANGUP_DEV;
- ast_channel_unlock(chan);
- }
- return ast_queue_frame(chan, &f);
-}
-
-/*! \brief Queue a control frame */
-int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
-{
- struct ast_frame f = { AST_FRAME_CONTROL, };
-
- f.subclass = control;
-
- return ast_queue_frame(chan, &f);
-}
-
-/*! \brief Queue a control frame with payload */
-int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control,
- const void *data, size_t datalen)
-{
- struct ast_frame f = { AST_FRAME_CONTROL, };
-
- f.subclass = control;
- f.data = (void *) data;
- f.datalen = datalen;
-
- return ast_queue_frame(chan, &f);
-}
-
-/*! \brief Set defer DTMF flag on channel */
-int ast_channel_defer_dtmf(struct ast_channel *chan)
-{
- int pre = 0;
-
- if (chan) {
- pre = ast_test_flag(chan, AST_FLAG_DEFER_DTMF);
- ast_set_flag(chan, AST_FLAG_DEFER_DTMF);
- }
- return pre;
-}
-
-/*! \brief Unset defer DTMF flag on channel */
-void ast_channel_undefer_dtmf(struct ast_channel *chan)
-{
- if (chan)
- ast_clear_flag(chan, AST_FLAG_DEFER_DTMF);
-}
-
-/*!
- * \brief Helper function to find channels.
- *
- * It supports these modes:
- *
- * prev != NULL : get channel next in list after prev
- * name != NULL : get channel with matching name
- * name != NULL && namelen != 0 : get channel whose name starts with prefix
- * exten != NULL : get channel whose exten or macroexten matches
- * context != NULL && exten != NULL : get channel whose context or macrocontext
- *
- * It returns with the channel's lock held. If getting the individual lock fails,
- * unlock and retry quickly up to 10 times, then give up.
- *
- * \note XXX Note that this code has cost O(N) because of the need to verify
- * that the object is still on the global list.
- *
- * \note XXX also note that accessing fields (e.g. c->name in ast_log())
- * can only be done with the lock held or someone could delete the
- * object while we work on it. This causes some ugliness in the code.
- * Note that removing the first ast_log() may be harmful, as it would
- * shorten the retry period and possibly cause failures.
- * We should definitely go for a better scheme that is deadlock-free.
- */
-static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
- const char *name, const int namelen,
- const char *context, const char *exten)
-{
- const char *msg = prev ? "deadlock" : "initial deadlock";
- int retries;
- struct ast_channel *c;
- const struct ast_channel *_prev = prev;
-
- for (retries = 0; retries < 200; retries++) {
- int done;
- /* Reset prev on each retry. See note below for the reason. */
- prev = _prev;
- AST_LIST_LOCK(&channels);
- AST_LIST_TRAVERSE(&channels, c, chan_list) {
- if (prev) { /* look for last item, first, before any evaluation */
- if (c != prev) /* not this one */
- continue;
- /* found, prepare to return c->next */
- if ((c = AST_LIST_NEXT(c, chan_list)) == NULL) break;
- /*!\note
- * We're done searching through the list for the previous item.
- * Any item after this point, we want to evaluate for a match.
- * If we didn't set prev to NULL here, then we would only
- * return matches for the first matching item (since the above
- * "if (c != prev)" would not permit any other potential
- * matches to reach the additional matching logic, below).
- * Instead, it would just iterate until it once again found the
- * original match, then iterate down to the end of the list and
- * quit.
- */
- prev = NULL;
- }
- if (name) { /* want match by name */
- if ((!namelen && strcasecmp(c->name, name)) ||
- (namelen && strncasecmp(c->name, name, namelen)))
- continue; /* name match failed */
- } else if (exten) {
- if (context && strcasecmp(c->context, context) &&
- strcasecmp(c->macrocontext, context))
- continue; /* context match failed */
- if (strcasecmp(c->exten, exten) &&
- strcasecmp(c->macroexten, exten))
- continue; /* exten match failed */
- }
- /* if we get here, c points to the desired record */
- break;
- }
- /* exit if chan not found or mutex acquired successfully */
- /* this is slightly unsafe, as we _should_ hold the lock to access c->name */
- done = c == NULL || ast_channel_trylock(c) == 0;
- if (!done) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Avoiding %s for channel '%p'\n", msg, c);
- if (retries == 199) {
- /* We are about to fail due to a deadlock, so report this
- * while we still have the list lock.
- */
- if (option_debug)
- ast_log(LOG_DEBUG, "Failure, could not lock '%p' after %d retries!\n", c, retries);
- /* As we have deadlocked, we will skip this channel and
- * see if there is another match.
- * NOTE: No point doing this for a full-name match,
- * as there can be no more matches.
- */
- if (!(name && !namelen)) {
- prev = c;
- retries = -1;
- }
- }
- }
- AST_LIST_UNLOCK(&channels);
- if (done)
- return c;
- /* If we reach this point we basically tried to lock a channel and failed. Instead of
- * starting from the beginning of the list we can restore our saved pointer to the previous
- * channel and start from there.
- */
- prev = _prev;
- usleep(1); /* give other threads a chance before retrying */
- }
-
- return NULL;
-}
-
-/*! \brief Browse channels in use */
-struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
-{
- return channel_find_locked(prev, NULL, 0, NULL, NULL);
-}
-
-/*! \brief Get channel by name and lock it */
-struct ast_channel *ast_get_channel_by_name_locked(const char *name)
-{
- return channel_find_locked(NULL, name, 0, NULL, NULL);
-}
-
-/*! \brief Get channel by name prefix and lock it */
-struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
-{
- return channel_find_locked(NULL, name, namelen, NULL, NULL);
-}
-
-/*! \brief Get next channel by name prefix and lock it */
-struct ast_channel *ast_walk_channel_by_name_prefix_locked(const struct ast_channel *chan, const char *name,
- const int namelen)
-{
- return channel_find_locked(chan, name, namelen, NULL, NULL);
-}
-
-/*! \brief Get channel by exten (and optionally context) and lock it */
-struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
-{
- return channel_find_locked(NULL, NULL, 0, context, exten);
-}
-
-/*! \brief Get next channel by exten (and optionally context) and lock it */
-struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
- const char *context)
-{
- return channel_find_locked(chan, NULL, 0, context, exten);
-}
-
-/*! \brief Wait, look for hangups and condition arg */
-int ast_safe_sleep_conditional(struct ast_channel *chan, int ms, int (*cond)(void*), void *data)
-{
- struct ast_frame *f;
-
- while (ms > 0) {
- if (cond && ((*cond)(data) == 0))
- return 0;
- ms = ast_waitfor(chan, ms);
- if (ms < 0)
- return -1;
- if (ms > 0) {
- f = ast_read(chan);
- if (!f)
- return -1;
- ast_frfree(f);
- }
- }
- return 0;
-}
-
-/*! \brief Wait, look for hangups */
-int ast_safe_sleep(struct ast_channel *chan, int ms)
-{
- return ast_safe_sleep_conditional(chan, ms, NULL, NULL);
-}
-
-static void free_cid(struct ast_callerid *cid)
-{
- if (cid->cid_dnid)
- free(cid->cid_dnid);
- if (cid->cid_num)
- free(cid->cid_num);
- if (cid->cid_name)
- free(cid->cid_name);
- if (cid->cid_ani)
- free(cid->cid_ani);
- if (cid->cid_rdnis)
- free(cid->cid_rdnis);
-}
-
-/*! \brief Free a channel structure */
-void ast_channel_free(struct ast_channel *chan)
-{
- int fd;
- struct ast_var_t *vardata;
- struct ast_frame *f;
- struct varshead *headp;
- struct ast_datastore *datastore = NULL;
- char name[AST_CHANNEL_NAME], *dashptr;
-
- headp=&chan->varshead;
-
- AST_LIST_LOCK(&channels);
- if (!AST_LIST_REMOVE(&channels, chan, chan_list)) {
- AST_LIST_UNLOCK(&channels);
- ast_log(LOG_ERROR, "Unable to find channel in list to free. Assuming it has already been done.\n");
- }
- /* Lock and unlock the channel just to be sure nobody has it locked still
- due to a reference retrieved from the channel list. */
- ast_channel_lock(chan);
- ast_channel_unlock(chan);
-
- /* Get rid of each of the data stores on the channel */
- while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry)))
- /* Free the data store */
- ast_channel_datastore_free(datastore);
-
- /* Lock and unlock the channel just to be sure nobody has it locked still
- due to a reference that was stored in a datastore. (i.e. app_chanspy) */
- ast_channel_lock(chan);
- ast_channel_unlock(chan);
-
- if (chan->tech_pvt) {
- ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
- free(chan->tech_pvt);
- }
-
- if (chan->sched)
- sched_context_destroy(chan->sched);
-
- ast_copy_string(name, chan->name, sizeof(name));
- if ((dashptr = strrchr(name, '-'))) {
- *dashptr = '\0';
- }
-
- /* Stop monitoring */
- if (chan->monitor)
- chan->monitor->stop( chan, 0 );
-
- /* If there is native format music-on-hold state, free it */
- if (chan->music_state)
- ast_moh_cleanup(chan);
-
- /* Free translators */
- if (chan->readtrans)
- ast_translator_free_path(chan->readtrans);
- if (chan->writetrans)
- ast_translator_free_path(chan->writetrans);
- if (chan->pbx)
- ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
- free_cid(&chan->cid);
- /* Close pipes if appropriate */
- if ((fd = chan->alertpipe[0]) > -1)
- close(fd);
- if ((fd = chan->alertpipe[1]) > -1)
- close(fd);
- if ((fd = chan->timingfd) > -1)
- close(fd);
- while ((f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list)))
- ast_frfree(f);
-
- /* loop over the variables list, freeing all data and deleting list items */
- /* no need to lock the list, as the channel is already locked */
-
- while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
- ast_var_delete(vardata);
-
- ast_app_group_discard(chan);
-
- /* Destroy the jitterbuffer */
- ast_jb_destroy(chan);
-
- if (chan->cdr) {
- ast_cdr_discard(chan->cdr);
- chan->cdr = NULL;
- }
-
- ast_mutex_destroy(&chan->lock);
-
- ast_string_field_free_memory(chan);
- free(chan);
- AST_LIST_UNLOCK(&channels);
-
- ast_device_state_changed_literal(name);
-}
-
-struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, char *uid)
-{
- struct ast_datastore *datastore = NULL;
-
- /* Make sure we at least have type so we can identify this */
- if (info == NULL) {
- return NULL;
- }
-
- /* Allocate memory for datastore and clear it */
- datastore = ast_calloc(1, sizeof(*datastore));
- if (datastore == NULL) {
- return NULL;
- }
-
- datastore->info = info;
-
- datastore->uid = ast_strdup(uid);
-
- return datastore;
-}
-
-int ast_channel_datastore_free(struct ast_datastore *datastore)
-{
- int res = 0;
-
- /* Using the destroy function (if present) destroy the data */
- if (datastore->info->destroy != NULL && datastore->data != NULL) {
- datastore->info->destroy(datastore->data);
- datastore->data = NULL;
- }
-
- /* Free allocated UID memory */
- if (datastore->uid != NULL) {
- free(datastore->uid);
- datastore->uid = NULL;
- }
-
- /* Finally free memory used by ourselves */
- free(datastore);
-
- return res;
-}
-
-int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
-{
- struct ast_datastore *datastore = NULL, *datastore2;
-
- AST_LIST_TRAVERSE(&from->datastores, datastore, entry) {
- if (datastore->inheritance > 0) {
- datastore2 = ast_channel_datastore_alloc(datastore->info, datastore->uid);
- if (datastore2) {
- datastore2->data = datastore->info->duplicate ? datastore->info->duplicate(datastore->data) : NULL;
- datastore2->inheritance = datastore->inheritance == DATASTORE_INHERIT_FOREVER ? DATASTORE_INHERIT_FOREVER : datastore->inheritance - 1;
- AST_LIST_INSERT_TAIL(&to->datastores, datastore2, entry);
- }
- }
- }
- return 0;
-}
-
-int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
-{
- int res = 0;
-
- AST_LIST_INSERT_HEAD(&chan->datastores, datastore, entry);
-
- return res;
-}
-
-int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
-{
- struct ast_datastore *datastore2 = NULL;
- int res = -1;
-
- /* Find our position and remove ourselves */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->datastores, datastore2, entry) {
- if (datastore2 == datastore) {
- AST_LIST_REMOVE_CURRENT(&chan->datastores, entry);
- res = 0;
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- return res;
-}
-
-struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, char *uid)
-{
- struct ast_datastore *datastore = NULL;
-
- if (info == NULL)
- return NULL;
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->datastores, datastore, entry) {
- if (datastore->info == info) {
- if (uid != NULL && datastore->uid != NULL) {
- if (!strcasecmp(uid, datastore->uid)) {
- /* Matched by type AND uid */
- break;
- }
- } else {
- /* Matched by type at least */
- break;
- }
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- return datastore;
-}
-
-/*! \brief Softly hangup a channel, don't lock */
-int ast_softhangup_nolock(struct ast_channel *chan, int cause)
-{
- if (option_debug)
- ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name);
- /* Inform channel driver that we need to be hung up, if it cares */
- chan->_softhangup |= cause;
- ast_queue_frame(chan, &ast_null_frame);
- /* Interrupt any poll call or such */
- if (ast_test_flag(chan, AST_FLAG_BLOCKING))
- pthread_kill(chan->blocker, SIGURG);
- return 0;
-}
-
-/*! \brief Softly hangup a channel, lock */
-int ast_softhangup(struct ast_channel *chan, int cause)
-{
- int res;
- ast_channel_lock(chan);
- res = ast_softhangup_nolock(chan, cause);
- ast_channel_unlock(chan);
- return res;
-}
-
-static void free_translation(struct ast_channel *clone)
-{
- if (clone->writetrans)
- ast_translator_free_path(clone->writetrans);
- if (clone->readtrans)
- ast_translator_free_path(clone->readtrans);
- clone->writetrans = NULL;
- clone->readtrans = NULL;
- clone->rawwriteformat = clone->nativeformats;
- clone->rawreadformat = clone->nativeformats;
-}
-
-/*! \brief Hangup a channel */
-int ast_hangup(struct ast_channel *chan)
-{
- int res = 0;
-
- /* Don't actually hang up a channel that will masquerade as someone else, or
- if someone is going to masquerade as us */
- ast_channel_lock(chan);
-
- if (chan->audiohooks) {
- ast_audiohook_detach_list(chan->audiohooks);
- chan->audiohooks = NULL;
- }
-
- ast_autoservice_stop(chan);
-
- if (chan->masq) {
- if (ast_do_masquerade(chan))
- ast_log(LOG_WARNING, "Failed to perform masquerade\n");
- }
-
- if (chan->masq) {
- ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
- ast_channel_unlock(chan);
- return 0;
- }
- /* If this channel is one which will be masqueraded into something,
- mark it as a zombie already, so we know to free it later */
- if (chan->masqr) {
- ast_set_flag(chan, AST_FLAG_ZOMBIE);
- ast_channel_unlock(chan);
- return 0;
- }
- free_translation(chan);
- /* Close audio stream */
- if (chan->stream) {
- ast_closestream(chan->stream);
- chan->stream = NULL;
- }
- /* Close video stream */
- if (chan->vstream) {
- ast_closestream(chan->vstream);
- chan->vstream = NULL;
- }
- if (chan->sched) {
- sched_context_destroy(chan->sched);
- chan->sched = NULL;
- }
-
- if (chan->generatordata) /* Clear any tone stuff remaining */
- chan->generator->release(chan, chan->generatordata);
- chan->generatordata = NULL;
- chan->generator = NULL;
- if (ast_test_flag(chan, AST_FLAG_BLOCKING)) {
- ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
- "is blocked by thread %ld in procedure %s! Expect a failure\n",
- (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc);
- ast_assert(ast_test_flag(chan, AST_FLAG_BLOCKING) == 0);
- }
- if (!ast_test_flag(chan, AST_FLAG_ZOMBIE)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
- if (chan->tech->hangup)
- res = chan->tech->hangup(chan);
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
- }
-
- ast_channel_unlock(chan);
- manager_event(EVENT_FLAG_CALL, "Hangup",
- "Channel: %s\r\n"
- "Uniqueid: %s\r\n"
- "Cause: %d\r\n"
- "Cause-txt: %s\r\n",
- chan->name,
- chan->uniqueid,
- chan->hangupcause,
- ast_cause2str(chan->hangupcause)
- );
-
- if (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_BRIDGED) &&
- !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED) &&
- (chan->cdr->disposition != AST_CDR_NULL || ast_test_flag(chan->cdr, AST_CDR_FLAG_DIALED))) {
-
- ast_cdr_end(chan->cdr);
- ast_cdr_detach(chan->cdr);
- chan->cdr = NULL;
- }
-
- ast_channel_free(chan);
-
- return res;
-}
-
-int ast_answer(struct ast_channel *chan)
-{
- int res = 0;
- ast_channel_lock(chan);
- /* You can't answer an outbound call */
- if (ast_test_flag(chan, AST_FLAG_OUTGOING)) {
- ast_channel_unlock(chan);
- return 0;
- }
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
- ast_channel_unlock(chan);
- return -1;
- }
- switch(chan->_state) {
- case AST_STATE_RINGING:
- case AST_STATE_RING:
- if (chan->tech->answer)
- res = chan->tech->answer(chan);
- ast_setstate(chan, AST_STATE_UP);
- ast_cdr_answer(chan->cdr);
- break;
- case AST_STATE_UP:
- break;
- default:
- break;
- }
- chan->visible_indication = 0;
- ast_channel_unlock(chan);
- return res;
-}
-
-void ast_deactivate_generator(struct ast_channel *chan)
-{
- ast_channel_lock(chan);
- if (chan->generatordata) {
- if (chan->generator && chan->generator->release)
- chan->generator->release(chan, chan->generatordata);
- chan->generatordata = NULL;
- chan->generator = NULL;
- chan->fds[AST_GENERATOR_FD] = -1;
- ast_clear_flag(chan, AST_FLAG_WRITE_INT);
- ast_settimeout(chan, 0, NULL, NULL);
- }
- ast_channel_unlock(chan);
-}
-
-static int generator_force(const void *data)
-{
- /* Called if generator doesn't have data */
- void *tmp;
- int res;
- int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples) = NULL;
- struct ast_channel *chan = (struct ast_channel *)data;
-
- ast_channel_lock(chan);
- tmp = chan->generatordata;
- chan->generatordata = NULL;
- if (chan->generator)
- generate = chan->generator->generate;
- ast_channel_unlock(chan);
-
- if (!tmp || !generate)
- return 0;
-
- res = generate(chan, tmp, 0, ast_format_rate(chan->writeformat & AST_FORMAT_AUDIO_MASK) / 50);
-
- chan->generatordata = tmp;
-
- if (res) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
- ast_deactivate_generator(chan);
- }
-
- return 0;
-}
-
-int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
-{
- int res = 0;
-
- ast_channel_lock(chan);
-
- if (chan->generatordata) {
- if (chan->generator && chan->generator->release)
- chan->generator->release(chan, chan->generatordata);
- chan->generatordata = NULL;
- }
-
- ast_prod(chan);
- if (gen->alloc && !(chan->generatordata = gen->alloc(chan, params))) {
- res = -1;
- }
-
- if (!res) {
- ast_settimeout(chan, 160, generator_force, chan);
- chan->generator = gen;
- }
-
- ast_channel_unlock(chan);
-
- return res;
-}
-
-/*! \brief Wait for x amount of time on a file descriptor to have input. */
-int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
-{
- int winner = -1;
- ast_waitfor_nandfds(NULL, 0, fds, n, exception, &winner, ms);
- return winner;
-}
-
-/*! \brief Wait for x amount of time on a file descriptor to have input. */
-struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds,
- int *exception, int *outfd, int *ms)
-{
- struct timeval start = { 0 , 0 };
- struct pollfd *pfds = NULL;
- int res;
- long rms;
- int x, y, max;
- int sz;
- time_t now = 0;
- long whentohangup = 0, diff;
- struct ast_channel *winner = NULL;
- struct fdmap {
- int chan;
- int fdno;
- } *fdmap = NULL;
-
- if ((sz = n * AST_MAX_FDS + nfds)) {
- pfds = alloca(sizeof(*pfds) * sz);
- fdmap = alloca(sizeof(*fdmap) * sz);
- }
-
- if (outfd)
- *outfd = -99999;
- if (exception)
- *exception = 0;
-
- /* Perform any pending masquerades */
- for (x=0; x < n; x++) {
- ast_channel_lock(c[x]);
- if (c[x]->masq) {
- if (ast_do_masquerade(c[x])) {
- ast_log(LOG_WARNING, "Masquerade failed\n");
- *ms = -1;
- ast_channel_unlock(c[x]);
- return NULL;
- }
- }
- if (c[x]->whentohangup) {
- if (!whentohangup)
- time(&now);
- diff = c[x]->whentohangup - now;
- if (diff < 1) {
- /* Should already be hungup */
- c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
- ast_channel_unlock(c[x]);
- return c[x];
- }
- if (!whentohangup || (diff < whentohangup))
- whentohangup = diff;
- }
- ast_channel_unlock(c[x]);
- }
- /* Wait full interval */
- rms = *ms;
- if (whentohangup) {
- rms = whentohangup * 1000; /* timeout in milliseconds */
- if (*ms >= 0 && *ms < rms) /* original *ms still smaller */
- rms = *ms;
- }
- /*
- * Build the pollfd array, putting the channels' fds first,
- * followed by individual fds. Order is important because
- * individual fd's must have priority over channel fds.
- */
- max = 0;
- for (x=0; x<n; x++) {
- for (y=0; y<AST_MAX_FDS; y++) {
- fdmap[max].fdno = y; /* fd y is linked to this pfds */
- fdmap[max].chan = x; /* channel x is linked to this pfds */
- max += ast_add_fd(&pfds[max], c[x]->fds[y]);
- }
- CHECK_BLOCKING(c[x]);
- }
- /* Add the individual fds */
- for (x=0; x<nfds; x++) {
- fdmap[max].chan = -1;
- max += ast_add_fd(&pfds[max], fds[x]);
- }
-
- if (*ms > 0)
- start = ast_tvnow();
-
- if (sizeof(int) == 4) { /* XXX fix timeout > 600000 on linux x86-32 */
- do {
- int kbrms = rms;
- if (kbrms > 600000)
- kbrms = 600000;
- res = poll(pfds, max, kbrms);
- if (!res)
- rms -= kbrms;
- } while (!res && (rms > 0));
- } else {
- res = poll(pfds, max, rms);
- }
- for (x=0; x<n; x++)
- ast_clear_flag(c[x], AST_FLAG_BLOCKING);
- if (res < 0) { /* Simulate a timeout if we were interrupted */
- if (errno != EINTR)
- *ms = -1;
- return NULL;
- }
- if (whentohangup) { /* if we have a timeout, check who expired */
- time(&now);
- for (x=0; x<n; x++) {
- if (c[x]->whentohangup && now >= c[x]->whentohangup) {
- c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
- if (winner == NULL)
- winner = c[x];
- }
- }
- }
- if (res == 0) { /* no fd ready, reset timeout and done */
- *ms = 0; /* XXX use 0 since we may not have an exact timeout. */
- return winner;
- }
- /*
- * Then check if any channel or fd has a pending event.
- * Remember to check channels first and fds last, as they
- * must have priority on setting 'winner'
- */
- for (x = 0; x < max; x++) {
- res = pfds[x].revents;
- if (res == 0)
- continue;
- if (fdmap[x].chan >= 0) { /* this is a channel */
- winner = c[fdmap[x].chan]; /* override previous winners */
- if (res & POLLPRI)
- ast_set_flag(winner, AST_FLAG_EXCEPTION);
- else
- ast_clear_flag(winner, AST_FLAG_EXCEPTION);
- winner->fdno = fdmap[x].fdno;
- } else { /* this is an fd */
- if (outfd)
- *outfd = pfds[x].fd;
- if (exception)
- *exception = (res & POLLPRI) ? -1 : 0;
- winner = NULL;
- }
- }
- if (*ms > 0) {
- *ms -= ast_tvdiff_ms(ast_tvnow(), start);
- if (*ms < 0)
- *ms = 0;
- }
- return winner;
-}
-
-struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
-{
- return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
-}
-
-int ast_waitfor(struct ast_channel *c, int ms)
-{
- int oldms = ms; /* -1 if no timeout */
-
- ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms);
- if ((ms < 0) && (oldms < 0))
- ms = 0;
- return ms;
-}
-
-/* XXX never to be called with ms = -1 */
-int ast_waitfordigit(struct ast_channel *c, int ms)
-{
- return ast_waitfordigit_full(c, ms, -1, -1);
-}
-
-int ast_settimeout(struct ast_channel *c, int samples, int (*func)(const void *data), void *data)
-{
- int res = -1;
-#ifdef HAVE_DAHDI
- if (c->timingfd > -1) {
- if (!func) {
- samples = 0;
- data = 0;
- }
- if (option_debug)
- ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples);
- res = ioctl(c->timingfd, DAHDI_TIMERCONFIG, &samples);
- c->timingfunc = func;
- c->timingdata = data;
- }
-#endif
- return res;
-}
-
-int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int cmdfd)
-{
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c))
- return -1;
-
- /* Only look for the end of DTMF, don't bother with the beginning and don't emulate things */
- ast_set_flag(c, AST_FLAG_END_DTMF_ONLY);
-
- /* Wait for a digit, no more than ms milliseconds total. */
- while (ms) {
- struct ast_channel *rchan;
- int outfd;
-
- errno = 0;
- rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
- if (!rchan && outfd < 0 && ms) {
- if (errno == 0 || errno == EINTR)
- continue;
- ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return -1;
- } else if (outfd > -1) {
- /* The FD we were watching has something waiting */
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return 1;
- } else if (rchan) {
- int res;
- struct ast_frame *f = ast_read(c);
- if (!f)
- return -1;
-
- switch(f->frametype) {
- case AST_FRAME_DTMF_BEGIN:
- break;
- case AST_FRAME_DTMF_END:
- res = f->subclass;
- ast_frfree(f);
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return res;
- case AST_FRAME_CONTROL:
- switch(f->subclass) {
- case AST_CONTROL_HANGUP:
- ast_frfree(f);
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return -1;
- case AST_CONTROL_RINGING:
- case AST_CONTROL_ANSWER:
- case AST_CONTROL_SRCUPDATE:
- /* Unimportant */
- break;
- default:
- ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass);
- break;
- }
- break;
- case AST_FRAME_VOICE:
- /* Write audio if appropriate */
- if (audiofd > -1) {
- if (write(audiofd, f->data, f->datalen) < 0) {
- ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
- }
- }
- default:
- /* Ignore */
- break;
- }
- ast_frfree(f);
- }
- }
-
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
-
- return 0; /* Time is up */
-}
-
-static void ast_read_generator_actions(struct ast_channel *chan, struct ast_frame *f)
-{
- if (chan->generatordata && !ast_internal_timing_enabled(chan)) {
- void *tmp = chan->generatordata;
- int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples) = NULL;
- int res;
- int samples;
-
- if (chan->timingfunc) {
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
- ast_settimeout(chan, 0, NULL, NULL);
- }
-
- chan->generatordata = NULL; /* reset, to let writes go through */
-
- if (f->subclass != chan->writeformat) {
- float factor;
- factor = ((float) ast_format_rate(chan->writeformat)) / ((float) ast_format_rate(f->subclass));
- samples = (int) ( ((float) f->samples) * factor );
- } else {
- samples = f->samples;
- }
-
- if (chan->generator->generate) {
- generate = chan->generator->generate;
- }
- /* This unlock is here based on two assumptions that hold true at this point in the
- * code. 1) this function is only called from within __ast_read() and 2) all generators
- * call ast_write() in their generate callback.
- *
- * The reason this is added is so that when ast_write is called, the lock that occurs
- * there will not recursively lock the channel. Doing this will cause intended deadlock
- * avoidance not to work in deeper functions
- */
- ast_channel_unlock(chan);
- res = generate(chan, tmp, f->datalen, samples);
- ast_channel_lock(chan);
- chan->generatordata = tmp;
- if (res) {
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
- ast_deactivate_generator(chan);
- }
-
- } else if (f->frametype == AST_FRAME_CNG) {
- if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) {
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "Generator got CNG, switching to timed mode\n");
- ast_settimeout(chan, 160, generator_force, chan);
- }
- }
-}
-
-static inline void queue_dtmf_readq(struct ast_channel *chan, struct ast_frame *f)
-{
- struct ast_frame *fr = &chan->dtmff;
-
- fr->frametype = AST_FRAME_DTMF_END;
- fr->subclass = f->subclass;
- fr->len = f->len;
-
- /* The only time this function will be called is for a frame that just came
- * out of the channel driver. So, we want to stick it on the tail of the
- * readq. */
-
- ast_queue_frame(chan, fr);
-}
-
-/*!
- * \brief Determine whether or not we should ignore DTMF in the readq
- */
-static inline int should_skip_dtmf(struct ast_channel *chan)
-{
- if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF)) {
- /* We're in the middle of emulating a digit, or DTMF has been
- * explicitly deferred. Skip this digit, then. */
- return 1;
- }
-
- if (!ast_tvzero(chan->dtmf_tv) &&
- ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) {
- /* We're not in the middle of a digit, but it hasn't been long enough
- * since the last digit, so we'll have to skip DTMF for now. */
- return 1;
- }
-
- return 0;
-}
-
-static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
-{
- struct ast_frame *f = NULL; /* the return value */
- int blah;
- int prestate;
- int count = 0;
-
- /* this function is very long so make sure there is only one return
- * point at the end (there are only two exceptions to this).
- */
- while(ast_channel_trylock(chan)) {
- if(count++ > 10)
- /*cannot goto done since the channel is not locked*/
- return &ast_null_frame;
- usleep(1);
- }
-
- if (chan->masq) {
- if (ast_do_masquerade(chan))
- ast_log(LOG_WARNING, "Failed to perform masquerade\n");
- else
- f = &ast_null_frame;
- goto done;
- }
-
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
- if (chan->generator)
- ast_deactivate_generator(chan);
- goto done;
- }
- prestate = chan->_state;
-
- /* Read and ignore anything on the alertpipe, but read only
- one sizeof(blah) per frame that we send from it */
- if (chan->alertpipe[0] > -1) {
- int flags = fcntl(chan->alertpipe[0], F_GETFL);
- /* For some odd reason, the alertpipe occasionally loses nonblocking status,
- * which immediately causes a deadlock scenario. Detect and prevent this. */
- if ((flags & O_NONBLOCK) == 0) {
- ast_log(LOG_ERROR, "Alertpipe on channel %s lost O_NONBLOCK?!!\n", chan->name);
- if (fcntl(chan->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
- ast_log(LOG_WARNING, "Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno));
- f = &ast_null_frame;
- goto done;
- }
- }
- if (read(chan->alertpipe[0], &blah, sizeof(blah)) < 0) {
- if (errno != EINTR && errno != EAGAIN)
- ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
- }
- }
-
-#ifdef HAVE_DAHDI
- if (chan->timingfd > -1 && chan->fdno == AST_TIMING_FD && ast_test_flag(chan, AST_FLAG_EXCEPTION)) {
- int res;
-
- ast_clear_flag(chan, AST_FLAG_EXCEPTION);
- blah = -1;
- /* IF we can't get event, assume it's an expired as-per the old interface */
- res = ioctl(chan->timingfd, DAHDI_GETEVENT, &blah);
- if (res)
- blah = DAHDI_EVENT_TIMER_EXPIRED;
-
- if (blah == DAHDI_EVENT_TIMER_PING) {
- if (AST_LIST_EMPTY(&chan->readq) || !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) {
- /* Acknowledge PONG unless we need it again */
- if (ioctl(chan->timingfd, DAHDI_TIMERPONG, &blah)) {
- ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno));
- }
- }
- } else if (blah == DAHDI_EVENT_TIMER_EXPIRED) {
- ioctl(chan->timingfd, DAHDI_TIMERACK, &blah);
- if (chan->timingfunc) {
- /* save a copy of func/data before unlocking the channel */
- int (*func)(const void *) = chan->timingfunc;
- void *data = chan->timingdata;
- ast_channel_unlock(chan);
- func(data);
- } else {
- blah = 0;
- ioctl(chan->timingfd, DAHDI_TIMERCONFIG, &blah);
- chan->timingdata = NULL;
- ast_channel_unlock(chan);
- }
- /* cannot 'goto done' because the channel is already unlocked */
- return &ast_null_frame;
- } else
- ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
- } else
-#endif
- if (chan->fds[AST_GENERATOR_FD] > -1 && chan->fdno == AST_GENERATOR_FD) {
- /* if the AST_GENERATOR_FD is set, call the generator with args
- * set to -1 so it can do whatever it needs to.
- */
- void *tmp = chan->generatordata;
- chan->generatordata = NULL; /* reset to let ast_write get through */
- chan->generator->generate(chan, tmp, -1, -1);
- chan->generatordata = tmp;
- f = &ast_null_frame;
- goto done;
- }
-
- /* Check for pending read queue */
- if (!AST_LIST_EMPTY(&chan->readq)) {
- int skip_dtmf = should_skip_dtmf(chan);
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->readq, f, frame_list) {
- /* We have to be picky about which frame we pull off of the readq because
- * there are cases where we want to leave DTMF frames on the queue until
- * some later time. */
-
- if ( (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) {
- continue;
- }
-
- AST_LIST_REMOVE_CURRENT(&chan->readq, frame_list);
- break;
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- if (!f) {
- /* There were no acceptable frames on the readq. */
- f = &ast_null_frame;
- if (chan->alertpipe[0] > -1) {
- int poke = 0;
- /* Restore the state of the alertpipe since we aren't ready for any
- * of the frames in the readq. */
- if (write(chan->alertpipe[1], &poke, sizeof(poke)) != sizeof(poke)) {
- ast_log(LOG_ERROR, "Failed to write to alertpipe: %s\n", strerror(errno));
- }
- }
- }
-
- /* Interpret hangup and return NULL */
- /* XXX why not the same for frames from the channel ? */
- if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
- ast_frfree(f);
- f = NULL;
- }
- } else {
- chan->blocker = pthread_self();
- if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) {
- if (chan->tech->exception)
- f = chan->tech->exception(chan);
- else {
- ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
- f = &ast_null_frame;
- }
- /* Clear the exception flag */
- ast_clear_flag(chan, AST_FLAG_EXCEPTION);
- } else if (chan->tech->read)
- f = chan->tech->read(chan);
- else
- ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
- }
-
- if (f) {
- /* if the channel driver returned more than one frame, stuff the excess
- into the readq for the next ast_read call (note that we can safely assume
- that the readq is empty, because otherwise we would not have called into
- the channel driver and f would be only a single frame)
- */
- if (AST_LIST_NEXT(f, frame_list)) {
- AST_LIST_HEAD_SET_NOLOCK(&chan->readq, AST_LIST_NEXT(f, frame_list));
- AST_LIST_NEXT(f, frame_list) = NULL;
- }
-
- switch (f->frametype) {
- case AST_FRAME_CONTROL:
- if (f->subclass == AST_CONTROL_ANSWER) {
- if (!ast_test_flag(chan, AST_FLAG_OUTGOING)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Ignoring answer on an inbound call!\n");
- ast_frfree(f);
- f = &ast_null_frame;
- } else if (prestate == AST_STATE_UP) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Dropping duplicate answer!\n");
- ast_frfree(f);
- f = &ast_null_frame;
- } else {
- /* Answer the CDR */
- ast_setstate(chan, AST_STATE_UP);
- /* removed a call to ast_cdr_answer(chan->cdr) from here. */
- }
- }
- break;
- case AST_FRAME_DTMF_END:
- ast_log(LOG_DTMF, "DTMF end '%c' received on %s, duration %ld ms\n", f->subclass, chan->name, f->len);
- /* Queue it up if DTMF is deferred, or if DTMF emulation is forced. */
- if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF) || ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) {
- queue_dtmf_readq(chan, f);
- ast_frfree(f);
- f = &ast_null_frame;
- } else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) {
- if (!ast_tvzero(chan->dtmf_tv) &&
- ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) {
- /* If it hasn't been long enough, defer this digit */
- queue_dtmf_readq(chan, f);
- ast_frfree(f);
- f = &ast_null_frame;
- } else {
- /* There was no begin, turn this into a begin and send the end later */
- f->frametype = AST_FRAME_DTMF_BEGIN;
- ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
- chan->emulate_dtmf_digit = f->subclass;
- chan->dtmf_tv = ast_tvnow();
- if (f->len) {
- if (f->len > AST_MIN_DTMF_DURATION)
- chan->emulate_dtmf_duration = f->len;
- else
- chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION;
- } else
- chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
- ast_log(LOG_DTMF, "DTMF begin emulation of '%c' with duration %u queued on %s\n", f->subclass, chan->emulate_dtmf_duration, chan->name);
- }
- if (chan->audiohooks) {
- struct ast_frame *old_frame = f;
- f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f);
- if (old_frame != f)
- ast_frfree(old_frame);
- }
- } else {
- struct timeval now = ast_tvnow();
- if (ast_test_flag(chan, AST_FLAG_IN_DTMF)) {
- ast_log(LOG_DTMF, "DTMF end accepted with begin '%c' on %s\n", f->subclass, chan->name);
- ast_clear_flag(chan, AST_FLAG_IN_DTMF);
- if (!f->len)
- f->len = ast_tvdiff_ms(now, chan->dtmf_tv);
- } else if (!f->len) {
- ast_log(LOG_DTMF, "DTMF end accepted without begin '%c' on %s\n", f->subclass, chan->name);
- f->len = AST_MIN_DTMF_DURATION;
- }
- if (f->len < AST_MIN_DTMF_DURATION && !ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) {
- ast_log(LOG_DTMF, "DTMF end '%c' has duration %ld but want minimum %d, emulating on %s\n", f->subclass, f->len, AST_MIN_DTMF_DURATION, chan->name);
- ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
- chan->emulate_dtmf_digit = f->subclass;
- chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION - f->len;
- ast_frfree(f);
- f = &ast_null_frame;
- } else {
- ast_log(LOG_DTMF, "DTMF end passthrough '%c' on %s\n", f->subclass, chan->name);
- if (f->len < AST_MIN_DTMF_DURATION) {
- f->len = AST_MIN_DTMF_DURATION;
- }
- chan->dtmf_tv = now;
- }
- if (chan->audiohooks) {
- struct ast_frame *old_frame = f;
- f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f);
- if (old_frame != f)
- ast_frfree(old_frame);
- }
- }
- break;
- case AST_FRAME_DTMF_BEGIN:
- ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass, chan->name);
- if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY | AST_FLAG_EMULATE_DTMF) ||
- (!ast_tvzero(chan->dtmf_tv) &&
- ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) ) {
- ast_log(LOG_DTMF, "DTMF begin ignored '%c' on %s\n", f->subclass, chan->name);
- ast_frfree(f);
- f = &ast_null_frame;
- } else {
- ast_set_flag(chan, AST_FLAG_IN_DTMF);
- chan->dtmf_tv = ast_tvnow();
- ast_log(LOG_DTMF, "DTMF begin passthrough '%c' on %s\n", f->subclass, chan->name);
- }
- break;
- case AST_FRAME_NULL:
- /* The EMULATE_DTMF flag must be cleared here as opposed to when the duration
- * is reached , because we want to make sure we pass at least one
- * voice frame through before starting the next digit, to ensure a gap
- * between DTMF digits. */
- if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) {
- struct timeval now = ast_tvnow();
- if (!chan->emulate_dtmf_duration) {
- ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF);
- chan->emulate_dtmf_digit = 0;
- } else if (ast_tvdiff_ms(now, chan->dtmf_tv) >= chan->emulate_dtmf_duration) {
- chan->emulate_dtmf_duration = 0;
- ast_frfree(f);
- f = &chan->dtmff;
- f->frametype = AST_FRAME_DTMF_END;
- f->subclass = chan->emulate_dtmf_digit;
- f->len = ast_tvdiff_ms(now, chan->dtmf_tv);
- chan->dtmf_tv = now;
- ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF);
- chan->emulate_dtmf_digit = 0;
- ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass, chan->name);
- }
- }
- break;
- case AST_FRAME_VOICE:
- /* The EMULATE_DTMF flag must be cleared here as opposed to when the duration
- * is reached , because we want to make sure we pass at least one
- * voice frame through before starting the next digit, to ensure a gap
- * between DTMF digits. */
- if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !chan->emulate_dtmf_duration) {
- ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF);
- chan->emulate_dtmf_digit = 0;
- }
-
- if (dropaudio || ast_test_flag(chan, AST_FLAG_IN_DTMF)) {
- if (dropaudio)
- ast_read_generator_actions(chan, f);
- ast_frfree(f);
- f = &ast_null_frame;
- }
-
- if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !ast_test_flag(chan, AST_FLAG_IN_DTMF)) {
- struct timeval now = ast_tvnow();
- if (ast_tvdiff_ms(now, chan->dtmf_tv) >= chan->emulate_dtmf_duration) {
- chan->emulate_dtmf_duration = 0;
- ast_frfree(f);
- f = &chan->dtmff;
- f->frametype = AST_FRAME_DTMF_END;
- f->subclass = chan->emulate_dtmf_digit;
- f->len = ast_tvdiff_ms(now, chan->dtmf_tv);
- chan->dtmf_tv = now;
- if (chan->audiohooks) {
- struct ast_frame *old_frame = f;
- f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f);
- if (old_frame != f)
- ast_frfree(old_frame);
- }
- ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass, chan->name);
- } else {
- /* Drop voice frames while we're still in the middle of the digit */
- ast_frfree(f);
- f = &ast_null_frame;
- }
- } else if ((f->frametype == AST_FRAME_VOICE) && !(f->subclass & chan->nativeformats)) {
- /* This frame is not one of the current native formats -- drop it on the floor */
- char to[200];
- ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n",
- chan->name, ast_getformatname(f->subclass), ast_getformatname_multiple(to, sizeof(to), chan->nativeformats));
- ast_frfree(f);
- f = &ast_null_frame;
- } else if ((f->frametype == AST_FRAME_VOICE)) {
- if (chan->audiohooks) {
- struct ast_frame *old_frame = f;
- f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f);
- if (old_frame != f)
- ast_frfree(old_frame);
- }
- if (chan->monitor && chan->monitor->read_stream ) {
- /* XXX what does this do ? */
-#ifndef MONITOR_CONSTANT_DELAY
- int jump = chan->outsmpl - chan->insmpl - 4 * f->samples;
- if (jump >= 0) {
- jump = chan->outsmpl - chan->insmpl;
- if (ast_seekstream(chan->monitor->read_stream, jump, SEEK_FORCECUR) == -1)
- ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
- chan->insmpl += jump + f->samples;
- } else
- chan->insmpl+= f->samples;
-#else
- int jump = chan->outsmpl - chan->insmpl;
- if (jump - MONITOR_DELAY >= 0) {
- if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
- ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
- chan->insmpl += jump;
- } else
- chan->insmpl += f->samples;
-#endif
- if (chan->monitor->state == AST_MONITOR_RUNNING) {
- if (ast_writestream(chan->monitor->read_stream, f) < 0)
- ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
- }
- }
-
- if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL)
- f = &ast_null_frame;
-
- /* Run generator sitting on the line if timing device not available
- * and synchronous generation of outgoing frames is necessary */
- ast_read_generator_actions(chan, f);
- }
- default:
- /* Just pass it on! */
- break;
- }
- } else {
- /* Make sure we always return NULL in the future */
- chan->_softhangup |= AST_SOFTHANGUP_DEV;
- if (chan->generator)
- ast_deactivate_generator(chan);
- /* We no longer End the CDR here */
- }
-
- /* High bit prints debugging */
- if (chan->fin & DEBUGCHAN_FLAG)
- ast_frame_dump(chan->name, f, "<<");
- chan->fin = FRAMECOUNT_INC(chan->fin);
-
-done:
- ast_channel_unlock(chan);
- return f;
-}
-
-int ast_internal_timing_enabled(struct ast_channel *chan)
-{
- int ret = ast_opt_internal_timing && chan->timingfd > -1;
- if (option_debug > 4)
- ast_log(LOG_DEBUG, "Internal timing is %s (option_internal_timing=%d chan->timingfd=%d)\n", ret? "enabled": "disabled", ast_opt_internal_timing, chan->timingfd);
- return ret;
-}
-
-struct ast_frame *ast_read(struct ast_channel *chan)
-{
- return __ast_read(chan, 0);
-}
-
-struct ast_frame *ast_read_noaudio(struct ast_channel *chan)
-{
- return __ast_read(chan, 1);
-}
-
-int ast_indicate(struct ast_channel *chan, int condition)
-{
- return ast_indicate_data(chan, condition, NULL, 0);
-}
-
-static int attribute_const is_visible_indication(enum ast_control_frame_type condition)
-{
- /* Don't include a default case here so that we get compiler warnings
- * when a new type is added. */
-
- switch (condition) {
- case AST_CONTROL_PROGRESS:
- case AST_CONTROL_PROCEEDING:
- case AST_CONTROL_VIDUPDATE:
- case AST_CONTROL_SRCUPDATE:
- case AST_CONTROL_RADIO_KEY:
- case AST_CONTROL_RADIO_UNKEY:
- case AST_CONTROL_OPTION:
- case AST_CONTROL_WINK:
- case AST_CONTROL_FLASH:
- case AST_CONTROL_OFFHOOK:
- case AST_CONTROL_TAKEOFFHOOK:
- case AST_CONTROL_ANSWER:
- case AST_CONTROL_HANGUP:
- return 0;
-
- case AST_CONTROL_CONGESTION:
- case AST_CONTROL_BUSY:
- case AST_CONTROL_RINGING:
- case AST_CONTROL_RING:
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
- return 1;
- }
-
- return 0;
-}
-
-int ast_indicate_data(struct ast_channel *chan, int _condition,
- const void *data, size_t datalen)
-{
- /* By using an enum, we'll get compiler warnings for values not handled
- * in switch statements. */
- enum ast_control_frame_type condition = _condition;
- const struct tone_zone_sound *ts = NULL;
- int res = -1;
-
- ast_channel_lock(chan);
-
- /* Don't bother if the channel is about to go away, anyway. */
- if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
- ast_channel_unlock(chan);
- return -1;
- }
-
- if (chan->tech->indicate) {
- /* See if the channel driver can handle this condition. */
- res = chan->tech->indicate(chan, condition, data, datalen);
- }
-
- ast_channel_unlock(chan);
-
- if (chan->tech->indicate && !res) {
- /* The channel driver successfully handled this indication */
- if (is_visible_indication(condition)) {
- chan->visible_indication = condition;
- }
- return 0;
- }
-
- /* The channel driver does not support this indication, let's fake
- * it by doing our own tone generation if applicable. */
-
- /*!\note If we compare the enumeration type, which does not have any
- * negative constants, the compiler may optimize this code away.
- * Therefore, we must perform an integer comparison here. */
- if (_condition < 0) {
- /* Stop any tones that are playing */
- ast_playtones_stop(chan);
- return 0;
- }
-
- /* Handle conditions that we have tones for. */
- switch (condition) {
- case AST_CONTROL_RINGING:
- ts = ast_get_indication_tone(chan->zone, "ring");
- break;
- case AST_CONTROL_BUSY:
- ts = ast_get_indication_tone(chan->zone, "busy");
- break;
- case AST_CONTROL_CONGESTION:
- ts = ast_get_indication_tone(chan->zone, "congestion");
- break;
- case AST_CONTROL_PROGRESS:
- case AST_CONTROL_PROCEEDING:
- case AST_CONTROL_VIDUPDATE:
- case AST_CONTROL_SRCUPDATE:
- case AST_CONTROL_RADIO_KEY:
- case AST_CONTROL_RADIO_UNKEY:
- case AST_CONTROL_OPTION:
- case AST_CONTROL_WINK:
- case AST_CONTROL_FLASH:
- case AST_CONTROL_OFFHOOK:
- case AST_CONTROL_TAKEOFFHOOK:
- case AST_CONTROL_ANSWER:
- case AST_CONTROL_HANGUP:
- case AST_CONTROL_RING:
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
- /* Nothing left to do for these. */
- res = 0;
- break;
- }
-
- if (ts && ts->data[0]) {
- /* We have a tone to play, yay. */
- if (option_debug) {
- ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
- }
- ast_playtones_start(chan, 0, ts->data, 1);
- res = 0;
- chan->visible_indication = condition;
- }
-
- if (res) {
- /* not handled */
- ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
- }
-
- return res;
-}
-
-int ast_recvchar(struct ast_channel *chan, int timeout)
-{
- int c;
- char *buf = ast_recvtext(chan, timeout);
- if (buf == NULL)
- return -1; /* error or timeout */
- c = *(unsigned char *)buf;
- free(buf);
- return c;
-}
-
-char *ast_recvtext(struct ast_channel *chan, int timeout)
-{
- int res, done = 0;
- char *buf = NULL;
-
- while (!done) {
- struct ast_frame *f;
- if (ast_check_hangup(chan))
- break;
- res = ast_waitfor(chan, timeout);
- if (res <= 0) /* timeout or error */
- break;
- timeout = res; /* update timeout */
- f = ast_read(chan);
- if (f == NULL)
- break; /* no frame */
- if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)
- done = 1; /* force a break */
- else if (f->frametype == AST_FRAME_TEXT) { /* what we want */
- buf = ast_strndup((char *) f->data, f->datalen); /* dup and break */
- done = 1;
- }
- ast_frfree(f);
- }
- return buf;
-}
-
-int ast_sendtext(struct ast_channel *chan, const char *text)
-{
- int res = 0;
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))
- return -1;
- CHECK_BLOCKING(chan);
- if (chan->tech->send_text)
- res = chan->tech->send_text(chan, text);
- ast_clear_flag(chan, AST_FLAG_BLOCKING);
- return res;
-}
-
-int ast_senddigit_begin(struct ast_channel *chan, char digit)
-{
- /* Device does not support DTMF tones, lets fake
- * it by doing our own generation. */
- static const char* dtmf_tones[] = {
- "941+1336", /* 0 */
- "697+1209", /* 1 */
- "697+1336", /* 2 */
- "697+1477", /* 3 */
- "770+1209", /* 4 */
- "770+1336", /* 5 */
- "770+1477", /* 6 */
- "852+1209", /* 7 */
- "852+1336", /* 8 */
- "852+1477", /* 9 */
- "697+1633", /* A */
- "770+1633", /* B */
- "852+1633", /* C */
- "941+1633", /* D */
- "941+1209", /* * */
- "941+1477" /* # */
- };
-
- if (!chan->tech->send_digit_begin)
- return 0;
-
- if (!chan->tech->send_digit_begin(chan, digit))
- return 0;
-
- if (digit >= '0' && digit <='9')
- ast_playtones_start(chan, 0, dtmf_tones[digit-'0'], 0);
- else if (digit >= 'A' && digit <= 'D')
- ast_playtones_start(chan, 0, dtmf_tones[digit-'A'+10], 0);
- else if (digit == '*')
- ast_playtones_start(chan, 0, dtmf_tones[14], 0);
- else if (digit == '#')
- ast_playtones_start(chan, 0, dtmf_tones[15], 0);
- else {
- /* not handled */
- if (option_debug)
- ast_log(LOG_DEBUG, "Unable to generate DTMF tone '%c' for '%s'\n", digit, chan->name);
- }
-
- return 0;
-}
-
-int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration)
-{
- int res = -1;
-
- if (chan->tech->send_digit_end)
- res = chan->tech->send_digit_end(chan, digit, duration);
-
- if (res && chan->generator)
- ast_playtones_stop(chan);
-
- return 0;
-}
-
-int ast_senddigit(struct ast_channel *chan, char digit)
-{
- if (chan->tech->send_digit_begin) {
- ast_senddigit_begin(chan, digit);
- ast_safe_sleep(chan, AST_DEFAULT_EMULATE_DTMF_DURATION);
- }
-
- return ast_senddigit_end(chan, digit, AST_DEFAULT_EMULATE_DTMF_DURATION);
-}
-
-int ast_prod(struct ast_channel *chan)
-{
- struct ast_frame a = { AST_FRAME_VOICE };
- char nothing[128];
-
- /* Send an empty audio frame to get things moving */
- if (chan->_state != AST_STATE_UP) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
- a.subclass = chan->rawwriteformat;
- a.data = nothing + AST_FRIENDLY_OFFSET;
- a.src = "ast_prod";
- if (ast_write(chan, &a))
- ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name);
- }
- return 0;
-}
-
-int ast_write_video(struct ast_channel *chan, struct ast_frame *fr)
-{
- int res;
- if (!chan->tech->write_video)
- return 0;
- res = ast_write(chan, fr);
- if (!res)
- res = 1;
- return res;
-}
-
-int ast_write(struct ast_channel *chan, struct ast_frame *fr)
-{
- int res = -1;
- int count = 0;
- struct ast_frame *f = NULL, *f2 = NULL;
-
- /*Deadlock avoidance*/
- while(ast_channel_trylock(chan)) {
- /*cannot goto done since the channel is not locked*/
- if(count++ > 10) {
- if(option_debug)
- ast_log(LOG_DEBUG, "Deadlock avoided for write to channel '%s'\n", chan->name);
- return 0;
- }
- usleep(1);
- }
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))
- goto done;
-
- /* Handle any pending masquerades */
- if (chan->masq && ast_do_masquerade(chan)) {
- ast_log(LOG_WARNING, "Failed to perform masquerade\n");
- goto done;
- }
- if (chan->masqr) {
- res = 0; /* XXX explain, why 0 ? */
- goto done;
- }
- if (chan->generatordata) {
- if (ast_test_flag(chan, AST_FLAG_WRITE_INT))
- ast_deactivate_generator(chan);
- else {
- if (fr->frametype == AST_FRAME_DTMF_END) {
- /* There is a generator running while we're in the middle of a digit.
- * It's probably inband DTMF, so go ahead and pass it so it can
- * stop the generator */
- ast_clear_flag(chan, AST_FLAG_BLOCKING);
- ast_channel_unlock(chan);
- res = ast_senddigit_end(chan, fr->subclass, fr->len);
- ast_channel_lock(chan);
- CHECK_BLOCKING(chan);
- } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_UNHOLD) {
- /* This is a side case where Echo is basically being called and the person put themselves on hold and took themselves off hold */
- res = (chan->tech->indicate == NULL) ? 0 :
- chan->tech->indicate(chan, fr->subclass, fr->data, fr->datalen);
- }
- res = 0; /* XXX explain, why 0 ? */
- goto done;
- }
- }
- /* High bit prints debugging */
- if (chan->fout & DEBUGCHAN_FLAG)
- ast_frame_dump(chan->name, fr, ">>");
- CHECK_BLOCKING(chan);
- switch(fr->frametype) {
- case AST_FRAME_CONTROL:
- res = (chan->tech->indicate == NULL) ? 0 :
- chan->tech->indicate(chan, fr->subclass, fr->data, fr->datalen);
- break;
- case AST_FRAME_DTMF_BEGIN:
- if (chan->audiohooks) {
- struct ast_frame *old_frame = fr;
- fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
- if (old_frame != fr)
- f = fr;
- }
- ast_clear_flag(chan, AST_FLAG_BLOCKING);
- ast_channel_unlock(chan);
- res = ast_senddigit_begin(chan, fr->subclass);
- ast_channel_lock(chan);
- CHECK_BLOCKING(chan);
- break;
- case AST_FRAME_DTMF_END:
- if (chan->audiohooks) {
- struct ast_frame *old_frame = fr;
- fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
- if (old_frame != fr)
- f = fr;
- }
- ast_clear_flag(chan, AST_FLAG_BLOCKING);
- ast_channel_unlock(chan);
- res = ast_senddigit_end(chan, fr->subclass, fr->len);
- ast_channel_lock(chan);
- CHECK_BLOCKING(chan);
- break;
- case AST_FRAME_TEXT:
- res = (chan->tech->send_text == NULL) ? 0 :
- chan->tech->send_text(chan, (char *) fr->data);
- break;
- case AST_FRAME_HTML:
- res = (chan->tech->send_html == NULL) ? 0 :
- chan->tech->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen);
- break;
- case AST_FRAME_VIDEO:
- /* XXX Handle translation of video codecs one day XXX */
- res = (chan->tech->write_video == NULL) ? 0 :
- chan->tech->write_video(chan, fr);
- break;
- case AST_FRAME_MODEM:
- res = (chan->tech->write == NULL) ? 0 :
- chan->tech->write(chan, fr);
- break;
- case AST_FRAME_VOICE:
- if (chan->tech->write == NULL)
- break; /*! \todo XXX should return 0 maybe ? */
-
- if (chan->audiohooks) {
- struct ast_frame *old_frame = fr;
- fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
- if (old_frame != fr)
- f2 = fr;
- }
-
- /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */
- if (fr->subclass == chan->rawwriteformat)
- f = fr;
- else
- f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr;
-
- /* If we have no frame of audio, then we have to bail out */
- if (!f) {
- res = 0;
- break;
- }
-
- /* If Monitor is running on this channel, then we have to write frames out there too */
- if (chan->monitor && chan->monitor->write_stream) {
- /* XXX must explain this code */
-#ifndef MONITOR_CONSTANT_DELAY
- int jump = chan->insmpl - chan->outsmpl - 4 * f->samples;
- if (jump >= 0) {
- jump = chan->insmpl - chan->outsmpl;
- if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1)
- ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
- chan->outsmpl += jump + f->samples;
- } else
- chan->outsmpl += f->samples;
-#else
- int jump = chan->insmpl - chan->outsmpl;
- if (jump - MONITOR_DELAY >= 0) {
- if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
- ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
- chan->outsmpl += jump;
- } else
- chan->outsmpl += f->samples;
-#endif
- if (chan->monitor->state == AST_MONITOR_RUNNING) {
- if (ast_writestream(chan->monitor->write_stream, f) < 0)
- ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
- }
- }
-
- if (f)
- res = chan->tech->write(chan,f);
- else
- res = 0;
- break;
- case AST_FRAME_NULL:
- case AST_FRAME_IAX:
- /* Ignore these */
- res = 0;
- break;
- default:
- /* At this point, fr is the incoming frame and f is NULL. Channels do
- * not expect to get NULL as a frame pointer and will segfault. Hence,
- * we output the original frame passed in. */
- res = chan->tech->write(chan, fr);
- break;
- }
-
- if (f && f != fr)
- ast_frfree(f);
- if (f2)
- ast_frfree(f2);
- ast_clear_flag(chan, AST_FLAG_BLOCKING);
- /* Consider a write failure to force a soft hangup */
- if (res < 0)
- chan->_softhangup |= AST_SOFTHANGUP_DEV;
- else {
- chan->fout = FRAMECOUNT_INC(chan->fout);
- }
-done:
- ast_channel_unlock(chan);
- return res;
-}
-
-static int set_format(struct ast_channel *chan, int fmt, int *rawformat, int *format,
- struct ast_trans_pvt **trans, const int direction)
-{
- int native;
- int res;
- char from[200], to[200];
-
- /* Make sure we only consider audio */
- fmt &= AST_FORMAT_AUDIO_MASK;
-
- native = chan->nativeformats;
- /* Find a translation path from the native format to one of the desired formats */
- if (!direction)
- /* reading */
- res = ast_translator_best_choice(&fmt, &native);
- else
- /* writing */
- res = ast_translator_best_choice(&native, &fmt);
-
- if (res < 0) {
- ast_log(LOG_WARNING, "Unable to find a codec translation path from %s to %s\n",
- ast_getformatname_multiple(from, sizeof(from), native),
- ast_getformatname_multiple(to, sizeof(to), fmt));
- return -1;
- }
-
- /* Now we have a good choice for both. */
- ast_channel_lock(chan);
-
- if ((*rawformat == native) && (*format == fmt) && ((*rawformat == *format) || (*trans))) {
- /* the channel is already in these formats, so nothing to do */
- ast_channel_unlock(chan);
- return 0;
- }
-
- *rawformat = native;
- /* User perspective is fmt */
- *format = fmt;
- /* Free any read translation we have right now */
- if (*trans)
- ast_translator_free_path(*trans);
- /* Build a translation path from the raw format to the desired format */
- if (!direction)
- /* reading */
- *trans = ast_translator_build_path(*format, *rawformat);
- else
- /* writing */
- *trans = ast_translator_build_path(*rawformat, *format);
- ast_channel_unlock(chan);
- if (option_debug)
- ast_log(LOG_DEBUG, "Set channel %s to %s format %s\n", chan->name,
- direction ? "write" : "read", ast_getformatname(fmt));
- return 0;
-}
-
-int ast_set_read_format(struct ast_channel *chan, int fmt)
-{
- return set_format(chan, fmt, &chan->rawreadformat, &chan->readformat,
- &chan->readtrans, 0);
-}
-
-int ast_set_write_format(struct ast_channel *chan, int fmt)
-{
- return set_format(chan, fmt, &chan->rawwriteformat, &chan->writeformat,
- &chan->writetrans, 1);
-}
-
-char *ast_channel_reason2str(int reason)
-{
- switch (reason) /* the following appear to be the only ones actually returned by request_and_dial */
- {
- case 0:
- return "Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?)";
- case AST_CONTROL_HANGUP:
- return "Hangup";
- case AST_CONTROL_RING:
- return "Local Ring";
- case AST_CONTROL_RINGING:
- return "Remote end Ringing";
- case AST_CONTROL_ANSWER:
- return "Remote end has Answered";
- case AST_CONTROL_BUSY:
- return "Remote end is Busy";
- case AST_CONTROL_CONGESTION:
- return "Congestion (circuits busy)";
- default:
- return "Unknown Reason!!";
- }
-}
-
-struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
-{
- int dummy_outstate;
- int cause = 0;
- struct ast_channel *chan;
- int res = 0;
- int last_subclass = 0;
-
- if (outstate)
- *outstate = 0;
- else
- outstate = &dummy_outstate; /* make outstate always a valid pointer */
-
- chan = ast_request(type, format, data, &cause);
- if (!chan) {
- ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
- /* compute error and return */
- if (cause == AST_CAUSE_BUSY)
- *outstate = AST_CONTROL_BUSY;
- else if (cause == AST_CAUSE_CONGESTION)
- *outstate = AST_CONTROL_CONGESTION;
- return NULL;
- }
-
- if (oh) {
- if (oh->vars)
- ast_set_variables(chan, oh->vars);
- /* XXX why is this necessary, for the parent_channel perhaps ? */
- if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name))
- ast_set_callerid(chan, oh->cid_num, oh->cid_name, oh->cid_num);
- if (oh->parent_channel)
- ast_channel_inherit_variables(oh->parent_channel, chan);
- if (oh->account)
- ast_cdr_setaccount(chan, oh->account);
- }
- ast_set_callerid(chan, cid_num, cid_name, cid_num);
-
- if (ast_call(chan, data, 0)) { /* ast_call failed... */
- ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
- } else {
- res = 1; /* mark success in case chan->_state is already AST_STATE_UP */
- while (timeout && chan->_state != AST_STATE_UP) {
- struct ast_frame *f;
- res = ast_waitfor(chan, timeout);
- if (res <= 0) /* error, timeout, or done */
- break;
- if (timeout > -1)
- timeout = res;
- f = ast_read(chan);
- if (!f) {
- *outstate = AST_CONTROL_HANGUP;
- res = 0;
- break;
- }
- if (f->frametype == AST_FRAME_CONTROL) {
- switch (f->subclass) {
- case AST_CONTROL_RINGING: /* record but keep going */
- *outstate = f->subclass;
- break;
-
- case AST_CONTROL_BUSY:
- case AST_CONTROL_CONGESTION:
- case AST_CONTROL_ANSWER:
- *outstate = f->subclass;
- timeout = 0; /* trick to force exit from the while() */
- break;
-
- /* Ignore these */
- case AST_CONTROL_PROGRESS:
- case AST_CONTROL_PROCEEDING:
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
- case AST_CONTROL_VIDUPDATE:
- case AST_CONTROL_SRCUPDATE:
- case -1: /* Ignore -- just stopping indications */
- break;
-
- default:
- ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
- }
- last_subclass = f->subclass;
- }
- ast_frfree(f);
- }
- }
-
- /* Final fixups */
- if (oh) {
- if (!ast_strlen_zero(oh->context))
- ast_copy_string(chan->context, oh->context, sizeof(chan->context));
- if (!ast_strlen_zero(oh->exten))
- ast_copy_string(chan->exten, oh->exten, sizeof(chan->exten));
- if (oh->priority)
- chan->priority = oh->priority;
- }
- if (chan->_state == AST_STATE_UP)
- *outstate = AST_CONTROL_ANSWER;
-
- if (res <= 0) {
- if ( AST_CONTROL_RINGING == last_subclass )
- chan->hangupcause = AST_CAUSE_NO_ANSWER;
- if (!chan->cdr && (chan->cdr = ast_cdr_alloc()))
- ast_cdr_init(chan->cdr, chan);
- if (chan->cdr) {
- char tmp[256];
- snprintf(tmp, sizeof(tmp), "%s/%s", type, (char *)data);
- ast_cdr_setapp(chan->cdr,"Dial",tmp);
- ast_cdr_update(chan);
- ast_cdr_start(chan->cdr);
- ast_cdr_end(chan->cdr);
- /* If the cause wasn't handled properly */
- if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
- ast_cdr_failed(chan->cdr);
- }
- ast_hangup(chan);
- chan = NULL;
- }
- return chan;
-}
-
-struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname)
-{
- return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
-}
-
-struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
-{
- struct chanlist *chan;
- struct ast_channel *c;
- int capabilities;
- int fmt;
- int res;
- int foo;
- int videoformat = format & AST_FORMAT_VIDEO_MASK;
-
- if (!cause)
- cause = &foo;
- *cause = AST_CAUSE_NOTDEFINED;
-
- if (AST_LIST_LOCK(&channels)) {
- ast_log(LOG_WARNING, "Unable to lock channel list\n");
- return NULL;
- }
-
- AST_LIST_TRAVERSE(&backends, chan, list) {
- if (strcasecmp(type, chan->tech->type))
- continue;
-
- capabilities = chan->tech->capabilities;
- fmt = format & AST_FORMAT_AUDIO_MASK;
- res = ast_translator_best_choice(&fmt, &capabilities);
- if (res < 0) {
- ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->tech->capabilities, format);
- *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
- AST_LIST_UNLOCK(&channels);
- return NULL;
- }
- AST_LIST_UNLOCK(&channels);
- if (!chan->tech->requester)
- return NULL;
-
- if (!(c = chan->tech->requester(type, capabilities | videoformat, data, cause)))
- return NULL;
-
- /* no need to generate a Newchannel event here; it is done in the channel_alloc call */
- return c;
- }
-
- ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
- *cause = AST_CAUSE_NOSUCHDRIVER;
- AST_LIST_UNLOCK(&channels);
-
- return NULL;
-}
-
-int ast_call(struct ast_channel *chan, char *addr, int timeout)
-{
- /* Place an outgoing call, but don't wait any longer than timeout ms before returning.
- If the remote end does not answer within the timeout, then do NOT hang up, but
- return anyway. */
- int res = -1;
- /* Stop if we're a zombie or need a soft hangup */
- ast_channel_lock(chan);
- if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) {
- if (chan->cdr)
- ast_set_flag(chan->cdr, AST_CDR_FLAG_DIALED);
- if (chan->tech->call)
- res = chan->tech->call(chan, addr, timeout);
- ast_set_flag(chan, AST_FLAG_OUTGOING);
- }
- ast_channel_unlock(chan);
- return res;
-}
-
-/*!
- \brief Transfer a call to dest, if the channel supports transfer
-
- Called by:
- \arg app_transfer
- \arg the manager interface
-*/
-int ast_transfer(struct ast_channel *chan, char *dest)
-{
- int res = -1;
-
- /* Stop if we're a zombie or need a soft hangup */
- ast_channel_lock(chan);
- if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) {
- if (chan->tech->transfer) {
- res = chan->tech->transfer(chan, dest);
- if (!res)
- res = 1;
- } else
- res = 0;
- }
- ast_channel_unlock(chan);
- return res;
-}
-
-int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
-{
- return ast_readstring_full(c, s, len, timeout, ftimeout, enders, -1, -1);
-}
-
-int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
-{
- int pos = 0; /* index in the buffer where we accumulate digits */
- int to = ftimeout;
-
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c))
- return -1;
- if (!len)
- return -1;
- for (;;) {
- int d;
- if (c->stream) {
- d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
- ast_stopstream(c);
- usleep(1000);
- if (!d)
- d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
- } else {
- d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
- }
- if (d < 0)
- return -1;
- if (d == 0) {
- s[pos]='\0';
- return 1;
- }
- if (d == 1) {
- s[pos]='\0';
- return 2;
- }
- if (!strchr(enders, d))
- s[pos++] = d;
- if (strchr(enders, d) || (pos >= len)) {
- s[pos]='\0';
- return 0;
- }
- to = timeout;
- }
- /* Never reached */
- return 0;
-}
-
-int ast_channel_supports_html(struct ast_channel *chan)
-{
- return (chan->tech->send_html) ? 1 : 0;
-}
-
-int ast_channel_sendhtml(struct ast_channel *chan, int subclass, const char *data, int datalen)
-{
- if (chan->tech->send_html)
- return chan->tech->send_html(chan, subclass, data, datalen);
- return -1;
-}
-
-int ast_channel_sendurl(struct ast_channel *chan, const char *url)
-{
- return ast_channel_sendhtml(chan, AST_HTML_URL, url, strlen(url) + 1);
-}
-
-int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
-{
- int src;
- int dst;
-
- if (chan->readformat == peer->writeformat && chan->writeformat == peer->readformat) {
- /* Already compatible! Moving on ... */
- return 0;
- }
-
- /* Set up translation from the chan to the peer */
- src = chan->nativeformats;
- dst = peer->nativeformats;
- if (ast_translator_best_choice(&dst, &src) < 0) {
- ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, src, peer->name, dst);
- return -1;
- }
-
- /* if the best path is not 'pass through', then
- transcoding is needed; if desired, force transcode path
- to use SLINEAR between channels, but only if there is
- no direct conversion available */
- if ((src != dst) && ast_opt_transcode_via_slin &&
- (ast_translate_path_steps(dst, src) != 1))
- dst = AST_FORMAT_SLINEAR;
- if (ast_set_read_format(chan, dst) < 0) {
- ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, dst);
- return -1;
- }
- if (ast_set_write_format(peer, dst) < 0) {
- ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, dst);
- return -1;
- }
-
- /* Set up translation from the peer to the chan */
- src = peer->nativeformats;
- dst = chan->nativeformats;
- if (ast_translator_best_choice(&dst, &src) < 0) {
- ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, src, chan->name, dst);
- return -1;
- }
-
- /* if the best path is not 'pass through', then
- transcoding is needed; if desired, force transcode path
- to use SLINEAR between channels, but only if there is
- no direct conversion available */
- if ((src != dst) && ast_opt_transcode_via_slin &&
- (ast_translate_path_steps(dst, src) != 1))
- dst = AST_FORMAT_SLINEAR;
- if (ast_set_read_format(peer, dst) < 0) {
- ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, dst);
- return -1;
- }
- if (ast_set_write_format(chan, dst) < 0) {
- ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, dst);
- return -1;
- }
- return 0;
-}
-
-int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
-{
- int res = -1;
- struct ast_channel *final_orig, *final_clone, *base;
-
-retrymasq:
- final_orig = original;
- final_clone = clone;
-
- ast_channel_lock(original);
- while (ast_channel_trylock(clone)) {
- ast_channel_unlock(original);
- usleep(1);
- ast_channel_lock(original);
- }
-
- /* each of these channels may be sitting behind a channel proxy (i.e. chan_agent)
- and if so, we don't really want to masquerade it, but its proxy */
- if (original->_bridge && (original->_bridge != ast_bridged_channel(original)) && (original->_bridge->_bridge != original))
- final_orig = original->_bridge;
-
- if (clone->_bridge && (clone->_bridge != ast_bridged_channel(clone)) && (clone->_bridge->_bridge != clone))
- final_clone = clone->_bridge;
-
- if (final_clone->tech->get_base_channel && (base = final_clone->tech->get_base_channel(final_clone))) {
- final_clone = base;
- }
-
- if ((final_orig != original) || (final_clone != clone)) {
- /* Lots and lots of deadlock avoidance. The main one we're competing with
- * is ast_write(), which locks channels recursively, when working with a
- * proxy channel. */
- if (ast_channel_trylock(final_orig)) {
- ast_channel_unlock(clone);
- ast_channel_unlock(original);
- goto retrymasq;
- }
- if (ast_channel_trylock(final_clone)) {
- ast_channel_unlock(final_orig);
- ast_channel_unlock(clone);
- ast_channel_unlock(original);
- goto retrymasq;
- }
- ast_channel_unlock(clone);
- ast_channel_unlock(original);
- original = final_orig;
- clone = final_clone;
- }
-
- if (original == clone) {
- ast_log(LOG_WARNING, "Can't masquerade channel '%s' into itself!\n", original->name);
- ast_channel_unlock(clone);
- ast_channel_unlock(original);
- return -1;
- }
-
- if (option_debug)
- ast_log(LOG_DEBUG, "Planning to masquerade channel %s into the structure of %s\n",
- clone->name, original->name);
- if (original->masq) {
- ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
- original->masq->name, original->name);
- } else if (clone->masqr) {
- ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
- clone->name, clone->masqr->name);
- } else {
- original->masq = clone;
- clone->masqr = original;
- ast_queue_frame(original, &ast_null_frame);
- ast_queue_frame(clone, &ast_null_frame);
- if (option_debug)
- ast_log(LOG_DEBUG, "Done planning to masquerade channel %s into the structure of %s\n", clone->name, original->name);
- res = 0;
- }
-
- ast_channel_unlock(clone);
- ast_channel_unlock(original);
-
- return res;
-}
-
-void ast_change_name(struct ast_channel *chan, char *newname)
-{
- manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", chan->name, newname, chan->uniqueid);
- ast_string_field_set(chan, name, newname);
-}
-
-void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
-{
- struct ast_var_t *current, *newvar;
- const char *varname;
-
- AST_LIST_TRAVERSE(&parent->varshead, current, entries) {
- int vartype = 0;
-
- varname = ast_var_full_name(current);
- if (!varname)
- continue;
-
- if (varname[0] == '_') {
- vartype = 1;
- if (varname[1] == '_')
- vartype = 2;
- }
-
- switch (vartype) {
- case 1:
- newvar = ast_var_assign(&varname[1], ast_var_value(current));
- if (newvar) {
- AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries);
- if (option_debug)
- ast_log(LOG_DEBUG, "Copying soft-transferable variable %s.\n", ast_var_name(newvar));
- }
- break;
- case 2:
- newvar = ast_var_assign(ast_var_full_name(current), ast_var_value(current));
- if (newvar) {
- AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries);
- if (option_debug)
- ast_log(LOG_DEBUG, "Copying hard-transferable variable %s.\n", ast_var_name(newvar));
- }
- break;
- default:
- if (option_debug)
- ast_log(LOG_DEBUG, "Not copying variable %s.\n", ast_var_name(current));
- break;
- }
- }
-}
-
-/*!
- \brief Clone channel variables from 'clone' channel into 'original' channel
-
- All variables except those related to app_groupcount are cloned.
- Variables are actually _removed_ from 'clone' channel, presumably
- because it will subsequently be destroyed.
-
- \note Assumes locks will be in place on both channels when called.
-*/
-static void clone_variables(struct ast_channel *original, struct ast_channel *clone)
-{
- struct ast_var_t *current, *newvar;
- /* Append variables from clone channel into original channel */
- /* XXX Is this always correct? We have to in order to keep MACROS working XXX */
- if (AST_LIST_FIRST(&clone->varshead))
- AST_LIST_APPEND_LIST(&original->varshead, &clone->varshead, entries);
-
- /* then, dup the varshead list into the clone */
-
- AST_LIST_TRAVERSE(&original->varshead, current, entries) {
- newvar = ast_var_assign(current->name, current->value);
- if (newvar)
- AST_LIST_INSERT_TAIL(&clone->varshead, newvar, entries);
- }
-}
-
-/*!
- \brief Masquerade a channel
-
- \note Assumes channel will be locked when called
-*/
-int ast_do_masquerade(struct ast_channel *original)
-{
- int x,i;
- int res=0;
- int origstate;
- struct ast_frame *cur;
- const struct ast_channel_tech *t;
- void *t_pvt;
- struct ast_callerid tmpcid;
- struct ast_channel *clone = original->masq;
- struct ast_cdr *cdr;
- int rformat = original->readformat;
- int wformat = original->writeformat;
- char newn[100];
- char orig[100];
- char masqn[100];
- char zombn[100];
-
- if (option_debug > 3)
- ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
- clone->name, clone->_state, original->name, original->_state);
-
- /* XXX This is a seriously wacked out operation. We're essentially putting the guts of
- the clone channel into the original channel. Start by killing off the original
- channel's backend. I'm not sure we're going to keep this function, because
- while the features are nice, the cost is very high in terms of pure nastiness. XXX */
-
- /* We need the clone's lock, too */
- ast_channel_lock(clone);
-
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "Got clone lock for masquerade on '%s' at %p\n", clone->name, &clone->lock);
-
- /* Having remembered the original read/write formats, we turn off any translation on either
- one */
- free_translation(clone);
- free_translation(original);
-
-
- /* Unlink the masquerade */
- original->masq = NULL;
- clone->masqr = NULL;
-
- /* Save the original name */
- ast_copy_string(orig, original->name, sizeof(orig));
- /* Save the new name */
- ast_copy_string(newn, clone->name, sizeof(newn));
- /* Create the masq name */
- snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn);
-
- /* Copy the name from the clone channel */
- ast_string_field_set(original, name, newn);
-
- /* Mangle the name of the clone channel */
- ast_string_field_set(clone, name, masqn);
-
- /* Notify any managers of the change, first the masq then the other */
- manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
- manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
-
- /* Swap the technologies */
- t = original->tech;
- original->tech = clone->tech;
- clone->tech = t;
-
- /* Swap the cdrs */
- cdr = original->cdr;
- original->cdr = clone->cdr;
- clone->cdr = cdr;
-
- t_pvt = original->tech_pvt;
- original->tech_pvt = clone->tech_pvt;
- clone->tech_pvt = t_pvt;
-
- /* Swap the alertpipes */
- for (i = 0; i < 2; i++) {
- x = original->alertpipe[i];
- original->alertpipe[i] = clone->alertpipe[i];
- clone->alertpipe[i] = x;
- }
-
- /*
- * Swap the readq's. The end result should be this:
- *
- * 1) All frames should be on the new (original) channel.
- * 2) Any frames that were already on the new channel before this
- * masquerade need to be at the end of the readq, after all of the
- * frames on the old (clone) channel.
- * 3) The alertpipe needs to get poked for every frame that was already
- * on the new channel, since we are now using the alert pipe from the
- * old (clone) channel.
- */
- {
- AST_LIST_HEAD_NOLOCK(, ast_frame) tmp_readq;
- AST_LIST_HEAD_SET_NOLOCK(&tmp_readq, NULL);
-
- AST_LIST_APPEND_LIST(&tmp_readq, &original->readq, frame_list);
- AST_LIST_APPEND_LIST(&original->readq, &clone->readq, frame_list);
-
- while ((cur = AST_LIST_REMOVE_HEAD(&tmp_readq, frame_list))) {
- AST_LIST_INSERT_TAIL(&original->readq, cur, frame_list);
- if (original->alertpipe[1] > -1) {
- int poke = 0;
-
- if (write(original->alertpipe[1], &poke, sizeof(poke)) < 0) {
- ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
- }
- }
- }
- }
-
- /* Swap the raw formats */
- x = original->rawreadformat;
- original->rawreadformat = clone->rawreadformat;
- clone->rawreadformat = x;
- x = original->rawwriteformat;
- original->rawwriteformat = clone->rawwriteformat;
- clone->rawwriteformat = x;
-
- clone->_softhangup = AST_SOFTHANGUP_DEV;
-
- /* And of course, so does our current state. Note we need not
- call ast_setstate since the event manager doesn't really consider
- these separate. We do this early so that the clone has the proper
- state of the original channel. */
- origstate = original->_state;
- original->_state = clone->_state;
- clone->_state = origstate;
-
- if (clone->tech->fixup){
- res = clone->tech->fixup(original, clone);
- if (res)
- ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
- }
-
- /* Start by disconnecting the original's physical side */
- if (clone->tech->hangup)
- res = clone->tech->hangup(clone);
- if (res) {
- ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n");
- ast_channel_unlock(clone);
- return -1;
- }
-
- snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig);
- /* Mangle the name of the clone channel */
- ast_string_field_set(clone, name, zombn);
- manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid);
-
- /* Update the type. */
- t_pvt = original->monitor;
- original->monitor = clone->monitor;
- clone->monitor = t_pvt;
-
- /* Keep the same language. */
- ast_string_field_set(original, language, clone->language);
- /* Copy the FD's other than the generator fd */
- for (x = 0; x < AST_MAX_FDS; x++) {
- if (x != AST_GENERATOR_FD)
- original->fds[x] = clone->fds[x];
- }
-
- ast_app_group_update(clone, original);
- /* Move data stores over */
- if (AST_LIST_FIRST(&clone->datastores)) {
- struct ast_datastore *ds;
- AST_LIST_TRAVERSE(&clone->datastores, ds, entry) {
- if (ds->info->chan_fixup)
- ds->info->chan_fixup(ds->data, clone, original);
- }
- AST_LIST_APPEND_LIST(&original->datastores, &clone->datastores, entry);
- }
-
- clone_variables(original, clone);
- /* Presense of ADSI capable CPE follows clone */
- original->adsicpe = clone->adsicpe;
- /* Bridge remains the same */
- /* CDR fields remain the same */
- /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */
- /* Application and data remain the same */
- /* Clone exception becomes real one, as with fdno */
- ast_copy_flags(original, clone, AST_FLAG_EXCEPTION | AST_FLAG_OUTGOING);
- original->fdno = clone->fdno;
- /* Schedule context remains the same */
- /* Stream stuff stays the same */
- /* Keep the original state. The fixup code will need to work with it most likely */
-
- /* Just swap the whole structures, nevermind the allocations, they'll work themselves
- out. */
- tmpcid = original->cid;
- original->cid = clone->cid;
- clone->cid = tmpcid;
-
- /* Restore original timing file descriptor */
- original->fds[AST_TIMING_FD] = original->timingfd;
-
- /* Our native formats are different now */
- original->nativeformats = clone->nativeformats;
-
- /* Context, extension, priority, app data, jump table, remain the same */
- /* pvt switches. pbx stays the same, as does next */
-
- /* Set the write format */
- ast_set_write_format(original, wformat);
-
- /* Set the read format */
- ast_set_read_format(original, rformat);
-
- /* Copy the music class */
- ast_string_field_set(original, musicclass, clone->musicclass);
-
- if (option_debug)
- ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat);
-
- /* Okay. Last thing is to let the channel driver know about all this mess, so he
- can fix up everything as best as possible */
- if (original->tech->fixup) {
- res = original->tech->fixup(clone, original);
- if (res) {
- ast_log(LOG_WARNING, "Channel for type '%s' could not fixup channel %s\n",
- original->tech->type, original->name);
- ast_channel_unlock(clone);
- return -1;
- }
- } else
- ast_log(LOG_WARNING, "Channel type '%s' does not have a fixup routine (for %s)! Bad things may happen.\n",
- original->tech->type, original->name);
-
- /*
- * If an indication is currently playing, maintain it on the channel
- * that is taking the place of original
- *
- * This is needed because the masquerade is swapping out in the internals
- * of this channel, and the new channel private data needs to be made
- * aware of the current visible indication (RINGING, CONGESTION, etc.)
- */
- if (original->visible_indication) {
- ast_indicate(original, original->visible_indication);
- }
-
- /* Now, at this point, the "clone" channel is totally F'd up. We mark it as
- a zombie so nothing tries to touch it. If it's already been marked as a
- zombie, then free it now (since it already is considered invalid). */
- if (ast_test_flag(clone, AST_FLAG_ZOMBIE)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Destroying channel clone '%s'\n", clone->name);
- ast_channel_unlock(clone);
- manager_event(EVENT_FLAG_CALL, "Hangup",
- "Channel: %s\r\n"
- "Uniqueid: %s\r\n"
- "Cause: %d\r\n"
- "Cause-txt: %s\r\n",
- clone->name,
- clone->uniqueid,
- clone->hangupcause,
- ast_cause2str(clone->hangupcause)
- );
- ast_channel_free(clone);
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name);
- ast_set_flag(clone, AST_FLAG_ZOMBIE);
- ast_queue_frame(clone, &ast_null_frame);
- ast_channel_unlock(clone);
- }
-
- /* Signal any blocker */
- if (ast_test_flag(original, AST_FLAG_BLOCKING))
- pthread_kill(original->blocker, SIGURG);
- if (option_debug)
- ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n", original->name, original->_state);
- return 0;
-}
-
-void ast_set_callerid(struct ast_channel *chan, const char *callerid, const char *calleridname, const char *ani)
-{
- ast_channel_lock(chan);
-
- if (callerid) {
- if (chan->cid.cid_num)
- free(chan->cid.cid_num);
- chan->cid.cid_num = ast_strdup(callerid);
- }
- if (calleridname) {
- if (chan->cid.cid_name)
- free(chan->cid.cid_name);
- chan->cid.cid_name = ast_strdup(calleridname);
- }
- if (ani) {
- if (chan->cid.cid_ani)
- free(chan->cid.cid_ani);
- chan->cid.cid_ani = ast_strdup(ani);
- }
- manager_event(EVENT_FLAG_CALL, "Newcallerid",
- "Channel: %s\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n"
- "Uniqueid: %s\r\n"
- "CID-CallingPres: %d (%s)\r\n",
- chan->name,
- S_OR(chan->cid.cid_num, "<Unknown>"),
- S_OR(chan->cid.cid_name, "<Unknown>"),
- chan->uniqueid,
- chan->cid.cid_pres,
- ast_describe_caller_presentation(chan->cid.cid_pres)
- );
-
- ast_channel_unlock(chan);
-}
-
-int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
-{
- char name[AST_CHANNEL_NAME], *dashptr;
- int oldstate = chan->_state;
-
- if (oldstate == state)
- return 0;
-
- ast_copy_string(name, chan->name, sizeof(name));
- if ((dashptr = strrchr(name, '-'))) {
- *dashptr = '\0';
- }
-
- chan->_state = state;
- ast_device_state_changed_literal(name);
- /* setstate used to conditionally report Newchannel; this is no more */
- manager_event(EVENT_FLAG_CALL,
- "Newstate",
- "Channel: %s\r\n"
- "State: %s\r\n"
- "CallerID: %s\r\n"
- "CallerIDName: %s\r\n"
- "Uniqueid: %s\r\n",
- chan->name, ast_state2str(chan->_state),
- S_OR(chan->cid.cid_num, "<unknown>"),
- S_OR(chan->cid.cid_name, "<unknown>"),
- chan->uniqueid);
-
- return 0;
-}
-
-/*! \brief Find bridged channel */
-struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
-{
- struct ast_channel *bridged;
- bridged = chan->_bridge;
- if (bridged && bridged->tech->bridged_channel)
- bridged = bridged->tech->bridged_channel(chan, bridged);
- return bridged;
-}
-
-static void bridge_playfile(struct ast_channel *chan, struct ast_channel *peer, const char *sound, int remain)
-{
- int min = 0, sec = 0, check;
-
- check = ast_autoservice_start(peer);
- if (check)
- return;
-
- if (remain > 0) {
- if (remain / 60 > 1) {
- min = remain / 60;
- sec = remain % 60;
- } else {
- sec = remain;
- }
- }
-
- if (!strcmp(sound,"timeleft")) { /* Queue support */
- ast_stream_and_wait(chan, "vm-youhave", chan->language, "");
- if (min) {
- ast_say_number(chan, min, AST_DIGIT_ANY, chan->language, NULL);
- ast_stream_and_wait(chan, "queue-minutes", chan->language, "");
- }
- if (sec) {
- ast_say_number(chan, sec, AST_DIGIT_ANY, chan->language, NULL);
- ast_stream_and_wait(chan, "queue-seconds", chan->language, "");
- }
- } else {
- ast_stream_and_wait(chan, sound, chan->language, "");
- }
-
- ast_autoservice_stop(peer);
-}
-
-static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct ast_channel *c1,
- struct ast_bridge_config *config, struct ast_frame **fo,
- struct ast_channel **rc, struct timeval bridge_end)
-{
- /* Copy voice back and forth between the two channels. */
- struct ast_channel *cs[3];
- struct ast_frame *f;
- enum ast_bridge_result res = AST_BRIDGE_COMPLETE;
- int o0nativeformats;
- int o1nativeformats;
- int watch_c0_dtmf;
- int watch_c1_dtmf;
- void *pvt0, *pvt1;
- /* Indicates whether a frame was queued into a jitterbuffer */
- int frame_put_in_jb = 0;
- int jb_in_use;
- int to;
-
- cs[0] = c0;
- cs[1] = c1;
- pvt0 = c0->tech_pvt;
- pvt1 = c1->tech_pvt;
- o0nativeformats = c0->nativeformats;
- o1nativeformats = c1->nativeformats;
- watch_c0_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_0;
- watch_c1_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_1;
-
- /* Check the need of a jitterbuffer for each channel */
- jb_in_use = ast_jb_do_usecheck(c0, c1);
- if (jb_in_use)
- ast_jb_empty_and_reset(c0, c1);
-
- for (;;) {
- struct ast_channel *who, *other;
-
- if ((c0->tech_pvt != pvt0) || (c1->tech_pvt != pvt1) ||
- (o0nativeformats != c0->nativeformats) ||
- (o1nativeformats != c1->nativeformats)) {
- /* Check for Masquerade, codec changes, etc */
- res = AST_BRIDGE_RETRY;
- break;
- }
- if (bridge_end.tv_sec) {
- to = ast_tvdiff_ms(bridge_end, ast_tvnow());
- if (to <= 0) {
- if (config->timelimit)
- res = AST_BRIDGE_RETRY;
- else
- res = AST_BRIDGE_COMPLETE;
- break;
- }
- } else
- to = -1;
- /* Calculate the appropriate max sleep interval - in general, this is the time,
- left to the closest jb delivery moment */
- if (jb_in_use)
- to = ast_jb_get_when_to_wakeup(c0, c1, to);
- who = ast_waitfor_n(cs, 2, &to);
- if (!who) {
- /* No frame received within the specified timeout - check if we have to deliver now */
- if (jb_in_use)
- ast_jb_get_and_deliver(c0, c1);
- if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
- if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
- c0->_softhangup = 0;
- if (c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
- c1->_softhangup = 0;
- c0->_bridge = c1;
- c1->_bridge = c0;
- }
- continue;
- }
- f = ast_read(who);
- if (!f) {
- *fo = NULL;
- *rc = who;
- if (option_debug)
- ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
- break;
- }
-
- other = (who == c0) ? c1 : c0; /* the 'other' channel */
- /* Try add the frame info the who's bridged channel jitterbuff */
- if (jb_in_use)
- frame_put_in_jb = !ast_jb_put(other, f);
-
- if ((f->frametype == AST_FRAME_CONTROL) && !(config->flags & AST_BRIDGE_IGNORE_SIGS)) {
- int bridge_exit = 0;
-
- switch (f->subclass) {
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
- case AST_CONTROL_VIDUPDATE:
- case AST_CONTROL_SRCUPDATE:
- ast_indicate_data(other, f->subclass, f->data, f->datalen);
- if (jb_in_use) {
- ast_jb_empty_and_reset(c0, c1);
- }
- break;
- default:
- *fo = f;
- *rc = who;
- bridge_exit = 1;
- if (option_debug)
- ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
- break;
- }
- if (bridge_exit)
- break;
- }
- if ((f->frametype == AST_FRAME_VOICE) ||
- (f->frametype == AST_FRAME_DTMF_BEGIN) ||
- (f->frametype == AST_FRAME_DTMF) ||
- (f->frametype == AST_FRAME_VIDEO) ||
- (f->frametype == AST_FRAME_IMAGE) ||
- (f->frametype == AST_FRAME_HTML) ||
- (f->frametype == AST_FRAME_MODEM) ||
- (f->frametype == AST_FRAME_TEXT)) {
- /* monitored dtmf causes exit from bridge */
- int monitored_source = (who == c0) ? watch_c0_dtmf : watch_c1_dtmf;
-
- if (monitored_source &&
- (f->frametype == AST_FRAME_DTMF_END ||
- f->frametype == AST_FRAME_DTMF_BEGIN)) {
- *fo = f;
- *rc = who;
- if (option_debug)
- ast_log(LOG_DEBUG, "Got DTMF %s on channel (%s)\n",
- f->frametype == AST_FRAME_DTMF_END ? "end" : "begin",
- who->name);
- break;
- }
- /* Write immediately frames, not passed through jb */
- if (!frame_put_in_jb)
- ast_write(other, f);
-
- /* Check if we have to deliver now */
- if (jb_in_use)
- ast_jb_get_and_deliver(c0, c1);
- }
- /* XXX do we want to pass on also frames not matched above ? */
- ast_frfree(f);
-
- /* Swap who gets priority */
- cs[2] = cs[0];
- cs[0] = cs[1];
- cs[1] = cs[2];
- }
- return res;
-}
-
-/*! \brief Bridge two channels together */
-enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1,
- struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
-{
- struct ast_channel *who = NULL;
- enum ast_bridge_result res = AST_BRIDGE_COMPLETE;
- int nativefailed=0;
- int firstpass;
- int o0nativeformats;
- int o1nativeformats;
- long time_left_ms=0;
- struct timeval nexteventts = { 0, };
- char caller_warning = 0;
- char callee_warning = 0;
-
- if (c0->_bridge) {
- ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
- c0->name, c0->_bridge->name);
- return -1;
- }
- if (c1->_bridge) {
- ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
- c1->name, c1->_bridge->name);
- return -1;
- }
-
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
- ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1))
- return -1;
-
- *fo = NULL;
- firstpass = config->firstpass;
- config->firstpass = 0;
-
- if (ast_tvzero(config->start_time))
- config->start_time = ast_tvnow();
- time_left_ms = config->timelimit;
-
- caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING);
- callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING);
-
- if (config->start_sound && firstpass) {
- if (caller_warning)
- bridge_playfile(c0, c1, config->start_sound, time_left_ms / 1000);
- if (callee_warning)
- bridge_playfile(c1, c0, config->start_sound, time_left_ms / 1000);
- }
-
- /* Keep track of bridge */
- c0->_bridge = c1;
- c1->_bridge = c0;
-
- /* \todo XXX here should check that cid_num is not NULL */
- manager_event(EVENT_FLAG_CALL, "Link",
- "Channel1: %s\r\n"
- "Channel2: %s\r\n"
- "Uniqueid1: %s\r\n"
- "Uniqueid2: %s\r\n"
- "CallerID1: %s\r\n"
- "CallerID2: %s\r\n",
- c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num);
-
- o0nativeformats = c0->nativeformats;
- o1nativeformats = c1->nativeformats;
-
- if (config->feature_timer) {
- nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->feature_timer, 1000));
- } else if (config->timelimit) {
- nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
- if (caller_warning || callee_warning)
- nexteventts = ast_tvsub(nexteventts, ast_samp2tv(config->play_warning, 1000));
- }
-
- if (!c0->tech->send_digit_begin)
- ast_set_flag(c1, AST_FLAG_END_DTMF_ONLY);
- if (!c1->tech->send_digit_begin)
- ast_set_flag(c0, AST_FLAG_END_DTMF_ONLY);
-
- /* Before we enter in and bridge these two together tell them both the source of audio has changed */
- ast_indicate(c0, AST_CONTROL_SRCUPDATE);
- ast_indicate(c1, AST_CONTROL_SRCUPDATE);
-
- for (/* ever */;;) {
- struct timeval now = { 0, };
- int to;
-
- to = -1;
-
- if (!ast_tvzero(nexteventts)) {
- now = ast_tvnow();
- to = ast_tvdiff_ms(nexteventts, now);
- if (to <= 0) {
- if (!config->timelimit) {
- res = AST_BRIDGE_COMPLETE;
- break;
- }
- to = 0;
- }
- }
-
- if (config->timelimit) {
- time_left_ms = config->timelimit - ast_tvdiff_ms(now, config->start_time);
- if (time_left_ms < to)
- to = time_left_ms;
-
- if (time_left_ms <= 0) {
- if (caller_warning && config->end_sound)
- bridge_playfile(c0, c1, config->end_sound, 0);
- if (callee_warning && config->end_sound)
- bridge_playfile(c1, c0, config->end_sound, 0);
- *fo = NULL;
- if (who)
- *rc = who;
- res = 0;
- break;
- }
-
- if (!to) {
- if (time_left_ms >= 5000 && config->warning_sound && config->play_warning) {
- int t = (time_left_ms + 500) / 1000; /* round to nearest second */
- if (caller_warning)
- bridge_playfile(c0, c1, config->warning_sound, t);
- if (callee_warning)
- bridge_playfile(c1, c0, config->warning_sound, t);
- }
- if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000)))
- nexteventts = ast_tvadd(nexteventts, ast_samp2tv(config->warning_freq, 1000));
- else
- nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
- }
- }
-
- if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
- if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
- c0->_softhangup = 0;
- if (c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
- c1->_softhangup = 0;
- c0->_bridge = c1;
- c1->_bridge = c0;
- if (option_debug)
- ast_log(LOG_DEBUG, "Unbridge signal received. Ending native bridge.\n");
- continue;
- }
-
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
- ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) {
- *fo = NULL;
- if (who)
- *rc = who;
- res = 0;
- if (option_debug)
- ast_log(LOG_DEBUG, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",
- c0->name, c1->name,
- ast_test_flag(c0, AST_FLAG_ZOMBIE) ? "Yes" : "No",
- ast_check_hangup(c0) ? "Yes" : "No",
- ast_test_flag(c1, AST_FLAG_ZOMBIE) ? "Yes" : "No",
- ast_check_hangup(c1) ? "Yes" : "No");
- break;
- }
-
- /* See if the BRIDGEPEER variable needs to be updated */
- if (!ast_strlen_zero(pbx_builtin_getvar_helper(c0, "BRIDGEPEER")))
- pbx_builtin_setvar_helper(c0, "BRIDGEPEER", c1->name);
- if (!ast_strlen_zero(pbx_builtin_getvar_helper(c1, "BRIDGEPEER")))
- pbx_builtin_setvar_helper(c1, "BRIDGEPEER", c0->name);
-
- if (c0->tech->bridge &&
- (config->timelimit == 0) &&
- (c0->tech->bridge == c1->tech->bridge) &&
- !nativefailed && !c0->monitor && !c1->monitor &&
- !c0->audiohooks && !c1->audiohooks && !ast_test_flag(&(config->features_callee),AST_FEATURE_REDIRECT) &&
- !ast_test_flag(&(config->features_caller),AST_FEATURE_REDIRECT) &&
- !c0->masq && !c0->masqr && !c1->masq && !c1->masqr) {
- /* Looks like they share a bridge method and nothing else is in the way */
- ast_set_flag(c0, AST_FLAG_NBRIDGE);
- ast_set_flag(c1, AST_FLAG_NBRIDGE);
- if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, to)) == AST_BRIDGE_COMPLETE) {
- /* \todo XXX here should check that cid_num is not NULL */
- manager_event(EVENT_FLAG_CALL, "Unlink",
- "Channel1: %s\r\n"
- "Channel2: %s\r\n"
- "Uniqueid1: %s\r\n"
- "Uniqueid2: %s\r\n"
- "CallerID1: %s\r\n"
- "CallerID2: %s\r\n",
- c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num);
- if (option_debug)
- ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n", c0->name, c1->name);
-
- ast_clear_flag(c0, AST_FLAG_NBRIDGE);
- ast_clear_flag(c1, AST_FLAG_NBRIDGE);
-
- if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
- continue;
-
- c0->_bridge = NULL;
- c1->_bridge = NULL;
-
- return res;
- } else {
- ast_clear_flag(c0, AST_FLAG_NBRIDGE);
- ast_clear_flag(c1, AST_FLAG_NBRIDGE);
- }
- switch (res) {
- case AST_BRIDGE_RETRY:
- continue;
- default:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s ended\n",
- c0->name, c1->name);
- /* fallthrough */
- case AST_BRIDGE_FAILED_NOWARN:
- nativefailed++;
- break;
- }
- }
-
- if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) ||
- (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) &&
- !(c0->generator || c1->generator)) {
- if (ast_channel_make_compatible(c0, c1)) {
- ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
- /* \todo XXX here should check that cid_num is not NULL */
- manager_event(EVENT_FLAG_CALL, "Unlink",
- "Channel1: %s\r\n"
- "Channel2: %s\r\n"
- "Uniqueid1: %s\r\n"
- "Uniqueid2: %s\r\n"
- "CallerID1: %s\r\n"
- "CallerID2: %s\r\n",
- c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num);
- return AST_BRIDGE_FAILED;
- }
- o0nativeformats = c0->nativeformats;
- o1nativeformats = c1->nativeformats;
- }
-
- if (!ast_strlen_zero(pbx_builtin_getvar_helper(c0, "BRIDGEPEER")))
- pbx_builtin_setvar_helper(c0, "BRIDGEPEER", c1->name);
- if (!ast_strlen_zero(pbx_builtin_getvar_helper(c1, "BRIDGEPEER")))
- pbx_builtin_setvar_helper(c1, "BRIDGEPEER", c0->name);
-
- res = ast_generic_bridge(c0, c1, config, fo, rc, nexteventts);
- if (res != AST_BRIDGE_RETRY)
- break;
- }
-
- ast_clear_flag(c0, AST_FLAG_END_DTMF_ONLY);
- ast_clear_flag(c1, AST_FLAG_END_DTMF_ONLY);
-
- /* Now that we have broken the bridge the source will change yet again */
- ast_indicate(c0, AST_CONTROL_SRCUPDATE);
- ast_indicate(c1, AST_CONTROL_SRCUPDATE);
-
- c0->_bridge = NULL;
- c1->_bridge = NULL;
-
- /* \todo XXX here should check that cid_num is not NULL */
- manager_event(EVENT_FLAG_CALL, "Unlink",
- "Channel1: %s\r\n"
- "Channel2: %s\r\n"
- "Uniqueid1: %s\r\n"
- "Uniqueid2: %s\r\n"
- "CallerID1: %s\r\n"
- "CallerID2: %s\r\n",
- c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num);
- if (option_debug)
- ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n", c0->name, c1->name);
-
- return res;
-}
-
-/*! \brief Sets an option on a channel */
-int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int datalen, int block)
-{
- int res;
-
- if (chan->tech->setoption) {
- res = chan->tech->setoption(chan, option, data, datalen);
- if (res < 0)
- return res;
- } else {
- errno = ENOSYS;
- return -1;
- }
- if (block) {
- /* XXX Implement blocking -- just wait for our option frame reply, discarding
- intermediate packets. XXX */
- ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
- return -1;
- }
- return 0;
-}
-
-struct tonepair_def {
- int freq1;
- int freq2;
- int duration;
- int vol;
-};
-
-struct tonepair_state {
- int fac1;
- int fac2;
- int v1_1;
- int v2_1;
- int v3_1;
- int v1_2;
- int v2_2;
- int v3_2;
- int origwfmt;
- int pos;
- int duration;
- int modulate;
- struct ast_frame f;
- unsigned char offset[AST_FRIENDLY_OFFSET];
- short data[4000];
-};
-
-static void tonepair_release(struct ast_channel *chan, void *params)
-{
- struct tonepair_state *ts = params;
-
- if (chan)
- ast_set_write_format(chan, ts->origwfmt);
- free(ts);
-}
-
-static void *tonepair_alloc(struct ast_channel *chan, void *params)
-{
- struct tonepair_state *ts;
- struct tonepair_def *td = params;
-
- if (!(ts = ast_calloc(1, sizeof(*ts))))
- return NULL;
- ts->origwfmt = chan->writeformat;
- if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
- ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
- tonepair_release(NULL, ts);
- ts = NULL;
- } else {
- ts->fac1 = 2.0 * cos(2.0 * M_PI * (td->freq1 / 8000.0)) * 32768.0;
- ts->v1_1 = 0;
- ts->v2_1 = sin(-4.0 * M_PI * (td->freq1 / 8000.0)) * td->vol;
- ts->v3_1 = sin(-2.0 * M_PI * (td->freq1 / 8000.0)) * td->vol;
- ts->v2_1 = 0;
- ts->fac2 = 2.0 * cos(2.0 * M_PI * (td->freq2 / 8000.0)) * 32768.0;
- ts->v2_2 = sin(-4.0 * M_PI * (td->freq2 / 8000.0)) * td->vol;
- ts->v3_2 = sin(-2.0 * M_PI * (td->freq2 / 8000.0)) * td->vol;
- ts->duration = td->duration;
- ts->modulate = 0;
- }
- /* Let interrupts interrupt :) */
- ast_set_flag(chan, AST_FLAG_WRITE_INT);
- return ts;
-}
-
-static int tonepair_generator(struct ast_channel *chan, void *data, int len, int samples)
-{
- struct tonepair_state *ts = data;
- int x;
-
- /* we need to prepare a frame with 16 * timelen samples as we're
- * generating SLIN audio
- */
- len = samples * 2;
-
- if (len > sizeof(ts->data) / 2 - 1) {
- ast_log(LOG_WARNING, "Can't generate that much data!\n");
- return -1;
- }
- memset(&ts->f, 0, sizeof(ts->f));
- for (x=0;x<len/2;x++) {
- ts->v1_1 = ts->v2_1;
- ts->v2_1 = ts->v3_1;
- ts->v3_1 = (ts->fac1 * ts->v2_1 >> 15) - ts->v1_1;
-
- ts->v1_2 = ts->v2_2;
- ts->v2_2 = ts->v3_2;
- ts->v3_2 = (ts->fac2 * ts->v2_2 >> 15) - ts->v1_2;
- if (ts->modulate) {
- int p;
- p = ts->v3_2 - 32768;
- if (p < 0) p = -p;
- p = ((p * 9) / 10) + 1;
- ts->data[x] = (ts->v3_1 * p) >> 15;
- } else
- ts->data[x] = ts->v3_1 + ts->v3_2;
- }
- ts->f.frametype = AST_FRAME_VOICE;
- ts->f.subclass = AST_FORMAT_SLINEAR;
- ts->f.datalen = len;
- ts->f.samples = samples;
- ts->f.offset = AST_FRIENDLY_OFFSET;
- ts->f.data = ts->data;
- ast_write(chan, &ts->f);
- ts->pos += x;
- if (ts->duration > 0) {
- if (ts->pos >= ts->duration * 8)
- return -1;
- }
- return 0;
-}
-
-static struct ast_generator tonepair = {
- alloc: tonepair_alloc,
- release: tonepair_release,
- generate: tonepair_generator,
-};
-
-int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
-{
- struct tonepair_def d = { 0, };
-
- d.freq1 = freq1;
- d.freq2 = freq2;
- d.duration = duration;
- d.vol = (vol < 1) ? 8192 : vol; /* force invalid to 8192 */
- if (ast_activate_generator(chan, &tonepair, &d))
- return -1;
- return 0;
-}
-
-void ast_tonepair_stop(struct ast_channel *chan)
-{
- ast_deactivate_generator(chan);
-}
-
-int ast_tonepair(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
-{
- int res;
-
- if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
- return res;
-
- /* Give us some wiggle room */
- while (chan->generatordata && ast_waitfor(chan, 100) >= 0) {
- struct ast_frame *f = ast_read(chan);
- if (f)
- ast_frfree(f);
- else
- return -1;
- }
- return 0;
-}
-
-ast_group_t ast_get_group(const char *s)
-{
- char *piece;
- char *c;
- int start=0, finish=0, x;
- ast_group_t group = 0;
-
- if (ast_strlen_zero(s))
- return 0;
-
- c = ast_strdupa(s);
-
- while ((piece = strsep(&c, ","))) {
- if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
- /* Range */
- } else if (sscanf(piece, "%d", &start)) {
- /* Just one */
- finish = start;
- } else {
- ast_log(LOG_ERROR, "Syntax error parsing group configuration '%s' at '%s'. Ignoring.\n", s, piece);
- continue;
- }
- for (x = start; x <= finish; x++) {
- if ((x > 63) || (x < 0)) {
- ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 63)\n", x);
- } else
- group |= ((ast_group_t) 1 << x);
- }
- }
- return group;
-}
-
-static int (*ast_moh_start_ptr)(struct ast_channel *, const char *, const char *) = NULL;
-static void (*ast_moh_stop_ptr)(struct ast_channel *) = NULL;
-static void (*ast_moh_cleanup_ptr)(struct ast_channel *) = NULL;
-
-void ast_install_music_functions(int (*start_ptr)(struct ast_channel *, const char *, const char *),
- void (*stop_ptr)(struct ast_channel *),
- void (*cleanup_ptr)(struct ast_channel *))
-{
- ast_moh_start_ptr = start_ptr;
- ast_moh_stop_ptr = stop_ptr;
- ast_moh_cleanup_ptr = cleanup_ptr;
-}
-
-void ast_uninstall_music_functions(void)
-{
- ast_moh_start_ptr = NULL;
- ast_moh_stop_ptr = NULL;
- ast_moh_cleanup_ptr = NULL;
-}
-
-/*! \brief Turn on music on hold on a given channel */
-int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
-{
- if (ast_moh_start_ptr)
- return ast_moh_start_ptr(chan, mclass, interpclass);
-
- if (option_verbose > 2) {
- ast_verbose(VERBOSE_PREFIX_3 "Music class %s requested but no musiconhold loaded.\n",
- mclass ? mclass : (interpclass ? interpclass : "default"));
- }
-
- return 0;
-}
-
-/*! \brief Turn off music on hold on a given channel */
-void ast_moh_stop(struct ast_channel *chan)
-{
- if (ast_moh_stop_ptr)
- ast_moh_stop_ptr(chan);
-}
-
-void ast_moh_cleanup(struct ast_channel *chan)
-{
- if (ast_moh_cleanup_ptr)
- ast_moh_cleanup_ptr(chan);
-}
-
-void ast_channels_init(void)
-{
- ast_cli_register_multiple(cli_channel, sizeof(cli_channel) / sizeof(struct ast_cli_entry));
-}
-
-/*! \brief Print call group and pickup group ---*/
-char *ast_print_group(char *buf, int buflen, ast_group_t group)
-{
- unsigned int i;
- int first=1;
- char num[3];
-
- buf[0] = '\0';
-
- if (!group) /* Return empty string if no group */
- return buf;
-
- for (i = 0; i <= 63; i++) { /* Max group is 63 */
- if (group & ((ast_group_t) 1 << i)) {
- if (!first) {
- strncat(buf, ", ", buflen - strlen(buf) - 1);
- } else {
- first=0;
- }
- snprintf(num, sizeof(num), "%u", i);
- strncat(buf, num, buflen - strlen(buf) - 1);
- }
- }
- return buf;
-}
-
-void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
-{
- struct ast_variable *cur;
-
- for (cur = vars; cur; cur = cur->next)
- pbx_builtin_setvar_helper(chan, cur->name, cur->value);
-}
-
-static void *silence_generator_alloc(struct ast_channel *chan, void *data)
-{
- /* just store the data pointer in the channel structure */
- return data;
-}
-
-static void silence_generator_release(struct ast_channel *chan, void *data)
-{
- /* nothing to do */
-}
-
-static int silence_generator_generate(struct ast_channel *chan, void *data, int len, int samples)
-{
- short buf[samples];
- struct ast_frame frame = {
- .frametype = AST_FRAME_VOICE,
- .subclass = AST_FORMAT_SLINEAR,
- .data = buf,
- .samples = samples,
- .datalen = sizeof(buf),
- };
- memset(buf, 0, sizeof(buf));
- if (ast_write(chan, &frame))
- return -1;
- return 0;
-}
-
-static struct ast_generator silence_generator = {
- .alloc = silence_generator_alloc,
- .release = silence_generator_release,
- .generate = silence_generator_generate,
-};
-
-struct ast_silence_generator {
- int old_write_format;
-};
-
-struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_channel *chan)
-{
- struct ast_silence_generator *state;
-
- if (!(state = ast_calloc(1, sizeof(*state)))) {
- return NULL;
- }
-
- state->old_write_format = chan->writeformat;
-
- if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
- ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n");
- free(state);
- return NULL;
- }
-
- ast_activate_generator(chan, &silence_generator, state);
-
- if (option_debug)
- ast_log(LOG_DEBUG, "Started silence generator on '%s'\n", chan->name);
-
- return state;
-}
-
-void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
-{
- if (!state)
- return;
-
- ast_deactivate_generator(chan);
-
- if (option_debug)
- ast_log(LOG_DEBUG, "Stopped silence generator on '%s'\n", chan->name);
-
- if (ast_set_write_format(chan, state->old_write_format) < 0)
- ast_log(LOG_ERROR, "Could not return write format to its original state\n");
-
- free(state);
-}
-
-
-/*! \ brief Convert channel reloadreason (ENUM) to text string for manager event */
-const char *channelreloadreason2txt(enum channelreloadreason reason)
-{
- switch (reason) {
- case CHANNEL_MODULE_LOAD:
- return "LOAD (Channel module load)";
-
- case CHANNEL_MODULE_RELOAD:
- return "RELOAD (Channel module reload)";
-
- case CHANNEL_CLI_RELOAD:
- return "CLIRELOAD (Channel module reload by CLI command)";
-
- default:
- return "MANAGERRELOAD (Channel module reload by manager)";
- }
-};
-
-#ifdef DEBUG_CHANNEL_LOCKS
-
-/*! \brief Unlock AST channel (and print debugging output)
-\note You need to enable DEBUG_CHANNEL_LOCKS for this function
-*/
-int __ast_channel_unlock(struct ast_channel *chan, const char *filename, int lineno, const char *func)
-{
- int res = 0;
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "::::==== Unlocking AST channel %s\n", chan->name);
-
- if (!chan) {
- if (option_debug)
- ast_log(LOG_DEBUG, "::::==== Unlocking non-existing channel \n");
- return 0;
- }
-#ifdef DEBUG_THREADS
- res = __ast_pthread_mutex_unlock(filename, lineno, func, "(channel lock)", &chan->lock);
-#else
- res = ast_mutex_unlock(&chan->lock);
-#endif
-
- if (option_debug > 2) {
-#ifdef DEBUG_THREADS
- int count = 0;
- if ((count = chan->lock.reentrancy))
- ast_log(LOG_DEBUG, ":::=== Still have %d locks (recursive)\n", count);
-#endif
- if (!res)
- if (option_debug)
- ast_log(LOG_DEBUG, "::::==== Channel %s was unlocked\n", chan->name);
- if (res == EINVAL) {
- if (option_debug)
- ast_log(LOG_DEBUG, "::::==== Channel %s had no lock by this thread. Failed unlocking\n", chan->name);
- }
- }
- if (res == EPERM) {
- /* We had no lock, so okay any way*/
- if (option_debug > 3)
- ast_log(LOG_DEBUG, "::::==== Channel %s was not locked at all \n", chan->name);
- res = 0;
- }
- return res;
-}
-
-/*! \brief Lock AST channel (and print debugging output)
-\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
-int __ast_channel_lock(struct ast_channel *chan, const char *filename, int lineno, const char *func)
-{
- int res;
-
- if (option_debug > 3)
- ast_log(LOG_DEBUG, "====:::: Locking AST channel %s\n", chan->name);
-
-#ifdef DEBUG_THREADS
- res = __ast_pthread_mutex_lock(filename, lineno, func, "(channel lock)", &chan->lock);
-#else
- res = ast_mutex_lock(&chan->lock);
-#endif
-
- if (option_debug > 3) {
-#ifdef DEBUG_THREADS
- int count = 0;
- if ((count = chan->lock.reentrancy))
- ast_log(LOG_DEBUG, ":::=== Now have %d locks (recursive)\n", count);
-#endif
- if (!res)
- ast_log(LOG_DEBUG, "::::==== Channel %s was locked\n", chan->name);
- if (res == EDEADLK) {
- /* We had no lock, so okey any way */
- if (option_debug > 3)
- ast_log(LOG_DEBUG, "::::==== Channel %s was not locked by us. Lock would cause deadlock.\n", chan->name);
- }
- if (res == EINVAL) {
- if (option_debug > 3)
- ast_log(LOG_DEBUG, "::::==== Channel %s lock failed. No mutex.\n", chan->name);
- }
- }
- return res;
-}
-
-/*! \brief Lock AST channel (and print debugging output)
-\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
-int __ast_channel_trylock(struct ast_channel *chan, const char *filename, int lineno, const char *func)
-{
- int res;
-
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "====:::: Trying to lock AST channel %s\n", chan->name);
-#ifdef DEBUG_THREADS
- res = __ast_pthread_mutex_trylock(filename, lineno, func, "(channel lock)", &chan->lock);
-#else
- res = ast_mutex_trylock(&chan->lock);
-#endif
-
- if (option_debug > 2) {
-#ifdef DEBUG_THREADS
- int count = 0;
- if ((count = chan->lock.reentrancy))
- ast_log(LOG_DEBUG, ":::=== Now have %d locks (recursive)\n", count);
-#endif
- if (!res)
- ast_log(LOG_DEBUG, "::::==== Channel %s was locked\n", chan->name);
- if (res == EBUSY) {
- /* We failed to lock */
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "::::==== Channel %s failed to lock. Not waiting around...\n", chan->name);
- }
- if (res == EDEADLK) {
- /* We had no lock, so okey any way*/
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "::::==== Channel %s was not locked. Lock would cause deadlock.\n", chan->name);
- }
- if (res == EINVAL && option_debug > 2)
- ast_log(LOG_DEBUG, "::::==== Channel %s lock failed. No mutex.\n", chan->name);
- }
- return res;
-}
-
-#endif
-
-/*
- * Wrappers for various ast_say_*() functions that call the full version
- * of the same functions.
- * The proper place would be say.c, but that file is optional and one
- * must be able to build asterisk even without it (using a loadable 'say'
- * implementation that only supplies the 'full' version of the functions.
- */
-
-int ast_say_number(struct ast_channel *chan, int num,
- const char *ints, const char *language, const char *options)
-{
- return ast_say_number_full(chan, num, ints, language, options, -1, -1);
-}
-
-int ast_say_enumeration(struct ast_channel *chan, int num,
- const char *ints, const char *language, const char *options)
-{
- return ast_say_enumeration_full(chan, num, ints, language, options, -1, -1);
-}
-
-int ast_say_digits(struct ast_channel *chan, int num,
- const char *ints, const char *lang)
-{
- return ast_say_digits_full(chan, num, ints, lang, -1, -1);
-}
-
-int ast_say_digit_str(struct ast_channel *chan, const char *str,
- const char *ints, const char *lang)
-{
- return ast_say_digit_str_full(chan, str, ints, lang, -1, -1);
-}
-
-int ast_say_character_str(struct ast_channel *chan, const char *str,
- const char *ints, const char *lang)
-{
- return ast_say_character_str_full(chan, str, ints, lang, -1, -1);
-}
-
-int ast_say_phonetic_str(struct ast_channel *chan, const char *str,
- const char *ints, const char *lang)
-{
- return ast_say_phonetic_str_full(chan, str, ints, lang, -1, -1);
-}
-
-int ast_say_digits_full(struct ast_channel *chan, int num,
- const char *ints, const char *lang, int audiofd, int ctrlfd)
-{
- char buf[256];
-
- snprintf(buf, sizeof(buf), "%d", num);
- return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd);
-}
-
diff --git a/main/chanvars.c b/main/chanvars.c
deleted file mode 100644
index 7e617c1fb..000000000
--- a/main/chanvars.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Channel Variables
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "asterisk/chanvars.h"
-#include "asterisk/logger.h"
-#include "asterisk/strings.h"
-#include "asterisk/utils.h"
-
-struct ast_var_t *ast_var_assign(const char *name, const char *value)
-{
- struct ast_var_t *var;
- int name_len = strlen(name) + 1;
- int value_len = strlen(value) + 1;
-
- if (!(var = ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char)))) {
- return NULL;
- }
-
- ast_copy_string(var->name, name, name_len);
- var->value = var->name + name_len;
- ast_copy_string(var->value, value, value_len);
-
- return var;
-}
-
-void ast_var_delete(struct ast_var_t *var)
-{
- if (var)
- free(var);
-}
-
-const char *ast_var_name(const struct ast_var_t *var)
-{
- const char *name;
-
- if (var == NULL || (name = var->name) == NULL)
- return NULL;
- /* Return the name without the initial underscores */
- if (name[0] == '_') {
- name++;
- if (name[0] == '_')
- name++;
- }
- return name;
-}
-
-const char *ast_var_full_name(const struct ast_var_t *var)
-{
- return (var ? var->name : NULL);
-}
-
-const char *ast_var_value(const struct ast_var_t *var)
-{
- return (var ? var->value : NULL);
-}
-
-
diff --git a/main/cli.c b/main/cli.c
deleted file mode 100644
index ef3ce6d19..000000000
--- a/main/cli.c
+++ /dev/null
@@ -1,2037 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Standard Command Line Interface
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/signal.h>
-#include <stdio.h>
-#include <signal.h>
-#include <string.h>
-#include <ctype.h>
-#include <regex.h>
-
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/cli.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/module.h"
-#include "asterisk/pbx.h"
-#include "asterisk/channel.h"
-#include "asterisk/utils.h"
-#include "asterisk/app.h"
-#include "asterisk/lock.h"
-#include "editline/readline/readline.h"
-#include "asterisk/threadstorage.h"
-
-extern unsigned long global_fin, global_fout;
-
-AST_THREADSTORAGE(ast_cli_buf, ast_cli_buf_init);
-
-/*! \brief Initial buffer size for resulting strings in ast_cli() */
-#define AST_CLI_INITLEN 256
-
-void ast_cli(int fd, char *fmt, ...)
-{
- int res;
- struct ast_dynamic_str *buf;
- va_list ap;
-
- if (!(buf = ast_dynamic_str_thread_get(&ast_cli_buf, AST_CLI_INITLEN)))
- return;
-
- va_start(ap, fmt);
- res = ast_dynamic_str_thread_set_va(&buf, 0, &ast_cli_buf, fmt, ap);
- va_end(ap);
-
- if (res != AST_DYNSTR_BUILD_FAILED)
- ast_carefulwrite(fd, buf->str, strlen(buf->str), 100);
-}
-
-static AST_LIST_HEAD_STATIC(helpers, ast_cli_entry);
-
-static char load_help[] =
-"Usage: module load <module name>\n"
-" Loads the specified module into Asterisk.\n";
-
-static char unload_help[] =
-"Usage: module unload [-f|-h] <module name>\n"
-" Unloads the specified module from Asterisk. The -f\n"
-" option causes the module to be unloaded even if it is\n"
-" in use (may cause a crash) and the -h module causes the\n"
-" module to be unloaded even if the module says it cannot, \n"
-" which almost always will cause a crash.\n";
-
-static char help_help[] =
-"Usage: help [topic]\n"
-" When called with a topic as an argument, displays usage\n"
-" information on the given command. If called without a\n"
-" topic, it provides a list of commands.\n";
-
-static char chanlist_help[] =
-"Usage: core show channels [concise|verbose]\n"
-" Lists currently defined channels and some information about them. If\n"
-" 'concise' is specified, the format is abridged and in a more easily\n"
-" machine parsable format. If 'verbose' is specified, the output includes\n"
-" more and longer fields.\n";
-
-static char reload_help[] =
-"Usage: module reload [module ...]\n"
-" Reloads configuration files for all listed modules which support\n"
-" reloading, or for all supported modules if none are listed.\n";
-
-static char verbose_help[] =
-"Usage: core set verbose <level>\n"
-" Sets level of verbose messages to be displayed. 0 means\n"
-" no messages should be displayed. Equivalent to -v[v[v...]]\n"
-" on startup\n";
-
-static char debug_help[] =
-"Usage: core set debug <level> [filename]\n"
-" Sets level of core debug messages to be displayed. 0 means\n"
-" no messages should be displayed. Equivalent to -d[d[d...]]\n"
-" on startup. If filename is specified, debugging will be\n"
-" limited to just that file.\n";
-
-static char nodebug_help[] =
-"Usage: core set debug off\n"
-" Turns off core debug messages.\n";
-
-static char logger_mute_help[] =
-"Usage: logger mute\n"
-" Disables logging output to the current console, making it possible to\n"
-" gather information without being disturbed by scrolling lines.\n";
-
-static char softhangup_help[] =
-"Usage: soft hangup <channel>\n"
-" Request that a channel be hung up. The hangup takes effect\n"
-" the next time the driver reads or writes from the channel\n";
-
-static char group_show_channels_help[] =
-"Usage: group show channels [pattern]\n"
-" Lists all currently active channels with channel group(s) specified.\n"
-" Optional regular expression pattern is matched to group names for each\n"
-" channel.\n";
-
-static int handle_load_deprecated(int fd, int argc, char *argv[])
-{
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- if (ast_load_resource(argv[1])) {
- ast_cli(fd, "Unable to load module %s\n", argv[1]);
- return RESULT_FAILURE;
- }
- return RESULT_SUCCESS;
-}
-
-static int handle_load(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- if (ast_load_resource(argv[2])) {
- ast_cli(fd, "Unable to load module %s\n", argv[2]);
- return RESULT_FAILURE;
- }
- return RESULT_SUCCESS;
-}
-
-static int handle_reload_deprecated(int fd, int argc, char *argv[])
-{
- int x;
- int res;
- if (argc < 1)
- return RESULT_SHOWUSAGE;
- if (argc > 1) {
- for (x = 1; x < argc; x++) {
- res = ast_module_reload(argv[x]);
- switch(res) {
- case 0:
- ast_cli(fd, "No such module '%s'\n", argv[x]);
- break;
- case 1:
- ast_cli(fd, "Module '%s' does not support reload\n", argv[x]);
- break;
- }
- }
- } else
- ast_module_reload(NULL);
- return RESULT_SUCCESS;
-}
-
-static int handle_reload(int fd, int argc, char *argv[])
-{
- int x;
- int res;
- if (argc < 2)
- return RESULT_SHOWUSAGE;
- if (argc > 2) {
- for (x = 2; x < argc; x++) {
- res = ast_module_reload(argv[x]);
- switch(res) {
- case 0:
- ast_cli(fd, "No such module '%s'\n", argv[x]);
- break;
- case 1:
- ast_cli(fd, "Module '%s' does not support reload\n", argv[x]);
- break;
- }
- }
- } else
- ast_module_reload(NULL);
- return RESULT_SUCCESS;
-}
-
-static int handle_set_verbose_deprecated(int fd, int argc, char *argv[])
-{
- int val = 0;
- int oldval = option_verbose;
-
- /* "set verbose [atleast] N" */
- if (argc == 3)
- option_verbose = atoi(argv[2]);
- else if (argc == 4) {
- if (strcasecmp(argv[2], "atleast"))
- return RESULT_SHOWUSAGE;
- val = atoi(argv[3]);
- if (val > option_verbose)
- option_verbose = val;
- } else
- return RESULT_SHOWUSAGE;
-
- if (oldval != option_verbose && option_verbose > 0)
- ast_cli(fd, "Verbosity was %d and is now %d\n", oldval, option_verbose);
- else if (oldval > 0 && option_verbose > 0)
- ast_cli(fd, "Verbosity is at least %d\n", option_verbose);
- else if (oldval > 0 && option_verbose == 0)
- ast_cli(fd, "Verbosity is now OFF\n");
-
- return RESULT_SUCCESS;
-}
-
-static int handle_verbose(int fd, int argc, char *argv[])
-{
- int oldval = option_verbose;
- int newlevel;
- int atleast = 0;
-
- if ((argc < 4) || (argc > 5))
- return RESULT_SHOWUSAGE;
-
- if (!strcasecmp(argv[3], "atleast"))
- atleast = 1;
-
- if (!atleast) {
- if (argc > 4)
- return RESULT_SHOWUSAGE;
-
- option_verbose = atoi(argv[3]);
- } else {
- if (argc < 5)
- return RESULT_SHOWUSAGE;
-
- newlevel = atoi(argv[4]);
- if (newlevel > option_verbose)
- option_verbose = newlevel;
- }
- if (oldval > 0 && option_verbose == 0)
- ast_cli(fd, "Verbosity is now OFF\n");
- else if (option_verbose > 0) {
- if (oldval == option_verbose)
- ast_cli(fd, "Verbosity is at least %d\n", option_verbose);
- else
- ast_cli(fd, "Verbosity was %d and is now %d\n", oldval, option_verbose);
- }
-
- return RESULT_SUCCESS;
-}
-
-static int handle_set_debug_deprecated(int fd, int argc, char *argv[])
-{
- int val = 0;
- int oldval = option_debug;
-
- /* "set debug [atleast] N" */
- if (argc == 3)
- option_debug = atoi(argv[2]);
- else if (argc == 4) {
- if (strcasecmp(argv[2], "atleast"))
- return RESULT_SHOWUSAGE;
- val = atoi(argv[3]);
- if (val > option_debug)
- option_debug = val;
- } else
- return RESULT_SHOWUSAGE;
-
- if (oldval != option_debug && option_debug > 0)
- ast_cli(fd, "Core debug was %d and is now %d\n", oldval, option_debug);
- else if (oldval > 0 && option_debug > 0)
- ast_cli(fd, "Core debug is at least %d\n", option_debug);
- else if (oldval > 0 && option_debug == 0)
- ast_cli(fd, "Core debug is now OFF\n");
-
- return RESULT_SUCCESS;
-}
-
-static int handle_set_debug(int fd, int argc, char *argv[])
-{
- int oldval = option_debug;
- int newlevel;
- int atleast = 0;
- char *filename = '\0';
-
- /* 'core set debug <level>'
- * 'core set debug <level> <fn>'
- * 'core set debug atleast <level>'
- * 'core set debug atleast <level> <fn>'
- */
- if ((argc < 4) || (argc > 6))
- return RESULT_SHOWUSAGE;
-
- if (!strcasecmp(argv[3], "atleast"))
- atleast = 1;
-
- if (!atleast) {
- if (argc > 5)
- return RESULT_SHOWUSAGE;
-
- if (sscanf(argv[3], "%d", &newlevel) != 1)
- return RESULT_SHOWUSAGE;
-
- if (argc == 4) {
- debug_filename[0] = '\0';
- } else {
- filename = argv[4];
- ast_copy_string(debug_filename, filename, sizeof(debug_filename));
- }
-
- option_debug = newlevel;
- } else {
- if (argc < 5 || argc > 6)
- return RESULT_SHOWUSAGE;
-
- if (sscanf(argv[4], "%d", &newlevel) != 1)
- return RESULT_SHOWUSAGE;
-
- if (argc == 5) {
- debug_filename[0] = '\0';
- } else {
- filename = argv[5];
- ast_copy_string(debug_filename, filename, sizeof(debug_filename));
- }
-
- if (newlevel > option_debug)
- option_debug = newlevel;
- }
-
- if (oldval > 0 && option_debug == 0)
- ast_cli(fd, "Core debug is now OFF\n");
- else if (option_debug > 0) {
- if (filename) {
- if (oldval == option_debug)
- ast_cli(fd, "Core debug is at least %d, file '%s'\n", option_debug, filename);
- else
- ast_cli(fd, "Core debug was %d and is now %d, file '%s'\n", oldval, option_debug, filename);
- } else {
- if (oldval == option_debug)
- ast_cli(fd, "Core debug is at least %d\n", option_debug);
- else
- ast_cli(fd, "Core debug was %d and is now %d\n", oldval, option_debug);
- }
- }
-
- return RESULT_SUCCESS;
-}
-
-static int handle_nodebug(int fd, int argc, char *argv[])
-{
- int oldval = option_debug;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- option_debug = 0;
- debug_filename[0] = '\0';
-
- if (oldval > 0)
- ast_cli(fd, "Core debug is now OFF\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_debuglevel_deprecated(int fd, int argc, char *argv[])
-{
- int newlevel;
- char *filename = "<any>";
- if ((argc < 3) || (argc > 4))
- return RESULT_SHOWUSAGE;
- if (sscanf(argv[2], "%d", &newlevel) != 1)
- return RESULT_SHOWUSAGE;
- option_debug = newlevel;
- if (argc == 4) {
- filename = argv[3];
- ast_copy_string(debug_filename, filename, sizeof(debug_filename));
- } else {
- debug_filename[0] = '\0';
- }
- ast_cli(fd, "Debugging level set to %d, file '%s'\n", newlevel, filename);
- return RESULT_SUCCESS;
-}
-
-static int handle_logger_mute(int fd, int argc, char *argv[])
-{
- if (argc < 2 || argc > 3)
- return RESULT_SHOWUSAGE;
- if (argc == 3 && !strcasecmp(argv[2], "silent"))
- ast_console_toggle_mute(fd, 1);
- else
- ast_console_toggle_mute(fd, 0);
- return RESULT_SUCCESS;
-}
-
-static int handle_unload_deprecated(int fd, int argc, char *argv[])
-{
- int x;
- int force = AST_FORCE_SOFT;
- if (argc < 2)
- return RESULT_SHOWUSAGE;
- for (x = 1; x < argc; x++) {
- if (argv[x][0] == '-') {
- switch(argv[x][1]) {
- case 'f':
- force = AST_FORCE_FIRM;
- break;
- case 'h':
- force = AST_FORCE_HARD;
- break;
- default:
- return RESULT_SHOWUSAGE;
- }
- } else if (x != argc - 1)
- return RESULT_SHOWUSAGE;
- else if (ast_unload_resource(argv[x], force)) {
- ast_cli(fd, "Unable to unload resource %s\n", argv[x]);
- return RESULT_FAILURE;
- }
- }
- return RESULT_SUCCESS;
-}
-
-static int handle_unload(int fd, int argc, char *argv[])
-{
- int x;
- int force = AST_FORCE_SOFT;
- if (argc < 3)
- return RESULT_SHOWUSAGE;
- for (x = 2; x < argc; x++) {
- if (argv[x][0] == '-') {
- switch(argv[x][1]) {
- case 'f':
- force = AST_FORCE_FIRM;
- break;
- case 'h':
- force = AST_FORCE_HARD;
- break;
- default:
- return RESULT_SHOWUSAGE;
- }
- } else if (x != argc - 1)
- return RESULT_SHOWUSAGE;
- else if (ast_unload_resource(argv[x], force)) {
- ast_cli(fd, "Unable to unload resource %s\n", argv[x]);
- return RESULT_FAILURE;
- }
- }
- return RESULT_SUCCESS;
-}
-
-#define MODLIST_FORMAT "%-30s %-40.40s %-10d\n"
-#define MODLIST_FORMAT2 "%-30s %-40.40s %-10s\n"
-
-AST_MUTEX_DEFINE_STATIC(climodentrylock);
-static int climodentryfd = -1;
-
-static int modlist_modentry(const char *module, const char *description, int usecnt, const char *like)
-{
- /* Comparing the like with the module */
- if (strcasestr(module, like) ) {
- ast_cli(climodentryfd, MODLIST_FORMAT, module, description, usecnt);
- return 1;
- }
- return 0;
-}
-
-static char modlist_help[] =
-"Usage: module show [like <keyword>]\n"
-" Shows Asterisk modules currently in use, and usage statistics.\n";
-
-static char uptime_help[] =
-"Usage: core show uptime [seconds]\n"
-" Shows Asterisk uptime information.\n"
-" The seconds word returns the uptime in seconds only.\n";
-
-static void print_uptimestr(int fd, time_t timeval, const char *prefix, int printsec)
-{
- int x; /* the main part - years, weeks, etc. */
- char timestr[256]="", *s = timestr;
- size_t maxbytes = sizeof(timestr);
-
-#define SECOND (1)
-#define MINUTE (SECOND*60)
-#define HOUR (MINUTE*60)
-#define DAY (HOUR*24)
-#define WEEK (DAY*7)
-#define YEAR (DAY*365)
-#define ESS(x) ((x == 1) ? "" : "s") /* plural suffix */
-#define NEEDCOMMA(x) ((x)? ",": "") /* define if we need a comma */
- if (timeval < 0) /* invalid, nothing to show */
- return;
- if (printsec) { /* plain seconds output */
- ast_build_string(&s, &maxbytes, "%lu", (u_long)timeval);
- timeval = 0; /* bypass the other cases */
- }
- if (timeval > YEAR) {
- x = (timeval / YEAR);
- timeval -= (x * YEAR);
- ast_build_string(&s, &maxbytes, "%d year%s%s ", x, ESS(x),NEEDCOMMA(timeval));
- }
- if (timeval > WEEK) {
- x = (timeval / WEEK);
- timeval -= (x * WEEK);
- ast_build_string(&s, &maxbytes, "%d week%s%s ", x, ESS(x),NEEDCOMMA(timeval));
- }
- if (timeval > DAY) {
- x = (timeval / DAY);
- timeval -= (x * DAY);
- ast_build_string(&s, &maxbytes, "%d day%s%s ", x, ESS(x),NEEDCOMMA(timeval));
- }
- if (timeval > HOUR) {
- x = (timeval / HOUR);
- timeval -= (x * HOUR);
- ast_build_string(&s, &maxbytes, "%d hour%s%s ", x, ESS(x),NEEDCOMMA(timeval));
- }
- if (timeval > MINUTE) {
- x = (timeval / MINUTE);
- timeval -= (x * MINUTE);
- ast_build_string(&s, &maxbytes, "%d minute%s%s ", x, ESS(x),NEEDCOMMA(timeval));
- }
- x = timeval;
- if (x > 0)
- ast_build_string(&s, &maxbytes, "%d second%s ", x, ESS(x));
- if (timestr[0] != '\0')
- ast_cli(fd, "%s: %s\n", prefix, timestr);
-}
-
-static int handle_showuptime_deprecated(int fd, int argc, char *argv[])
-{
- /* 'show uptime [seconds]' */
- time_t curtime = time(NULL);
- int printsec = (argc == 3 && !strcasecmp(argv[2],"seconds"));
-
- if (argc != 2 && !printsec)
- return RESULT_SHOWUSAGE;
- if (ast_startuptime)
- print_uptimestr(fd, curtime - ast_startuptime, "System uptime", printsec);
- if (ast_lastreloadtime)
- print_uptimestr(fd, curtime - ast_lastreloadtime, "Last reload", printsec);
- return RESULT_SUCCESS;
-}
-
-static int handle_showuptime(int fd, int argc, char *argv[])
-{
- /* 'core show uptime [seconds]' */
- time_t curtime = time(NULL);
- int printsec = (argc == 4 && !strcasecmp(argv[3],"seconds"));
-
- if (argc != 3 && !printsec)
- return RESULT_SHOWUSAGE;
- if (ast_startuptime)
- print_uptimestr(fd, curtime - ast_startuptime, "System uptime", printsec);
- if (ast_lastreloadtime)
- print_uptimestr(fd, curtime - ast_lastreloadtime, "Last reload", printsec);
- return RESULT_SUCCESS;
-}
-
-static int handle_modlist(int fd, int argc, char *argv[])
-{
- char *like = "";
- if (argc == 3)
- return RESULT_SHOWUSAGE;
- else if (argc >= 4) {
- if (strcmp(argv[2],"like"))
- return RESULT_SHOWUSAGE;
- like = argv[3];
- }
-
- ast_mutex_lock(&climodentrylock);
- climodentryfd = fd; /* global, protected by climodentrylock */
- ast_cli(fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
- ast_cli(fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
- climodentryfd = -1;
- ast_mutex_unlock(&climodentrylock);
- return RESULT_SUCCESS;
-}
-#undef MODLIST_FORMAT
-#undef MODLIST_FORMAT2
-
-#define FORMAT_STRING "%-20.20s %-20.20s %-7.7s %-30.30s\n"
-#define FORMAT_STRING2 "%-20.20s %-20.20s %-7.7s %-30.30s\n"
-#define CONCISE_FORMAT_STRING "%s!%s!%s!%d!%s!%s!%s!%s!%s!%d!%s!%s\n"
-#define VERBOSE_FORMAT_STRING "%-20.20s %-20.20s %-16.16s %4d %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-20.20s\n"
-#define VERBOSE_FORMAT_STRING2 "%-20.20s %-20.20s %-16.16s %-4.4s %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-20.20s\n"
-
-static int handle_chanlist_deprecated(int fd, int argc, char *argv[])
-{
- struct ast_channel *c = NULL;
- char durbuf[10] = "-";
- char locbuf[40];
- char appdata[40];
- int duration;
- int durh, durm, durs;
- int numchans = 0, concise = 0, verbose = 0;
-
- concise = (argc == 3 && (!strcasecmp(argv[2],"concise")));
- verbose = (argc == 3 && (!strcasecmp(argv[2],"verbose")));
-
- if (argc < 2 || argc > 3 || (argc == 3 && !concise && !verbose))
- return RESULT_SHOWUSAGE;
-
- if (!concise && !verbose)
- ast_cli(fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
- else if (verbose)
- ast_cli(fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
- "CallerID", "Duration", "Accountcode", "BridgedTo");
-
- while ((c = ast_channel_walk_locked(c)) != NULL) {
- struct ast_channel *bc = ast_bridged_channel(c);
- if ((concise || verbose) && c->cdr && !ast_tvzero(c->cdr->start)) {
- duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
- if (verbose) {
- durh = duration / 3600;
- durm = (duration % 3600) / 60;
- durs = duration % 60;
- snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
- } else {
- snprintf(durbuf, sizeof(durbuf), "%d", duration);
- }
- } else {
- durbuf[0] = '\0';
- }
- if (concise) {
- ast_cli(fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
- c->appl ? c->appl : "(None)",
- S_OR(c->data, ""), /* XXX different from verbose ? */
- S_OR(c->cid.cid_num, ""),
- S_OR(c->accountcode, ""),
- c->amaflags,
- durbuf,
- bc ? bc->name : "(None)");
- } else if (verbose) {
- ast_cli(fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
- c->appl ? c->appl : "(None)",
- c->data ? S_OR(c->data, "(Empty)" ): "(None)",
- S_OR(c->cid.cid_num, ""),
- durbuf,
- S_OR(c->accountcode, ""),
- bc ? bc->name : "(None)");
- } else {
- if (!ast_strlen_zero(c->context) && !ast_strlen_zero(c->exten))
- snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", c->exten, c->context, c->priority);
- else
- strcpy(locbuf, "(None)");
- if (c->appl)
- snprintf(appdata, sizeof(appdata), "%s(%s)", c->appl, c->data ? c->data : "");
- else
- strcpy(appdata, "(None)");
- ast_cli(fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
- }
- numchans++;
- ast_channel_unlock(c);
- }
- if (!concise) {
- ast_cli(fd, "%d active channel%s\n", numchans, ESS(numchans));
- if (option_maxcalls)
- ast_cli(fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
- ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
- ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
- else
- ast_cli(fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
- }
- return RESULT_SUCCESS;
-}
-
-static int handle_chanlist(int fd, int argc, char *argv[])
-{
- struct ast_channel *c = NULL;
- char durbuf[10] = "-";
- char locbuf[40];
- char appdata[40];
- int duration;
- int durh, durm, durs;
- int numchans = 0, concise = 0, verbose = 0;
-
- concise = (argc == 4 && (!strcasecmp(argv[3],"concise")));
- verbose = (argc == 4 && (!strcasecmp(argv[3],"verbose")));
-
- if (argc < 3 || argc > 4 || (argc == 4 && !concise && !verbose))
- return RESULT_SHOWUSAGE;
-
- if (!concise && !verbose)
- ast_cli(fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
- else if (verbose)
- ast_cli(fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
- "CallerID", "Duration", "Accountcode", "BridgedTo");
-
- while ((c = ast_channel_walk_locked(c)) != NULL) {
- struct ast_channel *bc = ast_bridged_channel(c);
- if ((concise || verbose) && c->cdr && !ast_tvzero(c->cdr->start)) {
- duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
- if (verbose) {
- durh = duration / 3600;
- durm = (duration % 3600) / 60;
- durs = duration % 60;
- snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
- } else {
- snprintf(durbuf, sizeof(durbuf), "%d", duration);
- }
- } else {
- durbuf[0] = '\0';
- }
- if (concise) {
- ast_cli(fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
- c->appl ? c->appl : "(None)",
- S_OR(c->data, ""), /* XXX different from verbose ? */
- S_OR(c->cid.cid_num, ""),
- S_OR(c->accountcode, ""),
- c->amaflags,
- durbuf,
- bc ? bc->name : "(None)");
- } else if (verbose) {
- ast_cli(fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
- c->appl ? c->appl : "(None)",
- c->data ? S_OR(c->data, "(Empty)" ): "(None)",
- S_OR(c->cid.cid_num, ""),
- durbuf,
- S_OR(c->accountcode, ""),
- bc ? bc->name : "(None)");
- } else {
- if (!ast_strlen_zero(c->context) && !ast_strlen_zero(c->exten))
- snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", c->exten, c->context, c->priority);
- else
- strcpy(locbuf, "(None)");
- if (c->appl)
- snprintf(appdata, sizeof(appdata), "%s(%s)", c->appl, c->data ? c->data : "");
- else
- strcpy(appdata, "(None)");
- ast_cli(fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
- }
- numchans++;
- ast_channel_unlock(c);
- }
- if (!concise) {
- ast_cli(fd, "%d active channel%s\n", numchans, ESS(numchans));
- if (option_maxcalls)
- ast_cli(fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
- ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
- ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
- else
- ast_cli(fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
- }
- return RESULT_SUCCESS;
-}
-
-#undef FORMAT_STRING
-#undef FORMAT_STRING2
-#undef CONCISE_FORMAT_STRING
-#undef VERBOSE_FORMAT_STRING
-#undef VERBOSE_FORMAT_STRING2
-
-static char showchan_help[] =
-"Usage: core show channel <channel>\n"
-" Shows lots of information about the specified channel.\n";
-
-static char debugchan_help[] =
-"Usage: core set debug channel <channel> [off]\n"
-" Enables/disables debugging on a specific channel.\n";
-
-static char commandcomplete_help[] =
-"Usage: _command complete \"<line>\" text state\n"
-" This function is used internally to help with command completion and should.\n"
-" never be called by the user directly.\n";
-
-static char commandnummatches_help[] =
-"Usage: _command nummatches \"<line>\" text \n"
-" This function is used internally to help with command completion and should.\n"
-" never be called by the user directly.\n";
-
-static char commandmatchesarray_help[] =
-"Usage: _command matchesarray \"<line>\" text \n"
-" This function is used internally to help with command completion and should.\n"
-" never be called by the user directly.\n";
-
-static int handle_softhangup(int fd, int argc, char *argv[])
-{
- struct ast_channel *c=NULL;
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- c = ast_get_channel_by_name_locked(argv[2]);
- if (c) {
- ast_cli(fd, "Requested Hangup on channel '%s'\n", c->name);
- ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
- ast_channel_unlock(c);
- } else
- ast_cli(fd, "%s is not a known channel\n", argv[2]);
- return RESULT_SUCCESS;
-}
-
-static char *__ast_cli_generator(const char *text, const char *word, int state, int lock);
-
-static int handle_commandmatchesarray(int fd, int argc, char *argv[])
-{
- char *buf, *obuf;
- int buflen = 2048;
- int len = 0;
- char **matches;
- int x, matchlen;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- if (!(buf = ast_malloc(buflen)))
- return RESULT_FAILURE;
- buf[len] = '\0';
- matches = ast_cli_completion_matches(argv[2], argv[3]);
- if (matches) {
- for (x=0; matches[x]; x++) {
- matchlen = strlen(matches[x]) + 1;
- if (len + matchlen >= buflen) {
- buflen += matchlen * 3;
- obuf = buf;
- if (!(buf = ast_realloc(obuf, buflen)))
- /* Memory allocation failure... Just free old buffer and be done */
- free(obuf);
- }
- if (buf)
- len += sprintf( buf + len, "%s ", matches[x]);
- free(matches[x]);
- matches[x] = NULL;
- }
- free(matches);
- }
-
- if (buf) {
- ast_cli(fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
- free(buf);
- } else
- ast_cli(fd, "NULL\n");
-
- return RESULT_SUCCESS;
-}
-
-
-
-static int handle_commandnummatches(int fd, int argc, char *argv[])
-{
- int matches = 0;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- matches = ast_cli_generatornummatches(argv[2], argv[3]);
-
- ast_cli(fd, "%d", matches);
-
- return RESULT_SUCCESS;
-}
-
-static int handle_commandcomplete(int fd, int argc, char *argv[])
-{
- char *buf;
-
- if (argc != 5)
- return RESULT_SHOWUSAGE;
- buf = __ast_cli_generator(argv[2], argv[3], atoi(argv[4]), 0);
- if (buf) {
- ast_cli(fd, "%s", buf);
- free(buf);
- } else
- ast_cli(fd, "NULL\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_debugchan_deprecated(int fd, int argc, char *argv[])
-{
- struct ast_channel *c=NULL;
- int is_all;
-
- /* 'debug channel {all|chan_id}' */
- if (argc != 3)
- return RESULT_SHOWUSAGE;
-
- is_all = !strcasecmp("all", argv[2]);
- if (is_all) {
- global_fin |= DEBUGCHAN_FLAG;
- global_fout |= DEBUGCHAN_FLAG;
- c = ast_channel_walk_locked(NULL);
- } else {
- c = ast_get_channel_by_name_locked(argv[2]);
- if (c == NULL)
- ast_cli(fd, "No such channel %s\n", argv[2]);
- }
- while (c) {
- if (!(c->fin & DEBUGCHAN_FLAG) || !(c->fout & DEBUGCHAN_FLAG)) {
- c->fin |= DEBUGCHAN_FLAG;
- c->fout |= DEBUGCHAN_FLAG;
- ast_cli(fd, "Debugging enabled on channel %s\n", c->name);
- }
- ast_channel_unlock(c);
- if (!is_all)
- break;
- c = ast_channel_walk_locked(c);
- }
- ast_cli(fd, "Debugging on new channels is enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_core_set_debug_channel(int fd, int argc, char *argv[])
-{
- struct ast_channel *c = NULL;
- int is_all, is_off = 0;
-
- /* 'core set debug channel {all|chan_id}' */
- if (argc == 6 && strcmp(argv[5], "off") == 0)
- is_off = 1;
- else if (argc != 5)
- return RESULT_SHOWUSAGE;
-
- is_all = !strcasecmp("all", argv[4]);
- if (is_all) {
- if (is_off) {
- global_fin &= ~DEBUGCHAN_FLAG;
- global_fout &= ~DEBUGCHAN_FLAG;
- } else {
- global_fin |= DEBUGCHAN_FLAG;
- global_fout |= DEBUGCHAN_FLAG;
- }
- c = ast_channel_walk_locked(NULL);
- } else {
- c = ast_get_channel_by_name_locked(argv[4]);
- if (c == NULL)
- ast_cli(fd, "No such channel %s\n", argv[4]);
- }
- while (c) {
- if (!(c->fin & DEBUGCHAN_FLAG) || !(c->fout & DEBUGCHAN_FLAG)) {
- if (is_off) {
- c->fin &= ~DEBUGCHAN_FLAG;
- c->fout &= ~DEBUGCHAN_FLAG;
- } else {
- c->fin |= DEBUGCHAN_FLAG;
- c->fout |= DEBUGCHAN_FLAG;
- }
- ast_cli(fd, "Debugging %s on channel %s\n", is_off ? "disabled" : "enabled", c->name);
- }
- ast_channel_unlock(c);
- if (!is_all)
- break;
- c = ast_channel_walk_locked(c);
- }
- ast_cli(fd, "Debugging on new channels is %s\n", is_off ? "disabled" : "enabled");
- return RESULT_SUCCESS;
-}
-
-static int handle_nodebugchan_deprecated(int fd, int argc, char *argv[])
-{
- struct ast_channel *c=NULL;
- int is_all;
- /* 'no debug channel {all|chan_id}' */
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- is_all = !strcasecmp("all", argv[3]);
- if (is_all) {
- global_fin &= ~DEBUGCHAN_FLAG;
- global_fout &= ~DEBUGCHAN_FLAG;
- c = ast_channel_walk_locked(NULL);
- } else {
- c = ast_get_channel_by_name_locked(argv[3]);
- if (c == NULL)
- ast_cli(fd, "No such channel %s\n", argv[3]);
- }
- while(c) {
- if ((c->fin & DEBUGCHAN_FLAG) || (c->fout & DEBUGCHAN_FLAG)) {
- c->fin &= ~DEBUGCHAN_FLAG;
- c->fout &= ~DEBUGCHAN_FLAG;
- ast_cli(fd, "Debugging disabled on channel %s\n", c->name);
- }
- ast_channel_unlock(c);
- if (!is_all)
- break;
- c = ast_channel_walk_locked(c);
- }
- ast_cli(fd, "Debugging on new channels is disabled\n");
- return RESULT_SUCCESS;
-}
-
-static int handle_showchan_deprecated(int fd, int argc, char *argv[])
-{
- struct ast_channel *c=NULL;
- struct timeval now;
- char buf[2048];
- char cdrtime[256];
- char nf[256], wf[256], rf[256];
- long elapsed_seconds=0;
- int hour=0, min=0, sec=0;
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- now = ast_tvnow();
- c = ast_get_channel_by_name_locked(argv[2]);
- if (!c) {
- ast_cli(fd, "%s is not a known channel\n", argv[2]);
- return RESULT_SUCCESS;
- }
- if(c->cdr) {
- elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
- hour = elapsed_seconds / 3600;
- min = (elapsed_seconds % 3600) / 60;
- sec = elapsed_seconds % 60;
- snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
- } else
- strcpy(cdrtime, "N/A");
- ast_cli(fd,
- " -- General --\n"
- " Name: %s\n"
- " Type: %s\n"
- " UniqueID: %s\n"
- " Caller ID: %s\n"
- " Caller ID Name: %s\n"
- " DNID Digits: %s\n"
- " State: %s (%d)\n"
- " Rings: %d\n"
- " NativeFormats: %s\n"
- " WriteFormat: %s\n"
- " ReadFormat: %s\n"
- " WriteTranscode: %s\n"
- " ReadTranscode: %s\n"
- "1st File Descriptor: %d\n"
- " Frames in: %d%s\n"
- " Frames out: %d%s\n"
- " Time to Hangup: %ld\n"
- " Elapsed Time: %s\n"
- " Direct Bridge: %s\n"
- "Indirect Bridge: %s\n"
- " -- PBX --\n"
- " Context: %s\n"
- " Extension: %s\n"
- " Priority: %d\n"
- " Call Group: %llu\n"
- " Pickup Group: %llu\n"
- " Application: %s\n"
- " Data: %s\n"
- " Blocking in: %s\n",
- c->name, c->tech->type, c->uniqueid,
- S_OR(c->cid.cid_num, "(N/A)"),
- S_OR(c->cid.cid_name, "(N/A)"),
- S_OR(c->cid.cid_dnid, "(N/A)"), ast_state2str(c->_state), c->_state, c->rings,
- ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats),
- ast_getformatname_multiple(wf, sizeof(wf), c->writeformat),
- ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
- c->writetrans ? "Yes" : "No",
- c->readtrans ? "Yes" : "No",
- c->fds[0],
- c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
- c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
- (long)c->whentohangup,
- cdrtime, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>",
- c->context, c->exten, c->priority, c->callgroup, c->pickupgroup, ( c->appl ? c->appl : "(N/A)" ),
- ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
- (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
-
- if(pbx_builtin_serialize_variables(c,buf,sizeof(buf)))
- ast_cli(fd," Variables:\n%s\n",buf);
- if(c->cdr && ast_cdr_serialize_variables(c->cdr,buf, sizeof(buf), '=', '\n', 1))
- ast_cli(fd," CDR Variables:\n%s\n",buf);
-
- ast_channel_unlock(c);
- return RESULT_SUCCESS;
-}
-
-static int handle_showchan(int fd, int argc, char *argv[])
-{
- struct ast_channel *c=NULL;
- struct timeval now;
- char buf[2048];
- char cdrtime[256];
- char nf[256], wf[256], rf[256];
- long elapsed_seconds=0;
- int hour=0, min=0, sec=0;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- now = ast_tvnow();
- c = ast_get_channel_by_name_locked(argv[3]);
- if (!c) {
- ast_cli(fd, "%s is not a known channel\n", argv[3]);
- return RESULT_SUCCESS;
- }
- if(c->cdr) {
- elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
- hour = elapsed_seconds / 3600;
- min = (elapsed_seconds % 3600) / 60;
- sec = elapsed_seconds % 60;
- snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
- } else
- strcpy(cdrtime, "N/A");
- ast_cli(fd,
- " -- General --\n"
- " Name: %s\n"
- " Type: %s\n"
- " UniqueID: %s\n"
- " Caller ID: %s\n"
- " Caller ID Name: %s\n"
- " DNID Digits: %s\n"
- " State: %s (%d)\n"
- " Rings: %d\n"
- " NativeFormats: %s\n"
- " WriteFormat: %s\n"
- " ReadFormat: %s\n"
- " WriteTranscode: %s\n"
- " ReadTranscode: %s\n"
- "1st File Descriptor: %d\n"
- " Frames in: %d%s\n"
- " Frames out: %d%s\n"
- " Time to Hangup: %ld\n"
- " Elapsed Time: %s\n"
- " Direct Bridge: %s\n"
- "Indirect Bridge: %s\n"
- " -- PBX --\n"
- " Context: %s\n"
- " Extension: %s\n"
- " Priority: %d\n"
- " Call Group: %llu\n"
- " Pickup Group: %llu\n"
- " Application: %s\n"
- " Data: %s\n"
- " Blocking in: %s\n",
- c->name, c->tech->type, c->uniqueid,
- S_OR(c->cid.cid_num, "(N/A)"),
- S_OR(c->cid.cid_name, "(N/A)"),
- S_OR(c->cid.cid_dnid, "(N/A)"), ast_state2str(c->_state), c->_state, c->rings,
- ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats),
- ast_getformatname_multiple(wf, sizeof(wf), c->writeformat),
- ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
- c->writetrans ? "Yes" : "No",
- c->readtrans ? "Yes" : "No",
- c->fds[0],
- c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
- c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
- (long)c->whentohangup,
- cdrtime, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>",
- c->context, c->exten, c->priority, c->callgroup, c->pickupgroup, ( c->appl ? c->appl : "(N/A)" ),
- ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
- (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
-
- if(pbx_builtin_serialize_variables(c,buf,sizeof(buf)))
- ast_cli(fd," Variables:\n%s\n",buf);
- if(c->cdr && ast_cdr_serialize_variables(c->cdr,buf, sizeof(buf), '=', '\n', 1))
- ast_cli(fd," CDR Variables:\n%s\n",buf);
-
- ast_channel_unlock(c);
- return RESULT_SUCCESS;
-}
-
-/*
- * helper function to generate CLI matches from a fixed set of values.
- * A NULL word is acceptable.
- */
-char *ast_cli_complete(const char *word, char *const choices[], int state)
-{
- int i, which = 0, len;
- len = ast_strlen_zero(word) ? 0 : strlen(word);
-
- for (i = 0; choices[i]; i++) {
- if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state)
- return ast_strdup(choices[i]);
- }
- return NULL;
-}
-
-static char *complete_show_channels_deprecated(const char *line, const char *word, int pos, int state)
-{
- static char *choices[] = { "concise", "verbose", NULL };
-
- return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
-}
-
-static char *complete_show_channels(const char *line, const char *word, int pos, int state)
-{
- static char *choices[] = { "concise", "verbose", NULL };
-
- return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
-}
-
-char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
-{
- struct ast_channel *c = NULL;
- int which = 0;
- int wordlen;
- char notfound = '\0';
- char *ret = &notfound; /* so NULL can break the loop */
-
- if (pos != rpos)
- return NULL;
-
- wordlen = strlen(word);
-
- while (ret == &notfound && (c = ast_channel_walk_locked(c))) {
- if (!strncasecmp(word, c->name, wordlen) && ++which > state)
- ret = ast_strdup(c->name);
- ast_channel_unlock(c);
- }
- return ret == &notfound ? NULL : ret;
-}
-
-static char *complete_ch_3(const char *line, const char *word, int pos, int state)
-{
- return ast_complete_channels(line, word, pos, state, 2);
-}
-
-static char *complete_ch_4(const char *line, const char *word, int pos, int state)
-{
- return ast_complete_channels(line, word, pos, state, 3);
-}
-
-static char *complete_ch_5(const char *line, const char *word, int pos, int state)
-{
- return ast_complete_channels(line, word, pos, state, 4);
-}
-
-static char *complete_mod_2(const char *line, const char *word, int pos, int state)
-{
- return ast_module_helper(line, word, pos, state, 1, 1);
-}
-
-static char *complete_mod_3_nr(const char *line, const char *word, int pos, int state)
-{
- return ast_module_helper(line, word, pos, state, 2, 0);
-}
-
-static char *complete_mod_3(const char *line, const char *word, int pos, int state)
-{
- return ast_module_helper(line, word, pos, state, 2, 1);
-}
-
-static char *complete_mod_4(const char *line, const char *word, int pos, int state)
-{
- return ast_module_helper(line, word, pos, state, 3, 0);
-}
-
-static char *complete_fn_2(const char *line, const char *word, int pos, int state)
-{
- char *c, *d;
- char filename[PATH_MAX];
-
- if (pos != 1)
- return NULL;
-
- if (word[0] == '/')
- ast_copy_string(filename, word, sizeof(filename));
- else
- snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
-
- c = d = filename_completion_function(filename, state);
-
- if (c && word[0] != '/')
- c += (strlen(ast_config_AST_MODULE_DIR) + 1);
- if (c)
- c = strdup(c);
- free(d);
-
- return c;
-}
-
-static char *complete_fn_3(const char *line, const char *word, int pos, int state)
-{
- char *c, *d;
- char filename[PATH_MAX];
-
- if (pos != 2)
- return NULL;
-
- if (word[0] == '/')
- ast_copy_string(filename, word, sizeof(filename));
- else
- snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
-
- c = d = filename_completion_function(filename, state);
-
- if (c && word[0] != '/')
- c += (strlen(ast_config_AST_MODULE_DIR) + 1);
- if (c)
- c = strdup(c);
- free(d);
-
- return c;
-}
-
-static int group_show_channels(int fd, int argc, char *argv[])
-{
-#define FORMAT_STRING "%-25s %-20s %-20s\n"
-
- struct ast_group_info *gi = NULL;
- int numchans = 0;
- regex_t regexbuf;
- int havepattern = 0;
-
- if (argc < 3 || argc > 4)
- return RESULT_SHOWUSAGE;
-
- if (argc == 4) {
- if (regcomp(&regexbuf, argv[3], REG_EXTENDED | REG_NOSUB))
- return RESULT_SHOWUSAGE;
- havepattern = 1;
- }
-
- ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
-
- ast_app_group_list_lock();
-
- gi = ast_app_group_list_head();
- while (gi) {
- if (!havepattern || !regexec(&regexbuf, gi->group, 0, NULL, 0)) {
- ast_cli(fd, FORMAT_STRING, gi->chan->name, gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
- numchans++;
- }
- gi = AST_LIST_NEXT(gi, list);
- }
-
- ast_app_group_list_unlock();
-
- if (havepattern)
- regfree(&regexbuf);
-
- ast_cli(fd, "%d active channel%s\n", numchans, (numchans != 1) ? "s" : "");
- return RESULT_SUCCESS;
-#undef FORMAT_STRING
-}
-
-static int handle_help(int fd, int argc, char *argv[]);
-
-static char * complete_help(const char *text, const char *word, int pos, int state)
-{
- /* skip first 4 or 5 chars, "help "*/
- int l = strlen(text);
-
- if (l > 5)
- l = 5;
- text += l;
- /* XXX watch out, should stop to the non-generator parts */
- return __ast_cli_generator(text, word, state, 0);
-}
-
-/* XXX Nothing in this array can currently be deprecated...
- You have to change the way find_cli works in order to remove this array
- I recommend doing this eventually...
- */
-static struct ast_cli_entry builtins[] = {
- /* Keep alphabetized, with longer matches first (example: abcd before abc) */
- { { "_command", "complete", NULL },
- handle_commandcomplete, "Command complete",
- commandcomplete_help },
-
- { { "_command", "nummatches", NULL },
- handle_commandnummatches, "Returns number of command matches",
- commandnummatches_help },
-
- { { "_command", "matchesarray", NULL },
- handle_commandmatchesarray, "Returns command matches array",
- commandmatchesarray_help },
-
- { { NULL }, NULL, NULL, NULL }
-};
-
-static struct ast_cli_entry cli_debug_channel_deprecated = {
- { "debug", "channel", NULL },
- handle_debugchan_deprecated, NULL,
- NULL, complete_ch_3 };
-
-static struct ast_cli_entry cli_debug_level_deprecated = {
- { "debug", "level", NULL },
- handle_debuglevel_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_set_debug_deprecated = {
- { "set", "debug", NULL },
- handle_set_debug_deprecated, NULL,
- NULL, NULL, &cli_debug_level_deprecated };
-
-static struct ast_cli_entry cli_set_verbose_deprecated = {
- { "set", "verbose", NULL },
- handle_set_verbose_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_channel_deprecated = {
- { "show", "channel", NULL },
- handle_showchan_deprecated, NULL,
- NULL, complete_ch_3 };
-
-static struct ast_cli_entry cli_show_channels_deprecated = {
- { "show", "channels", NULL },
- handle_chanlist_deprecated, NULL,
- NULL, complete_show_channels_deprecated };
-
-static struct ast_cli_entry cli_show_modules_deprecated = {
- { "show", "modules", NULL },
- handle_modlist, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_modules_like_deprecated = {
- { "show", "modules", "like", NULL },
- handle_modlist, NULL,
- NULL, complete_mod_4 };
-
-static struct ast_cli_entry cli_module_load_deprecated = {
- { "load", NULL },
- handle_load_deprecated, NULL,
- NULL, complete_fn_2 };
-
-static struct ast_cli_entry cli_module_reload_deprecated = {
- { "reload", NULL },
- handle_reload_deprecated, NULL,
- NULL, complete_mod_2 };
-
-static struct ast_cli_entry cli_module_unload_deprecated = {
- { "unload", NULL },
- handle_unload_deprecated, NULL,
- NULL, complete_mod_2 };
-
-static struct ast_cli_entry cli_show_uptime_deprecated = {
- { "show", "uptime", NULL },
- handle_showuptime_deprecated, "Show uptime information",
- NULL };
-
-static struct ast_cli_entry cli_cli[] = {
- /* Deprecated, but preferred command is now consolidated (and already has a deprecated command for it). */
- { { "no", "debug", "channel", NULL },
- handle_nodebugchan_deprecated, NULL,
- NULL, complete_ch_4 },
-
- { { "core", "show", "channels", NULL },
- handle_chanlist, "Display information on channels",
- chanlist_help, complete_show_channels, &cli_show_channels_deprecated },
-
- { { "core", "show", "channel", NULL },
- handle_showchan, "Display information on a specific channel",
- showchan_help, complete_ch_4, &cli_show_channel_deprecated },
-
- { { "core", "set", "debug", "channel", NULL },
- handle_core_set_debug_channel, "Enable/disable debugging on a channel",
- debugchan_help, complete_ch_5, &cli_debug_channel_deprecated },
-
- { { "core", "set", "debug", NULL },
- handle_set_debug, "Set level of debug chattiness",
- debug_help, NULL, &cli_set_debug_deprecated },
-
- { { "core", "set", "debug", "off", NULL },
- handle_nodebug, "Turns off debug chattiness",
- nodebug_help },
-
- { { "core", "set", "verbose", NULL },
- handle_verbose, "Set level of verboseness",
- verbose_help, NULL, &cli_set_verbose_deprecated },
-
- { { "group", "show", "channels", NULL },
- group_show_channels, "Display active channels with group(s)",
- group_show_channels_help },
-
- { { "help", NULL },
- handle_help, "Display help list, or specific help on a command",
- help_help, complete_help },
-
- { { "logger", "mute", NULL },
- handle_logger_mute, "Toggle logging output to a console",
- logger_mute_help },
-
- { { "module", "show", NULL },
- handle_modlist, "List modules and info",
- modlist_help, NULL, &cli_show_modules_deprecated },
-
- { { "module", "show", "like", NULL },
- handle_modlist, "List modules and info",
- modlist_help, complete_mod_4, &cli_show_modules_like_deprecated },
-
- { { "module", "load", NULL },
- handle_load, "Load a module by name",
- load_help, complete_fn_3, &cli_module_load_deprecated },
-
- { { "module", "reload", NULL },
- handle_reload, "Reload configuration",
- reload_help, complete_mod_3, &cli_module_reload_deprecated },
-
- { { "module", "unload", NULL },
- handle_unload, "Unload a module by name",
- unload_help, complete_mod_3_nr, &cli_module_unload_deprecated },
-
- { { "core", "show", "uptime", NULL },
- handle_showuptime, "Show uptime information",
- uptime_help, NULL, &cli_show_uptime_deprecated },
-
- { { "soft", "hangup", NULL },
- handle_softhangup, "Request a hangup on a given channel",
- softhangup_help, complete_ch_3 },
-};
-
-/*! \brief initialize the _full_cmd string in * each of the builtins. */
-void ast_builtins_init(void)
-{
- struct ast_cli_entry *e;
-
- for (e = builtins; e->cmda[0] != NULL; e++) {
- char buf[80];
- ast_join(buf, sizeof(buf), e->cmda);
- e->_full_cmd = strdup(buf);
- if (!e->_full_cmd)
- ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
- }
-
- ast_cli_register_multiple(cli_cli, sizeof(cli_cli) / sizeof(struct ast_cli_entry));
-}
-
-/*
- * We have two sets of commands: builtins are stored in a
- * NULL-terminated array of ast_cli_entry, whereas external
- * commands are in a list.
- * When navigating, we need to keep two pointers and get
- * the next one in lexicographic order. For the purpose,
- * we use a structure.
- */
-
-struct cli_iterator {
- struct ast_cli_entry *builtins;
- struct ast_cli_entry *helpers;
-};
-
-static struct ast_cli_entry *cli_next(struct cli_iterator *i)
-{
- struct ast_cli_entry *e;
-
- if (i->builtins == NULL && i->helpers == NULL) {
- /* initialize */
- i->builtins = builtins;
- i->helpers = AST_LIST_FIRST(&helpers);
- }
- e = i->builtins; /* temporary */
- if (!e->cmda[0] || (i->helpers &&
- strcmp(i->helpers->_full_cmd, e->_full_cmd) < 0)) {
- /* Use helpers */
- e = i->helpers;
- if (e)
- i->helpers = AST_LIST_NEXT(e, list);
- } else { /* use builtin. e is already set */
- (i->builtins)++; /* move to next */
- }
- return e;
-}
-
-/*!
- * \brief locate a cli command in the 'helpers' list (which must be locked).
- * exact has 3 values:
- * 0 returns if the search key is equal or longer than the entry.
- * -1 true if the mismatch is on the last word XXX not true!
- * 1 true only on complete, exact match.
- */
-static struct ast_cli_entry *find_cli(char *const cmds[], int match_type)
-{
- int matchlen = -1; /* length of longest match so far */
- struct ast_cli_entry *cand = NULL, *e=NULL;
- struct cli_iterator i = { NULL, NULL};
-
- while( (e = cli_next(&i)) ) {
- int y;
- for (y = 0 ; cmds[y] && e->cmda[y]; y++) {
- if (strcasecmp(e->cmda[y], cmds[y]))
- break;
- }
- if (e->cmda[y] == NULL) { /* no more words in candidate */
- if (cmds[y] == NULL) /* this is an exact match, cannot do better */
- break;
- /* here the search key is longer than the candidate */
- if (match_type != 0) /* but we look for almost exact match... */
- continue; /* so we skip this one. */
- /* otherwise we like it (case 0) */
- } else { /* still words in candidate */
- if (cmds[y] == NULL) /* search key is shorter, not good */
- continue;
- /* if we get here, both words exist but there is a mismatch */
- if (match_type == 0) /* not the one we look for */
- continue;
- if (match_type == 1) /* not the one we look for */
- continue;
- if (cmds[y+1] != NULL || e->cmda[y+1] != NULL) /* not the one we look for */
- continue;
- /* we are in case match_type == -1 and mismatch on last word */
- }
- if (y > matchlen) { /* remember the candidate */
- matchlen = y;
- cand = e;
- }
- }
- return e ? e : cand;
-}
-
-static char *find_best(char *argv[])
-{
- static char cmdline[80];
- int x;
- /* See how close we get, then print the candidate */
- char *myargv[AST_MAX_CMD_LEN];
- for (x=0;x<AST_MAX_CMD_LEN;x++)
- myargv[x]=NULL;
- AST_LIST_LOCK(&helpers);
- for (x=0;argv[x];x++) {
- myargv[x] = argv[x];
- if (!find_cli(myargv, -1))
- break;
- }
- AST_LIST_UNLOCK(&helpers);
- ast_join(cmdline, sizeof(cmdline), myargv);
- return cmdline;
-}
-
-static int __ast_cli_unregister(struct ast_cli_entry *e, struct ast_cli_entry *ed)
-{
- if (e->deprecate_cmd) {
- __ast_cli_unregister(e->deprecate_cmd, e);
- }
- if (e->inuse) {
- ast_log(LOG_WARNING, "Can't remove command that is in use\n");
- } else {
- AST_LIST_LOCK(&helpers);
- AST_LIST_REMOVE(&helpers, e, list);
- AST_LIST_UNLOCK(&helpers);
- free(e->_full_cmd);
- }
- return 0;
-}
-
-static int __ast_cli_register(struct ast_cli_entry *e, struct ast_cli_entry *ed)
-{
- struct ast_cli_entry *cur;
- char fulle[80] ="";
- int lf, ret = -1;
-
- ast_join(fulle, sizeof(fulle), e->cmda);
- AST_LIST_LOCK(&helpers);
-
- if (find_cli(e->cmda, 1)) {
- ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", fulle);
- goto done;
- }
- e->_full_cmd = ast_strdup(fulle);
- if (!e->_full_cmd)
- goto done;
-
- if (ed) {
- e->deprecated = 1;
- e->summary = ed->summary;
- e->usage = ed->usage;
- /* XXX If command A deprecates command B, and command B deprecates command C...
- Do we want to show command A or command B when telling the user to use new syntax?
- This currently would show command A.
- To show command B, you just need to always use ed->_full_cmd.
- */
- e->_deprecated_by = S_OR(ed->_deprecated_by, ed->_full_cmd);
- } else {
- e->deprecated = 0;
- }
-
- lf = strlen(fulle);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&helpers, cur, list) {
- int len = strlen(cur->_full_cmd);
- if (lf < len)
- len = lf;
- if (strncasecmp(fulle, cur->_full_cmd, len) < 0) {
- AST_LIST_INSERT_BEFORE_CURRENT(&helpers, e, list);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- if (!cur)
- AST_LIST_INSERT_TAIL(&helpers, e, list);
- ret = 0; /* success */
-
-done:
- AST_LIST_UNLOCK(&helpers);
-
- if (e->deprecate_cmd) {
- /* This command deprecates another command. Register that one also. */
- __ast_cli_register(e->deprecate_cmd, e);
- }
-
- return ret;
-}
-
-/* wrapper function, so we can unregister deprecated commands recursively */
-int ast_cli_unregister(struct ast_cli_entry *e)
-{
- return __ast_cli_unregister(e, NULL);
-}
-
-/* wrapper function, so we can register deprecated commands recursively */
-int ast_cli_register(struct ast_cli_entry *e)
-{
- return __ast_cli_register(e, NULL);
-}
-
-/*
- * register/unregister an array of entries.
- */
-void ast_cli_register_multiple(struct ast_cli_entry *e, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- ast_cli_register(e + i);
-}
-
-void ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- ast_cli_unregister(e + i);
-}
-
-
-/*! \brief helper for help_workhorse and final part of handle_help
- * if locked = 0 it's just help_workhorse, otherwise assume the
- * list is already locked.
- */
-static int help1(int fd, char *match[], int locked)
-{
- char matchstr[80] = "";
- struct ast_cli_entry *e;
- int len = 0;
- int found = 0;
- struct cli_iterator i = { NULL, NULL};
-
- if (match) {
- ast_join(matchstr, sizeof(matchstr), match);
- len = strlen(matchstr);
- }
- if (!locked)
- AST_LIST_LOCK(&helpers);
- while ( (e = cli_next(&i)) ) {
- /* Hide commands that start with '_' */
- if (e->_full_cmd[0] == '_')
- continue;
- /* Hide commands that are marked as deprecated. */
- if (e->deprecated)
- continue;
- if (match && strncasecmp(matchstr, e->_full_cmd, len))
- continue;
- ast_cli(fd, "%25.25s %s\n", e->_full_cmd, S_OR(e->summary, ""));
- found++;
- }
- if (!locked)
- AST_LIST_UNLOCK(&helpers);
- if (!found && matchstr[0])
- ast_cli(fd, "No such command '%s'.\n", matchstr);
- return RESULT_SUCCESS;
-}
-
-static int help_workhorse(int fd, char *match[])
-{
- return help1(fd, match, 0 /* do not print errors */);
-}
-
-static int handle_help(int fd, int argc, char *argv[])
-{
- char fullcmd[80];
- struct ast_cli_entry *e;
- int res = RESULT_SUCCESS;
-
- if (argc < 1)
- return RESULT_SHOWUSAGE;
- if (argc == 1)
- return help_workhorse(fd, NULL);
-
- AST_LIST_LOCK(&helpers);
- e = find_cli(argv + 1, 1); /* try exact match first */
- if (!e) {
- res = help1(fd, argv + 1, 1 /* locked */);
- AST_LIST_UNLOCK(&helpers);
- return res;
- }
- if (e->usage)
- ast_cli(fd, "%s", e->usage);
- else {
- ast_join(fullcmd, sizeof(fullcmd), argv+1);
- ast_cli(fd, "No help text available for '%s'.\n", fullcmd);
- }
- AST_LIST_UNLOCK(&helpers);
- return res;
-}
-
-static char *parse_args(const char *s, int *argc, char *argv[], int max, int *trailingwhitespace)
-{
- char *dup, *cur;
- int x = 0;
- int quoted = 0;
- int escaped = 0;
- int whitespace = 1;
-
- *trailingwhitespace = 0;
- if (s == NULL) /* invalid, though! */
- return NULL;
- /* make a copy to store the parsed string */
- if (!(dup = ast_strdup(s)))
- return NULL;
-
- cur = dup;
- /* scan the original string copying into cur when needed */
- for (; *s ; s++) {
- if (x >= max - 1) {
- ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
- break;
- }
- if (*s == '"' && !escaped) {
- quoted = !quoted;
- if (quoted && whitespace) {
- /* start a quoted string from previous whitespace: new argument */
- argv[x++] = cur;
- whitespace = 0;
- }
- } else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
- /* If we are not already in whitespace, and not in a quoted string or
- processing an escape sequence, and just entered whitespace, then
- finalize the previous argument and remember that we are in whitespace
- */
- if (!whitespace) {
- *cur++ = '\0';
- whitespace = 1;
- }
- } else if (*s == '\\' && !escaped) {
- escaped = 1;
- } else {
- if (whitespace) {
- /* we leave whitespace, and are not quoted. So it's a new argument */
- argv[x++] = cur;
- whitespace = 0;
- }
- *cur++ = *s;
- escaped = 0;
- }
- }
- /* Null terminate */
- *cur++ = '\0';
- /* XXX put a NULL in the last argument, because some functions that take
- * the array may want a null-terminated array.
- * argc still reflects the number of non-NULL entries.
- */
- argv[x] = NULL;
- *argc = x;
- *trailingwhitespace = whitespace;
- return dup;
-}
-
-/*! \brief Return the number of unique matches for the generator */
-int ast_cli_generatornummatches(const char *text, const char *word)
-{
- int matches = 0, i = 0;
- char *buf = NULL, *oldbuf = NULL;
-
- while ((buf = ast_cli_generator(text, word, i++))) {
- if (!oldbuf || strcmp(buf,oldbuf))
- matches++;
- if (oldbuf)
- free(oldbuf);
- oldbuf = buf;
- }
- if (oldbuf)
- free(oldbuf);
- return matches;
-}
-
-char **ast_cli_completion_matches(const char *text, const char *word)
-{
- char **match_list = NULL, *retstr, *prevstr;
- size_t match_list_len, max_equal, which, i;
- int matches = 0;
-
- /* leave entry 0 free for the longest common substring */
- match_list_len = 1;
- while ((retstr = ast_cli_generator(text, word, matches)) != NULL) {
- if (matches + 1 >= match_list_len) {
- match_list_len <<= 1;
- if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(*match_list))))
- return NULL;
- }
- match_list[++matches] = retstr;
- }
-
- if (!match_list)
- return match_list; /* NULL */
-
- /* Find the longest substring that is common to all results
- * (it is a candidate for completion), and store a copy in entry 0.
- */
- prevstr = match_list[1];
- max_equal = strlen(prevstr);
- for (which = 2; which <= matches; which++) {
- for (i = 0; i < max_equal && toupper(prevstr[i]) == toupper(match_list[which][i]); i++)
- continue;
- max_equal = i;
- }
-
- if (!(retstr = ast_malloc(max_equal + 1)))
- return NULL;
-
- ast_copy_string(retstr, match_list[1], max_equal + 1);
- match_list[0] = retstr;
-
- /* ensure that the array is NULL terminated */
- if (matches + 1 >= match_list_len) {
- if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(*match_list))))
- return NULL;
- }
- match_list[matches + 1] = NULL;
-
- return match_list;
-}
-
-static char *__ast_cli_generator(const char *text, const char *word, int state, int lock)
-{
- char *argv[AST_MAX_ARGS];
- struct ast_cli_entry *e;
- struct cli_iterator i = { NULL, NULL };
- int x = 0, argindex, matchlen;
- int matchnum=0;
- char *ret = NULL;
- char matchstr[80] = "";
- int tws = 0;
- char *dup = parse_args(text, &x, argv, sizeof(argv) / sizeof(argv[0]), &tws);
-
- if (!dup) /* error */
- return NULL;
- argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
- /* rebuild the command, ignore tws */
- ast_join(matchstr, sizeof(matchstr)-1, argv);
- matchlen = strlen(matchstr);
- if (tws) {
- strcat(matchstr, " "); /* XXX */
- if (matchlen)
- matchlen++;
- }
- if (lock)
- AST_LIST_LOCK(&helpers);
- while( !ret && (e = cli_next(&i)) ) {
- int lc = strlen(e->_full_cmd);
- if (e->_full_cmd[0] != '_' && lc > 0 && matchlen <= lc &&
- !strncasecmp(matchstr, e->_full_cmd, matchlen)) {
- /* Found initial part, return a copy of the next word... */
- if (e->cmda[argindex] && ++matchnum > state)
- ret = strdup(e->cmda[argindex]); /* we need a malloced string */
- } else if (e->generator && !strncasecmp(matchstr, e->_full_cmd, lc) && matchstr[lc] < 33) {
- /* We have a command in its entirity within us -- theoretically only one
- command can have this occur */
- ret = e->generator(matchstr, word, argindex, state);
- }
- }
- if (lock)
- AST_LIST_UNLOCK(&helpers);
- free(dup);
- return ret;
-}
-
-char *ast_cli_generator(const char *text, const char *word, int state)
-{
- return __ast_cli_generator(text, word, state, 1);
-}
-
-int ast_cli_command(int fd, const char *s)
-{
- char *argv[AST_MAX_ARGS];
- struct ast_cli_entry *e;
- int x;
- char *dup;
- int tws;
-
- if (!(dup = parse_args(s, &x, argv, sizeof(argv) / sizeof(argv[0]), &tws)))
- return -1;
-
- /* We need at least one entry, or ignore */
- if (x > 0) {
- AST_LIST_LOCK(&helpers);
- e = find_cli(argv, 0);
- if (e)
- e->inuse++;
- AST_LIST_UNLOCK(&helpers);
- if (e) {
- switch(e->handler(fd, x, argv)) {
- case RESULT_SHOWUSAGE:
- if (e->usage)
- ast_cli(fd, "%s", e->usage);
- else
- ast_cli(fd, "Invalid usage, but no usage information available.\n");
- AST_LIST_LOCK(&helpers);
- if (e->deprecated)
- ast_cli(fd, "The '%s' command is deprecated and will be removed in a future release. Please use '%s' instead.\n", e->_full_cmd, e->_deprecated_by);
- AST_LIST_UNLOCK(&helpers);
- break;
- default:
- AST_LIST_LOCK(&helpers);
- if (e->deprecated == 1) {
- ast_cli(fd, "The '%s' command is deprecated and will be removed in a future release. Please use '%s' instead.\n", e->_full_cmd, e->_deprecated_by);
- e->deprecated = 2;
- }
- AST_LIST_UNLOCK(&helpers);
- break;
- }
- } else
- ast_cli(fd, "No such command '%s' (type 'help %s' for other possible commands)\n", s, find_best(argv));
- if (e)
- ast_atomic_fetchadd_int(&e->inuse, -1);
- }
- free(dup);
-
- return 0;
-}
-
-int ast_cli_command_multiple(int fd, size_t size, const char *s)
-{
- char cmd[512];
- int x, y = 0, count = 0;
-
- for (x = 0; x < size; x++) {
- cmd[y] = s[x];
- y++;
- if (s[x] == '\0') {
- ast_cli_command(fd, cmd);
- y = 0;
- count++;
- }
- }
- return count;
-}
diff --git a/main/coef_in.h b/main/coef_in.h
deleted file mode 100644
index 9aba022f6..000000000
--- a/main/coef_in.h
+++ /dev/null
@@ -1,13 +0,0 @@
- { { 1.8229206611e-04,-7.8997325866e-01,2.2401819940e+00,-4.6751353581e+00,5.5080745712e+00,-5.0571565772e+00,2.6215820004e+00,0.0000000000e+00,
- }, { 9.8532175289e-02,-5.6297236492e-02,3.3146713415e-01,-9.2239200436e-01,1.4844365184e+00,-2.0183258642e+00,2.0074154497e+00,0.0000000000e+00,
- }, }, { { 1.8229206610e-04,-7.8997325866e-01,7.7191410839e-01,-2.8075643964e+00,1.6948618347e+00,-3.0367273700e+00,9.0333559408e-01,0.0000000000e+00,
- }, { 9.8531161839e-02,-5.6297236492e-02,1.1421579050e-01,-4.8122536483e-01,4.0121072432e-01,-7.4834487567e-01,6.9170822332e-01,0.0000000000e+00,
- }, }, { { 1.8229206611e-04,-7.8997325866e-01,2.9003821430e+00,-6.1082779024e+00,7.7169345751e+00,-6.6075999680e+00,3.3941838836e+00,0.0000000000e+00,
- }, { 9.8539686961e-02,-5.6297236492e-02,4.2915323820e-01,-1.2609358633e+00,2.2399213250e+00,-2.9928879142e+00,2.5990173742e+00,0.0000000000e+00,
- }, }, { { 1.8229206610e-04,-7.8997325866e-01,-7.7191410839e-01,-2.8075643964e+00,-1.6948618347e+00,-3.0367273700e+00,-9.0333559408e-01,0.0000000000e+00,
- }, { 9.8531161839e-02,-5.6297236492e-02,-1.1421579050e-01,-4.8122536483e-01,-4.0121072432e-01,-7.4834487567e-01,-6.9170822332e-01,0.0000000000e+00,
- }, }, { { 1.8229206611e-04,-7.8997325866e-01,2.5782298908e+00,-5.3629717478e+00,6.5890882172e+00,-5.8012914776e+00,3.0171839130e+00,0.0000000000e+00,
- }, { 9.8534230718e-02,-5.6297236492e-02,3.8148618075e-01,-1.0848760410e+00,1.8441165168e+00,-2.4860666655e+00,2.3103384142e+00,0.0000000000e+00,
- }, }, { { 1.8229206610e-04,-7.8997325866e-01,-3.8715051001e-01,-2.6192408538e+00,-8.3977994034e-01,-2.8329897913e+00,-4.5306444352e-01,0.0000000000e+00,
- }, { 9.8531160936e-02,-5.6297236492e-02,-5.7284484199e-02,-4.3673866734e-01,-1.9564766257e-01,-6.2028156584e-01,-3.4692356122e-01,0.0000000000e+00,
- }, },
diff --git a/main/coef_out.h b/main/coef_out.h
deleted file mode 100644
index d80f5c490..000000000
--- a/main/coef_out.h
+++ /dev/null
@@ -1,4 +0,0 @@
- { 1.3868644653e-08,-6.3283665042e-01,4.0895057217e+00,-1.1020074592e+01,1.5850766191e+01,-1.2835109292e+01,5.5477477340e+00,0.0000000000e+00,
- }, { 3.1262119724e-03,-7.8390522307e-03,8.5209627801e-02,-4.0804129163e-01,1.1157139955e+00,-1.8767603680e+00,1.8916395224e+00,0.0000000000e+00
- },
-
diff --git a/main/config.c b/main/config.c
deleted file mode 100644
index 6163f827a..000000000
--- a/main/config.c
+++ /dev/null
@@ -1,1520 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Configuration File Parser
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * Includes the Asterisk Realtime API - ARA
- * See doc/realtime.txt and doc/extconfig.txt
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/stat.h>
-#define AST_INCLUDE_GLOB 1
-#ifdef AST_INCLUDE_GLOB
-#if defined(__Darwin__) || defined(__CYGWIN__)
-#define GLOB_ABORTED GLOB_ABEND
-#endif
-# include <glob.h>
-#endif
-
-#include "asterisk/config.h"
-#include "asterisk/cli.h"
-#include "asterisk/lock.h"
-#include "asterisk/options.h"
-#include "asterisk/logger.h"
-#include "asterisk/utils.h"
-#include "asterisk/channel.h"
-#include "asterisk/app.h"
-
-#define MAX_NESTED_COMMENTS 128
-#define COMMENT_START ";--"
-#define COMMENT_END "--;"
-#define COMMENT_META ';'
-#define COMMENT_TAG '-'
-
-static char *extconfig_conf = "extconfig.conf";
-
-
-/*! \brief Structure to keep comments for rewriting configuration files */
-struct ast_comment {
- struct ast_comment *next;
- char cmt[0];
-};
-
-#define CB_INCR 250
-
-static void CB_INIT(char **comment_buffer, int *comment_buffer_size, char **lline_buffer, int *lline_buffer_size)
-{
- if (!(*comment_buffer)) {
- *comment_buffer = ast_malloc(CB_INCR);
- if (!(*comment_buffer))
- return;
- (*comment_buffer)[0] = 0;
- *comment_buffer_size = CB_INCR;
- *lline_buffer = ast_malloc(CB_INCR);
- if (!(*lline_buffer))
- return;
- (*lline_buffer)[0] = 0;
- *lline_buffer_size = CB_INCR;
- } else {
- (*comment_buffer)[0] = 0;
- (*lline_buffer)[0] = 0;
- }
-}
-
-static void CB_ADD(char **comment_buffer, int *comment_buffer_size, char *str)
-{
- int rem = *comment_buffer_size - strlen(*comment_buffer) - 1;
- int siz = strlen(str);
- if (rem < siz+1) {
- *comment_buffer = ast_realloc(*comment_buffer, *comment_buffer_size + CB_INCR + siz + 1);
- if (!(*comment_buffer))
- return;
- *comment_buffer_size += CB_INCR+siz+1;
- }
- strcat(*comment_buffer,str);
-}
-
-static void CB_ADD_LEN(char **comment_buffer, int *comment_buffer_size, char *str, int len)
-{
- int cbl = strlen(*comment_buffer) + 1;
- int rem = *comment_buffer_size - cbl;
- if (rem < len+1) {
- *comment_buffer = ast_realloc(*comment_buffer, *comment_buffer_size + CB_INCR + len + 1);
- if (!(*comment_buffer))
- return;
- *comment_buffer_size += CB_INCR+len+1;
- }
- strncat(*comment_buffer,str,len);
- (*comment_buffer)[cbl+len-1] = 0;
-}
-
-static void LLB_ADD(char **lline_buffer, int *lline_buffer_size, char *str)
-{
- int rem = *lline_buffer_size - strlen(*lline_buffer) - 1;
- int siz = strlen(str);
- if (rem < siz+1) {
- *lline_buffer = ast_realloc(*lline_buffer, *lline_buffer_size + CB_INCR + siz + 1);
- if (!(*lline_buffer))
- return;
- *lline_buffer_size += CB_INCR + siz + 1;
- }
- strcat(*lline_buffer,str);
-}
-
-static void CB_RESET(char **comment_buffer, char **lline_buffer)
-{
- (*comment_buffer)[0] = 0;
- (*lline_buffer)[0] = 0;
-}
-
-
-static struct ast_comment *ALLOC_COMMENT(const char *buffer)
-{
- struct ast_comment *x = ast_calloc(1,sizeof(struct ast_comment)+strlen(buffer)+1);
- strcpy(x->cmt, buffer);
- return x;
-}
-
-
-static struct ast_config_map {
- struct ast_config_map *next;
- char *name;
- char *driver;
- char *database;
- char *table;
- char stuff[0];
-} *config_maps = NULL;
-
-AST_MUTEX_DEFINE_STATIC(config_lock);
-static struct ast_config_engine *config_engine_list;
-
-#define MAX_INCLUDE_LEVEL 10
-
-struct ast_category_template_instance {
- char name[80]; /* redundant? */
- const struct ast_category *inst;
- AST_LIST_ENTRY(ast_category_template_instance) next;
-};
-
-struct ast_category {
- char name[80];
- int ignored; /*!< do not let user of the config see this category */
- int include_level;
- AST_LIST_HEAD_NOLOCK(template_instance_list, ast_category_template_instance) template_instances;
- struct ast_comment *precomments;
- struct ast_comment *sameline;
- struct ast_variable *root;
- struct ast_variable *last;
- struct ast_category *next;
-};
-
-struct ast_config {
- struct ast_category *root;
- struct ast_category *last;
- struct ast_category *current;
- struct ast_category *last_browse; /*!< used to cache the last category supplied via category_browse */
- int include_level;
- int max_include_level;
-};
-
-struct ast_variable *ast_variable_new(const char *name, const char *value)
-{
- struct ast_variable *variable;
- int name_len = strlen(name) + 1;
-
- if ((variable = ast_calloc(1, name_len + strlen(value) + 1 + sizeof(*variable)))) {
- variable->name = variable->stuff;
- variable->value = variable->stuff + name_len;
- strcpy(variable->name,name);
- strcpy(variable->value,value);
- }
-
- return variable;
-}
-
-void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
-{
- if (!variable)
- return;
- if (category->last)
- category->last->next = variable;
- else
- category->root = variable;
- category->last = variable;
- while (category->last->next)
- category->last = category->last->next;
-}
-
-void ast_variables_destroy(struct ast_variable *v)
-{
- struct ast_variable *vn;
-
- while(v) {
- vn = v;
- v = v->next;
- free(vn);
- }
-}
-
-struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category)
-{
- struct ast_category *cat = NULL;
-
- if (category && config->last_browse && (config->last_browse->name == category))
- cat = config->last_browse;
- else
- cat = ast_category_get(config, category);
-
- return (cat) ? cat->root : NULL;
-}
-
-const char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
-{
- const char *tmp;
- tmp = ast_variable_retrieve(cfg, cat, var);
- if (!tmp)
- tmp = ast_variable_retrieve(cfg, "general", var);
- return tmp;
-}
-
-
-const char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
-{
- struct ast_variable *v;
-
- if (category) {
- for (v = ast_variable_browse(config, category); v; v = v->next) {
- if (!strcasecmp(variable, v->name))
- return v->value;
- }
- } else {
- struct ast_category *cat;
-
- for (cat = config->root; cat; cat = cat->next)
- for (v = cat->root; v; v = v->next)
- if (!strcasecmp(variable, v->name))
- return v->value;
- }
-
- return NULL;
-}
-
-static struct ast_variable *variable_clone(const struct ast_variable *old)
-{
- struct ast_variable *new = ast_variable_new(old->name, old->value);
-
- if (new) {
- new->lineno = old->lineno;
- new->object = old->object;
- new->blanklines = old->blanklines;
- /* TODO: clone comments? */
- }
-
- return new;
-}
-
-static void move_variables(struct ast_category *old, struct ast_category *new)
-{
- struct ast_variable *var = old->root;
- old->root = NULL;
-#if 1
- /* we can just move the entire list in a single op */
- ast_variable_append(new, var);
-#else
- while (var) {
- struct ast_variable *next = var->next;
- var->next = NULL;
- ast_variable_append(new, var);
- var = next;
- }
-#endif
-}
-
-struct ast_category *ast_category_new(const char *name)
-{
- struct ast_category *category;
-
- if ((category = ast_calloc(1, sizeof(*category))))
- ast_copy_string(category->name, name, sizeof(category->name));
- return category;
-}
-
-static struct ast_category *category_get(const struct ast_config *config, const char *category_name, int ignored)
-{
- struct ast_category *cat;
-
- /* try exact match first, then case-insensitive match */
- for (cat = config->root; cat; cat = cat->next) {
- if (cat->name == category_name && (ignored || !cat->ignored))
- return cat;
- }
-
- for (cat = config->root; cat; cat = cat->next) {
- if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
- return cat;
- }
-
- return NULL;
-}
-
-struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name)
-{
- return category_get(config, category_name, 0);
-}
-
-int ast_category_exist(const struct ast_config *config, const char *category_name)
-{
- return !!ast_category_get(config, category_name);
-}
-
-void ast_category_append(struct ast_config *config, struct ast_category *category)
-{
- if (config->last)
- config->last->next = category;
- else
- config->root = category;
- category->include_level = config->include_level;
- config->last = category;
- config->current = category;
-}
-
-static void ast_destroy_comments(struct ast_category *cat)
-{
- struct ast_comment *n, *p;
- for (p=cat->precomments; p; p=n) {
- n = p->next;
- free(p);
- }
- for (p=cat->sameline; p; p=n) {
- n = p->next;
- free(p);
- }
- cat->precomments = NULL;
- cat->sameline = NULL;
-}
-
-static void ast_destroy_template_list(struct ast_category *cat)
-{
- struct ast_category_template_instance *x;
- AST_LIST_TRAVERSE_SAFE_BEGIN(&cat->template_instances, x, next) {
- AST_LIST_REMOVE_CURRENT(&cat->template_instances, next);
- free(x);
- }
- AST_LIST_TRAVERSE_SAFE_END;
-}
-
-void ast_category_destroy(struct ast_category *cat)
-{
- ast_variables_destroy(cat->root);
- ast_destroy_comments(cat);
- ast_destroy_template_list(cat);
- free(cat);
-}
-
-static struct ast_category *next_available_category(struct ast_category *cat)
-{
- for (; cat && cat->ignored; cat = cat->next);
-
- return cat;
-}
-
-struct ast_variable *ast_category_root(struct ast_config *config, char *cat)
-{
- struct ast_category *category = ast_category_get(config, cat);
- if (category)
- return category->root;
- return NULL;
-}
-
-char *ast_category_browse(struct ast_config *config, const char *prev)
-{
- struct ast_category *cat = NULL;
-
- if (prev && config->last_browse && (config->last_browse->name == prev))
- cat = config->last_browse->next;
- else if (!prev && config->root)
- cat = config->root;
- else if (prev) {
- for (cat = config->root; cat; cat = cat->next) {
- if (cat->name == prev) {
- cat = cat->next;
- break;
- }
- }
- if (!cat) {
- for (cat = config->root; cat; cat = cat->next) {
- if (!strcasecmp(cat->name, prev)) {
- cat = cat->next;
- break;
- }
- }
- }
- }
-
- if (cat)
- cat = next_available_category(cat);
-
- config->last_browse = cat;
- return (cat) ? cat->name : NULL;
-}
-
-struct ast_variable *ast_category_detach_variables(struct ast_category *cat)
-{
- struct ast_variable *v;
-
- v = cat->root;
- cat->root = NULL;
- cat->last = NULL;
-
- return v;
-}
-
-void ast_category_rename(struct ast_category *cat, const char *name)
-{
- ast_copy_string(cat->name, name, sizeof(cat->name));
-}
-
-static void inherit_category(struct ast_category *new, const struct ast_category *base)
-{
- struct ast_variable *var;
- struct ast_category_template_instance *x = ast_calloc(1,sizeof(struct ast_category_template_instance));
- strcpy(x->name, base->name);
- x->inst = base;
- AST_LIST_INSERT_TAIL(&new->template_instances, x, next);
- for (var = base->root; var; var = var->next)
- ast_variable_append(new, variable_clone(var));
-}
-
-struct ast_config *ast_config_new(void)
-{
- struct ast_config *config;
-
- if ((config = ast_calloc(1, sizeof(*config))))
- config->max_include_level = MAX_INCLUDE_LEVEL;
- return config;
-}
-
-int ast_variable_delete(struct ast_category *category, char *variable, char *match)
-{
- struct ast_variable *cur, *prev=NULL, *curn;
- int res = -1;
- cur = category->root;
- while (cur) {
- if (cur->name == variable) {
- if (prev) {
- prev->next = cur->next;
- if (cur == category->last)
- category->last = prev;
- } else {
- category->root = cur->next;
- if (cur == category->last)
- category->last = NULL;
- }
- cur->next = NULL;
- ast_variables_destroy(cur);
- return 0;
- }
- prev = cur;
- cur = cur->next;
- }
-
- prev = NULL;
- cur = category->root;
- while (cur) {
- curn = cur->next;
- if (!strcasecmp(cur->name, variable) && (ast_strlen_zero(match) || !strcasecmp(cur->value, match))) {
- if (prev) {
- prev->next = cur->next;
- if (cur == category->last)
- category->last = prev;
- } else {
- category->root = cur->next;
- if (cur == category->last)
- category->last = NULL;
- }
- cur->next = NULL;
- ast_variables_destroy(cur);
- res = 0;
- } else
- prev = cur;
-
- cur = curn;
- }
- return res;
-}
-
-int ast_variable_update(struct ast_category *category, const char *variable,
- const char *value, const char *match, unsigned int object)
-{
- struct ast_variable *cur, *prev=NULL, *newer;
-
- if (!(newer = ast_variable_new(variable, value)))
- return -1;
-
- newer->object = object;
-
- for (cur = category->root; cur; prev = cur, cur = cur->next) {
- if (strcasecmp(cur->name, variable) ||
- (!ast_strlen_zero(match) && strcasecmp(cur->value, match)))
- continue;
-
- newer->next = cur->next;
- newer->object = cur->object || object;
- if (prev)
- prev->next = newer;
- else
- category->root = newer;
- if (category->last == cur)
- category->last = newer;
-
- cur->next = NULL;
- ast_variables_destroy(cur);
-
- return 0;
- }
-
- if (prev)
- prev->next = newer;
- else
- category->root = newer;
-
- return 0;
-}
-
-int ast_category_delete(struct ast_config *cfg, char *category)
-{
- struct ast_category *prev=NULL, *cat;
- cat = cfg->root;
- while(cat) {
- if (cat->name == category) {
- if (prev) {
- prev->next = cat->next;
- if (cat == cfg->last)
- cfg->last = prev;
- } else {
- cfg->root = cat->next;
- if (cat == cfg->last)
- cfg->last = NULL;
- }
- ast_category_destroy(cat);
- return 0;
- }
- prev = cat;
- cat = cat->next;
- }
-
- prev = NULL;
- cat = cfg->root;
- while(cat) {
- if (!strcasecmp(cat->name, category)) {
- if (prev) {
- prev->next = cat->next;
- if (cat == cfg->last)
- cfg->last = prev;
- } else {
- cfg->root = cat->next;
- if (cat == cfg->last)
- cfg->last = NULL;
- }
- ast_category_destroy(cat);
- return 0;
- }
- prev = cat;
- cat = cat->next;
- }
- return -1;
-}
-
-void ast_config_destroy(struct ast_config *cfg)
-{
- struct ast_category *cat, *catn;
-
- if (!cfg)
- return;
-
- cat = cfg->root;
- while(cat) {
- catn = cat;
- cat = cat->next;
- ast_category_destroy(catn);
- }
- free(cfg);
-}
-
-struct ast_category *ast_config_get_current_category(const struct ast_config *cfg)
-{
- return cfg->current;
-}
-
-void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat)
-{
- /* cast below is just to silence compiler warning about dropping "const" */
- cfg->current = (struct ast_category *) cat;
-}
-
-static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, int withcomments,
- char **comment_buffer, int *comment_buffer_size, char **lline_buffer, int *lline_buffer_size)
-{
- char *c;
- char *cur = buf;
- struct ast_variable *v;
- char cmd[512], exec_file[512];
- int object, do_exec, do_include;
-
- /* Actually parse the entry */
- if (cur[0] == '[') {
- struct ast_category *newcat = NULL;
- char *catname;
-
- /* A category header */
- c = strchr(cur, ']');
- if (!c) {
- ast_log(LOG_WARNING, "parse error: no closing ']', line %d of %s\n", lineno, configfile);
- return -1;
- }
- *c++ = '\0';
- cur++;
- if (*c++ != '(')
- c = NULL;
- catname = cur;
- if (!(*cat = newcat = ast_category_new(catname))) {
- return -1;
- }
- /* add comments */
- if (withcomments && *comment_buffer && (*comment_buffer)[0] ) {
- newcat->precomments = ALLOC_COMMENT(*comment_buffer);
- }
- if (withcomments && *lline_buffer && (*lline_buffer)[0] ) {
- newcat->sameline = ALLOC_COMMENT(*lline_buffer);
- }
- if( withcomments )
- CB_RESET(comment_buffer, lline_buffer);
-
- /* If there are options or categories to inherit from, process them now */
- if (c) {
- if (!(cur = strchr(c, ')'))) {
- ast_log(LOG_WARNING, "parse error: no closing ')', line %d of %s\n", lineno, configfile);
- return -1;
- }
- *cur = '\0';
- while ((cur = strsep(&c, ","))) {
- if (!strcasecmp(cur, "!")) {
- (*cat)->ignored = 1;
- } else if (!strcasecmp(cur, "+")) {
- *cat = category_get(cfg, catname, 1);
- if (!(*cat)) {
- if (newcat)
- ast_category_destroy(newcat);
- ast_log(LOG_WARNING, "Category addition requested, but category '%s' does not exist, line %d of %s\n", catname, lineno, configfile);
- return -1;
- }
- if (newcat) {
- move_variables(newcat, *cat);
- ast_category_destroy(newcat);
- newcat = NULL;
- }
- } else {
- struct ast_category *base;
-
- base = category_get(cfg, cur, 1);
- if (!base) {
- ast_log(LOG_WARNING, "Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur, lineno, configfile);
- return -1;
- }
- inherit_category(*cat, base);
- }
- }
- }
- if (newcat)
- ast_category_append(cfg, *cat);
- } else if (cur[0] == '#') {
- /* A directive */
- cur++;
- c = cur;
- while(*c && (*c > 32)) c++;
- if (*c) {
- *c = '\0';
- /* Find real argument */
- c = ast_skip_blanks(c + 1);
- if (!(*c))
- c = NULL;
- } else
- c = NULL;
- do_include = !strcasecmp(cur, "include");
- if(!do_include)
- do_exec = !strcasecmp(cur, "exec");
- else
- do_exec = 0;
- if (do_exec && !ast_opt_exec_includes) {
- ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
- do_exec = 0;
- }
- if (do_include || do_exec) {
- if (c) {
- /* Strip off leading and trailing "'s and <>'s */
- while((*c == '<') || (*c == '>') || (*c == '\"')) c++;
- /* Get rid of leading mess */
- cur = c;
- while (!ast_strlen_zero(cur)) {
- c = cur + strlen(cur) - 1;
- if ((*c == '>') || (*c == '<') || (*c == '\"'))
- *c = '\0';
- else
- break;
- }
- /* #exec </path/to/executable>
- We create a tmp file, then we #include it, then we delete it. */
- if (do_exec) {
- snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self());
- snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file);
- ast_safe_system(cmd);
- cur = exec_file;
- } else
- exec_file[0] = '\0';
- /* A #include */
- do_include = ast_config_internal_load(cur, cfg, withcomments) ? 1 : 0;
- if(!ast_strlen_zero(exec_file))
- unlink(exec_file);
- if (!do_include) {
- ast_log(LOG_ERROR, "*********************************************************\n");
- ast_log(LOG_ERROR, "*********** YOU SHOULD REALLY READ THIS ERROR ***********\n");
- ast_log(LOG_ERROR, "Future versions of Asterisk will treat a #include of a "
- "file that does not exist as an error, and will fail to "
- "load that configuration file. Please ensure that the "
- "file '%s' exists, even if it is empty.\n", cur);
- ast_log(LOG_ERROR, "*********** YOU SHOULD REALLY READ THIS ERROR ***********\n");
- ast_log(LOG_ERROR, "*********************************************************\n");
- return 0;
- }
-
- } else {
- ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n",
- do_exec ? "exec" : "include",
- do_exec ? "/path/to/executable" : "filename",
- lineno,
- configfile);
- }
- }
- else
- ast_log(LOG_WARNING, "Unknown directive '#%s' at line %d of %s\n", cur, lineno, configfile);
- } else {
- /* Just a line (variable = value) */
- if (!(*cat)) {
- ast_log(LOG_WARNING,
- "parse error: No category context for line %d of %s\n", lineno, configfile);
- return -1;
- }
- c = strchr(cur, '=');
- if (c) {
- *c = 0;
- c++;
- /* Ignore > in => */
- if (*c== '>') {
- object = 1;
- c++;
- } else
- object = 0;
- if ((v = ast_variable_new(ast_strip(cur), ast_strip(c)))) {
- v->lineno = lineno;
- v->object = object;
- /* Put and reset comments */
- v->blanklines = 0;
- ast_variable_append(*cat, v);
- /* add comments */
- if (withcomments && *comment_buffer && (*comment_buffer)[0] ) {
- v->precomments = ALLOC_COMMENT(*comment_buffer);
- }
- if (withcomments && *lline_buffer && (*lline_buffer)[0] ) {
- v->sameline = ALLOC_COMMENT(*lline_buffer);
- }
- if( withcomments )
- CB_RESET(comment_buffer, lline_buffer);
-
- } else {
- return -1;
- }
- } else {
- ast_log(LOG_WARNING, "No '=' (equal sign) in line %d of %s\n", lineno, configfile);
- }
- }
- return 0;
-}
-
-static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments)
-{
- char fn[256];
-#if defined(LOW_MEMORY)
- char buf[512];
-#else
- char buf[8192];
-#endif
- char *new_buf, *comment_p, *process_buf;
- FILE *f;
- int lineno=0;
- int comment = 0, nest[MAX_NESTED_COMMENTS];
- struct ast_category *cat = NULL;
- int count = 0;
- struct stat statbuf;
- /*! Growable string buffer */
- char *comment_buffer=0; /*!< this will be a comment collector.*/
- int comment_buffer_size=0; /*!< the amount of storage so far alloc'd for the comment_buffer */
-
- char *lline_buffer=0; /*!< A buffer for stuff behind the ; */
- int lline_buffer_size=0;
-
-
- cat = ast_config_get_current_category(cfg);
-
- if (filename[0] == '/') {
- ast_copy_string(fn, filename, sizeof(fn));
- } else {
- snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, filename);
- }
-
- if (withcomments) {
- CB_INIT(&comment_buffer, &comment_buffer_size, &lline_buffer, &lline_buffer_size);
- if (!lline_buffer || !comment_buffer) {
- ast_log(LOG_ERROR, "Failed to initialize the comment buffer!\n");
- return NULL;
- }
- }
-#ifdef AST_INCLUDE_GLOB
- {
- int glob_ret;
- glob_t globbuf;
- globbuf.gl_offs = 0; /* initialize it to silence gcc */
-#ifdef SOLARIS
- glob_ret = glob(fn, GLOB_NOCHECK, NULL, &globbuf);
-#else
- glob_ret = glob(fn, GLOB_NOMAGIC|GLOB_BRACE, NULL, &globbuf);
-#endif
- if (glob_ret == GLOB_NOSPACE)
- ast_log(LOG_WARNING,
- "Glob Expansion of pattern '%s' failed: Not enough memory\n", fn);
- else if (glob_ret == GLOB_ABORTED)
- ast_log(LOG_WARNING,
- "Glob Expansion of pattern '%s' failed: Read error\n", fn);
- else {
- /* loop over expanded files */
- int i;
- for (i=0; i<globbuf.gl_pathc; i++) {
- ast_copy_string(fn, globbuf.gl_pathv[i], sizeof(fn));
-#endif
- do {
- if (stat(fn, &statbuf))
- continue;
-
- if (!S_ISREG(statbuf.st_mode)) {
- ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn);
- continue;
- }
- if (option_verbose > 1) {
- ast_verbose(VERBOSE_PREFIX_2 "Parsing '%s': ", fn);
- fflush(stdout);
- }
- if (!(f = fopen(fn, "r"))) {
- if (option_debug)
- ast_log(LOG_DEBUG, "No file to parse: %s\n", fn);
- if (option_verbose > 1)
- ast_verbose( "Not found (%s)\n", strerror(errno));
- continue;
- }
- count++;
- if (option_debug)
- ast_log(LOG_DEBUG, "Parsing %s\n", fn);
- if (option_verbose > 1)
- ast_verbose("Found\n");
- while(!feof(f)) {
- lineno++;
- if (fgets(buf, sizeof(buf), f)) {
- if ( withcomments ) {
- CB_ADD(&comment_buffer, &comment_buffer_size, lline_buffer); /* add the current lline buffer to the comment buffer */
- lline_buffer[0] = 0; /* erase the lline buffer */
- }
-
- new_buf = buf;
- if (comment)
- process_buf = NULL;
- else
- process_buf = buf;
-
- while ((comment_p = strchr(new_buf, COMMENT_META))) {
- if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) {
- /* Escaped semicolons aren't comments. */
- new_buf = comment_p + 1;
- } else if(comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) {
- /* Meta-Comment start detected ";--" */
- if (comment < MAX_NESTED_COMMENTS) {
- *comment_p = '\0';
- new_buf = comment_p + 3;
- comment++;
- nest[comment-1] = lineno;
- } else {
- ast_log(LOG_ERROR, "Maximum nest limit of %d reached.\n", MAX_NESTED_COMMENTS);
- }
- } else if ((comment_p >= new_buf + 2) &&
- (*(comment_p - 1) == COMMENT_TAG) &&
- (*(comment_p - 2) == COMMENT_TAG)) {
- /* Meta-Comment end detected */
- comment--;
- new_buf = comment_p + 1;
- if (!comment) {
- /* Back to non-comment now */
- if (process_buf) {
- /* Actually have to move what's left over the top, then continue */
- char *oldptr;
- oldptr = process_buf + strlen(process_buf);
- if ( withcomments ) {
- CB_ADD(&comment_buffer, &comment_buffer_size, ";");
- CB_ADD_LEN(&comment_buffer, &comment_buffer_size, oldptr+1, new_buf-oldptr-1);
- }
-
- memmove(oldptr, new_buf, strlen(new_buf) + 1);
- new_buf = oldptr;
- } else
- process_buf = new_buf;
- }
- } else {
- if (!comment) {
- /* If ; is found, and we are not nested in a comment,
- we immediately stop all comment processing */
- if ( withcomments ) {
- LLB_ADD(&lline_buffer, &lline_buffer_size, comment_p);
- }
- *comment_p = '\0';
- new_buf = comment_p;
- } else
- new_buf = comment_p + 1;
- }
- }
- if( withcomments && comment && !process_buf )
- {
- CB_ADD(&comment_buffer, &comment_buffer_size, buf); /* the whole line is a comment, store it */
- }
-
- if (process_buf) {
- char *buf = ast_strip(process_buf);
- if (!ast_strlen_zero(buf)) {
- if (process_text_line(cfg, &cat, buf, lineno, fn, withcomments, &comment_buffer, &comment_buffer_size, &lline_buffer, &lline_buffer_size)) {
- cfg = NULL;
- break;
- }
- }
- }
- }
- }
- fclose(f);
- } while(0);
- if (comment) {
- ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment - 1]);
- }
-#ifdef AST_INCLUDE_GLOB
- if (!cfg)
- break;
- }
- globfree(&globbuf);
- }
- }
-#endif
-
- if (cfg && cfg->include_level == 1 && withcomments && comment_buffer) {
- free(comment_buffer);
- free(lline_buffer);
- comment_buffer = NULL;
- lline_buffer = NULL;
- comment_buffer_size = 0;
- lline_buffer_size = 0;
- }
-
- if (count == 0)
- return NULL;
-
- return cfg;
-}
-
-int config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator)
-{
- FILE *f = NULL;
- int fd = -1;
- char fn[256], fntmp[256];
- char date[256]="";
- time_t t;
- struct ast_variable *var;
- struct ast_category *cat;
- struct ast_comment *cmt;
- struct stat s;
- int blanklines = 0;
- int stat_result = 0;
-
- if (configfile[0] == '/') {
- snprintf(fntmp, sizeof(fntmp), "%s.XXXXXX", configfile);
- ast_copy_string(fn, configfile, sizeof(fn));
- } else {
- snprintf(fntmp, sizeof(fntmp), "%s/%s.XXXXXX", ast_config_AST_CONFIG_DIR, configfile);
- snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, configfile);
- }
- time(&t);
- ast_copy_string(date, ctime(&t), sizeof(date));
- if ((fd = mkstemp(fntmp)) > 0 && (f = fdopen(fd, "w")) != NULL) {
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Saving '%s': ", fn);
- fprintf(f, ";!\n");
- fprintf(f, ";! Automatically generated configuration file\n");
- if (strcmp(configfile, fn))
- fprintf(f, ";! Filename: %s (%s)\n", configfile, fn);
- else
- fprintf(f, ";! Filename: %s\n", configfile);
- fprintf(f, ";! Generator: %s\n", generator);
- fprintf(f, ";! Creation Date: %s", date);
- fprintf(f, ";!\n");
- cat = cfg->root;
- while(cat) {
- /* Dump section with any appropriate comment */
- for (cmt = cat->precomments; cmt; cmt=cmt->next)
- {
- if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
- fprintf(f,"%s", cmt->cmt);
- }
- if (!cat->precomments)
- fprintf(f,"\n");
- fprintf(f, "[%s]", cat->name);
- if (cat->ignored || !AST_LIST_EMPTY(&cat->template_instances)) {
- fprintf(f, "(");
- if (cat->ignored) {
- fprintf(f, "!");
- }
- if (cat->ignored && !AST_LIST_EMPTY(&cat->template_instances)) {
- fprintf(f, ",");
- }
- if (!AST_LIST_EMPTY(&cat->template_instances)) {
- struct ast_category_template_instance *x;
- AST_LIST_TRAVERSE(&cat->template_instances, x, next) {
- fprintf(f,"%s",x->name);
- if (x != AST_LIST_LAST(&cat->template_instances))
- fprintf(f,",");
- }
- }
- fprintf(f, ")");
- }
- for(cmt = cat->sameline; cmt; cmt=cmt->next)
- {
- fprintf(f,"%s", cmt->cmt);
- }
- if (!cat->sameline)
- fprintf(f,"\n");
- var = cat->root;
- while(var) {
- struct ast_category_template_instance *x;
- struct ast_variable *v2;
- int found = 0;
- AST_LIST_TRAVERSE(&cat->template_instances, x, next) {
-
- for (v2 = x->inst->root; v2; v2 = v2->next) {
- if (!strcasecmp(var->name, v2->name))
- break;
- }
- if (v2 && v2->value && !strcmp(v2->value, var->value)) {
- found = 1;
- break;
- }
- }
- if (found) {
- var = var->next;
- continue;
- }
- for (cmt = var->precomments; cmt; cmt=cmt->next)
- {
- if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
- fprintf(f,"%s", cmt->cmt);
- }
- if (var->sameline)
- fprintf(f, "%s %s %s %s", var->name, (var->object ? "=>" : "="), var->value, var->sameline->cmt);
- else
- fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value);
- if (var->blanklines) {
- blanklines = var->blanklines;
- while (blanklines--)
- fprintf(f, "\n");
- }
-
- var = var->next;
- }
-#if 0
- /* Put an empty line */
- fprintf(f, "\n");
-#endif
- cat = cat->next;
- }
- if ((option_verbose > 1) && !option_debug)
- ast_verbose("Saved\n");
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Unable to open for writing: %s (%s)\n", fn, strerror(errno));
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
- if (fd > -1)
- close(fd);
- return -1;
- }
- if (!(stat_result = stat(fn, &s))) {
- fchmod(fd, s.st_mode);
- }
- fclose(f);
- if ((!stat_result && unlink(fn)) || link(fntmp, fn)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Unable to open for writing: %s (%s)\n", fn, strerror(errno));
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Unable to write %s (%s)", fn, strerror(errno));
- unlink(fntmp);
- return -1;
- }
- unlink(fntmp);
- return 0;
-}
-
-static void clear_config_maps(void)
-{
- struct ast_config_map *map;
-
- ast_mutex_lock(&config_lock);
-
- while (config_maps) {
- map = config_maps;
- config_maps = config_maps->next;
- free(map);
- }
-
- ast_mutex_unlock(&config_lock);
-}
-
-static int append_mapping(char *name, char *driver, char *database, char *table)
-{
- struct ast_config_map *map;
- int length;
-
- length = sizeof(*map);
- length += strlen(name) + 1;
- length += strlen(driver) + 1;
- length += strlen(database) + 1;
- if (table)
- length += strlen(table) + 1;
-
- if (!(map = ast_calloc(1, length)))
- return -1;
-
- map->name = map->stuff;
- strcpy(map->name, name);
- map->driver = map->name + strlen(map->name) + 1;
- strcpy(map->driver, driver);
- map->database = map->driver + strlen(map->driver) + 1;
- strcpy(map->database, database);
- if (table) {
- map->table = map->database + strlen(map->database) + 1;
- strcpy(map->table, table);
- }
- map->next = config_maps;
-
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Binding %s to %s/%s/%s\n",
- map->name, map->driver, map->database, map->table ? map->table : map->name);
-
- config_maps = map;
- return 0;
-}
-
-int read_config_maps(void)
-{
- struct ast_config *config, *configtmp;
- struct ast_variable *v;
- char *driver, *table, *database, *stringp, *tmp;
-
- clear_config_maps();
-
- configtmp = ast_config_new();
- configtmp->max_include_level = 1;
- config = ast_config_internal_load(extconfig_conf, configtmp, 0);
- if (!config) {
- ast_config_destroy(configtmp);
- return 0;
- }
-
- for (v = ast_variable_browse(config, "settings"); v; v = v->next) {
- stringp = v->value;
- driver = strsep(&stringp, ",");
-
- if ((tmp = strchr(stringp, '\"')))
- stringp = tmp;
-
- /* check if the database text starts with a double quote */
- if (*stringp == '"') {
- stringp++;
- database = strsep(&stringp, "\"");
- strsep(&stringp, ",");
- } else {
- /* apparently this text has no quotes */
- database = strsep(&stringp, ",");
- }
-
- table = strsep(&stringp, ",");
-
- if (!strcmp(v->name, extconfig_conf)) {
- ast_log(LOG_WARNING, "Cannot bind '%s'!\n", extconfig_conf);
- continue;
- }
-
- if (!strcmp(v->name, "asterisk.conf")) {
- ast_log(LOG_WARNING, "Cannot bind 'asterisk.conf'!\n");
- continue;
- }
-
- if (!strcmp(v->name, "logger.conf")) {
- ast_log(LOG_WARNING, "Cannot bind 'logger.conf'!\n");
- continue;
- }
-
- if (!driver || !database)
- continue;
- if (!strcasecmp(v->name, "sipfriends")) {
- ast_log(LOG_WARNING, "The 'sipfriends' table is obsolete, update your config to use sipusers and sippeers, though they can point to the same table.\n");
- append_mapping("sipusers", driver, database, table ? table : "sipfriends");
- append_mapping("sippeers", driver, database, table ? table : "sipfriends");
- } else if (!strcasecmp(v->name, "iaxfriends")) {
- ast_log(LOG_WARNING, "The 'iaxfriends' table is obsolete, update your config to use iaxusers and iaxpeers, though they can point to the same table.\n");
- append_mapping("iaxusers", driver, database, table ? table : "iaxfriends");
- append_mapping("iaxpeers", driver, database, table ? table : "iaxfriends");
- } else
- append_mapping(v->name, driver, database, table);
- }
-
- ast_config_destroy(config);
- return 0;
-}
-
-int ast_config_engine_register(struct ast_config_engine *new)
-{
- struct ast_config_engine *ptr;
-
- ast_mutex_lock(&config_lock);
-
- if (!config_engine_list) {
- config_engine_list = new;
- } else {
- for (ptr = config_engine_list; ptr->next; ptr=ptr->next);
- ptr->next = new;
- }
-
- ast_mutex_unlock(&config_lock);
- ast_log(LOG_NOTICE,"Registered Config Engine %s\n", new->name);
-
- return 1;
-}
-
-int ast_config_engine_deregister(struct ast_config_engine *del)
-{
- struct ast_config_engine *ptr, *last=NULL;
-
- ast_mutex_lock(&config_lock);
-
- for (ptr = config_engine_list; ptr; ptr=ptr->next) {
- if (ptr == del) {
- if (last)
- last->next = ptr->next;
- else
- config_engine_list = ptr->next;
- break;
- }
- last = ptr;
- }
-
- ast_mutex_unlock(&config_lock);
-
- return 0;
-}
-
-/*! \brief Find realtime engine for realtime family */
-static struct ast_config_engine *find_engine(const char *family, char *database, int dbsiz, char *table, int tabsiz)
-{
- struct ast_config_engine *eng, *ret = NULL;
- struct ast_config_map *map;
-
- ast_mutex_lock(&config_lock);
-
- for (map = config_maps; map; map = map->next) {
- if (!strcasecmp(family, map->name)) {
- if (database)
- ast_copy_string(database, map->database, dbsiz);
- if (table)
- ast_copy_string(table, map->table ? map->table : family, tabsiz);
- break;
- }
- }
-
- /* Check if the required driver (engine) exist */
- if (map) {
- for (eng = config_engine_list; !ret && eng; eng = eng->next) {
- if (!strcasecmp(eng->name, map->driver))
- ret = eng;
- }
- }
-
- ast_mutex_unlock(&config_lock);
-
- /* if we found a mapping, but the engine is not available, then issue a warning */
- if (map && !ret)
- ast_log(LOG_WARNING, "Realtime mapping for '%s' found to engine '%s', but the engine is not available\n", map->name, map->driver);
-
- return ret;
-}
-
-static struct ast_config_engine text_file_engine = {
- .name = "text",
- .load_func = config_text_file_load,
-};
-
-struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments)
-{
- char db[256];
- char table[256];
- struct ast_config_engine *loader = &text_file_engine;
- struct ast_config *result;
-
- /* The config file itself bumps include_level by 1 */
- if (cfg->max_include_level > 0 && cfg->include_level == cfg->max_include_level + 1) {
- ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
- return NULL;
- }
-
- cfg->include_level++;
-
- if (strcmp(filename, extconfig_conf) && strcmp(filename, "asterisk.conf") && config_engine_list) {
- struct ast_config_engine *eng;
-
- eng = find_engine(filename, db, sizeof(db), table, sizeof(table));
-
-
- if (eng && eng->load_func) {
- loader = eng;
- } else {
- eng = find_engine("global", db, sizeof(db), table, sizeof(table));
- if (eng && eng->load_func)
- loader = eng;
- }
- }
-
- result = loader->load_func(db, table, filename, cfg, withcomments);
-
- if (result)
- result->include_level--;
- else
- cfg->include_level--;
-
- return result;
-}
-
-struct ast_config *ast_config_load(const char *filename)
-{
- struct ast_config *cfg;
- struct ast_config *result;
-
- cfg = ast_config_new();
- if (!cfg)
- return NULL;
-
- result = ast_config_internal_load(filename, cfg, 0);
- if (!result)
- ast_config_destroy(cfg);
-
- return result;
-}
-
-struct ast_config *ast_config_load_with_comments(const char *filename)
-{
- struct ast_config *cfg;
- struct ast_config *result;
-
- cfg = ast_config_new();
- if (!cfg)
- return NULL;
-
- result = ast_config_internal_load(filename, cfg, 1);
- if (!result)
- ast_config_destroy(cfg);
-
- return result;
-}
-
-struct ast_variable *ast_load_realtime(const char *family, ...)
-{
- struct ast_config_engine *eng;
- char db[256]="";
- char table[256]="";
- struct ast_variable *res=NULL;
- va_list ap;
-
- va_start(ap, family);
- eng = find_engine(family, db, sizeof(db), table, sizeof(table));
- if (eng && eng->realtime_func)
- res = eng->realtime_func(db, table, ap);
- va_end(ap);
-
- return res;
-}
-
-/*! \brief Check if realtime engine is configured for family */
-int ast_check_realtime(const char *family)
-{
- struct ast_config_engine *eng;
-
- eng = find_engine(family, NULL, 0, NULL, 0);
- if (eng)
- return 1;
- return 0;
-
-}
-
-struct ast_config *ast_load_realtime_multientry(const char *family, ...)
-{
- struct ast_config_engine *eng;
- char db[256]="";
- char table[256]="";
- struct ast_config *res=NULL;
- va_list ap;
-
- va_start(ap, family);
- eng = find_engine(family, db, sizeof(db), table, sizeof(table));
- if (eng && eng->realtime_multi_func)
- res = eng->realtime_multi_func(db, table, ap);
- va_end(ap);
-
- return res;
-}
-
-int ast_update_realtime(const char *family, const char *keyfield, const char *lookup, ...)
-{
- struct ast_config_engine *eng;
- int res = -1;
- char db[256]="";
- char table[256]="";
- va_list ap;
-
- va_start(ap, lookup);
- eng = find_engine(family, db, sizeof(db), table, sizeof(table));
- if (eng && eng->update_func)
- res = eng->update_func(db, table, keyfield, lookup, ap);
- va_end(ap);
-
- return res;
-}
-
-static int config_command(int fd, int argc, char **argv)
-{
- struct ast_config_engine *eng;
- struct ast_config_map *map;
-
- ast_mutex_lock(&config_lock);
-
- ast_cli(fd, "\n\n");
- for (eng = config_engine_list; eng; eng = eng->next) {
- ast_cli(fd, "\nConfig Engine: %s\n", eng->name);
- for (map = config_maps; map; map = map->next)
- if (!strcasecmp(map->driver, eng->name)) {
- ast_cli(fd, "===> %s (db=%s, table=%s)\n", map->name, map->database,
- map->table ? map->table : map->name);
- }
- }
- ast_cli(fd,"\n\n");
-
- ast_mutex_unlock(&config_lock);
-
- return 0;
-}
-
-static char show_config_help[] =
- "Usage: core show config mappings\n"
- " Shows the filenames to config engines.\n";
-
-static struct ast_cli_entry cli_show_config_mappings_deprecated = {
- { "show", "config", "mappings", NULL },
- config_command, NULL,
- NULL };
-
-static struct ast_cli_entry cli_config[] = {
- { { "core", "show", "config", "mappings", NULL },
- config_command, "Display config mappings (file names to config engines)",
- show_config_help, NULL, &cli_show_config_mappings_deprecated },
-};
-
-int register_config_cli()
-{
- ast_cli_register_multiple(cli_config, sizeof(cli_config) / sizeof(struct ast_cli_entry));
- return 0;
-}
diff --git a/main/cryptostub.c b/main/cryptostub.c
deleted file mode 100644
index 676110374..000000000
--- a/main/cryptostub.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Stubs for res_crypto routines
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "asterisk/crypto.h"
-#include "asterisk/logger.h"
-
-/* Hrm, I wonder if the compiler is smart enough to only create two functions
- for all these... I could force it to only make two, but those would be some
- really nasty looking casts. */
-
-static struct ast_key *stub_ast_key_get(const char *kname, int ktype)
-{
- ast_log(LOG_NOTICE, "Crypto support not loaded!\n");
- return NULL;
-}
-
-static int stub_ast_check_signature(struct ast_key *key, const char *msg, const char *sig)
-{
- ast_log(LOG_NOTICE, "Crypto support not loaded!\n");
- return -1;
-}
-
-static int stub_ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *sig)
-{
- ast_log(LOG_NOTICE, "Crypto support not loaded!\n");
- return -1;
-}
-
-static int stub_ast_sign(struct ast_key *key, char *msg, char *sig)
-{
- ast_log(LOG_NOTICE, "Crypto support not loaded!\n");
- return -1;
-}
-
-static int stub_ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *sig)
-{
- ast_log(LOG_NOTICE, "Crypto support not loaded!\n");
- return -1;
-}
-
-static int stub_ast_encdec_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
-{
- ast_log(LOG_NOTICE, "Crypto support not loaded!\n");
- return -1;
-}
-
-struct ast_key *(*ast_key_get)(const char *key, int type) =
- stub_ast_key_get;
-
-int (*ast_check_signature)(struct ast_key *key, const char *msg, const char *sig) =
- stub_ast_check_signature;
-
-int (*ast_check_signature_bin)(struct ast_key *key, const char *msg, int msglen, const unsigned char *sig) =
- stub_ast_check_signature_bin;
-
-int (*ast_sign)(struct ast_key *key, char *msg, char *sig) =
- stub_ast_sign;
-
-int (*ast_sign_bin)(struct ast_key *key, const char *msg, int msglen, unsigned char *sig) =
- stub_ast_sign_bin;
-
-int (*ast_encrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key) =
- stub_ast_encdec_bin;
-
-int (*ast_decrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key) =
- stub_ast_encdec_bin;
diff --git a/main/db.c b/main/db.c
deleted file mode 100644
index 3e61be509..000000000
--- a/main/db.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief ASTdb Management
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * \note DB3 is licensed under Sleepycat Public License and is thus incompatible
- * with GPL. To avoid having to make another exception (and complicate
- * licensing even further) we elect to use DB1 which is BSD licensed
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <dirent.h>
-
-#include "asterisk/channel.h"
-#include "asterisk/file.h"
-#include "asterisk/app.h"
-#include "asterisk/dsp.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/astdb.h"
-#include "asterisk/cli.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/manager.h"
-#include "db1-ast/include/db.h"
-
-#ifdef __CYGWIN__
-#define dbopen __dbopen
-#endif
-
-static DB *astdb;
-AST_MUTEX_DEFINE_STATIC(dblock);
-
-static int dbinit(void)
-{
- if (!astdb && !(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
- ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", ast_config_AST_DB, strerror(errno));
- return -1;
- }
- return 0;
-}
-
-
-static inline int keymatch(const char *key, const char *prefix)
-{
- int preflen = strlen(prefix);
- if (!preflen)
- return 1;
- if (!strcasecmp(key, prefix))
- return 1;
- if ((strlen(key) > preflen) && !strncasecmp(key, prefix, preflen)) {
- if (key[preflen] == '/')
- return 1;
- }
- return 0;
-}
-
-static inline int subkeymatch(const char *key, const char *suffix)
-{
- int suffixlen = strlen(suffix);
- if (suffixlen) {
- const char *subkey = key + strlen(key) - suffixlen;
- if (subkey < key)
- return 0;
- if (!strcasecmp(subkey, suffix))
- return 1;
- }
- return 0;
-}
-
-int ast_db_deltree(const char *family, const char *keytree)
-{
- char prefix[256];
- DBT key, data;
- char *keys;
- int res;
- int pass;
-
- if (family) {
- if (keytree) {
- snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
- } else {
- snprintf(prefix, sizeof(prefix), "/%s", family);
- }
- } else if (keytree) {
- return -1;
- } else {
- prefix[0] = '\0';
- }
-
- ast_mutex_lock(&dblock);
- if (dbinit()) {
- ast_mutex_unlock(&dblock);
- return -1;
- }
-
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
- pass = 0;
- while (!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
- if (key.size) {
- keys = key.data;
- keys[key.size - 1] = '\0';
- } else {
- keys = "<bad key>";
- }
- if (keymatch(keys, prefix)) {
- astdb->del(astdb, &key, 0);
- }
- }
- astdb->sync(astdb, 0);
- ast_mutex_unlock(&dblock);
- return 0;
-}
-
-int ast_db_put(const char *family, const char *keys, char *value)
-{
- char fullkey[256];
- DBT key, data;
- int res, fullkeylen;
-
- ast_mutex_lock(&dblock);
- if (dbinit()) {
- ast_mutex_unlock(&dblock);
- return -1;
- }
-
- fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
- key.data = fullkey;
- key.size = fullkeylen + 1;
- data.data = value;
- data.size = strlen(value) + 1;
- res = astdb->put(astdb, &key, &data, 0);
- astdb->sync(astdb, 0);
- ast_mutex_unlock(&dblock);
- if (res)
- ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family);
- return res;
-}
-
-int ast_db_get(const char *family, const char *keys, char *value, int valuelen)
-{
- char fullkey[256] = "";
- DBT key, data;
- int res, fullkeylen;
-
- ast_mutex_lock(&dblock);
- if (dbinit()) {
- ast_mutex_unlock(&dblock);
- return -1;
- }
-
- fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
- memset(value, 0, valuelen);
- key.data = fullkey;
- key.size = fullkeylen + 1;
-
- res = astdb->get(astdb, &key, &data, 0);
-
- ast_mutex_unlock(&dblock);
-
- /* Be sure to NULL terminate our data either way */
- if (res) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
- } else {
-#if 0
- printf("Got value of size %d\n", data.size);
-#endif
- if (data.size) {
- ((char *)data.data)[data.size - 1] = '\0';
- /* Make sure that we don't write too much to the dst pointer or we don't read too much from the source pointer */
- ast_copy_string(value, data.data, (valuelen > data.size) ? data.size : valuelen);
- } else {
- ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys);
- }
- }
- return res;
-}
-
-int ast_db_del(const char *family, const char *keys)
-{
- char fullkey[256];
- DBT key;
- int res, fullkeylen;
-
- ast_mutex_lock(&dblock);
- if (dbinit()) {
- ast_mutex_unlock(&dblock);
- return -1;
- }
-
- fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
- memset(&key, 0, sizeof(key));
- key.data = fullkey;
- key.size = fullkeylen + 1;
-
- res = astdb->del(astdb, &key, 0);
- astdb->sync(astdb, 0);
-
- ast_mutex_unlock(&dblock);
-
- if (res && option_debug)
- ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
- return res;
-}
-
-static int database_put(int fd, int argc, char *argv[])
-{
- int res;
- if (argc != 5)
- return RESULT_SHOWUSAGE;
- res = ast_db_put(argv[2], argv[3], argv[4]);
- if (res) {
- ast_cli(fd, "Failed to update entry\n");
- } else {
- ast_cli(fd, "Updated database successfully\n");
- }
- return RESULT_SUCCESS;
-}
-
-static int database_get(int fd, int argc, char *argv[])
-{
- int res;
- char tmp[256];
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
- if (res) {
- ast_cli(fd, "Database entry not found.\n");
- } else {
- ast_cli(fd, "Value: %s\n", tmp);
- }
- return RESULT_SUCCESS;
-}
-
-static int database_del(int fd, int argc, char *argv[])
-{
- int res;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- res = ast_db_del(argv[2], argv[3]);
- if (res) {
- ast_cli(fd, "Database entry does not exist.\n");
- } else {
- ast_cli(fd, "Database entry removed.\n");
- }
- return RESULT_SUCCESS;
-}
-
-static int database_deltree(int fd, int argc, char *argv[])
-{
- int res;
- if ((argc < 3) || (argc > 4))
- return RESULT_SHOWUSAGE;
- if (argc == 4) {
- res = ast_db_deltree(argv[2], argv[3]);
- } else {
- res = ast_db_deltree(argv[2], NULL);
- }
- if (res) {
- ast_cli(fd, "Database entries do not exist.\n");
- } else {
- ast_cli(fd, "Database entries removed.\n");
- }
- return RESULT_SUCCESS;
-}
-
-static int database_show(int fd, int argc, char *argv[])
-{
- char prefix[256];
- DBT key, data;
- char *keys, *values;
- int res;
- int pass;
-
- if (argc == 4) {
- /* Family and key tree */
- snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]);
- } else if (argc == 3) {
- /* Family only */
- snprintf(prefix, sizeof(prefix), "/%s", argv[2]);
- } else if (argc == 2) {
- /* Neither */
- prefix[0] = '\0';
- } else {
- return RESULT_SHOWUSAGE;
- }
- ast_mutex_lock(&dblock);
- if (dbinit()) {
- ast_mutex_unlock(&dblock);
- ast_cli(fd, "Database unavailable\n");
- return RESULT_SUCCESS;
- }
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
- pass = 0;
- while (!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
- if (key.size) {
- keys = key.data;
- keys[key.size - 1] = '\0';
- } else {
- keys = "<bad key>";
- }
- if (data.size) {
- values = data.data;
- values[data.size - 1]='\0';
- } else {
- values = "<bad value>";
- }
- if (keymatch(keys, prefix)) {
- ast_cli(fd, "%-50s: %-25s\n", keys, values);
- }
- }
- ast_mutex_unlock(&dblock);
- return RESULT_SUCCESS;
-}
-
-static int database_showkey(int fd, int argc, char *argv[])
-{
- char suffix[256];
- DBT key, data;
- char *keys, *values;
- int res;
- int pass;
-
- if (argc == 3) {
- /* Key only */
- snprintf(suffix, sizeof(suffix), "/%s", argv[2]);
- } else {
- return RESULT_SHOWUSAGE;
- }
- ast_mutex_lock(&dblock);
- if (dbinit()) {
- ast_mutex_unlock(&dblock);
- ast_cli(fd, "Database unavailable\n");
- return RESULT_SUCCESS;
- }
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
- pass = 0;
- while (!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
- if (key.size) {
- keys = key.data;
- keys[key.size - 1] = '\0';
- } else {
- keys = "<bad key>";
- }
- if (data.size) {
- values = data.data;
- values[data.size - 1]='\0';
- } else {
- values = "<bad value>";
- }
- if (subkeymatch(keys, suffix)) {
- ast_cli(fd, "%-50s: %-25s\n", keys, values);
- }
- }
- ast_mutex_unlock(&dblock);
- return RESULT_SUCCESS;
-}
-
-struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
-{
- char prefix[256];
- DBT key, data;
- char *keys, *values;
- int values_len;
- int res;
- int pass;
- struct ast_db_entry *last = NULL;
- struct ast_db_entry *cur, *ret=NULL;
-
- if (!ast_strlen_zero(family)) {
- if (!ast_strlen_zero(keytree)) {
- /* Family and key tree */
- snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
- } else {
- /* Family only */
- snprintf(prefix, sizeof(prefix), "/%s", family);
- }
- } else {
- prefix[0] = '\0';
- }
- ast_mutex_lock(&dblock);
- if (dbinit()) {
- ast_mutex_unlock(&dblock);
- ast_log(LOG_WARNING, "Database unavailable\n");
- return NULL;
- }
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
- pass = 0;
- while (!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
- if (key.size) {
- keys = key.data;
- keys[key.size - 1] = '\0';
- } else {
- keys = "<bad key>";
- }
- if (data.size) {
- values = data.data;
- values[data.size - 1] = '\0';
- } else {
- values = "<bad value>";
- }
- values_len = strlen(values) + 1;
- if (keymatch(keys, prefix) && (cur = ast_malloc(sizeof(*cur) + strlen(keys) + 1 + values_len))) {
- cur->next = NULL;
- cur->key = cur->data + values_len;
- strcpy(cur->data, values);
- strcpy(cur->key, keys);
- if (last) {
- last->next = cur;
- } else {
- ret = cur;
- }
- last = cur;
- }
- }
- ast_mutex_unlock(&dblock);
- return ret;
-}
-
-void ast_db_freetree(struct ast_db_entry *dbe)
-{
- struct ast_db_entry *last;
- while (dbe) {
- last = dbe;
- dbe = dbe->next;
- free(last);
- }
-}
-
-static char database_show_usage[] =
-"Usage: database show [family [keytree]]\n"
-" Shows Asterisk database contents, optionally restricted\n"
-"to a given family, or family and keytree.\n";
-
-static char database_showkey_usage[] =
-"Usage: database showkey <keytree>\n"
-" Shows Asterisk database contents, restricted to a given key.\n";
-
-static char database_put_usage[] =
-"Usage: database put <family> <key> <value>\n"
-" Adds or updates an entry in the Asterisk database for\n"
-"a given family, key, and value.\n";
-
-static char database_get_usage[] =
-"Usage: database get <family> <key>\n"
-" Retrieves an entry in the Asterisk database for a given\n"
-"family and key.\n";
-
-static char database_del_usage[] =
-"Usage: database del <family> <key>\n"
-" Deletes an entry in the Asterisk database for a given\n"
-"family and key.\n";
-
-static char database_deltree_usage[] =
-"Usage: database deltree <family> [keytree]\n"
-" Deletes a family or specific keytree within a family\n"
-"in the Asterisk database.\n";
-
-struct ast_cli_entry cli_database[] = {
- { { "database", "show", NULL },
- database_show, "Shows database contents",
- database_show_usage },
-
- { { "database", "showkey", NULL },
- database_showkey, "Shows database contents",
- database_showkey_usage },
-
- { { "database", "get", NULL },
- database_get, "Gets database value",
- database_get_usage },
-
- { { "database", "put", NULL },
- database_put, "Adds/updates database value",
- database_put_usage },
-
- { { "database", "del", NULL },
- database_del, "Removes database key/value",
- database_del_usage },
-
- { { "database", "deltree", NULL },
- database_deltree, "Removes database keytree/values",
- database_deltree_usage },
-};
-
-static int manager_dbput(struct mansession *s, const struct message *m)
-{
- const char *family = astman_get_header(m, "Family");
- const char *key = astman_get_header(m, "Key");
- const char *val = astman_get_header(m, "Val");
- int res;
-
- if (ast_strlen_zero(family)) {
- astman_send_error(s, m, "No family specified");
- return 0;
- }
- if (ast_strlen_zero(key)) {
- astman_send_error(s, m, "No key specified");
- return 0;
- }
-
- res = ast_db_put(family, key, (char *) S_OR(val, ""));
- if (res) {
- astman_send_error(s, m, "Failed to update entry");
- } else {
- astman_send_ack(s, m, "Updated database successfully");
- }
- return 0;
-}
-
-static int manager_dbget(struct mansession *s, const struct message *m)
-{
- const char *id = astman_get_header(m,"ActionID");
- char idText[256] = "";
- const char *family = astman_get_header(m, "Family");
- const char *key = astman_get_header(m, "Key");
- char tmp[256];
- int res;
-
- if (ast_strlen_zero(family)) {
- astman_send_error(s, m, "No family specified.");
- return 0;
- }
- if (ast_strlen_zero(key)) {
- astman_send_error(s, m, "No key specified.");
- return 0;
- }
-
- if (!ast_strlen_zero(id))
- snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
-
- res = ast_db_get(family, key, tmp, sizeof(tmp));
- if (res) {
- astman_send_error(s, m, "Database entry not found");
- } else {
- astman_send_ack(s, m, "Result will follow");
- astman_append(s, "Event: DBGetResponse\r\n"
- "Family: %s\r\n"
- "Key: %s\r\n"
- "Val: %s\r\n"
- "%s"
- "\r\n",
- family, key, tmp, idText);
- }
- return 0;
-}
-
-int astdb_init(void)
-{
- dbinit();
- ast_cli_register_multiple(cli_database, sizeof(cli_database) / sizeof(struct ast_cli_entry));
- ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
- ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
- return 0;
-}
diff --git a/main/db1-ast/Makefile b/main/db1-ast/Makefile
deleted file mode 100644
index c9d29b369..000000000
--- a/main/db1-ast/Makefile
+++ /dev/null
@@ -1,71 +0,0 @@
-# @(#)Makefile 8.9 (Berkeley) 7/14/94
-
-LIBDB= libdb1.a
-ARCH=$(shell uname -m)
-ifeq ($(ARCH),alpha)
-SOVER=2.1
-else
-SOVER=2
-endif
-
-ifeq ($(OSARCH),Darwin)
- OSARCH_DEFINE+=-D__Darwin__
-endif
-
-LIBDBSO=libdb.so.$(SOVER)
-PROG= db_dump185
-OBJ1= hash/hash.o hash/hash_bigkey.o hash/hash_buf.o hash/hash_func.o hash/hash_log2.o hash/hash_page.o \
- hash/ndbm.o
-OBJ2= btree/bt_close.o btree/bt_conv.o btree/bt_debug.o btree/bt_delete.o btree/bt_get.o btree/bt_open.o \
- btree/bt_overflow.o btree/bt_page.o btree/bt_put.o btree/bt_search.o btree/bt_seq.o btree/bt_split.o \
- btree/bt_utils.o
-OBJ3= db/db.o
-OBJ4= mpool/mpool.o
-OBJ5= recno/rec_close.o recno/rec_delete.o recno/rec_get.o recno/rec_open.o recno/rec_put.o recno/rec_search.o \
- recno/rec_seq.o recno/rec_utils.o
-MISC=
-OBJS= $(OBJ1) $(OBJ2) $(OBJ3) $(OBJ4) $(OBJ5) $(MISC)
-SHOBJS= $(patsubst %.o,%.os,$(OBJS))
-
-include $(ASTTOPDIR)/Makefile.rules
-
-all: $(LIBDB) #$(LIBDBSO) $(PROG)
-
-$(LIBDB): $(OBJS)
- $(ECHO_PREFIX) echo " [AR] $^ -> $@"
- $(CMD_PREFIX) $(AR) cr $@ $^
- $(CMD_PREFIX) $(RANLIB) $@
-
-$(LIBDBSO): $(SHOBJS)
- $(CC) -Wl,-O1 -Wl,--version-script=libdb.map -Wl,-soname=$(LIBDBSO) -shared -o $@ $^
- ln -sf $@ libdb.so
-
-$(PROG): db_dump185.o $(LIBDBSO)
- $(CC) -o $@ db_dump185.o -L. -ldb
-
-clean-depend:
-
-clean:
- rm -f $(LIBDB) $(LIBDBSO) $(OBJS) $(SHOBJS) */*.s */*.i
-
-ASTCFLAGS:=-Wall -D__DBINTERFACE_PRIVATE -I. -I.. -Iinclude -Ihash -Ibtree -Irecno $(ASTCFLAGS)
-
-OSTYPE=$(shell uname -s)
-ifeq ($(OSTYPE),SunOS)
-ASTCFLAGS+=-I../../include -I../../include/solaris-compat -DSOLARIS
-endif
-
-db_dump185.o: db_dump185.c
- $(CL) -o $@ $<
-x%.o: hash/%.c
- $(CL) -Ihash $(OSARCH_DEFINE) -o $@ $<
-%.os: hash/%.c
- $(CL) -Ihash -fPIC -o $@ $<
-x%.o: btree/%.c
- $(CL) -Ibtree -o $@ $<
-%.os: btree/%.c
- $(CL) -Ibtree -fPIC -o $@ $<
-x%.o: recno/%.c
- $(CL) -Irecno -o $@ $<
-%.os: recno/%.c
- $(CL) -Irecno -fPIC -o $@ $<
diff --git a/main/db1-ast/btree/bt_close.c b/main/db1-ast/btree/bt_close.c
deleted file mode 100644
index 67a6e5340..000000000
--- a/main/db1-ast/btree/bt_close.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_close.c 8.7 (Berkeley) 8/17/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-static int bt_meta __P((BTREE *));
-
-/*
- * BT_CLOSE -- Close a btree.
- *
- * Parameters:
- * dbp: pointer to access method
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__bt_close(dbp)
- DB *dbp;
-{
- BTREE *t;
- int fd;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /* Sync the tree. */
- if (__bt_sync(dbp, 0) == RET_ERROR)
- return (RET_ERROR);
-
- /* Close the memory pool. */
- if (mpool_close(t->bt_mp) == RET_ERROR)
- return (RET_ERROR);
-
- /* Free random memory. */
- if (t->bt_cursor.key.data != NULL) {
- free(t->bt_cursor.key.data);
- t->bt_cursor.key.size = 0;
- t->bt_cursor.key.data = NULL;
- }
- if (t->bt_rkey.data) {
- free(t->bt_rkey.data);
- t->bt_rkey.size = 0;
- t->bt_rkey.data = NULL;
- }
- if (t->bt_rdata.data) {
- free(t->bt_rdata.data);
- t->bt_rdata.size = 0;
- t->bt_rdata.data = NULL;
- }
-
- fd = t->bt_fd;
- free(t);
- free(dbp);
- return (close(fd) ? RET_ERROR : RET_SUCCESS);
-}
-
-/*
- * BT_SYNC -- sync the btree to disk.
- *
- * Parameters:
- * dbp: pointer to access method
- *
- * Returns:
- * RET_SUCCESS, RET_ERROR.
- */
-int
-__bt_sync(dbp, flags)
- const DB *dbp;
- u_int flags;
-{
- BTREE *t;
- int status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /* Sync doesn't currently take any flags. */
- if (flags != 0) {
- errno = EINVAL;
- return (RET_ERROR);
- }
-
- if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED))
- return (RET_SUCCESS);
-
- if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
- return (RET_ERROR);
-
- if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
- F_CLR(t, B_MODIFIED);
-
- return (status);
-}
-
-/*
- * BT_META -- write the tree meta data to disk.
- *
- * Parameters:
- * t: tree
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-static int
-bt_meta(t)
- BTREE *t;
-{
- BTMETA m;
- void *p;
-
- if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
- return (RET_ERROR);
-
- /* Fill in metadata. */
- m.magic = BTREEMAGIC;
- m.version = BTREEVERSION;
- m.psize = t->bt_psize;
- m.free = t->bt_free;
- m.nrecs = t->bt_nrecs;
- m.flags = F_ISSET(t, SAVEMETA);
-
- memmove(p, &m, sizeof(BTMETA));
- mpool_put(t->bt_mp, p, MPOOL_DIRTY);
- return (RET_SUCCESS);
-}
diff --git a/main/db1-ast/btree/bt_conv.c b/main/db1-ast/btree/bt_conv.c
deleted file mode 100644
index d2ebdc57b..000000000
--- a/main/db1-ast/btree/bt_conv.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_conv.c 8.5 (Berkeley) 8/17/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
-
-#include <stdio.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-static void mswap __P((PAGE *));
-
-/*
- * __BT_BPGIN, __BT_BPGOUT --
- * Convert host-specific number layout to/from the host-independent
- * format stored on disk.
- *
- * Parameters:
- * t: tree
- * pg: page number
- * h: page to convert
- */
-void
-__bt_pgin(t, pg, pp)
- void *t;
- pgno_t pg;
- void *pp;
-{
- PAGE *h;
- indx_t i, top;
- u_char flags;
- char *p;
-
- if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
- return;
- if (pg == P_META) {
- mswap(pp);
- return;
- }
-
- h = pp;
- M_32_SWAP(h->pgno);
- M_32_SWAP(h->prevpg);
- M_32_SWAP(h->nextpg);
- M_32_SWAP(h->flags);
- M_16_SWAP(h->lower);
- M_16_SWAP(h->upper);
-
- top = NEXTINDEX(h);
- if ((h->flags & P_TYPE) == P_BINTERNAL)
- for (i = 0; i < top; i++) {
- M_16_SWAP(h->linp[i]);
- p = (char *)GETBINTERNAL(h, i);
- P_32_SWAP(p);
- p += sizeof(u_int32_t);
- P_32_SWAP(p);
- p += sizeof(pgno_t);
- if (*(u_char *)p & P_BIGKEY) {
- p += sizeof(u_char);
- P_32_SWAP(p);
- p += sizeof(pgno_t);
- P_32_SWAP(p);
- }
- }
- else if ((h->flags & P_TYPE) == P_BLEAF)
- for (i = 0; i < top; i++) {
- M_16_SWAP(h->linp[i]);
- p = (char *)GETBLEAF(h, i);
- P_32_SWAP(p);
- p += sizeof(u_int32_t);
- P_32_SWAP(p);
- p += sizeof(u_int32_t);
- flags = *(u_char *)p;
- if (flags & (P_BIGKEY | P_BIGDATA)) {
- p += sizeof(u_char);
- if (flags & P_BIGKEY) {
- P_32_SWAP(p);
- p += sizeof(pgno_t);
- P_32_SWAP(p);
- }
- if (flags & P_BIGDATA) {
- p += sizeof(u_int32_t);
- P_32_SWAP(p);
- p += sizeof(pgno_t);
- P_32_SWAP(p);
- }
- }
- }
-}
-
-void
-__bt_pgout(t, pg, pp)
- void *t;
- pgno_t pg;
- void *pp;
-{
- PAGE *h;
- indx_t i, top;
- u_char flags;
- char *p;
-
- if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
- return;
- if (pg == P_META) {
- mswap(pp);
- return;
- }
-
- h = pp;
- top = NEXTINDEX(h);
- if ((h->flags & P_TYPE) == P_BINTERNAL)
- for (i = 0; i < top; i++) {
- p = (char *)GETBINTERNAL(h, i);
- P_32_SWAP(p);
- p += sizeof(u_int32_t);
- P_32_SWAP(p);
- p += sizeof(pgno_t);
- if (*(u_char *)p & P_BIGKEY) {
- p += sizeof(u_char);
- P_32_SWAP(p);
- p += sizeof(pgno_t);
- P_32_SWAP(p);
- }
- M_16_SWAP(h->linp[i]);
- }
- else if ((h->flags & P_TYPE) == P_BLEAF)
- for (i = 0; i < top; i++) {
- p = (char *)GETBLEAF(h, i);
- P_32_SWAP(p);
- p += sizeof(u_int32_t);
- P_32_SWAP(p);
- p += sizeof(u_int32_t);
- flags = *(u_char *)p;
- if (flags & (P_BIGKEY | P_BIGDATA)) {
- p += sizeof(u_char);
- if (flags & P_BIGKEY) {
- P_32_SWAP(p);
- p += sizeof(pgno_t);
- P_32_SWAP(p);
- }
- if (flags & P_BIGDATA) {
- p += sizeof(u_int32_t);
- P_32_SWAP(p);
- p += sizeof(pgno_t);
- P_32_SWAP(p);
- }
- }
- M_16_SWAP(h->linp[i]);
- }
-
- M_32_SWAP(h->pgno);
- M_32_SWAP(h->prevpg);
- M_32_SWAP(h->nextpg);
- M_32_SWAP(h->flags);
- M_16_SWAP(h->lower);
- M_16_SWAP(h->upper);
-}
-
-/*
- * MSWAP -- Actually swap the bytes on the meta page.
- *
- * Parameters:
- * p: page to convert
- */
-static void
-mswap(pg)
- PAGE *pg;
-{
- char *p;
-
- p = (char *)pg;
- P_32_SWAP(p); /* magic */
- p += sizeof(u_int32_t);
- P_32_SWAP(p); /* version */
- p += sizeof(u_int32_t);
- P_32_SWAP(p); /* psize */
- p += sizeof(u_int32_t);
- P_32_SWAP(p); /* free */
- p += sizeof(u_int32_t);
- P_32_SWAP(p); /* nrecs */
- p += sizeof(u_int32_t);
- P_32_SWAP(p); /* flags */
- p += sizeof(u_int32_t);
-}
diff --git a/main/db1-ast/btree/bt_debug.c b/main/db1-ast/btree/bt_debug.c
deleted file mode 100644
index e035851a8..000000000
--- a/main/db1-ast/btree/bt_debug.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_debug.c 8.5 (Berkeley) 8/17/94";
-#endif /* LIBC_SCCS and not lint */
-
-#ifdef DEBUG
-#include <sys/param.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-/*
- * BT_DUMP -- Dump the tree
- *
- * Parameters:
- * dbp: pointer to the DB
- */
-void
-__bt_dump(dbp)
- DB *dbp;
-{
- BTREE *t;
- PAGE *h;
- pgno_t i;
- char *sep;
-
- t = dbp->internal;
- (void)fprintf(stderr, "%s: pgsz %d",
- F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize);
- if (F_ISSET(t, R_RECNO))
- (void)fprintf(stderr, " keys %lu", t->bt_nrecs);
-#undef X
-#define X(flag, name) \
- if (F_ISSET(t, flag)) { \
- (void)fprintf(stderr, "%s%s", sep, name); \
- sep = ", "; \
- }
- if (t->flags != 0) {
- sep = " flags (";
- X(R_FIXLEN, "FIXLEN");
- X(B_INMEM, "INMEM");
- X(B_NODUPS, "NODUPS");
- X(B_RDONLY, "RDONLY");
- X(R_RECNO, "RECNO");
- X(B_METADIRTY,"METADIRTY");
- (void)fprintf(stderr, ")\n");
- }
-#undef X
-
- for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
- __bt_dpage(h);
- (void)mpool_put(t->bt_mp, h, 0);
- }
-}
-
-/*
- * BT_DMPAGE -- Dump the meta page
- *
- * Parameters:
- * h: pointer to the PAGE
- */
-void
-__bt_dmpage(h)
- PAGE *h;
-{
- BTMETA *m;
- char *sep;
-
- m = (BTMETA *)h;
- (void)fprintf(stderr, "magic %lx\n", m->magic);
- (void)fprintf(stderr, "version %lu\n", m->version);
- (void)fprintf(stderr, "psize %lu\n", m->psize);
- (void)fprintf(stderr, "free %lu\n", m->free);
- (void)fprintf(stderr, "nrecs %lu\n", m->nrecs);
- (void)fprintf(stderr, "flags %lu", m->flags);
-#undef X
-#define X(flag, name) \
- if (m->flags & flag) { \
- (void)fprintf(stderr, "%s%s", sep, name); \
- sep = ", "; \
- }
- if (m->flags) {
- sep = " (";
- X(B_NODUPS, "NODUPS");
- X(R_RECNO, "RECNO");
- (void)fprintf(stderr, ")");
- }
-}
-
-/*
- * BT_DNPAGE -- Dump the page
- *
- * Parameters:
- * n: page number to dump.
- */
-void
-__bt_dnpage(dbp, pgno)
- DB *dbp;
- pgno_t pgno;
-{
- BTREE *t;
- PAGE *h;
-
- t = dbp->internal;
- if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) {
- __bt_dpage(h);
- (void)mpool_put(t->bt_mp, h, 0);
- }
-}
-
-/*
- * BT_DPAGE -- Dump the page
- *
- * Parameters:
- * h: pointer to the PAGE
- */
-void
-__bt_dpage(h)
- PAGE *h;
-{
- BINTERNAL *bi;
- BLEAF *bl;
- RINTERNAL *ri;
- RLEAF *rl;
- indx_t cur, top;
- char *sep;
-
- (void)fprintf(stderr, " page %d: (", h->pgno);
-#undef X
-#define X(flag, name) \
- if (h->flags & flag) { \
- (void)fprintf(stderr, "%s%s", sep, name); \
- sep = ", "; \
- }
- sep = "";
- X(P_BINTERNAL, "BINTERNAL") /* types */
- X(P_BLEAF, "BLEAF")
- X(P_RINTERNAL, "RINTERNAL") /* types */
- X(P_RLEAF, "RLEAF")
- X(P_OVERFLOW, "OVERFLOW")
- X(P_PRESERVE, "PRESERVE");
- (void)fprintf(stderr, ")\n");
-#undef X
-
- (void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg);
- if (h->flags & P_OVERFLOW)
- return;
-
- top = NEXTINDEX(h);
- (void)fprintf(stderr, " lower %3d upper %3d nextind %d\n",
- h->lower, h->upper, top);
- for (cur = 0; cur < top; cur++) {
- (void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]);
- switch (h->flags & P_TYPE) {
- case P_BINTERNAL:
- bi = GETBINTERNAL(h, cur);
- (void)fprintf(stderr,
- "size %03d pgno %03d", bi->ksize, bi->pgno);
- if (bi->flags & P_BIGKEY)
- (void)fprintf(stderr, " (indirect)");
- else if (bi->ksize)
- (void)fprintf(stderr,
- " {%.*s}", (int)bi->ksize, bi->bytes);
- break;
- case P_RINTERNAL:
- ri = GETRINTERNAL(h, cur);
- (void)fprintf(stderr, "entries %03d pgno %03d",
- ri->nrecs, ri->pgno);
- break;
- case P_BLEAF:
- bl = GETBLEAF(h, cur);
- if (bl->flags & P_BIGKEY)
- (void)fprintf(stderr,
- "big key page %lu size %u/",
- *(pgno_t *)bl->bytes,
- *(u_int32_t *)(bl->bytes + sizeof(pgno_t)));
- else if (bl->ksize)
- (void)fprintf(stderr, "%s/", bl->bytes);
- if (bl->flags & P_BIGDATA)
- (void)fprintf(stderr,
- "big data page %lu size %u",
- *(pgno_t *)(bl->bytes + bl->ksize),
- *(u_int32_t *)(bl->bytes + bl->ksize +
- sizeof(pgno_t)));
- else if (bl->dsize)
- (void)fprintf(stderr, "%.*s",
- (int)bl->dsize, bl->bytes + bl->ksize);
- break;
- case P_RLEAF:
- rl = GETRLEAF(h, cur);
- if (rl->flags & P_BIGDATA)
- (void)fprintf(stderr,
- "big data page %lu size %u",
- *(pgno_t *)rl->bytes,
- *(u_int32_t *)(rl->bytes + sizeof(pgno_t)));
- else if (rl->dsize)
- (void)fprintf(stderr,
- "%.*s", (int)rl->dsize, rl->bytes);
- break;
- }
- (void)fprintf(stderr, "\n");
- }
-}
-#endif
-
-#ifdef STATISTICS
-/*
- * BT_STAT -- Gather/print the tree statistics
- *
- * Parameters:
- * dbp: pointer to the DB
- */
-void
-__bt_stat(dbp)
- DB *dbp;
-{
- extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit;
- extern u_long bt_sortsplit, bt_split;
- BTREE *t;
- PAGE *h;
- pgno_t i, pcont, pinternal, pleaf;
- u_long ifree, lfree, nkeys;
- int levels;
-
- t = dbp->internal;
- pcont = pinternal = pleaf = 0;
- nkeys = ifree = lfree = 0;
- for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
- switch (h->flags & P_TYPE) {
- case P_BINTERNAL:
- case P_RINTERNAL:
- ++pinternal;
- ifree += h->upper - h->lower;
- break;
- case P_BLEAF:
- case P_RLEAF:
- ++pleaf;
- lfree += h->upper - h->lower;
- nkeys += NEXTINDEX(h);
- break;
- case P_OVERFLOW:
- ++pcont;
- break;
- }
- (void)mpool_put(t->bt_mp, h, 0);
- }
-
- /* Count the levels of the tree. */
- for (i = P_ROOT, levels = 0 ;; ++levels) {
- h = mpool_get(t->bt_mp, i, 0);
- if (h->flags & (P_BLEAF|P_RLEAF)) {
- if (levels == 0)
- levels = 1;
- (void)mpool_put(t->bt_mp, h, 0);
- break;
- }
- i = F_ISSET(t, R_RECNO) ?
- GETRINTERNAL(h, 0)->pgno :
- GETBINTERNAL(h, 0)->pgno;
- (void)mpool_put(t->bt_mp, h, 0);
- }
-
- (void)fprintf(stderr, "%d level%s with %ld keys",
- levels, levels == 1 ? "" : "s", nkeys);
- if (F_ISSET(t, R_RECNO))
- (void)fprintf(stderr, " (%ld header count)", t->bt_nrecs);
- (void)fprintf(stderr,
- "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n",
- pinternal + pleaf + pcont, pleaf, pinternal, pcont);
- (void)fprintf(stderr, "%ld cache hits, %ld cache misses\n",
- bt_cache_hit, bt_cache_miss);
- (void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n",
- bt_split, bt_rootsplit, bt_sortsplit);
- pleaf *= t->bt_psize - BTDATAOFF;
- if (pleaf)
- (void)fprintf(stderr,
- "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n",
- ((double)(pleaf - lfree) / pleaf) * 100,
- pleaf - lfree, lfree);
- pinternal *= t->bt_psize - BTDATAOFF;
- if (pinternal)
- (void)fprintf(stderr,
- "%.0f%% internal fill (%ld bytes used, %ld bytes free\n",
- ((double)(pinternal - ifree) / pinternal) * 100,
- pinternal - ifree, ifree);
- if (bt_pfxsaved)
- (void)fprintf(stderr, "prefix checking removed %lu bytes.\n",
- bt_pfxsaved);
-}
-#endif
diff --git a/main/db1-ast/btree/bt_delete.c b/main/db1-ast/btree/bt_delete.c
deleted file mode 100644
index e816c432a..000000000
--- a/main/db1-ast/btree/bt_delete.c
+++ /dev/null
@@ -1,657 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-static int __bt_bdelete __P((BTREE *, const DBT *));
-static int __bt_curdel __P((BTREE *, const DBT *, PAGE *, u_int));
-static int __bt_pdelete __P((BTREE *, PAGE *));
-static int __bt_relink __P((BTREE *, PAGE *));
-static int __bt_stkacq __P((BTREE *, PAGE **, CURSOR *));
-
-/*
- * __bt_delete
- * Delete the item(s) referenced by a key.
- *
- * Return RET_SPECIAL if the key is not found.
- */
-int
-__bt_delete(dbp, key, flags)
- const DB *dbp;
- const DBT *key;
- u_int flags;
-{
- BTREE *t;
- CURSOR *c;
- PAGE *h;
- int status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /* Check for change to a read-only tree. */
- if (F_ISSET(t, B_RDONLY)) {
- errno = EPERM;
- return (RET_ERROR);
- }
-
- switch (flags) {
- case 0:
- status = __bt_bdelete(t, key);
- break;
- case R_CURSOR:
- /*
- * If flags is R_CURSOR, delete the cursor. Must already
- * have started a scan and not have already deleted it.
- */
- c = &t->bt_cursor;
- if (F_ISSET(c, CURS_INIT)) {
- if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
- return (RET_SPECIAL);
- if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
- return (RET_ERROR);
-
- /*
- * If the page is about to be emptied, we'll need to
- * delete it, which means we have to acquire a stack.
- */
- if (NEXTINDEX(h) == 1)
- if (__bt_stkacq(t, &h, &t->bt_cursor))
- return (RET_ERROR);
-
- status = __bt_dleaf(t, NULL, h, c->pg.index);
-
- if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) {
- if (__bt_pdelete(t, h))
- return (RET_ERROR);
- } else
- mpool_put(t->bt_mp,
- h, status == RET_SUCCESS ? MPOOL_DIRTY : 0);
- break;
- }
- /* FALLTHROUGH */
- default:
- errno = EINVAL;
- return (RET_ERROR);
- }
- if (status == RET_SUCCESS)
- F_SET(t, B_MODIFIED);
- return (status);
-}
-
-/*
- * __bt_stkacq --
- * Acquire a stack so we can delete a cursor entry.
- *
- * Parameters:
- * t: tree
- * hp: pointer to current, pinned PAGE pointer
- * c: pointer to the cursor
- *
- * Returns:
- * 0 on success, 1 on failure
- */
-static int
-__bt_stkacq(t, hp, c)
- BTREE *t;
- PAGE **hp;
- CURSOR *c;
-{
- BINTERNAL *bi;
- EPG *e;
- EPGNO *parent;
- PAGE *h;
- indx_t index = 0;
- pgno_t pgno;
- recno_t nextpg, prevpg;
- int exact, level;
-
- /*
- * Find the first occurrence of the key in the tree. Toss the
- * currently locked page so we don't hit an already-locked page.
- */
- h = *hp;
- mpool_put(t->bt_mp, h, 0);
- if ((e = __bt_search(t, &c->key, &exact)) == NULL)
- return (1);
- h = e->page;
-
- /* See if we got it in one shot. */
- if (h->pgno == c->pg.pgno)
- goto ret;
-
- /*
- * Move right, looking for the page. At each move we have to move
- * up the stack until we don't have to move to the next page. If
- * we have to change pages at an internal level, we have to fix the
- * stack back up.
- */
- while (h->pgno != c->pg.pgno) {
- if ((nextpg = h->nextpg) == P_INVALID)
- break;
- mpool_put(t->bt_mp, h, 0);
-
- /* Move up the stack. */
- for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
- /* Get the parent page. */
- if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
- return (1);
-
- /* Move to the next index. */
- if (parent->index != NEXTINDEX(h) - 1) {
- index = parent->index + 1;
- BT_PUSH(t, h->pgno, index);
- break;
- }
- mpool_put(t->bt_mp, h, 0);
- }
-
- /* Restore the stack. */
- while (level--) {
- /* Push the next level down onto the stack. */
- bi = GETBINTERNAL(h, index);
- pgno = bi->pgno;
- BT_PUSH(t, pgno, 0);
-
- /* Lose the currently pinned page. */
- mpool_put(t->bt_mp, h, 0);
-
- /* Get the next level down. */
- if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
- return (1);
- index = 0;
- }
- mpool_put(t->bt_mp, h, 0);
- if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL)
- return (1);
- }
-
- if (h->pgno == c->pg.pgno)
- goto ret;
-
- /* Reacquire the original stack. */
- mpool_put(t->bt_mp, h, 0);
- if ((e = __bt_search(t, &c->key, &exact)) == NULL)
- return (1);
- h = e->page;
-
- /*
- * Move left, looking for the page. At each move we have to move
- * up the stack until we don't have to change pages to move to the
- * next page. If we have to change pages at an internal level, we
- * have to fix the stack back up.
- */
- while (h->pgno != c->pg.pgno) {
- if ((prevpg = h->prevpg) == P_INVALID)
- break;
- mpool_put(t->bt_mp, h, 0);
-
- /* Move up the stack. */
- for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
- /* Get the parent page. */
- if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
- return (1);
-
- /* Move to the next index. */
- if (parent->index != 0) {
- index = parent->index - 1;
- BT_PUSH(t, h->pgno, index);
- break;
- }
- mpool_put(t->bt_mp, h, 0);
- }
-
- /* Restore the stack. */
- while (level--) {
- /* Push the next level down onto the stack. */
- bi = GETBINTERNAL(h, index);
- pgno = bi->pgno;
-
- /* Lose the currently pinned page. */
- mpool_put(t->bt_mp, h, 0);
-
- /* Get the next level down. */
- if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
- return (1);
-
- index = NEXTINDEX(h) - 1;
- BT_PUSH(t, pgno, index);
- }
- mpool_put(t->bt_mp, h, 0);
- if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL)
- return (1);
- }
-
-
-ret: mpool_put(t->bt_mp, h, 0);
- return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);
-}
-
-/*
- * __bt_bdelete --
- * Delete all key/data pairs matching the specified key.
- *
- * Parameters:
- * t: tree
- * key: key to delete
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
- */
-static int
-__bt_bdelete(t, key)
- BTREE *t;
- const DBT *key;
-{
- EPG *e;
- PAGE *h;
- int deleted, exact, redo;
-
- deleted = 0;
-
- /* Find any matching record; __bt_search pins the page. */
-loop: if ((e = __bt_search(t, key, &exact)) == NULL)
- return (deleted ? RET_SUCCESS : RET_ERROR);
- if (!exact) {
- mpool_put(t->bt_mp, e->page, 0);
- return (deleted ? RET_SUCCESS : RET_SPECIAL);
- }
-
- /*
- * Delete forward, then delete backward, from the found key. If
- * there are duplicates and we reach either side of the page, do
- * the key search again, so that we get them all.
- */
- redo = 0;
- h = e->page;
- do {
- if (__bt_dleaf(t, key, h, e->index)) {
- mpool_put(t->bt_mp, h, 0);
- return (RET_ERROR);
- }
- if (F_ISSET(t, B_NODUPS)) {
- if (NEXTINDEX(h) == 0) {
- if (__bt_pdelete(t, h))
- return (RET_ERROR);
- } else
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- return (RET_SUCCESS);
- }
- deleted = 1;
- } while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
-
- /* Check for right-hand edge of the page. */
- if (e->index == NEXTINDEX(h))
- redo = 1;
-
- /* Delete from the key to the beginning of the page. */
- while (e->index-- > 0) {
- if (__bt_cmp(t, key, e) != 0)
- break;
- if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) {
- mpool_put(t->bt_mp, h, 0);
- return (RET_ERROR);
- }
- if (e->index == 0)
- redo = 1;
- }
-
- /* Check for an empty page. */
- if (NEXTINDEX(h) == 0) {
- if (__bt_pdelete(t, h))
- return (RET_ERROR);
- goto loop;
- }
-
- /* Put the page. */
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
-
- if (redo)
- goto loop;
- return (RET_SUCCESS);
-}
-
-/*
- * __bt_pdelete --
- * Delete a single page from the tree.
- *
- * Parameters:
- * t: tree
- * h: leaf page
- *
- * Returns:
- * RET_SUCCESS, RET_ERROR.
- *
- * Side-effects:
- * mpool_put's the page
- */
-static int
-__bt_pdelete(t, h)
- BTREE *t;
- PAGE *h;
-{
- BINTERNAL *bi;
- PAGE *pg;
- EPGNO *parent;
- indx_t cnt, index, *ip, offset;
- u_int32_t nksize;
- char *from;
-
- /*
- * Walk the parent page stack -- a LIFO stack of the pages that were
- * traversed when we searched for the page where the delete occurred.
- * Each stack entry is a page number and a page index offset. The
- * offset is for the page traversed on the search. We've just deleted
- * a page, so we have to delete the key from the parent page.
- *
- * If the delete from the parent page makes it empty, this process may
- * continue all the way up the tree. We stop if we reach the root page
- * (which is never deleted, it's just not worth the effort) or if the
- * delete does not empty the page.
- */
- while ((parent = BT_POP(t)) != NULL) {
- /* Get the parent page. */
- if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
- return (RET_ERROR);
-
- index = parent->index;
- bi = GETBINTERNAL(pg, index);
-
- /* Free any overflow pages. */
- if (bi->flags & P_BIGKEY &&
- __ovfl_delete(t, bi->bytes) == RET_ERROR) {
- mpool_put(t->bt_mp, pg, 0);
- return (RET_ERROR);
- }
-
- /*
- * Free the parent if it has only the one key and it's not the
- * root page. If it's the rootpage, turn it back into an empty
- * leaf page.
- */
- if (NEXTINDEX(pg) == 1) {
- if (pg->pgno == P_ROOT) {
- pg->lower = BTDATAOFF;
- pg->upper = t->bt_psize;
- pg->flags = P_BLEAF;
- } else {
- if (__bt_relink(t, pg) || __bt_free(t, pg))
- return (RET_ERROR);
- continue;
- }
- } else {
- /* Pack remaining key items at the end of the page. */
- nksize = NBINTERNAL(bi->ksize);
- from = (char *)pg + pg->upper;
- memmove(from + nksize, from, (char *)bi - from);
- pg->upper += nksize;
-
- /* Adjust indices' offsets, shift the indices down. */
- offset = pg->linp[index];
- for (cnt = index, ip = &pg->linp[0]; cnt--; ++ip)
- if (ip[0] < offset)
- ip[0] += nksize;
- for (cnt = NEXTINDEX(pg) - index; --cnt; ++ip)
- ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1];
- pg->lower -= sizeof(indx_t);
- }
-
- mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
- break;
- }
-
- /* Free the leaf page, as long as it wasn't the root. */
- if (h->pgno == P_ROOT) {
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- return (RET_SUCCESS);
- }
- return (__bt_relink(t, h) || __bt_free(t, h));
-}
-
-/*
- * __bt_dleaf --
- * Delete a single record from a leaf page.
- *
- * Parameters:
- * t: tree
- * key: referenced key
- * h: page
- * index: index on page to delete
- *
- * Returns:
- * RET_SUCCESS, RET_ERROR.
- */
-int
-__bt_dleaf(t, key, h, index)
- BTREE *t;
- const DBT *key;
- PAGE *h;
- u_int index;
-{
- BLEAF *bl;
- indx_t cnt, *ip, offset;
- u_int32_t nbytes;
- void *to;
- char *from;
-
- /* If this record is referenced by the cursor, delete the cursor. */
- if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
- !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
- t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == index &&
- __bt_curdel(t, key, h, index))
- return (RET_ERROR);
-
- /* If the entry uses overflow pages, make them available for reuse. */
- to = bl = GETBLEAF(h, index);
- if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
- return (RET_ERROR);
- if (bl->flags & P_BIGDATA &&
- __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR)
- return (RET_ERROR);
-
- /* Pack the remaining key/data items at the end of the page. */
- nbytes = NBLEAF(bl);
- from = (char *)h + h->upper;
- memmove(from + nbytes, from, (char *)to - from);
- h->upper += nbytes;
-
- /* Adjust the indices' offsets, shift the indices down. */
- offset = h->linp[index];
- for (cnt = index, ip = &h->linp[0]; cnt--; ++ip)
- if (ip[0] < offset)
- ip[0] += nbytes;
- for (cnt = NEXTINDEX(h) - index; --cnt; ++ip)
- ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
- h->lower -= sizeof(indx_t);
-
- /* If the cursor is on this page, adjust it as necessary. */
- if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
- !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
- t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > index)
- --t->bt_cursor.pg.index;
-
- return (RET_SUCCESS);
-}
-
-/*
- * __bt_curdel --
- * Delete the cursor.
- *
- * Parameters:
- * t: tree
- * key: referenced key (or NULL)
- * h: page
- * index: index on page to delete
- *
- * Returns:
- * RET_SUCCESS, RET_ERROR.
- */
-static int
-__bt_curdel(t, key, h, index)
- BTREE *t;
- const DBT *key;
- PAGE *h;
- u_int index;
-{
- CURSOR *c;
- EPG e;
- PAGE *pg;
- int curcopy, status;
-
- /*
- * If there are duplicates, move forward or backward to one.
- * Otherwise, copy the key into the cursor area.
- */
- c = &t->bt_cursor;
- F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE);
-
- curcopy = 0;
- if (!F_ISSET(t, B_NODUPS)) {
- /*
- * We're going to have to do comparisons. If we weren't
- * provided a copy of the key, i.e. the user is deleting
- * the current cursor position, get one.
- */
- if (key == NULL) {
- e.page = h;
- e.index = index;
- if ((status = __bt_ret(t, &e,
- &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS)
- return (status);
- curcopy = 1;
- key = &c->key;
- }
- /* Check previous key, if not at the beginning of the page. */
- if (index > 0) {
- e.page = h;
- e.index = index - 1;
- if (__bt_cmp(t, key, &e) == 0) {
- F_SET(c, CURS_BEFORE);
- goto dup2;
- }
- }
- /* Check next key, if not at the end of the page. */
- if (index < NEXTINDEX(h) - 1) {
- e.page = h;
- e.index = index + 1;
- if (__bt_cmp(t, key, &e) == 0) {
- F_SET(c, CURS_AFTER);
- goto dup2;
- }
- }
- /* Check previous key if at the beginning of the page. */
- if (index == 0 && h->prevpg != P_INVALID) {
- if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
- return (RET_ERROR);
- e.page = pg;
- e.index = NEXTINDEX(pg) - 1;
- if (__bt_cmp(t, key, &e) == 0) {
- F_SET(c, CURS_BEFORE);
- goto dup1;
- }
- mpool_put(t->bt_mp, pg, 0);
- }
- /* Check next key if at the end of the page. */
- if (index == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
- if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
- return (RET_ERROR);
- e.page = pg;
- e.index = 0;
- if (__bt_cmp(t, key, &e) == 0) {
- F_SET(c, CURS_AFTER);
-dup1: mpool_put(t->bt_mp, pg, 0);
-dup2: c->pg.pgno = e.page->pgno;
- c->pg.index = e.index;
- return (RET_SUCCESS);
- }
- mpool_put(t->bt_mp, pg, 0);
- }
- }
- e.page = h;
- e.index = index;
- if (curcopy || (status =
- __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) {
- F_SET(c, CURS_ACQUIRE);
- return (RET_SUCCESS);
- }
- return (status);
-}
-
-/*
- * __bt_relink --
- * Link around a deleted page.
- *
- * Parameters:
- * t: tree
- * h: page to be deleted
- */
-static int
-__bt_relink(t, h)
- BTREE *t;
- PAGE *h;
-{
- PAGE *pg;
-
- if (h->nextpg != P_INVALID) {
- if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
- return (RET_ERROR);
- pg->prevpg = h->prevpg;
- mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
- }
- if (h->prevpg != P_INVALID) {
- if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
- return (RET_ERROR);
- pg->nextpg = h->nextpg;
- mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
- }
- return (0);
-}
diff --git a/main/db1-ast/btree/bt_get.c b/main/db1-ast/btree/bt_get.c
deleted file mode 100644
index b5e18022c..000000000
--- a/main/db1-ast/btree/bt_get.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_get.c 8.6 (Berkeley) 7/20/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-/*
- * __BT_GET -- Get a record from the btree.
- *
- * Parameters:
- * dbp: pointer to access method
- * key: key to find
- * data: data to return
- * flag: currently unused
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
- */
-int
-__bt_get(dbp, key, data, flags)
- const DB *dbp;
- const DBT *key;
- DBT *data;
- u_int flags;
-{
- BTREE *t;
- EPG *e;
- int exact, status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /* Get currently doesn't take any flags. */
- if (flags) {
- errno = EINVAL;
- return (RET_ERROR);
- }
-
- if ((e = __bt_search(t, key, &exact)) == NULL)
- return (RET_ERROR);
- if (!exact) {
- mpool_put(t->bt_mp, e->page, 0);
- return (RET_SPECIAL);
- }
-
- status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0);
-
- /*
- * If the user is doing concurrent access, we copied the
- * key/data, toss the page.
- */
- if (F_ISSET(t, B_DB_LOCK))
- mpool_put(t->bt_mp, e->page, 0);
- else
- t->bt_pinned = e->page;
- return (status);
-}
diff --git a/main/db1-ast/btree/bt_open.c b/main/db1-ast/btree/bt_open.c
deleted file mode 100644
index 5d40e4593..000000000
--- a/main/db1-ast/btree/bt_open.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_open.c 8.10 (Berkeley) 8/17/94";
-#endif /* LIBC_SCCS and not lint */
-
-/*
- * Implementation of btree access method for 4.4BSD.
- *
- * The design here was originally based on that of the btree access method
- * used in the Postgres database system at UC Berkeley. This implementation
- * is wholly independent of the Postgres code.
- */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-#ifdef DEBUG
-#undef MINPSIZE
-#define MINPSIZE 128
-#endif
-
-static int byteorder __P((void));
-static int nroot __P((BTREE *));
-static int tmp __P((void));
-
-/*
- * __BT_OPEN -- Open a btree.
- *
- * Creates and fills a DB struct, and calls the routine that actually
- * opens the btree.
- *
- * Parameters:
- * fname: filename (NULL for in-memory trees)
- * flags: open flag bits
- * mode: open permission bits
- * b: BTREEINFO pointer
- *
- * Returns:
- * NULL on failure, pointer to DB on success.
- *
- */
-DB *
-__bt_open(fname, flags, mode, openinfo, dflags)
- const char *fname;
- int flags, mode, dflags;
- const BTREEINFO *openinfo;
-{
- struct stat sb;
- BTMETA m;
- BTREE *t;
- BTREEINFO b;
- DB *dbp;
- pgno_t ncache;
- ssize_t nr;
- int machine_lorder;
-
- t = NULL;
-
- /*
- * Intention is to make sure all of the user's selections are okay
- * here and then use them without checking. Can't be complete, since
- * we don't know the right page size, lorder or flags until the backing
- * file is opened. Also, the file's page size can cause the cachesize
- * to change.
- */
- machine_lorder = byteorder();
- if (openinfo) {
- b = *openinfo;
-
- /* Flags: R_DUP. */
- if (b.flags & ~(R_DUP))
- goto einval;
-
- /*
- * Page size must be indx_t aligned and >= MINPSIZE. Default
- * page size is set farther on, based on the underlying file
- * transfer size.
- */
- if (b.psize &&
- (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 ||
- b.psize & (sizeof(indx_t) - 1)))
- goto einval;
-
- /* Minimum number of keys per page; absolute minimum is 2. */
- if (b.minkeypage) {
- if (b.minkeypage < 2)
- goto einval;
- } else
- b.minkeypage = DEFMINKEYPAGE;
-
- /* If no comparison, use default comparison and prefix. */
- if (b.compare == NULL) {
- b.compare = __bt_defcmp;
- if (b.prefix == NULL)
- b.prefix = __bt_defpfx;
- }
-
- if (b.lorder == 0)
- b.lorder = machine_lorder;
- } else {
- b.compare = __bt_defcmp;
- b.cachesize = 0;
- b.flags = 0;
- b.lorder = machine_lorder;
- b.minkeypage = DEFMINKEYPAGE;
- b.prefix = __bt_defpfx;
- b.psize = 0;
- }
-
- /* Check for the ubiquitous PDP-11. */
- if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN)
- goto einval;
-
- /* Allocate and initialize DB and BTREE structures. */
- if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL)
- goto err;
- memset(t, 0, sizeof(BTREE));
- t->bt_fd = -1; /* Don't close unopened fd on error. */
- t->bt_lorder = b.lorder;
- t->bt_order = NOT;
- t->bt_cmp = b.compare;
- t->bt_pfx = b.prefix;
- t->bt_rfd = -1;
-
- if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL)
- goto err;
- memset(t->bt_dbp, 0, sizeof(DB));
- if (t->bt_lorder != machine_lorder)
- F_SET(t, B_NEEDSWAP);
-
- dbp->type = DB_BTREE;
- dbp->internal = t;
- dbp->close = __bt_close;
- dbp->del = __bt_delete;
- dbp->fd = __bt_fd;
- dbp->get = __bt_get;
- dbp->put = __bt_put;
- dbp->seq = __bt_seq;
- dbp->sync = __bt_sync;
-
- /*
- * If no file name was supplied, this is an in-memory btree and we
- * open a backing temporary file. Otherwise, it's a disk-based tree.
- */
- if (fname) {
- switch (flags & O_ACCMODE) {
- case O_RDONLY:
- F_SET(t, B_RDONLY);
- break;
- case O_RDWR:
- break;
- case O_WRONLY:
- default:
- goto einval;
- }
-
- if ((t->bt_fd = open(fname, flags, mode)) < 0)
- goto err;
-
- } else {
- if ((flags & O_ACCMODE) != O_RDWR)
- goto einval;
- if ((t->bt_fd = tmp()) == -1)
- goto err;
- F_SET(t, B_INMEM);
- }
-
- if (fcntl(t->bt_fd, F_SETFD, 1) == -1)
- goto err;
-
- if (fstat(t->bt_fd, &sb))
- goto err;
- if (sb.st_size) {
- if ((nr = read(t->bt_fd, &m, sizeof(BTMETA))) < 0)
- goto err;
- if (nr != sizeof(BTMETA))
- goto eftype;
-
- /*
- * Read in the meta-data. This can change the notion of what
- * the lorder, page size and flags are, and, when the page size
- * changes, the cachesize value can change too. If the user
- * specified the wrong byte order for an existing database, we
- * don't bother to return an error, we just clear the NEEDSWAP
- * bit.
- */
- if (m.magic == BTREEMAGIC)
- F_CLR(t, B_NEEDSWAP);
- else {
- F_SET(t, B_NEEDSWAP);
- M_32_SWAP(m.magic);
- M_32_SWAP(m.version);
- M_32_SWAP(m.psize);
- M_32_SWAP(m.free);
- M_32_SWAP(m.nrecs);
- M_32_SWAP(m.flags);
- }
- if (m.magic != BTREEMAGIC || m.version != BTREEVERSION)
- goto eftype;
- if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 ||
- m.psize & (sizeof(indx_t) - 1))
- goto eftype;
- if (m.flags & ~SAVEMETA)
- goto eftype;
- b.psize = m.psize;
- F_SET(t, m.flags);
- t->bt_free = m.free;
- t->bt_nrecs = m.nrecs;
- } else {
- /*
- * Set the page size to the best value for I/O to this file.
- * Don't overflow the page offset type.
- */
- if (b.psize == 0) {
-#ifdef _STATBUF_ST_BLKSIZE
- b.psize = sb.st_blksize;
-#endif
- if (b.psize < MINPSIZE)
- b.psize = MINPSIZE;
- if (b.psize > MAX_PAGE_OFFSET + 1)
- b.psize = MAX_PAGE_OFFSET + 1;
- }
-
- /* Set flag if duplicates permitted. */
- if (!(b.flags & R_DUP))
- F_SET(t, B_NODUPS);
-
- t->bt_free = P_INVALID;
- t->bt_nrecs = 0;
- F_SET(t, B_METADIRTY);
- }
-
- t->bt_psize = b.psize;
-
- /* Set the cache size; must be a multiple of the page size. */
- if (b.cachesize && b.cachesize & (b.psize - 1))
- b.cachesize += (~b.cachesize & (b.psize - 1)) + 1;
- if (b.cachesize < b.psize * MINCACHE)
- b.cachesize = b.psize * MINCACHE;
-
- /* Calculate number of pages to cache. */
- ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize;
-
- /*
- * The btree data structure requires that at least two keys can fit on
- * a page, but other than that there's no fixed requirement. The user
- * specified a minimum number per page, and we translated that into the
- * number of bytes a key/data pair can use before being placed on an
- * overflow page. This calculation includes the page header, the size
- * of the index referencing the leaf item and the size of the leaf item
- * structure. Also, don't let the user specify a minkeypage such that
- * a key/data pair won't fit even if both key and data are on overflow
- * pages.
- */
- t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage -
- (sizeof(indx_t) + NBLEAFDBT(0, 0));
- if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t))
- t->bt_ovflsize =
- NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t);
-
- /* Initialize the buffer pool. */
- if ((t->bt_mp =
- mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL)
- goto err;
- if (!F_ISSET(t, B_INMEM))
- mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t);
-
- /* Create a root page if new tree. */
- if (nroot(t) == RET_ERROR)
- goto err;
-
- /* Global flags. */
- if (dflags & DB_LOCK)
- F_SET(t, B_DB_LOCK);
- if (dflags & DB_SHMEM)
- F_SET(t, B_DB_SHMEM);
- if (dflags & DB_TXN)
- F_SET(t, B_DB_TXN);
-
- return (dbp);
-
-einval: errno = EINVAL;
- goto err;
-
-eftype: errno = EFTYPE;
- goto err;
-
-err: if (t) {
- if (t->bt_dbp)
- free(t->bt_dbp);
- if (t->bt_fd != -1)
- (void)close(t->bt_fd);
- free(t);
- }
- return (NULL);
-}
-
-/*
- * NROOT -- Create the root of a new tree.
- *
- * Parameters:
- * t: tree
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-static int
-nroot(t)
- BTREE *t;
-{
- PAGE *meta, *root;
- pgno_t npg;
-
- if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) {
- mpool_put(t->bt_mp, meta, 0);
- return (RET_SUCCESS);
- }
- if (errno != EINVAL) /* It's OK to not exist. */
- return (RET_ERROR);
- errno = 0;
-
- if ((meta = mpool_new(t->bt_mp, &npg)) == NULL)
- return (RET_ERROR);
-
- if ((root = mpool_new(t->bt_mp, &npg)) == NULL)
- return (RET_ERROR);
-
- if (npg != P_ROOT)
- return (RET_ERROR);
- root->pgno = npg;
- root->prevpg = root->nextpg = P_INVALID;
- root->lower = BTDATAOFF;
- root->upper = t->bt_psize;
- root->flags = P_BLEAF;
- memset(meta, 0, t->bt_psize);
- mpool_put(t->bt_mp, meta, MPOOL_DIRTY);
- mpool_put(t->bt_mp, root, MPOOL_DIRTY);
- return (RET_SUCCESS);
-}
-
-static int
-tmp()
-{
- sigset_t set, oset;
- int fd;
- const char *envtmp;
- char *path;
- static const char fmt[] = "%s/bt.XXXXXX";
- size_t n;
-
- envtmp = getenv("TMPDIR");
- if (!envtmp)
- envtmp = "/tmp";
- n = strlen (envtmp) + sizeof fmt;
-#ifdef __GNUC__
- path = __builtin_alloca(n);
-#else
- path = malloc(n);
-#endif
- (void)snprintf(path, n, fmt, envtmp ? envtmp : "/tmp");
-
- (void)sigfillset(&set);
- (void)sigprocmask(SIG_BLOCK, &set, &oset);
- if ((fd = mkstemp(path)) != -1)
- (void)unlink(path);
- (void)sigprocmask(SIG_SETMASK, &oset, NULL);
-#ifndef __GNUC__
- free(path);
-#endif
- return(fd);
-}
-
-static int
-byteorder()
-{
- u_int32_t x;
- u_char *p;
-
- x = 0x01020304;
- p = (u_char *)&x;
- switch (*p) {
- case 1:
- return (BIG_ENDIAN);
- case 4:
- return (LITTLE_ENDIAN);
- default:
- return (0);
- }
-}
-
-int
-__bt_fd(dbp)
- const DB *dbp;
-{
- BTREE *t;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /* In-memory database can't have a file descriptor. */
- if (F_ISSET(t, B_INMEM)) {
- errno = ENOENT;
- return (-1);
- }
- return (t->bt_fd);
-}
diff --git a/main/db1-ast/btree/bt_overflow.c b/main/db1-ast/btree/bt_overflow.c
deleted file mode 100644
index d8f310d91..000000000
--- a/main/db1-ast/btree/bt_overflow.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_overflow.c 8.5 (Berkeley) 7/16/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-/*
- * Big key/data code.
- *
- * Big key and data entries are stored on linked lists of pages. The initial
- * reference is byte string stored with the key or data and is the page number
- * and size. The actual record is stored in a chain of pages linked by the
- * nextpg field of the PAGE header.
- *
- * The first page of the chain has a special property. If the record is used
- * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set
- * in the header.
- *
- * XXX
- * A single DBT is written to each chain, so a lot of space on the last page
- * is wasted. This is a fairly major bug for some data sets.
- */
-
-/*
- * __OVFL_GET -- Get an overflow key/data item.
- *
- * Parameters:
- * t: tree
- * p: pointer to { pgno_t, u_int32_t }
- * buf: storage address
- * bufsz: storage size
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__ovfl_get(t, p, ssz, buf, bufsz)
- BTREE *t;
- void *p;
- size_t *ssz;
- void **buf;
- size_t *bufsz;
-{
- PAGE *h;
- pgno_t pg;
- size_t nb, plen;
- u_int32_t sz;
-
- memmove(&pg, p, sizeof(pgno_t));
- memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
- *ssz = sz;
-
-#ifdef DEBUG
- if (pg == P_INVALID || sz == 0)
- abort();
-#endif
- /* Make the buffer bigger as necessary. */
- if (*bufsz < sz) {
- *buf = (char *)(*buf == NULL ? malloc(sz) : realloc(*buf, sz));
- if (*buf == NULL)
- return (RET_ERROR);
- *bufsz = sz;
- }
-
- /*
- * Step through the linked list of pages, copying the data on each one
- * into the buffer. Never copy more than the data's length.
- */
- plen = t->bt_psize - BTDATAOFF;
- for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
-
- nb = MIN(sz, plen);
- memmove(p, (char *)h + BTDATAOFF, nb);
- mpool_put(t->bt_mp, h, 0);
-
- if ((sz -= nb) == 0)
- break;
- }
- return (RET_SUCCESS);
-}
-
-/*
- * __OVFL_PUT -- Store an overflow key/data item.
- *
- * Parameters:
- * t: tree
- * data: DBT to store
- * pgno: storage page number
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__ovfl_put(t, dbt, pg)
- BTREE *t;
- const DBT *dbt;
- pgno_t *pg;
-{
- PAGE *h, *last;
- void *p;
- pgno_t npg;
- size_t nb, plen;
- u_int32_t sz;
-
- /*
- * Allocate pages and copy the key/data record into them. Store the
- * number of the first page in the chain.
- */
- plen = t->bt_psize - BTDATAOFF;
- for (last = NULL, p = dbt->data, sz = dbt->size;;
- p = (char *)p + plen, last = h) {
- if ((h = __bt_new(t, &npg)) == NULL)
- return (RET_ERROR);
-
- h->pgno = npg;
- h->nextpg = h->prevpg = P_INVALID;
- h->flags = P_OVERFLOW;
- h->lower = h->upper = 0;
-
- nb = MIN(sz, plen);
- memmove((char *)h + BTDATAOFF, p, nb);
-
- if (last) {
- last->nextpg = h->pgno;
- mpool_put(t->bt_mp, last, MPOOL_DIRTY);
- } else
- *pg = h->pgno;
-
- if ((sz -= nb) == 0) {
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- break;
- }
- }
- return (RET_SUCCESS);
-}
-
-/*
- * __OVFL_DELETE -- Delete an overflow chain.
- *
- * Parameters:
- * t: tree
- * p: pointer to { pgno_t, u_int32_t }
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__ovfl_delete(t, p)
- BTREE *t;
- void *p;
-{
- PAGE *h;
- pgno_t pg;
- size_t plen;
- u_int32_t sz;
-
- memmove(&pg, p, sizeof(pgno_t));
- memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
-
-#ifdef DEBUG
- if (pg == P_INVALID || sz == 0)
- abort();
-#endif
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
-
- /* Don't delete chains used by internal pages. */
- if (h->flags & P_PRESERVE) {
- mpool_put(t->bt_mp, h, 0);
- return (RET_SUCCESS);
- }
-
- /* Step through the chain, calling the free routine for each page. */
- for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) {
- pg = h->nextpg;
- __bt_free(t, h);
- if (sz <= plen)
- break;
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
- }
- return (RET_SUCCESS);
-}
diff --git a/main/db1-ast/btree/bt_page.c b/main/db1-ast/btree/bt_page.c
deleted file mode 100644
index e77a1d6b5..000000000
--- a/main/db1-ast/btree/bt_page.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_page.c 8.3 (Berkeley) 7/14/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <stdio.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-/*
- * __bt_free --
- * Put a page on the freelist.
- *
- * Parameters:
- * t: tree
- * h: page to free
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- *
- * Side-effect:
- * mpool_put's the page.
- */
-int
-__bt_free(t, h)
- BTREE *t;
- PAGE *h;
-{
- /* Insert the page at the head of the free list. */
- h->prevpg = P_INVALID;
- h->nextpg = t->bt_free;
- t->bt_free = h->pgno;
- F_SET(t, B_METADIRTY);
-
- /* Make sure the page gets written back. */
- return (mpool_put(t->bt_mp, h, MPOOL_DIRTY));
-}
-
-/*
- * __bt_new --
- * Get a new page, preferably from the freelist.
- *
- * Parameters:
- * t: tree
- * npg: storage for page number.
- *
- * Returns:
- * Pointer to a page, NULL on error.
- */
-PAGE *
-__bt_new(t, npg)
- BTREE *t;
- pgno_t *npg;
-{
- PAGE *h;
-
- if (t->bt_free != P_INVALID &&
- (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) {
- *npg = t->bt_free;
- t->bt_free = h->nextpg;
- F_SET(t, B_METADIRTY);
- return (h);
- }
- return (mpool_new(t->bt_mp, npg));
-}
diff --git a/main/db1-ast/btree/bt_put.c b/main/db1-ast/btree/bt_put.c
deleted file mode 100644
index aeb0bb16c..000000000
--- a/main/db1-ast/btree/bt_put.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_put.c 8.8 (Berkeley) 7/26/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-static EPG *bt_fast __P((BTREE *, const DBT *, const DBT *, int *));
-
-/*
- * __BT_PUT -- Add a btree item to the tree.
- *
- * Parameters:
- * dbp: pointer to access method
- * key: key
- * data: data
- * flag: R_NOOVERWRITE
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the
- * tree and R_NOOVERWRITE specified.
- */
-int
-__bt_put(dbp, key, data, flags)
- const DB *dbp;
- DBT *key;
- const DBT *data;
- u_int flags;
-{
- BTREE *t;
- DBT tkey, tdata;
- EPG *e = 0;
- PAGE *h;
- indx_t index, nxtindex;
- pgno_t pg;
- u_int32_t nbytes;
- int dflags, exact, status;
- char *dest, db[NOVFLSIZE], kb[NOVFLSIZE];
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /* Check for change to a read-only tree. */
- if (F_ISSET(t, B_RDONLY)) {
- errno = EPERM;
- return (RET_ERROR);
- }
-
- switch (flags) {
- case 0:
- case R_NOOVERWRITE:
- break;
- case R_CURSOR:
- /*
- * If flags is R_CURSOR, put the cursor. Must already
- * have started a scan and not have already deleted it.
- */
- if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
- !F_ISSET(&t->bt_cursor,
- CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
- break;
- /* FALLTHROUGH */
- default:
- errno = EINVAL;
- return (RET_ERROR);
- }
-
- /*
- * If the key/data pair won't fit on a page, store it on overflow
- * pages. Only put the key on the overflow page if the pair are
- * still too big after moving the data to an overflow page.
- *
- * XXX
- * If the insert fails later on, the overflow pages aren't recovered.
- */
- dflags = 0;
- if (key->size + data->size > t->bt_ovflsize) {
- if (key->size > t->bt_ovflsize) {
-storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR)
- return (RET_ERROR);
- tkey.data = kb;
- tkey.size = NOVFLSIZE;
- memmove(kb, &pg, sizeof(pgno_t));
- memmove(kb + sizeof(pgno_t),
- &key->size, sizeof(u_int32_t));
- dflags |= P_BIGKEY;
- key = &tkey;
- }
- if (key->size + data->size > t->bt_ovflsize) {
- if (__ovfl_put(t, data, &pg) == RET_ERROR)
- return (RET_ERROR);
- tdata.data = db;
- tdata.size = NOVFLSIZE;
- memmove(db, &pg, sizeof(pgno_t));
- memmove(db + sizeof(pgno_t),
- &data->size, sizeof(u_int32_t));
- dflags |= P_BIGDATA;
- data = &tdata;
- }
- if (key->size + data->size > t->bt_ovflsize)
- goto storekey;
- }
-
- /* Replace the cursor. */
- if (flags == R_CURSOR) {
- if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL)
- return (RET_ERROR);
- index = t->bt_cursor.pg.index;
- goto delete;
- }
-
- /*
- * Find the key to delete, or, the location at which to insert.
- * Bt_fast and __bt_search both pin the returned page.
- */
- if (t->bt_order == NOT || (e = bt_fast(t, key, data, &exact)) == NULL)
- if ((e = __bt_search(t, key, &exact)) == NULL)
- return (RET_ERROR);
- h = e->page;
- index = e->index;
-
- /*
- * Add the key/data pair to the tree. If an identical key is already
- * in the tree, and R_NOOVERWRITE is set, an error is returned. If
- * R_NOOVERWRITE is not set, the key is either added (if duplicates are
- * permitted) or an error is returned.
- */
- switch (flags) {
- case R_NOOVERWRITE:
- if (!exact)
- break;
- mpool_put(t->bt_mp, h, 0);
- return (RET_SPECIAL);
- default:
- if (!exact || !F_ISSET(t, B_NODUPS))
- break;
- /*
- * !!!
- * Note, the delete may empty the page, so we need to put a
- * new entry into the page immediately.
- */
-delete: if (__bt_dleaf(t, key, h, index) == RET_ERROR) {
- mpool_put(t->bt_mp, h, 0);
- return (RET_ERROR);
- }
- break;
- }
-
- /*
- * If not enough room, or the user has put a ceiling on the number of
- * keys permitted in the page, split the page. The split code will
- * insert the key and data and unpin the current page. If inserting
- * into the offset array, shift the pointers up.
- */
- nbytes = NBLEAFDBT(key->size, data->size);
- if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) {
- if ((status = __bt_split(t, h, key,
- data, dflags, nbytes, index)) != RET_SUCCESS)
- return (status);
- goto success;
- }
-
- if (index < (nxtindex = NEXTINDEX(h)))
- memmove(h->linp + index + 1, h->linp + index,
- (nxtindex - index) * sizeof(indx_t));
- h->lower += sizeof(indx_t);
-
- h->linp[index] = h->upper -= nbytes;
- dest = (char *)h + h->upper;
- WR_BLEAF(dest, key, data, dflags);
-
- /* If the cursor is on this page, adjust it as necessary. */
- if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
- !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
- t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= index)
- ++t->bt_cursor.pg.index;
-
- if (t->bt_order == NOT) {
- if (h->nextpg == P_INVALID) {
- if (index == NEXTINDEX(h) - 1) {
- t->bt_order = FORWARD;
- t->bt_last.index = index;
- t->bt_last.pgno = h->pgno;
- }
- } else if (h->prevpg == P_INVALID) {
- if (index == 0) {
- t->bt_order = BACK;
- t->bt_last.index = 0;
- t->bt_last.pgno = h->pgno;
- }
- }
- }
-
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
-
-success:
- if (flags == R_SETCURSOR)
- __bt_setcur(t, e->page->pgno, e->index);
-
- F_SET(t, B_MODIFIED);
- return (RET_SUCCESS);
-}
-
-#ifdef STATISTICS
-u_long bt_cache_hit, bt_cache_miss;
-#endif
-
-/*
- * BT_FAST -- Do a quick check for sorted data.
- *
- * Parameters:
- * t: tree
- * key: key to insert
- *
- * Returns:
- * EPG for new record or NULL if not found.
- */
-static EPG *
-bt_fast(t, key, data, exactp)
- BTREE *t;
- const DBT *key, *data;
- int *exactp;
-{
- PAGE *h;
- u_int32_t nbytes;
- int cmp;
-
- if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) {
- t->bt_order = NOT;
- return (NULL);
- }
- t->bt_cur.page = h;
- t->bt_cur.index = t->bt_last.index;
-
- /*
- * If won't fit in this page or have too many keys in this page,
- * have to search to get split stack.
- */
- nbytes = NBLEAFDBT(key->size, data->size);
- if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t))
- goto miss;
-
- if (t->bt_order == FORWARD) {
- if (t->bt_cur.page->nextpg != P_INVALID)
- goto miss;
- if (t->bt_cur.index != NEXTINDEX(h) - 1)
- goto miss;
- if ((cmp = __bt_cmp(t, key, &t->bt_cur)) < 0)
- goto miss;
- t->bt_last.index = cmp ? ++t->bt_cur.index : t->bt_cur.index;
- } else {
- if (t->bt_cur.page->prevpg != P_INVALID)
- goto miss;
- if (t->bt_cur.index != 0)
- goto miss;
- if ((cmp = __bt_cmp(t, key, &t->bt_cur)) > 0)
- goto miss;
- t->bt_last.index = 0;
- }
- *exactp = cmp == 0;
-#ifdef STATISTICS
- ++bt_cache_hit;
-#endif
- return (&t->bt_cur);
-
-miss:
-#ifdef STATISTICS
- ++bt_cache_miss;
-#endif
- t->bt_order = NOT;
- mpool_put(t->bt_mp, h, 0);
- return (NULL);
-}
diff --git a/main/db1-ast/btree/bt_search.c b/main/db1-ast/btree/bt_search.c
deleted file mode 100644
index 623f43949..000000000
--- a/main/db1-ast/btree/bt_search.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_search.c 8.8 (Berkeley) 7/31/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <stdio.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-static int __bt_snext __P((BTREE *, PAGE *, const DBT *, int *));
-static int __bt_sprev __P((BTREE *, PAGE *, const DBT *, int *));
-
-/*
- * __bt_search --
- * Search a btree for a key.
- *
- * Parameters:
- * t: tree to search
- * key: key to find
- * exactp: pointer to exact match flag
- *
- * Returns:
- * The EPG for matching record, if any, or the EPG for the location
- * of the key, if it were inserted into the tree, is entered into
- * the bt_cur field of the tree. A pointer to the field is returned.
- */
-EPG *
-__bt_search(t, key, exactp)
- BTREE *t;
- const DBT *key;
- int *exactp;
-{
- PAGE *h;
- indx_t base, index, lim;
- pgno_t pg;
- int cmp;
-
- BT_CLR(t);
- for (pg = P_ROOT;;) {
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (NULL);
-
- /* Do a binary search on the current page. */
- t->bt_cur.page = h;
- for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
- t->bt_cur.index = index = base + (lim >> 1);
- if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {
- if (h->flags & P_BLEAF) {
- *exactp = 1;
- return (&t->bt_cur);
- }
- goto next;
- }
- if (cmp > 0) {
- base = index + 1;
- --lim;
- }
- }
-
- /*
- * If it's a leaf page, we're almost done. If no duplicates
- * are allowed, or we have an exact match, we're done. Else,
- * it's possible that there were matching keys on this page,
- * which later deleted, and we're on a page with no matches
- * while there are matches on other pages. If at the start or
- * end of a page, check the adjacent page.
- */
- if (h->flags & P_BLEAF) {
- if (!F_ISSET(t, B_NODUPS)) {
- if (base == 0 &&
- h->prevpg != P_INVALID &&
- __bt_sprev(t, h, key, exactp))
- return (&t->bt_cur);
- if (base == NEXTINDEX(h) &&
- h->nextpg != P_INVALID &&
- __bt_snext(t, h, key, exactp))
- return (&t->bt_cur);
- }
- *exactp = 0;
- t->bt_cur.index = base;
- return (&t->bt_cur);
- }
-
- /*
- * No match found. Base is the smallest index greater than
- * key and may be zero or a last + 1 index. If it's non-zero,
- * decrement by one, and record the internal page which should
- * be a parent page for the key. If a split later occurs, the
- * inserted page will be to the right of the saved page.
- */
- index = base ? base - 1 : base;
-
-next: BT_PUSH(t, h->pgno, index);
- pg = GETBINTERNAL(h, index)->pgno;
- mpool_put(t->bt_mp, h, 0);
- }
-}
-
-/*
- * __bt_snext --
- * Check for an exact match after the key.
- *
- * Parameters:
- * t: tree
- * h: current page
- * key: key
- * exactp: pointer to exact match flag
- *
- * Returns:
- * If an exact match found.
- */
-static int
-__bt_snext(t, h, key, exactp)
- BTREE *t;
- PAGE *h;
- const DBT *key;
- int *exactp;
-{
- EPG e;
-
- /*
- * Get the next page. The key is either an exact
- * match, or not as good as the one we already have.
- */
- if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
- return (0);
- e.index = 0;
- if (__bt_cmp(t, key, &e) == 0) {
- mpool_put(t->bt_mp, h, 0);
- t->bt_cur = e;
- *exactp = 1;
- return (1);
- }
- mpool_put(t->bt_mp, e.page, 0);
- return (0);
-}
-
-/*
- * __bt_sprev --
- * Check for an exact match before the key.
- *
- * Parameters:
- * t: tree
- * h: current page
- * key: key
- * exactp: pointer to exact match flag
- *
- * Returns:
- * If an exact match found.
- */
-static int
-__bt_sprev(t, h, key, exactp)
- BTREE *t;
- PAGE *h;
- const DBT *key;
- int *exactp;
-{
- EPG e;
-
- /*
- * Get the previous page. The key is either an exact
- * match, or not as good as the one we already have.
- */
- if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
- return (0);
- e.index = NEXTINDEX(e.page) - 1;
- if (__bt_cmp(t, key, &e) == 0) {
- mpool_put(t->bt_mp, h, 0);
- t->bt_cur = e;
- *exactp = 1;
- return (1);
- }
- mpool_put(t->bt_mp, e.page, 0);
- return (0);
-}
diff --git a/main/db1-ast/btree/bt_seq.c b/main/db1-ast/btree/bt_seq.c
deleted file mode 100644
index 3f1724274..000000000
--- a/main/db1-ast/btree/bt_seq.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-static int __bt_first __P((BTREE *, const DBT *, EPG *, int *));
-static int __bt_seqadv __P((BTREE *, EPG *, int));
-static int __bt_seqset __P((BTREE *, EPG *, DBT *, int));
-
-/*
- * Sequential scan support.
- *
- * The tree can be scanned sequentially, starting from either end of the
- * tree or from any specific key. A scan request before any scanning is
- * done is initialized as starting from the least node.
- */
-
-/*
- * __bt_seq --
- * Btree sequential scan interface.
- *
- * Parameters:
- * dbp: pointer to access method
- * key: key for positioning and return value
- * data: data return value
- * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
- */
-int
-__bt_seq(dbp, key, data, flags)
- const DB *dbp;
- DBT *key, *data;
- u_int flags;
-{
- BTREE *t;
- EPG e;
- int status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /*
- * If scan uninitialized as yet, or starting at a specific record, set
- * the scan to a specific key. Both __bt_seqset and __bt_seqadv pin
- * the page the cursor references if they're successful.
- */
- switch (flags) {
- case R_NEXT:
- case R_PREV:
- if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
- status = __bt_seqadv(t, &e, flags);
- break;
- }
- /* FALLTHROUGH */
- case R_FIRST:
- case R_LAST:
- case R_CURSOR:
- status = __bt_seqset(t, &e, key, flags);
- break;
- default:
- errno = EINVAL;
- return (RET_ERROR);
- }
-
- if (status == RET_SUCCESS) {
- __bt_setcur(t, e.page->pgno, e.index);
-
- status =
- __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0);
-
- /*
- * If the user is doing concurrent access, we copied the
- * key/data, toss the page.
- */
- if (F_ISSET(t, B_DB_LOCK))
- mpool_put(t->bt_mp, e.page, 0);
- else
- t->bt_pinned = e.page;
- }
- return (status);
-}
-
-/*
- * __bt_seqset --
- * Set the sequential scan to a specific key.
- *
- * Parameters:
- * t: tree
- * ep: storage for returned key
- * key: key for initial scan position
- * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV
- *
- * Side effects:
- * Pins the page the cursor references.
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
- */
-static int
-__bt_seqset(t, ep, key, flags)
- BTREE *t;
- EPG *ep;
- DBT *key;
- int flags;
-{
- PAGE *h;
- pgno_t pg;
- int exact;
-
- /*
- * Find the first, last or specific key in the tree and point the
- * cursor at it. The cursor may not be moved until a new key has
- * been found.
- */
- switch (flags) {
- case R_CURSOR: /* Keyed scan. */
- /*
- * Find the first instance of the key or the smallest key
- * which is greater than or equal to the specified key.
- */
- if (key->data == NULL || key->size == 0) {
- errno = EINVAL;
- return (RET_ERROR);
- }
- return (__bt_first(t, key, ep, &exact));
- case R_FIRST: /* First record. */
- case R_NEXT:
- /* Walk down the left-hand side of the tree. */
- for (pg = P_ROOT;;) {
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
-
- /* Check for an empty tree. */
- if (NEXTINDEX(h) == 0) {
- mpool_put(t->bt_mp, h, 0);
- return (RET_SPECIAL);
- }
-
- if (h->flags & (P_BLEAF | P_RLEAF))
- break;
- pg = GETBINTERNAL(h, 0)->pgno;
- mpool_put(t->bt_mp, h, 0);
- }
- ep->page = h;
- ep->index = 0;
- break;
- case R_LAST: /* Last record. */
- case R_PREV:
- /* Walk down the right-hand side of the tree. */
- for (pg = P_ROOT;;) {
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
-
- /* Check for an empty tree. */
- if (NEXTINDEX(h) == 0) {
- mpool_put(t->bt_mp, h, 0);
- return (RET_SPECIAL);
- }
-
- if (h->flags & (P_BLEAF | P_RLEAF))
- break;
- pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno;
- mpool_put(t->bt_mp, h, 0);
- }
-
- ep->page = h;
- ep->index = NEXTINDEX(h) - 1;
- break;
- }
- return (RET_SUCCESS);
-}
-
-/*
- * __bt_seqadvance --
- * Advance the sequential scan.
- *
- * Parameters:
- * t: tree
- * flags: R_NEXT, R_PREV
- *
- * Side effects:
- * Pins the page the new key/data record is on.
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
- */
-static int
-__bt_seqadv(t, ep, flags)
- BTREE *t;
- EPG *ep;
- int flags;
-{
- CURSOR *c;
- PAGE *h;
- indx_t index = 0;
- pgno_t pg;
- int exact;
-
- /*
- * There are a couple of states that we can be in. The cursor has
- * been initialized by the time we get here, but that's all we know.
- */
- c = &t->bt_cursor;
-
- /*
- * The cursor was deleted where there weren't any duplicate records,
- * so the key was saved. Find out where that key would go in the
- * current tree. It doesn't matter if the returned key is an exact
- * match or not -- if it's an exact match, the record was added after
- * the delete so we can just return it. If not, as long as there's
- * a record there, return it.
- */
- if (F_ISSET(c, CURS_ACQUIRE))
- return (__bt_first(t, &c->key, ep, &exact));
-
- /* Get the page referenced by the cursor. */
- if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
- return (RET_ERROR);
-
- /*
- * Find the next/previous record in the tree and point the cursor at
- * it. The cursor may not be moved until a new key has been found.
- */
- switch (flags) {
- case R_NEXT: /* Next record. */
- /*
- * The cursor was deleted in duplicate records, and moved
- * forward to a record that has yet to be returned. Clear
- * that flag, and return the record.
- */
- if (F_ISSET(c, CURS_AFTER))
- goto usecurrent;
- index = c->pg.index;
- if (++index == NEXTINDEX(h)) {
- pg = h->nextpg;
- mpool_put(t->bt_mp, h, 0);
- if (pg == P_INVALID)
- return (RET_SPECIAL);
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
- index = 0;
- }
- break;
- case R_PREV: /* Previous record. */
- /*
- * The cursor was deleted in duplicate records, and moved
- * backward to a record that has yet to be returned. Clear
- * that flag, and return the record.
- */
- if (F_ISSET(c, CURS_BEFORE)) {
-usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE);
- ep->page = h;
- ep->index = c->pg.index;
- return (RET_SUCCESS);
- }
- index = c->pg.index;
- if (index == 0) {
- pg = h->prevpg;
- mpool_put(t->bt_mp, h, 0);
- if (pg == P_INVALID)
- return (RET_SPECIAL);
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
- index = NEXTINDEX(h) - 1;
- } else
- --index;
- break;
- }
-
- ep->page = h;
- ep->index = index;
- return (RET_SUCCESS);
-}
-
-/*
- * __bt_first --
- * Find the first entry.
- *
- * Parameters:
- * t: the tree
- * key: the key
- * erval: return EPG
- * exactp: pointer to exact match flag
- *
- * Returns:
- * The first entry in the tree greater than or equal to key,
- * or RET_SPECIAL if no such key exists.
- */
-static int
-__bt_first(t, key, erval, exactp)
- BTREE *t;
- const DBT *key;
- EPG *erval;
- int *exactp;
-{
- PAGE *h;
- EPG *ep, save;
- pgno_t pg;
-
- /*
- * Find any matching record; __bt_search pins the page.
- *
- * If it's an exact match and duplicates are possible, walk backwards
- * in the tree until we find the first one. Otherwise, make sure it's
- * a valid key (__bt_search may return an index just past the end of a
- * page) and return it.
- */
- if ((ep = __bt_search(t, key, exactp)) == NULL)
- return (RET_SPECIAL);
- if (*exactp) {
- if (F_ISSET(t, B_NODUPS)) {
- *erval = *ep;
- return (RET_SUCCESS);
- }
-
- /*
- * Walk backwards, as long as the entry matches and there are
- * keys left in the tree. Save a copy of each match in case
- * we go too far.
- */
- save = *ep;
- h = ep->page;
- do {
- if (save.page->pgno != ep->page->pgno) {
- mpool_put(t->bt_mp, save.page, 0);
- save = *ep;
- } else
- save.index = ep->index;
-
- /*
- * Don't unpin the page the last (or original) match
- * was on, but make sure it's unpinned if an error
- * occurs.
- */
- if (ep->index == 0) {
- if (h->prevpg == P_INVALID)
- break;
- if (h->pgno != save.page->pgno)
- mpool_put(t->bt_mp, h, 0);
- if ((h = mpool_get(t->bt_mp,
- h->prevpg, 0)) == NULL) {
- if (h->pgno == save.page->pgno)
- mpool_put(t->bt_mp,
- save.page, 0);
- return (RET_ERROR);
- }
- ep->page = h;
- ep->index = NEXTINDEX(h);
- }
- --ep->index;
- } while (__bt_cmp(t, key, ep) == 0);
-
- /*
- * Reach here with the last page that was looked at pinned,
- * which may or may not be the same as the last (or original)
- * match page. If it's not useful, release it.
- */
- if (h->pgno != save.page->pgno)
- mpool_put(t->bt_mp, h, 0);
-
- *erval = save;
- return (RET_SUCCESS);
- }
-
- /* If at the end of a page, find the next entry. */
- if (ep->index == NEXTINDEX(ep->page)) {
- h = ep->page;
- pg = h->nextpg;
- mpool_put(t->bt_mp, h, 0);
- if (pg == P_INVALID)
- return (RET_SPECIAL);
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
- ep->index = 0;
- ep->page = h;
- }
- *erval = *ep;
- return (RET_SUCCESS);
-}
-
-/*
- * __bt_setcur --
- * Set the cursor to an entry in the tree.
- *
- * Parameters:
- * t: the tree
- * pgno: page number
- * index: page index
- */
-void
-__bt_setcur(t, pgno, index)
- BTREE *t;
- pgno_t pgno;
- u_int index;
-{
- /* Lose any already deleted key. */
- if (t->bt_cursor.key.data != NULL) {
- free(t->bt_cursor.key.data);
- t->bt_cursor.key.size = 0;
- t->bt_cursor.key.data = NULL;
- }
- F_CLR(&t->bt_cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
-
- /* Update the cursor. */
- t->bt_cursor.pg.pgno = pgno;
- t->bt_cursor.pg.index = index;
- F_SET(&t->bt_cursor, CURS_INIT);
-}
diff --git a/main/db1-ast/btree/bt_split.c b/main/db1-ast/btree/bt_split.c
deleted file mode 100644
index 8fede1e45..000000000
--- a/main/db1-ast/btree/bt_split.c
+++ /dev/null
@@ -1,829 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_split.c 8.9 (Berkeley) 7/26/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-static int bt_broot __P((BTREE *, PAGE *, PAGE *, PAGE *));
-static PAGE *bt_page
- __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t));
-static int bt_preserve __P((BTREE *, pgno_t));
-static PAGE *bt_psplit
- __P((BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t));
-static PAGE *bt_root
- __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t));
-static int bt_rroot __P((BTREE *, PAGE *, PAGE *, PAGE *));
-static recno_t rec_total __P((PAGE *));
-
-#ifdef STATISTICS
-u_long bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved;
-#endif
-
-/*
- * __BT_SPLIT -- Split the tree.
- *
- * Parameters:
- * t: tree
- * sp: page to split
- * key: key to insert
- * data: data to insert
- * flags: BIGKEY/BIGDATA flags
- * ilen: insert length
- * skip: index to leave open
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__bt_split(t, sp, key, data, flags, ilen, argskip)
- BTREE *t;
- PAGE *sp;
- const DBT *key, *data;
- int flags;
- size_t ilen;
- u_int32_t argskip;
-{
- BINTERNAL *bi = 0;
- BLEAF *bl = 0, *tbl;
- DBT a, b;
- EPGNO *parent;
- PAGE *h, *l, *r, *lchild, *rchild;
- indx_t nxtindex;
- u_int16_t skip;
- u_int32_t n, nbytes, nksize = 0;
- int parentsplit;
- char *dest;
-
- /*
- * Split the page into two pages, l and r. The split routines return
- * a pointer to the page into which the key should be inserted and with
- * skip set to the offset which should be used. Additionally, l and r
- * are pinned.
- */
- skip = argskip;
- h = sp->pgno == P_ROOT ?
- bt_root(t, sp, &l, &r, &skip, ilen) :
- bt_page(t, sp, &l, &r, &skip, ilen);
- if (h == NULL)
- return (RET_ERROR);
-
- /*
- * Insert the new key/data pair into the leaf page. (Key inserts
- * always cause a leaf page to split first.)
- */
- h->linp[skip] = h->upper -= ilen;
- dest = (char *)h + h->upper;
- if (F_ISSET(t, R_RECNO))
- WR_RLEAF(dest, data, flags)
- else
- WR_BLEAF(dest, key, data, flags)
-
- /* If the root page was split, make it look right. */
- if (sp->pgno == P_ROOT &&
- (F_ISSET(t, R_RECNO) ?
- bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
- goto err2;
-
- /*
- * Now we walk the parent page stack -- a LIFO stack of the pages that
- * were traversed when we searched for the page that split. Each stack
- * entry is a page number and a page index offset. The offset is for
- * the page traversed on the search. We've just split a page, so we
- * have to insert a new key into the parent page.
- *
- * If the insert into the parent page causes it to split, may have to
- * continue splitting all the way up the tree. We stop if the root
- * splits or the page inserted into didn't have to split to hold the
- * new key. Some algorithms replace the key for the old page as well
- * as the new page. We don't, as there's no reason to believe that the
- * first key on the old page is any better than the key we have, and,
- * in the case of a key being placed at index 0 causing the split, the
- * key is unavailable.
- *
- * There are a maximum of 5 pages pinned at any time. We keep the left
- * and right pages pinned while working on the parent. The 5 are the
- * two children, left parent and right parent (when the parent splits)
- * and the root page or the overflow key page when calling bt_preserve.
- * This code must make sure that all pins are released other than the
- * root page or overflow page which is unlocked elsewhere.
- */
- while ((parent = BT_POP(t)) != NULL) {
- lchild = l;
- rchild = r;
-
- /* Get the parent page. */
- if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
- goto err2;
-
- /*
- * The new key goes ONE AFTER the index, because the split
- * was to the right.
- */
- skip = parent->index + 1;
-
- /*
- * Calculate the space needed on the parent page.
- *
- * Prefix trees: space hack when inserting into BINTERNAL
- * pages. Retain only what's needed to distinguish between
- * the new entry and the LAST entry on the page to its left.
- * If the keys compare equal, retain the entire key. Note,
- * we don't touch overflow keys, and the entire key must be
- * retained for the next-to-left most key on the leftmost
- * page of each level, or the search will fail. Applicable
- * ONLY to internal pages that have leaf pages as children.
- * Further reduction of the key between pairs of internal
- * pages loses too much information.
- */
- switch (rchild->flags & P_TYPE) {
- case P_BINTERNAL:
- bi = GETBINTERNAL(rchild, 0);
- nbytes = NBINTERNAL(bi->ksize);
- break;
- case P_BLEAF:
- bl = GETBLEAF(rchild, 0);
- nbytes = NBINTERNAL(bl->ksize);
- if (t->bt_pfx && !(bl->flags & P_BIGKEY) &&
- (h->prevpg != P_INVALID || skip > 1)) {
- tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1);
- a.size = tbl->ksize;
- a.data = tbl->bytes;
- b.size = bl->ksize;
- b.data = bl->bytes;
- nksize = t->bt_pfx(&a, &b);
- n = NBINTERNAL(nksize);
- if (n < nbytes) {
-#ifdef STATISTICS
- bt_pfxsaved += nbytes - n;
-#endif
- nbytes = n;
- } else
- nksize = 0;
- } else
- nksize = 0;
- break;
- case P_RINTERNAL:
- case P_RLEAF:
- nbytes = NRINTERNAL;
- break;
- default:
- abort();
- }
-
- /* Split the parent page if necessary or shift the indices. */
- if ((u_int32_t) (h->upper - h->lower)
- < nbytes + sizeof(indx_t)) {
- sp = h;
- h = h->pgno == P_ROOT ?
- bt_root(t, h, &l, &r, &skip, nbytes) :
- bt_page(t, h, &l, &r, &skip, nbytes);
- if (h == NULL)
- goto err1;
- parentsplit = 1;
- } else {
- if (skip < (nxtindex = NEXTINDEX(h)))
- memmove(h->linp + skip + 1, h->linp + skip,
- (nxtindex - skip) * sizeof(indx_t));
- h->lower += sizeof(indx_t);
- parentsplit = 0;
- }
-
- /* Insert the key into the parent page. */
- switch (rchild->flags & P_TYPE) {
- case P_BINTERNAL:
- h->linp[skip] = h->upper -= nbytes;
- dest = (char *)h + h->linp[skip];
- memmove(dest, bi, nbytes);
- ((BINTERNAL *)dest)->pgno = rchild->pgno;
- break;
- case P_BLEAF:
- h->linp[skip] = h->upper -= nbytes;
- dest = (char *)h + h->linp[skip];
- WR_BINTERNAL(dest, nksize ? nksize : bl->ksize,
- rchild->pgno, bl->flags & P_BIGKEY);
- memmove(dest, bl->bytes, nksize ? nksize : bl->ksize);
- if (bl->flags & P_BIGKEY &&
- bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
- goto err1;
- break;
- case P_RINTERNAL:
- /*
- * Update the left page count. If split
- * added at index 0, fix the correct page.
- */
- if (skip > 0)
- dest = (char *)h + h->linp[skip - 1];
- else
- dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
- ((RINTERNAL *)dest)->nrecs = rec_total(lchild);
- ((RINTERNAL *)dest)->pgno = lchild->pgno;
-
- /* Update the right page count. */
- h->linp[skip] = h->upper -= nbytes;
- dest = (char *)h + h->linp[skip];
- ((RINTERNAL *)dest)->nrecs = rec_total(rchild);
- ((RINTERNAL *)dest)->pgno = rchild->pgno;
- break;
- case P_RLEAF:
- /*
- * Update the left page count. If split
- * added at index 0, fix the correct page.
- */
- if (skip > 0)
- dest = (char *)h + h->linp[skip - 1];
- else
- dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
- ((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild);
- ((RINTERNAL *)dest)->pgno = lchild->pgno;
-
- /* Update the right page count. */
- h->linp[skip] = h->upper -= nbytes;
- dest = (char *)h + h->linp[skip];
- ((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild);
- ((RINTERNAL *)dest)->pgno = rchild->pgno;
- break;
- default:
- abort();
- }
-
- /* Unpin the held pages. */
- if (!parentsplit) {
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- break;
- }
-
- /* If the root page was split, make it look right. */
- if (sp->pgno == P_ROOT &&
- (F_ISSET(t, R_RECNO) ?
- bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
- goto err1;
-
- mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
- mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
- }
-
- /* Unpin the held pages. */
- mpool_put(t->bt_mp, l, MPOOL_DIRTY);
- mpool_put(t->bt_mp, r, MPOOL_DIRTY);
-
- /* Clear any pages left on the stack. */
- return (RET_SUCCESS);
-
- /*
- * If something fails in the above loop we were already walking back
- * up the tree and the tree is now inconsistent. Nothing much we can
- * do about it but release any memory we're holding.
- */
-err1: mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
- mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
-
-err2: mpool_put(t->bt_mp, l, 0);
- mpool_put(t->bt_mp, r, 0);
- __dbpanic(t->bt_dbp);
- return (RET_ERROR);
-}
-
-/*
- * BT_PAGE -- Split a non-root page of a btree.
- *
- * Parameters:
- * t: tree
- * h: root page
- * lp: pointer to left page pointer
- * rp: pointer to right page pointer
- * skip: pointer to index to leave open
- * ilen: insert length
- *
- * Returns:
- * Pointer to page in which to insert or NULL on error.
- */
-static PAGE *
-bt_page(t, h, lp, rp, skip, ilen)
- BTREE *t;
- PAGE *h, **lp, **rp;
- indx_t *skip;
- size_t ilen;
-{
- PAGE *l, *r, *tp;
- pgno_t npg;
-
-#ifdef STATISTICS
- ++bt_split;
-#endif
- /* Put the new right page for the split into place. */
- if ((r = __bt_new(t, &npg)) == NULL)
- return (NULL);
- r->pgno = npg;
- r->lower = BTDATAOFF;
- r->upper = t->bt_psize;
- r->nextpg = h->nextpg;
- r->prevpg = h->pgno;
- r->flags = h->flags & P_TYPE;
-
- /*
- * If we're splitting the last page on a level because we're appending
- * a key to it (skip is NEXTINDEX()), it's likely that the data is
- * sorted. Adding an empty page on the side of the level is less work
- * and can push the fill factor much higher than normal. If we're
- * wrong it's no big deal, we'll just do the split the right way next
- * time. It may look like it's equally easy to do a similar hack for
- * reverse sorted data, that is, split the tree left, but it's not.
- * Don't even try.
- */
- if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) {
-#ifdef STATISTICS
- ++bt_sortsplit;
-#endif
- h->nextpg = r->pgno;
- r->lower = BTDATAOFF + sizeof(indx_t);
- *skip = 0;
- *lp = h;
- *rp = r;
- return (r);
- }
-
- /* Put the new left page for the split into place. */
- if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) {
- mpool_put(t->bt_mp, r, 0);
- return (NULL);
- }
-#ifdef PURIFY
- memset(l, 0xff, t->bt_psize);
-#endif
- l->pgno = h->pgno;
- l->nextpg = r->pgno;
- l->prevpg = h->prevpg;
- l->lower = BTDATAOFF;
- l->upper = t->bt_psize;
- l->flags = h->flags & P_TYPE;
-
- /* Fix up the previous pointer of the page after the split page. */
- if (h->nextpg != P_INVALID) {
- if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) {
- free(l);
- /* XXX mpool_free(t->bt_mp, r->pgno); */
- return (NULL);
- }
- tp->prevpg = r->pgno;
- mpool_put(t->bt_mp, tp, MPOOL_DIRTY);
- }
-
- /*
- * Split right. The key/data pairs aren't sorted in the btree page so
- * it's simpler to copy the data from the split page onto two new pages
- * instead of copying half the data to the right page and compacting
- * the left page in place. Since the left page can't change, we have
- * to swap the original and the allocated left page after the split.
- */
- tp = bt_psplit(t, h, l, r, skip, ilen);
-
- /* Move the new left page onto the old left page. */
- memmove(h, l, t->bt_psize);
- if (tp == l)
- tp = h;
- free(l);
-
- *lp = h;
- *rp = r;
- return (tp);
-}
-
-/*
- * BT_ROOT -- Split the root page of a btree.
- *
- * Parameters:
- * t: tree
- * h: root page
- * lp: pointer to left page pointer
- * rp: pointer to right page pointer
- * skip: pointer to index to leave open
- * ilen: insert length
- *
- * Returns:
- * Pointer to page in which to insert or NULL on error.
- */
-static PAGE *
-bt_root(t, h, lp, rp, skip, ilen)
- BTREE *t;
- PAGE *h, **lp, **rp;
- indx_t *skip;
- size_t ilen;
-{
- PAGE *l, *r, *tp;
- pgno_t lnpg, rnpg;
-
-#ifdef STATISTICS
- ++bt_split;
- ++bt_rootsplit;
-#endif
- /* Put the new left and right pages for the split into place. */
- if ((l = __bt_new(t, &lnpg)) == NULL ||
- (r = __bt_new(t, &rnpg)) == NULL)
- return (NULL);
- l->pgno = lnpg;
- r->pgno = rnpg;
- l->nextpg = r->pgno;
- r->prevpg = l->pgno;
- l->prevpg = r->nextpg = P_INVALID;
- l->lower = r->lower = BTDATAOFF;
- l->upper = r->upper = t->bt_psize;
- l->flags = r->flags = h->flags & P_TYPE;
-
- /* Split the root page. */
- tp = bt_psplit(t, h, l, r, skip, ilen);
-
- *lp = l;
- *rp = r;
- return (tp);
-}
-
-/*
- * BT_RROOT -- Fix up the recno root page after it has been split.
- *
- * Parameters:
- * t: tree
- * h: root page
- * l: left page
- * r: right page
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-static int
-bt_rroot(t, h, l, r)
- BTREE *t;
- PAGE *h, *l, *r;
-{
- char *dest;
-
- /* Insert the left and right keys, set the header information. */
- h->linp[0] = h->upper = t->bt_psize - NRINTERNAL;
- dest = (char *)h + h->upper;
- WR_RINTERNAL(dest,
- l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno);
-
- h->linp[1] = h->upper -= NRINTERNAL;
- dest = (char *)h + h->upper;
- WR_RINTERNAL(dest,
- r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno);
-
- h->lower = BTDATAOFF + 2 * sizeof(indx_t);
-
- /* Unpin the root page, set to recno internal page. */
- h->flags &= ~P_TYPE;
- h->flags |= P_RINTERNAL;
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
-
- return (RET_SUCCESS);
-}
-
-/*
- * BT_BROOT -- Fix up the btree root page after it has been split.
- *
- * Parameters:
- * t: tree
- * h: root page
- * l: left page
- * r: right page
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-static int
-bt_broot(t, h, l, r)
- BTREE *t;
- PAGE *h, *l, *r;
-{
- BINTERNAL *bi;
- BLEAF *bl;
- u_int32_t nbytes;
- char *dest;
-
- /*
- * If the root page was a leaf page, change it into an internal page.
- * We copy the key we split on (but not the key's data, in the case of
- * a leaf page) to the new root page.
- *
- * The btree comparison code guarantees that the left-most key on any
- * level of the tree is never used, so it doesn't need to be filled in.
- */
- nbytes = NBINTERNAL(0);
- h->linp[0] = h->upper = t->bt_psize - nbytes;
- dest = (char *)h + h->upper;
- WR_BINTERNAL(dest, 0, l->pgno, 0);
-
- switch (h->flags & P_TYPE) {
- case P_BLEAF:
- bl = GETBLEAF(r, 0);
- nbytes = NBINTERNAL(bl->ksize);
- h->linp[1] = h->upper -= nbytes;
- dest = (char *)h + h->upper;
- WR_BINTERNAL(dest, bl->ksize, r->pgno, 0);
- memmove(dest, bl->bytes, bl->ksize);
-
- /*
- * If the key is on an overflow page, mark the overflow chain
- * so it isn't deleted when the leaf copy of the key is deleted.
- */
- if (bl->flags & P_BIGKEY &&
- bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
- return (RET_ERROR);
- break;
- case P_BINTERNAL:
- bi = GETBINTERNAL(r, 0);
- nbytes = NBINTERNAL(bi->ksize);
- h->linp[1] = h->upper -= nbytes;
- dest = (char *)h + h->upper;
- memmove(dest, bi, nbytes);
- ((BINTERNAL *)dest)->pgno = r->pgno;
- break;
- default:
- abort();
- }
-
- /* There are two keys on the page. */
- h->lower = BTDATAOFF + 2 * sizeof(indx_t);
-
- /* Unpin the root page, set to btree internal page. */
- h->flags &= ~P_TYPE;
- h->flags |= P_BINTERNAL;
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
-
- return (RET_SUCCESS);
-}
-
-/*
- * BT_PSPLIT -- Do the real work of splitting the page.
- *
- * Parameters:
- * t: tree
- * h: page to be split
- * l: page to put lower half of data
- * r: page to put upper half of data
- * pskip: pointer to index to leave open
- * ilen: insert length
- *
- * Returns:
- * Pointer to page in which to insert.
- */
-static PAGE *
-bt_psplit(t, h, l, r, pskip, ilen)
- BTREE *t;
- PAGE *h, *l, *r;
- indx_t *pskip;
- size_t ilen;
-{
- BINTERNAL *bi;
- BLEAF *bl;
- CURSOR *c;
- RLEAF *rl;
- PAGE *rval;
- void *src = 0;
- indx_t full, half, nxt, off, skip, top, used;
- u_int32_t nbytes;
- int bigkeycnt, isbigkey;
-
- /*
- * Split the data to the left and right pages. Leave the skip index
- * open. Additionally, make some effort not to split on an overflow
- * key. This makes internal page processing faster and can save
- * space as overflow keys used by internal pages are never deleted.
- */
- bigkeycnt = 0;
- skip = *pskip;
- full = t->bt_psize - BTDATAOFF;
- half = full / 2;
- used = 0;
- for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) {
- if (skip == off) {
- nbytes = ilen;
- isbigkey = 0; /* XXX: not really known. */
- } else
- switch (h->flags & P_TYPE) {
- case P_BINTERNAL:
- src = bi = GETBINTERNAL(h, nxt);
- nbytes = NBINTERNAL(bi->ksize);
- isbigkey = bi->flags & P_BIGKEY;
- break;
- case P_BLEAF:
- src = bl = GETBLEAF(h, nxt);
- nbytes = NBLEAF(bl);
- isbigkey = bl->flags & P_BIGKEY;
- break;
- case P_RINTERNAL:
- src = GETRINTERNAL(h, nxt);
- nbytes = NRINTERNAL;
- isbigkey = 0;
- break;
- case P_RLEAF:
- src = rl = GETRLEAF(h, nxt);
- nbytes = NRLEAF(rl);
- isbigkey = 0;
- break;
- default:
- abort();
- }
-
- /*
- * If the key/data pairs are substantial fractions of the max
- * possible size for the page, it's possible to get situations
- * where we decide to try and copy too much onto the left page.
- * Make sure that doesn't happen.
- */
- if ((skip <= off && used + nbytes + sizeof(indx_t) >= full)
- || nxt == top - 1) {
- --off;
- break;
- }
-
- /* Copy the key/data pair, if not the skipped index. */
- if (skip != off) {
- ++nxt;
-
- l->linp[off] = l->upper -= nbytes;
- memmove((char *)l + l->upper, src, nbytes);
- }
-
- used += nbytes + sizeof(indx_t);
- if (used >= half) {
- if (!isbigkey || bigkeycnt == 3)
- break;
- else
- ++bigkeycnt;
- }
- }
-
- /*
- * Off is the last offset that's valid for the left page.
- * Nxt is the first offset to be placed on the right page.
- */
- l->lower += (off + 1) * sizeof(indx_t);
-
- /*
- * If splitting the page that the cursor was on, the cursor has to be
- * adjusted to point to the same record as before the split. If the
- * cursor is at or past the skipped slot, the cursor is incremented by
- * one. If the cursor is on the right page, it is decremented by the
- * number of records split to the left page.
- */
- c = &t->bt_cursor;
- if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) {
- if (c->pg.index >= skip)
- ++c->pg.index;
- if (c->pg.index < nxt) /* Left page. */
- c->pg.pgno = l->pgno;
- else { /* Right page. */
- c->pg.pgno = r->pgno;
- c->pg.index -= nxt;
- }
- }
-
- /*
- * If the skipped index was on the left page, just return that page.
- * Otherwise, adjust the skip index to reflect the new position on
- * the right page.
- */
- if (skip <= off) {
- skip = 0;
- rval = l;
- } else {
- rval = r;
- *pskip -= nxt;
- }
-
- for (off = 0; nxt < top; ++off) {
- if (skip == nxt) {
- ++off;
- skip = 0;
- }
- switch (h->flags & P_TYPE) {
- case P_BINTERNAL:
- src = bi = GETBINTERNAL(h, nxt);
- nbytes = NBINTERNAL(bi->ksize);
- break;
- case P_BLEAF:
- src = bl = GETBLEAF(h, nxt);
- nbytes = NBLEAF(bl);
- break;
- case P_RINTERNAL:
- src = GETRINTERNAL(h, nxt);
- nbytes = NRINTERNAL;
- break;
- case P_RLEAF:
- src = rl = GETRLEAF(h, nxt);
- nbytes = NRLEAF(rl);
- break;
- default:
- abort();
- }
- ++nxt;
- r->linp[off] = r->upper -= nbytes;
- memmove((char *)r + r->upper, src, nbytes);
- }
- r->lower += off * sizeof(indx_t);
-
- /* If the key is being appended to the page, adjust the index. */
- if (skip == top)
- r->lower += sizeof(indx_t);
-
- return (rval);
-}
-
-/*
- * BT_PRESERVE -- Mark a chain of pages as used by an internal node.
- *
- * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the
- * record that references them gets deleted. Chains pointed to by internal
- * pages never get deleted. This routine marks a chain as pointed to by an
- * internal page.
- *
- * Parameters:
- * t: tree
- * pg: page number of first page in the chain.
- *
- * Returns:
- * RET_SUCCESS, RET_ERROR.
- */
-static int
-bt_preserve(t, pg)
- BTREE *t;
- pgno_t pg;
-{
- PAGE *h;
-
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
- h->flags |= P_PRESERVE;
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- return (RET_SUCCESS);
-}
-
-/*
- * REC_TOTAL -- Return the number of recno entries below a page.
- *
- * Parameters:
- * h: page
- *
- * Returns:
- * The number of recno entries below a page.
- *
- * XXX
- * These values could be set by the bt_psplit routine. The problem is that the
- * entry has to be popped off of the stack etc. or the values have to be passed
- * all the way back to bt_split/bt_rroot and it's not very clean.
- */
-static recno_t
-rec_total(h)
- PAGE *h;
-{
- recno_t recs;
- indx_t nxt, top;
-
- for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt)
- recs += GETRINTERNAL(h, nxt)->nrecs;
- return (recs);
-}
diff --git a/main/db1-ast/btree/bt_utils.c b/main/db1-ast/btree/bt_utils.c
deleted file mode 100644
index 2ecb5e678..000000000
--- a/main/db1-ast/btree/bt_utils.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)bt_utils.c 8.8 (Berkeley) 7/20/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "btree.h"
-
-/*
- * __bt_ret --
- * Build return key/data pair.
- *
- * Parameters:
- * t: tree
- * e: key/data pair to be returned
- * key: user's key structure (NULL if not to be filled in)
- * rkey: memory area to hold key
- * data: user's data structure (NULL if not to be filled in)
- * rdata: memory area to hold data
- * copy: always copy the key/data item
- *
- * Returns:
- * RET_SUCCESS, RET_ERROR.
- */
-int
-__bt_ret(t, e, key, rkey, data, rdata, copy)
- BTREE *t;
- EPG *e;
- DBT *key, *rkey, *data, *rdata;
- int copy;
-{
- BLEAF *bl;
- void *p;
-
- bl = GETBLEAF(e->page, e->index);
-
- /*
- * We must copy big keys/data to make them contiguous. Otherwise,
- * leave the page pinned and don't copy unless the user specified
- * concurrent access.
- */
- if (key == NULL)
- goto dataonly;
-
- if (bl->flags & P_BIGKEY) {
- if (__ovfl_get(t, bl->bytes,
- &key->size, &rkey->data, &rkey->size))
- return (RET_ERROR);
- key->data = rkey->data;
- } else if (copy || F_ISSET(t, B_DB_LOCK)) {
- if (bl->ksize > rkey->size) {
- p = (void *)(rkey->data == NULL ?
- malloc(bl->ksize) : realloc(rkey->data, bl->ksize));
- if (p == NULL)
- return (RET_ERROR);
- rkey->data = p;
- rkey->size = bl->ksize;
- }
- memmove(rkey->data, bl->bytes, bl->ksize);
- key->size = bl->ksize;
- key->data = rkey->data;
- } else {
- key->size = bl->ksize;
- key->data = bl->bytes;
- }
-
-dataonly:
- if (data == NULL)
- return (RET_SUCCESS);
-
- if (bl->flags & P_BIGDATA) {
- if (__ovfl_get(t, bl->bytes + bl->ksize,
- &data->size, &rdata->data, &rdata->size))
- return (RET_ERROR);
- data->data = rdata->data;
- } else if (copy || F_ISSET(t, B_DB_LOCK)) {
- /* Use +1 in case the first record retrieved is 0 length. */
- if (bl->dsize + 1 > rdata->size) {
- p = (void *)(rdata->data == NULL ?
- malloc(bl->dsize + 1) :
- realloc(rdata->data, bl->dsize + 1));
- if (p == NULL)
- return (RET_ERROR);
- rdata->data = p;
- rdata->size = bl->dsize + 1;
- }
- memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize);
- data->size = bl->dsize;
- data->data = rdata->data;
- } else {
- data->size = bl->dsize;
- data->data = bl->bytes + bl->ksize;
- }
-
- return (RET_SUCCESS);
-}
-
-/*
- * __BT_CMP -- Compare a key to a given record.
- *
- * Parameters:
- * t: tree
- * k1: DBT pointer of first arg to comparison
- * e: pointer to EPG for comparison
- *
- * Returns:
- * < 0 if k1 is < record
- * = 0 if k1 is = record
- * > 0 if k1 is > record
- */
-int
-__bt_cmp(t, k1, e)
- BTREE *t;
- const DBT *k1;
- EPG *e;
-{
- BINTERNAL *bi;
- BLEAF *bl;
- DBT k2;
- PAGE *h;
- void *bigkey;
-
- /*
- * The left-most key on internal pages, at any level of the tree, is
- * guaranteed by the following code to be less than any user key.
- * This saves us from having to update the leftmost key on an internal
- * page when the user inserts a new key in the tree smaller than
- * anything we've yet seen.
- */
- h = e->page;
- if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
- return (1);
-
- bigkey = NULL;
- if (h->flags & P_BLEAF) {
- bl = GETBLEAF(h, e->index);
- if (bl->flags & P_BIGKEY)
- bigkey = bl->bytes;
- else {
- k2.data = bl->bytes;
- k2.size = bl->ksize;
- }
- } else {
- bi = GETBINTERNAL(h, e->index);
- if (bi->flags & P_BIGKEY)
- bigkey = bi->bytes;
- else {
- k2.data = bi->bytes;
- k2.size = bi->ksize;
- }
- }
-
- if (bigkey) {
- if (__ovfl_get(t, bigkey,
- &k2.size, &t->bt_rdata.data, &t->bt_rdata.size))
- return (RET_ERROR);
- k2.data = t->bt_rdata.data;
- }
- return ((*t->bt_cmp)(k1, &k2));
-}
-
-/*
- * __BT_DEFCMP -- Default comparison routine.
- *
- * Parameters:
- * a: DBT #1
- * b: DBT #2
- *
- * Returns:
- * < 0 if a is < b
- * = 0 if a is = b
- * > 0 if a is > b
- */
-int
-__bt_defcmp(a, b)
- const DBT *a, *b;
-{
- register size_t len;
- register u_char *p1, *p2;
-
- /*
- * XXX
- * If a size_t doesn't fit in an int, this routine can lose.
- * What we need is a integral type which is guaranteed to be
- * larger than a size_t, and there is no such thing.
- */
- len = MIN(a->size, b->size);
- for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
- if (*p1 != *p2)
- return ((int)*p1 - (int)*p2);
- return ((int)a->size - (int)b->size);
-}
-
-/*
- * __BT_DEFPFX -- Default prefix routine.
- *
- * Parameters:
- * a: DBT #1
- * b: DBT #2
- *
- * Returns:
- * Number of bytes needed to distinguish b from a.
- */
-size_t
-__bt_defpfx(a, b)
- const DBT *a, *b;
-{
- register u_char *p1, *p2;
- register size_t cnt, len;
-
- cnt = 1;
- len = MIN(a->size, b->size);
- for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
- if (*p1 != *p2)
- return (cnt);
-
- /* a->size must be <= b->size, or they wouldn't be in this order. */
- return (a->size < b->size ? a->size + 1 : a->size);
-}
diff --git a/main/db1-ast/btree/btree.h b/main/db1-ast/btree/btree.h
deleted file mode 100644
index 1f4a9ec91..000000000
--- a/main/db1-ast/btree/btree.h
+++ /dev/null
@@ -1,391 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)btree.h 8.11 (Berkeley) 8/17/94
- */
-
-/* Macros to set/clear/test flags. */
-#define F_SET(p, f) (p)->flags |= (f)
-#define F_CLR(p, f) (p)->flags &= ~(f)
-#define F_ISSET(p, f) ((p)->flags & (f))
-
-#include <mpool.h>
-
-#define mpool_open __mpool_open
-#define mpool_filter __mpool_filter
-#define mpool_new __mpool_new
-#define mpool_get __mpool_get
-#define mpool_put __mpool_put
-#define mpool_sync __mpool_sync
-#define mpool_close __mpool_close
-
-#define DEFMINKEYPAGE (2) /* Minimum keys per page */
-#define MINCACHE (5) /* Minimum cached pages */
-#define MINPSIZE (512) /* Minimum page size */
-
-/*
- * Page 0 of a btree file contains a copy of the meta-data. This page is also
- * used as an out-of-band page, i.e. page pointers that point to nowhere point
- * to page 0. Page 1 is the root of the btree.
- */
-#define P_INVALID 0 /* Invalid tree page number. */
-#define P_META 0 /* Tree metadata page number. */
-#define P_ROOT 1 /* Tree root page number. */
-
-/*
- * There are five page layouts in the btree: btree internal pages (BINTERNAL),
- * btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages
- * (RLEAF) and overflow pages. All five page types have a page header (PAGE).
- * This implementation requires that values within structures NOT be padded.
- * (ANSI C permits random padding.) If your compiler pads randomly you'll have
- * to do some work to get this package to run.
- */
-typedef struct _page {
- pgno_t pgno; /* this page's page number */
- pgno_t prevpg; /* left sibling */
- pgno_t nextpg; /* right sibling */
-
-#define P_BINTERNAL 0x01 /* btree internal page */
-#define P_BLEAF 0x02 /* leaf page */
-#define P_OVERFLOW 0x04 /* overflow page */
-#define P_RINTERNAL 0x08 /* recno internal page */
-#define P_RLEAF 0x10 /* leaf page */
-#define P_TYPE 0x1f /* type mask */
-#define P_PRESERVE 0x20 /* never delete this chain of pages */
- u_int32_t flags;
-
- indx_t lower; /* lower bound of free space on page */
- indx_t upper; /* upper bound of free space on page */
- indx_t linp[1]; /* indx_t-aligned VAR. LENGTH DATA */
-} PAGE;
-
-/* First and next index. */
-#define BTDATAOFF \
- (sizeof(pgno_t) + sizeof(pgno_t) + sizeof(pgno_t) + \
- sizeof(u_int32_t) + sizeof(indx_t) + sizeof(indx_t))
-#define NEXTINDEX(p) (((p)->lower - BTDATAOFF) / sizeof(indx_t))
-
-/*
- * For pages other than overflow pages, there is an array of offsets into the
- * rest of the page immediately following the page header. Each offset is to
- * an item which is unique to the type of page. The h_lower offset is just
- * past the last filled-in index. The h_upper offset is the first item on the
- * page. Offsets are from the beginning of the page.
- *
- * If an item is too big to store on a single page, a flag is set and the item
- * is a { page, size } pair such that the page is the first page of an overflow
- * chain with size bytes of item. Overflow pages are simply bytes without any
- * external structure.
- *
- * The page number and size fields in the items are pgno_t-aligned so they can
- * be manipulated without copying. (This presumes that 32 bit items can be
- * manipulated on this system.)
- */
-#define LALIGN(n) (((n) + sizeof(pgno_t) - 1) & ~(sizeof(pgno_t) - 1))
-#define NOVFLSIZE (sizeof(pgno_t) + sizeof(u_int32_t))
-
-/*
- * For the btree internal pages, the item is a key. BINTERNALs are {key, pgno}
- * pairs, such that the key compares less than or equal to all of the records
- * on that page. For a tree without duplicate keys, an internal page with two
- * consecutive keys, a and b, will have all records greater than or equal to a
- * and less than b stored on the page associated with a. Duplicate keys are
- * somewhat special and can cause duplicate internal and leaf page records and
- * some minor modifications of the above rule.
- */
-typedef struct _binternal {
- u_int32_t ksize; /* key size */
- pgno_t pgno; /* page number stored on */
-#define P_BIGDATA 0x01 /* overflow data */
-#define P_BIGKEY 0x02 /* overflow key */
- u_char flags;
- char bytes[1]; /* data */
-} BINTERNAL;
-
-/* Get the page's BINTERNAL structure at index indx. */
-#define GETBINTERNAL(pg, indx) \
- ((BINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
-
-/* Get the number of bytes in the entry. */
-#define NBINTERNAL(len) \
- LALIGN(sizeof(u_int32_t) + sizeof(pgno_t) + sizeof(u_char) + (len))
-
-/* Copy a BINTERNAL entry to the page. */
-#define WR_BINTERNAL(p, size, pgno, flags) { \
- *(u_int32_t *)p = size; \
- p += sizeof(u_int32_t); \
- *(pgno_t *)p = pgno; \
- p += sizeof(pgno_t); \
- *(u_char *)p = flags; \
- p += sizeof(u_char); \
-}
-
-/*
- * For the recno internal pages, the item is a page number with the number of
- * keys found on that page and below.
- */
-typedef struct _rinternal {
- recno_t nrecs; /* number of records */
- pgno_t pgno; /* page number stored below */
-} RINTERNAL;
-
-/* Get the page's RINTERNAL structure at index indx. */
-#define GETRINTERNAL(pg, indx) \
- ((RINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
-
-/* Get the number of bytes in the entry. */
-#define NRINTERNAL \
- LALIGN(sizeof(recno_t) + sizeof(pgno_t))
-
-/* Copy a RINTERNAL entry to the page. */
-#define WR_RINTERNAL(p, nrecs, pgno) { \
- *(recno_t *)p = nrecs; \
- p += sizeof(recno_t); \
- *(pgno_t *)p = pgno; \
-}
-
-/* For the btree leaf pages, the item is a key and data pair. */
-typedef struct _bleaf {
- u_int32_t ksize; /* size of key */
- u_int32_t dsize; /* size of data */
- u_char flags; /* P_BIGDATA, P_BIGKEY */
- char bytes[1]; /* data */
-} BLEAF;
-
-/* Get the page's BLEAF structure at index indx. */
-#define GETBLEAF(pg, indx) \
- ((BLEAF *)((char *)(pg) + (pg)->linp[indx]))
-
-/* Get the number of bytes in the entry. */
-#define NBLEAF(p) NBLEAFDBT((p)->ksize, (p)->dsize)
-
-/* Get the number of bytes in the user's key/data pair. */
-#define NBLEAFDBT(ksize, dsize) \
- LALIGN(sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_char) + \
- (ksize) + (dsize))
-
-/* Copy a BLEAF entry to the page. */
-#define WR_BLEAF(p, key, data, flags) { \
- *(u_int32_t *)p = key->size; \
- p += sizeof(u_int32_t); \
- *(u_int32_t *)p = data->size; \
- p += sizeof(u_int32_t); \
- *(u_char *)p = flags; \
- p += sizeof(u_char); \
- memmove(p, key->data, key->size); \
- p += key->size; \
- memmove(p, data->data, data->size); \
-}
-
-/* For the recno leaf pages, the item is a data entry. */
-typedef struct _rleaf {
- u_int32_t dsize; /* size of data */
- u_char flags; /* P_BIGDATA */
- char bytes[1];
-} RLEAF;
-
-/* Get the page's RLEAF structure at index indx. */
-#define GETRLEAF(pg, indx) \
- ((RLEAF *)((char *)(pg) + (pg)->linp[indx]))
-
-/* Get the number of bytes in the entry. */
-#define NRLEAF(p) NRLEAFDBT((p)->dsize)
-
-/* Get the number of bytes from the user's data. */
-#define NRLEAFDBT(dsize) \
- LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize))
-
-/* Copy a RLEAF entry to the page. */
-#define WR_RLEAF(p, data, flags) { \
- *(u_int32_t *)p = data->size; \
- p += sizeof(u_int32_t); \
- *(u_char *)p = flags; \
- p += sizeof(u_char); \
- memmove(p, data->data, data->size); \
-}
-
-/*
- * A record in the tree is either a pointer to a page and an index in the page
- * or a page number and an index. These structures are used as a cursor, stack
- * entry and search returns as well as to pass records to other routines.
- *
- * One comment about searches. Internal page searches must find the largest
- * record less than key in the tree so that descents work. Leaf page searches
- * must find the smallest record greater than key so that the returned index
- * is the record's correct position for insertion.
- */
-typedef struct _epgno {
- pgno_t pgno; /* the page number */
- indx_t index; /* the index on the page */
-} EPGNO;
-
-typedef struct _epg {
- PAGE *page; /* the (pinned) page */
- indx_t index; /* the index on the page */
-} EPG;
-
-/*
- * About cursors. The cursor (and the page that contained the key/data pair
- * that it referenced) can be deleted, which makes things a bit tricky. If
- * there are no duplicates of the cursor key in the tree (i.e. B_NODUPS is set
- * or there simply aren't any duplicates of the key) we copy the key that it
- * referenced when it's deleted, and reacquire a new cursor key if the cursor
- * is used again. If there are duplicates keys, we move to the next/previous
- * key, and set a flag so that we know what happened. NOTE: if duplicate (to
- * the cursor) keys are added to the tree during this process, it is undefined
- * if they will be returned or not in a cursor scan.
- *
- * The flags determine the possible states of the cursor:
- *
- * CURS_INIT The cursor references *something*.
- * CURS_ACQUIRE The cursor was deleted, and a key has been saved so that
- * we can reacquire the right position in the tree.
- * CURS_AFTER, CURS_BEFORE
- * The cursor was deleted, and now references a key/data pair
- * that has not yet been returned, either before or after the
- * deleted key/data pair.
- * XXX
- * This structure is broken out so that we can eventually offer multiple
- * cursors as part of the DB interface.
- */
-typedef struct _cursor {
- EPGNO pg; /* B: Saved tree reference. */
- DBT key; /* B: Saved key, or key.data == NULL. */
- recno_t rcursor; /* R: recno cursor (1-based) */
-
-#define CURS_ACQUIRE 0x01 /* B: Cursor needs to be reacquired. */
-#define CURS_AFTER 0x02 /* B: Unreturned cursor after key. */
-#define CURS_BEFORE 0x04 /* B: Unreturned cursor before key. */
-#define CURS_INIT 0x08 /* RB: Cursor initialized. */
- u_int8_t flags;
-} CURSOR;
-
-/*
- * The metadata of the tree. The nrecs field is used only by the RECNO code.
- * This is because the btree doesn't really need it and it requires that every
- * put or delete call modify the metadata.
- */
-typedef struct _btmeta {
- u_int32_t magic; /* magic number */
- u_int32_t version; /* version */
- u_int32_t psize; /* page size */
- u_int32_t free; /* page number of first free page */
- u_int32_t nrecs; /* R: number of records */
-
-#define SAVEMETA (B_NODUPS | R_RECNO)
- u_int32_t flags; /* bt_flags & SAVEMETA */
-} BTMETA;
-
-/* The in-memory btree/recno data structure. */
-typedef struct _btree {
- MPOOL *bt_mp; /* memory pool cookie */
-
- DB *bt_dbp; /* pointer to enclosing DB */
-
- EPG bt_cur; /* current (pinned) page */
- PAGE *bt_pinned; /* page pinned across calls */
-
- CURSOR bt_cursor; /* cursor */
-
-#define BT_PUSH(t, p, i) { \
- t->bt_sp->pgno = p; \
- t->bt_sp->index = i; \
- ++t->bt_sp; \
-}
-#define BT_POP(t) (t->bt_sp == t->bt_stack ? NULL : --t->bt_sp)
-#define BT_CLR(t) (t->bt_sp = t->bt_stack)
- EPGNO bt_stack[50]; /* stack of parent pages */
- EPGNO *bt_sp; /* current stack pointer */
-
- DBT bt_rkey; /* returned key */
- DBT bt_rdata; /* returned data */
-
- int bt_fd; /* tree file descriptor */
-
- pgno_t bt_free; /* next free page */
- u_int32_t bt_psize; /* page size */
- indx_t bt_ovflsize; /* cut-off for key/data overflow */
- int bt_lorder; /* byte order */
- /* sorted order */
- enum { NOT, BACK, FORWARD } bt_order;
- EPGNO bt_last; /* last insert */
-
- /* B: key comparison function */
- int (*bt_cmp) __P((const DBT *, const DBT *));
- /* B: prefix comparison function */
- size_t (*bt_pfx) __P((const DBT *, const DBT *));
- /* R: recno input function */
- int (*bt_irec) __P((struct _btree *, recno_t));
-
- FILE *bt_rfp; /* R: record FILE pointer */
- int bt_rfd; /* R: record file descriptor */
-
- caddr_t bt_cmap; /* R: current point in mapped space */
- caddr_t bt_smap; /* R: start of mapped space */
- caddr_t bt_emap; /* R: end of mapped space */
- size_t bt_msize; /* R: size of mapped region. */
-
- recno_t bt_nrecs; /* R: number of records */
- size_t bt_reclen; /* R: fixed record length */
- u_char bt_bval; /* R: delimiting byte/pad character */
-
-/*
- * NB:
- * B_NODUPS and R_RECNO are stored on disk, and may not be changed.
- */
-#define B_INMEM 0x00001 /* in-memory tree */
-#define B_METADIRTY 0x00002 /* need to write metadata */
-#define B_MODIFIED 0x00004 /* tree modified */
-#define B_NEEDSWAP 0x00008 /* if byte order requires swapping */
-#define B_RDONLY 0x00010 /* read-only tree */
-
-#define B_NODUPS 0x00020 /* no duplicate keys permitted */
-#define R_RECNO 0x00080 /* record oriented tree */
-
-#define R_CLOSEFP 0x00040 /* opened a file pointer */
-#define R_EOF 0x00100 /* end of input file reached. */
-#define R_FIXLEN 0x00200 /* fixed length records */
-#define R_MEMMAPPED 0x00400 /* memory mapped file. */
-#define R_INMEM 0x00800 /* in-memory file */
-#define R_MODIFIED 0x01000 /* modified file */
-#define R_RDONLY 0x02000 /* read-only file */
-
-#define B_DB_LOCK 0x04000 /* DB_LOCK specified. */
-#define B_DB_SHMEM 0x08000 /* DB_SHMEM specified. */
-#define B_DB_TXN 0x10000 /* DB_TXN specified. */
- u_int32_t flags;
-} BTREE;
-
-#include "extern.h"
diff --git a/main/db1-ast/btree/extern.h b/main/db1-ast/btree/extern.h
deleted file mode 100644
index ebd9c5492..000000000
--- a/main/db1-ast/btree/extern.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)extern.h 8.10 (Berkeley) 7/20/94
- */
-
-int __bt_close __P((DB *));
-int __bt_cmp __P((BTREE *, const DBT *, EPG *));
-int __bt_crsrdel __P((BTREE *, EPGNO *));
-int __bt_defcmp __P((const DBT *, const DBT *));
-size_t __bt_defpfx __P((const DBT *, const DBT *));
-int __bt_delete __P((const DB *, const DBT *, u_int));
-int __bt_dleaf __P((BTREE *, const DBT *, PAGE *, u_int));
-int __bt_fd __P((const DB *));
-int __bt_free __P((BTREE *, PAGE *));
-int __bt_get __P((const DB *, const DBT *, DBT *, u_int));
-PAGE *__bt_new __P((BTREE *, pgno_t *));
-void __bt_pgin __P((void *, pgno_t, void *));
-void __bt_pgout __P((void *, pgno_t, void *));
-int __bt_push __P((BTREE *, pgno_t, int));
-int __bt_put __P((const DB *dbp, DBT *, const DBT *, u_int));
-int __bt_ret __P((BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int));
-EPG *__bt_search __P((BTREE *, const DBT *, int *));
-int __bt_seq __P((const DB *, DBT *, DBT *, u_int));
-void __bt_setcur __P((BTREE *, pgno_t, u_int));
-int __bt_split __P((BTREE *, PAGE *,
- const DBT *, const DBT *, int, size_t, u_int32_t));
-int __bt_sync __P((const DB *, u_int));
-
-int __ovfl_delete __P((BTREE *, void *));
-int __ovfl_get __P((BTREE *, void *, size_t *, void **, size_t *));
-int __ovfl_put __P((BTREE *, const DBT *, pgno_t *));
-
-#ifdef DEBUG
-void __bt_dnpage __P((DB *, pgno_t));
-void __bt_dpage __P((PAGE *));
-void __bt_dump __P((DB *));
-#endif
-#ifdef STATISTICS
-void __bt_stat __P((DB *));
-#endif
diff --git a/main/db1-ast/db/db.c b/main/db1-ast/db/db.c
deleted file mode 100644
index 8c0584d4c..000000000
--- a/main/db1-ast/db/db.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)db.c 8.4 (Berkeley) 2/21/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-
-#include "../include/db.h"
-
-DB *
-dbopen(fname, flags, mode, type, openinfo)
- const char *fname;
- int flags, mode;
- DBTYPE type;
- const void *openinfo;
-{
-
-#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN)
-#define USE_OPEN_FLAGS \
- (O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY | \
- O_RDWR | O_SHLOCK | O_TRUNC)
-
- if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
- switch (type) {
- case DB_BTREE:
- return (__bt_open(fname, flags & USE_OPEN_FLAGS,
- mode, openinfo, flags & DB_FLAGS));
- case DB_HASH:
- return (__hash_open(fname, flags & USE_OPEN_FLAGS,
- mode, openinfo, flags & DB_FLAGS));
- case DB_RECNO:
- return (__rec_open(fname, flags & USE_OPEN_FLAGS,
- mode, openinfo, flags & DB_FLAGS));
- }
- errno = EINVAL;
- return (NULL);
-}
-
-static int
-__dberr __P((void))
-{
- return (RET_ERROR);
-}
-
-/*
- * __DBPANIC -- Stop.
- *
- * Parameters:
- * dbp: pointer to the DB structure.
- */
-void
-__dbpanic(dbp)
- DB *dbp;
-{
- /* The only thing that can succeed is a close. */
- dbp->del = (int (*)__P((const struct __db *,
- const DBT *, u_int))) __dberr;
- dbp->get = (int (*)__P((const struct __db *,
- const DBT *, DBT *, u_int))) __dberr;
- dbp->put = (int (*)__P((const struct __db *,
- DBT *, const DBT *, u_int))) __dberr;
- dbp->seq = (int (*)__P((const struct __db *,
- DBT *, DBT *, u_int))) __dberr;
- dbp->sync = (int (*)__P((const struct __db *, u_int))) __dberr;
- dbp->fd = (int (*)__P((const struct __db *))) __dberr;
-}
diff --git a/main/db1-ast/hash/README b/main/db1-ast/hash/README
deleted file mode 100644
index f29ccf7e1..000000000
--- a/main/db1-ast/hash/README
+++ /dev/null
@@ -1,72 +0,0 @@
-# @(#)README 8.1 (Berkeley) 6/4/93
-
-This package implements a superset of the hsearch and dbm/ndbm libraries.
-
-Test Programs:
- All test programs which need key/data pairs expect them entered
- with key and data on separate lines
-
- tcreat3.c
- Takes
- bucketsize (bsize),
- fill factor (ffactor), and
- initial number of elements (nelem).
- Creates a hash table named hashtest containing the
- keys/data pairs entered from standard in.
- thash4.c
- Takes
- bucketsize (bsize),
- fill factor (ffactor),
- initial number of elements (nelem)
- bytes of cache (ncached), and
- file from which to read data (fname)
- Creates a table from the key/data pairs on standard in and
- then does a read of each key/data in fname
- tdel.c
- Takes
- bucketsize (bsize), and
- fill factor (ffactor).
- file from which to read data (fname)
- Reads each key/data pair from fname and deletes the
- key from the hash table hashtest
- tseq.c
- Reads the key/data pairs in the file hashtest and writes them
- to standard out.
- tread2.c
- Takes
- butes of cache (ncached).
- Reads key/data pairs from standard in and looks them up
- in the file hashtest.
- tverify.c
- Reads key/data pairs from standard in, looks them up
- in the file hashtest, and verifies that the data is
- correct.
-
-NOTES:
-
-The file search.h is provided for using the hsearch compatible interface
-on BSD systems. On System V derived systems, search.h should appear in
-/usr/include.
-
-The man page ../man/db.3 explains the interface to the hashing system.
-The file hash.ps is a postscript copy of a paper explaining
-the history, implementation, and performance of the hash package.
-
-"bugs" or idiosyncracies
-
-If you have a lot of overflows, it is possible to run out of overflow
-pages. Currently, this will cause a message to be printed on stderr.
-Eventually, this will be indicated by a return error code.
-
-If you are using the ndbm interface and exit without flushing or closing the
-file, you may lose updates since the package buffers all writes. Also,
-the db interface only creates a single database file. To avoid overwriting
-the user's original file, the suffix ".db" is appended to the file name
-passed to dbm_open. Additionally, if your code "knows" about the historic
-.dir and .pag files, it will break.
-
-There is a fundamental difference between this package and the old hsearch.
-Hsearch requires the user to maintain the keys and data in the application's
-allocated memory while hash takes care of all storage management. The down
-side is that the byte strings passed in the ENTRY structure must be null
-terminated (both the keys and the data).
diff --git a/main/db1-ast/hash/extern.h b/main/db1-ast/hash/extern.h
deleted file mode 100644
index 4f1f23d67..000000000
--- a/main/db1-ast/hash/extern.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)extern.h 8.4 (Berkeley) 6/16/94
- */
-
-BUFHEAD *__add_ovflpage __P((HTAB *, BUFHEAD *));
-int __addel __P((HTAB *, BUFHEAD *, const DBT *, const DBT *));
-int __big_delete __P((HTAB *, BUFHEAD *));
-int __big_insert __P((HTAB *, BUFHEAD *, const DBT *, const DBT *));
-int __big_keydata __P((HTAB *, BUFHEAD *, DBT *, DBT *, int));
-int __big_return __P((HTAB *, BUFHEAD *, int, DBT *, int));
-int __big_split __P((HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *,
- int, u_int32_t, SPLIT_RETURN *));
-int __buf_free __P((HTAB *, int, int));
-void __buf_init __P((HTAB *, int));
-u_int32_t __call_hash __P((HTAB *, char *, int));
-int __delpair __P((HTAB *, BUFHEAD *, int));
-int __expand_table __P((HTAB *));
-int __find_bigpair __P((HTAB *, BUFHEAD *, int, char *, int));
-u_int16_t __find_last_page __P((HTAB *, BUFHEAD **));
-void __free_ovflpage __P((HTAB *, BUFHEAD *));
-BUFHEAD *__get_buf __P((HTAB *, u_int32_t, BUFHEAD *, int));
-int __get_page __P((HTAB *, char *, u_int32_t, int, int, int));
-int __ibitmap __P((HTAB *, int, int, int));
-u_int32_t __hash_log2 __P((u_int32_t));
-int __put_page __P((HTAB *, char *, u_int32_t, int, int));
-void __reclaim_buf __P((HTAB *, BUFHEAD *));
-int __split_page __P((HTAB *, u_int32_t, u_int32_t));
-
-/* Default hash routine. */
-extern u_int32_t (*__default_hash) __P((const void *, size_t));
-
-#ifdef HASH_STATISTICS
-extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
-#endif
diff --git a/main/db1-ast/hash/hash.c b/main/db1-ast/hash/hash.c
deleted file mode 100644
index 47dc52a0e..000000000
--- a/main/db1-ast/hash/hash.c
+++ /dev/null
@@ -1,999 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#ifdef DEBUG
-#include <assert.h>
-#endif
-
-#include "../include/db.h"
-#include "hash.h"
-#include "page.h"
-#include "extern.h"
-
-static int alloc_segs __P((HTAB *, int));
-static int flush_meta __P((HTAB *));
-static int hash_access __P((HTAB *, ACTION, DBT *, DBT *));
-static int hash_close __P((DB *));
-static int hash_delete __P((const DB *, const DBT *, u_int32_t));
-static int hash_fd __P((const DB *));
-static int hash_get __P((const DB *, const DBT *, DBT *, u_int32_t));
-static int hash_put __P((const DB *, DBT *, const DBT *, u_int32_t));
-static void *hash_realloc __P((SEGMENT **, int, int));
-static int hash_seq __P((const DB *, DBT *, DBT *, u_int32_t));
-static int hash_sync __P((const DB *, u_int32_t));
-static int hdestroy __P((HTAB *));
-static HTAB *init_hash __P((HTAB *, const char *, const HASHINFO *));
-static int init_htab __P((HTAB *, int));
-#if BYTE_ORDER == LITTLE_ENDIAN
-static void swap_header __P((HTAB *));
-static void swap_header_copy __P((HASHHDR *, HASHHDR *));
-#endif
-
-/* Fast arithmetic, relying on powers of 2, */
-#define MOD(x, y) ((x) & ((y) - 1))
-
-#define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; }
-
-/* Return values */
-#define SUCCESS (0)
-#define ERROR (-1)
-#define ABNORMAL (1)
-
-#ifdef HASH_STATISTICS
-int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
-#endif
-
-/************************** INTERFACE ROUTINES ***************************/
-/* OPEN/CLOSE */
-
-extern DB *
-__hash_open(file, flags, mode, info, dflags)
- const char *file;
- int flags, mode, dflags;
- const HASHINFO *info; /* Special directives for create */
-{
- HTAB *hashp;
- struct stat statbuf;
- DB *dbp;
- int bpages, hdrsize, new_table, nsegs, save_errno;
-
- if ((flags & O_ACCMODE) == O_WRONLY) {
- errno = EINVAL;
- return (NULL);
- }
-
- if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
- return (NULL);
- hashp->fp = -1;
-
- /*
- * Even if user wants write only, we need to be able to read
- * the actual file, so we need to open it read/write. But, the
- * field in the hashp structure needs to be accurate so that
- * we can check accesses.
- */
- hashp->flags = flags;
-
- new_table = 0;
- if (!file || (flags & O_TRUNC) ||
- (stat(file, &statbuf) && (errno == ENOENT))) {
- if (errno == ENOENT)
- errno = 0; /* Just in case someone looks at errno */
- new_table = 1;
- }
- if (file) {
- if ((hashp->fp = open(file, flags, mode)) == -1)
- RETURN_ERROR(errno, error0);
- (void)fcntl(hashp->fp, F_SETFD, 1);
- }
- if (new_table) {
- if (!(hashp = init_hash(hashp, file, info)))
- RETURN_ERROR(errno, error1);
- } else {
- /* Table already exists */
- if (info && info->hash)
- hashp->hash = info->hash;
- else
- hashp->hash = __default_hash;
-
- hdrsize = read(hashp->fp, &hashp->hdr, sizeof(HASHHDR));
-#if BYTE_ORDER == LITTLE_ENDIAN
- swap_header(hashp);
-#endif
- if (hdrsize == -1)
- RETURN_ERROR(errno, error1);
- if (hdrsize != sizeof(HASHHDR))
- RETURN_ERROR(EFTYPE, error1);
- /* Verify file type, versions and hash function */
- if (hashp->MAGIC != HASHMAGIC)
- RETURN_ERROR(EFTYPE, error1);
-#define OLDHASHVERSION 1
- if (hashp->VERSION != HASHVERSION &&
- hashp->VERSION != OLDHASHVERSION)
- RETURN_ERROR(EFTYPE, error1);
- if (hashp->hash(CHARKEY, sizeof(CHARKEY))
- != (u_int32_t) hashp->H_CHARKEY)
- RETURN_ERROR(EFTYPE, error1);
- /*
- * Figure out how many segments we need. Max_Bucket is the
- * maximum bucket number, so the number of buckets is
- * max_bucket + 1.
- */
- nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
- hashp->SGSIZE;
- hashp->nsegs = 0;
- if (alloc_segs(hashp, nsegs))
- /*
- * If alloc_segs fails, table will have been destroyed
- * and errno will have been set.
- */
- return (NULL);
- /* Read in bitmaps */
- bpages = (hashp->SPARES[hashp->OVFL_POINT] +
- (hashp->BSIZE << BYTE_SHIFT) - 1) >>
- (hashp->BSHIFT + BYTE_SHIFT);
-
- hashp->nmaps = bpages;
- (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *));
- }
-
- /* Initialize Buffer Manager */
- if (info && info->cachesize)
- __buf_init(hashp, info->cachesize);
- else
- __buf_init(hashp, DEF_BUFSIZE);
-
- hashp->new_file = new_table;
- hashp->save_file = file && (hashp->flags & O_ACCMODE) != O_RDONLY;
- hashp->cbucket = -1;
- if (!(dbp = (DB *)malloc(sizeof(DB)))) {
- save_errno = errno;
- hdestroy(hashp);
- errno = save_errno;
- return (NULL);
- }
- dbp->internal = hashp;
- dbp->close = hash_close;
- dbp->del = hash_delete;
- dbp->fd = hash_fd;
- dbp->get = hash_get;
- dbp->put = hash_put;
- dbp->seq = hash_seq;
- dbp->sync = hash_sync;
- dbp->type = DB_HASH;
-
-#ifdef DEBUG
- (void)fprintf(stderr,
-"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
- "init_htab:",
- "TABLE POINTER ", hashp,
- "BUCKET SIZE ", hashp->BSIZE,
- "BUCKET SHIFT ", hashp->BSHIFT,
- "DIRECTORY SIZE ", hashp->DSIZE,
- "SEGMENT SIZE ", hashp->SGSIZE,
- "SEGMENT SHIFT ", hashp->SSHIFT,
- "FILL FACTOR ", hashp->FFACTOR,
- "MAX BUCKET ", hashp->MAX_BUCKET,
- "OVFL POINT ", hashp->OVFL_POINT,
- "LAST FREED ", hashp->LAST_FREED,
- "HIGH MASK ", hashp->HIGH_MASK,
- "LOW MASK ", hashp->LOW_MASK,
- "NSEGS ", hashp->nsegs,
- "NKEYS ", hashp->NKEYS);
-#endif
-#ifdef HASH_STATISTICS
- hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
-#endif
- return (dbp);
-
-error1:
- if (hashp != NULL)
- (void)close(hashp->fp);
-
-error0:
- free(hashp);
- errno = save_errno;
- return (NULL);
-}
-
-static int
-hash_close(dbp)
- DB *dbp;
-{
- HTAB *hashp;
- int retval;
-
- if (!dbp)
- return (ERROR);
-
- hashp = (HTAB *)dbp->internal;
- retval = hdestroy(hashp);
- free(dbp);
- return (retval);
-}
-
-static int
-hash_fd(dbp)
- const DB *dbp;
-{
- HTAB *hashp;
-
- if (!dbp)
- return (ERROR);
-
- hashp = (HTAB *)dbp->internal;
- if (hashp->fp == -1) {
- errno = ENOENT;
- return (-1);
- }
- return (hashp->fp);
-}
-
-/************************** LOCAL CREATION ROUTINES **********************/
-static HTAB *
-init_hash(hashp, file, info)
- HTAB *hashp;
- const char *file;
- const HASHINFO *info;
-{
-#ifdef _STATBUF_ST_BLKSIZE
- struct stat statbuf;
-#endif
- int nelem;
-
- nelem = 1;
- hashp->NKEYS = 0;
- hashp->LORDER = BYTE_ORDER;
- hashp->BSIZE = DEF_BUCKET_SIZE;
- hashp->BSHIFT = DEF_BUCKET_SHIFT;
- hashp->SGSIZE = DEF_SEGSIZE;
- hashp->SSHIFT = DEF_SEGSIZE_SHIFT;
- hashp->DSIZE = DEF_DIRSIZE;
- hashp->FFACTOR = DEF_FFACTOR;
- hashp->hash = __default_hash;
- memset(hashp->SPARES, 0, sizeof(hashp->SPARES));
- memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS));
-
- /* Fix bucket size to be optimal for file system */
-#ifdef _STATBUF_ST_BLKSIZE
- if (file != NULL) {
- if (stat(file, &statbuf))
- return (NULL);
- hashp->BSIZE = statbuf.st_blksize;
- hashp->BSHIFT = __hash_log2(hashp->BSIZE);
- }
-#endif
-
- if (info) {
- if (info->bsize) {
- /* Round pagesize up to power of 2 */
- hashp->BSHIFT = __hash_log2(info->bsize);
- hashp->BSIZE = 1 << hashp->BSHIFT;
- if (hashp->BSIZE > MAX_BSIZE) {
- errno = EINVAL;
- return (NULL);
- }
- }
- if (info->ffactor)
- hashp->FFACTOR = info->ffactor;
- if (info->hash)
- hashp->hash = info->hash;
- if (info->nelem)
- nelem = info->nelem;
- if (info->lorder) {
- if (info->lorder != BIG_ENDIAN &&
- info->lorder != LITTLE_ENDIAN) {
- errno = EINVAL;
- return (NULL);
- }
- hashp->LORDER = info->lorder;
- }
- }
- /* init_htab should destroy the table and set errno if it fails */
- if (init_htab(hashp, nelem))
- return (NULL);
- else
- return (hashp);
-}
-/*
- * This calls alloc_segs which may run out of memory. Alloc_segs will destroy
- * the table and set errno, so we just pass the error information along.
- *
- * Returns 0 on No Error
- */
-static int
-init_htab(hashp, nelem)
- HTAB *hashp;
- int nelem;
-{
- register int nbuckets, nsegs;
- int l2;
-
- /*
- * Divide number of elements by the fill factor and determine a
- * desired number of buckets. Allocate space for the next greater
- * power of two number of buckets.
- */
- nelem = (nelem - 1) / hashp->FFACTOR + 1;
-
- l2 = __hash_log2(MAX(nelem, 2));
- nbuckets = 1 << l2;
-
- hashp->SPARES[l2] = l2 + 1;
- hashp->SPARES[l2 + 1] = l2 + 1;
- hashp->OVFL_POINT = l2;
- hashp->LAST_FREED = 2;
-
- /* First bitmap page is at: splitpoint l2 page offset 1 */
- if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0))
- return (-1);
-
- hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1;
- hashp->HIGH_MASK = (nbuckets << 1) - 1;
- hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >>
- hashp->BSHIFT) + 1;
-
- nsegs = (nbuckets - 1) / hashp->SGSIZE + 1;
- nsegs = 1 << __hash_log2(nsegs);
-
- if (nsegs > hashp->DSIZE)
- hashp->DSIZE = nsegs;
- return (alloc_segs(hashp, nsegs));
-}
-
-/********************** DESTROY/CLOSE ROUTINES ************************/
-
-/*
- * Flushes any changes to the file if necessary and destroys the hashp
- * structure, freeing all allocated space.
- */
-static int
-hdestroy(hashp)
- HTAB *hashp;
-{
- int i, save_errno;
-
- save_errno = 0;
-
-#ifdef HASH_STATISTICS
- (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n",
- hash_accesses, hash_collisions);
- (void)fprintf(stderr, "hdestroy: expansions %ld\n",
- hash_expansions);
- (void)fprintf(stderr, "hdestroy: overflows %ld\n",
- hash_overflows);
- (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n",
- hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs);
-
- for (i = 0; i < NCACHED; i++)
- (void)fprintf(stderr,
- "spares[%d] = %d\n", i, hashp->SPARES[i]);
-#endif
- /*
- * Call on buffer manager to free buffers, and if required,
- * write them to disk.
- */
- if (__buf_free(hashp, 1, hashp->save_file))
- save_errno = errno;
- if (hashp->dir) {
- free(*hashp->dir); /* Free initial segments */
- /* Free extra segments */
- while (hashp->exsegs--)
- free(hashp->dir[--hashp->nsegs]);
- free(hashp->dir);
- }
- if (flush_meta(hashp) && !save_errno)
- save_errno = errno;
- /* Free Bigmaps */
- for (i = 0; i < hashp->nmaps; i++)
- if (hashp->mapp[i])
- free(hashp->mapp[i]);
-
- if (hashp->fp != -1)
- (void)close(hashp->fp);
-
- free(hashp);
-
- if (save_errno) {
- errno = save_errno;
- return (ERROR);
- }
- return (SUCCESS);
-}
-/*
- * Write modified pages to disk
- *
- * Returns:
- * 0 == OK
- * -1 ERROR
- */
-static int
-hash_sync(dbp, flags)
- const DB *dbp;
- u_int32_t flags;
-{
- HTAB *hashp;
-
- if (flags != 0) {
- errno = EINVAL;
- return (ERROR);
- }
-
- if (!dbp)
- return (ERROR);
-
- hashp = (HTAB *)dbp->internal;
- if (!hashp->save_file)
- return (0);
- if (__buf_free(hashp, 0, 1) || flush_meta(hashp))
- return (ERROR);
- hashp->new_file = 0;
- return (0);
-}
-
-/*
- * Returns:
- * 0 == OK
- * -1 indicates that errno should be set
- */
-static int
-flush_meta(hashp)
- HTAB *hashp;
-{
- HASHHDR *whdrp;
-#if BYTE_ORDER == LITTLE_ENDIAN
- HASHHDR whdr;
-#endif
- int fp, i, wsize;
-
- if (!hashp->save_file)
- return (0);
- hashp->MAGIC = HASHMAGIC;
- hashp->VERSION = HASHVERSION;
- hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY));
-
- fp = hashp->fp;
- whdrp = &hashp->hdr;
-#if BYTE_ORDER == LITTLE_ENDIAN
- whdrp = &whdr;
- swap_header_copy(&hashp->hdr, whdrp);
-#endif
- if ((lseek(fp, (off_t)0, SEEK_SET) == -1) ||
- ((wsize = write(fp, whdrp, sizeof(HASHHDR))) == -1))
- return (-1);
- else
- if (wsize != sizeof(HASHHDR)) {
- errno = EFTYPE;
- hashp->errnum = errno;
- return (-1);
- }
- for (i = 0; i < NCACHED; i++)
- if (hashp->mapp[i])
- if (__put_page(hashp, (char *)hashp->mapp[i],
- hashp->BITMAPS[i], 0, 1))
- return (-1);
- return (0);
-}
-
-/*******************************SEARCH ROUTINES *****************************/
-/*
- * All the access routines return
- *
- * Returns:
- * 0 on SUCCESS
- * 1 to indicate an external ERROR (i.e. key not found, etc)
- * -1 to indicate an internal ERROR (i.e. out of memory, etc)
- */
-static int
-hash_get(dbp, key, data, flag)
- const DB *dbp;
- const DBT *key;
- DBT *data;
- u_int32_t flag;
-{
- HTAB *hashp;
-
- hashp = (HTAB *)dbp->internal;
- if (flag) {
- hashp->errnum = errno = EINVAL;
- return (ERROR);
- }
- return (hash_access(hashp, HASH_GET, (DBT *)key, data));
-}
-
-static int
-hash_put(dbp, key, data, flag)
- const DB *dbp;
- DBT *key;
- const DBT *data;
- u_int32_t flag;
-{
- HTAB *hashp;
-
- hashp = (HTAB *)dbp->internal;
- if (flag && flag != R_NOOVERWRITE) {
- hashp->errnum = errno = EINVAL;
- return (ERROR);
- }
- if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
- hashp->errnum = errno = EPERM;
- return (ERROR);
- }
- return (hash_access(hashp, flag == R_NOOVERWRITE ?
- HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data));
-}
-
-static int
-hash_delete(dbp, key, flag)
- const DB *dbp;
- const DBT *key;
- u_int32_t flag; /* Ignored */
-{
- HTAB *hashp;
-
- hashp = (HTAB *)dbp->internal;
- if (flag && flag != R_CURSOR) {
- hashp->errnum = errno = EINVAL;
- return (ERROR);
- }
- if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
- hashp->errnum = errno = EPERM;
- return (ERROR);
- }
- return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
-}
-
-/*
- * Assume that hashp has been set in wrapper routine.
- */
-static int
-hash_access(hashp, action, key, val)
- HTAB *hashp;
- ACTION action;
- DBT *key, *val;
-{
- register BUFHEAD *rbufp;
- BUFHEAD *bufp, *save_bufp;
- register u_int16_t *bp;
- register int n, ndx, off, size;
- register char *kp;
- u_int16_t pageno;
-
-#ifdef HASH_STATISTICS
- hash_accesses++;
-#endif
-
- off = hashp->BSIZE;
- size = key->size;
- kp = (char *)key->data;
- rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0);
- if (!rbufp)
- return (ERROR);
- save_bufp = rbufp;
-
- /* Pin the bucket chain */
- rbufp->flags |= BUF_PIN;
- for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;)
- if (bp[1] >= REAL_KEY) {
- /* Real key/data pair */
- if (size == off - *bp &&
- memcmp(kp, rbufp->page + *bp, size) == 0)
- goto found;
- off = bp[1];
-#ifdef HASH_STATISTICS
- hash_collisions++;
-#endif
- bp += 2;
- ndx += 2;
- } else if (bp[1] == OVFLPAGE) {
- rbufp = __get_buf(hashp, *bp, rbufp, 0);
- if (!rbufp) {
- save_bufp->flags &= ~BUF_PIN;
- return (ERROR);
- }
- /* FOR LOOP INIT */
- bp = (u_int16_t *)rbufp->page;
- n = *bp++;
- ndx = 1;
- off = hashp->BSIZE;
- } else if (bp[1] < REAL_KEY) {
- if ((ndx =
- __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0)
- goto found;
- if (ndx == -2) {
- bufp = rbufp;
- if (!(pageno =
- __find_last_page(hashp, &bufp))) {
- ndx = 0;
- rbufp = bufp;
- break; /* FOR */
- }
- rbufp = __get_buf(hashp, pageno, bufp, 0);
- if (!rbufp) {
- save_bufp->flags &= ~BUF_PIN;
- return (ERROR);
- }
- /* FOR LOOP INIT */
- bp = (u_int16_t *)rbufp->page;
- n = *bp++;
- ndx = 1;
- off = hashp->BSIZE;
- } else {
- save_bufp->flags &= ~BUF_PIN;
- return (ERROR);
- }
- }
-
- /* Not found */
- switch (action) {
- case HASH_PUT:
- case HASH_PUTNEW:
- if (__addel(hashp, rbufp, key, val)) {
- save_bufp->flags &= ~BUF_PIN;
- return (ERROR);
- } else {
- save_bufp->flags &= ~BUF_PIN;
- return (SUCCESS);
- }
- case HASH_GET:
- case HASH_DELETE:
- default:
- save_bufp->flags &= ~BUF_PIN;
- return (ABNORMAL);
- }
-
-found:
- switch (action) {
- case HASH_PUTNEW:
- save_bufp->flags &= ~BUF_PIN;
- return (ABNORMAL);
- case HASH_GET:
- bp = (u_int16_t *)rbufp->page;
- if (bp[ndx + 1] < REAL_KEY) {
- if (__big_return(hashp, rbufp, ndx, val, 0))
- return (ERROR);
- } else {
- val->data = (u_char *)rbufp->page + (int)bp[ndx + 1];
- val->size = bp[ndx] - bp[ndx + 1];
- }
- break;
- case HASH_PUT:
- if ((__delpair(hashp, rbufp, ndx)) ||
- (__addel(hashp, rbufp, key, val))) {
- save_bufp->flags &= ~BUF_PIN;
- return (ERROR);
- }
- break;
- case HASH_DELETE:
- if (__delpair(hashp, rbufp, ndx))
- return (ERROR);
- break;
- default:
- abort();
- }
- save_bufp->flags &= ~BUF_PIN;
- return (SUCCESS);
-}
-
-static int
-hash_seq(dbp, key, data, flag)
- const DB *dbp;
- DBT *key, *data;
- u_int32_t flag;
-{
- register u_int32_t bucket;
- register BUFHEAD *bufp = NULL;
- HTAB *hashp;
- u_int16_t *bp, ndx;
-
- hashp = (HTAB *)dbp->internal;
- if (flag && flag != R_FIRST && flag != R_NEXT) {
- hashp->errnum = errno = EINVAL;
- return (ERROR);
- }
-#ifdef HASH_STATISTICS
- hash_accesses++;
-#endif
- if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
- hashp->cbucket = 0;
- hashp->cndx = 1;
- hashp->cpage = NULL;
- }
-
- for (bp = NULL; !bp || !bp[0]; ) {
- if (!(bufp = hashp->cpage)) {
- for (bucket = hashp->cbucket;
- bucket <= (u_int32_t) hashp->MAX_BUCKET;
- bucket++, hashp->cndx = 1) {
- bufp = __get_buf(hashp, bucket, NULL, 0);
- if (!bufp)
- return (ERROR);
- hashp->cpage = bufp;
- bp = (u_int16_t *)bufp->page;
- if (bp[0])
- break;
- }
- hashp->cbucket = bucket;
- if (hashp->cbucket > hashp->MAX_BUCKET) {
- hashp->cbucket = -1;
- return (ABNORMAL);
- }
- } else
- bp = (u_int16_t *)hashp->cpage->page;
-
-#ifdef DEBUG
- assert(bp);
- assert(bufp);
-#endif
- while (bp[hashp->cndx + 1] == OVFLPAGE) {
- bufp = hashp->cpage =
- __get_buf(hashp, bp[hashp->cndx], bufp, 0);
- if (!bufp)
- return (ERROR);
- bp = (u_int16_t *)(bufp->page);
- hashp->cndx = 1;
- }
- if (!bp[0]) {
- hashp->cpage = NULL;
- ++hashp->cbucket;
- }
- }
- ndx = hashp->cndx;
- if (bp[ndx + 1] < REAL_KEY) {
- if (__big_keydata(hashp, bufp, key, data, 1))
- return (ERROR);
- } else {
- key->data = (u_char *)hashp->cpage->page + bp[ndx];
- key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
- data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
- data->size = bp[ndx] - bp[ndx + 1];
- ndx += 2;
- if (ndx > bp[0]) {
- hashp->cpage = NULL;
- hashp->cbucket++;
- hashp->cndx = 1;
- } else
- hashp->cndx = ndx;
- }
- return (SUCCESS);
-}
-
-/********************************* UTILITIES ************************/
-
-/*
- * Returns:
- * 0 ==> OK
- * -1 ==> Error
- */
-extern int
-__expand_table(hashp)
- HTAB *hashp;
-{
- u_int32_t old_bucket, new_bucket;
- int dirsize, new_segnum, spare_ndx;
-
-#ifdef HASH_STATISTICS
- hash_expansions++;
-#endif
- new_bucket = ++hashp->MAX_BUCKET;
- old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK);
-
- new_segnum = new_bucket >> hashp->SSHIFT;
-
- /* Check if we need a new segment */
- if (new_segnum >= hashp->nsegs) {
- /* Check if we need to expand directory */
- if (new_segnum >= hashp->DSIZE) {
- /* Reallocate directory */
- dirsize = hashp->DSIZE * sizeof(SEGMENT *);
- if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1))
- return (-1);
- hashp->DSIZE = dirsize << 1;
- }
- if ((hashp->dir[new_segnum] =
- (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL)
- return (-1);
- hashp->exsegs++;
- hashp->nsegs++;
- }
- /*
- * If the split point is increasing (MAX_BUCKET's log base 2
- * * increases), we need to copy the current contents of the spare
- * split bucket to the next bucket.
- */
- spare_ndx = __hash_log2(hashp->MAX_BUCKET + 1);
- if (spare_ndx > hashp->OVFL_POINT) {
- hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT];
- hashp->OVFL_POINT = spare_ndx;
- }
-
- if (new_bucket > (u_int32_t) hashp->HIGH_MASK) {
- /* Starting a new doubling */
- hashp->LOW_MASK = hashp->HIGH_MASK;
- hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK;
- }
- /* Relocate records to the new bucket */
- return (__split_page(hashp, old_bucket, new_bucket));
-}
-
-/*
- * If realloc guarantees that the pointer is not destroyed if the realloc
- * fails, then this routine can go away.
- */
-static void *
-hash_realloc(p_ptr, oldsize, newsize)
- SEGMENT **p_ptr;
- int oldsize, newsize;
-{
- register void *p;
-
- if ((p = malloc(newsize))) {
- memmove(p, *p_ptr, oldsize);
- memset((char *)p + oldsize, 0, newsize - oldsize);
- free(*p_ptr);
- *p_ptr = p;
- }
- return (p);
-}
-
-extern u_int32_t
-__call_hash(hashp, k, len)
- HTAB *hashp;
- char *k;
- int len;
-{
- int n, bucket;
-
- n = hashp->hash(k, len);
- bucket = n & hashp->HIGH_MASK;
- if (bucket > hashp->MAX_BUCKET)
- bucket = bucket & hashp->LOW_MASK;
- return (bucket);
-}
-
-/*
- * Allocate segment table. On error, destroy the table and set errno.
- *
- * Returns 0 on success
- */
-static int
-alloc_segs(hashp, nsegs)
- HTAB *hashp;
- int nsegs;
-{
- register int i;
- register SEGMENT store;
-
- int save_errno;
-
- if ((hashp->dir =
- (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) {
- save_errno = errno;
- (void)hdestroy(hashp);
- errno = save_errno;
- return (-1);
- }
- /* Allocate segments */
- if ((store =
- (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) {
- save_errno = errno;
- (void)hdestroy(hashp);
- errno = save_errno;
- return (-1);
- }
- for (i = 0; i < nsegs; i++, hashp->nsegs++)
- hashp->dir[i] = &store[i << hashp->SSHIFT];
- return (0);
-}
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-/*
- * Hashp->hdr needs to be byteswapped.
- */
-static void
-swap_header_copy(srcp, destp)
- HASHHDR *srcp, *destp;
-{
- int i;
-
- P_32_COPY(srcp->magic, destp->magic);
- P_32_COPY(srcp->version, destp->version);
- P_32_COPY(srcp->lorder, destp->lorder);
- P_32_COPY(srcp->bsize, destp->bsize);
- P_32_COPY(srcp->bshift, destp->bshift);
- P_32_COPY(srcp->dsize, destp->dsize);
- P_32_COPY(srcp->ssize, destp->ssize);
- P_32_COPY(srcp->sshift, destp->sshift);
- P_32_COPY(srcp->ovfl_point, destp->ovfl_point);
- P_32_COPY(srcp->last_freed, destp->last_freed);
- P_32_COPY(srcp->max_bucket, destp->max_bucket);
- P_32_COPY(srcp->high_mask, destp->high_mask);
- P_32_COPY(srcp->low_mask, destp->low_mask);
- P_32_COPY(srcp->ffactor, destp->ffactor);
- P_32_COPY(srcp->nkeys, destp->nkeys);
- P_32_COPY(srcp->hdrpages, destp->hdrpages);
- P_32_COPY(srcp->h_charkey, destp->h_charkey);
- for (i = 0; i < NCACHED; i++) {
- P_32_COPY(srcp->spares[i], destp->spares[i]);
- P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]);
- }
-}
-
-static void
-swap_header(hashp)
- HTAB *hashp;
-{
- HASHHDR *hdrp;
- int i;
-
- hdrp = &hashp->hdr;
-
- M_32_SWAP(hdrp->magic);
- M_32_SWAP(hdrp->version);
- M_32_SWAP(hdrp->lorder);
- M_32_SWAP(hdrp->bsize);
- M_32_SWAP(hdrp->bshift);
- M_32_SWAP(hdrp->dsize);
- M_32_SWAP(hdrp->ssize);
- M_32_SWAP(hdrp->sshift);
- M_32_SWAP(hdrp->ovfl_point);
- M_32_SWAP(hdrp->last_freed);
- M_32_SWAP(hdrp->max_bucket);
- M_32_SWAP(hdrp->high_mask);
- M_32_SWAP(hdrp->low_mask);
- M_32_SWAP(hdrp->ffactor);
- M_32_SWAP(hdrp->nkeys);
- M_32_SWAP(hdrp->hdrpages);
- M_32_SWAP(hdrp->h_charkey);
- for (i = 0; i < NCACHED; i++) {
- M_32_SWAP(hdrp->spares[i]);
- M_16_SWAP(hdrp->bitmaps[i]);
- }
-}
-#endif
diff --git a/main/db1-ast/hash/hash.h b/main/db1-ast/hash/hash.h
deleted file mode 100644
index d07db6f07..000000000
--- a/main/db1-ast/hash/hash.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)hash.h 8.3 (Berkeley) 5/31/94
- */
-
-/* Operations */
-typedef enum {
- HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
-} ACTION;
-
-/* Buffer Management structures */
-typedef struct _bufhead BUFHEAD;
-
-struct _bufhead {
- BUFHEAD *prev; /* LRU links */
- BUFHEAD *next; /* LRU links */
- BUFHEAD *ovfl; /* Overflow page buffer header */
- u_int32_t addr; /* Address of this page */
- char *page; /* Actual page data */
- char flags;
-#define BUF_MOD 0x0001
-#define BUF_DISK 0x0002
-#define BUF_BUCKET 0x0004
-#define BUF_PIN 0x0008
-};
-
-#define IS_BUCKET(X) ((X) & BUF_BUCKET)
-
-typedef BUFHEAD **SEGMENT;
-
-/* Hash Table Information */
-typedef struct hashhdr { /* Disk resident portion */
- int magic; /* Magic NO for hash tables */
- int version; /* Version ID */
- u_int32_t lorder; /* Byte Order */
- int bsize; /* Bucket/Page Size */
- int bshift; /* Bucket shift */
- int dsize; /* Directory Size */
- int ssize; /* Segment Size */
- int sshift; /* Segment shift */
- int ovfl_point; /* Where overflow pages are being
- * allocated */
- int last_freed; /* Last overflow page freed */
- int max_bucket; /* ID of Maximum bucket in use */
- int high_mask; /* Mask to modulo into entire table */
- int low_mask; /* Mask to modulo into lower half of
- * table */
- int ffactor; /* Fill factor */
- int nkeys; /* Number of keys in hash table */
- int hdrpages; /* Size of table header */
- int h_charkey; /* value of hash(CHARKEY) */
-#define NCACHED 32 /* number of bit maps and spare
- * points */
- int spares[NCACHED];/* spare pages for overflow */
- u_int16_t bitmaps[NCACHED]; /* address of overflow page
- * bitmaps */
-} HASHHDR;
-
-typedef struct htab { /* Memory resident data structure */
- HASHHDR hdr; /* Header */
- int nsegs; /* Number of allocated segments */
- int exsegs; /* Number of extra allocated
- * segments */
- u_int32_t /* Hash function */
- (*hash)__P((const void *, size_t));
- int flags; /* Flag values */
- int fp; /* File pointer */
- char *tmp_buf; /* Temporary Buffer for BIG data */
- char *tmp_key; /* Temporary Buffer for BIG keys */
- BUFHEAD *cpage; /* Current page */
- int cbucket; /* Current bucket */
- int cndx; /* Index of next item on cpage */
- int errnum; /* Error Number -- for DBM
- * compatibility */
- int new_file; /* Indicates if fd is backing store
- * or no */
- int save_file; /* Indicates whether we need to flush
- * file at
- * exit */
- u_int32_t *mapp[NCACHED]; /* Pointers to page maps */
- int nmaps; /* Initial number of bitmaps */
- int nbufs; /* Number of buffers left to
- * allocate */
- BUFHEAD bufhead; /* Header of buffer lru list */
- SEGMENT *dir; /* Hash Bucket directory */
-} HTAB;
-
-/*
- * Constants
- */
-#define MAX_BSIZE 65536 /* 2^16 */
-#define MIN_BUFFERS 6
-#define MINHDRSIZE 512
-#define DEF_BUFSIZE 65536 /* 64 K */
-#define DEF_BUCKET_SIZE 4096
-#define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */
-#define DEF_SEGSIZE 256
-#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */
-#define DEF_DIRSIZE 256
-#define DEF_FFACTOR 65536
-#define MIN_FFACTOR 4
-#define SPLTMAX 8
-#define CHARKEY "%$sniglet^&"
-#define NUMKEY 1038583
-#define BYTE_SHIFT 3
-#define INT_TO_BYTE 2
-#define INT_BYTE_SHIFT 5
-#define ALL_SET ((u_int32_t)0xFFFFFFFF)
-#define ALL_CLEAR 0
-
-#define PTROF(X) ((BUFHEAD *)((ptrdiff_t)(X)&~0x3))
-#define ISMOD(X) ((u_int32_t)(ptrdiff_t)(X)&0x1)
-#define DOMOD(X) ((X) = (char *)((ptrdiff_t)(X)|0x1))
-#define ISDISK(X) ((u_int32_t)(ptrdiff_t)(X)&0x2)
-#define DODISK(X) ((X) = (char *)((ptrdiff_t)(X)|0x2))
-
-#define BITS_PER_MAP 32
-
-/* Given the address of the beginning of a big map, clear/set the nth bit */
-#define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
-#define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
-#define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
-
-/* Overflow management */
-/*
- * Overflow page numbers are allocated per split point. At each doubling of
- * the table, we can allocate extra pages. So, an overflow page number has
- * the top 5 bits indicate which split point and the lower 11 bits indicate
- * which page at that split point is indicated (pages within split points are
- * numberered starting with 1).
- */
-
-#define SPLITSHIFT 11
-#define SPLITMASK 0x7FF
-#define SPLITNUM(N) (((u_int32_t)(N)) >> SPLITSHIFT)
-#define OPAGENUM(N) ((N) & SPLITMASK)
-#define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O))
-
-#define BUCKET_TO_PAGE(B) \
- (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__hash_log2((B)+1)-1] : 0)
-#define OADDR_TO_PAGE(B) \
- BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));
-
-/*
- * page.h contains a detailed description of the page format.
- *
- * Normally, keys and data are accessed from offset tables in the top of
- * each page which point to the beginning of the key and data. There are
- * four flag values which may be stored in these offset tables which indicate
- * the following:
- *
- *
- * OVFLPAGE Rather than a key data pair, this pair contains
- * the address of an overflow page. The format of
- * the pair is:
- * OVERFLOW_PAGE_NUMBER OVFLPAGE
- *
- * PARTIAL_KEY This must be the first key/data pair on a page
- * and implies that page contains only a partial key.
- * That is, the key is too big to fit on a single page
- * so it starts on this page and continues on the next.
- * The format of the page is:
- * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE
- *
- * KEY_OFF -- offset of the beginning of the key
- * PARTIAL_KEY -- 1
- * OVFL_PAGENO - page number of the next overflow page
- * OVFLPAGE -- 0
- *
- * FULL_KEY This must be the first key/data pair on the page. It
- * is used in two cases.
- *
- * Case 1:
- * There is a complete key on the page but no data
- * (because it wouldn't fit). The next page contains
- * the data.
- *
- * Page format it:
- * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
- *
- * KEY_OFF -- offset of the beginning of the key
- * FULL_KEY -- 2
- * OVFL_PAGENO - page number of the next overflow page
- * OVFLPAGE -- 0
- *
- * Case 2:
- * This page contains no key, but part of a large
- * data field, which is continued on the next page.
- *
- * Page format it:
- * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
- *
- * KEY_OFF -- offset of the beginning of the data on
- * this page
- * FULL_KEY -- 2
- * OVFL_PAGENO - page number of the next overflow page
- * OVFLPAGE -- 0
- *
- * FULL_KEY_DATA
- * This must be the first key/data pair on the page.
- * There are two cases:
- *
- * Case 1:
- * This page contains a key and the beginning of the
- * data field, but the data field is continued on the
- * next page.
- *
- * Page format is:
- * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF
- *
- * KEY_OFF -- offset of the beginning of the key
- * FULL_KEY_DATA -- 3
- * OVFL_PAGENO - page number of the next overflow page
- * DATA_OFF -- offset of the beginning of the data
- *
- * Case 2:
- * This page contains the last page of a big data pair.
- * There is no key, only the tail end of the data
- * on this page.
- *
- * Page format is:
- * DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE>
- *
- * DATA_OFF -- offset of the beginning of the data on
- * this page
- * FULL_KEY_DATA -- 3
- * OVFL_PAGENO - page number of the next overflow page
- * OVFLPAGE -- 0
- *
- * OVFL_PAGENO and OVFLPAGE are optional (they are
- * not present if there is no next page).
- */
-
-#define OVFLPAGE 0
-#define PARTIAL_KEY 1
-#define FULL_KEY 2
-#define FULL_KEY_DATA 3
-#define REAL_KEY 4
-
-/* Short hands for accessing structure */
-#define BSIZE hdr.bsize
-#define BSHIFT hdr.bshift
-#define DSIZE hdr.dsize
-#define SGSIZE hdr.ssize
-#define SSHIFT hdr.sshift
-#define LORDER hdr.lorder
-#define OVFL_POINT hdr.ovfl_point
-#define LAST_FREED hdr.last_freed
-#define MAX_BUCKET hdr.max_bucket
-#define FFACTOR hdr.ffactor
-#define HIGH_MASK hdr.high_mask
-#define LOW_MASK hdr.low_mask
-#define NKEYS hdr.nkeys
-#define HDRPAGES hdr.hdrpages
-#define SPARES hdr.spares
-#define BITMAPS hdr.bitmaps
-#define VERSION hdr.version
-#define MAGIC hdr.magic
-#define NEXT_FREE hdr.next_free
-#define H_CHARKEY hdr.h_charkey
diff --git a/main/db1-ast/hash/hash_bigkey.c b/main/db1-ast/hash/hash_bigkey.c
deleted file mode 100644
index daa8c1f17..000000000
--- a/main/db1-ast/hash/hash_bigkey.c
+++ /dev/null
@@ -1,668 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
-#endif /* LIBC_SCCS and not lint */
-
-/*
- * PACKAGE: hash
- * DESCRIPTION:
- * Big key/data handling for the hashing package.
- *
- * ROUTINES:
- * External
- * __big_keydata
- * __big_split
- * __big_insert
- * __big_return
- * __big_delete
- * __find_last_page
- * Internal
- * collect_key
- * collect_data
- */
-
-#include <sys/param.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef DEBUG
-#include <assert.h>
-#endif
-
-#include "../include/db.h"
-#include "hash.h"
-#include "page.h"
-#include "extern.h"
-
-static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int));
-static int collect_data __P((HTAB *, BUFHEAD *, int, int));
-
-/*
- * Big_insert
- *
- * You need to do an insert and the key/data pair is too big
- *
- * Returns:
- * 0 ==> OK
- *-1 ==> ERROR
- */
-extern int
-__big_insert(hashp, bufp, key, val)
- HTAB *hashp;
- BUFHEAD *bufp;
- const DBT *key, *val;
-{
- register u_int16_t *p;
- int key_size, n, val_size;
- u_int16_t space, move_bytes, off;
- char *cp, *key_data, *val_data;
-
- cp = bufp->page; /* Character pointer of p. */
- p = (u_int16_t *)cp;
-
- key_data = (char *)key->data;
- key_size = key->size;
- val_data = (char *)val->data;
- val_size = val->size;
-
- /* First move the Key */
- for (space = FREESPACE(p) - BIGOVERHEAD; key_size;
- space = FREESPACE(p) - BIGOVERHEAD) {
- move_bytes = MIN(space, key_size);
- off = OFFSET(p) - move_bytes;
- memmove(cp + off, key_data, move_bytes);
- key_size -= move_bytes;
- key_data += move_bytes;
- n = p[0];
- p[++n] = off;
- p[0] = ++n;
- FREESPACE(p) = off - PAGE_META(n);
- OFFSET(p) = off;
- p[n] = PARTIAL_KEY;
- bufp = __add_ovflpage(hashp, bufp);
- if (!bufp)
- return (-1);
- n = p[0];
- if (!key_size) {
- if (FREESPACE(p)) {
- move_bytes = MIN(FREESPACE(p), val_size);
- off = OFFSET(p) - move_bytes;
- p[n] = off;
- memmove(cp + off, val_data, move_bytes);
- val_data += move_bytes;
- val_size -= move_bytes;
- p[n - 2] = FULL_KEY_DATA;
- FREESPACE(p) = FREESPACE(p) - move_bytes;
- OFFSET(p) = off;
- } else
- p[n - 2] = FULL_KEY;
- }
- p = (u_int16_t *)bufp->page;
- cp = bufp->page;
- bufp->flags |= BUF_MOD;
- }
-
- /* Now move the data */
- for (space = FREESPACE(p) - BIGOVERHEAD; val_size;
- space = FREESPACE(p) - BIGOVERHEAD) {
- move_bytes = MIN(space, val_size);
- /*
- * Here's the hack to make sure that if the data ends on the
- * same page as the key ends, FREESPACE is at least one.
- */
- if ((int) space == val_size && (size_t) val_size == val->size)
- move_bytes--;
- off = OFFSET(p) - move_bytes;
- memmove(cp + off, val_data, move_bytes);
- val_size -= move_bytes;
- val_data += move_bytes;
- n = p[0];
- p[++n] = off;
- p[0] = ++n;
- FREESPACE(p) = off - PAGE_META(n);
- OFFSET(p) = off;
- if (val_size) {
- p[n] = FULL_KEY;
- bufp = __add_ovflpage(hashp, bufp);
- if (!bufp)
- return (-1);
- cp = bufp->page;
- p = (u_int16_t *)cp;
- } else
- p[n] = FULL_KEY_DATA;
- bufp->flags |= BUF_MOD;
- }
- return (0);
-}
-
-/*
- * Called when bufp's page contains a partial key (index should be 1)
- *
- * All pages in the big key/data pair except bufp are freed. We cannot
- * free bufp because the page pointing to it is lost and we can't get rid
- * of its pointer.
- *
- * Returns:
- * 0 => OK
- *-1 => ERROR
- */
-extern int
-__big_delete(hashp, bufp)
- HTAB *hashp;
- BUFHEAD *bufp;
-{
- register BUFHEAD *last_bfp, *rbufp;
- u_int16_t *bp, pageno;
- int key_done, n;
-
- rbufp = bufp;
- last_bfp = NULL;
- bp = (u_int16_t *)bufp->page;
- pageno = 0;
- key_done = 0;
-
- while (!key_done || (bp[2] != FULL_KEY_DATA)) {
- if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA)
- key_done = 1;
-
- /*
- * If there is freespace left on a FULL_KEY_DATA page, then
- * the data is short and fits entirely on this page, and this
- * is the last page.
- */
- if (bp[2] == FULL_KEY_DATA && FREESPACE(bp))
- break;
- pageno = bp[bp[0] - 1];
- rbufp->flags |= BUF_MOD;
- rbufp = __get_buf(hashp, pageno, rbufp, 0);
- if (last_bfp)
- __free_ovflpage(hashp, last_bfp);
- last_bfp = rbufp;
- if (!rbufp)
- return (-1); /* Error. */
- bp = (u_int16_t *)rbufp->page;
- }
-
- /*
- * If we get here then rbufp points to the last page of the big
- * key/data pair. Bufp points to the first one -- it should now be
- * empty pointing to the next page after this pair. Can't free it
- * because we don't have the page pointing to it.
- */
-
- /* This is information from the last page of the pair. */
- n = bp[0];
- pageno = bp[n - 1];
-
- /* Now, bp is the first page of the pair. */
- bp = (u_int16_t *)bufp->page;
- if (n > 2) {
- /* There is an overflow page. */
- bp[1] = pageno;
- bp[2] = OVFLPAGE;
- bufp->ovfl = rbufp->ovfl;
- } else
- /* This is the last page. */
- bufp->ovfl = NULL;
- n -= 2;
- bp[0] = n;
- FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
- OFFSET(bp) = hashp->BSIZE - 1;
-
- bufp->flags |= BUF_MOD;
- if (rbufp)
- __free_ovflpage(hashp, rbufp);
- if (last_bfp && last_bfp != rbufp)
- __free_ovflpage(hashp, last_bfp);
-
- hashp->NKEYS--;
- return (0);
-}
-/*
- * Returns:
- * 0 = key not found
- * -1 = get next overflow page
- * -2 means key not found and this is big key/data
- * -3 error
- */
-extern int
-__find_bigpair(hashp, bufp, ndx, key, size)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
- char *key;
- int size;
-{
- register u_int16_t *bp;
- register char *p;
- int ksize;
- u_int16_t bytes;
- char *kkey;
-
- bp = (u_int16_t *)bufp->page;
- p = bufp->page;
- ksize = size;
- kkey = key;
-
- for (bytes = hashp->BSIZE - bp[ndx];
- bytes <= size && bp[ndx + 1] == PARTIAL_KEY;
- bytes = hashp->BSIZE - bp[ndx]) {
- if (memcmp(p + bp[ndx], kkey, bytes))
- return (-2);
- kkey += bytes;
- ksize -= bytes;
- bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0);
- if (!bufp)
- return (-3);
- p = bufp->page;
- bp = (u_int16_t *)p;
- ndx = 1;
- }
-
- if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {
-#ifdef HASH_STATISTICS
- ++hash_collisions;
-#endif
- return (-2);
- } else
- return (ndx);
-}
-
-/*
- * Given the buffer pointer of the first overflow page of a big pair,
- * find the end of the big pair
- *
- * This will set bpp to the buffer header of the last page of the big pair.
- * It will return the pageno of the overflow page following the last page
- * of the pair; 0 if there isn't any (i.e. big pair is the last key in the
- * bucket)
- */
-extern u_int16_t
-__find_last_page(hashp, bpp)
- HTAB *hashp;
- BUFHEAD **bpp;
-{
- BUFHEAD *bufp;
- u_int16_t *bp, pageno;
- int n;
-
- bufp = *bpp;
- bp = (u_int16_t *)bufp->page;
- for (;;) {
- n = bp[0];
-
- /*
- * This is the last page if: the tag is FULL_KEY_DATA and
- * either only 2 entries OVFLPAGE marker is explicit there
- * is freespace on the page.
- */
- if (bp[2] == FULL_KEY_DATA &&
- ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp))))
- break;
-
- pageno = bp[n - 1];
- bufp = __get_buf(hashp, pageno, bufp, 0);
- if (!bufp)
- return (0); /* Need to indicate an error! */
- bp = (u_int16_t *)bufp->page;
- }
-
- *bpp = bufp;
- if (bp[0] > 2)
- return (bp[3]);
- else
- return (0);
-}
-
-/*
- * Return the data for the key/data pair that begins on this page at this
- * index (index should always be 1).
- */
-extern int
-__big_return(hashp, bufp, ndx, val, set_current)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
- DBT *val;
- int set_current;
-{
- BUFHEAD *save_p;
- u_int16_t *bp, len, off, save_addr;
- char *tp;
-
- bp = (u_int16_t *)bufp->page;
- while (bp[ndx + 1] == PARTIAL_KEY) {
- bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
- if (!bufp)
- return (-1);
- bp = (u_int16_t *)bufp->page;
- ndx = 1;
- }
-
- if (bp[ndx + 1] == FULL_KEY) {
- bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
- if (!bufp)
- return (-1);
- bp = (u_int16_t *)bufp->page;
- save_p = bufp;
- save_addr = save_p->addr;
- off = bp[1];
- len = 0;
- } else
- if (!FREESPACE(bp)) {
- /*
- * This is a hack. We can't distinguish between
- * FULL_KEY_DATA that contains complete data or
- * incomplete data, so we require that if the data
- * is complete, there is at least 1 byte of free
- * space left.
- */
- off = bp[bp[0]];
- len = bp[1] - off;
- save_p = bufp;
- save_addr = bufp->addr;
- bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
- if (!bufp)
- return (-1);
- bp = (u_int16_t *)bufp->page;
- } else {
- /* The data is all on one page. */
- tp = (char *)bp;
- off = bp[bp[0]];
- val->data = (u_char *)tp + off;
- val->size = bp[1] - off;
- if (set_current) {
- if (bp[0] == 2) { /* No more buckets in
- * chain */
- hashp->cpage = NULL;
- hashp->cbucket++;
- hashp->cndx = 1;
- } else {
- hashp->cpage = __get_buf(hashp,
- bp[bp[0] - 1], bufp, 0);
- if (!hashp->cpage)
- return (-1);
- hashp->cndx = 1;
- if (!((u_int16_t *)
- hashp->cpage->page)[0]) {
- hashp->cbucket++;
- hashp->cpage = NULL;
- }
- }
- }
- return (0);
- }
-
- val->size = collect_data(hashp, bufp, (int)len, set_current);
- if (val->size == (size_t) -1)
- return (-1);
- if (save_p->addr != save_addr) {
- /* We are pretty short on buffers. */
- errno = EINVAL; /* OUT OF BUFFERS */
- return (-1);
- }
- memmove(hashp->tmp_buf, (save_p->page) + off, len);
- val->data = (u_char *)hashp->tmp_buf;
- return (0);
-}
-/*
- * Count how big the total datasize is by recursing through the pages. Then
- * allocate a buffer and copy the data as you recurse up.
- */
-static int
-collect_data(hashp, bufp, len, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- int len, set;
-{
- register u_int16_t *bp;
- register char *p;
- BUFHEAD *xbp;
- u_int16_t save_addr;
- int mylen, totlen;
-
- p = bufp->page;
- bp = (u_int16_t *)p;
- mylen = hashp->BSIZE - bp[1];
- save_addr = bufp->addr;
-
- if (bp[2] == FULL_KEY_DATA) { /* End of Data */
- totlen = len + mylen;
- if (hashp->tmp_buf)
- free(hashp->tmp_buf);
- if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL)
- return (-1);
- if (set) {
- hashp->cndx = 1;
- if (bp[0] == 2) { /* No more buckets in chain */
- hashp->cpage = NULL;
- hashp->cbucket++;
- } else {
- hashp->cpage =
- __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
- if (!hashp->cpage)
- return (-1);
- else if (!((u_int16_t *)hashp->cpage->page)[0]) {
- hashp->cbucket++;
- hashp->cpage = NULL;
- }
- }
- }
- } else {
- xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
- if (!xbp || ((totlen =
- collect_data(hashp, xbp, len + mylen, set)) < 1))
- return (-1);
- }
- if (bufp->addr != save_addr) {
- errno = EINVAL; /* Out of buffers. */
- return (-1);
- }
- memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen);
- return (totlen);
-}
-
-/*
- * Fill in the key and data for this big pair.
- */
-extern int
-__big_keydata(hashp, bufp, key, val, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- DBT *key, *val;
- int set;
-{
- key->size = collect_key(hashp, bufp, 0, val, set);
- if (key->size == (size_t) -1)
- return (-1);
- key->data = (u_char *)hashp->tmp_key;
- return (0);
-}
-
-/*
- * Count how big the total key size is by recursing through the pages. Then
- * collect the data, allocate a buffer and copy the key as you recurse up.
- */
-static int
-collect_key(hashp, bufp, len, val, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- int len;
- DBT *val;
- int set;
-{
- BUFHEAD *xbp;
- char *p;
- int mylen, totlen;
- u_int16_t *bp, save_addr;
-
- p = bufp->page;
- bp = (u_int16_t *)p;
- mylen = hashp->BSIZE - bp[1];
-
- save_addr = bufp->addr;
- totlen = len + mylen;
- if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */
- if (hashp->tmp_key != NULL)
- free(hashp->tmp_key);
- if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL)
- return (-1);
- if (__big_return(hashp, bufp, 1, val, set))
- return (-1);
- } else {
- xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
- if (!xbp || ((totlen =
- collect_key(hashp, xbp, totlen, val, set)) < 1))
- return (-1);
- }
- if (bufp->addr != save_addr) {
- errno = EINVAL; /* MIS -- OUT OF BUFFERS */
- return (-1);
- }
- memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen);
- return (totlen);
-}
-
-/*
- * Returns:
- * 0 => OK
- * -1 => error
- */
-extern int
-__big_split(hashp, op, np, big_keyp, addr, obucket, ret)
- HTAB *hashp;
- BUFHEAD *op; /* Pointer to where to put keys that go in old bucket */
- BUFHEAD *np; /* Pointer to new bucket page */
- /* Pointer to first page containing the big key/data */
- BUFHEAD *big_keyp;
- int addr; /* Address of big_keyp */
- u_int32_t obucket;/* Old Bucket */
- SPLIT_RETURN *ret;
-{
- register BUFHEAD *tmpp;
- register u_int16_t *tp;
- BUFHEAD *bp;
- DBT key, val;
- u_int32_t change;
- u_int16_t free_space, n, off;
-
- bp = big_keyp;
-
- /* Now figure out where the big key/data goes */
- if (__big_keydata(hashp, big_keyp, &key, &val, 0))
- return (-1);
- change = (__call_hash(hashp, key.data, key.size) != obucket);
-
- if ((ret->next_addr = __find_last_page(hashp, &big_keyp))) {
- if (!(ret->nextp =
- __get_buf(hashp, ret->next_addr, big_keyp, 0)))
- return (-1);;
- } else
- ret->nextp = NULL;
-
- /* Now make one of np/op point to the big key/data pair */
-#ifdef DEBUG
- assert(np->ovfl == NULL);
-#endif
- if (change)
- tmpp = np;
- else
- tmpp = op;
-
- tmpp->flags |= BUF_MOD;
-#ifdef DEBUG1
- (void)fprintf(stderr,
- "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
- (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
-#endif
- tmpp->ovfl = bp; /* one of op/np point to big_keyp */
- tp = (u_int16_t *)tmpp->page;
-#ifdef DEBUG
- assert(FREESPACE(tp) >= OVFLSIZE);
-#endif
- n = tp[0];
- off = OFFSET(tp);
- free_space = FREESPACE(tp);
- tp[++n] = (u_int16_t)addr;
- tp[++n] = OVFLPAGE;
- tp[0] = n;
- OFFSET(tp) = off;
- FREESPACE(tp) = free_space - OVFLSIZE;
-
- /*
- * Finally, set the new and old return values. BIG_KEYP contains a
- * pointer to the last page of the big key_data pair. Make sure that
- * big_keyp has no following page (2 elements) or create an empty
- * following page.
- */
-
- ret->newp = np;
- ret->oldp = op;
-
- tp = (u_int16_t *)big_keyp->page;
- big_keyp->flags |= BUF_MOD;
- if (tp[0] > 2) {
- /*
- * There may be either one or two offsets on this page. If
- * there is one, then the overflow page is linked on normally
- * and tp[4] is OVFLPAGE. If there are two, tp[4] contains
- * the second offset and needs to get stuffed in after the
- * next overflow page is added.
- */
- n = tp[4];
- free_space = FREESPACE(tp);
- off = OFFSET(tp);
- tp[0] -= 2;
- FREESPACE(tp) = free_space + OVFLSIZE;
- OFFSET(tp) = off;
- tmpp = __add_ovflpage(hashp, big_keyp);
- if (!tmpp)
- return (-1);
- tp[4] = n;
- } else
- tmpp = big_keyp;
-
- if (change)
- ret->newp = tmpp;
- else
- ret->oldp = tmpp;
- return (0);
-}
diff --git a/main/db1-ast/hash/hash_buf.c b/main/db1-ast/hash/hash_buf.c
deleted file mode 100644
index 063dd8229..000000000
--- a/main/db1-ast/hash/hash_buf.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94";
-#endif /* LIBC_SCCS and not lint */
-
-/*
- * PACKAGE: hash
- *
- * DESCRIPTION:
- * Contains buffer management
- *
- * ROUTINES:
- * External
- * __buf_init
- * __get_buf
- * __buf_free
- * __reclaim_buf
- * Internal
- * newbuf
- */
-
-#include <sys/param.h>
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef DEBUG
-#include <assert.h>
-#endif
-
-#include "../include/db.h"
-#include "hash.h"
-#include "page.h"
-#include "extern.h"
-
-static BUFHEAD *newbuf __P((HTAB *, u_int32_t, BUFHEAD *));
-
-/* Unlink B from its place in the lru */
-#define BUF_REMOVE(B) { \
- (B)->prev->next = (B)->next; \
- (B)->next->prev = (B)->prev; \
-}
-
-/* Insert B after P */
-#define BUF_INSERT(B, P) { \
- (B)->next = (P)->next; \
- (B)->prev = (P); \
- (P)->next = (B); \
- (B)->next->prev = (B); \
-}
-
-#define MRU hashp->bufhead.next
-#define LRU hashp->bufhead.prev
-
-#define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead)
-#define LRU_INSERT(B) BUF_INSERT((B), LRU)
-
-/*
- * We are looking for a buffer with address "addr". If prev_bp is NULL, then
- * address is a bucket index. If prev_bp is not NULL, then it points to the
- * page previous to an overflow page that we are trying to find.
- *
- * CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer
- * be valid. Therefore, you must always verify that its address matches the
- * address you are seeking.
- */
-extern BUFHEAD *
-__get_buf(hashp, addr, prev_bp, newpage)
- HTAB *hashp;
- u_int32_t addr;
- BUFHEAD *prev_bp;
- int newpage; /* If prev_bp set, indicates a new overflow page. */
-{
- register BUFHEAD *bp;
- register u_int32_t is_disk_mask;
- register int is_disk, segment_ndx = 0;
- SEGMENT segp = 0;
-
- is_disk = 0;
- is_disk_mask = 0;
- if (prev_bp) {
- bp = prev_bp->ovfl;
- if (!bp || (bp->addr != addr))
- bp = NULL;
- if (!newpage)
- is_disk = BUF_DISK;
- } else {
- /* Grab buffer out of directory */
- segment_ndx = addr & (hashp->SGSIZE - 1);
-
- /* valid segment ensured by __call_hash() */
- segp = hashp->dir[addr >> hashp->SSHIFT];
-#ifdef DEBUG
- assert(segp != NULL);
-#endif
- bp = PTROF(segp[segment_ndx]);
- is_disk_mask = ISDISK(segp[segment_ndx]);
- is_disk = is_disk_mask || !hashp->new_file;
- }
-
- if (!bp) {
- bp = newbuf(hashp, addr, prev_bp);
- if (!bp ||
- __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0))
- return (NULL);
- if (!prev_bp)
- segp[segment_ndx] =
- (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask);
- } else {
- BUF_REMOVE(bp);
- MRU_INSERT(bp);
- }
- return (bp);
-}
-
-/*
- * We need a buffer for this page. Either allocate one, or evict a resident
- * one (if we have as many buffers as we're allowed) and put this one in.
- *
- * If newbuf finds an error (returning NULL), it also sets errno.
- */
-static BUFHEAD *
-newbuf(hashp, addr, prev_bp)
- HTAB *hashp;
- u_int32_t addr;
- BUFHEAD *prev_bp;
-{
- register BUFHEAD *bp; /* The buffer we're going to use */
- register BUFHEAD *xbp; /* Temp pointer */
- register BUFHEAD *next_xbp;
- SEGMENT segp;
- int segment_ndx;
- u_int16_t oaddr, *shortp;
-
- oaddr = 0;
- bp = LRU;
- /*
- * If LRU buffer is pinned, the buffer pool is too small. We need to
- * allocate more buffers.
- */
- if (hashp->nbufs || (bp->flags & BUF_PIN)) {
- /* Allocate a new one */
- if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
- return (NULL);
-#ifdef PURIFY
- memset(bp, 0xff, sizeof(BUFHEAD));
-#endif
- if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) {
- free(bp);
- return (NULL);
- }
-#ifdef PURIFY
- memset(bp->page, 0xff, hashp->BSIZE);
-#endif
- if (hashp->nbufs)
- hashp->nbufs--;
- } else {
- /* Kick someone out */
- BUF_REMOVE(bp);
- /*
- * If this is an overflow page with addr 0, it's already been
- * flushed back in an overflow chain and initialized.
- */
- if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) {
- /*
- * Set oaddr before __put_page so that you get it
- * before bytes are swapped.
- */
- shortp = (u_int16_t *)bp->page;
- if (shortp[0])
- oaddr = shortp[shortp[0] - 1];
- if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page,
- bp->addr, (int)IS_BUCKET(bp->flags), 0))
- return (NULL);
- /*
- * Update the pointer to this page (i.e. invalidate it).
- *
- * If this is a new file (i.e. we created it at open
- * time), make sure that we mark pages which have been
- * written to disk so we retrieve them from disk later,
- * rather than allocating new pages.
- */
- if (IS_BUCKET(bp->flags)) {
- segment_ndx = bp->addr & (hashp->SGSIZE - 1);
- segp = hashp->dir[bp->addr >> hashp->SSHIFT];
-#ifdef DEBUG
- assert(segp != NULL);
-#endif
-
- if (hashp->new_file &&
- ((bp->flags & BUF_MOD) ||
- ISDISK(segp[segment_ndx])))
- segp[segment_ndx] = (BUFHEAD *)BUF_DISK;
- else
- segp[segment_ndx] = NULL;
- }
- /*
- * Since overflow pages can only be access by means of
- * their bucket, free overflow pages associated with
- * this bucket.
- */
- for (xbp = bp; xbp->ovfl;) {
- next_xbp = xbp->ovfl;
- xbp->ovfl = 0;
- xbp = next_xbp;
-
- /* Check that ovfl pointer is up date. */
- if (IS_BUCKET(xbp->flags) ||
- (oaddr != xbp->addr))
- break;
-
- shortp = (u_int16_t *)xbp->page;
- if (shortp[0])
- /* set before __put_page */
- oaddr = shortp[shortp[0] - 1];
- if ((xbp->flags & BUF_MOD) && __put_page(hashp,
- xbp->page, xbp->addr, 0, 0))
- return (NULL);
- xbp->addr = 0;
- xbp->flags = 0;
- BUF_REMOVE(xbp);
- LRU_INSERT(xbp);
- }
- }
- }
-
- /* Now assign this buffer */
- bp->addr = addr;
-#ifdef DEBUG1
- (void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n",
- bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0);
-#endif
- bp->ovfl = NULL;
- if (prev_bp) {
- /*
- * If prev_bp is set, this is an overflow page, hook it in to
- * the buffer overflow links.
- */
-#ifdef DEBUG1
- (void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
- prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0),
- (bp ? bp->addr : 0));
-#endif
- prev_bp->ovfl = bp;
- bp->flags = 0;
- } else
- bp->flags = BUF_BUCKET;
- MRU_INSERT(bp);
- return (bp);
-}
-
-extern void
-__buf_init(hashp, nbytes)
- HTAB *hashp;
- int nbytes;
-{
- BUFHEAD *bfp;
- int npages;
-
- bfp = &(hashp->bufhead);
- npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT;
- npages = MAX(npages, MIN_BUFFERS);
-
- hashp->nbufs = npages;
- bfp->next = bfp;
- bfp->prev = bfp;
- /*
- * This space is calloc'd so these are already null.
- *
- * bfp->ovfl = NULL;
- * bfp->flags = 0;
- * bfp->page = NULL;
- * bfp->addr = 0;
- */
-}
-
-extern int
-__buf_free(hashp, do_free, to_disk)
- HTAB *hashp;
- int do_free, to_disk;
-{
- BUFHEAD *bp;
-
- /* Need to make sure that buffer manager has been initialized */
- if (!LRU)
- return (0);
- for (bp = LRU; bp != &hashp->bufhead;) {
- /* Check that the buffer is valid */
- if (bp->addr || IS_BUCKET(bp->flags)) {
- if (to_disk && (bp->flags & BUF_MOD) &&
- __put_page(hashp, bp->page,
- bp->addr, IS_BUCKET(bp->flags), 0))
- return (-1);
- }
- /* Check if we are freeing stuff */
- if (do_free) {
- if (bp->page)
- free(bp->page);
- BUF_REMOVE(bp);
- free(bp);
- bp = LRU;
- } else
- bp = bp->prev;
- }
- return (0);
-}
-
-extern void
-__reclaim_buf(hashp, bp)
- HTAB *hashp;
- BUFHEAD *bp;
-{
- bp->ovfl = 0;
- bp->addr = 0;
- bp->flags = 0;
- BUF_REMOVE(bp);
- LRU_INSERT(bp);
-}
diff --git a/main/db1-ast/hash/hash_func.c b/main/db1-ast/hash/hash_func.c
deleted file mode 100644
index 4d7907b57..000000000
--- a/main/db1-ast/hash/hash_func.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include "../include/db.h"
-#include "hash.h"
-#include "page.h"
-#include "extern.h"
-
-/* only one of these can be defined */
-/* #define HASH1_EJB 1 */
-/* #define HASH2_PHONG 1 */
-/* #define HASH3_SDBM 1 */
-#define HASH4_TOREK 1
-
-static u_int32_t hashfunc __P((const void *, size_t));
-
-/* Global default hash function */
-u_int32_t (*__default_hash) __P((const void *, size_t)) = hashfunc;
-
-/*
- * HASH FUNCTIONS
- *
- * Assume that we've already split the bucket to which this key hashes,
- * calculate that bucket, and check that in fact we did already split it.
- *
- * This came from ejb's hsearch.
- */
-
-#ifdef HASH1_EJB
-
-#define PRIME1 37
-#define PRIME2 1048583
-
-static u_int32_t
-hashfunc(keyarg, len)
- const void *keyarg;
- register size_t len;
-{
- register const u_char *key;
- register u_int32_t h;
-
- /* Convert string to integer */
- for (key = keyarg, h = 0; len--;)
- h = h * PRIME1 ^ (*key++ - ' ');
- h %= PRIME2;
- return (h);
-}
-
-#endif
-
-#ifdef HASH2_PHONG
-/*
- * Phong's linear congruential hash
- */
-#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
-
-static u_int32_t
-hashfunc(keyarg, len)
- const void *keyarg;
- size_t len;
-{
- register const u_char *e, *key;
- register u_int32_t h;
- register u_char c;
-
- key = keyarg;
- e = key + len;
- for (h = 0; key != e;) {
- c = *key++;
- if (!c && key > e)
- break;
- dcharhash(h, c);
- }
- return (h);
-}
-#endif
-
-#ifdef HASH3_SDBM
-/*
- * This is INCREDIBLY ugly, but fast. We break the string up into 8 byte
- * units. On the first time through the loop we get the "leftover bytes"
- * (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle
- * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If
- * this routine is heavily used enough, it's worth the ugly coding.
- *
- * OZ's original sdbm hash
- */
-static u_int32_t
-hashfunc(keyarg, len)
- const void *keyarg;
- register size_t len;
-{
- register const u_char *key;
- register size_t loop;
- register u_int32_t h;
-
-#define HASHC h = *key++ + 65599 * h
-
- h = 0;
- key = keyarg;
- if (len > 0) {
- loop = (len + 8 - 1) >> 3;
-
- switch (len & (8 - 1)) {
- case 0:
- do {
- HASHC;
- /* FALLTHROUGH */
- case 7:
- HASHC;
- /* FALLTHROUGH */
- case 6:
- HASHC;
- /* FALLTHROUGH */
- case 5:
- HASHC;
- /* FALLTHROUGH */
- case 4:
- HASHC;
- /* FALLTHROUGH */
- case 3:
- HASHC;
- /* FALLTHROUGH */
- case 2:
- HASHC;
- /* FALLTHROUGH */
- case 1:
- HASHC;
- } while (--loop);
- }
- }
- return (h);
-}
-#endif
-
-#ifdef HASH4_TOREK
-/* Hash function from Chris Torek. */
-static u_int32_t
-hashfunc(keyarg, len)
- const void *keyarg;
- register size_t len;
-{
- register const u_char *key;
- register size_t loop;
- register u_int32_t h;
-
-#define HASH4a h = (h << 5) - h + *key++;
-#define HASH4b h = (h << 5) + h + *key++;
-#define HASH4 HASH4b
-
- h = 0;
- key = keyarg;
- if (len > 0) {
- loop = (len + 8 - 1) >> 3;
-
- switch (len & (8 - 1)) {
- case 0:
- do {
- HASH4;
- /* FALLTHROUGH */
- case 7:
- HASH4;
- /* FALLTHROUGH */
- case 6:
- HASH4;
- /* FALLTHROUGH */
- case 5:
- HASH4;
- /* FALLTHROUGH */
- case 4:
- HASH4;
- /* FALLTHROUGH */
- case 3:
- HASH4;
- /* FALLTHROUGH */
- case 2:
- HASH4;
- /* FALLTHROUGH */
- case 1:
- HASH4;
- } while (--loop);
- }
- }
- return (h);
-}
-#endif
diff --git a/main/db1-ast/hash/hash_log2.c b/main/db1-ast/hash/hash_log2.c
deleted file mode 100644
index b86655d47..000000000
--- a/main/db1-ast/hash/hash_log2.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include "../include/db.h"
-
-u_int32_t __hash_log2 __P((u_int32_t));
-
-u_int32_t
-__hash_log2(num)
- u_int32_t num;
-{
- register u_int32_t i, limit;
-
- limit = 1;
- for (i = 0; limit < num; limit = limit << 1, i++);
- return (i);
-}
diff --git a/main/db1-ast/hash/hash_page.c b/main/db1-ast/hash/hash_page.c
deleted file mode 100644
index 52571c552..000000000
--- a/main/db1-ast/hash/hash_page.c
+++ /dev/null
@@ -1,946 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94";
-#endif /* LIBC_SCCS and not lint */
-
-/*
- * PACKAGE: hashing
- *
- * DESCRIPTION:
- * Page manipulation for hashing package.
- *
- * ROUTINES:
- *
- * External
- * __get_page
- * __add_ovflpage
- * Internal
- * overflow_page
- * open_temp
- */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#ifdef DEBUG
-#include <assert.h>
-#endif
-
-#include "../include/db.h"
-#include "hash.h"
-#include "page.h"
-#include "extern.h"
-
-static u_int32_t *fetch_bitmap __P((HTAB *, int));
-static u_int32_t first_free __P((u_int32_t));
-static int open_temp __P((HTAB *));
-static u_int16_t overflow_page __P((HTAB *));
-static void putpair __P((char *, const DBT *, const DBT *));
-static void squeeze_key __P((u_int16_t *, const DBT *, const DBT *));
-static int ugly_split
- __P((HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int));
-
-#define PAGE_INIT(P) { \
- ((u_int16_t *)(P))[0] = 0; \
- ((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \
- ((u_int16_t *)(P))[2] = hashp->BSIZE; \
-}
-
-/*
- * This is called AFTER we have verified that there is room on the page for
- * the pair (PAIRFITS has returned true) so we go right ahead and start moving
- * stuff on.
- */
-static void
-putpair(p, key, val)
- char *p;
- const DBT *key, *val;
-{
- register u_int16_t *bp, n, off;
-
- bp = (u_int16_t *)p;
-
- /* Enter the key first. */
- n = bp[0];
-
- off = OFFSET(bp) - key->size;
- memmove(p + off, key->data, key->size);
- bp[++n] = off;
-
- /* Now the data. */
- off -= val->size;
- memmove(p + off, val->data, val->size);
- bp[++n] = off;
-
- /* Adjust page info. */
- bp[0] = n;
- bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t));
- bp[n + 2] = off;
-}
-
-/*
- * Returns:
- * 0 OK
- * -1 error
- */
-extern int
-__delpair(hashp, bufp, ndx)
- HTAB *hashp;
- BUFHEAD *bufp;
- register int ndx;
-{
- register u_int16_t *bp, newoff;
- register int n;
- u_int16_t pairlen;
-
- bp = (u_int16_t *)bufp->page;
- n = bp[0];
-
- if (bp[ndx + 1] < REAL_KEY)
- return (__big_delete(hashp, bufp));
- if (ndx != 1)
- newoff = bp[ndx - 1];
- else
- newoff = hashp->BSIZE;
- pairlen = newoff - bp[ndx + 1];
-
- if (ndx != (n - 1)) {
- /* Hard Case -- need to shuffle keys */
- register int i;
- register char *src = bufp->page + (int)OFFSET(bp);
- register char *dst = src + (int)pairlen;
- memmove(dst, src, bp[ndx + 1] - OFFSET(bp));
-
- /* Now adjust the pointers */
- for (i = ndx + 2; i <= n; i += 2) {
- if (bp[i + 1] == OVFLPAGE) {
- bp[i - 2] = bp[i];
- bp[i - 1] = bp[i + 1];
- } else {
- bp[i - 2] = bp[i] + pairlen;
- bp[i - 1] = bp[i + 1] + pairlen;
- }
- }
- }
- /* Finally adjust the page data */
- bp[n] = OFFSET(bp) + pairlen;
- bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t);
- bp[0] = n - 2;
- hashp->NKEYS--;
-
- bufp->flags |= BUF_MOD;
- return (0);
-}
-/*
- * Returns:
- * 0 ==> OK
- * -1 ==> Error
- */
-extern int
-__split_page(hashp, obucket, nbucket)
- HTAB *hashp;
- u_int32_t obucket, nbucket;
-{
- register BUFHEAD *new_bufp, *old_bufp;
- register u_int16_t *ino;
- register char *np;
- DBT key, val;
- int n, ndx, retval;
- u_int16_t copyto, diff, off, moved;
- char *op;
-
- copyto = (u_int16_t)hashp->BSIZE;
- off = (u_int16_t)hashp->BSIZE;
- old_bufp = __get_buf(hashp, obucket, NULL, 0);
- if (old_bufp == NULL)
- return (-1);
- new_bufp = __get_buf(hashp, nbucket, NULL, 0);
- if (new_bufp == NULL)
- return (-1);
-
- old_bufp->flags |= (BUF_MOD | BUF_PIN);
- new_bufp->flags |= (BUF_MOD | BUF_PIN);
-
- ino = (u_int16_t *)(op = old_bufp->page);
- np = new_bufp->page;
-
- moved = 0;
-
- for (n = 1, ndx = 1; n < ino[0]; n += 2) {
- if (ino[n + 1] < REAL_KEY) {
- retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
- (int)copyto, (int)moved);
- old_bufp->flags &= ~BUF_PIN;
- new_bufp->flags &= ~BUF_PIN;
- return (retval);
-
- }
- key.data = (u_char *)op + ino[n];
- key.size = off - ino[n];
-
- if (__call_hash(hashp, key.data, key.size) == obucket) {
- /* Don't switch page */
- diff = copyto - off;
- if (diff) {
- copyto = ino[n + 1] + diff;
- memmove(op + copyto, op + ino[n + 1],
- off - ino[n + 1]);
- ino[ndx] = copyto + ino[n] - ino[n + 1];
- ino[ndx + 1] = copyto;
- } else
- copyto = ino[n + 1];
- ndx += 2;
- } else {
- /* Switch page */
- val.data = (u_char *)op + ino[n + 1];
- val.size = ino[n] - ino[n + 1];
- putpair(np, &key, &val);
- moved += 2;
- }
-
- off = ino[n + 1];
- }
-
- /* Now clean up the page */
- ino[0] -= moved;
- FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3);
- OFFSET(ino) = copyto;
-
-#ifdef DEBUG3
- (void)fprintf(stderr, "split %d/%d\n",
- ((u_int16_t *)np)[0] / 2,
- ((u_int16_t *)op)[0] / 2);
-#endif
- /* unpin both pages */
- old_bufp->flags &= ~BUF_PIN;
- new_bufp->flags &= ~BUF_PIN;
- return (0);
-}
-
-/*
- * Called when we encounter an overflow or big key/data page during split
- * handling. This is special cased since we have to begin checking whether
- * the key/data pairs fit on their respective pages and because we may need
- * overflow pages for both the old and new pages.
- *
- * The first page might be a page with regular key/data pairs in which case
- * we have a regular overflow condition and just need to go on to the next
- * page or it might be a big key/data pair in which case we need to fix the
- * big key/data pair.
- *
- * Returns:
- * 0 ==> success
- * -1 ==> failure
- */
-static int
-ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
- HTAB *hashp;
- u_int32_t obucket; /* Same as __split_page. */
- BUFHEAD *old_bufp, *new_bufp;
- int copyto; /* First byte on page which contains key/data values. */
- int moved; /* Number of pairs moved to new page. */
-{
- register BUFHEAD *bufp; /* Buffer header for ino */
- register u_int16_t *ino; /* Page keys come off of */
- register u_int16_t *np; /* New page */
- register u_int16_t *op; /* Page keys go on to if they aren't moving */
-
- BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */
- DBT key, val;
- SPLIT_RETURN ret;
- u_int16_t n, off, ov_addr, scopyto;
- char *cino; /* Character value of ino */
-
- bufp = old_bufp;
- ino = (u_int16_t *)old_bufp->page;
- np = (u_int16_t *)new_bufp->page;
- op = (u_int16_t *)old_bufp->page;
- last_bfp = NULL;
- scopyto = (u_int16_t)copyto; /* ANSI */
-
- n = ino[0] - 1;
- while (n < ino[0]) {
- if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
- if (__big_split(hashp, old_bufp,
- new_bufp, bufp, bufp->addr, obucket, &ret))
- return (-1);
- old_bufp = ret.oldp;
- if (!old_bufp)
- return (-1);
- op = (u_int16_t *)old_bufp->page;
- new_bufp = ret.newp;
- if (!new_bufp)
- return (-1);
- np = (u_int16_t *)new_bufp->page;
- bufp = ret.nextp;
- if (!bufp)
- return (0);
- cino = (char *)bufp->page;
- ino = (u_int16_t *)cino;
- last_bfp = ret.nextp;
- } else if (ino[n + 1] == OVFLPAGE) {
- ov_addr = ino[n];
- /*
- * Fix up the old page -- the extra 2 are the fields
- * which contained the overflow information.
- */
- ino[0] -= (moved + 2);
- FREESPACE(ino) =
- scopyto - sizeof(u_int16_t) * (ino[0] + 3);
- OFFSET(ino) = scopyto;
-
- bufp = __get_buf(hashp, ov_addr, bufp, 0);
- if (!bufp)
- return (-1);
-
- ino = (u_int16_t *)bufp->page;
- n = 1;
- scopyto = hashp->BSIZE;
- moved = 0;
-
- if (last_bfp)
- __free_ovflpage(hashp, last_bfp);
- last_bfp = bufp;
- }
- /* Move regular sized pairs of there are any */
- off = hashp->BSIZE;
- for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
- cino = (char *)ino;
- key.data = (u_char *)cino + ino[n];
- key.size = off - ino[n];
- val.data = (u_char *)cino + ino[n + 1];
- val.size = ino[n] - ino[n + 1];
- off = ino[n + 1];
-
- if (__call_hash(hashp, key.data, key.size) == obucket) {
- /* Keep on old page */
- if (PAIRFITS(op, (&key), (&val)))
- putpair((char *)op, &key, &val);
- else {
- old_bufp =
- __add_ovflpage(hashp, old_bufp);
- if (!old_bufp)
- return (-1);
- op = (u_int16_t *)old_bufp->page;
- putpair((char *)op, &key, &val);
- }
- old_bufp->flags |= BUF_MOD;
- } else {
- /* Move to new page */
- if (PAIRFITS(np, (&key), (&val)))
- putpair((char *)np, &key, &val);
- else {
- new_bufp =
- __add_ovflpage(hashp, new_bufp);
- if (!new_bufp)
- return (-1);
- np = (u_int16_t *)new_bufp->page;
- putpair((char *)np, &key, &val);
- }
- new_bufp->flags |= BUF_MOD;
- }
- }
- }
- if (last_bfp)
- __free_ovflpage(hashp, last_bfp);
- return (0);
-}
-
-/*
- * Add the given pair to the page
- *
- * Returns:
- * 0 ==> OK
- * 1 ==> failure
- */
-extern int
-__addel(hashp, bufp, key, val)
- HTAB *hashp;
- BUFHEAD *bufp;
- const DBT *key, *val;
-{
- register u_int16_t *bp, *sop;
- int do_expand;
-
- bp = (u_int16_t *)bufp->page;
- do_expand = 0;
- while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
- /* Exception case */
- if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
- /* This is the last page of a big key/data pair
- and we need to add another page */
- break;
- else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
- bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
- if (!bufp)
- return (-1);
- bp = (u_int16_t *)bufp->page;
- } else
- /* Try to squeeze key on this page */
- if (FREESPACE(bp) > PAIRSIZE(key, val)) {
- squeeze_key(bp, key, val);
- return (0);
- } else {
- bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
- if (!bufp)
- return (-1);
- bp = (u_int16_t *)bufp->page;
- }
-
- if (PAIRFITS(bp, key, val))
- putpair(bufp->page, key, val);
- else {
- do_expand = 1;
- bufp = __add_ovflpage(hashp, bufp);
- if (!bufp)
- return (-1);
- sop = (u_int16_t *)bufp->page;
-
- if (PAIRFITS(sop, key, val))
- putpair((char *)sop, key, val);
- else
- if (__big_insert(hashp, bufp, key, val))
- return (-1);
- }
- bufp->flags |= BUF_MOD;
- /*
- * If the average number of keys per bucket exceeds the fill factor,
- * expand the table.
- */
- hashp->NKEYS++;
- if (do_expand ||
- (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
- return (__expand_table(hashp));
- return (0);
-}
-
-/*
- *
- * Returns:
- * pointer on success
- * NULL on error
- */
-extern BUFHEAD *
-__add_ovflpage(hashp, bufp)
- HTAB *hashp;
- BUFHEAD *bufp;
-{
- register u_int16_t *sp;
- u_int16_t ndx, ovfl_num;
-#ifdef DEBUG1
- int tmp1, tmp2;
-#endif
- sp = (u_int16_t *)bufp->page;
-
- /* Check if we are dynamically determining the fill factor */
- if (hashp->FFACTOR == DEF_FFACTOR) {
- hashp->FFACTOR = sp[0] >> 1;
- if (hashp->FFACTOR < MIN_FFACTOR)
- hashp->FFACTOR = MIN_FFACTOR;
- }
- bufp->flags |= BUF_MOD;
- ovfl_num = overflow_page(hashp);
-#ifdef DEBUG1
- tmp1 = bufp->addr;
- tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
-#endif
- if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))
- return (NULL);
- bufp->ovfl->flags |= BUF_MOD;
-#ifdef DEBUG1
- (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
- tmp1, tmp2, bufp->ovfl->addr);
-#endif
- ndx = sp[0];
- /*
- * Since a pair is allocated on a page only if there's room to add
- * an overflow page, we know that the OVFL information will fit on
- * the page.
- */
- sp[ndx + 4] = OFFSET(sp);
- sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
- sp[ndx + 1] = ovfl_num;
- sp[ndx + 2] = OVFLPAGE;
- sp[0] = ndx + 2;
-#ifdef HASH_STATISTICS
- hash_overflows++;
-#endif
- return (bufp->ovfl);
-}
-
-/*
- * Returns:
- * 0 indicates SUCCESS
- * -1 indicates FAILURE
- */
-extern int
-__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
- HTAB *hashp;
- char *p;
- u_int32_t bucket;
- int is_bucket, is_disk, is_bitmap;
-{
- register int fd, page, size;
- int rsize;
- u_int16_t *bp;
-
- fd = hashp->fp;
- size = hashp->BSIZE;
-
- if ((fd == -1) || !is_disk) {
- PAGE_INIT(p);
- return (0);
- }
- if (is_bucket)
- page = BUCKET_TO_PAGE(bucket);
- else
- page = OADDR_TO_PAGE(bucket);
- if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
- ((rsize = read(fd, p, size)) == -1))
- return (-1);
- bp = (u_int16_t *)p;
- if (!rsize)
- bp[0] = 0; /* We hit the EOF, so initialize a new page */
- else
- if (rsize != size) {
- errno = EFTYPE;
- return (-1);
- }
- if (!is_bitmap && !bp[0]) {
- PAGE_INIT(p);
- } else
- if (hashp->LORDER != BYTE_ORDER) {
- register int i, max;
-
- if (is_bitmap) {
- max = hashp->BSIZE >> 2; /* divide by 4 */
- for (i = 0; i < max; i++)
- M_32_SWAP(((int *)p)[i]);
- } else {
- M_16_SWAP(bp[0]);
- max = bp[0] + 2;
- for (i = 1; i <= max; i++)
- M_16_SWAP(bp[i]);
- }
- }
- return (0);
-}
-
-/*
- * Write page p to disk
- *
- * Returns:
- * 0 ==> OK
- * -1 ==>failure
- */
-extern int
-__put_page(hashp, p, bucket, is_bucket, is_bitmap)
- HTAB *hashp;
- char *p;
- u_int32_t bucket;
- int is_bucket, is_bitmap;
-{
- register int fd, page, size;
- int wsize;
-
- size = hashp->BSIZE;
- if ((hashp->fp == -1) && open_temp(hashp))
- return (-1);
- fd = hashp->fp;
-
- if (hashp->LORDER != BYTE_ORDER) {
- register int i;
- register int max;
-
- if (is_bitmap) {
- max = hashp->BSIZE >> 2; /* divide by 4 */
- for (i = 0; i < max; i++)
- M_32_SWAP(((int *)p)[i]);
- } else {
- max = ((u_int16_t *)p)[0] + 2;
- for (i = 0; i <= max; i++)
- M_16_SWAP(((u_int16_t *)p)[i]);
- }
- }
- if (is_bucket)
- page = BUCKET_TO_PAGE(bucket);
- else
- page = OADDR_TO_PAGE(bucket);
- if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
- ((wsize = write(fd, p, size)) == -1))
- /* Errno is set */
- return (-1);
- if (wsize != size) {
- errno = EFTYPE;
- return (-1);
- }
- return (0);
-}
-
-#define BYTE_MASK ((1 << INT_BYTE_SHIFT) -1)
-/*
- * Initialize a new bitmap page. Bitmap pages are left in memory
- * once they are read in.
- */
-extern int
-__ibitmap(hashp, pnum, nbits, ndx)
- HTAB *hashp;
- int pnum, nbits, ndx;
-{
- u_int32_t *ip;
- int clearbytes, clearints;
-
- if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
- return (1);
- hashp->nmaps++;
- clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
- clearbytes = clearints << INT_TO_BYTE;
- (void)memset((char *)ip, 0, clearbytes);
- (void)memset(((char *)ip) + clearbytes, 0xFF,
- hashp->BSIZE - clearbytes);
- ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
- SETBIT(ip, 0);
- hashp->BITMAPS[ndx] = (u_int16_t)pnum;
- hashp->mapp[ndx] = ip;
- return (0);
-}
-
-static u_int32_t
-first_free(map)
- u_int32_t map;
-{
- register u_int32_t i, mask;
-
- mask = 0x1;
- for (i = 0; i < BITS_PER_MAP; i++) {
- if (!(mask & map))
- return (i);
- mask = mask << 1;
- }
- return (i);
-}
-
-static u_int16_t
-overflow_page(hashp)
- HTAB *hashp;
-{
- register u_int32_t *freep = 0;
- register int max_free, offset, splitnum;
- u_int16_t addr;
- int bit, first_page, free_bit, free_page, i, in_use_bits, j;
-#ifdef DEBUG2
- int tmp1, tmp2;
-#endif
- splitnum = hashp->OVFL_POINT;
- max_free = hashp->SPARES[splitnum];
-
- free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
- free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
-
- /* Look through all the free maps to find the first free block */
- first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);
- for ( i = first_page; i <= free_page; i++ ) {
- if (!(freep = (u_int32_t *)hashp->mapp[i]) &&
- !(freep = fetch_bitmap(hashp, i)))
- return (0);
- if (i == free_page)
- in_use_bits = free_bit;
- else
- in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
-
- if (i == first_page) {
- bit = hashp->LAST_FREED &
- ((hashp->BSIZE << BYTE_SHIFT) - 1);
- j = bit / BITS_PER_MAP;
- bit = bit & ~(BITS_PER_MAP - 1);
- } else {
- bit = 0;
- j = 0;
- }
- for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
- if (freep[j] != ALL_SET)
- goto found;
- }
-
- /* No Free Page Found */
- hashp->LAST_FREED = hashp->SPARES[splitnum];
- hashp->SPARES[splitnum]++;
- offset = hashp->SPARES[splitnum] -
- (splitnum ? hashp->SPARES[splitnum - 1] : 0);
-
-#define OVMSG "HASH: Out of overflow pages. Increase page size\n"
- if (offset > SPLITMASK) {
- if (++splitnum >= NCACHED) {
- if (write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1) < 0) {
- }
- return (0);
- }
- hashp->OVFL_POINT = splitnum;
- hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
- hashp->SPARES[splitnum-1]--;
- offset = 1;
- }
-
- /* Check if we need to allocate a new bitmap page */
- if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
- free_page++;
- if (free_page >= NCACHED) {
- if (write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1) < 0) {
- }
- return (0);
- }
- /*
- * This is tricky. The 1 indicates that you want the new page
- * allocated with 1 clear bit. Actually, you are going to
- * allocate 2 pages from this map. The first is going to be
- * the map page, the second is the overflow page we were
- * looking for. The init_bitmap routine automatically, sets
- * the first bit of itself to indicate that the bitmap itself
- * is in use. We would explicitly set the second bit, but
- * don't have to if we tell init_bitmap not to leave it clear
- * in the first place.
- */
- if (__ibitmap(hashp,
- (int)OADDR_OF(splitnum, offset), 1, free_page))
- return (0);
- hashp->SPARES[splitnum]++;
-#ifdef DEBUG2
- free_bit = 2;
-#endif
- offset++;
- if (offset > SPLITMASK) {
- if (++splitnum >= NCACHED) {
- if (write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1) < 0) {
- }
- return (0);
- }
- hashp->OVFL_POINT = splitnum;
- hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
- hashp->SPARES[splitnum-1]--;
- offset = 0;
- }
- } else {
- /*
- * Free_bit addresses the last used bit. Bump it to address
- * the first available bit.
- */
- free_bit++;
- SETBIT(freep, free_bit);
- }
-
- /* Calculate address of the new overflow page */
- addr = OADDR_OF(splitnum, offset);
-#ifdef DEBUG2
- (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
- addr, free_bit, free_page);
-#endif
- return (addr);
-
-found:
- bit = bit + first_free(freep[j]);
- SETBIT(freep, bit);
-#ifdef DEBUG2
- tmp1 = bit;
- tmp2 = i;
-#endif
- /*
- * Bits are addressed starting with 0, but overflow pages are addressed
- * beginning at 1. Bit is a bit addressnumber, so we need to increment
- * it to convert it to a page number.
- */
- bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
- if (bit >= hashp->LAST_FREED)
- hashp->LAST_FREED = bit - 1;
-
- /* Calculate the split number for this page */
- for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
- offset = (i ? bit - hashp->SPARES[i - 1] : bit);
- if (offset >= SPLITMASK)
- return (0); /* Out of overflow pages */
- addr = OADDR_OF(i, offset);
-#ifdef DEBUG2
- (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
- addr, tmp1, tmp2);
-#endif
-
- /* Allocate and return the overflow page */
- return (addr);
-}
-
-/*
- * Mark this overflow page as free.
- */
-extern void
-__free_ovflpage(hashp, obufp)
- HTAB *hashp;
- BUFHEAD *obufp;
-{
- register u_int16_t addr;
- u_int32_t *freep;
- int bit_address, free_page, free_bit;
- u_int16_t ndx;
-
- addr = obufp->addr;
-#ifdef DEBUG1
- (void)fprintf(stderr, "Freeing %d\n", addr);
-#endif
- ndx = (((u_int16_t)addr) >> SPLITSHIFT);
- bit_address =
- (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
- if (bit_address < hashp->LAST_FREED)
- hashp->LAST_FREED = bit_address;
- free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
- free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
-
- if (!(freep = hashp->mapp[free_page]))
- freep = fetch_bitmap(hashp, free_page);
-#ifdef DEBUG
- /*
- * This had better never happen. It means we tried to read a bitmap
- * that has already had overflow pages allocated off it, and we
- * failed to read it from the file.
- */
- if (!freep)
- assert(0);
-#endif
- CLRBIT(freep, free_bit);
-#ifdef DEBUG2
- (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
- obufp->addr, free_bit, free_page);
-#endif
- __reclaim_buf(hashp, obufp);
-}
-
-/*
- * Returns:
- * 0 success
- * -1 failure
- */
-static int
-open_temp(hashp)
- HTAB *hashp;
-{
- sigset_t set, oset;
- static char namestr[] = "_hashXXXXXX";
-
- /* Block signals; make sure file goes away at process exit. */
- (void)sigfillset(&set);
- (void)sigprocmask(SIG_BLOCK, &set, &oset);
- if ((hashp->fp = mkstemp(namestr)) != -1) {
- (void)unlink(namestr);
- (void)fcntl(hashp->fp, F_SETFD, 1);
- }
- (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
- return (hashp->fp != -1 ? 0 : -1);
-}
-
-/*
- * We have to know that the key will fit, but the last entry on the page is
- * an overflow pair, so we need to shift things.
- */
-static void
-squeeze_key(sp, key, val)
- u_int16_t *sp;
- const DBT *key, *val;
-{
- register char *p;
- u_int16_t free_space, n, off, pageno;
-
- p = (char *)sp;
- n = sp[0];
- free_space = FREESPACE(sp);
- off = OFFSET(sp);
-
- pageno = sp[n - 1];
- off -= key->size;
- sp[n - 1] = off;
- memmove(p + off, key->data, key->size);
- off -= val->size;
- sp[n] = off;
- memmove(p + off, val->data, val->size);
- sp[0] = n + 2;
- sp[n + 1] = pageno;
- sp[n + 2] = OVFLPAGE;
- FREESPACE(sp) = free_space - PAIRSIZE(key, val);
- OFFSET(sp) = off;
-}
-
-static u_int32_t *
-fetch_bitmap(hashp, ndx)
- HTAB *hashp;
- int ndx;
-{
- if (ndx >= hashp->nmaps)
- return (NULL);
- if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
- return (NULL);
- if (__get_page(hashp,
- (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) {
- free(hashp->mapp[ndx]);
- return (NULL);
- }
- return (hashp->mapp[ndx]);
-}
-
-#ifdef DEBUG4
-int
-print_chain(addr)
- int addr;
-{
- BUFHEAD *bufp;
- short *bp, oaddr;
-
- (void)fprintf(stderr, "%d ", addr);
- bufp = __get_buf(hashp, addr, NULL, 0);
- bp = (short *)bufp->page;
- while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
- ((bp[0] > 2) && bp[2] < REAL_KEY))) {
- oaddr = bp[bp[0] - 1];
- (void)fprintf(stderr, "%d ", (int)oaddr);
- bufp = __get_buf(hashp, (int)oaddr, bufp, 0);
- bp = (short *)bufp->page;
- }
- (void)fprintf(stderr, "\n");
-}
-#endif
diff --git a/main/db1-ast/hash/hsearch.c b/main/db1-ast/hash/hsearch.c
deleted file mode 100644
index 2971f9308..000000000
--- a/main/db1-ast/hash/hsearch.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)hsearch.c 8.4 (Berkeley) 7/21/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <fcntl.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "search.h"
-
-static DB *dbp = NULL;
-static ENTRY retval;
-
-extern int
-hcreate(nel)
- u_int nel;
-{
- HASHINFO info;
-
- info.nelem = nel;
- info.bsize = 256;
- info.ffactor = 8;
- info.cachesize = 0;
- info.hash = NULL;
- info.lorder = 0;
- dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0);
- return ((int)dbp);
-}
-
-extern ENTRY *
-hsearch(item, action)
- ENTRY item;
- ACTION action;
-{
- DBT key, val;
- int status;
-
- if (!dbp)
- return (NULL);
- key.data = (u_char *)item.key;
- key.size = strlen(item.key) + 1;
-
- if (action == ENTER) {
- val.data = (u_char *)item.data;
- val.size = strlen(item.data) + 1;
- status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE);
- if (status)
- return (NULL);
- } else {
- /* FIND */
- status = (dbp->get)(dbp, &key, &val, 0);
- if (status)
- return (NULL);
- else
- item.data = (char *)val.data;
- }
- retval.key = item.key;
- retval.data = item.data;
- return (&retval);
-}
-
-extern void
-hdestroy()
-{
- if (dbp) {
- (void)(dbp->close)(dbp);
- dbp = NULL;
- }
-}
diff --git a/main/db1-ast/hash/ndbm.c b/main/db1-ast/hash/ndbm.c
deleted file mode 100644
index d702f737a..000000000
--- a/main/db1-ast/hash/ndbm.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94";
-#endif /* LIBC_SCCS and not lint */
-
-/*
- * This package provides a dbm compatible interface to the new hashing
- * package described in db(3).
- */
-
-#include <sys/param.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <ndbm.h>
-#include "hash.h"
-
-/*
- * Returns:
- * *DBM on success
- * NULL on failure
- */
-extern DBM *
-dbm_open(file, flags, mode)
- const char *file;
- int flags, mode;
-{
- DBM *db;
- HASHINFO info;
- const size_t len = strlen(file) + sizeof (DBM_SUFFIX);
-#ifdef __GNUC__
- char path[len];
-#else
- char *path = malloc(len);
- if (path == NULL)
- return NULL;
-#endif
-
- info.bsize = 4096;
- info.ffactor = 40;
- info.nelem = 1;
- info.cachesize = 0;
- info.hash = NULL;
- info.lorder = 0;
- (void)strncpy(path, file, len - 1);
- (void)strncat(path, DBM_SUFFIX, len - strlen(path) - 1);
- db = (DBM *)__hash_open(path, flags, mode, &info, 0);
-#ifndef __GNUC__
- free(path);
-#endif
- return db;
-}
-
-extern void
-dbm_close(db)
- DBM *db;
-{
- (void)(db->close)(db);
-}
-
-/*
- * Returns:
- * DATUM on success
- * NULL on failure
- */
-extern datum
-dbm_fetch(db, key)
- DBM *db;
- datum key;
-{
- datum retdata;
- int status;
- DBT dbtkey, dbtretdata;
-
- dbtkey.data = key.dptr;
- dbtkey.size = key.dsize;
- status = (db->get)(db, &dbtkey, &dbtretdata, 0);
- if (status) {
- dbtretdata.data = NULL;
- dbtretdata.size = 0;
- }
- retdata.dptr = dbtretdata.data;
- retdata.dsize = dbtretdata.size;
- return (retdata);
-}
-
-/*
- * Returns:
- * DATUM on success
- * NULL on failure
- */
-extern datum
-dbm_firstkey(db)
- DBM *db;
-{
- int status;
- datum retkey;
- DBT dbtretkey, dbtretdata;
-
- status = (db->seq)(db, &dbtretkey, &dbtretdata, R_FIRST);
- if (status)
- dbtretkey.data = NULL;
- retkey.dptr = dbtretkey.data;
- retkey.dsize = dbtretkey.size;
- return (retkey);
-}
-
-/*
- * Returns:
- * DATUM on success
- * NULL on failure
- */
-extern datum
-dbm_nextkey(db)
- DBM *db;
-{
- int status;
- datum retkey;
- DBT dbtretkey, dbtretdata;
-
- status = (db->seq)(db, &dbtretkey, &dbtretdata, R_NEXT);
- if (status)
- dbtretkey.data = NULL;
- retkey.dptr = dbtretkey.data;
- retkey.dsize = dbtretkey.size;
- return (retkey);
-}
-/*
- * Returns:
- * 0 on success
- * <0 failure
- */
-extern int
-dbm_delete(db, key)
- DBM *db;
- datum key;
-{
- int status;
- DBT dbtkey;
-
- dbtkey.data = key.dptr;
- dbtkey.size = key.dsize;
- status = (db->del)(db, &dbtkey, 0);
- if (status)
- return (-1);
- else
- return (0);
-}
-
-/*
- * Returns:
- * 0 on success
- * <0 failure
- * 1 if DBM_INSERT and entry exists
- */
-extern int
-dbm_store(db, key, data, flags)
- DBM *db;
- datum key, data;
- int flags;
-{
- DBT dbtkey, dbtdata;
-
- dbtkey.data = key.dptr;
- dbtkey.size = key.dsize;
- dbtdata.data = data.dptr;
- dbtdata.size = data.dsize;
- return ((db->put)(db, &dbtkey, &dbtdata,
- (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
-}
-
-extern int
-dbm_error(db)
- DBM *db;
-{
- HTAB *hp;
-
- hp = (HTAB *)db->internal;
- return (hp->errnum);
-}
-
-extern int
-dbm_clearerr(db)
- DBM *db;
-{
- HTAB *hp;
-
- hp = (HTAB *)db->internal;
- hp->errnum = 0;
- return (0);
-}
-
-extern int
-dbm_dirfno(db)
- DBM *db;
-{
- return(((HTAB *)db->internal)->fp);
-}
diff --git a/main/db1-ast/hash/page.h b/main/db1-ast/hash/page.h
deleted file mode 100644
index 0fc0d5a3e..000000000
--- a/main/db1-ast/hash/page.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)page.h 8.2 (Berkeley) 5/31/94
- */
-
-/*
- * Definitions for hashing page file format.
- */
-
-/*
- * routines dealing with a data page
- *
- * page format:
- * +------------------------------+
- * p | n | keyoff | datoff | keyoff |
- * +------------+--------+--------+
- * | datoff | free | ptr | --> |
- * +--------+---------------------+
- * | F R E E A R E A |
- * +--------------+---------------+
- * | <---- - - - | data |
- * +--------+-----+----+----------+
- * | key | data | key |
- * +--------+----------+----------+
- *
- * Pointer to the free space is always: p[p[0] + 2]
- * Amount of free space on the page is: p[p[0] + 1]
- */
-
-/*
- * How many bytes required for this pair?
- * 2 shorts in the table at the top of the page + room for the
- * key and room for the data
- *
- * We prohibit entering a pair on a page unless there is also room to append
- * an overflow page. The reason for this it that you can get in a situation
- * where a single key/data pair fits on a page, but you can't append an
- * overflow page and later you'd have to split the key/data and handle like
- * a big pair.
- * You might as well do this up front.
- */
-
-#define PAIRSIZE(K,D) (2*sizeof(u_int16_t) + (K)->size + (D)->size)
-#define BIGOVERHEAD (4*sizeof(u_int16_t))
-#define KEYSIZE(K) (4*sizeof(u_int16_t) + (K)->size);
-#define OVFLSIZE (2*sizeof(u_int16_t))
-#define FREESPACE(P) ((P)[(P)[0]+1])
-#define OFFSET(P) ((P)[(P)[0]+2])
-#define PAIRFITS(P,K,D) \
- (((P)[2] >= REAL_KEY) && \
- (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P)))
-#define PAGE_META(N) (((N)+3) * sizeof(u_int16_t))
-
-typedef struct {
- BUFHEAD *newp;
- BUFHEAD *oldp;
- BUFHEAD *nextp;
- u_int16_t next_addr;
-} SPLIT_RETURN;
diff --git a/main/db1-ast/hash/search.h b/main/db1-ast/hash/search.h
deleted file mode 100644
index 4d3b9143e..000000000
--- a/main/db1-ast/hash/search.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)search.h 8.1 (Berkeley) 6/4/93
- */
-
-/* Backward compatibility to hsearch interface. */
-typedef struct entry {
- char *key;
- char *data;
-} ENTRY;
-
-typedef enum {
- FIND, ENTER
-} ACTION;
-
-int hcreate __P((unsigned int));
-void hdestroy __P((void));
-ENTRY *hsearch __P((ENTRY, ACTION));
diff --git a/main/db1-ast/include/circ-queue.h b/main/db1-ast/include/circ-queue.h
deleted file mode 100644
index 33ba9115b..000000000
--- a/main/db1-ast/include/circ-queue.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- * $FreeBSD: ports/misc/44bsd-more/files/queue.h,v 1.1 2001/01/06 03:41:36 hoek Exp $
- */
-
-/*
- * Circular queue definitions.
- */
-#define CIRCLEQ_HEAD(name, type) \
-struct name { \
- struct type *cqh_first; /* first element */ \
- struct type *cqh_last; /* last element */ \
-}
-
-#define CIRCLEQ_ENTRY(type) \
-struct { \
- struct type *cqe_next; /* next element */ \
- struct type *cqe_prev; /* previous element */ \
-}
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
-
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-
-#define CIRCLEQ_FOREACH(var, head, field) \
- for((var) = (head)->cqh_first; \
- (var) != (void *)(head); \
- (var) = (var)->field.cqe_next)
-
-#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
- for((var) = (head)->cqh_last; \
- (var) != (void *)(head); \
- (var) = (var)->field.cqe_prev)
-
-#define CIRCLEQ_INIT(head) do { \
- (head)->cqh_first = (void *)(head); \
- (head)->cqh_last = (void *)(head); \
-} while (0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm)->field.cqe_next; \
- (elm)->field.cqe_prev = (listelm); \
- if ((listelm)->field.cqe_next == (void *)(head)) \
- (head)->cqh_last = (elm); \
- else \
- (listelm)->field.cqe_next->field.cqe_prev = (elm); \
- (listelm)->field.cqe_next = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm); \
- (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
- if ((listelm)->field.cqe_prev == (void *)(head)) \
- (head)->cqh_first = (elm); \
- else \
- (listelm)->field.cqe_prev->field.cqe_next = (elm); \
- (listelm)->field.cqe_prev = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.cqe_next = (head)->cqh_first; \
- (elm)->field.cqe_prev = (void *)(head); \
- if ((head)->cqh_last == (void *)(head)) \
- (head)->cqh_last = (elm); \
- else \
- (head)->cqh_first->field.cqe_prev = (elm); \
- (head)->cqh_first = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.cqe_next = (void *)(head); \
- (elm)->field.cqe_prev = (head)->cqh_last; \
- if ((head)->cqh_first == (void *)(head)) \
- (head)->cqh_first = (elm); \
- else \
- (head)->cqh_last->field.cqe_next = (elm); \
- (head)->cqh_last = (elm); \
-} while (0)
-
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-
-#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
-
-#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
-
-#define CIRCLEQ_REMOVE(head, elm, field) do { \
- if ((elm)->field.cqe_next == (void *)(head)) \
- (head)->cqh_last = (elm)->field.cqe_prev; \
- else \
- (elm)->field.cqe_next->field.cqe_prev = \
- (elm)->field.cqe_prev; \
- if ((elm)->field.cqe_prev == (void *)(head)) \
- (head)->cqh_first = (elm)->field.cqe_next; \
- else \
- (elm)->field.cqe_prev->field.cqe_next = \
- (elm)->field.cqe_next; \
-} while (0)
diff --git a/main/db1-ast/include/compat.h b/main/db1-ast/include/compat.h
deleted file mode 100644
index 706e58265..000000000
--- a/main/db1-ast/include/compat.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Values for building 4.4 BSD db routines in the GNU C library. */
-
-#ifndef _compat_h_
-#define _compat_h_
-
-#include <fcntl.h>
-
-/*
- * If you can't provide lock values in the open(2) call. Note, this
- * allows races to happen.
- */
-#ifndef O_EXLOCK /* 4.4BSD extension. */
-#define O_EXLOCK 0
-#endif
-
-#ifndef O_SHLOCK /* 4.4BSD extension. */
-#define O_SHLOCK 0
-#endif
-
-#include <errno.h>
-
-#ifndef EFTYPE
-#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */
-#endif
-
-#include <unistd.h>
-#include <limits.h>
-
-#ifndef _POSIX_VDISABLE /* POSIX 1003.1 disabling char. */
-#define _POSIX_VDISABLE 0 /* Some systems used 0. */
-#endif
-
-#include <termios.h>
-
-#ifndef TCSASOFT /* 4.4BSD extension. */
-#define TCSASOFT 0
-#endif
-
-#include <sys/param.h>
-
-#ifndef MAX /* Usually found in <sys/param.h>. */
-#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a))
-#endif
-#ifndef MIN /* Usually found in <sys/param.h>. */
-#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
-#endif
-
-
-#endif /* compat.h */
diff --git a/main/db1-ast/include/db.h b/main/db1-ast/include/db.h
deleted file mode 100644
index a58724bdd..000000000
--- a/main/db1-ast/include/db.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)db.h 8.7 (Berkeley) 6/16/94
- */
-
-#ifndef _DB_H
-#define _DB_H 1
-
-#include <sys/types.h>
-#include <sys/cdefs.h>
-
-#include <limits.h>
-
-#ifdef __DBINTERFACE_PRIVATE
-#include <compat.h>
-#endif
-
-#ifdef SOLARIS
-#include "solaris-compat/compat.h"
-#endif
-
-#define RET_ERROR -1 /* Return values. */
-#define RET_SUCCESS 0
-#define RET_SPECIAL 1
-
-#ifndef __BIT_TYPES_DEFINED__
-#define __BIT_TYPES_DEFINED__
-#if (!defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__APPLE__))
-typedef __signed char int8_t;
-typedef short int16_t;
-typedef int int32_t;
-typedef unsigned char u_int8_t;
-typedef unsigned short u_int16_t;
-typedef unsigned int u_int32_t;
-#ifdef WE_DONT_NEED_QUADS
-typedef long long int64_t;
-typedef unsigned long long u_int64_t;
-#endif
-#endif /* __FreeBSD__ */
-#endif
-
-#ifdef SOLARIS
-#define __P(p) p
-#define __BEGIN_DECLS
-#define __END_DECLS
-#endif
-
-#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */
-typedef u_int32_t pgno_t;
-#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */
-typedef u_int16_t indx_t;
-#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */
-typedef u_int32_t recno_t;
-
-/* Key/data structure -- a Data-Base Thang. */
-typedef struct {
- void *data; /* data */
- size_t size; /* data length */
-} DBT;
-
-/* Routine flags. */
-#define R_CURSOR 1 /* del, put, seq */
-#define __R_UNUSED 2 /* UNUSED */
-#define R_FIRST 3 /* seq */
-#define R_IAFTER 4 /* put (RECNO) */
-#define R_IBEFORE 5 /* put (RECNO) */
-#define R_LAST 6 /* seq (BTREE, RECNO) */
-#define R_NEXT 7 /* seq */
-#define R_NOOVERWRITE 8 /* put */
-#define R_PREV 9 /* seq (BTREE, RECNO) */
-#define R_SETCURSOR 10 /* put (RECNO) */
-#define R_RECNOSYNC 11 /* sync (RECNO) */
-
-typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
-
-/*
- * !!!
- * The following flags are included in the dbopen(3) call as part of the
- * open(2) flags. In order to avoid conflicts with the open flags, start
- * at the top of the 16 or 32-bit number space and work our way down. If
- * the open flags were significantly expanded in the future, it could be
- * a problem. Wish I'd left another flags word in the dbopen call.
- *
- * !!!
- * None of this stuff is implemented yet. The only reason that it's here
- * is so that the access methods can skip copying the key/data pair when
- * the DB_LOCK flag isn't set.
- */
-#if UINT_MAX > 65535
-#define DB_LOCK 0x20000000 /* Do locking. */
-#define DB_SHMEM 0x40000000 /* Use shared memory. */
-#define DB_TXN 0x80000000 /* Do transactions. */
-#else
-#define DB_LOCK 0x2000 /* Do locking. */
-#define DB_SHMEM 0x4000 /* Use shared memory. */
-#define DB_TXN 0x8000 /* Do transactions. */
-#endif
-
-/* Access method description structure. */
-typedef struct __db {
- DBTYPE type; /* Underlying db type. */
- int (*close) __P((struct __db *));
- int (*del) __P((const struct __db *, const DBT *, u_int));
- int (*get) __P((const struct __db *, const DBT *, DBT *, u_int));
- int (*put) __P((const struct __db *, DBT *, const DBT *, u_int));
- int (*seq) __P((const struct __db *, DBT *, DBT *, u_int));
- int (*sync) __P((const struct __db *, u_int));
- void *internal; /* Access method private. */
- int (*fd) __P((const struct __db *));
-} DB;
-
-#define BTREEMAGIC 0x053162
-#define BTREEVERSION 3
-
-/* Structure used to pass parameters to the btree routines. */
-typedef struct {
-#define R_DUP 0x01 /* duplicate keys */
- u_long flags;
- u_int cachesize; /* bytes to cache */
- int maxkeypage; /* maximum keys per page */
- int minkeypage; /* minimum keys per page */
- u_int psize; /* page size */
- int (*compare) /* comparison function */
- __P((const DBT *, const DBT *));
- size_t (*prefix) /* prefix function */
- __P((const DBT *, const DBT *));
- int lorder; /* byte order */
-} BTREEINFO;
-
-#define HASHMAGIC 0x061561
-#define HASHVERSION 2
-
-/* Structure used to pass parameters to the hashing routines. */
-typedef struct {
- u_int bsize; /* bucket size */
- u_int ffactor; /* fill factor */
- u_int nelem; /* number of elements */
- u_int cachesize; /* bytes to cache */
- u_int32_t /* hash function */
- (*hash) __P((const void *, size_t));
- int lorder; /* byte order */
-} HASHINFO;
-
-/* Structure used to pass parameters to the record routines. */
-typedef struct {
-#define R_FIXEDLEN 0x01 /* fixed-length records */
-#define R_NOKEY 0x02 /* key not required */
-#define R_SNAPSHOT 0x04 /* snapshot the input */
- u_long flags;
- u_int cachesize; /* bytes to cache */
- u_int psize; /* page size */
- int lorder; /* byte order */
- size_t reclen; /* record length (fixed-length records) */
- u_char bval; /* delimiting byte (variable-length records */
- char *bfname; /* btree file name */
-} RECNOINFO;
-
-#ifdef __DBINTERFACE_PRIVATE
-/*
- * Little endian <==> big endian 32-bit swap macros.
- * M_32_SWAP swap a memory location
- * P_32_SWAP swap a referenced memory location
- * P_32_COPY swap from one location to another
- */
-#define M_32_SWAP(a) { \
- u_int32_t _tmp = a; \
- ((char *)&a)[0] = ((char *)&_tmp)[3]; \
- ((char *)&a)[1] = ((char *)&_tmp)[2]; \
- ((char *)&a)[2] = ((char *)&_tmp)[1]; \
- ((char *)&a)[3] = ((char *)&_tmp)[0]; \
-}
-#define P_32_SWAP(a) { \
- u_int32_t _tmp = *(u_int32_t *)a; \
- ((char *)a)[0] = ((char *)&_tmp)[3]; \
- ((char *)a)[1] = ((char *)&_tmp)[2]; \
- ((char *)a)[2] = ((char *)&_tmp)[1]; \
- ((char *)a)[3] = ((char *)&_tmp)[0]; \
-}
-#define P_32_COPY(a, b) { \
- ((char *)&(b))[0] = ((char *)&(a))[3]; \
- ((char *)&(b))[1] = ((char *)&(a))[2]; \
- ((char *)&(b))[2] = ((char *)&(a))[1]; \
- ((char *)&(b))[3] = ((char *)&(a))[0]; \
-}
-
-/*
- * Little endian <==> big endian 16-bit swap macros.
- * M_16_SWAP swap a memory location
- * P_16_SWAP swap a referenced memory location
- * P_16_COPY swap from one location to another
- */
-#define M_16_SWAP(a) { \
- u_int16_t _tmp = a; \
- ((char *)&a)[0] = ((char *)&_tmp)[1]; \
- ((char *)&a)[1] = ((char *)&_tmp)[0]; \
-}
-#define P_16_SWAP(a) { \
- u_int16_t _tmp = *(u_int16_t *)a; \
- ((char *)a)[0] = ((char *)&_tmp)[1]; \
- ((char *)a)[1] = ((char *)&_tmp)[0]; \
-}
-#define P_16_COPY(a, b) { \
- ((char *)&(b))[0] = ((char *)&(a))[1]; \
- ((char *)&(b))[1] = ((char *)&(a))[0]; \
-}
-#endif
-
-__BEGIN_DECLS
-DB *__dbopen __P((const char *, int, int, DBTYPE, const void *));
-DB *dbopen __P((const char *, int, int, DBTYPE, const void *));
-
-#ifdef __DBINTERFACE_PRIVATE
-DB *__bt_open __P((const char *, int, int, const BTREEINFO *, int));
-DB *__hash_open __P((const char *, int, int, const HASHINFO *, int));
-DB *__rec_open __P((const char *, int, int, const RECNOINFO *, int));
-void __dbpanic __P((DB *dbp));
-#endif
-__END_DECLS
-
-#endif /* db.h */
diff --git a/main/db1-ast/include/mpool.h b/main/db1-ast/include/mpool.h
deleted file mode 100644
index 0cfc5741c..000000000
--- a/main/db1-ast/include/mpool.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)mpool.h 8.2 (Berkeley) 7/14/94
- */
-
-#ifndef _MPOOL_H
-#define _MPOOL_H 1
-
-#include <sys/queue.h>
-#ifndef CIRCLEQ_HEAD
-#include <circ-queue.h>
-#endif
-
-/*
- * The memory pool scheme is a simple one. Each in-memory page is referenced
- * by a bucket which is threaded in up to two of three ways. All active pages
- * are threaded on a hash chain (hashed by page number) and an lru chain.
- * Inactive pages are threaded on a free chain. Each reference to a memory
- * pool is handed an opaque MPOOL cookie which stores all of this information.
- */
-#define HASHSIZE 128
-#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE)
-
-/* The BKT structures are the elements of the queues. */
-typedef struct _bkt {
- CIRCLEQ_ENTRY(_bkt) hq; /* hash queue */
- CIRCLEQ_ENTRY(_bkt) q; /* lru queue */
- void *page; /* page */
- pgno_t pgno; /* page number */
-
-#define MPOOL_DIRTY 0x01 /* page needs to be written */
-#define MPOOL_PINNED 0x02 /* page is pinned into memory */
- u_int8_t flags; /* flags */
-} BKT;
-
-typedef struct MPOOL {
- CIRCLEQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */
- /* hash queue array */
- CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE];
- pgno_t curcache; /* current number of cached pages */
- pgno_t maxcache; /* max number of cached pages */
- pgno_t npages; /* number of pages in the file */
- u_long pagesize; /* file page size */
- int fd; /* file descriptor */
- /* page in conversion routine */
- void (*pgin) __P((void *, pgno_t, void *));
- /* page out conversion routine */
- void (*pgout) __P((void *, pgno_t, void *));
- void *pgcookie; /* cookie for page in/out routines */
-#ifdef STATISTICS
- u_long cachehit;
- u_long cachemiss;
- u_long pagealloc;
- u_long pageflush;
- u_long pageget;
- u_long pagenew;
- u_long pageput;
- u_long pageread;
- u_long pagewrite;
-#endif
-} MPOOL;
-
-__BEGIN_DECLS
-MPOOL *__mpool_open __P((void *, int, pgno_t, pgno_t));
-MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t));
-void __mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *),
- void (*)(void *, pgno_t, void *), void *));
-void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *),
- void (*)(void *, pgno_t, void *), void *));
-void *__mpool_new __P((MPOOL *, pgno_t *));
-void *mpool_new __P((MPOOL *, pgno_t *));
-void *__mpool_get __P((MPOOL *, pgno_t, u_int));
-void *mpool_get __P((MPOOL *, pgno_t, u_int));
-int __mpool_put __P((MPOOL *, void *, u_int));
-int mpool_put __P((MPOOL *, void *, u_int));
-int __mpool_sync __P((MPOOL *));
-int mpool_sync __P((MPOOL *));
-int __mpool_close __P((MPOOL *));
-int mpool_close __P((MPOOL *));
-#ifdef STATISTICS
-void mpool_stat __P((MPOOL *));
-#endif
-__END_DECLS
-
-#endif /* mpool.h */
diff --git a/main/db1-ast/include/ndbm.h b/main/db1-ast/include/ndbm.h
deleted file mode 100644
index d2079b0a5..000000000
--- a/main/db1-ast/include/ndbm.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Margo Seltzer.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ndbm.h 8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _NDBM_H
-#define _NDBM_H 1
-
-#include "db.h"
-
-/* Map dbm interface onto db(3). */
-#define DBM_RDONLY O_RDONLY
-
-/* Flags to dbm_store(). */
-#define DBM_INSERT 0
-#define DBM_REPLACE 1
-
-/*
- * The db(3) support for ndbm(3) always appends this suffix to the
- * file name to avoid overwriting the user's original database.
- */
-#define DBM_SUFFIX ".db"
-
-typedef struct {
- char *dptr;
- int dsize;
-} datum;
-
-typedef DB DBM;
-#define dbm_pagfno(a) DBM_PAGFNO_NOT_AVAILABLE
-
-__BEGIN_DECLS
-void dbm_close __P((DBM *));
-int dbm_delete __P((DBM *, datum));
-datum dbm_fetch __P((DBM *, datum));
-datum dbm_firstkey __P((DBM *));
-long dbm_forder __P((DBM *, datum));
-datum dbm_nextkey __P((DBM *));
-DBM *dbm_open __P((const char *, int, int));
-int dbm_store __P((DBM *, datum, datum, int));
-int dbm_dirfno __P((DBM *));
-int dbm_error __P((DBM *));
-int dbm_clearerr __P((DBM *));
-__END_DECLS
-
-#endif /* ndbm.h */
diff --git a/main/db1-ast/libdb.map b/main/db1-ast/libdb.map
deleted file mode 100644
index 87e34c430..000000000
--- a/main/db1-ast/libdb.map
+++ /dev/null
@@ -1,11 +0,0 @@
-GLIBC_2.0 {
- global:
- # the real DB entry point.
- dbopen; __dbopen;
-
- # The compatibility functions.
- dbm_clearerr; dbm_close; dbm_delete; dbm_dirfno; dbm_error;
- dbm_fetch; dbm_firstkey; dbm_nextkey; dbm_open; dbm_store;
- local:
- *;
-};
diff --git a/main/db1-ast/mpool/README b/main/db1-ast/mpool/README
deleted file mode 100644
index 0f01fbcdb..000000000
--- a/main/db1-ast/mpool/README
+++ /dev/null
@@ -1,7 +0,0 @@
-# @(#)README 8.1 (Berkeley) 6/4/93
-
-These are the current memory pool routines.
-They aren't ready for prime time, yet, and
-the interface is expected to change.
-
---keith
diff --git a/main/db1-ast/mpool/mpool.c b/main/db1-ast/mpool/mpool.c
deleted file mode 100644
index b5b7c86d6..000000000
--- a/main/db1-ast/mpool/mpool.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../include/db.h"
-
-#define __MPOOLINTERFACE_PRIVATE
-#include <mpool.h>
-
-#undef __APPLE__
-
-#ifndef __APPLE__
-#define mpool_open __mpool_open
-#define mpool_filter __mpool_filter
-#define mpool_new __mpool_new
-#define mpool_get __mpool_get
-#define mpool_put __mpool_put
-#define mpool_sync __mpool_sync
-#define mpool_close __mpool_close
-#endif
-
-static BKT *mpool_bkt __P((MPOOL *));
-static BKT *mpool_look __P((MPOOL *, pgno_t));
-static int mpool_write __P((MPOOL *, BKT *));
-
-/*
- * mpool_open --
- * Initialize a memory pool.
- */
-MPOOL *
-mpool_open(key, fd, pagesize, maxcache)
- void *key;
- int fd;
- pgno_t pagesize, maxcache;
-{
- struct stat sb;
- MPOOL *mp;
- int entry;
-
- /*
- * Get information about the file.
- *
- * XXX
- * We don't currently handle pipes, although we should.
- */
- if (fstat(fd, &sb))
- return (NULL);
- if (!S_ISREG(sb.st_mode)) {
- errno = ESPIPE;
- return (NULL);
- }
-
- /* Allocate and initialize the MPOOL cookie. */
- if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL)
- return (NULL);
- CIRCLEQ_INIT(&mp->lqh);
- for (entry = 0; entry < HASHSIZE; ++entry)
- CIRCLEQ_INIT(&mp->hqh[entry]);
- mp->maxcache = maxcache;
- mp->npages = sb.st_size / pagesize;
- mp->pagesize = pagesize;
- mp->fd = fd;
- return (mp);
-}
-
-/*
- * mpool_filter --
- * Initialize input/output filters.
- */
-void
-mpool_filter(mp, pgin, pgout, pgcookie)
- MPOOL *mp;
- void (*pgin) __P((void *, pgno_t, void *));
- void (*pgout) __P((void *, pgno_t, void *));
- void *pgcookie;
-{
- mp->pgin = pgin;
- mp->pgout = pgout;
- mp->pgcookie = pgcookie;
-}
-
-/*
- * mpool_new --
- * Get a new page of memory.
- */
-void *
-mpool_new(mp, pgnoaddr)
- MPOOL *mp;
- pgno_t *pgnoaddr;
-{
- struct _hqh *head;
- BKT *bp;
-
- if (mp->npages == MAX_PAGE_NUMBER) {
- (void)fprintf(stderr, "mpool_new: page allocation overflow.\n");
- abort();
- }
-#ifdef STATISTICS
- ++mp->pagenew;
-#endif
- /*
- * Get a BKT from the cache. Assign a new page number, attach
- * it to the head of the hash chain, the tail of the lru chain,
- * and return.
- */
- if ((bp = mpool_bkt(mp)) == NULL)
- return (NULL);
- *pgnoaddr = bp->pgno = mp->npages++;
- bp->flags = MPOOL_PINNED;
-
- head = &mp->hqh[HASHKEY(bp->pgno)];
- CIRCLEQ_INSERT_HEAD(head, bp, hq);
- CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
- return (bp->page);
-}
-
-/*
- * mpool_get
- * Get a page.
- */
-void *
-mpool_get(mp, pgno, flags)
- MPOOL *mp;
- pgno_t pgno;
- u_int flags; /* XXX not used? */
-{
- struct _hqh *head;
- BKT *bp;
- off_t off;
- int nr;
-
- /* Check for attempt to retrieve a non-existent page. */
- if (pgno >= mp->npages) {
- errno = EINVAL;
- return (NULL);
- }
-
-#ifdef STATISTICS
- ++mp->pageget;
-#endif
-
- /* Check for a page that is cached. */
- if ((bp = mpool_look(mp, pgno)) != NULL) {
-#ifdef DEBUG
- if (bp->flags & MPOOL_PINNED) {
- (void)fprintf(stderr,
- "mpool_get: page %d already pinned\n", bp->pgno);
- abort();
- }
-#endif
- /*
- * Move the page to the head of the hash chain and the tail
- * of the lru chain.
- */
- head = &mp->hqh[HASHKEY(bp->pgno)];
- CIRCLEQ_REMOVE(head, bp, hq);
- CIRCLEQ_INSERT_HEAD(head, bp, hq);
- CIRCLEQ_REMOVE(&mp->lqh, bp, q);
- CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
-
- /* Return a pinned page. */
- bp->flags |= MPOOL_PINNED;
- return (bp->page);
- }
-
- /* Get a page from the cache. */
- if ((bp = mpool_bkt(mp)) == NULL)
- return (NULL);
-
- /* Read in the contents. */
-#ifdef STATISTICS
- ++mp->pageread;
-#endif
- off = mp->pagesize * pgno;
- if (lseek(mp->fd, off, SEEK_SET) != off)
- return (NULL);
- if ((u_long) (nr = read(mp->fd, bp->page, mp->pagesize))
- != mp->pagesize) {
- if (nr >= 0)
- errno = EFTYPE;
- return (NULL);
- }
-
- /* Set the page number, pin the page. */
- bp->pgno = pgno;
- bp->flags = MPOOL_PINNED;
-
- /*
- * Add the page to the head of the hash chain and the tail
- * of the lru chain.
- */
- head = &mp->hqh[HASHKEY(bp->pgno)];
- CIRCLEQ_INSERT_HEAD(head, bp, hq);
- CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
-
- /* Run through the user's filter. */
- if (mp->pgin != NULL)
- (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
-
- return (bp->page);
-}
-
-/*
- * mpool_put
- * Return a page.
- */
-int
-mpool_put(mp, page, flags)
- MPOOL *mp;
- void *page;
- u_int flags;
-{
- BKT *bp;
-
-#ifdef STATISTICS
- ++mp->pageput;
-#endif
- bp = (BKT *)((char *)page - sizeof(BKT));
-#ifdef DEBUG
- if (!(bp->flags & MPOOL_PINNED)) {
- (void)fprintf(stderr,
- "mpool_put: page %d not pinned\n", bp->pgno);
- abort();
- }
-#endif
- bp->flags &= ~MPOOL_PINNED;
- bp->flags |= flags & MPOOL_DIRTY;
- return (RET_SUCCESS);
-}
-
-/*
- * mpool_close
- * Close the buffer pool.
- */
-int
-mpool_close(mp)
- MPOOL *mp;
-{
- BKT *bp;
-
- /* Free up any space allocated to the lru pages. */
- while ((bp = mp->lqh.cqh_first) != (void *)&mp->lqh) {
- CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q);
- free(bp);
- }
-
- /* Free the MPOOL cookie. */
- free(mp);
- return (RET_SUCCESS);
-}
-
-/*
- * mpool_sync
- * Sync the pool to disk.
- */
-int
-mpool_sync(mp)
- MPOOL *mp;
-{
- BKT *bp;
-
- /* Walk the lru chain, flushing any dirty pages to disk. */
- for (bp = mp->lqh.cqh_first;
- bp != (void *)&mp->lqh; bp = bp->q.cqe_next)
- if (bp->flags & MPOOL_DIRTY &&
- mpool_write(mp, bp) == RET_ERROR)
- return (RET_ERROR);
-
- /* Sync the file descriptor. */
- return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
-}
-
-#define __APPLE__
-
-#ifndef __APPLE__
-#undef mpool_open
-#undef mpool_filter
-#undef mpool_new
-#undef mpool_get
-#undef mpool_put
-#undef mpool_close
-#undef mpool_sync
-
-#define weak_alias(original, alias) \
- asm (".weak " #alias "\n" #alias " = " #original);
-weak_alias (__mpool_open, mpool_open)
-weak_alias (__mpool_filter, mpool_filter)
-weak_alias (__mpool_new, mpool_new)
-weak_alias (__mpool_get, mpool_get)
-weak_alias (__mpool_put, mpool_put)
-weak_alias (__mpool_close, mpool_close)
-weak_alias (__mpool_sync, mpool_sync)
-#endif
-
-/*
- * mpool_bkt
- * Get a page from the cache (or create one).
- */
-static BKT *
-mpool_bkt(mp)
- MPOOL *mp;
-{
- struct _hqh *head;
- BKT *bp;
-
- /* If under the max cached, always create a new page. */
- if (mp->curcache < mp->maxcache)
- goto new;
-
- /*
- * If the cache is max'd out, walk the lru list for a buffer we
- * can flush. If we find one, write it (if necessary) and take it
- * off any lists. If we don't find anything we grow the cache anyway.
- * The cache never shrinks.
- */
- for (bp = mp->lqh.cqh_first;
- bp != (void *)&mp->lqh; bp = bp->q.cqe_next)
- if (!(bp->flags & MPOOL_PINNED)) {
- /* Flush if dirty. */
- if (bp->flags & MPOOL_DIRTY &&
- mpool_write(mp, bp) == RET_ERROR)
- return (NULL);
-#ifdef STATISTICS
- ++mp->pageflush;
-#endif
- /* Remove from the hash and lru queues. */
- head = &mp->hqh[HASHKEY(bp->pgno)];
- CIRCLEQ_REMOVE(head, bp, hq);
- CIRCLEQ_REMOVE(&mp->lqh, bp, q);
-#ifdef DEBUG
- { void *spage;
- spage = bp->page;
- memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
- bp->page = spage;
- }
-#endif
- return (bp);
- }
-
-new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
- return (NULL);
-#ifdef STATISTICS
- ++mp->pagealloc;
-#endif
-#if defined(DEBUG) || defined(PURIFY)
- memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
-#endif
- bp->page = (char *)bp + sizeof(BKT);
- ++mp->curcache;
- return (bp);
-}
-
-/*
- * mpool_write
- * Write a page to disk.
- */
-static int
-mpool_write(mp, bp)
- MPOOL *mp;
- BKT *bp;
-{
- off_t off;
-
-#ifdef STATISTICS
- ++mp->pagewrite;
-#endif
-
- /* Run through the user's filter. */
- if (mp->pgout)
- (mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
-
- off = mp->pagesize * bp->pgno;
- if (lseek(mp->fd, off, SEEK_SET) != off)
- return (RET_ERROR);
- if ((u_long) write(mp->fd, bp->page, mp->pagesize) != mp->pagesize)
- return (RET_ERROR);
-
- bp->flags &= ~MPOOL_DIRTY;
- return (RET_SUCCESS);
-}
-
-/*
- * mpool_look
- * Lookup a page in the cache.
- */
-static BKT *
-mpool_look(mp, pgno)
- MPOOL *mp;
- pgno_t pgno;
-{
- struct _hqh *head;
- BKT *bp;
-
- head = &mp->hqh[HASHKEY(pgno)];
- for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next)
- if (bp->pgno == pgno) {
-#ifdef STATISTICS
- ++mp->cachehit;
-#endif
- return (bp);
- }
-#ifdef STATISTICS
- ++mp->cachemiss;
-#endif
- return (NULL);
-}
-
-#ifdef STATISTICS
-/*
- * mpool_stat
- * Print out cache statistics.
- */
-void
-mpool_stat(mp)
- MPOOL *mp;
-{
- BKT *bp;
- int cnt;
- char *sep;
-
- (void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
- (void)fprintf(stderr,
- "page size %lu, cacheing %lu pages of %lu page max cache\n",
- mp->pagesize, mp->curcache, mp->maxcache);
- (void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
- mp->pageput, mp->pageget, mp->pagenew);
- (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n",
- mp->pagealloc, mp->pageflush);
- if (mp->cachehit + mp->cachemiss)
- (void)fprintf(stderr,
- "%.0f%% cache hit rate (%lu hits, %lu misses)\n",
- ((double)mp->cachehit / (mp->cachehit + mp->cachemiss))
- * 100, mp->cachehit, mp->cachemiss);
- (void)fprintf(stderr, "%lu page reads, %lu page writes\n",
- mp->pageread, mp->pagewrite);
-
- sep = "";
- cnt = 0;
- for (bp = mp->lqh.cqh_first;
- bp != (void *)&mp->lqh; bp = bp->q.cqe_next) {
- (void)fprintf(stderr, "%s%d", sep, bp->pgno);
- if (bp->flags & MPOOL_DIRTY)
- (void)fprintf(stderr, "d");
- if (bp->flags & MPOOL_PINNED)
- (void)fprintf(stderr, "P");
- if (++cnt == 10) {
- sep = "\n";
- cnt = 0;
- } else
- sep = ", ";
-
- }
- (void)fprintf(stderr, "\n");
-}
-#endif
diff --git a/main/db1-ast/recno/extern.h b/main/db1-ast/recno/extern.h
deleted file mode 100644
index feed43445..000000000
--- a/main/db1-ast/recno/extern.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)extern.h 8.3 (Berkeley) 6/4/94
- */
-
-#include "../btree/extern.h"
-
-int __rec_close __P((DB *));
-int __rec_delete __P((const DB *, const DBT *, u_int));
-int __rec_dleaf __P((BTREE *, PAGE *, u_int32_t));
-int __rec_fd __P((const DB *));
-int __rec_fmap __P((BTREE *, recno_t));
-int __rec_fout __P((BTREE *));
-int __rec_fpipe __P((BTREE *, recno_t));
-int __rec_get __P((const DB *, const DBT *, DBT *, u_int));
-int __rec_iput __P((BTREE *, recno_t, const DBT *, u_int));
-int __rec_put __P((const DB *dbp, DBT *, const DBT *, u_int));
-int __rec_ret __P((BTREE *, EPG *, recno_t, DBT *, DBT *));
-EPG *__rec_search __P((BTREE *, recno_t, enum SRCHOP));
-int __rec_seq __P((const DB *, DBT *, DBT *, u_int));
-int __rec_sync __P((const DB *, u_int));
-int __rec_vmap __P((BTREE *, recno_t));
-int __rec_vout __P((BTREE *));
-int __rec_vpipe __P((BTREE *, recno_t));
diff --git a/main/db1-ast/recno/rec_close.c b/main/db1-ast/recno/rec_close.c
deleted file mode 100644
index 20b00f52c..000000000
--- a/main/db1-ast/recno/rec_close.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rec_close.c 8.6 (Berkeley) 8/18/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/mman.h>
-
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "../include/db.h"
-#include "recno.h"
-
-/*
- * __REC_CLOSE -- Close a recno tree.
- *
- * Parameters:
- * dbp: pointer to access method
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__rec_close(dbp)
- DB *dbp;
-{
- BTREE *t;
- int status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- if (__rec_sync(dbp, 0) == RET_ERROR)
- return (RET_ERROR);
-
- /* Committed to closing. */
- status = RET_SUCCESS;
- if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
- status = RET_ERROR;
-
- if (!F_ISSET(t, R_INMEM)) {
- if (F_ISSET(t, R_CLOSEFP)) {
- if (fclose(t->bt_rfp))
- status = RET_ERROR;
- } else
- if (close(t->bt_rfd))
- status = RET_ERROR;
- }
-
- if (__bt_close(dbp) == RET_ERROR)
- status = RET_ERROR;
-
- return (status);
-}
-
-/*
- * __REC_SYNC -- sync the recno tree to disk.
- *
- * Parameters:
- * dbp: pointer to access method
- *
- * Returns:
- * RET_SUCCESS, RET_ERROR.
- */
-int
-__rec_sync(dbp, flags)
- const DB *dbp;
- u_int flags;
-{
- struct iovec iov[2];
- BTREE *t;
- DBT data, key;
- off_t off;
- recno_t scursor, trec;
- int status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- if (flags == R_RECNOSYNC)
- return (__bt_sync(dbp, 0));
-
- if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))
- return (RET_SUCCESS);
-
- /* Read any remaining records into the tree. */
- if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
- return (RET_ERROR);
-
- /* Rewind the file descriptor. */
- if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)
- return (RET_ERROR);
-
- /* Save the cursor. */
- scursor = t->bt_cursor.rcursor;
-
- key.size = sizeof(recno_t);
- key.data = &trec;
-
- if (F_ISSET(t, R_FIXLEN)) {
- /*
- * We assume that fixed length records are all fixed length.
- * Any that aren't are either EINVAL'd or corrected by the
- * record put code.
- */
- status = (dbp->seq)(dbp, &key, &data, R_FIRST);
- while (status == RET_SUCCESS) {
- if ((size_t) write(t->bt_rfd, data.data, data.size) != data.size)
- return (RET_ERROR);
- status = (dbp->seq)(dbp, &key, &data, R_NEXT);
- }
- } else {
- iov[1].iov_base = &t->bt_bval;
- iov[1].iov_len = 1;
-
- status = (dbp->seq)(dbp, &key, &data, R_FIRST);
- while (status == RET_SUCCESS) {
- iov[0].iov_base = data.data;
- iov[0].iov_len = data.size;
- if ((size_t) writev(t->bt_rfd, iov, 2) != data.size + 1)
- return (RET_ERROR);
- status = (dbp->seq)(dbp, &key, &data, R_NEXT);
- }
- }
-
- /* Restore the cursor. */
- t->bt_cursor.rcursor = scursor;
-
- if (status == RET_ERROR)
- return (RET_ERROR);
- if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)
- return (RET_ERROR);
- if (ftruncate(t->bt_rfd, off))
- return (RET_ERROR);
- F_CLR(t, R_MODIFIED);
- return (RET_SUCCESS);
-}
diff --git a/main/db1-ast/recno/rec_delete.c b/main/db1-ast/recno/rec_delete.c
deleted file mode 100644
index fc2047226..000000000
--- a/main/db1-ast/recno/rec_delete.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rec_delete.c 8.7 (Berkeley) 7/14/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "recno.h"
-
-static int rec_rdelete __P((BTREE *, recno_t));
-
-/*
- * __REC_DELETE -- Delete the item(s) referenced by a key.
- *
- * Parameters:
- * dbp: pointer to access method
- * key: key to delete
- * flags: R_CURSOR if deleting what the cursor references
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
- */
-int
-__rec_delete(dbp, key, flags)
- const DB *dbp;
- const DBT *key;
- u_int flags;
-{
- BTREE *t;
- recno_t nrec;
- int status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- switch(flags) {
- case 0:
- if ((nrec = *(recno_t *)key->data) == 0)
- goto einval;
- if (nrec > t->bt_nrecs)
- return (RET_SPECIAL);
- --nrec;
- status = rec_rdelete(t, nrec);
- break;
- case R_CURSOR:
- if (!F_ISSET(&t->bt_cursor, CURS_INIT))
- goto einval;
- if (t->bt_nrecs == 0)
- return (RET_SPECIAL);
- status = rec_rdelete(t, t->bt_cursor.rcursor - 1);
- if (status == RET_SUCCESS)
- --t->bt_cursor.rcursor;
- break;
- default:
-einval: errno = EINVAL;
- return (RET_ERROR);
- }
-
- if (status == RET_SUCCESS)
- F_SET(t, B_MODIFIED | R_MODIFIED);
- return (status);
-}
-
-/*
- * REC_RDELETE -- Delete the data matching the specified key.
- *
- * Parameters:
- * tree: tree
- * nrec: record to delete
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
- */
-static int
-rec_rdelete(t, nrec)
- BTREE *t;
- recno_t nrec;
-{
- EPG *e;
- PAGE *h;
- int status;
-
- /* Find the record; __rec_search pins the page. */
- if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
- return (RET_ERROR);
-
- /* Delete the record. */
- h = e->page;
- status = __rec_dleaf(t, h, e->index);
- if (status != RET_SUCCESS) {
- mpool_put(t->bt_mp, h, 0);
- return (status);
- }
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- return (RET_SUCCESS);
-}
-
-/*
- * __REC_DLEAF -- Delete a single record from a recno leaf page.
- *
- * Parameters:
- * t: tree
- * index: index on current page to delete
- *
- * Returns:
- * RET_SUCCESS, RET_ERROR.
- */
-int
-__rec_dleaf(t, h, index)
- BTREE *t;
- PAGE *h;
- u_int32_t index;
-{
- RLEAF *rl;
- indx_t *ip, cnt, offset;
- u_int32_t nbytes;
- char *from;
- void *to;
-
- /*
- * Delete a record from a recno leaf page. Internal records are never
- * deleted from internal pages, regardless of the records that caused
- * them to be added being deleted. Pages made empty by deletion are
- * not reclaimed. They are, however, made available for reuse.
- *
- * Pack the remaining entries at the end of the page, shift the indices
- * down, overwriting the deleted record and its index. If the record
- * uses overflow pages, make them available for reuse.
- */
- to = rl = GETRLEAF(h, index);
- if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
- return (RET_ERROR);
- nbytes = NRLEAF(rl);
-
- /*
- * Compress the key/data pairs. Compress and adjust the [BR]LEAF
- * offsets. Reset the headers.
- */
- from = (char *)h + h->upper;
- memmove(from + nbytes, from, (char *)to - from);
- h->upper += nbytes;
-
- offset = h->linp[index];
- for (cnt = &h->linp[index] - (ip = &h->linp[0]); cnt--; ++ip)
- if (ip[0] < offset)
- ip[0] += nbytes;
- for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
- ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
- h->lower -= sizeof(indx_t);
- --t->bt_nrecs;
- return (RET_SUCCESS);
-}
diff --git a/main/db1-ast/recno/rec_get.c b/main/db1-ast/recno/rec_get.c
deleted file mode 100644
index 7038cc81a..000000000
--- a/main/db1-ast/recno/rec_get.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rec_get.c 8.9 (Berkeley) 8/18/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../include/db.h"
-#include "recno.h"
-
-/*
- * __REC_GET -- Get a record from the btree.
- *
- * Parameters:
- * dbp: pointer to access method
- * key: key to find
- * data: data to return
- * flag: currently unused
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
- */
-int
-__rec_get(dbp, key, data, flags)
- const DB *dbp;
- const DBT *key;
- DBT *data;
- u_int flags;
-{
- BTREE *t;
- EPG *e;
- recno_t nrec;
- int status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /* Get currently doesn't take any flags, and keys of 0 are illegal. */
- if (flags || (nrec = *(recno_t *)key->data) == 0) {
- errno = EINVAL;
- return (RET_ERROR);
- }
-
- /*
- * If we haven't seen this record yet, try to find it in the
- * original file.
- */
- if (nrec > t->bt_nrecs) {
- if (F_ISSET(t, R_EOF | R_INMEM))
- return (RET_SPECIAL);
- if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
- return (status);
- }
-
- --nrec;
- if ((e = __rec_search(t, nrec, SEARCH)) == NULL)
- return (RET_ERROR);
-
- status = __rec_ret(t, e, 0, NULL, data);
- if (F_ISSET(t, B_DB_LOCK))
- mpool_put(t->bt_mp, e->page, 0);
- else
- t->bt_pinned = e->page;
- return (status);
-}
-
-/*
- * __REC_FPIPE -- Get fixed length records from a pipe.
- *
- * Parameters:
- * t: tree
- * cnt: records to read
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__rec_fpipe(t, top)
- BTREE *t;
- recno_t top;
-{
- DBT data;
- recno_t nrec;
- size_t len;
- int ch;
- u_char *p;
-
- if (t->bt_rdata.size < t->bt_reclen) {
- t->bt_rdata.data = t->bt_rdata.data == NULL ?
- malloc(t->bt_reclen) :
- realloc(t->bt_rdata.data, t->bt_reclen);
- if (t->bt_rdata.data == NULL)
- return (RET_ERROR);
- t->bt_rdata.size = t->bt_reclen;
- }
- data.data = t->bt_rdata.data;
- data.size = t->bt_reclen;
-
- for (nrec = t->bt_nrecs; nrec < top;) {
- len = t->bt_reclen;
- for (p = t->bt_rdata.data;; *p++ = ch)
- if ((ch = getc(t->bt_rfp)) == EOF || !--len) {
- if (ch != EOF)
- *p = ch;
- if (len != 0)
- memset(p, t->bt_bval, len);
- if (__rec_iput(t,
- nrec, &data, 0) != RET_SUCCESS)
- return (RET_ERROR);
- ++nrec;
- break;
- }
- if (ch == EOF)
- break;
- }
- if (nrec < top) {
- F_SET(t, R_EOF);
- return (RET_SPECIAL);
- }
- return (RET_SUCCESS);
-}
-
-/*
- * __REC_VPIPE -- Get variable length records from a pipe.
- *
- * Parameters:
- * t: tree
- * cnt: records to read
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__rec_vpipe(t, top)
- BTREE *t;
- recno_t top;
-{
- DBT data;
- recno_t nrec;
- indx_t len;
- size_t sz;
- int bval, ch;
- u_char *p;
-
- bval = t->bt_bval;
- for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
- for (p = t->bt_rdata.data,
- sz = t->bt_rdata.size;; *p++ = ch, --sz) {
- if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) {
- data.data = t->bt_rdata.data;
- data.size = p - (u_char *)t->bt_rdata.data;
- if (ch == EOF && data.size == 0)
- break;
- if (__rec_iput(t, nrec, &data, 0)
- != RET_SUCCESS)
- return (RET_ERROR);
- break;
- }
- if (sz == 0) {
- len = p - (u_char *)t->bt_rdata.data;
- t->bt_rdata.size += (sz = 256);
- t->bt_rdata.data = t->bt_rdata.data == NULL ?
- malloc(t->bt_rdata.size) :
- realloc(t->bt_rdata.data, t->bt_rdata.size);
- if (t->bt_rdata.data == NULL)
- return (RET_ERROR);
- p = (u_char *)t->bt_rdata.data + len;
- }
- }
- if (ch == EOF)
- break;
- }
- if (nrec < top) {
- F_SET(t, R_EOF);
- return (RET_SPECIAL);
- }
- return (RET_SUCCESS);
-}
-
-/*
- * __REC_FMAP -- Get fixed length records from a file.
- *
- * Parameters:
- * t: tree
- * cnt: records to read
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__rec_fmap(t, top)
- BTREE *t;
- recno_t top;
-{
- DBT data;
- recno_t nrec;
- u_char *sp, *ep, *p;
- size_t len;
-
- if (t->bt_rdata.size < t->bt_reclen) {
- t->bt_rdata.data = t->bt_rdata.data == NULL ?
- malloc(t->bt_reclen) :
- realloc(t->bt_rdata.data, t->bt_reclen);
- if (t->bt_rdata.data == NULL)
- return (RET_ERROR);
- t->bt_rdata.size = t->bt_reclen;
- }
- data.data = t->bt_rdata.data;
- data.size = t->bt_reclen;
-
- sp = (u_char *)t->bt_cmap;
- ep = (u_char *)t->bt_emap;
- for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
- if (sp >= ep) {
- F_SET(t, R_EOF);
- return (RET_SPECIAL);
- }
- len = t->bt_reclen;
- for (p = t->bt_rdata.data;
- sp < ep && len > 0; *p++ = *sp++, --len);
- if (len != 0)
- memset(p, t->bt_bval, len);
- if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
- return (RET_ERROR);
- }
- t->bt_cmap = (caddr_t)sp;
- return (RET_SUCCESS);
-}
-
-/*
- * __REC_VMAP -- Get variable length records from a file.
- *
- * Parameters:
- * t: tree
- * cnt: records to read
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__rec_vmap(t, top)
- BTREE *t;
- recno_t top;
-{
- DBT data;
- u_char *sp, *ep;
- recno_t nrec;
- int bval;
-
- sp = (u_char *)t->bt_cmap;
- ep = (u_char *)t->bt_emap;
- bval = t->bt_bval;
-
- for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
- if (sp >= ep) {
- F_SET(t, R_EOF);
- return (RET_SPECIAL);
- }
- for (data.data = sp; sp < ep && *sp != bval; ++sp);
- data.size = sp - (u_char *)data.data;
- if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
- return (RET_ERROR);
- ++sp;
- }
- t->bt_cmap = (caddr_t)sp;
- return (RET_SUCCESS);
-}
diff --git a/main/db1-ast/recno/rec_open.c b/main/db1-ast/recno/rec_open.c
deleted file mode 100644
index 0ebc8c7c4..000000000
--- a/main/db1-ast/recno/rec_open.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Olson.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rec_open.c 8.10 (Berkeley) 9/1/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "../include/db.h"
-#include "recno.h"
-
-DB *
-__rec_open(fname, flags, mode, openinfo, dflags)
- const char *fname;
- int flags, mode, dflags;
- const RECNOINFO *openinfo;
-{
- BTREE *t;
- BTREEINFO btopeninfo;
- DB *dbp;
- PAGE *h;
- struct stat sb;
- int rfd = 0, sverrno;
-
- /* Open the user's file -- if this fails, we're done. */
- if (fname != NULL && (rfd = open(fname, flags, mode)) < 0)
- return (NULL);
-
- /* Create a btree in memory (backed by disk). */
- dbp = NULL;
- if (openinfo) {
- if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
- goto einval;
- btopeninfo.flags = 0;
- btopeninfo.cachesize = openinfo->cachesize;
- btopeninfo.maxkeypage = 0;
- btopeninfo.minkeypage = 0;
- btopeninfo.psize = openinfo->psize;
- btopeninfo.compare = NULL;
- btopeninfo.prefix = NULL;
- btopeninfo.lorder = openinfo->lorder;
- dbp = __bt_open(openinfo->bfname,
- O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
- } else
- dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
- if (dbp == NULL)
- goto err;
-
- /*
- * Some fields in the tree structure are recno specific. Fill them
- * in and make the btree structure look like a recno structure. We
- * don't change the bt_ovflsize value, it's close enough and slightly
- * bigger.
- */
- t = dbp->internal;
- if (openinfo) {
- if (openinfo->flags & R_FIXEDLEN) {
- F_SET(t, R_FIXLEN);
- t->bt_reclen = openinfo->reclen;
- if (t->bt_reclen == 0)
- goto einval;
- }
- t->bt_bval = openinfo->bval;
- } else
- t->bt_bval = '\n';
-
- F_SET(t, R_RECNO);
- if (fname == NULL)
- F_SET(t, R_EOF | R_INMEM);
- else
- t->bt_rfd = rfd;
-
- if (fname != NULL) {
- /*
- * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
- * Unfortunately, that's not portable, so we use lseek
- * and check the errno values.
- */
- errno = 0;
- if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
- switch (flags & O_ACCMODE) {
- case O_RDONLY:
- F_SET(t, R_RDONLY);
- break;
- default:
- goto einval;
- }
-slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
- goto err;
- F_SET(t, R_CLOSEFP);
- t->bt_irec =
- F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
- } else {
- switch (flags & O_ACCMODE) {
- case O_RDONLY:
- F_SET(t, R_RDONLY);
- break;
- case O_RDWR:
- break;
- default:
- goto einval;
- }
-
- if (fstat(rfd, &sb))
- goto err;
- /*
- * Kluge -- we'd like to test to see if the file is too
- * big to mmap. Since, we don't know what size or type
- * off_t's or size_t's are, what the largest unsigned
- * integral type is, or what random insanity the local
- * C compiler will perpetrate, doing the comparison in
- * a portable way is flatly impossible. Hope that mmap
- * fails if the file is too large.
- */
- if (sb.st_size == 0)
- F_SET(t, R_EOF);
- else {
-#ifdef MMAP_NOT_AVAILABLE
- /*
- * XXX
- * Mmap doesn't work correctly on many current
- * systems. In particular, it can fail subtly,
- * with cache coherency problems. Don't use it
- * for now.
- */
- t->bt_msize = sb.st_size;
- if ((t->bt_smap = mmap(NULL, t->bt_msize,
- PROT_READ, MAP_PRIVATE, rfd,
- (off_t)0)) == (caddr_t)-1)
- goto slow;
- t->bt_cmap = t->bt_smap;
- t->bt_emap = t->bt_smap + sb.st_size;
- t->bt_irec = F_ISSET(t, R_FIXLEN) ?
- __rec_fmap : __rec_vmap;
- F_SET(t, R_MEMMAPPED);
-#else
- goto slow;
-#endif
- }
- }
- }
-
- /* Use the recno routines. */
- dbp->close = __rec_close;
- dbp->del = __rec_delete;
- dbp->fd = __rec_fd;
- dbp->get = __rec_get;
- dbp->put = __rec_put;
- dbp->seq = __rec_seq;
- dbp->sync = __rec_sync;
-
- /* If the root page was created, reset the flags. */
- if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
- goto err;
- if ((h->flags & P_TYPE) == P_BLEAF) {
- F_CLR(h, P_TYPE);
- F_SET(h, P_RLEAF);
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- } else
- mpool_put(t->bt_mp, h, 0);
-
- if (openinfo && openinfo->flags & R_SNAPSHOT &&
- !F_ISSET(t, R_EOF | R_INMEM) &&
- t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
- goto err;
- return (dbp);
-
-einval: errno = EINVAL;
-err: sverrno = errno;
- if (dbp != NULL)
- (void)__bt_close(dbp);
- if (fname != NULL)
- (void)close(rfd);
- errno = sverrno;
- return (NULL);
-}
-
-int
-__rec_fd(dbp)
- const DB *dbp;
-{
- BTREE *t;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /* In-memory database can't have a file descriptor. */
- if (F_ISSET(t, R_INMEM)) {
- errno = ENOENT;
- return (-1);
- }
- return (t->bt_rfd);
-}
diff --git a/main/db1-ast/recno/rec_put.c b/main/db1-ast/recno/rec_put.c
deleted file mode 100644
index 331699867..000000000
--- a/main/db1-ast/recno/rec_put.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "recno.h"
-
-/*
- * __REC_PUT -- Add a recno item to the tree.
- *
- * Parameters:
- * dbp: pointer to access method
- * key: key
- * data: data
- * flag: R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is
- * already in the tree and R_NOOVERWRITE specified.
- */
-int
-__rec_put(dbp, key, data, flags)
- const DB *dbp;
- DBT *key;
- const DBT *data;
- u_int flags;
-{
- BTREE *t;
- DBT fdata, tdata;
- recno_t nrec;
- int status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- /*
- * If using fixed-length records, and the record is long, return
- * EINVAL. If it's short, pad it out. Use the record data return
- * memory, it's only short-term.
- */
- if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) {
- if (data->size > t->bt_reclen)
- goto einval;
-
- if (t->bt_rdata.size < t->bt_reclen) {
- t->bt_rdata.data = t->bt_rdata.data == NULL ?
- malloc(t->bt_reclen) :
- realloc(t->bt_rdata.data, t->bt_reclen);
- if (t->bt_rdata.data == NULL)
- return (RET_ERROR);
- t->bt_rdata.size = t->bt_reclen;
- }
- memmove(t->bt_rdata.data, data->data, data->size);
- memset((char *)t->bt_rdata.data + data->size,
- t->bt_bval, t->bt_reclen - data->size);
- fdata.data = t->bt_rdata.data;
- fdata.size = t->bt_reclen;
- } else {
- fdata.data = data->data;
- fdata.size = data->size;
- }
-
- switch (flags) {
- case R_CURSOR:
- if (!F_ISSET(&t->bt_cursor, CURS_INIT))
- goto einval;
- nrec = t->bt_cursor.rcursor;
- break;
- case R_SETCURSOR:
- if ((nrec = *(recno_t *)key->data) == 0)
- goto einval;
- break;
- case R_IAFTER:
- if ((nrec = *(recno_t *)key->data) == 0) {
- nrec = 1;
- flags = R_IBEFORE;
- }
- break;
- case 0:
- case R_IBEFORE:
- if ((nrec = *(recno_t *)key->data) == 0)
- goto einval;
- break;
- case R_NOOVERWRITE:
- if ((nrec = *(recno_t *)key->data) == 0)
- goto einval;
- if (nrec <= t->bt_nrecs)
- return (RET_SPECIAL);
- break;
- default:
-einval: errno = EINVAL;
- return (RET_ERROR);
- }
-
- /*
- * Make sure that records up to and including the put record are
- * already in the database. If skipping records, create empty ones.
- */
- if (nrec > t->bt_nrecs) {
- if (!F_ISSET(t, R_EOF | R_INMEM) &&
- t->bt_irec(t, nrec) == RET_ERROR)
- return (RET_ERROR);
- if (nrec > t->bt_nrecs + 1) {
- if (F_ISSET(t, R_FIXLEN)) {
- if ((tdata.data =
- (void *)malloc(t->bt_reclen)) == NULL)
- return (RET_ERROR);
- tdata.size = t->bt_reclen;
- memset(tdata.data, t->bt_bval, tdata.size);
- } else {
- tdata.data = NULL;
- tdata.size = 0;
- }
- while (nrec > t->bt_nrecs + 1)
- if (__rec_iput(t,
- t->bt_nrecs, &tdata, 0) != RET_SUCCESS)
- return (RET_ERROR);
- if (F_ISSET(t, R_FIXLEN))
- free(tdata.data);
- }
- }
-
- if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS)
- return (status);
-
- if (flags == R_SETCURSOR)
- t->bt_cursor.rcursor = nrec;
-
- F_SET(t, R_MODIFIED);
- return (__rec_ret(t, NULL, nrec, key, NULL));
-}
-
-/*
- * __REC_IPUT -- Add a recno item to the tree.
- *
- * Parameters:
- * t: tree
- * nrec: record number
- * data: data
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__rec_iput(t, nrec, data, flags)
- BTREE *t;
- recno_t nrec;
- const DBT *data;
- u_int flags;
-{
- DBT tdata;
- EPG *e;
- PAGE *h;
- indx_t index, nxtindex;
- pgno_t pg;
- u_int32_t nbytes;
- int dflags, status;
- char *dest, db[NOVFLSIZE];
-
- /*
- * If the data won't fit on a page, store it on indirect pages.
- *
- * XXX
- * If the insert fails later on, these pages aren't recovered.
- */
- if (data->size > t->bt_ovflsize) {
- if (__ovfl_put(t, data, &pg) == RET_ERROR)
- return (RET_ERROR);
- tdata.data = db;
- tdata.size = NOVFLSIZE;
- *(pgno_t *)db = pg;
- *(u_int32_t *)(db + sizeof(pgno_t)) = data->size;
- dflags = P_BIGDATA;
- data = &tdata;
- } else
- dflags = 0;
-
- /* __rec_search pins the returned page. */
- if ((e = __rec_search(t, nrec,
- nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ?
- SINSERT : SEARCH)) == NULL)
- return (RET_ERROR);
-
- h = e->page;
- index = e->index;
-
- /*
- * Add the specified key/data pair to the tree. The R_IAFTER and
- * R_IBEFORE flags insert the key after/before the specified key.
- *
- * Pages are split as required.
- */
- switch (flags) {
- case R_IAFTER:
- ++index;
- break;
- case R_IBEFORE:
- break;
- default:
- if (nrec < t->bt_nrecs &&
- __rec_dleaf(t, h, index) == RET_ERROR) {
- mpool_put(t->bt_mp, h, 0);
- return (RET_ERROR);
- }
- break;
- }
-
- /*
- * If not enough room, split the page. The split code will insert
- * the key and data and unpin the current page. If inserting into
- * the offset array, shift the pointers up.
- */
- nbytes = NRLEAFDBT(data->size);
- if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) {
- status = __bt_split(t, h, NULL, data, dflags, nbytes, index);
- if (status == RET_SUCCESS)
- ++t->bt_nrecs;
- return (status);
- }
-
- if (index < (nxtindex = NEXTINDEX(h)))
- memmove(h->linp + index + 1, h->linp + index,
- (nxtindex - index) * sizeof(indx_t));
- h->lower += sizeof(indx_t);
-
- h->linp[index] = h->upper -= nbytes;
- dest = (char *)h + h->upper;
- WR_RLEAF(dest, data, dflags);
-
- ++t->bt_nrecs;
- F_SET(t, B_MODIFIED);
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
-
- return (RET_SUCCESS);
-}
diff --git a/main/db1-ast/recno/rec_search.c b/main/db1-ast/recno/rec_search.c
deleted file mode 100644
index e70fe4c13..000000000
--- a/main/db1-ast/recno/rec_search.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rec_search.c 8.4 (Berkeley) 7/14/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdio.h>
-
-#include "../include/db.h"
-#include "recno.h"
-
-/*
- * __REC_SEARCH -- Search a btree for a key.
- *
- * Parameters:
- * t: tree to search
- * recno: key to find
- * op: search operation
- *
- * Returns:
- * EPG for matching record, if any, or the EPG for the location of the
- * key, if it were inserted into the tree.
- *
- * Returns:
- * The EPG for matching record, if any, or the EPG for the location
- * of the key, if it were inserted into the tree, is entered into
- * the bt_cur field of the tree. A pointer to the field is returned.
- */
-EPG *
-__rec_search(t, recno, op)
- BTREE *t;
- recno_t recno;
- enum SRCHOP op;
-{
- register indx_t index;
- register PAGE *h;
- EPGNO *parent;
- RINTERNAL *r;
- pgno_t pg;
- indx_t top;
- recno_t total;
- int sverrno;
-
- BT_CLR(t);
- for (pg = P_ROOT, total = 0;;) {
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- goto err;
- if (h->flags & P_RLEAF) {
- t->bt_cur.page = h;
- t->bt_cur.index = recno - total;
- return (&t->bt_cur);
- }
- for (index = 0, top = NEXTINDEX(h);;) {
- r = GETRINTERNAL(h, index);
- if (++index == top || total + r->nrecs > recno)
- break;
- total += r->nrecs;
- }
-
- BT_PUSH(t, pg, index - 1);
-
- pg = r->pgno;
- switch (op) {
- case SDELETE:
- --GETRINTERNAL(h, (index - 1))->nrecs;
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- break;
- case SINSERT:
- ++GETRINTERNAL(h, (index - 1))->nrecs;
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- break;
- case SEARCH:
- mpool_put(t->bt_mp, h, 0);
- break;
- }
-
- }
- /* Try and recover the tree. */
-err: sverrno = errno;
- if (op != SEARCH)
- while ((parent = BT_POP(t)) != NULL) {
- if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
- break;
- if (op == SINSERT)
- --GETRINTERNAL(h, parent->index)->nrecs;
- else
- ++GETRINTERNAL(h, parent->index)->nrecs;
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- }
- errno = sverrno;
- return (NULL);
-}
diff --git a/main/db1-ast/recno/rec_seq.c b/main/db1-ast/recno/rec_seq.c
deleted file mode 100644
index ca3451ca6..000000000
--- a/main/db1-ast/recno/rec_seq.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94";
-#endif /* not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "recno.h"
-
-/*
- * __REC_SEQ -- Recno sequential scan interface.
- *
- * Parameters:
- * dbp: pointer to access method
- * key: key for positioning and return value
- * data: data return value
- * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
- */
-int
-__rec_seq(dbp, key, data, flags)
- const DB *dbp;
- DBT *key, *data;
- u_int flags;
-{
- BTREE *t;
- EPG *e;
- recno_t nrec;
- int status;
-
- t = dbp->internal;
-
- /* Toss any page pinned across calls. */
- if (t->bt_pinned != NULL) {
- mpool_put(t->bt_mp, t->bt_pinned, 0);
- t->bt_pinned = NULL;
- }
-
- switch(flags) {
- case R_CURSOR:
- if ((nrec = *(recno_t *)key->data) == 0)
- goto einval;
- break;
- case R_NEXT:
- if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
- nrec = t->bt_cursor.rcursor + 1;
- break;
- }
- /* FALLTHROUGH */
- case R_FIRST:
- nrec = 1;
- break;
- case R_PREV:
- if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
- if ((nrec = t->bt_cursor.rcursor - 1) == 0)
- return (RET_SPECIAL);
- break;
- }
- /* FALLTHROUGH */
- case R_LAST:
- if (!F_ISSET(t, R_EOF | R_INMEM) &&
- t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
- return (RET_ERROR);
- nrec = t->bt_nrecs;
- break;
- default:
-einval: errno = EINVAL;
- return (RET_ERROR);
- }
-
- if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
- if (!F_ISSET(t, R_EOF | R_INMEM) &&
- (status = t->bt_irec(t, nrec)) != RET_SUCCESS)
- return (status);
- if (t->bt_nrecs == 0 || nrec > t->bt_nrecs)
- return (RET_SPECIAL);
- }
-
- if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL)
- return (RET_ERROR);
-
- F_SET(&t->bt_cursor, CURS_INIT);
- t->bt_cursor.rcursor = nrec;
-
- status = __rec_ret(t, e, nrec, key, data);
- if (F_ISSET(t, B_DB_LOCK))
- mpool_put(t->bt_mp, e->page, 0);
- else
- t->bt_pinned = e->page;
- return (status);
-}
diff --git a/main/db1-ast/recno/rec_utils.c b/main/db1-ast/recno/rec_utils.c
deleted file mode 100644
index ddc309712..000000000
--- a/main/db1-ast/recno/rec_utils.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)rec_utils.c 8.6 (Berkeley) 7/16/94";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../include/db.h"
-#include "recno.h"
-
-/*
- * __rec_ret --
- * Build return data.
- *
- * Parameters:
- * t: tree
- * e: key/data pair to be returned
- * nrec: record number
- * key: user's key structure
- * data: user's data structure
- *
- * Returns:
- * RET_SUCCESS, RET_ERROR.
- */
-int
-__rec_ret(t, e, nrec, key, data)
- BTREE *t;
- EPG *e;
- recno_t nrec;
- DBT *key, *data;
-{
- RLEAF *rl;
- void *p;
-
- if (key == NULL)
- goto dataonly;
-
- /* We have to copy the key, it's not on the page. */
- if (sizeof(recno_t) > t->bt_rkey.size) {
- p = (void *)(t->bt_rkey.data == NULL ?
- malloc(sizeof(recno_t)) :
- realloc(t->bt_rkey.data, sizeof(recno_t)));
- if (p == NULL)
- return (RET_ERROR);
- t->bt_rkey.data = p;
- t->bt_rkey.size = sizeof(recno_t);
- }
- memmove(t->bt_rkey.data, &nrec, sizeof(recno_t));
- key->size = sizeof(recno_t);
- key->data = t->bt_rkey.data;
-
-dataonly:
- if (data == NULL)
- return (RET_SUCCESS);
-
- /*
- * We must copy big keys/data to make them contiguous. Otherwise,
- * leave the page pinned and don't copy unless the user specified
- * concurrent access.
- */
- rl = GETRLEAF(e->page, e->index);
- if (rl->flags & P_BIGDATA) {
- if (__ovfl_get(t, rl->bytes,
- &data->size, &t->bt_rdata.data, &t->bt_rdata.size))
- return (RET_ERROR);
- data->data = t->bt_rdata.data;
- } else if (F_ISSET(t, B_DB_LOCK)) {
- /* Use +1 in case the first record retrieved is 0 length. */
- if (rl->dsize + 1 > t->bt_rdata.size) {
- p = (void *)(t->bt_rdata.data == NULL ?
- malloc(rl->dsize + 1) :
- realloc(t->bt_rdata.data, rl->dsize + 1));
- if (p == NULL)
- return (RET_ERROR);
- t->bt_rdata.data = p;
- t->bt_rdata.size = rl->dsize + 1;
- }
- memmove(t->bt_rdata.data, rl->bytes, rl->dsize);
- data->size = rl->dsize;
- data->data = t->bt_rdata.data;
- } else {
- data->size = rl->dsize;
- data->data = rl->bytes;
- }
- return (RET_SUCCESS);
-}
diff --git a/main/db1-ast/recno/recno.h b/main/db1-ast/recno/recno.h
deleted file mode 100644
index bec772c2f..000000000
--- a/main/db1-ast/recno/recno.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)recno.h 8.1 (Berkeley) 6/4/93
- */
-
-enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */
-
-#include "../btree/btree.h"
-#include "extern.h"
diff --git a/main/devicestate.c b/main/devicestate.c
deleted file mode 100644
index f84c87df7..000000000
--- a/main/devicestate.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Device state management
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "asterisk/channel.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/logger.h"
-#include "asterisk/devicestate.h"
-#include "asterisk/pbx.h"
-#include "asterisk/app.h"
-#include "asterisk/options.h"
-
-/*! \brief Device state strings for printing */
-static const char *devstatestring[] = {
- /* 0 AST_DEVICE_UNKNOWN */ "Unknown", /*!< Valid, but unknown state */
- /* 1 AST_DEVICE_NOT_INUSE */ "Not in use", /*!< Not used */
- /* 2 AST_DEVICE IN USE */ "In use", /*!< In use */
- /* 3 AST_DEVICE_BUSY */ "Busy", /*!< Busy */
- /* 4 AST_DEVICE_INVALID */ "Invalid", /*!< Invalid - not known to Asterisk */
- /* 5 AST_DEVICE_UNAVAILABLE */ "Unavailable", /*!< Unavailable (not registred) */
- /* 6 AST_DEVICE_RINGING */ "Ringing", /*!< Ring, ring, ring */
- /* 7 AST_DEVICE_RINGINUSE */ "Ring+Inuse", /*!< Ring and in use */
- /* 8 AST_DEVICE_ONHOLD */ "On Hold" /*!< On Hold */
-};
-
-/*! \brief A device state provider (not a channel) */
-struct devstate_prov {
- char label[40];
- ast_devstate_prov_cb_type callback;
- AST_LIST_ENTRY(devstate_prov) list;
-};
-
-/*! \brief A list of providers */
-static AST_LIST_HEAD_STATIC(devstate_provs, devstate_prov);
-
-/*! \brief A device state watcher (callback) */
-struct devstate_cb {
- void *data;
- ast_devstate_cb_type callback;
- AST_LIST_ENTRY(devstate_cb) list;
-};
-
-/*! \brief A device state watcher list */
-static AST_LIST_HEAD_STATIC(devstate_cbs, devstate_cb);
-
-struct state_change {
- AST_LIST_ENTRY(state_change) list;
- char device[1];
-};
-
-/*! \brief The state change queue. State changes are queued
- for processing by a separate thread */
-static AST_LIST_HEAD_STATIC(state_changes, state_change);
-
-/*! \brief The device state change notification thread */
-static pthread_t change_thread = AST_PTHREADT_NULL;
-
-/*! \brief Flag for the queue */
-static ast_cond_t change_pending;
-
-/* Forward declarations */
-static int getproviderstate(const char *provider, const char *address);
-
-/*! \brief Find devicestate as text message for output */
-const char *devstate2str(int devstate)
-{
- return devstatestring[devstate];
-}
-
-/*! \brief Find out if device is active in a call or not
- \note find channels with the device's name in it
- This function is only used for channels that does not implement
- devicestate natively
-*/
-int ast_parse_device_state(const char *device)
-{
- struct ast_channel *chan;
- char match[AST_CHANNEL_NAME];
- int res;
-
- ast_copy_string(match, device, sizeof(match)-1);
- strcat(match, "-");
- chan = ast_get_channel_by_name_prefix_locked(match, strlen(match));
-
- if (!chan)
- return AST_DEVICE_UNKNOWN;
-
- if (chan->_state == AST_STATE_RINGING)
- res = AST_DEVICE_RINGING;
- else
- res = AST_DEVICE_INUSE;
-
- ast_channel_unlock(chan);
-
- return res;
-}
-
-/*! \brief Check device state through channel specific function or generic function */
-int ast_device_state(const char *device)
-{
- char *buf;
- char *number;
- const struct ast_channel_tech *chan_tech;
- int res = 0;
- /*! \brief Channel driver that provides device state */
- char *tech;
- /*! \brief Another provider of device state */
- char *provider = NULL;
-
- buf = ast_strdupa(device);
- tech = strsep(&buf, "/");
- number = buf;
- if (!number) {
- provider = strsep(&tech, ":");
- if (!provider)
- return AST_DEVICE_INVALID;
- /* We have a provider */
- number = tech;
- tech = NULL;
- }
-
- if (provider) {
- if(option_debug > 2)
- ast_log(LOG_DEBUG, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number);
- return getproviderstate(provider, number);
- }
- if (option_debug > 3)
- ast_log(LOG_DEBUG, "No provider found, checking channel drivers for %s - %s\n", tech, number);
-
- chan_tech = ast_get_channel_tech(tech);
- if (!chan_tech)
- return AST_DEVICE_INVALID;
-
- if (!chan_tech->devicestate) /* Does the channel driver support device state notification? */
- return ast_parse_device_state(device); /* No, try the generic function */
- else {
- res = chan_tech->devicestate(number); /* Ask the channel driver for device state */
- if (res == AST_DEVICE_UNKNOWN) {
- res = ast_parse_device_state(device);
- /* at this point we know the device exists, but the channel driver
- could not give us a state; if there is no channel state available,
- it must be 'not in use'
- */
- if (res == AST_DEVICE_UNKNOWN)
- res = AST_DEVICE_NOT_INUSE;
- return res;
- } else
- return res;
- }
-}
-
-/*! \brief Add device state provider */
-int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
-{
- struct devstate_prov *devprov;
-
- if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov))))
- return -1;
-
- devprov->callback = callback;
- ast_copy_string(devprov->label, label, sizeof(devprov->label));
-
- AST_LIST_LOCK(&devstate_provs);
- AST_LIST_INSERT_HEAD(&devstate_provs, devprov, list);
- AST_LIST_UNLOCK(&devstate_provs);
-
- return 0;
-}
-
-/*! \brief Remove device state provider */
-void ast_devstate_prov_del(const char *label)
-{
- struct devstate_prov *devcb;
-
- AST_LIST_LOCK(&devstate_provs);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) {
- if (!strcasecmp(devcb->label, label)) {
- AST_LIST_REMOVE_CURRENT(&devstate_provs, list);
- free(devcb);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&devstate_provs);
-}
-
-/*! \brief Get provider device state */
-static int getproviderstate(const char *provider, const char *address)
-{
- struct devstate_prov *devprov;
- int res = AST_DEVICE_INVALID;
-
-
- AST_LIST_LOCK(&devstate_provs);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devprov, list) {
- if(option_debug > 4)
- ast_log(LOG_DEBUG, "Checking provider %s with %s\n", devprov->label, provider);
-
- if (!strcasecmp(devprov->label, provider)) {
- res = devprov->callback(address);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&devstate_provs);
- return res;
-}
-
-/*! \brief Add device state watcher */
-int ast_devstate_add(ast_devstate_cb_type callback, void *data)
-{
- struct devstate_cb *devcb;
-
- if (!callback || !(devcb = ast_calloc(1, sizeof(*devcb))))
- return -1;
-
- devcb->data = data;
- devcb->callback = callback;
-
- AST_LIST_LOCK(&devstate_cbs);
- AST_LIST_INSERT_HEAD(&devstate_cbs, devcb, list);
- AST_LIST_UNLOCK(&devstate_cbs);
-
- return 0;
-}
-
-/*! \brief Remove device state watcher */
-void ast_devstate_del(ast_devstate_cb_type callback, void *data)
-{
- struct devstate_cb *devcb;
-
- AST_LIST_LOCK(&devstate_cbs);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&devstate_cbs, devcb, list) {
- if ((devcb->callback == callback) && (devcb->data == data)) {
- AST_LIST_REMOVE_CURRENT(&devstate_cbs, list);
- free(devcb);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&devstate_cbs);
-}
-
-/*! \brief Notify callback watchers of change, and notify PBX core for hint updates
- Normally executed within a separate thread
-*/
-static void do_state_change(const char *device)
-{
- int state;
- struct devstate_cb *devcb;
-
- state = ast_device_state(device);
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "Changing state for %s - state %d (%s)\n", device, state, devstate2str(state));
-
- AST_LIST_LOCK(&devstate_cbs);
- AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
- devcb->callback(device, state, devcb->data);
- AST_LIST_UNLOCK(&devstate_cbs);
-
- ast_hint_state_changed(device);
-}
-
-int ast_device_state_changed_literal(const char *device)
-{
- struct state_change *change;
-
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "Notification of state change to be queued on device/channel %s\n", device);
-
- if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
- /* we could not allocate a change struct, or */
- /* there is no background thread, so process the change now */
- do_state_change(device);
- } else {
- /* queue the change */
- strcpy(change->device, device);
- AST_LIST_LOCK(&state_changes);
- AST_LIST_INSERT_TAIL(&state_changes, change, list);
- if (AST_LIST_FIRST(&state_changes) == change)
- /* the list was empty, signal the thread */
- ast_cond_signal(&change_pending);
- AST_LIST_UNLOCK(&state_changes);
- }
-
- return 1;
-}
-
-/*! \brief Accept change notification, add it to change queue */
-int ast_device_state_changed(const char *fmt, ...)
-{
- char buf[AST_MAX_EXTENSION];
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
- return ast_device_state_changed_literal(buf);
-}
-
-/*! \brief Go through the dev state change queue and update changes in the dev state thread */
-static void *do_devstate_changes(void *data)
-{
- struct state_change *cur;
-
- AST_LIST_LOCK(&state_changes);
- for(;;) {
- /* the list lock will _always_ be held at this point in the loop */
- cur = AST_LIST_REMOVE_HEAD(&state_changes, list);
- if (cur) {
- /* we got an entry, so unlock the list while we process it */
- AST_LIST_UNLOCK(&state_changes);
- do_state_change(cur->device);
- free(cur);
- AST_LIST_LOCK(&state_changes);
- } else {
- /* there was no entry, so atomically unlock the list and wait for
- the condition to be signalled (returns with the lock held) */
- ast_cond_wait(&change_pending, &state_changes.lock);
- }
- }
-
- return NULL;
-}
-
-/*! \brief Initialize the device state engine in separate thread */
-int ast_device_state_engine_init(void)
-{
- ast_cond_init(&change_pending, NULL);
- if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) {
- ast_log(LOG_ERROR, "Unable to start device state change thread.\n");
- return -1;
- }
-
- return 0;
-}
diff --git a/main/dial.c b/main/dial.c
deleted file mode 100644
index 401e5af6c..000000000
--- a/main/dial.c
+++ /dev/null
@@ -1,894 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2007, Digium, Inc.
- *
- * Joshua Colp <jcolp@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Dialing API
- *
- * \author Joshua Colp <jcolp@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/options.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/dial.h"
-#include "asterisk/pbx.h"
-
-/*! \brief Main dialing structure. Contains global options, channels being dialed, and more! */
-struct ast_dial {
- int num; /*! Current number to give to next dialed channel */
- enum ast_dial_result state; /*! Status of dial */
- void *options[AST_DIAL_OPTION_MAX]; /*! Global options */
- ast_dial_state_callback state_callback; /*! Status callback */
- AST_LIST_HEAD(, ast_dial_channel) channels; /*! Channels being dialed */
- pthread_t thread; /*! Thread (if running in async) */
- ast_mutex_t lock; /*! Lock to protect the thread information above */
-};
-
-/*! \brief Dialing channel structure. Contains per-channel dialing options, asterisk channel, and more! */
-struct ast_dial_channel {
- int num; /*! Unique number for dialed channel */
- const char *tech; /*! Technology being dialed */
- const char *device; /*! Device being dialed */
- void *options[AST_DIAL_OPTION_MAX]; /*! Channel specific options */
- int cause; /*! Cause code in case of failure */
- int is_running_app:1; /*! Is this running an application? */
- struct ast_channel *owner; /*! Asterisk channel */
- AST_LIST_ENTRY(ast_dial_channel) list; /*! Linked list information */
-};
-
-/*! \brief Typedef for dial option enable */
-typedef void *(*ast_dial_option_cb_enable)(void *data);
-
-/*! \brief Typedef for dial option disable */
-typedef int (*ast_dial_option_cb_disable)(void *data);
-
-/* Structure for 'ANSWER_EXEC' option */
-struct answer_exec_struct {
- char app[AST_MAX_APP]; /* Application name */
- char *args; /* Application arguments */
-};
-
-/* Enable function for 'ANSWER_EXEC' option */
-static void *answer_exec_enable(void *data)
-{
- struct answer_exec_struct *answer_exec = NULL;
- char *app = ast_strdupa((char*)data), *args = NULL;
-
- /* Not giving any data to this option is bad, mmmk? */
- if (ast_strlen_zero(app))
- return NULL;
-
- /* Create new data structure */
- if (!(answer_exec = ast_calloc(1, sizeof(*answer_exec))))
- return NULL;
-
- /* Parse out application and arguments */
- if ((args = strchr(app, '|'))) {
- *args++ = '\0';
- answer_exec->args = ast_strdup(args);
- }
-
- /* Copy application name */
- ast_copy_string(answer_exec->app, app, sizeof(answer_exec->app));
-
- return answer_exec;
-}
-
-/* Disable function for 'ANSWER_EXEC' option */
-static int answer_exec_disable(void *data)
-{
- struct answer_exec_struct *answer_exec = data;
-
- /* Make sure we have a value */
- if (!answer_exec)
- return -1;
-
- /* If arguments are present, free them too */
- if (answer_exec->args)
- free(answer_exec->args);
-
- /* This is simple - just free the structure */
- free(answer_exec);
-
- return 0;
-}
-
-/* Application execution function for 'ANSWER_EXEC' option */
-static void answer_exec_run(struct ast_dial *dial, struct ast_dial_channel *dial_channel, char *app, char *args)
-{
- struct ast_channel *chan = dial_channel->owner;
- struct ast_app *ast_app = pbx_findapp(app);
-
- /* If the application was not found, return immediately */
- if (!ast_app)
- return;
-
- /* All is well... execute the application */
- pbx_exec(chan, ast_app, args);
-
- /* If another thread is not taking over hang up the channel */
- ast_mutex_lock(&dial->lock);
- if (dial->thread != AST_PTHREADT_STOP) {
- ast_hangup(chan);
- dial_channel->owner = NULL;
- }
- ast_mutex_unlock(&dial->lock);
-
- return;
-}
-
-/*! \brief Options structure - maps options to respective handlers (enable/disable). This list MUST be perfectly kept in order, or else madness will happen. */
-static const struct ast_option_types {
- enum ast_dial_option option;
- ast_dial_option_cb_enable enable;
- ast_dial_option_cb_disable disable;
-} option_types[] = {
- { AST_DIAL_OPTION_RINGING, NULL, NULL }, /*! Always indicate ringing to caller */
- { AST_DIAL_OPTION_ANSWER_EXEC, answer_exec_enable, answer_exec_disable }, /*! Execute application upon answer in async mode */
- { AST_DIAL_OPTION_MAX, NULL, NULL }, /*! Terminator of list */
-};
-
-/* free the buffer if allocated, and set the pointer to the second arg */
-#define S_REPLACE(s, new_val) \
- do { \
- if (s) \
- free(s); \
- s = (new_val); \
- } while (0)
-
-/*! \brief Maximum number of channels we can watch at a time */
-#define AST_MAX_WATCHERS 256
-
-/*! \brief Macro for finding the option structure to use on a dialed channel */
-#define FIND_RELATIVE_OPTION(dial, dial_channel, ast_dial_option) (dial_channel->options[ast_dial_option] ? dial_channel->options[ast_dial_option] : dial->options[ast_dial_option])
-
-/*! \brief Macro that determines whether a channel is the caller or not */
-#define IS_CALLER(chan, owner) (chan == owner ? 1 : 0)
-
-/*! \brief New dialing structure
- * \note Create a dialing structure
- * \return Returns a calloc'd ast_dial structure, NULL on failure
- */
-struct ast_dial *ast_dial_create(void)
-{
- struct ast_dial *dial = NULL;
-
- /* Allocate new memory for structure */
- if (!(dial = ast_calloc(1, sizeof(*dial))))
- return NULL;
-
- /* Initialize list of channels */
- AST_LIST_HEAD_INIT(&dial->channels);
-
- /* Initialize thread to NULL */
- dial->thread = AST_PTHREADT_NULL;
-
- /* Can't forget about the lock */
- ast_mutex_init(&dial->lock);
-
- return dial;
-}
-
-/*! \brief Append a channel
- * \note Appends a channel to a dialing structure
- * \return Returns channel reference number on success, -1 on failure
- */
-int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device)
-{
- struct ast_dial_channel *channel = NULL;
-
- /* Make sure we have required arguments */
- if (!dial || !tech || !device)
- return -1;
-
- /* Allocate new memory for dialed channel structure */
- if (!(channel = ast_calloc(1, sizeof(*channel))))
- return -1;
-
- /* Record technology and device for when we actually dial */
- channel->tech = tech;
- channel->device = device;
-
- /* Grab reference number from dial structure */
- channel->num = ast_atomic_fetchadd_int(&dial->num, +1);
-
- /* Insert into channels list */
- AST_LIST_INSERT_TAIL(&dial->channels, channel, list);
-
- return channel->num;
-}
-
-/*! \brief Helper function that does the beginning dialing */
-static int begin_dial(struct ast_dial *dial, struct ast_channel *chan)
-{
- struct ast_dial_channel *channel = NULL;
- int success = 0, res = 0;
-
- /* Iterate through channel list, requesting and calling each one */
- AST_LIST_LOCK(&dial->channels);
- AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- char numsubst[AST_MAX_EXTENSION];
-
- /* Copy device string over */
- ast_copy_string(numsubst, channel->device, sizeof(numsubst));
-
- /* Request that the channel be created */
- if (!(channel->owner = ast_request(channel->tech,
- chan ? chan->nativeformats : AST_FORMAT_AUDIO_MASK, numsubst, &channel->cause))) {
- continue;
- }
-
- channel->owner->appl = "AppDial2";
- channel->owner->data = "(Outgoing Line)";
- channel->owner->whentohangup = 0;
-
- /* Inherit everything from he who spawned this Dial */
- if (chan) {
- ast_channel_inherit_variables(chan, channel->owner);
-
- /* Copy over callerid information */
- S_REPLACE(channel->owner->cid.cid_num, ast_strdup(chan->cid.cid_num));
- S_REPLACE(channel->owner->cid.cid_name, ast_strdup(chan->cid.cid_name));
- S_REPLACE(channel->owner->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
- S_REPLACE(channel->owner->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
-
- ast_string_field_set(channel->owner, language, chan->language);
- ast_string_field_set(channel->owner, accountcode, chan->accountcode);
- channel->owner->cdrflags = chan->cdrflags;
- if (ast_strlen_zero(channel->owner->musicclass))
- ast_string_field_set(channel->owner, musicclass, chan->musicclass);
-
- channel->owner->cid.cid_pres = chan->cid.cid_pres;
- channel->owner->cid.cid_ton = chan->cid.cid_ton;
- channel->owner->cid.cid_tns = chan->cid.cid_tns;
- channel->owner->adsicpe = chan->adsicpe;
- channel->owner->transfercapability = chan->transfercapability;
- }
-
- /* Actually call the device */
- if ((res = ast_call(channel->owner, numsubst, 0))) {
- ast_hangup(channel->owner);
- channel->owner = NULL;
- } else {
- success++;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
- }
- }
- AST_LIST_UNLOCK(&dial->channels);
-
- /* If number of failures matches the number of channels, then this truly failed */
- return success;
-}
-
-/*! \brief Helper function that finds the dialed channel based on owner */
-static struct ast_dial_channel *find_relative_dial_channel(struct ast_dial *dial, struct ast_channel *owner)
-{
- struct ast_dial_channel *channel = NULL;
-
- AST_LIST_LOCK(&dial->channels);
- AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- if (channel->owner == owner)
- break;
- }
- AST_LIST_UNLOCK(&dial->channels);
-
- return channel;
-}
-
-static void set_state(struct ast_dial *dial, enum ast_dial_result state)
-{
- dial->state = state;
-
- if (dial->state_callback)
- dial->state_callback(dial);
-}
-
-/*! \brief Helper function that handles control frames WITH owner */
-static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr, struct ast_channel *chan)
-{
- if (fr->frametype == AST_FRAME_CONTROL) {
- switch (fr->subclass) {
- case AST_CONTROL_ANSWER:
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", channel->owner->name, chan->name);
- AST_LIST_LOCK(&dial->channels);
- AST_LIST_REMOVE(&dial->channels, channel, list);
- AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
- AST_LIST_UNLOCK(&dial->channels);
- set_state(dial, AST_DIAL_RESULT_ANSWERED);
- break;
- case AST_CONTROL_BUSY:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", channel->owner->name);
- ast_hangup(channel->owner);
- channel->owner = NULL;
- break;
- case AST_CONTROL_CONGESTION:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", channel->owner->name);
- ast_hangup(channel->owner);
- channel->owner = NULL;
- break;
- case AST_CONTROL_RINGING:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", channel->owner->name);
- ast_indicate(chan, AST_CONTROL_RINGING);
- set_state(dial, AST_DIAL_RESULT_RINGING);
- break;
- case AST_CONTROL_PROGRESS:
- if (option_verbose > 2)
- ast_verbose (VERBOSE_PREFIX_3 "%s is making progress, passing it to %s\n", channel->owner->name, chan->name);
- ast_indicate(chan, AST_CONTROL_PROGRESS);
- set_state(dial, AST_DIAL_RESULT_PROGRESS);
- break;
- case AST_CONTROL_VIDUPDATE:
- if (option_verbose > 2)
- ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", channel->owner->name, chan->name);
- ast_indicate(chan, AST_CONTROL_VIDUPDATE);
- break;
- case AST_CONTROL_SRCUPDATE:
- if (option_verbose > 2)
- ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name);
- ast_indicate(chan, AST_CONTROL_SRCUPDATE);
- break;
- case AST_CONTROL_PROCEEDING:
- if (option_verbose > 2)
- ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name);
- ast_indicate(chan, AST_CONTROL_PROCEEDING);
- set_state(dial, AST_DIAL_RESULT_PROCEEDING);
- break;
- case AST_CONTROL_HOLD:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", chan->name);
- ast_indicate(chan, AST_CONTROL_HOLD);
- break;
- case AST_CONTROL_UNHOLD:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", chan->name);
- ast_indicate(chan, AST_CONTROL_UNHOLD);
- break;
- case AST_CONTROL_OFFHOOK:
- case AST_CONTROL_FLASH:
- break;
- case -1:
- /* Prod the channel */
- ast_indicate(chan, -1);
- break;
- default:
- break;
- }
- }
-
- return;
-}
-
-/*! \brief Helper function that handles control frames WITHOUT owner */
-static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr)
-{
- /* If we have no owner we can only update the state of the dial structure, so only look at control frames */
- if (fr->frametype != AST_FRAME_CONTROL)
- return;
-
- switch (fr->subclass) {
- case AST_CONTROL_ANSWER:
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "%s answered\n", channel->owner->name);
- AST_LIST_LOCK(&dial->channels);
- AST_LIST_REMOVE(&dial->channels, channel, list);
- AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
- AST_LIST_UNLOCK(&dial->channels);
- set_state(dial, AST_DIAL_RESULT_ANSWERED);
- break;
- case AST_CONTROL_BUSY:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", channel->owner->name);
- ast_hangup(channel->owner);
- channel->owner = NULL;
- break;
- case AST_CONTROL_CONGESTION:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", channel->owner->name);
- ast_hangup(channel->owner);
- channel->owner = NULL;
- break;
- case AST_CONTROL_RINGING:
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", channel->owner->name);
- set_state(dial, AST_DIAL_RESULT_RINGING);
- break;
- case AST_CONTROL_PROGRESS:
- if (option_verbose > 2)
- ast_verbose (VERBOSE_PREFIX_3 "%s is making progress\n", channel->owner->name);
- set_state(dial, AST_DIAL_RESULT_PROGRESS);
- break;
- case AST_CONTROL_PROCEEDING:
- if (option_verbose > 2)
- ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding\n", channel->owner->name);
- set_state(dial, AST_DIAL_RESULT_PROCEEDING);
- break;
- default:
- break;
- }
-
- return;
-}
-
-/*! \brief Helper function that basically keeps tabs on dialing attempts */
-static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_channel *chan)
-{
- int timeout = -1, count = 0;
- struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL;
- struct ast_dial_channel *channel = NULL;
- struct answer_exec_struct *answer_exec = NULL;
-
- set_state(dial, AST_DIAL_RESULT_TRYING);
-
- /* If the "always indicate ringing" option is set, change state to ringing and indicate to the owner if present */
- if (dial->options[AST_DIAL_OPTION_RINGING]) {
- set_state(dial, AST_DIAL_RESULT_RINGING);
- if (chan)
- ast_indicate(chan, AST_CONTROL_RINGING);
- }
-
- /* Go into an infinite loop while we are trying */
- while ((dial->state != AST_DIAL_RESULT_UNANSWERED) && (dial->state != AST_DIAL_RESULT_ANSWERED) && (dial->state != AST_DIAL_RESULT_HANGUP) && (dial->state != AST_DIAL_RESULT_TIMEOUT)) {
- int pos = 0;
- struct ast_frame *fr = NULL;
-
- /* Set up channel structure array */
- pos = count = 0;
- if (chan)
- cs[pos++] = chan;
-
- /* Add channels we are attempting to dial */
- AST_LIST_LOCK(&dial->channels);
- AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- if (channel->owner) {
- cs[pos++] = channel->owner;
- count++;
- }
- }
- AST_LIST_UNLOCK(&dial->channels);
-
- /* If we have no outbound channels in progress, switch state to unanswered and stop */
- if (!count) {
- set_state(dial, AST_DIAL_RESULT_UNANSWERED);
- break;
- }
-
- /* Just to be safe... */
- if (dial->thread == AST_PTHREADT_STOP)
- break;
-
- /* Wait for frames from channels */
- who = ast_waitfor_n(cs, pos, &timeout);
-
- /* Check to see if our thread is being cancelled */
- if (dial->thread == AST_PTHREADT_STOP)
- break;
-
- /* If we are not being cancelled and we have no channel, then timeout was tripped */
- if (!who)
- continue;
-
- /* Find relative dial channel */
- if (!chan || !IS_CALLER(chan, who))
- channel = find_relative_dial_channel(dial, who);
-
- /* Attempt to read in a frame */
- if (!(fr = ast_read(who))) {
- /* If this is the caller then we switch state to hangup and stop */
- if (chan && IS_CALLER(chan, who)) {
- set_state(dial, AST_DIAL_RESULT_HANGUP);
- break;
- }
- ast_hangup(who);
- channel->owner = NULL;
- continue;
- }
-
- /* Process the frame */
- if (chan)
- handle_frame(dial, channel, fr, chan);
- else
- handle_frame_ownerless(dial, channel, fr);
-
- /* Free the received frame and start all over */
- ast_frfree(fr);
- }
-
- /* Do post-processing from loop */
- if (dial->state == AST_DIAL_RESULT_ANSWERED) {
- /* Hangup everything except that which answered */
- AST_LIST_LOCK(&dial->channels);
- AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- if (!channel->owner || channel->owner == who)
- continue;
- ast_hangup(channel->owner);
- channel->owner = NULL;
- }
- AST_LIST_UNLOCK(&dial->channels);
- /* If ANSWER_EXEC is enabled as an option, execute application on answered channel */
- if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) {
- channel->is_running_app = 1;
- answer_exec_run(dial, channel, answer_exec->app, answer_exec->args);
- channel->is_running_app = 0;
- }
- } else if (dial->state == AST_DIAL_RESULT_HANGUP) {
- /* Hangup everything */
- AST_LIST_LOCK(&dial->channels);
- AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- if (!channel->owner)
- continue;
- ast_hangup(channel->owner);
- channel->owner = NULL;
- }
- AST_LIST_UNLOCK(&dial->channels);
- }
-
- return dial->state;
-}
-
-/*! \brief Dial async thread function */
-static void *async_dial(void *data)
-{
- struct ast_dial *dial = data;
-
- /* This is really really simple... we basically pass monitor_dial a NULL owner and it changes it's behavior */
- monitor_dial(dial, NULL);
-
- return NULL;
-}
-
-/*! \brief Execute dialing synchronously or asynchronously
- * \note Dials channels in a dial structure.
- * \return Returns dial result code. (TRYING/INVALID/FAILED/ANSWERED/TIMEOUT/UNANSWERED).
- */
-enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
-{
- enum ast_dial_result res = AST_DIAL_RESULT_TRYING;
-
- /* Ensure required arguments are passed */
- if (!dial || (!chan && !async)) {
- ast_log(LOG_DEBUG, "invalid #1\n");
- return AST_DIAL_RESULT_INVALID;
- }
-
- /* If there are no channels to dial we can't very well try to dial them */
- if (AST_LIST_EMPTY(&dial->channels)) {
- ast_log(LOG_DEBUG, "invalid #2\n");
- return AST_DIAL_RESULT_INVALID;
- }
-
- /* Dial each requested channel */
- if (!begin_dial(dial, chan))
- return AST_DIAL_RESULT_FAILED;
-
- /* If we are running async spawn a thread and send it away... otherwise block here */
- if (async) {
- dial->state = AST_DIAL_RESULT_TRYING;
- /* Try to create a thread */
- if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
- /* Failed to create the thread - hangup all dialed channels and return failed */
- ast_dial_hangup(dial);
- res = AST_DIAL_RESULT_FAILED;
- }
- } else {
- res = monitor_dial(dial, chan);
- }
-
- return res;
-}
-
-/*! \brief Return channel that answered
- * \note Returns the Asterisk channel that answered
- * \param dial Dialing structure
- */
-struct ast_channel *ast_dial_answered(struct ast_dial *dial)
-{
- if (!dial)
- return NULL;
-
- return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL);
-}
-
-/*! \brief Return state of dial
- * \note Returns the state of the dial attempt
- * \param dial Dialing structure
- */
-enum ast_dial_result ast_dial_state(struct ast_dial *dial)
-{
- return dial->state;
-}
-
-/*! \brief Cancel async thread
- * \note Cancel a running async thread
- * \param dial Dialing structure
- */
-enum ast_dial_result ast_dial_join(struct ast_dial *dial)
-{
- pthread_t thread;
-
- /* If the dial structure is not running in async, return failed */
- if (dial->thread == AST_PTHREADT_NULL)
- return AST_DIAL_RESULT_FAILED;
-
- /* Record thread */
- thread = dial->thread;
-
- /* Boom, commence locking */
- ast_mutex_lock(&dial->lock);
-
- /* Stop the thread */
- dial->thread = AST_PTHREADT_STOP;
-
- /* If the answered channel is running an application we have to soft hangup it, can't just poke the thread */
- AST_LIST_LOCK(&dial->channels);
- if (AST_LIST_FIRST(&dial->channels)->is_running_app) {
- struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner;
- if (chan) {
- ast_channel_lock(chan);
- ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
- ast_channel_unlock(chan);
- }
- } else {
- /* Now we signal it with SIGURG so it will break out of it's waitfor */
- pthread_kill(thread, SIGURG);
- }
- AST_LIST_UNLOCK(&dial->channels);
-
- /* Yay done with it */
- ast_mutex_unlock(&dial->lock);
-
- /* Finally wait for the thread to exit */
- pthread_join(thread, NULL);
-
- /* Yay thread is all gone */
- dial->thread = AST_PTHREADT_NULL;
-
- return dial->state;
-}
-
-/*! \brief Hangup channels
- * \note Hangup all active channels
- * \param dial Dialing structure
- */
-void ast_dial_hangup(struct ast_dial *dial)
-{
- struct ast_dial_channel *channel = NULL;
-
- if (!dial)
- return;
-
- AST_LIST_LOCK(&dial->channels);
- AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- if (channel->owner) {
- ast_hangup(channel->owner);
- channel->owner = NULL;
- }
- }
- AST_LIST_UNLOCK(&dial->channels);
-
- return;
-}
-
-/*! \brief Destroys a dialing structure
- * \note Destroys (free's) the given ast_dial structure
- * \param dial Dialing structure to free
- * \return Returns 0 on success, -1 on failure
- */
-int ast_dial_destroy(struct ast_dial *dial)
-{
- int i = 0;
- struct ast_dial_channel *channel = NULL;
-
- if (!dial)
- return -1;
-
- /* Hangup and deallocate all the dialed channels */
- AST_LIST_LOCK(&dial->channels);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) {
- /* Disable any enabled options */
- for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
- if (!channel->options[i])
- continue;
- if (option_types[i].disable)
- option_types[i].disable(channel->options[i]);
- channel->options[i] = NULL;
- }
- /* Hang up channel if need be */
- if (channel->owner) {
- ast_hangup(channel->owner);
- channel->owner = NULL;
- }
- /* Free structure */
- AST_LIST_REMOVE_CURRENT(&dial->channels, list);
- free(channel);
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&dial->channels);
-
- /* Disable any enabled options globally */
- for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
- if (!dial->options[i])
- continue;
- if (option_types[i].disable)
- option_types[i].disable(dial->options[i]);
- dial->options[i] = NULL;
- }
-
- /* Lock be gone! */
- ast_mutex_destroy(&dial->lock);
-
- /* Free structure */
- free(dial);
-
- return 0;
-}
-
-/*! \brief Enables an option globally
- * \param dial Dial structure to enable option on
- * \param option Option to enable
- * \param data Data to pass to this option (not always needed)
- * \return Returns 0 on success, -1 on failure
- */
-int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
-{
- /* If the option is already enabled, return failure */
- if (dial->options[option])
- return -1;
-
- /* Execute enable callback if it exists, if not simply make sure the value is set */
- if (option_types[option].enable)
- dial->options[option] = option_types[option].enable(data);
- else
- dial->options[option] = (void*)1;
-
- return 0;
-}
-
-/*! \brief Enables an option per channel
- * \param dial Dial structure
- * \param num Channel number to enable option on
- * \param option Option to enable
- * \param data Data to pass to this option (not always needed)
- * \return Returns 0 on success, -1 on failure
- */
-int ast_dial_option_enable(struct ast_dial *dial, int num, enum ast_dial_option option, void *data)
-{
- struct ast_dial_channel *channel = NULL;
-
- /* Ensure we have required arguments */
- if (!dial || AST_LIST_EMPTY(&dial->channels))
- return -1;
-
- /* Look for channel, we can sort of cheat and predict things - the last channel in the list will probably be what they want */
- AST_LIST_LOCK(&dial->channels);
- if (AST_LIST_LAST(&dial->channels)->num != num) {
- AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- if (channel->num == num)
- break;
- }
- } else {
- channel = AST_LIST_LAST(&dial->channels);
- }
- AST_LIST_UNLOCK(&dial->channels);
-
- /* If none found, return failure */
- if (!channel)
- return -1;
-
- /* If the option is already enabled, return failure */
- if (channel->options[option])
- return -1;
-
- /* Execute enable callback if it exists, if not simply make sure the value is set */
- if (option_types[option].enable)
- channel->options[option] = option_types[option].enable(data);
- else
- channel->options[option] = (void*)1;
-
- return 0;
-}
-
-/*! \brief Disables an option globally
- * \param dial Dial structure to disable option on
- * \param option Option to disable
- * \return Returns 0 on success, -1 on failure
- */
-int ast_dial_option_global_disable(struct ast_dial *dial, enum ast_dial_option option)
-{
- /* If the option is not enabled, return failure */
- if (!dial->options[option])
- return -1;
-
- /* Execute callback of option to disable if it exists */
- if (option_types[option].disable)
- option_types[option].disable(dial->options[option]);
-
- /* Finally disable option on the structure */
- dial->options[option] = NULL;
-
- return 0;
-}
-
-/*! \brief Disables an option per channel
- * \param dial Dial structure
- * \param num Channel number to disable option on
- * \param option Option to disable
- * \return Returns 0 on success, -1 on failure
- */
-int ast_dial_option_disable(struct ast_dial *dial, int num, enum ast_dial_option option)
-{
- struct ast_dial_channel *channel = NULL;
-
- /* Ensure we have required arguments */
- if (!dial || AST_LIST_EMPTY(&dial->channels))
- return -1;
-
- /* Look for channel, we can sort of cheat and predict things - the last channel in the list will probably be what they want */
- AST_LIST_LOCK(&dial->channels);
- if (AST_LIST_LAST(&dial->channels)->num != num) {
- AST_LIST_TRAVERSE(&dial->channels, channel, list) {
- if (channel->num == num)
- break;
- }
- } else {
- channel = AST_LIST_LAST(&dial->channels);
- }
- AST_LIST_UNLOCK(&dial->channels);
-
- /* If none found, return failure */
- if (!channel)
- return -1;
-
- /* If the option is not enabled, return failure */
- if (!channel->options[option])
- return -1;
-
- /* Execute callback of option to disable it if it exists */
- if (option_types[option].disable)
- option_types[option].disable(channel->options[option]);
-
- /* Finally disable the option on the structure */
- channel->options[option] = NULL;
-
- return 0;
-}
-
-void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
-{
- dial->state_callback = callback;
-}
diff --git a/main/dns.c b/main/dns.c
deleted file mode 100644
index dc0d3c818..000000000
--- a/main/dns.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006 Thorsten Lockert
- *
- * Written by Thorsten Lockert <tholo@trollphone.org>
- *
- * Funding provided by Troll Phone Networks AS
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief DNS Support for Asterisk
- *
- * \author Thorsten Lockert <tholo@trollphone.org>
- *
- * \par Reference
- * - DNR SRV records http://www.ietf.org/rfc/rfc2782.txt
- *
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <unistd.h>
-
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/dns.h"
-#include "asterisk/endian.h"
-
-#define MAX_SIZE 4096
-
-/* The dns_HEADER structure definition below originated
- in the arpa/nameser.h header file distributed with ISC
- BIND, which contains the following copyright and license
- notices:
-
- * ++Copyright++ 1983, 1989, 1993
- * -
- * Copyright (c) 1983, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * -
- * --Copyright--
- */
-
-typedef struct {
- unsigned id:16; /*!< query identification number */
-#if __BYTE_ORDER == __BIG_ENDIAN
- /* fields in third byte */
- unsigned qr:1; /*!< response flag */
- unsigned opcode:4; /*!< purpose of message */
- unsigned aa:1; /*!< authoritive answer */
- unsigned tc:1; /*!< truncated message */
- unsigned rd:1; /*!< recursion desired */
- /* fields in fourth byte */
- unsigned ra:1; /*!< recursion available */
- unsigned unused:1; /*!< unused bits (MBZ as of 4.9.3a3) */
- unsigned ad:1; /*!< authentic data from named */
- unsigned cd:1; /*!< checking disabled by resolver */
- unsigned rcode:4; /*!< response code */
-#endif
-#if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN
- /* fields in third byte */
- unsigned rd:1; /*!< recursion desired */
- unsigned tc:1; /*!< truncated message */
- unsigned aa:1; /*!< authoritive answer */
- unsigned opcode:4; /*!< purpose of message */
- unsigned qr:1; /*!< response flag */
- /* fields in fourth byte */
- unsigned rcode:4; /*!< response code */
- unsigned cd:1; /*!< checking disabled by resolver */
- unsigned ad:1; /*!< authentic data from named */
- unsigned unused:1; /*!< unused bits (MBZ as of 4.9.3a3) */
- unsigned ra:1; /*!< recursion available */
-#endif
- /* remaining bytes */
- unsigned qdcount:16; /*!< number of question entries */
- unsigned ancount:16; /*!< number of answer entries */
- unsigned nscount:16; /*!< number of authority entries */
- unsigned arcount:16; /*!< number of resource entries */
-} dns_HEADER;
-
-struct dn_answer {
- unsigned short rtype;
- unsigned short class;
- unsigned int ttl;
- unsigned short size;
-} __attribute__((__packed__));
-
-static int skip_name(unsigned char *s, int len)
-{
- int x = 0;
-
- while (x < len) {
- if (*s == '\0') {
- s++;
- x++;
- break;
- }
- if ((*s & 0xc0) == 0xc0) {
- s += 2;
- x += 2;
- break;
- }
- x += *s + 1;
- s += *s + 1;
- }
- if (x >= len)
- return -1;
- return x;
-}
-
-/*! \brief Parse DNS lookup result, call callback */
-static int dns_parse_answer(void *context,
- int class, int type, unsigned char *answer, int len,
- int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
-{
- unsigned char *fullanswer = answer;
- struct dn_answer *ans;
- dns_HEADER *h;
- int res;
- int x;
-
- h = (dns_HEADER *)answer;
- answer += sizeof(dns_HEADER);
- len -= sizeof(dns_HEADER);
-
- for (x = 0; x < ntohs(h->qdcount); x++) {
- if ((res = skip_name(answer, len)) < 0) {
- ast_log(LOG_WARNING, "Couldn't skip over name\n");
- return -1;
- }
- answer += res + 4; /* Skip name and QCODE / QCLASS */
- len -= res + 4;
- if (len < 0) {
- ast_log(LOG_WARNING, "Strange query size\n");
- return -1;
- }
- }
-
- for (x = 0; x < ntohs(h->ancount); x++) {
- if ((res = skip_name(answer, len)) < 0) {
- ast_log(LOG_WARNING, "Failed skipping name\n");
- return -1;
- }
- answer += res;
- len -= res;
- ans = (struct dn_answer *)answer;
- answer += sizeof(struct dn_answer);
- len -= sizeof(struct dn_answer);
- if (len < 0) {
- ast_log(LOG_WARNING, "Strange result size\n");
- return -1;
- }
- if (len < 0) {
- ast_log(LOG_WARNING, "Length exceeds frame\n");
- return -1;
- }
-
- if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
- if (callback) {
- if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) {
- ast_log(LOG_WARNING, "Failed to parse result\n");
- return -1;
- }
- if (res > 0)
- return 1;
- }
- }
- answer += ntohs(ans->size);
- len -= ntohs(ans->size);
- }
- return 0;
-}
-
-#ifndef HAVE_RES_NINIT
-AST_MUTEX_DEFINE_STATIC(res_lock);
-#endif
-
-/*! \brief Lookup record in DNS
-\note Asterisk DNS is synchronus at this time. This means that if your DNS does
-not work properly, Asterisk might not start properly or a channel may lock.
-*/
-int ast_search_dns(void *context,
- const char *dname, int class, int type,
- int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
-{
-#ifdef HAVE_RES_NINIT
- struct __res_state dnsstate;
-#endif
- unsigned char answer[MAX_SIZE];
- int res, ret = -1;
-
-#ifdef HAVE_RES_NINIT
- memset(&dnsstate, 0, sizeof(dnsstate));
- res_ninit(&dnsstate);
- res = res_nsearch(&dnsstate, dname, class, type, answer, sizeof(answer));
-#else
- ast_mutex_lock(&res_lock);
- res_init();
- res = res_search(dname, class, type, answer, sizeof(answer));
-#endif
- if (res > 0) {
- if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
- ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
- ret = -1;
- }
- else if (res == 0) {
- ast_log(LOG_DEBUG, "No matches found in DNS for %s\n", dname);
- ret = 0;
- }
- else
- ret = 1;
- }
-#ifdef HAVE_RES_NINIT
-#ifdef HAVE_RES_NDESTROY
- res_ndestroy(&dnsstate);
-#else
- res_nclose(&dnsstate);
-#endif
-#else
-#ifndef __APPLE__
- res_close();
-#endif
- ast_mutex_unlock(&res_lock);
-#endif
-
- return ret;
-}
diff --git a/main/dnsmgr.c b/main/dnsmgr.c
deleted file mode 100644
index deb5c73db..000000000
--- a/main/dnsmgr.c
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2005-2006, Kevin P. Fleming
- *
- * Kevin P. Fleming <kpfleming@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Background DNS update manager
- *
- * \author Kevin P. Fleming <kpfleming@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <regex.h>
-#include <signal.h>
-
-#include "asterisk/dnsmgr.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/utils.h"
-#include "asterisk/config.h"
-#include "asterisk/logger.h"
-#include "asterisk/sched.h"
-#include "asterisk/options.h"
-#include "asterisk/cli.h"
-
-static struct sched_context *sched;
-static int refresh_sched = -1;
-static pthread_t refresh_thread = AST_PTHREADT_NULL;
-
-struct ast_dnsmgr_entry {
- /*! where we will store the resulting address */
- struct in_addr *result;
- /*! the last result, used to check if address has changed */
- struct in_addr last;
- /*! Set to 1 if the entry changes */
- int changed:1;
- ast_mutex_t lock;
- AST_LIST_ENTRY(ast_dnsmgr_entry) list;
- /*! just 1 here, but we use calloc to allocate the correct size */
- char name[1];
-};
-
-static AST_LIST_HEAD_STATIC(entry_list, ast_dnsmgr_entry);
-
-AST_MUTEX_DEFINE_STATIC(refresh_lock);
-
-#define REFRESH_DEFAULT 300
-
-static int enabled;
-static int refresh_interval;
-
-struct refresh_info {
- struct entry_list *entries;
- int verbose;
- unsigned int regex_present:1;
- regex_t filter;
-};
-
-static struct refresh_info master_refresh_info = {
- .entries = &entry_list,
- .verbose = 0,
-};
-
-struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct in_addr *result)
-{
- struct ast_dnsmgr_entry *entry;
-
- if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, sizeof(*entry) + strlen(name))))
- return NULL;
-
- entry->result = result;
- ast_mutex_init(&entry->lock);
- strcpy(entry->name, name);
- memcpy(&entry->last, result, sizeof(entry->last));
-
- AST_LIST_LOCK(&entry_list);
- AST_LIST_INSERT_HEAD(&entry_list, entry, list);
- AST_LIST_UNLOCK(&entry_list);
-
- return entry;
-}
-
-void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry)
-{
- if (!entry)
- return;
-
- AST_LIST_LOCK(&entry_list);
- AST_LIST_REMOVE(&entry_list, entry, list);
- AST_LIST_UNLOCK(&entry_list);
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_4 "removing dns manager for '%s'\n", entry->name);
-
- ast_mutex_destroy(&entry->lock);
- free(entry);
-}
-
-int ast_dnsmgr_lookup(const char *name, struct in_addr *result, struct ast_dnsmgr_entry **dnsmgr)
-{
- struct ast_hostent ahp;
- struct hostent *hp;
-
- if (ast_strlen_zero(name) || !result || !dnsmgr)
- return -1;
-
- if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name))
- return 0;
-
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_4 "doing dnsmgr_lookup for '%s'\n", name);
-
- /* if it's actually an IP address and not a name,
- there's no need for a managed lookup */
- if (inet_aton(name, result))
- return 0;
-
- /* do a lookup now but add a manager so it will automagically get updated in the background */
- if ((hp = ast_gethostbyname(name, &ahp)))
- memcpy(result, hp->h_addr, sizeof(result));
-
- /* if dnsmgr is not enable don't bother adding an entry */
- if (!enabled)
- return 0;
-
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_2 "adding dns manager for '%s'\n", name);
- *dnsmgr = ast_dnsmgr_get(name, result);
- return !*dnsmgr;
-}
-
-/*
- * Refresh a dnsmgr entry
- */
-static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose)
-{
- struct ast_hostent ahp;
- struct hostent *hp;
- char iabuf[INET_ADDRSTRLEN];
- char iabuf2[INET_ADDRSTRLEN];
- struct in_addr tmp;
- int changed = 0;
-
- ast_mutex_lock(&entry->lock);
- if (verbose && (option_verbose > 2))
- ast_verbose(VERBOSE_PREFIX_2 "refreshing '%s'\n", entry->name);
-
- if ((hp = ast_gethostbyname(entry->name, &ahp))) {
- /* check to see if it has changed, do callback if requested (where de callback is defined ????) */
- memcpy(&tmp, hp->h_addr, sizeof(tmp));
- if (tmp.s_addr != entry->last.s_addr) {
- ast_copy_string(iabuf, ast_inet_ntoa(entry->last), sizeof(iabuf));
- ast_copy_string(iabuf2, ast_inet_ntoa(tmp), sizeof(iabuf2));
- ast_log(LOG_NOTICE, "host '%s' changed from %s to %s\n",
- entry->name, iabuf, iabuf2);
- memcpy(entry->result, hp->h_addr, sizeof(entry->result));
- memcpy(&entry->last, hp->h_addr, sizeof(entry->last));
- changed = entry->changed = 1;
- }
-
- }
- ast_mutex_unlock(&entry->lock);
- return changed;
-}
-
-int ast_dnsmgr_refresh(struct ast_dnsmgr_entry *entry)
-{
- return dnsmgr_refresh(entry, 0);
-}
-
-/*
- * Check if dnsmgr entry has changed from since last call to this function
- */
-int ast_dnsmgr_changed(struct ast_dnsmgr_entry *entry)
-{
- int changed;
-
- ast_mutex_lock(&entry->lock);
-
- changed = entry->changed;
- entry->changed = 0;
-
- ast_mutex_unlock(&entry->lock);
-
- return changed;
-}
-
-static void *do_refresh(void *data)
-{
- for (;;) {
- pthread_testcancel();
- usleep((ast_sched_wait(sched)*1000));
- pthread_testcancel();
- ast_sched_runq(sched);
- }
- return NULL;
-}
-
-static int refresh_list(const void *data)
-{
- struct refresh_info *info = (struct refresh_info *)data;
- struct ast_dnsmgr_entry *entry;
-
- /* if a refresh or reload is already in progress, exit now */
- if (ast_mutex_trylock(&refresh_lock)) {
- if (info->verbose)
- ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n");
- return -1;
- }
-
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_2 "Refreshing DNS lookups.\n");
- AST_LIST_LOCK(info->entries);
- AST_LIST_TRAVERSE(info->entries, entry, list) {
- if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0))
- continue;
-
- dnsmgr_refresh(entry, info->verbose);
- }
- AST_LIST_UNLOCK(info->entries);
-
- ast_mutex_unlock(&refresh_lock);
-
- /* automatically reschedule based on the interval */
- return refresh_interval * 1000;
-}
-
-void dnsmgr_start_refresh(void)
-{
- if (refresh_sched > -1) {
- AST_SCHED_DEL(sched, refresh_sched);
- refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
- }
-}
-
-static int do_reload(int loading);
-
-static int handle_cli_reload(int fd, int argc, char *argv[])
-{
- if (argc > 2)
- return RESULT_SHOWUSAGE;
-
- do_reload(0);
- return 0;
-}
-
-static int handle_cli_refresh(int fd, int argc, char *argv[])
-{
- struct refresh_info info = {
- .entries = &entry_list,
- .verbose = 1,
- };
-
- if(!enabled) {
- ast_cli(fd, "DNS Manager is disabled.\n");
- return 0;
- }
-
- if (argc > 3)
- return RESULT_SHOWUSAGE;
-
- if (argc == 3) {
- if (regcomp(&info.filter, argv[2], REG_EXTENDED | REG_NOSUB))
- return RESULT_SHOWUSAGE;
- else
- info.regex_present = 1;
- }
-
- refresh_list(&info);
-
- if (info.regex_present)
- regfree(&info.filter);
-
- return 0;
-}
-
-static int handle_cli_status(int fd, int argc, char *argv[])
-{
- int count = 0;
- struct ast_dnsmgr_entry *entry;
-
- if (argc > 2)
- return RESULT_SHOWUSAGE;
-
- ast_cli(fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled");
- ast_cli(fd, "Refresh Interval: %d seconds\n", refresh_interval);
- AST_LIST_LOCK(&entry_list);
- AST_LIST_TRAVERSE(&entry_list, entry, list)
- count++;
- AST_LIST_UNLOCK(&entry_list);
- ast_cli(fd, "Number of entries: %d\n", count);
-
- return 0;
-}
-
-static struct ast_cli_entry cli_reload = {
- { "dnsmgr", "reload", NULL },
- handle_cli_reload, "Reloads the DNS manager configuration",
- "Usage: dnsmgr reload\n"
- " Reloads the DNS manager configuration.\n"
-};
-
-static struct ast_cli_entry cli_refresh = {
- { "dnsmgr", "refresh", NULL },
- handle_cli_refresh, "Performs an immediate refresh",
- "Usage: dnsmgr refresh [pattern]\n"
- " Peforms an immediate refresh of the managed DNS entries.\n"
- " Optional regular expression pattern is used to filter the entries to refresh.\n",
-};
-
-static struct ast_cli_entry cli_status = {
- { "dnsmgr", "status", NULL },
- handle_cli_status, "Display the DNS manager status",
- "Usage: dnsmgr status\n"
- " Displays the DNS manager status.\n"
-};
-
-int dnsmgr_init(void)
-{
- if (!(sched = sched_context_create())) {
- ast_log(LOG_ERROR, "Unable to create schedule context.\n");
- return -1;
- }
- ast_cli_register(&cli_reload);
- ast_cli_register(&cli_status);
- ast_cli_register(&cli_refresh);
- return do_reload(1);
-}
-
-int dnsmgr_reload(void)
-{
- return do_reload(0);
-}
-
-static int do_reload(int loading)
-{
- struct ast_config *config;
- const char *interval_value;
- const char *enabled_value;
- int interval;
- int was_enabled;
- int res = -1;
-
- /* ensure that no refresh cycles run while the reload is in progress */
- ast_mutex_lock(&refresh_lock);
-
- /* reset defaults in preparation for reading config file */
- refresh_interval = REFRESH_DEFAULT;
- was_enabled = enabled;
- enabled = 0;
-
- AST_SCHED_DEL(sched, refresh_sched);
-
- if ((config = ast_config_load("dnsmgr.conf"))) {
- if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
- enabled = ast_true(enabled_value);
- }
- if ((interval_value = ast_variable_retrieve(config, "general", "refreshinterval"))) {
- if (sscanf(interval_value, "%d", &interval) < 1)
- ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", interval_value);
- else if (interval < 0)
- ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval);
- else
- refresh_interval = interval;
- }
- ast_config_destroy(config);
- }
-
- if (enabled && refresh_interval)
- ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval);
-
- /* if this reload enabled the manager, create the background thread
- if it does not exist */
- if (enabled) {
- if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) {
- if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) {
- ast_log(LOG_ERROR, "Unable to start refresh thread.\n");
- }
- }
- /* make a background refresh happen right away */
- refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1);
- res = 0;
- }
- /* if this reload disabled the manager and there is a background thread,
- kill it */
- else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) {
- /* wake up the thread so it will exit */
- pthread_cancel(refresh_thread);
- pthread_kill(refresh_thread, SIGURG);
- pthread_join(refresh_thread, NULL);
- refresh_thread = AST_PTHREADT_NULL;
- res = 0;
- }
- else
- res = 0;
-
- ast_mutex_unlock(&refresh_lock);
-
- return res;
-}
diff --git a/main/dsp.c b/main/dsp.c
deleted file mode 100644
index 3caf65027..000000000
--- a/main/dsp.c
+++ /dev/null
@@ -1,1819 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * Goertzel routines are borrowed from Steve Underwood's tremendous work on the
- * DTMF detector.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Convenience Signal Processing routines
- *
- * \author Mark Spencer <markster@digium.com>
- * \author Steve Underwood <steveu@coppice.org>
- */
-
-/* Some routines from tone_detect.c by Steven Underwood as published under the zapata library */
-/*
- tone_detect.c - General telephony tone detection, and specific
- detection of DTMF.
-
- Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
-
- Despite my general liking of the GPL, I place this code in the
- public domain for the benefit of all mankind - even the slimy
- ones who might try to proprietize my work and use it to my
- detriment.
-*/
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <math.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include "asterisk/frame.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/dsp.h"
-#include "asterisk/ulaw.h"
-#include "asterisk/alaw.h"
-#include "asterisk/utils.h"
-
-/*! Number of goertzels for progress detect */
-enum gsamp_size {
- GSAMP_SIZE_NA = 183, /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */
- GSAMP_SIZE_CR = 188, /*!< Costa Rica, Brazil - Only care about 425 Hz */
- GSAMP_SIZE_UK = 160 /*!< UK disconnect goertzel feed - should trigger 400hz */
-};
-
-enum prog_mode {
- PROG_MODE_NA = 0,
- PROG_MODE_CR,
- PROG_MODE_UK
-};
-
-enum freq_index {
- /*! For US modes { */
- HZ_350 = 0,
- HZ_440,
- HZ_480,
- HZ_620,
- HZ_950,
- HZ_1400,
- HZ_1800, /*!< } */
-
- /*! For CR/BR modes */
- HZ_425 = 0,
-
- /*! For UK mode */
- HZ_400 = 0
-};
-
-static struct progalias {
- char *name;
- enum prog_mode mode;
-} aliases[] = {
- { "us", PROG_MODE_NA },
- { "ca", PROG_MODE_NA },
- { "cr", PROG_MODE_CR },
- { "br", PROG_MODE_CR },
- { "uk", PROG_MODE_UK },
-};
-
-static struct progress {
- enum gsamp_size size;
- int freqs[7];
-} modes[] = {
- { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } }, /*!< North America */
- { GSAMP_SIZE_CR, { 425 } }, /*!< Costa Rica, Brazil */
- { GSAMP_SIZE_UK, { 400 } }, /*!< UK */
-};
-
-#define DEFAULT_THRESHOLD 512
-
-enum busy_detect {
- BUSY_PERCENT = 10, /*!< The percentage difference between the two last silence periods */
- BUSY_PAT_PERCENT = 7, /*!< The percentage difference between measured and actual pattern */
- BUSY_THRESHOLD = 100, /*!< Max number of ms difference between max and min times in busy */
- BUSY_MIN = 75, /*!< Busy must be at least 80 ms in half-cadence */
- BUSY_MAX =3100 /*!< Busy can't be longer than 3100 ms in half-cadence */
-};
-
-/*! Remember last 15 units */
-#define DSP_HISTORY 15
-
-/*! Define if you want the fax detector -- NOT RECOMMENDED IN -STABLE */
-#define FAX_DETECT
-
-#define TONE_THRESH 10.0 /*!< How much louder the tone should be than channel energy */
-#define TONE_MIN_THRESH 1e8 /*!< How much tone there should be at least to attempt */
-
-/*! All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms) */
-enum gsamp_thresh {
- THRESH_RING = 8, /*!< Need at least 150ms ring to accept */
- THRESH_TALK = 2, /*!< Talk detection does not work continuously */
- THRESH_BUSY = 4, /*!< Need at least 80ms to accept */
- THRESH_CONGESTION = 4, /*!< Need at least 80ms to accept */
- THRESH_HANGUP = 60, /*!< Need at least 1300ms to accept hangup */
- THRESH_RING2ANSWER = 300 /*!< Timeout from start of ring to answer (about 6600 ms) */
-};
-
-#define MAX_DTMF_DIGITS 128
-
-/* Basic DTMF specs:
- *
- * Minimum tone on = 40ms
- * Minimum tone off = 50ms
- * Maximum digit rate = 10 per second
- * Normal twist <= 8dB accepted
- * Reverse twist <= 4dB accepted
- * S/N >= 15dB will detect OK
- * Attenuation <= 26dB will detect OK
- * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
- */
-
-#define DTMF_THRESHOLD 8.0e7
-#define FAX_THRESHOLD 8.0e7
-#define FAX_2ND_HARMONIC 2.0 /* 4dB */
-
-#ifdef RADIO_RELAX
-#define DTMF_NORMAL_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 11.3 : 6.3) /* 8dB sph 12.3 was 6.3 */
-#define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 9.5 : 2.5) /* 4dB normal sph 12.5 : 5.5 was 6.5 : 2.5 */
-#define DTMF_RELATIVE_PEAK_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 3.3 : 6.3) /* 8dB sph was 6.3 */
-#define DTMF_RELATIVE_PEAK_COL ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 3.3 : 6.3) /* 8dB sph was 6.3 */
-#define DTMF_TO_TOTAL_ENERGY ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 26.0 : 42.0)
-#else
-#define DTMF_NORMAL_TWIST 6.3
-#define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5) /* 4dB normal */
-#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
-#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
-#define DTMF_TO_TOTAL_ENERGY 42.0
-#endif
-
-#ifdef OLD_DSP_ROUTINES
-#define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) /* 4dB normal */
-#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */
-
-#define MF_THRESHOLD 8.0e7
-#define MF_NORMAL_TWIST 5.3 /* 8dB */
-#define MF_REVERSE_TWIST 4.0 /* was 2.5 */
-#define MF_RELATIVE_PEAK 5.3 /* 8dB */
-#define MF_2ND_HARMONIC 1.7 /* was 2.5 */
-#else
-#define BELL_MF_THRESHOLD 1.6e9
-#define BELL_MF_TWIST 4.0 /* 6dB */
-#define BELL_MF_RELATIVE_PEAK 12.6 /* 11dB */
-#endif
-
-#if !defined(BUSYDETECT_MARTIN) && !defined(BUSYDETECT) && !defined(BUSYDETECT_TONEONLY) && !defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
-#define BUSYDETECT_MARTIN
-#endif
-
-typedef struct {
- float v2;
- float v3;
- float fac;
-#ifndef OLD_DSP_ROUTINES
- int samples;
-#endif
-} goertzel_state_t;
-
-typedef struct
-{
- goertzel_state_t row_out[4];
- goertzel_state_t col_out[4];
-#ifdef FAX_DETECT
- goertzel_state_t fax_tone;
-#endif
-#ifdef OLD_DSP_ROUTINES
- goertzel_state_t row_out2nd[4];
- goertzel_state_t col_out2nd[4];
-#ifdef FAX_DETECT
- goertzel_state_t fax_tone2nd;
-#endif
- int hit1;
- int hit2;
- int hit3;
- int hit4;
-#else
- int lasthit;
-#endif
- int mhit;
- float energy;
- int current_sample;
-
- char digits[MAX_DTMF_DIGITS + 1];
-
- int current_digits;
- int detected_digits;
- int lost_digits;
- int digit_hits[16];
-#ifdef FAX_DETECT
- int fax_hits;
-#endif
-} dtmf_detect_state_t;
-
-typedef struct
-{
- goertzel_state_t tone_out[6];
- int mhit;
-#ifdef OLD_DSP_ROUTINES
- int hit1;
- int hit2;
- int hit3;
- int hit4;
- goertzel_state_t tone_out2nd[6];
- float energy;
-#else
- int hits[5];
-#endif
- int current_sample;
-
- char digits[MAX_DTMF_DIGITS + 1];
-
- int current_digits;
- int detected_digits;
- int lost_digits;
-#ifdef FAX_DETECT
- int fax_hits;
-#endif
-} mf_detect_state_t;
-
-static float dtmf_row[] =
-{
- 697.0, 770.0, 852.0, 941.0
-};
-static float dtmf_col[] =
-{
- 1209.0, 1336.0, 1477.0, 1633.0
-};
-
-static float mf_tones[] =
-{
- 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
-};
-
-#ifdef FAX_DETECT
-static float fax_freq = 1100.0;
-#endif
-
-static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
-
-#ifdef OLD_DSP_ROUTINES
-static char mf_hit[6][6] = {
- /* 700 + */ { 0, '1', '2', '4', '7', 'C' },
- /* 900 + */ { '1', 0, '3', '5', '8', 'A' },
- /* 1100 + */ { '2', '3', 0, '6', '9', '*' },
- /* 1300 + */ { '4', '5', '6', 0, '0', 'B' },
- /* 1500 + */ { '7', '8', '9', '0', 0, '#' },
- /* 1700 + */ { 'C', 'A', '*', 'B', '#', 0 },
-};
-#else
-static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
-#endif
-
-static inline void goertzel_sample(goertzel_state_t *s, short sample)
-{
- float v1;
- float fsamp = sample;
-
- v1 = s->v2;
- s->v2 = s->v3;
- s->v3 = s->fac * s->v2 - v1 + fsamp;
-}
-
-static inline void goertzel_update(goertzel_state_t *s, short *samps, int count)
-{
- int i;
-
- for (i=0;i<count;i++)
- goertzel_sample(s, samps[i]);
-}
-
-
-static inline float goertzel_result(goertzel_state_t *s)
-{
- return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac;
-}
-
-static inline void goertzel_init(goertzel_state_t *s, float freq, int samples)
-{
- s->v2 = s->v3 = 0.0;
- s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0));
-#ifndef OLD_DSP_ROUTINES
- s->samples = samples;
-#endif
-}
-
-static inline void goertzel_reset(goertzel_state_t *s)
-{
- s->v2 = s->v3 = 0.0;
-}
-
-struct ast_dsp {
- struct ast_frame f;
- int threshold;
- int totalsilence;
- int totalnoise;
- int features;
- int ringtimeout;
- int busymaybe;
- int busycount;
- int busy_tonelength;
- int busy_quietlength;
- int historicnoise[DSP_HISTORY];
- int historicsilence[DSP_HISTORY];
- goertzel_state_t freqs[7];
- int freqcount;
- int gsamps;
- enum gsamp_size gsamp_size;
- enum prog_mode progmode;
- int tstate;
- int tcount;
- int digitmode;
- int thinkdigit;
- float genergy;
- union {
- dtmf_detect_state_t dtmf;
- mf_detect_state_t mf;
- } td;
-};
-
-static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
-{
- int i;
-
-#ifdef OLD_DSP_ROUTINES
- s->hit1 =
- s->mhit =
- s->hit3 =
- s->hit4 =
- s->hit2 = 0;
-#else
- s->lasthit = 0;
-#endif
- for (i = 0; i < 4; i++) {
- goertzel_init (&s->row_out[i], dtmf_row[i], 102);
- goertzel_init (&s->col_out[i], dtmf_col[i], 102);
-#ifdef OLD_DSP_ROUTINES
- goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102);
- goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102);
-#endif
- s->energy = 0.0;
- }
-#ifdef FAX_DETECT
- /* Same for the fax dector */
- goertzel_init (&s->fax_tone, fax_freq, 102);
-
-#ifdef OLD_DSP_ROUTINES
- /* Same for the fax dector 2nd harmonic */
- goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102);
-#endif
-#endif /* FAX_DETECT */
- s->current_sample = 0;
- s->detected_digits = 0;
- s->current_digits = 0;
- memset(&s->digits, 0, sizeof(s->digits));
- s->lost_digits = 0;
- s->digits[0] = '\0';
-}
-
-static void ast_mf_detect_init (mf_detect_state_t *s)
-{
- int i;
-#ifdef OLD_DSP_ROUTINES
- s->hit1 =
- s->hit2 = 0;
-#else
- s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
-#endif
- for (i = 0; i < 6; i++) {
- goertzel_init (&s->tone_out[i], mf_tones[i], 160);
-#ifdef OLD_DSP_ROUTINES
- goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160);
- s->energy = 0.0;
-#endif
- }
- s->current_digits = 0;
- memset(&s->digits, 0, sizeof(s->digits));
- s->current_sample = 0;
- s->detected_digits = 0;
- s->lost_digits = 0;
- s->digits[0] = '\0';
- s->mhit = 0;
-}
-
-static int dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples,
- int digitmode, int *writeback, int faxdetect)
-{
- float row_energy[4];
- float col_energy[4];
-#ifdef FAX_DETECT
- float fax_energy;
-#ifdef OLD_DSP_ROUTINES
- float fax_energy_2nd;
-#endif
-#endif /* FAX_DETECT */
- float famp;
- float v1;
- int i;
- int j;
- int sample;
- int best_row;
- int best_col;
- int hit;
- int limit;
-
- hit = 0;
- for (sample = 0; sample < samples; sample = limit) {
- /* 102 is optimised to meet the DTMF specs. */
- if ((samples - sample) >= (102 - s->current_sample))
- limit = sample + (102 - s->current_sample);
- else
- limit = samples;
-#if defined(USE_3DNOW)
- _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
- _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
-#ifdef OLD_DSP_ROUTINES
- _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
- _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
-#endif
- /* XXX Need to fax detect for 3dnow too XXX */
- #warning "Fax Support Broken"
-#else
- /* The following unrolled loop takes only 35% (rough estimate) of the
- time of a rolled loop on the machine on which it was developed */
- for (j=sample;j<limit;j++) {
- famp = amp[j];
- s->energy += famp*famp;
- /* With GCC 2.95, the following unrolled code seems to take about 35%
- (rough estimate) as long as a neat little 0-3 loop */
- v1 = s->row_out[0].v2;
- s->row_out[0].v2 = s->row_out[0].v3;
- s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp;
- v1 = s->col_out[0].v2;
- s->col_out[0].v2 = s->col_out[0].v3;
- s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp;
- v1 = s->row_out[1].v2;
- s->row_out[1].v2 = s->row_out[1].v3;
- s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp;
- v1 = s->col_out[1].v2;
- s->col_out[1].v2 = s->col_out[1].v3;
- s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp;
- v1 = s->row_out[2].v2;
- s->row_out[2].v2 = s->row_out[2].v3;
- s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp;
- v1 = s->col_out[2].v2;
- s->col_out[2].v2 = s->col_out[2].v3;
- s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp;
- v1 = s->row_out[3].v2;
- s->row_out[3].v2 = s->row_out[3].v3;
- s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp;
- v1 = s->col_out[3].v2;
- s->col_out[3].v2 = s->col_out[3].v3;
- s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp;
-#ifdef FAX_DETECT
- /* Update fax tone */
- v1 = s->fax_tone.v2;
- s->fax_tone.v2 = s->fax_tone.v3;
- s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp;
-#endif /* FAX_DETECT */
-#ifdef OLD_DSP_ROUTINES
- v1 = s->col_out2nd[0].v2;
- s->col_out2nd[0].v2 = s->col_out2nd[0].v3;
- s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp;
- v1 = s->row_out2nd[0].v2;
- s->row_out2nd[0].v2 = s->row_out2nd[0].v3;
- s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp;
- v1 = s->col_out2nd[1].v2;
- s->col_out2nd[1].v2 = s->col_out2nd[1].v3;
- s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp;
- v1 = s->row_out2nd[1].v2;
- s->row_out2nd[1].v2 = s->row_out2nd[1].v3;
- s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp;
- v1 = s->col_out2nd[2].v2;
- s->col_out2nd[2].v2 = s->col_out2nd[2].v3;
- s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp;
- v1 = s->row_out2nd[2].v2;
- s->row_out2nd[2].v2 = s->row_out2nd[2].v3;
- s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp;
- v1 = s->col_out2nd[3].v2;
- s->col_out2nd[3].v2 = s->col_out2nd[3].v3;
- s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp;
- v1 = s->row_out2nd[3].v2;
- s->row_out2nd[3].v2 = s->row_out2nd[3].v3;
- s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp;
-#ifdef FAX_DETECT
- /* Update fax tone */
- v1 = s->fax_tone.v2;
- s->fax_tone2nd.v2 = s->fax_tone2nd.v3;
- s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp;
-#endif /* FAX_DETECT */
-#endif
- }
-#endif
- s->current_sample += (limit - sample);
- if (s->current_sample < 102) {
- if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
- /* If we had a hit last time, go ahead and clear this out since likely it
- will be another hit */
- for (i=sample;i<limit;i++)
- amp[i] = 0;
- *writeback = 1;
- }
- continue;
- }
-#ifdef FAX_DETECT
- /* Detect the fax energy, too */
- fax_energy = goertzel_result(&s->fax_tone);
-#endif
- /* We are at the end of a DTMF detection block */
- /* Find the peak row and the peak column */
- row_energy[0] = goertzel_result (&s->row_out[0]);
- col_energy[0] = goertzel_result (&s->col_out[0]);
-
- for (best_row = best_col = 0, i = 1; i < 4; i++) {
- row_energy[i] = goertzel_result (&s->row_out[i]);
- if (row_energy[i] > row_energy[best_row])
- best_row = i;
- col_energy[i] = goertzel_result (&s->col_out[i]);
- if (col_energy[i] > col_energy[best_col])
- best_col = i;
- }
- hit = 0;
- /* Basic signal level test and the twist test */
- if (row_energy[best_row] >= DTMF_THRESHOLD &&
- col_energy[best_col] >= DTMF_THRESHOLD &&
- col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
- col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
- /* Relative peak test */
- for (i = 0; i < 4; i++) {
- if ((i != best_col &&
- col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
- (i != best_row
- && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
- break;
- }
- }
-#ifdef OLD_DSP_ROUTINES
- /* ... and second harmonic test */
- if (i >= 4 &&
- (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy &&
- goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col]
- && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
-#else
- /* ... and fraction of total energy test */
- if (i >= 4 &&
- (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) {
-#endif
- /* Got a hit */
- hit = dtmf_positions[(best_row << 2) + best_col];
- if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
- /* Zero out frame data if this is part DTMF */
- for (i=sample;i<limit;i++)
- amp[i] = 0;
- *writeback = 1;
- }
-#ifdef OLD_DSP_ROUTINES
- /* Look for two successive similar results */
- /* The logic in the next test is:
- We need two successive identical clean detects, with
- something different preceeding it. This can work with
- back to back differing digits. More importantly, it
- can work with nasty phones that give a very wobbly start
- to a digit */
- if (hit == s->hit3 && s->hit3 != s->hit2) {
- s->mhit = hit;
- s->digit_hits[(best_row << 2) + best_col]++;
- s->detected_digits++;
- if (s->current_digits < MAX_DTMF_DIGITS) {
- s->digits[s->current_digits++] = hit;
- s->digits[s->current_digits] = '\0';
- } else {
- s->lost_digits++;
- }
- }
-#endif
- }
- }
-
-#ifndef OLD_DSP_ROUTINES
- /* Look for two successive similar results */
- /* The logic in the next test is:
- We need two successive identical clean detects, with
- something different preceeding it. This can work with
- back to back differing digits. More importantly, it
- can work with nasty phones that give a very wobbly start
- to a digit */
- if (hit == s->lasthit && hit != s->mhit) {
- if (hit) {
- s->digit_hits[(best_row << 2) + best_col]++;
- s->detected_digits++;
- if (s->current_digits < MAX_DTMF_DIGITS) {
- s->digits[s->current_digits++] = hit;
- s->digits[s->current_digits] = '\0';
- } else {
- s->lost_digits++;
- }
- }
- s->mhit = hit;
- }
-#endif
-
-#ifdef FAX_DETECT
- if (!hit && (fax_energy >= FAX_THRESHOLD) &&
- (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) &&
- (faxdetect)) {
-#if 0
- printf("Fax energy/Second Harmonic: %f\n", fax_energy);
-#endif
- /* XXX Probably need better checking than just this the energy XXX */
- hit = 'f';
- s->fax_hits++;
- } else {
- if (s->fax_hits > 5) {
- hit = 'f';
- s->mhit = 'f';
- s->detected_digits++;
- if (s->current_digits < MAX_DTMF_DIGITS) {
- s->digits[s->current_digits++] = hit;
- s->digits[s->current_digits] = '\0';
- } else {
- s->lost_digits++;
- }
- }
- s->fax_hits = 0;
- }
-#endif /* FAX_DETECT */
-#ifdef OLD_DSP_ROUTINES
- s->hit1 = s->hit2;
- s->hit2 = s->hit3;
- s->hit3 = hit;
-#else
- s->lasthit = hit;
-#endif
- /* Reinitialise the detector for the next block */
- for (i = 0; i < 4; i++) {
- goertzel_reset(&s->row_out[i]);
- goertzel_reset(&s->col_out[i]);
-#ifdef OLD_DSP_ROUTINES
- goertzel_reset(&s->row_out2nd[i]);
- goertzel_reset(&s->col_out2nd[i]);
-#endif
- }
-#ifdef FAX_DETECT
- goertzel_reset (&s->fax_tone);
-#ifdef OLD_DSP_ROUTINES
- goertzel_reset (&s->fax_tone2nd);
-#endif
-#endif
- s->energy = 0.0;
- s->current_sample = 0;
- }
-#ifdef OLD_DSP_ROUTINES
- if ((!s->mhit) || (s->mhit != hit)) {
- s->mhit = 0;
- return(0);
- }
- return (hit);
-#else
- return (s->mhit); /* return the debounced hit */
-#endif
-}
-
-/* MF goertzel size */
-#ifdef OLD_DSP_ROUTINES
-#define MF_GSIZE 160
-#else
-#define MF_GSIZE 120
-#endif
-
-static int mf_detect (mf_detect_state_t *s, int16_t amp[],
- int samples, int digitmode, int *writeback)
-{
-#ifdef OLD_DSP_ROUTINES
- float tone_energy[6];
- int best1;
- int best2;
- float max;
- int sofarsogood;
-#else
- float energy[6];
- int best;
- int second_best;
-#endif
- float famp;
- float v1;
- int i;
- int j;
- int sample;
- int hit;
- int limit;
-
- hit = 0;
- for (sample = 0; sample < samples; sample = limit) {
- /* 80 is optimised to meet the MF specs. */
- if ((samples - sample) >= (MF_GSIZE - s->current_sample))
- limit = sample + (MF_GSIZE - s->current_sample);
- else
- limit = samples;
-#if defined(USE_3DNOW)
- _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
- _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
-#ifdef OLD_DSP_ROUTINES
- _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
- _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
-#endif
- /* XXX Need to fax detect for 3dnow too XXX */
- #warning "Fax Support Broken"
-#else
- /* The following unrolled loop takes only 35% (rough estimate) of the
- time of a rolled loop on the machine on which it was developed */
- for (j = sample; j < limit; j++) {
- famp = amp[j];
-#ifdef OLD_DSP_ROUTINES
- s->energy += famp*famp;
-#endif
- /* With GCC 2.95, the following unrolled code seems to take about 35%
- (rough estimate) as long as a neat little 0-3 loop */
- v1 = s->tone_out[0].v2;
- s->tone_out[0].v2 = s->tone_out[0].v3;
- s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp;
- v1 = s->tone_out[1].v2;
- s->tone_out[1].v2 = s->tone_out[1].v3;
- s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp;
- v1 = s->tone_out[2].v2;
- s->tone_out[2].v2 = s->tone_out[2].v3;
- s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp;
- v1 = s->tone_out[3].v2;
- s->tone_out[3].v2 = s->tone_out[3].v3;
- s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp;
- v1 = s->tone_out[4].v2;
- s->tone_out[4].v2 = s->tone_out[4].v3;
- s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp;
- v1 = s->tone_out[5].v2;
- s->tone_out[5].v2 = s->tone_out[5].v3;
- s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp;
-#ifdef OLD_DSP_ROUTINES
- v1 = s->tone_out2nd[0].v2;
- s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3;
- s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp;
- v1 = s->tone_out2nd[1].v2;
- s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3;
- s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp;
- v1 = s->tone_out2nd[2].v2;
- s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3;
- s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp;
- v1 = s->tone_out2nd[3].v2;
- s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3;
- s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp;
- v1 = s->tone_out2nd[4].v2;
- s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3;
- s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp;
- v1 = s->tone_out2nd[3].v2;
- s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3;
- s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp;
-#endif
- }
-#endif
- s->current_sample += (limit - sample);
- if (s->current_sample < MF_GSIZE) {
- if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
- /* If we had a hit last time, go ahead and clear this out since likely it
- will be another hit */
- for (i=sample;i<limit;i++)
- amp[i] = 0;
- *writeback = 1;
- }
- continue;
- }
-#ifdef OLD_DSP_ROUTINES
- /* We're at the end of an MF detection block. Go ahead and calculate
- all the energies. */
- for (i=0;i<6;i++) {
- tone_energy[i] = goertzel_result(&s->tone_out[i]);
- }
- /* Find highest */
- best1 = 0;
- max = tone_energy[0];
- for (i=1;i<6;i++) {
- if (tone_energy[i] > max) {
- max = tone_energy[i];
- best1 = i;
- }
- }
-
- /* Find 2nd highest */
- if (best1) {
- max = tone_energy[0];
- best2 = 0;
- } else {
- max = tone_energy[1];
- best2 = 1;
- }
-
- for (i=0;i<6;i++) {
- if (i == best1) continue;
- if (tone_energy[i] > max) {
- max = tone_energy[i];
- best2 = i;
- }
- }
- hit = 0;
- if (best1 != best2)
- sofarsogood=1;
- else
- sofarsogood=0;
- /* Check for relative energies */
- for (i=0;i<6;i++) {
- if (i == best1)
- continue;
- if (i == best2)
- continue;
- if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) {
- sofarsogood = 0;
- break;
- }
- if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) {
- sofarsogood = 0;
- break;
- }
- }
-
- if (sofarsogood) {
- /* Check for 2nd harmonic */
- if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1])
- sofarsogood = 0;
- else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2])
- sofarsogood = 0;
- }
- if (sofarsogood) {
- hit = mf_hit[best1][best2];
- if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
- /* Zero out frame data if this is part DTMF */
- for (i=sample;i<limit;i++)
- amp[i] = 0;
- *writeback = 1;
- }
- /* Look for two consecutive clean hits */
- if ((hit == s->hit3) && (s->hit3 != s->hit2)) {
- s->mhit = hit;
- s->detected_digits++;
- if (s->current_digits < MAX_DTMF_DIGITS - 2) {
- s->digits[s->current_digits++] = hit;
- s->digits[s->current_digits] = '\0';
- } else {
- s->lost_digits++;
- }
- }
- }
-
- s->hit1 = s->hit2;
- s->hit2 = s->hit3;
- s->hit3 = hit;
- /* Reinitialise the detector for the next block */
- for (i = 0; i < 6; i++) {
- goertzel_reset(&s->tone_out[i]);
- goertzel_reset(&s->tone_out2nd[i]);
- }
- s->energy = 0.0;
- s->current_sample = 0;
- }
-#else
- /* We're at the end of an MF detection block. */
- /* Find the two highest energies. The spec says to look for
- two tones and two tones only. Taking this literally -ie
- only two tones pass the minimum threshold - doesn't work
- well. The sinc function mess, due to rectangular windowing
- ensure that! Find the two highest energies and ensure they
- are considerably stronger than any of the others. */
- energy[0] = goertzel_result(&s->tone_out[0]);
- energy[1] = goertzel_result(&s->tone_out[1]);
- if (energy[0] > energy[1]) {
- best = 0;
- second_best = 1;
- } else {
- best = 1;
- second_best = 0;
- }
- /*endif*/
- for (i=2;i<6;i++) {
- energy[i] = goertzel_result(&s->tone_out[i]);
- if (energy[i] >= energy[best]) {
- second_best = best;
- best = i;
- } else if (energy[i] >= energy[second_best]) {
- second_best = i;
- }
- }
- /* Basic signal level and twist tests */
- hit = 0;
- if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
- && energy[best] < energy[second_best]*BELL_MF_TWIST
- && energy[best]*BELL_MF_TWIST > energy[second_best]) {
- /* Relative peak test */
- hit = -1;
- for (i=0;i<6;i++) {
- if (i != best && i != second_best) {
- if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
- /* The best two are not clearly the best */
- hit = 0;
- break;
- }
- }
- }
- }
- if (hit) {
- /* Get the values into ascending order */
- if (second_best < best) {
- i = best;
- best = second_best;
- second_best = i;
- }
- best = best*5 + second_best - 1;
- hit = bell_mf_positions[best];
- /* Look for two successive similar results */
- /* The logic in the next test is:
- For KP we need 4 successive identical clean detects, with
- two blocks of something different preceeding it. For anything
- else we need two successive identical clean detects, with
- two blocks of something different preceeding it. */
- if (hit == s->hits[4] && hit == s->hits[3] &&
- ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])||
- (hit == '*' && hit == s->hits[2] && hit != s->hits[1] &&
- hit != s->hits[0]))) {
- s->detected_digits++;
- if (s->current_digits < MAX_DTMF_DIGITS) {
- s->digits[s->current_digits++] = hit;
- s->digits[s->current_digits] = '\0';
- } else {
- s->lost_digits++;
- }
- }
- } else {
- hit = 0;
- }
- s->hits[0] = s->hits[1];
- s->hits[1] = s->hits[2];
- s->hits[2] = s->hits[3];
- s->hits[3] = s->hits[4];
- s->hits[4] = hit;
- /* Reinitialise the detector for the next block */
- for (i = 0; i < 6; i++)
- goertzel_reset(&s->tone_out[i]);
- s->current_sample = 0;
- }
-#endif
- if ((!s->mhit) || (s->mhit != hit)) {
- s->mhit = 0;
- return(0);
- }
- return (hit);
-}
-
-static int __ast_dsp_digitdetect(struct ast_dsp *dsp, short *s, int len, int *writeback)
-{
- int res;
-
- if (dsp->digitmode & DSP_DIGITMODE_MF)
- res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
- else
- res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT);
- return res;
-}
-
-int ast_dsp_digitdetect(struct ast_dsp *dsp, struct ast_frame *inf)
-{
- short *s;
- int len;
- int ign=0;
-
- if (inf->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
- return 0;
- }
- if (inf->subclass != AST_FORMAT_SLINEAR) {
- ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
- return 0;
- }
- s = inf->data;
- len = inf->datalen / 2;
- return __ast_dsp_digitdetect(dsp, s, len, &ign);
-}
-
-static inline int pair_there(float p1, float p2, float i1, float i2, float e)
-{
- /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
- /* Make sure absolute levels are high enough */
- if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
- return 0;
- /* Amplify ignored stuff */
- i2 *= TONE_THRESH;
- i1 *= TONE_THRESH;
- e *= TONE_THRESH;
- /* Check first tone */
- if ((p1 < i1) || (p1 < i2) || (p1 < e))
- return 0;
- /* And second */
- if ((p2 < i1) || (p2 < i2) || (p2 < e))
- return 0;
- /* Guess it's there... */
- return 1;
-}
-
-int ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
-{
- if (dsp->digitmode & DSP_DIGITMODE_MF) {
- if (max > dsp->td.mf.current_digits)
- max = dsp->td.mf.current_digits;
- if (max > 0) {
- memcpy(buf, dsp->td.mf.digits, max);
- memmove(dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
- dsp->td.mf.current_digits -= max;
- }
- buf[max] = '\0';
- return max;
- } else {
- if (max > dsp->td.dtmf.current_digits)
- max = dsp->td.dtmf.current_digits;
- if (max > 0) {
- memcpy (buf, dsp->td.dtmf.digits, max);
- memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
- dsp->td.dtmf.current_digits -= max;
- }
- buf[max] = '\0';
- return max;
- }
-}
-
-static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
-{
- int x;
- int y;
- int pass;
- int newstate = DSP_TONE_STATE_SILENCE;
- int res = 0;
- while(len) {
- /* Take the lesser of the number of samples we need and what we have */
- pass = len;
- if (pass > dsp->gsamp_size - dsp->gsamps)
- pass = dsp->gsamp_size - dsp->gsamps;
- for (x=0;x<pass;x++) {
- for (y=0;y<dsp->freqcount;y++)
- goertzel_sample(&dsp->freqs[y], s[x]);
- dsp->genergy += s[x] * s[x];
- }
- s += pass;
- dsp->gsamps += pass;
- len -= pass;
- if (dsp->gsamps == dsp->gsamp_size) {
- float hz[7];
- for (y=0;y<7;y++)
- hz[y] = goertzel_result(&dsp->freqs[y]);
-#if 0
- printf("\n350: 425: 440: 480: 620: 950: 1400: 1800: Energy: \n");
- printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n",
- hz[HZ_350], hz[HZ_425], hz[HZ_440], hz[HZ_480], hz[HZ_620], hz[HZ_950], hz[HZ_1400], hz[HZ_1800], dsp->genergy);
-#endif
- switch(dsp->progmode) {
- case PROG_MODE_NA:
- if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
- newstate = DSP_TONE_STATE_BUSY;
- } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
- newstate = DSP_TONE_STATE_RINGING;
- } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
- newstate = DSP_TONE_STATE_DIALTONE;
- } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
- newstate = DSP_TONE_STATE_SPECIAL1;
- } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
- if (dsp->tstate == DSP_TONE_STATE_SPECIAL1)
- newstate = DSP_TONE_STATE_SPECIAL2;
- } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
- if (dsp->tstate == DSP_TONE_STATE_SPECIAL2)
- newstate = DSP_TONE_STATE_SPECIAL3;
- } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
- newstate = DSP_TONE_STATE_TALKING;
- } else
- newstate = DSP_TONE_STATE_SILENCE;
- break;
- case PROG_MODE_CR:
- if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
- newstate = DSP_TONE_STATE_RINGING;
- } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
- newstate = DSP_TONE_STATE_TALKING;
- } else
- newstate = DSP_TONE_STATE_SILENCE;
- break;
- case PROG_MODE_UK:
- if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) {
- newstate = DSP_TONE_STATE_HUNGUP;
- }
- break;
- default:
- ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
- }
- if (newstate == dsp->tstate) {
- dsp->tcount++;
- if (dsp->ringtimeout)
- dsp->ringtimeout++;
- switch (dsp->tstate) {
- case DSP_TONE_STATE_RINGING:
- if ((dsp->features & DSP_PROGRESS_RINGING) &&
- (dsp->tcount==THRESH_RING)) {
- res = AST_CONTROL_RINGING;
- dsp->ringtimeout= 1;
- }
- break;
- case DSP_TONE_STATE_BUSY:
- if ((dsp->features & DSP_PROGRESS_BUSY) &&
- (dsp->tcount==THRESH_BUSY)) {
- res = AST_CONTROL_BUSY;
- dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
- }
- break;
- case DSP_TONE_STATE_TALKING:
- if ((dsp->features & DSP_PROGRESS_TALK) &&
- (dsp->tcount==THRESH_TALK)) {
- res = AST_CONTROL_ANSWER;
- dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
- }
- break;
- case DSP_TONE_STATE_SPECIAL3:
- if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
- (dsp->tcount==THRESH_CONGESTION)) {
- res = AST_CONTROL_CONGESTION;
- dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
- }
- break;
- case DSP_TONE_STATE_HUNGUP:
- if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
- (dsp->tcount==THRESH_HANGUP)) {
- res = AST_CONTROL_HANGUP;
- dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
- }
- break;
- }
- if (dsp->ringtimeout==THRESH_RING2ANSWER) {
-#if 0
- ast_log(LOG_NOTICE, "Consider call as answered because of timeout after last ring\n");
-#endif
- res = AST_CONTROL_ANSWER;
- dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
- }
- } else {
-#if 0
- ast_log(LOG_NOTICE, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
- ast_log(LOG_NOTICE, "Start state %d\n", newstate);
-#endif
- dsp->tstate = newstate;
- dsp->tcount = 1;
- }
-
- /* Reset goertzel */
- for (x=0;x<7;x++)
- dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
- dsp->gsamps = 0;
- dsp->genergy = 0.0;
- }
- }
-#if 0
- if (res)
- printf("Returning %d\n", res);
-#endif
- return res;
-}
-
-int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
-{
- if (inf->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
- return 0;
- }
- if (inf->subclass != AST_FORMAT_SLINEAR) {
- ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
- return 0;
- }
- return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
-}
-
-static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totalsilence)
-{
- int accum;
- int x;
- int res = 0;
-
- if (!len)
- return 0;
- accum = 0;
- for (x=0;x<len; x++)
- accum += abs(s[x]);
- accum /= len;
- if (accum < dsp->threshold) {
- /* Silent */
- dsp->totalsilence += len/8;
- if (dsp->totalnoise) {
- /* Move and save history */
- memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
- dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
-/* we don't want to check for busydetect that frequently */
-#if 0
- dsp->busymaybe = 1;
-#endif
- }
- dsp->totalnoise = 0;
- res = 1;
- } else {
- /* Not silent */
- dsp->totalnoise += len/8;
- if (dsp->totalsilence) {
- int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
- int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
- /* Move and save history */
- memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
- dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
- /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
- if (silence1 < silence2) {
- if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
- dsp->busymaybe = 1;
- else
- dsp->busymaybe = 0;
- } else {
- if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
- dsp->busymaybe = 1;
- else
- dsp->busymaybe = 0;
- }
- }
- dsp->totalsilence = 0;
- }
- if (totalsilence)
- *totalsilence = dsp->totalsilence;
- return res;
-}
-
-#ifdef BUSYDETECT_MARTIN
-int ast_dsp_busydetect(struct ast_dsp *dsp)
-{
- int res = 0, x;
-#ifndef BUSYDETECT_TONEONLY
- int avgsilence = 0, hitsilence = 0;
-#endif
- int avgtone = 0, hittone = 0;
- if (!dsp->busymaybe)
- return res;
- for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
-#ifndef BUSYDETECT_TONEONLY
- avgsilence += dsp->historicsilence[x];
-#endif
- avgtone += dsp->historicnoise[x];
- }
-#ifndef BUSYDETECT_TONEONLY
- avgsilence /= dsp->busycount;
-#endif
- avgtone /= dsp->busycount;
- for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
-#ifndef BUSYDETECT_TONEONLY
- if (avgsilence > dsp->historicsilence[x]) {
- if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
- hitsilence++;
- } else {
- if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
- hitsilence++;
- }
-#endif
- if (avgtone > dsp->historicnoise[x]) {
- if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
- hittone++;
- } else {
- if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
- hittone++;
- }
- }
-#ifndef BUSYDETECT_TONEONLY
- if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) &&
- (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) &&
- (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
-#else
- if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
-#endif
-#ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
-#ifdef BUSYDETECT_TONEONLY
-#error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
-#endif
- if (avgtone > avgsilence) {
- if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
- res = 1;
- } else {
- if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
- res = 1;
- }
-#else
- res = 1;
-#endif
- }
- /* If we know the expected busy tone length, check we are in the range */
- if (res && (dsp->busy_tonelength > 0)) {
- if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
-#if 0
- ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n",
- avgtone, dsp->busy_tonelength);
-#endif
- res = 0;
- }
- }
-#ifndef BUSYDETECT_TONEONLY
- /* If we know the expected busy tone silent-period length, check we are in the range */
- if (res && (dsp->busy_quietlength > 0)) {
- if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
-#if 0
- ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
- avgsilence, dsp->busy_quietlength);
-#endif
- res = 0;
- }
- }
-#endif
-#ifndef BUSYDETECT_TONEONLY
-#if 1
- if (res)
- ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
-#endif
-#endif
- return res;
-}
-#endif
-
-#ifdef BUSYDETECT
-int ast_dsp_busydetect(struct ast_dsp *dsp)
-{
- int x;
- int res = 0;
- int max, min;
-
-#if 0
- if (dsp->busy_hits > 5);
- return 0;
-#endif
- if (dsp->busymaybe) {
-#if 0
- printf("Maybe busy!\n");
-#endif
- dsp->busymaybe = 0;
- min = 9999;
- max = 0;
- for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
-#if 0
- printf("Silence: %d, Noise: %d\n", dsp->historicsilence[x], dsp->historicnoise[x]);
-#endif
- if (dsp->historicsilence[x] < min)
- min = dsp->historicsilence[x];
- if (dsp->historicnoise[x] < min)
- min = dsp->historicnoise[x];
- if (dsp->historicsilence[x] > max)
- max = dsp->historicsilence[x];
- if (dsp->historicnoise[x] > max)
- max = dsp->historicnoise[x];
- }
- if ((max - min < BUSY_THRESHOLD) && (max < BUSY_MAX) && (min > BUSY_MIN)) {
-#if 0
- printf("Busy!\n");
-#endif
- res = 1;
- }
-#if 0
- printf("Min: %d, max: %d\n", min, max);
-#endif
- }
- return res;
-}
-#endif
-
-int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
-{
- short *s;
- int len;
-
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
- return 0;
- }
- if (f->subclass != AST_FORMAT_SLINEAR) {
- ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
- return 0;
- }
- s = f->data;
- len = f->datalen/2;
- return __ast_dsp_silence(dsp, s, len, totalsilence);
-}
-
-struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
-{
- int silence;
- int res;
- int digit;
- int x;
- short *shortdata;
- unsigned char *odata;
- int len;
- int writeback = 0;
-
-#define FIX_INF(inf) do { \
- if (writeback) { \
- switch(inf->subclass) { \
- case AST_FORMAT_SLINEAR: \
- break; \
- case AST_FORMAT_ULAW: \
- for (x=0;x<len;x++) \
- odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
- break; \
- case AST_FORMAT_ALAW: \
- for (x=0;x<len;x++) \
- odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
- break; \
- } \
- } \
- } while(0)
-
- if (!af)
- return NULL;
- if (af->frametype != AST_FRAME_VOICE)
- return af;
- odata = af->data;
- len = af->datalen;
- /* Make sure we have short data */
- switch(af->subclass) {
- case AST_FORMAT_SLINEAR:
- shortdata = af->data;
- len = af->datalen / 2;
- break;
- case AST_FORMAT_ULAW:
- shortdata = alloca(af->datalen * 2);
- for (x = 0;x < len; x++)
- shortdata[x] = AST_MULAW(odata[x]);
- break;
- case AST_FORMAT_ALAW:
- shortdata = alloca(af->datalen * 2);
- for (x = 0; x < len; x++)
- shortdata[x] = AST_ALAW(odata[x]);
- break;
- default:
- ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
- return af;
- }
- silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
- if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
- memset(&dsp->f, 0, sizeof(dsp->f));
- dsp->f.frametype = AST_FRAME_NULL;
- ast_frfree(af);
- ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
- return &dsp->f;
- }
- if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
- chan->_softhangup |= AST_SOFTHANGUP_DEV;
- memset(&dsp->f, 0, sizeof(dsp->f));
- dsp->f.frametype = AST_FRAME_CONTROL;
- dsp->f.subclass = AST_CONTROL_BUSY;
- ast_frfree(af);
- ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
- return &dsp->f;
- }
- if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
- digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
-#if 0
- if (digit)
- printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
-#endif
- if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
- if (!dsp->thinkdigit) {
- if (digit) {
- /* Looks like we might have something.
- * Request a conference mute for the moment */
- memset(&dsp->f, 0, sizeof(dsp->f));
- dsp->f.frametype = AST_FRAME_DTMF;
- dsp->f.subclass = 'm';
- dsp->thinkdigit = 'x';
- FIX_INF(af);
- if (chan)
- ast_queue_frame(chan, af);
- ast_frfree(af);
- ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
- return &dsp->f;
- }
- } else {
- if (digit) {
- /* Thought we saw one last time. Pretty sure we really have now */
- if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
- /* If we found a digit, and we're changing digits, go
- ahead and send this one, but DON'T stop confmute because
- we're detecting something else, too... */
- memset(&dsp->f, 0, sizeof(dsp->f));
- dsp->f.frametype = AST_FRAME_DTMF_END;
- dsp->f.subclass = dsp->thinkdigit;
- FIX_INF(af);
- if (chan)
- ast_queue_frame(chan, af);
- ast_frfree(af);
- } else {
- dsp->thinkdigit = digit;
- memset(&dsp->f, 0, sizeof(dsp->f));
- dsp->f.frametype = AST_FRAME_DTMF_BEGIN;
- dsp->f.subclass = dsp->thinkdigit;
- FIX_INF(af);
- if (chan)
- ast_queue_frame(chan, af);
- ast_frfree(af);
- }
- ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
- return &dsp->f;
- } else {
- memset(&dsp->f, 0, sizeof(dsp->f));
- if (dsp->thinkdigit != 'x') {
- /* If we found a digit, send it now */
- dsp->f.frametype = AST_FRAME_DTMF_END;
- dsp->f.subclass = dsp->thinkdigit;
- dsp->thinkdigit = 0;
- } else {
- dsp->f.frametype = AST_FRAME_DTMF;
- dsp->f.subclass = 'u';
- dsp->thinkdigit = 0;
- }
- FIX_INF(af);
- if (chan)
- ast_queue_frame(chan, af);
- ast_frfree(af);
- ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
- return &dsp->f;
- }
- }
- } else if (!digit) {
- /* Only check when there is *not* a hit... */
- if (dsp->digitmode & DSP_DIGITMODE_MF) {
- if (dsp->td.mf.current_digits) {
- memset(&dsp->f, 0, sizeof(dsp->f));
- dsp->f.frametype = AST_FRAME_DTMF;
- dsp->f.subclass = dsp->td.mf.digits[0];
- memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
- dsp->td.mf.current_digits--;
- FIX_INF(af);
- if (chan)
- ast_queue_frame(chan, af);
- ast_frfree(af);
- ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
- return &dsp->f;
- }
- } else {
- if (dsp->td.dtmf.current_digits) {
- memset(&dsp->f, 0, sizeof(dsp->f));
- dsp->f.frametype = AST_FRAME_DTMF_END;
- dsp->f.subclass = dsp->td.dtmf.digits[0];
- memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
- dsp->td.dtmf.current_digits--;
- FIX_INF(af);
- if (chan)
- ast_queue_frame(chan, af);
- ast_frfree(af);
- ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
- return &dsp->f;
- }
- }
- }
- }
- if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
- res = __ast_dsp_call_progress(dsp, shortdata, len);
- if (res) {
- switch(res) {
- case AST_CONTROL_ANSWER:
- case AST_CONTROL_BUSY:
- case AST_CONTROL_RINGING:
- case AST_CONTROL_CONGESTION:
- case AST_CONTROL_HANGUP:
- memset(&dsp->f, 0, sizeof(dsp->f));
- dsp->f.frametype = AST_FRAME_CONTROL;
- dsp->f.subclass = res;
- dsp->f.src = "dsp_progress";
- if (chan)
- ast_queue_frame(chan, &dsp->f);
- break;
- default:
- ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
- }
- }
- }
- FIX_INF(af);
- return af;
-}
-
-static void ast_dsp_prog_reset(struct ast_dsp *dsp)
-{
- int max = 0;
- int x;
-
- dsp->gsamp_size = modes[dsp->progmode].size;
- dsp->gsamps = 0;
- for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
- if (modes[dsp->progmode].freqs[x]) {
- goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
- max = x + 1;
- }
- }
- dsp->freqcount = max;
- dsp->ringtimeout= 0;
-}
-
-struct ast_dsp *ast_dsp_new(void)
-{
- struct ast_dsp *dsp;
-
- if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
- dsp->threshold = DEFAULT_THRESHOLD;
- dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
- dsp->busycount = DSP_HISTORY;
- /* Initialize DTMF detector */
- ast_dtmf_detect_init(&dsp->td.dtmf);
- /* Initialize initial DSP progress detect parameters */
- ast_dsp_prog_reset(dsp);
- }
- return dsp;
-}
-
-void ast_dsp_set_features(struct ast_dsp *dsp, int features)
-{
- dsp->features = features;
-}
-
-void ast_dsp_free(struct ast_dsp *dsp)
-{
- if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
- /* If this flag is still set, that means that the dsp's destruction
- * been torn down, while we still have a frame out there being used.
- * When ast_frfree() gets called on that frame, this ast_trans_pvt
- * will get destroyed, too. */
-
- /* Set the magic hint that this has been requested to be destroyed. */
- dsp->freqcount = -1;
-
- return;
- }
- free(dsp);
-}
-
-void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
-{
- dsp->threshold = threshold;
-}
-
-void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
-{
- if (cadences < 4)
- cadences = 4;
- if (cadences > DSP_HISTORY)
- cadences = DSP_HISTORY;
- dsp->busycount = cadences;
-}
-
-void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength)
-{
- dsp->busy_tonelength = tonelength;
- dsp->busy_quietlength = quietlength;
- ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
-}
-
-void ast_dsp_digitreset(struct ast_dsp *dsp)
-{
- int i;
-
- dsp->thinkdigit = 0;
- if (dsp->digitmode & DSP_DIGITMODE_MF) {
- memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
- dsp->td.mf.current_digits = 0;
- /* Reinitialise the detector for the next block */
- for (i = 0; i < 6; i++) {
- goertzel_reset(&dsp->td.mf.tone_out[i]);
-#ifdef OLD_DSP_ROUTINES
- goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
-#endif
- }
-#ifdef OLD_DSP_ROUTINES
- dsp->td.mf.energy = 0.0;
- dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
-#else
- dsp->td.mf.hits[4] = dsp->td.mf.hits[3] = dsp->td.mf.hits[2] = dsp->td.mf.hits[1] = dsp->td.mf.hits[0] = dsp->td.mf.mhit = 0;
-#endif
- dsp->td.mf.current_sample = 0;
- } else {
- memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
- dsp->td.dtmf.current_digits = 0;
- /* Reinitialise the detector for the next block */
- for (i = 0; i < 4; i++) {
- goertzel_reset(&dsp->td.dtmf.row_out[i]);
- goertzel_reset(&dsp->td.dtmf.col_out[i]);
-#ifdef OLD_DSP_ROUTINES
- goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
- goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
-#endif
- }
-#ifdef FAX_DETECT
- goertzel_reset (&dsp->td.dtmf.fax_tone);
-#endif
-#ifdef OLD_DSP_ROUTINES
-#ifdef FAX_DETECT
- goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
-#endif
- dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
-#else
- dsp->td.dtmf.lasthit = dsp->td.dtmf.mhit = 0;
-#endif
- dsp->td.dtmf.energy = 0.0;
- dsp->td.dtmf.current_sample = 0;
- }
-}
-
-void ast_dsp_reset(struct ast_dsp *dsp)
-{
- int x;
-
- dsp->totalsilence = 0;
- dsp->gsamps = 0;
- for (x=0;x<4;x++)
- dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
- memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
- memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
- dsp->ringtimeout= 0;
-}
-
-int ast_dsp_digitmode(struct ast_dsp *dsp, int digitmode)
-{
- int new;
- int old;
-
- old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
- new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
- if (old != new) {
- /* Must initialize structures if switching from MF to DTMF or vice-versa */
- if (new & DSP_DIGITMODE_MF)
- ast_mf_detect_init(&dsp->td.mf);
- else
- ast_dtmf_detect_init(&dsp->td.dtmf);
- }
- dsp->digitmode = digitmode;
- return 0;
-}
-
-int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
-{
- int x;
-
- for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
- if (!strcasecmp(aliases[x].name, zone)) {
- dsp->progmode = aliases[x].mode;
- ast_dsp_prog_reset(dsp);
- return 0;
- }
- }
- return -1;
-}
-
-int ast_dsp_get_tstate(struct ast_dsp *dsp)
-{
- return dsp->tstate;
-}
-
-int ast_dsp_get_tcount(struct ast_dsp *dsp)
-{
- return dsp->tcount;
-}
-
-void ast_dsp_frame_freed(struct ast_frame *fr)
-{
- struct ast_dsp *dsp;
-
- ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
-
- dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
-
- if (dsp->freqcount != -1)
- return;
-
- ast_dsp_free(dsp);
-}
diff --git a/main/ecdisa.h b/main/ecdisa.h
deleted file mode 100644
index df6f773a0..000000000
--- a/main/ecdisa.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* ecdisa.h: Generated from frequency 2100
- by gentone. 80 samples */
-static unsigned char ecdisa[80] = {
- 255, 143, 58, 16, 171, 146, 34, 20,
- 156, 151, 25, 26, 149, 159, 19, 38,
- 145, 177, 16, 73, 143, 73, 16, 177,
- 145, 38, 19, 159, 149, 26, 25, 151,
- 156, 20, 34, 146, 171, 16, 58, 143,
- 255, 15, 186, 144, 43, 18, 162, 148,
- 28, 23, 153, 154, 21, 31, 147, 166,
- 17, 49, 144, 201, 15, 201, 144, 49,
- 17, 166, 147, 31, 21, 154, 153, 23,
- 28, 148, 162, 18, 43, 144, 186, 15,
-
-};
diff --git a/main/editline/CHANGES b/main/editline/CHANGES
deleted file mode 100644
index c18b56cdf..000000000
--- a/main/editline/CHANGES
+++ /dev/null
@@ -1,42 +0,0 @@
-2002-02-25 : Christos Zoulas <christos@netbsd.org>
- * Bring in constification fixes from NetBSD tree.
- * Use NetBSD's vis, fgetln
-
-2002-02-10 : Jason Evans <jasone@freebsd.org>
-
- * Makefile.in : Append "" arguments to for loops, to avoid syntax errors
- with some shells that occur if there are no arguments to the for
- loops.
-
-2002-02-09 : Jason Evans <jasone@freebsd.org>
-
- * Install man pages in @prefix@/man/, rather than @prefix@/share/man.
-
- * Fix the Darwin -install_name S_LDFLAGS argument to default to a prefix
- of /usr/local if --prefix is not specified.
-
-2002-02-05 : Jason Evans <jasone@freebsd.org>
-
- * Convert to using an autoconf-generated config.h, rather than passing
- -D_HAVE_<foo>=1 definitions on the command line. Include sys.h in
- config.h, and include config.h in .c files rather than sys.h.
-
- * Mangle function names for implementations in the np directory in order
- to avoid namespace collisions with other code that may provide copies
- of the same unimplemented functions. For example:
-
- #define fgetln libedit_fgetln
-
-2002-02-03 : Jason Evans <jasone@freebsd.org>
-
- * Add autoconf infrastructure, plus a generic Makefile that works with
- at least BSD make, GNU make and Sun make.
-
- * Port and/or test on FreeBSD 4.5, FreeBSD-current, NetBSD 1.5 (sparc64
- and arm32), Apple OS X 10.1.2, Solaris 2.6, and Red Hat Linux 2.6.
- Add the np directory, which contains implementations of non-portable
- functions.
-
- * Add the LIBEDIT_MAJOR and LIBEDIT_MINOR macros to histedit.h, since
- there is otherwise no straightforward method of programmatically
- detecting the library version.
diff --git a/main/editline/INSTALL b/main/editline/INSTALL
deleted file mode 100644
index 16fb6ffd1..000000000
--- a/main/editline/INSTALL
+++ /dev/null
@@ -1,64 +0,0 @@
-Building this distribution in many cases is as simple as typing the following
-while in the root directory of the source tree:
-
- ./configure
- make
-
-To install, do the above, then type:
-
- make install
-
-Additional build targets of finer granularity include:
-
- lib_a
- lib_s
- install_hdr
- install_lib
- install_lib_a
- install_lib_s
- install_man
- test
-
-Cleanup targets include:
-
- clean
- distclean
-
-Optionally, pass any of the following (not a definitive list) arguments to
-'configure':
-
---prefix=<install-root-dir>
- Set the base directory in which to install. For example:
-
- ./configure --prefix=/usr/local
-
- will cause files to be installed into /usr/local/bin, /usr/local/man,
- /usr/local/include, /usr/local/lib, and /usr/local/share.
-
---disable-readline
- By default, libedit is built and installed such that it works as a
- drop-in replacement for the readline library. This option turns that
- behavior off.
-
---enable-debug
- Build debugging code (for libedit development).
-
-Optionally, define environment variables, including (not exclusively):
-
-CFLAGS="?"
- Pass these flags to the compiler. You probably shouldn't define this
- unless you know what you are doing.
-
-CPPFLAGS="?"
- Pass these flags to the C preprocessor. Note that CFLAGS is not passed
- to 'cpp' when 'configure' is looking for include files, so you must use
- CPPFLAGS instead if you need to help 'configure' find header files.
-
-LD_LIBRARY_PATH="?"
- 'ld' uses this colon-separated list to find libraries.
-
-LDFLAGS="?"
- Flags passed to 'gcc', which should normally be passed on to 'ld'.
-
-PATH="?"
- 'configure' uses this to find programs.
diff --git a/main/editline/Makefile.in b/main/editline/Makefile.in
deleted file mode 100644
index 5bb097f48..000000000
--- a/main/editline/Makefile.in
+++ /dev/null
@@ -1,234 +0,0 @@
-#
-# Generic Makefile for libedit.
-#
-
-OSTYPE=$(shell uname -s)
-define cyg_subst_sys
- if uname -s | ${GREP} -qi cygwin; then \
- cat $@ | sed -e s/"sys\.h"/"config.h"/g > $@.copy; \
- mv --force $@.copy $@; \
- fi
-endef
-
-SHELL = /bin/sh
-
-CC = @CC@
-AR = @AR@
-RANLIB = @RANLIB@
-CPPFLAGS = @CPPFLAGS@ -I.
-CFLAGS = @CFLAGS@
-A_CFLAGS = @A_CFLAGS@
-S_CFLAGS = @S_CFLAGS@
-LDFLAGS = @LDFLAGS@
-S_LDFLAGS = @S_LDFLAGS@
-LIBS = @LIBS@
-
-INSTALL = @INSTALL@
-PREFIX = @prefix@
-
-ifeq ($(OSTYPE),SunOS)
-CFLAGS+=-DSOLARIS -I../../include/solaris-compat
-endif
-
-# .c files.
-ACSRCS = @ACSRCS@
-BCSRCS = @BCSRCS@
-CCSRCS = @CCSRCS@
-
-# Generated .c files.
-AGCSRCS = @AGCSRCS@
-BGCSRCS = @BGCSRCS@
-
-# .h files.
-HDRS = @HDRS@
-
-# Generated .h files.
-AGHDRS = @AGHDRS@
-BGHDRS = @BGHDRS@
-
-# Installed .h files.
-IHDRS = @IHDRS@
-IHDR_LINKS = @IHDR_LINKS@
-HDR_DIRS = @HDR_DIRS@
-
-# Man pages.
-MAN3 = @MAN3@
-MAN5 = @MAN5@
-MAN3_LINKS = @MAN3_LINKS@
-MAN_DIRS = @MAN_DIRS@
-
-# Library.
-LIB_DIRS = @LIB_DIRS@
-LIB_VER = @LIB_VER@
-LIB_A = @LIB_A@
-LIB_A_LINKS = @LIB_A_LINKS@
-LIB_S = @LIB_S@
-LIB_S_LINKS = @LIB_S_LINKS@
-
-# Test program.
-TEST = @TEST@
-TCSRCS = @TCSRCS@
-
-# Clear out all paths, then set just one (default path) for the main build
-# directory.
-.PATH :
-.PATH : .
-
-.SUFFIXES :
-.SUFFIXES : .c .o .o_a .o_s
-
-all : lib_a lib_s
-
-lib_a : $(LIB_A)
-lib_s : $(LIB_S)
-
-test : $(TEST)
-
-install : install_hdr install_lib install_man
-
-install_hdr :
- @for i in $(HDR_DIRS) ; do \
- echo "$(INSTALL) -d $(PREFIX)/$$i/"; \
- $(INSTALL) -d $(PREFIX)/$$i/; \
- done
- @for i in $(IHDRS); do \
- echo "$(INSTALL) -m 0444 $$i $(PREFIX)/include/`dirname $$i`/"; \
- $(INSTALL) -m 0444 $$i $(PREFIX)/include/`dirname $$i`/; \
- done
- @f=; \
- for i in $(IHDR_LINKS) ""; do \
- if test -z "$$f" ; then \
- f=$$i; \
- else \
- echo "rm -f $(PREFIX)/include/$$i"; \
- rm -f $(PREFIX)/include/$$i; \
- echo "ln -s $$f $(PREFIX)/include/$$i"; \
- ln -s $$f $(PREFIX)/include/$$i; \
- f=; \
- fi; \
- done
-
-install_lib : install_lib_a install_lib_s
-
-install_lib_common :
- @for i in $(LIB_DIRS) ; do \
- echo "$(INSTALL) -d $(PREFIX)/$$i/"; \
- $(INSTALL) -d $(PREFIX)/$$i/; \
- done
-
-install_lib_a : $(LIB_A) install_lib_common
- $(INSTALL) -m 0644 $(LIB_A) $(PREFIX)/lib/
- @f=; \
- for i in $(LIB_A_LINKS) ""; do \
- if test -z "$$f" ; then \
- f=$$i; \
- else \
- echo "rm -f $(PREFIX)/lib/$$i"; \
- rm -f $(PREFIX)/lib/$$i; \
- echo "ln -s $$f $(PREFIX)/lib/$$i"; \
- ln -s $$f $(PREFIX)/lib/$$i; \
- f=; \
- fi; \
- done
-
-install_lib_s : $(LIB_S) install_lib_common
- $(INSTALL) -m 0755 $(LIB_S) $(PREFIX)/lib/
- @f=; \
- for i in $(LIB_S_LINKS) ""; do \
- if test -z "$$f" ; then \
- f=$$i; \
- else \
- echo "rm -f $(PREFIX)/lib/$$i"; \
- rm -f $(PREFIX)/lib/$$i; \
- echo "ln -s $$f $(PREFIX)/lib/$$i"; \
- ln -s $$f $(PREFIX)/lib/$$i; \
- f=; \
- fi; \
- done
-
-install_man :
- @for i in $(MAN_DIRS) ; do \
- echo "$(INSTALL) -d $(PREFIX)/$$i/"; \
- $(INSTALL) -d $(PREFIX)/$$i/; \
- done
- @for i in $(MAN3); do \
- echo $(INSTALL) -m 0444 $$i $(PREFIX)/man/man3/; \
- $(INSTALL) -m 0444 $$i $(PREFIX)/man/man3/; \
- done
- @f=; \
- for i in $(MAN3_LINKS) ""; do \
- if test -z "$$f" ; then \
- f=$$i; \
- else \
- echo "rm -f $(PREFIX)/man/man3/$$i"; \
- rm -f $(PREFIX)/man/man3/$$i; \
- echo "ln -s $$f $(PREFIX)/man/man3/$$i"; \
- ln -s $$f $(PREFIX)/man/man3/$$i; \
- f=; \
- fi; \
- done
- @for i in $(MAN5); do\
- echo $(INSTALL) -m 0444 $$i $(PREFIX)/man/man5/; \
- $(INSTALL) -m 0444 $$i $(PREFIX)/man/man5/; \
- done
-
-clean :
- rm -f $(AGCSRCS) $(BGCSRCS) $(AGHDRS) $(BGHDRS) $(LIB_A) $(LIB_S)
- rm -f $(BGCSRCS:.c=.o_a) $(CCSRCS:.c=.o_a)
- rm -f $(BGCSRCS:.c=.o_s) $(CCSRCS:.c=.o_s)
- rm -f $(TCSRCS:.c=.o) $(TEST)
- rm -f *.s *.i
-
-distclean : clean
- rm -f config.cache config.log config.status config.h makelist Makefile
-
-#
-# Internal targets and rules.
-#
-
-$(LIB_A) : $(BGCSRCS:.c=.o_a) $(CCSRCS:.c=.o_a)
- $(AR) cru $@ $?
- $(RANLIB) $@
-
-$(LIB_S) : $(BGCSRCS:.c=.o_s) $(CCSRCS:.c=.o_s)
- $(CC) $(S_LDFLAGS) -o $@ $(BGCSRCS:.c=.o_s) $(CCSRCS:.c=.o_s) $(LIBS)
-
-$(TEST) : $(TCSRCS:.c=.o) $(LIB_A)
- $(CC) -o $@ $(TCSRCS:.c=.o) $(LIB_A) $(LIBS)
-
-common.h : common.c
- $(SHELL) makelist -h common.c > $@
-
-emacs.h : emacs.c
- $(SHELL) makelist -h emacs.c> $@
-
-vi.h : vi.c
- $(SHELL) makelist -h vi.c > $@
-
-fcns.h : $(AGHDRS)
- $(SHELL) makelist -fh $(AGHDRS) > $@
-
-fcns.c : $(AGHDRS) fcns.h
- $(SHELL) makelist -fc $(AGHDRS) > $@
- $(cyg_subst_sys)
-
-help.h : $(ACSRCS)
- $(SHELL) makelist -bh $(ACSRCS) > $@
-
-help.c : $(ACSRCS) help.h
- $(SHELL) makelist -bc $(ACSRCS) > $@
- $(cyg_subst_sys)
-
-editline.c : $(ACSRCS) $(BCSRCS) $(AGCSRCS)
- $(SHELL) makelist -e $(ACSRCS) $(BCSRCS) $(AGCSRCS) > $@
-
-.c.o :
- $(CC) -c $(A_CFLAGS) $(CFLAGS) $(CPPFLAGS) $< -o $@
-
-.c.o_a : $(AGHDRS) $(BGHDRS)
- $(CC) -c $(A_CFLAGS) $(CFLAGS) $(CPPFLAGS) $< -o $@
-
-.c.o_s : $(AGHDRS) $(BGHDRS)
- $(CC) -c $(S_CFLAGS) $(CFLAGS) $(CPPFLAGS) $< -o $@
-
-$(CCSRCS) : $(BGHDRS)
diff --git a/main/editline/PLATFORMS b/main/editline/PLATFORMS
deleted file mode 100644
index ea7c5bb68..000000000
--- a/main/editline/PLATFORMS
+++ /dev/null
@@ -1,13 +0,0 @@
-This distribution of libedit is expected to work on at least the following
-platforms. It may also work on additional platforms, but no explicit support
-for them is built into the configuration system.
-
-* Apple OS X 10.1.
-
-* FreeBSD 4.x.
-
-* NetBSD 1.5.
-
-* Red Hat Linux 7.2.
-
-* Sun Solaris 2.6.
diff --git a/main/editline/README b/main/editline/README
deleted file mode 100644
index 49a2a6947..000000000
--- a/main/editline/README
+++ /dev/null
@@ -1,11 +0,0 @@
-libedit is a command line editing and history library. It is designed to be
-used by interactive programs that allow the user to type commands at a terminal
-prompt.
-
-The following files may be of direct interest to the user:
-
-* CHANGES - Software change log.
-
-* INSTALL - Installation information.
-
-* PLATFORMS - Supported platforms and platform-specific information.
diff --git a/main/editline/TEST/test.c b/main/editline/TEST/test.c
deleted file mode 100644
index 3169a2071..000000000
--- a/main/editline/TEST/test.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/* $NetBSD: test.c,v 1.9 2000/09/04 23:36:41 lukem Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#ifndef lint
-__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
- The Regents of the University of California. All rights reserved.\n");
-#endif /* not lint */
-
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: test.c,v 1.9 2000/09/04 23:36:41 lukem Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * test.c: A little test program
- */
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <dirent.h>
-
-#include "histedit.h"
-#include "tokenizer.h"
-
-static int continuation = 0;
-static EditLine *el = NULL;
-
-static u_char complete(EditLine *, int);
- int main(int, char **);
-static char *prompt(EditLine *);
-static void sig(int);
-
-static char *
-prompt(EditLine *el)
-{
- static char a[] = "Edit$";
- static char b[] = "Edit>";
-
- return (continuation ? b : a);
-}
-
-static void
-sig(int i)
-{
-
- (void) fprintf(stderr, "Got signal %d.\n", i);
- el_reset(el);
-}
-
-static unsigned char
-complete(EditLine *el, int ch)
-{
- DIR *dd = opendir(".");
- struct dirent *dp;
- const char* ptr;
- const LineInfo *lf = el_line(el);
- int len;
-
- /*
- * Find the last word
- */
- for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--)
- continue;
- len = lf->cursor - ++ptr;
-
- for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
- if (len > strlen(dp->d_name))
- continue;
- if (strncmp(dp->d_name, ptr, len) == 0) {
- closedir(dd);
- if (el_insertstr(el, &dp->d_name[len]) == -1)
- return (CC_ERROR);
- else
- return (CC_REFRESH);
- }
- }
-
- closedir(dd);
- return (CC_ERROR);
-}
-
-int
-main(int argc, char *argv[])
-{
- int num;
- const char *buf;
- Tokenizer *tok;
-#if 0
- int lastevent = 0;
-#endif
- int ncontinuation;
- History *hist;
- HistEvent ev;
-
- (void) signal(SIGINT, sig);
- (void) signal(SIGQUIT, sig);
- (void) signal(SIGHUP, sig);
- (void) signal(SIGTERM, sig);
-
- hist = history_init(); /* Init the builtin history */
- /* Remember 100 events */
- history(hist, &ev, H_SETSIZE, 100);
-
- tok = tok_init(NULL); /* Initialize the tokenizer */
-
- /* Initialize editline */
- el = el_init(*argv, stdin, stdout, stderr);
-
- el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */
- el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */
- el_set(el, EL_PROMPT, prompt); /* Set the prompt function */
-
- /* Tell editline to use this history interface */
- el_set(el, EL_HIST, history, hist);
-
- /* Add a user-defined function */
- el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete);
-
- /* Bind tab to it */
- el_set(el, EL_BIND, "^I", "ed-complete", NULL);
-
- /*
- * Bind j, k in vi command mode to previous and next line, instead
- * of previous and next history.
- */
- el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
- el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
-
- /*
- * Source the user's defaults file.
- */
- el_source(el, NULL);
-
- while ((buf = el_gets(el, &num)) != NULL && num != 0) {
- int ac;
- const char **av;
-#ifdef DEBUG
- (void) fprintf(stderr, "got %d %s", num, buf);
-#endif
- if (!continuation && num == 1)
- continue;
-
- ncontinuation = tok_line(tok, buf, &ac, &av) > 0;
-#if 0
- if (continuation) {
- /*
- * Append to the right event in case the user
- * moved around in history.
- */
- if (history(hist, &ev, H_SET, lastevent) == -1)
- err(1, "%d: %s\n", lastevent, ev.str);
- history(hist, &ev, H_ADD , buf);
- } else {
- history(hist, &ev, H_ENTER, buf);
- lastevent = ev.num;
- }
-#else
- /* Simpler */
- history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf);
-#endif
-
- continuation = ncontinuation;
- ncontinuation = 0;
-
- if (strcmp(av[0], "history") == 0) {
- int rv;
-
- switch (ac) {
- case 1:
- for (rv = history(hist, &ev, H_LAST); rv != -1;
- rv = history(hist, &ev, H_PREV))
- (void) fprintf(stdout, "%4d %s",
- ev.num, ev.str);
- break;
-
- case 2:
- if (strcmp(av[1], "clear") == 0)
- history(hist, &ev, H_CLEAR);
- else
- goto badhist;
- break;
-
- case 3:
- if (strcmp(av[1], "load") == 0)
- history(hist, &ev, H_LOAD, av[2]);
- else if (strcmp(av[1], "save") == 0)
- history(hist, &ev, H_SAVE, av[2]);
- break;
-
- badhist:
- default:
- (void) fprintf(stderr,
- "Bad history arguments\n");
- break;
- }
- } else if (el_parse(el, ac, av) == -1) {
- switch (fork()) {
- case 0:
- execvp(av[0], (char *const *)av);
- perror(av[0]);
- _exit(1);
- /*NOTREACHED*/
- break;
-
- case -1:
- perror("fork");
- break;
-
- default:
- if (wait(&num) == -1)
- perror("wait");
- (void) fprintf(stderr, "Exit %x\n", num);
- break;
- }
- }
-
- tok_reset(tok);
- }
-
- el_end(el);
- tok_end(tok);
- history_end(hist);
-
- return (0);
-}
diff --git a/main/editline/chared.c b/main/editline/chared.c
deleted file mode 100644
index 8eaeb3b54..000000000
--- a/main/editline/chared.c
+++ /dev/null
@@ -1,695 +0,0 @@
-/* $NetBSD: chared.c,v 1.15 2002/03/18 16:00:50 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: chared.c,v 1.15 2002/03/18 16:00:50 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * chared.c: Character editor utilities
- */
-#include <stdlib.h>
-#include "el.h"
-
-/* value to leave unused in line buffer */
-#define EL_LEAVE 2
-
-/* cv_undo():
- * Handle state for the vi undo command
- */
-protected void
-cv_undo(EditLine *el,int action, size_t size, char *ptr)
-{
- c_undo_t *vu = &el->el_chared.c_undo;
- vu->action = action;
- vu->ptr = ptr;
- vu->isize = size;
- (void) memcpy(vu->buf, vu->ptr, size);
-#ifdef DEBUG_UNDO
- (void) fprintf(el->el_errfile, "Undo buffer \"%s\" size = +%d -%d\n",
- vu->ptr, vu->isize, vu->dsize);
-#endif
-}
-
-
-/* c_insert():
- * Insert num characters
- */
-protected void
-c_insert(EditLine *el, int num)
-{
- char *cp;
-
- if (el->el_line.lastchar + num >= el->el_line.limit)
- return; /* can't go past end of buffer */
-
- if (el->el_line.cursor < el->el_line.lastchar) {
- /* if I must move chars */
- for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
- cp[num] = *cp;
- }
- el->el_line.lastchar += num;
-}
-
-
-/* c_delafter():
- * Delete num characters after the cursor
- */
-protected void
-c_delafter(EditLine *el, int num)
-{
-
- if (el->el_line.cursor + num > el->el_line.lastchar)
- num = el->el_line.lastchar - el->el_line.cursor;
-
- if (num > 0) {
- char *cp;
-
- if (el->el_map.current != el->el_map.emacs)
- cv_undo(el, INSERT, (size_t)num, el->el_line.cursor);
-
- for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
- *cp = cp[num];
-
- el->el_line.lastchar -= num;
- }
-}
-
-
-/* c_delbefore():
- * Delete num characters before the cursor
- */
-protected void
-c_delbefore(EditLine *el, int num)
-{
-
- if (el->el_line.cursor - num < el->el_line.buffer)
- num = el->el_line.cursor - el->el_line.buffer;
-
- if (num > 0) {
- char *cp;
-
- if (el->el_map.current != el->el_map.emacs)
- cv_undo(el, INSERT, (size_t)num,
- el->el_line.cursor - num);
-
- for (cp = el->el_line.cursor - num;
- cp <= el->el_line.lastchar;
- cp++)
- *cp = cp[num];
-
- el->el_line.lastchar -= num;
- }
-}
-
-
-/* ce__isword():
- * Return if p is part of a word according to emacs
- */
-protected int
-ce__isword(int p)
-{
- return (isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL);
-}
-
-
-/* cv__isword():
- * Return if p is part of a word according to vi
- */
-protected int
-cv__isword(int p)
-{
- return (!isspace(p));
-}
-
-
-/* c__prev_word():
- * Find the previous word
- */
-protected char *
-c__prev_word(char *p, char *low, int n, int (*wtest)(int))
-{
- p--;
-
- while (n--) {
- while ((p >= low) && !(*wtest)((unsigned char) *p))
- p--;
- while ((p >= low) && (*wtest)((unsigned char) *p))
- p--;
- }
-
- /* cp now points to one character before the word */
- p++;
- if (p < low)
- p = low;
- /* cp now points where we want it */
- return (p);
-}
-
-
-/* c__next_word():
- * Find the next word
- */
-protected char *
-c__next_word(char *p, char *high, int n, int (*wtest)(int))
-{
- while (n--) {
- while ((p < high) && !(*wtest)((unsigned char) *p))
- p++;
- while ((p < high) && (*wtest)((unsigned char) *p))
- p++;
- }
- if (p > high)
- p = high;
- /* p now points where we want it */
- return (p);
-}
-
-/* cv_next_word():
- * Find the next word vi style
- */
-protected char *
-cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
-{
- int test;
-
- while (n--) {
- test = (*wtest)((unsigned char) *p);
- while ((p < high) && (*wtest)((unsigned char) *p) == test)
- p++;
- /*
- * vi historically deletes with cw only the word preserving the
- * trailing whitespace! This is not what 'w' does..
- */
- if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
- while ((p < high) && isspace((unsigned char) *p))
- p++;
- }
-
- /* p now points where we want it */
- if (p > high)
- return (high);
- else
- return (p);
-}
-
-
-/* cv_prev_word():
- * Find the previous word vi style
- */
-protected char *
-cv_prev_word(EditLine *el, char *p, char *low, int n, int (*wtest)(int))
-{
- int test;
-
- while (n--) {
- p--;
- /*
- * vi historically deletes with cb only the word preserving the
- * leading whitespace! This is not what 'b' does..
- */
- if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
- while ((p > low) && isspace((unsigned char) *p))
- p--;
- test = (*wtest)((unsigned char) *p);
- while ((p >= low) && (*wtest)((unsigned char) *p) == test)
- p--;
- p++;
- while (isspace((unsigned char) *p))
- p++;
- }
-
- /* p now points where we want it */
- if (p < low)
- return (low);
- else
- return (p);
-}
-
-
-#ifdef notdef
-/* c__number():
- * Ignore character p points to, return number appearing after that.
- * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
- * Return p pointing to last char used.
- */
-protected char *
-c__number(
- char *p, /* character position */
- int *num, /* Return value */
- int dval) /* dval is the number to subtract from like $-3 */
-{
- int i;
- int sign = 1;
-
- if (*++p == '^') {
- *num = 1;
- return (p);
- }
- if (*p == '$') {
- if (*++p != '-') {
- *num = 0x7fffffff; /* Handle $ */
- return (--p);
- }
- sign = -1; /* Handle $- */
- ++p;
- }
- for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
- continue;
- *num = (sign < 0 ? dval - i : i);
- return (--p);
-}
-#endif
-
-/* cv_delfini():
- * Finish vi delete action
- */
-protected void
-cv_delfini(EditLine *el)
-{
- int size;
- int oaction;
-
- if (el->el_chared.c_vcmd.action & INSERT)
- el->el_map.current = el->el_map.key;
-
- oaction = el->el_chared.c_vcmd.action;
- el->el_chared.c_vcmd.action = NOP;
-
- if (el->el_chared.c_vcmd.pos == 0)
- return;
-
-
- if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
- size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
- c_delbefore(el, size);
- el->el_line.cursor = el->el_chared.c_vcmd.pos;
- re_refresh_cursor(el);
- } else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) {
- size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor);
- c_delafter(el, size);
- } else {
- size = 1;
- c_delafter(el, size);
- }
- switch (oaction) {
- case DELETE|INSERT:
- el->el_chared.c_undo.action = DELETE|INSERT;
- break;
- case DELETE:
- el->el_chared.c_undo.action = INSERT;
- break;
- case NOP:
- case INSERT:
- default:
- EL_ABORT((el->el_errfile, "Bad oaction %d\n", oaction));
- break;
- }
-
-
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.dsize = size;
-}
-
-
-#ifdef notdef
-/* ce__endword():
- * Go to the end of this word according to emacs
- */
-protected char *
-ce__endword(char *p, char *high, int n)
-{
- p++;
-
- while (n--) {
- while ((p < high) && isspace((unsigned char) *p))
- p++;
- while ((p < high) && !isspace((unsigned char) *p))
- p++;
- }
-
- p--;
- return (p);
-}
-#endif
-
-
-/* cv__endword():
- * Go to the end of this word according to vi
- */
-protected char *
-cv__endword(char *p, char *high, int n)
-{
- p++;
-
- while (n--) {
- while ((p < high) && isspace((unsigned char) *p))
- p++;
-
- if (isalnum((unsigned char) *p))
- while ((p < high) && isalnum((unsigned char) *p))
- p++;
- else
- while ((p < high) && !(isspace((unsigned char) *p) ||
- isalnum((unsigned char) *p)))
- p++;
- }
- p--;
- return (p);
-}
-
-/* ch_init():
- * Initialize the character editor
- */
-protected int
-ch_init(EditLine *el)
-{
- el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ);
- if (el->el_line.buffer == NULL)
- return (-1);
-
- (void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
- el->el_line.cursor = el->el_line.buffer;
- el->el_line.lastchar = el->el_line.buffer;
- el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - 2];
-
- el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ);
- if (el->el_chared.c_undo.buf == NULL)
- return (-1);
- (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
- el->el_chared.c_undo.action = NOP;
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
- el->el_chared.c_undo.ptr = el->el_line.buffer;
-
- el->el_chared.c_vcmd.action = NOP;
- el->el_chared.c_vcmd.pos = el->el_line.buffer;
- el->el_chared.c_vcmd.ins = el->el_line.buffer;
-
- el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ);
- if (el->el_chared.c_kill.buf == NULL)
- return (-1);
- (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
- el->el_chared.c_kill.mark = el->el_line.buffer;
- el->el_chared.c_kill.last = el->el_chared.c_kill.buf;
-
- el->el_map.current = el->el_map.key;
-
- el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
- el->el_state.doingarg = 0;
- el->el_state.metanext = 0;
- el->el_state.argument = 1;
- el->el_state.lastcmd = ED_UNASSIGNED;
-
- el->el_chared.c_macro.nline = NULL;
- el->el_chared.c_macro.level = -1;
- el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO *
- sizeof(char *));
- if (el->el_chared.c_macro.macro == NULL)
- return (-1);
- return (0);
-}
-
-/* ch_reset():
- * Reset the character editor
- */
-protected void
-ch_reset(EditLine *el)
-{
- el->el_line.cursor = el->el_line.buffer;
- el->el_line.lastchar = el->el_line.buffer;
-
- el->el_chared.c_undo.action = NOP;
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
- el->el_chared.c_undo.ptr = el->el_line.buffer;
-
- el->el_chared.c_vcmd.action = NOP;
- el->el_chared.c_vcmd.pos = el->el_line.buffer;
- el->el_chared.c_vcmd.ins = el->el_line.buffer;
-
- el->el_chared.c_kill.mark = el->el_line.buffer;
-
- el->el_map.current = el->el_map.key;
-
- el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
- el->el_state.doingarg = 0;
- el->el_state.metanext = 0;
- el->el_state.argument = 1;
- el->el_state.lastcmd = ED_UNASSIGNED;
-
- el->el_chared.c_macro.level = -1;
-
- el->el_history.eventno = 0;
-}
-
-/* ch_enlargebufs():
- * Enlarge line buffer to be able to hold twice as much characters.
- * Returns 1 if successful, 0 if not.
- */
-protected int
-ch_enlargebufs(el, addlen)
- EditLine *el;
- size_t addlen;
-{
- size_t sz, newsz;
- char *newbuffer, *oldbuf, *oldkbuf;
-
- sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE;
- newsz = sz * 2;
- /*
- * If newly required length is longer than current buffer, we need
- * to make the buffer big enough to hold both old and new stuff.
- */
- if (addlen > sz) {
- while(newsz - sz < addlen)
- newsz *= 2;
- }
-
- /*
- * Reallocate line buffer.
- */
- newbuffer = el_realloc(el->el_line.buffer, newsz);
- if (!newbuffer)
- return 0;
-
- /* zero the newly added memory, leave old data in */
- (void) memset(&newbuffer[sz], 0, newsz - sz);
-
- oldbuf = el->el_line.buffer;
-
- el->el_line.buffer = newbuffer;
- el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
- el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
- el->el_line.limit = &newbuffer[newsz - EL_LEAVE];
-
- /*
- * Reallocate kill buffer.
- */
- newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz);
- if (!newbuffer)
- return 0;
-
- /* zero the newly added memory, leave old data in */
- (void) memset(&newbuffer[sz], 0, newsz - sz);
-
- oldkbuf = el->el_chared.c_kill.buf;
-
- el->el_chared.c_kill.buf = newbuffer;
- el->el_chared.c_kill.last = newbuffer +
- (el->el_chared.c_kill.last - oldkbuf);
- el->el_chared.c_kill.mark = el->el_line.buffer +
- (el->el_chared.c_kill.mark - oldbuf);
-
- /*
- * Reallocate undo buffer.
- */
- newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz);
- if (!newbuffer)
- return 0;
-
- /* zero the newly added memory, leave old data in */
- (void) memset(&newbuffer[sz], 0, newsz - sz);
-
- el->el_chared.c_undo.ptr = el->el_line.buffer +
- (el->el_chared.c_undo.ptr - oldbuf);
- el->el_chared.c_undo.buf = newbuffer;
-
- if (!hist_enlargebuf(el, sz, newsz))
- return 0;
-
- return 1;
-}
-
-/* ch_end():
- * Free the data structures used by the editor
- */
-protected void
-ch_end(EditLine *el)
-{
- el_free((ptr_t) el->el_line.buffer);
- el->el_line.buffer = NULL;
- el->el_line.limit = NULL;
- el_free((ptr_t) el->el_chared.c_undo.buf);
- el->el_chared.c_undo.buf = NULL;
- el_free((ptr_t) el->el_chared.c_kill.buf);
- el->el_chared.c_kill.buf = NULL;
- el_free((ptr_t) el->el_chared.c_macro.macro);
- el->el_chared.c_macro.macro = NULL;
- ch_reset(el);
-}
-
-
-/* el_insertstr():
- * Insert string at cursorI
- */
-public int
-el_insertstr(EditLine *el, const char *s)
-{
- size_t len;
-
- if ((len = strlen(s)) == 0)
- return (-1);
- if (el->el_line.lastchar + len >= el->el_line.limit) {
- if (!ch_enlargebufs(el, len))
- return (-1);
- }
-
- c_insert(el, (int)len);
- while (*s)
- *el->el_line.cursor++ = *s++;
- return (0);
-}
-
-
-/* el_deletestr():
- * Delete num characters before the cursor
- */
-public void
-el_deletestr(EditLine *el, int n)
-{
- if (n <= 0)
- return;
-
- if (el->el_line.cursor < &el->el_line.buffer[n])
- return;
-
- c_delbefore(el, n); /* delete before dot */
- el->el_line.cursor -= n;
- if (el->el_line.cursor < el->el_line.buffer)
- el->el_line.cursor = el->el_line.buffer;
-}
-
-/* c_gets():
- * Get a string
- */
-protected int
-c_gets(EditLine *el, char *buf)
-{
- char ch;
- int len = 0;
-
- for (ch = 0; ch == 0;) {
- if (el_getc(el, &ch) != 1)
- return (ed_end_of_file(el, 0));
- switch (ch) {
- case 0010: /* Delete and backspace */
- case 0177:
- if (len > 1) {
- *el->el_line.cursor-- = '\0';
- el->el_line.lastchar = el->el_line.cursor;
- buf[len--] = '\0';
- } else {
- el->el_line.buffer[0] = '\0';
- el->el_line.lastchar = el->el_line.buffer;
- el->el_line.cursor = el->el_line.buffer;
- return (CC_REFRESH);
- }
- re_refresh(el);
- ch = 0;
- break;
-
- case 0033: /* ESC */
- case '\r': /* Newline */
- case '\n':
- break;
-
- default:
- if (len >= EL_BUFSIZ)
- term_beep(el);
- else {
- buf[len++] = ch;
- *el->el_line.cursor++ = ch;
- el->el_line.lastchar = el->el_line.cursor;
- }
- re_refresh(el);
- ch = 0;
- break;
- }
- }
- buf[len] = ch;
- return (len);
-}
-
-
-/* c_hpos():
- * Return the current horizontal position of the cursor
- */
-protected int
-c_hpos(EditLine *el)
-{
- char *ptr;
-
- /*
- * Find how many characters till the beginning of this line.
- */
- if (el->el_line.cursor == el->el_line.buffer)
- return (0);
- else {
- for (ptr = el->el_line.cursor - 1;
- ptr >= el->el_line.buffer && *ptr != '\n';
- ptr--)
- continue;
- return (el->el_line.cursor - ptr - 1);
- }
-}
diff --git a/main/editline/chared.h b/main/editline/chared.h
deleted file mode 100644
index 403eca011..000000000
--- a/main/editline/chared.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* $NetBSD: chared.h,v 1.8 2002/03/18 16:00:51 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)chared.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.chared.h: Character editor interface
- */
-#ifndef _h_el_chared
-#define _h_el_chared
-
-#include <ctype.h>
-#include <string.h>
-
-#include "histedit.h"
-
-#define EL_MAXMACRO 10
-
-/*
- * This is a issue of basic "vi" look-and-feel. Defining VI_MOVE works
- * like real vi: i.e. the transition from command<->insert modes moves
- * the cursor.
- *
- * On the other hand we really don't want to move the cursor, because
- * all the editing commands don't include the character under the cursor.
- * Probably the best fix is to make all the editing commands aware of
- * this fact.
- */
-#define VI_MOVE
-
-
-typedef struct c_macro_t {
- int level;
- char **macro;
- char *nline;
-} c_macro_t;
-
-/*
- * Undo information for both vi and emacs
- */
-typedef struct c_undo_t {
- int action;
- size_t isize;
- size_t dsize;
- char *ptr;
- char *buf;
-} c_undo_t;
-
-/*
- * Current action information for vi
- */
-typedef struct c_vcmd_t {
- int action;
- char *pos;
- char *ins;
-} c_vcmd_t;
-
-/*
- * Kill buffer for emacs
- */
-typedef struct c_kill_t {
- char *buf;
- char *last;
- char *mark;
-} c_kill_t;
-
-/*
- * Note that we use both data structures because the user can bind
- * commands from both editors!
- */
-typedef struct el_chared_t {
- c_undo_t c_undo;
- c_kill_t c_kill;
- c_vcmd_t c_vcmd;
- c_macro_t c_macro;
-} el_chared_t;
-
-
-#define STReof "^D\b\b"
-#define STRQQ "\"\""
-
-#define isglob(a) (strchr("*[]?", (a)) != NULL)
-#define isword(a) (isprint(a))
-
-#define NOP 0x00
-#define DELETE 0x01
-#define INSERT 0x02
-#define CHANGE 0x04
-
-#define CHAR_FWD 0
-#define CHAR_BACK 1
-
-#define MODE_INSERT 0
-#define MODE_REPLACE 1
-#define MODE_REPLACE_1 2
-
-#include "common.h"
-#include "vi.h"
-#include "emacs.h"
-#include "search.h"
-#include "fcns.h"
-
-
-protected int cv__isword(int);
-protected void cv_delfini(EditLine *);
-protected char *cv__endword(char *, char *, int);
-protected int ce__isword(int);
-protected void cv_undo(EditLine *, int, size_t, char *);
-protected char *cv_next_word(EditLine*, char *, char *, int, int (*)(int));
-protected char *cv_prev_word(EditLine*, char *, char *, int, int (*)(int));
-protected char *c__next_word(char *, char *, int, int (*)(int));
-protected char *c__prev_word(char *, char *, int, int (*)(int));
-protected void c_insert(EditLine *, int);
-protected void c_delbefore(EditLine *, int);
-protected void c_delafter(EditLine *, int);
-protected int c_gets(EditLine *, char *);
-protected int c_hpos(EditLine *);
-
-protected int ch_init(EditLine *);
-protected void ch_reset(EditLine *);
-protected int ch_enlargebufs(EditLine *, size_t);
-protected void ch_end(EditLine *);
-
-#endif /* _h_el_chared */
diff --git a/main/editline/common.c b/main/editline/common.c
deleted file mode 100644
index c831e79a3..000000000
--- a/main/editline/common.c
+++ /dev/null
@@ -1,951 +0,0 @@
-/* $NetBSD: common.c,v 1.11 2002/03/18 16:00:51 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: common.c,v 1.11 2002/03/18 16:00:51 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * common.c: Common Editor functions
- */
-#include "el.h"
-
-/* ed_end_of_file():
- * Indicate end of file
- * [^D]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_end_of_file(EditLine *el, int c)
-{
-
- re_goto_bottom(el);
- *el->el_line.lastchar = '\0';
- return (CC_EOF);
-}
-
-
-/* ed_insert():
- * Add character to the line
- * Insert a character [bound to all insert keys]
- */
-protected el_action_t
-ed_insert(EditLine *el, int c)
-{
- int i;
-
- if (c == '\0')
- return (CC_ERROR);
-
- if (el->el_line.lastchar + el->el_state.argument >=
- el->el_line.limit) {
- /* end of buffer space, try to allocate more */
- if (!ch_enlargebufs(el, (size_t) el->el_state.argument))
- return CC_ERROR; /* error allocating more */
- }
-
- if (el->el_state.argument == 1) {
- if (el->el_state.inputmode != MODE_INSERT) {
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
- *el->el_line.cursor;
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
- '\0';
- c_delafter(el, 1);
- }
- c_insert(el, 1);
-
- *el->el_line.cursor++ = c;
- el->el_state.doingarg = 0; /* just in case */
- re_fastaddc(el); /* fast refresh for one char. */
- } else {
- if (el->el_state.inputmode != MODE_INSERT) {
- for (i = 0; i < el->el_state.argument; i++)
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
- el->el_line.cursor[i];
-
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
- '\0';
- c_delafter(el, el->el_state.argument);
- }
- c_insert(el, el->el_state.argument);
-
- while (el->el_state.argument--)
- *el->el_line.cursor++ = c;
- re_refresh(el);
- }
-
- if (el->el_state.inputmode == MODE_REPLACE_1)
- (void) vi_command_mode(el, 0);
-
- return (CC_NORM);
-}
-
-
-/* ed_delete_prev_word():
- * Delete from beginning of current word to cursor
- * [M-^?] [^W]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_delete_prev_word(EditLine *el, int c)
-{
- char *cp, *p, *kp;
-
- if (el->el_line.cursor == el->el_line.buffer)
- return (CC_ERROR);
-
- cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
- el->el_state.argument, ce__isword);
-
- for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
- *kp++ = *p;
- el->el_chared.c_kill.last = kp;
-
- c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */
- el->el_line.cursor = cp;
- if (el->el_line.cursor < el->el_line.buffer)
- el->el_line.cursor = el->el_line.buffer; /* bounds check */
- return (CC_REFRESH);
-}
-
-
-/* ed_delete_next_char():
- * Delete character under cursor
- * [^D] [x]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_delete_next_char(EditLine *el, int c)
-{
-#ifdef notdef /* XXX */
-#define EL el->el_line
- (void) fprintf(el->el_errlfile,
- "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
- EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
- EL.lastchar, EL.limit, EL.limit);
-#endif
- if (el->el_line.cursor == el->el_line.lastchar) {
- /* if I'm at the end */
- if (el->el_map.type == MAP_VI) {
- if (el->el_line.cursor == el->el_line.buffer) {
- /* if I'm also at the beginning */
-#ifdef KSHVI
- return (CC_ERROR);
-#else
- term_overwrite(el, STReof, 4);
- /* then do a EOF */
- term__flush();
- return (CC_EOF);
-#endif
- } else {
-#ifdef KSHVI
- el->el_line.cursor--;
-#else
- return (CC_ERROR);
-#endif
- }
- } else {
- if (el->el_line.cursor != el->el_line.buffer)
- el->el_line.cursor--;
- else
- return (CC_ERROR);
- }
- }
- c_delafter(el, el->el_state.argument); /* delete after dot */
- if (el->el_line.cursor >= el->el_line.lastchar &&
- el->el_line.cursor > el->el_line.buffer)
- /* bounds check */
- el->el_line.cursor = el->el_line.lastchar - 1;
- return (CC_REFRESH);
-}
-
-
-/* ed_kill_line():
- * Cut to the end of line
- * [^K] [^K]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_kill_line(EditLine *el, int c)
-{
- char *kp, *cp;
-
- cp = el->el_line.cursor;
- kp = el->el_chared.c_kill.buf;
- while (cp < el->el_line.lastchar)
- *kp++ = *cp++; /* copy it */
- el->el_chared.c_kill.last = kp;
- /* zap! -- delete to end */
- el->el_line.lastchar = el->el_line.cursor;
- return (CC_REFRESH);
-}
-
-
-/* ed_move_to_end():
- * Move cursor to the end of line
- * [^E] [^E]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_move_to_end(EditLine *el, int c)
-{
-
- el->el_line.cursor = el->el_line.lastchar;
- if (el->el_map.type == MAP_VI) {
-#ifdef VI_MOVE
- el->el_line.cursor--;
-#endif
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- }
- return (CC_CURSOR);
-}
-
-
-/* ed_move_to_beg():
- * Move cursor to the beginning of line
- * [^A] [^A]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_move_to_beg(EditLine *el, int c)
-{
-
- el->el_line.cursor = el->el_line.buffer;
-
- if (el->el_map.type == MAP_VI) {
- /* We want FIRST non space character */
- while (isspace((unsigned char) *el->el_line.cursor))
- el->el_line.cursor++;
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- }
- return (CC_CURSOR);
-}
-
-
-/* ed_transpose_chars():
- * Exchange the character to the left of the cursor with the one under it
- * [^T] [^T]
- */
-protected el_action_t
-ed_transpose_chars(EditLine *el, int c)
-{
-
- if (el->el_line.cursor < el->el_line.lastchar) {
- if (el->el_line.lastchar <= &el->el_line.buffer[1])
- return (CC_ERROR);
- else
- el->el_line.cursor++;
- }
- if (el->el_line.cursor > &el->el_line.buffer[1]) {
- /* must have at least two chars entered */
- c = el->el_line.cursor[-2];
- el->el_line.cursor[-2] = el->el_line.cursor[-1];
- el->el_line.cursor[-1] = c;
- return (CC_REFRESH);
- } else
- return (CC_ERROR);
-}
-
-
-/* ed_next_char():
- * Move to the right one character
- * [^F] [^F]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_next_char(EditLine *el, int c)
-{
-
- if (el->el_line.cursor >= el->el_line.lastchar)
- return (CC_ERROR);
-
- el->el_line.cursor += el->el_state.argument;
- if (el->el_line.cursor > el->el_line.lastchar)
- el->el_line.cursor = el->el_line.lastchar;
-
- if (el->el_map.type == MAP_VI)
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
-}
-
-
-/* ed_prev_word():
- * Move to the beginning of the current word
- * [M-b] [b]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_prev_word(EditLine *el, int c)
-{
-
- if (el->el_line.cursor == el->el_line.buffer)
- return (CC_ERROR);
-
- el->el_line.cursor = c__prev_word(el->el_line.cursor,
- el->el_line.buffer,
- el->el_state.argument,
- ce__isword);
-
- if (el->el_map.type == MAP_VI)
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
-}
-
-
-/* ed_prev_char():
- * Move to the left one character
- * [^B] [^B]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_prev_char(EditLine *el, int c)
-{
-
- if (el->el_line.cursor > el->el_line.buffer) {
- el->el_line.cursor -= el->el_state.argument;
- if (el->el_line.cursor < el->el_line.buffer)
- el->el_line.cursor = el->el_line.buffer;
-
- if (el->el_map.type == MAP_VI)
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
- } else
- return (CC_ERROR);
-}
-
-
-/* ed_quoted_insert():
- * Add the next character typed verbatim
- * [^V] [^V]
- */
-protected el_action_t
-ed_quoted_insert(EditLine *el, int c)
-{
- int num;
- char tc;
-
- tty_quotemode(el);
- num = el_getc(el, &tc);
- c = (unsigned char) tc;
- tty_noquotemode(el);
- if (num == 1)
- return (ed_insert(el, c));
- else
- return (ed_end_of_file(el, 0));
-}
-
-
-/* ed_digit():
- * Adds to argument or enters a digit
- */
-protected el_action_t
-ed_digit(EditLine *el, int c)
-{
-
- if (!isdigit(c))
- return (CC_ERROR);
-
- if (el->el_state.doingarg) {
- /* if doing an arg, add this in... */
- if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
- el->el_state.argument = c - '0';
- else {
- if (el->el_state.argument > 1000000)
- return (CC_ERROR);
- el->el_state.argument =
- (el->el_state.argument * 10) + (c - '0');
- }
- return (CC_ARGHACK);
- } else {
- if (el->el_line.lastchar + 1 >= el->el_line.limit) {
- if (!ch_enlargebufs(el, 1))
- return (CC_ERROR);
- }
-
- if (el->el_state.inputmode != MODE_INSERT) {
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
- *el->el_line.cursor;
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
- '\0';
- c_delafter(el, 1);
- }
- c_insert(el, 1);
- *el->el_line.cursor++ = c;
- el->el_state.doingarg = 0;
- re_fastaddc(el);
- }
- return (CC_NORM);
-}
-
-
-/* ed_argument_digit():
- * Digit that starts argument
- * For ESC-n
- */
-protected el_action_t
-ed_argument_digit(EditLine *el, int c)
-{
-
- if (!isdigit(c))
- return (CC_ERROR);
-
- if (el->el_state.doingarg) {
- if (el->el_state.argument > 1000000)
- return (CC_ERROR);
- el->el_state.argument = (el->el_state.argument * 10) +
- (c - '0');
- } else { /* else starting an argument */
- el->el_state.argument = c - '0';
- el->el_state.doingarg = 1;
- }
- return (CC_ARGHACK);
-}
-
-
-/* ed_unassigned():
- * Indicates unbound character
- * Bound to keys that are not assigned
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_unassigned(EditLine *el, int c)
-{
-
- term_beep(el);
- term__flush();
- return (CC_NORM);
-}
-
-
-/**
- ** TTY key handling.
- **/
-
-/* ed_tty_sigint():
- * Tty interrupt character
- * [^C]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_tty_sigint(EditLine *el, int c)
-{
-
- return (CC_NORM);
-}
-
-
-/* ed_tty_dsusp():
- * Tty delayed suspend character
- * [^Y]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_tty_dsusp(EditLine *el, int c)
-{
-
- return (CC_NORM);
-}
-
-
-/* ed_tty_flush_output():
- * Tty flush output characters
- * [^O]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_tty_flush_output(EditLine *el, int c)
-{
-
- return (CC_NORM);
-}
-
-
-/* ed_tty_sigquit():
- * Tty quit character
- * [^\]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_tty_sigquit(EditLine *el, int c)
-{
-
- return (CC_NORM);
-}
-
-
-/* ed_tty_sigtstp():
- * Tty suspend character
- * [^Z]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_tty_sigtstp(EditLine *el, int c)
-{
-
- return (CC_NORM);
-}
-
-
-/* ed_tty_stop_output():
- * Tty disallow output characters
- * [^S]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_tty_stop_output(EditLine *el, int c)
-{
-
- return (CC_NORM);
-}
-
-
-/* ed_tty_start_output():
- * Tty allow output characters
- * [^Q]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_tty_start_output(EditLine *el, int c)
-{
-
- return (CC_NORM);
-}
-
-
-/* ed_newline():
- * Execute command
- * [^J]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_newline(EditLine *el, int c)
-{
-
- re_goto_bottom(el);
- *el->el_line.lastchar++ = '\n';
- *el->el_line.lastchar = '\0';
- if (el->el_map.type == MAP_VI)
- el->el_chared.c_vcmd.ins = el->el_line.buffer;
- return (CC_NEWLINE);
-}
-
-
-/* ed_delete_prev_char():
- * Delete the character to the left of the cursor
- * [^?]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_delete_prev_char(EditLine *el, int c)
-{
-
- if (el->el_line.cursor <= el->el_line.buffer)
- return (CC_ERROR);
-
- c_delbefore(el, el->el_state.argument);
- el->el_line.cursor -= el->el_state.argument;
- if (el->el_line.cursor < el->el_line.buffer)
- el->el_line.cursor = el->el_line.buffer;
- return (CC_REFRESH);
-}
-
-
-/* ed_clear_screen():
- * Clear screen leaving current line at the top
- * [^L]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_clear_screen(EditLine *el, int c)
-{
-
- term_clear_screen(el); /* clear the whole real screen */
- re_clear_display(el); /* reset everything */
- return (CC_REFRESH);
-}
-
-
-/* ed_redisplay():
- * Redisplay everything
- * ^R
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_redisplay(EditLine *el, int c)
-{
-
- return (CC_REDISPLAY);
-}
-
-
-/* ed_start_over():
- * Erase current line and start from scratch
- * [^G]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_start_over(EditLine *el, int c)
-{
-
- ch_reset(el);
- return (CC_REFRESH);
-}
-
-
-/* ed_sequence_lead_in():
- * First character in a bound sequence
- * Placeholder for external keys
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_sequence_lead_in(EditLine *el, int c)
-{
-
- return (CC_NORM);
-}
-
-
-/* ed_prev_history():
- * Move to the previous history line
- * [^P] [k]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_prev_history(EditLine *el, int c)
-{
- char beep = 0;
-
- el->el_chared.c_undo.action = NOP;
- *el->el_line.lastchar = '\0'; /* just in case */
-
- if (el->el_history.eventno == 0) { /* save the current buffer
- * away */
- (void) strncpy(el->el_history.buf, el->el_line.buffer,
- EL_BUFSIZ - 1);
- el->el_history.last = el->el_history.buf +
- (el->el_line.lastchar - el->el_line.buffer);
- }
- el->el_history.eventno += el->el_state.argument;
-
- if (hist_get(el) == CC_ERROR) {
- beep = 1;
- /* el->el_history.eventno was fixed by first call */
- (void) hist_get(el);
- }
- re_refresh(el);
- if (beep)
- return (CC_ERROR);
- else
- return (CC_NORM); /* was CC_UP_HIST */
-}
-
-
-/* ed_next_history():
- * Move to the next history line
- * [^N] [j]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_next_history(EditLine *el, int c)
-{
-
- el->el_chared.c_undo.action = NOP;
- *el->el_line.lastchar = '\0'; /* just in case */
-
- el->el_history.eventno -= el->el_state.argument;
-
- if (el->el_history.eventno < 0) {
- el->el_history.eventno = 0;
- return (CC_ERROR);/* make it beep */
- }
- return (hist_get(el));
-}
-
-
-/* ed_search_prev_history():
- * Search previous in history for a line matching the current
- * next search history [M-P] [K]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_search_prev_history(EditLine *el, int c)
-{
- const char *hp;
- int h;
- bool_t found = 0;
-
- el->el_chared.c_vcmd.action = NOP;
- el->el_chared.c_undo.action = NOP;
- *el->el_line.lastchar = '\0'; /* just in case */
- if (el->el_history.eventno < 0) {
-#ifdef DEBUG_EDIT
- (void) fprintf(el->el_errfile,
- "e_prev_search_hist(): eventno < 0;\n");
-#endif
- el->el_history.eventno = 0;
- return (CC_ERROR);
- }
- if (el->el_history.eventno == 0) {
- (void) strncpy(el->el_history.buf, el->el_line.buffer,
- EL_BUFSIZ - 1);
- el->el_history.last = el->el_history.buf +
- (el->el_line.lastchar - el->el_line.buffer);
- }
- if (el->el_history.ref == NULL)
- return (CC_ERROR);
-
- hp = HIST_FIRST(el);
- if (hp == NULL)
- return (CC_ERROR);
-
- c_setpat(el); /* Set search pattern !! */
-
- for (h = 1; h <= el->el_history.eventno; h++)
- hp = HIST_NEXT(el);
-
- while (hp != NULL) {
-#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
-#endif
- if ((strncmp(hp, el->el_line.buffer, (size_t)
- (el->el_line.lastchar - el->el_line.buffer)) ||
- hp[el->el_line.lastchar - el->el_line.buffer]) &&
- c_hmatch(el, hp)) {
- found++;
- break;
- }
- h++;
- hp = HIST_NEXT(el);
- }
-
- if (!found) {
-#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "not found\n");
-#endif
- return (CC_ERROR);
- }
- el->el_history.eventno = h;
-
- return (hist_get(el));
-}
-
-
-/* ed_search_next_history():
- * Search next in history for a line matching the current
- * [M-N] [J]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_search_next_history(EditLine *el, int c)
-{
- const char *hp;
- int h;
- bool_t found = 0;
-
- el->el_chared.c_vcmd.action = NOP;
- el->el_chared.c_undo.action = NOP;
- *el->el_line.lastchar = '\0'; /* just in case */
-
- if (el->el_history.eventno == 0)
- return (CC_ERROR);
-
- if (el->el_history.ref == NULL)
- return (CC_ERROR);
-
- hp = HIST_FIRST(el);
- if (hp == NULL)
- return (CC_ERROR);
-
- c_setpat(el); /* Set search pattern !! */
-
- for (h = 1; h < el->el_history.eventno && hp; h++) {
-#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
-#endif
- if ((strncmp(hp, el->el_line.buffer, (size_t)
- (el->el_line.lastchar - el->el_line.buffer)) ||
- hp[el->el_line.lastchar - el->el_line.buffer]) &&
- c_hmatch(el, hp))
- found = h;
- hp = HIST_NEXT(el);
- }
-
- if (!found) { /* is it the current history number? */
- if (!c_hmatch(el, el->el_history.buf)) {
-#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "not found\n");
-#endif
- return (CC_ERROR);
- }
- }
- el->el_history.eventno = found;
-
- return (hist_get(el));
-}
-
-
-/* ed_prev_line():
- * Move up one line
- * Could be [k] [^p]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_prev_line(EditLine *el, int c)
-{
- char *ptr;
- int nchars = c_hpos(el);
-
- /*
- * Move to the line requested
- */
- if (*(ptr = el->el_line.cursor) == '\n')
- ptr--;
-
- for (; ptr >= el->el_line.buffer; ptr--)
- if (*ptr == '\n' && --el->el_state.argument <= 0)
- break;
-
- if (el->el_state.argument > 0)
- return (CC_ERROR);
-
- /*
- * Move to the beginning of the line
- */
- for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
- continue;
-
- /*
- * Move to the character requested
- */
- for (ptr++;
- nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
- ptr++)
- continue;
-
- el->el_line.cursor = ptr;
- return (CC_CURSOR);
-}
-
-
-/* ed_next_line():
- * Move down one line
- * Could be [j] [^n]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_next_line(EditLine *el, int c)
-{
- char *ptr;
- int nchars = c_hpos(el);
-
- /*
- * Move to the line requested
- */
- for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
- if (*ptr == '\n' && --el->el_state.argument <= 0)
- break;
-
- if (el->el_state.argument > 0)
- return (CC_ERROR);
-
- /*
- * Move to the character requested
- */
- for (ptr++;
- nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
- ptr++)
- continue;
-
- el->el_line.cursor = ptr;
- return (CC_CURSOR);
-}
-
-
-/* ed_command():
- * Editline extended command
- * [M-X] [:]
- */
-protected el_action_t
-/*ARGSUSED*/
-ed_command(EditLine *el, int c)
-{
- char tmpbuf[EL_BUFSIZ];
- int tmplen;
-
- el->el_line.buffer[0] = '\0';
- el->el_line.lastchar = el->el_line.buffer;
- el->el_line.cursor = el->el_line.buffer;
-
- c_insert(el, 3); /* prompt + ": " */
- *el->el_line.cursor++ = '\n';
- *el->el_line.cursor++ = ':';
- *el->el_line.cursor++ = ' ';
- re_refresh(el);
-
- tmplen = c_gets(el, tmpbuf);
- tmpbuf[tmplen] = '\0';
-
- el->el_line.buffer[0] = '\0';
- el->el_line.lastchar = el->el_line.buffer;
- el->el_line.cursor = el->el_line.buffer;
-
- if (parse_line(el, tmpbuf) == -1)
- return (CC_ERROR);
- else
- return (CC_REFRESH);
-}
diff --git a/main/editline/config.guess b/main/editline/config.guess
deleted file mode 100755
index a6d8a945f..000000000
--- a/main/editline/config.guess
+++ /dev/null
@@ -1,1449 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
-timestamp='2004-06-24'
-
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Originally written by Per Bothner <per@bothner.com>.
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
-#
-# This script attempts to guess a canonical system name similar to
-# config.sub. If it succeeds, it prints the system name on stdout, and
-# exits with 0. Otherwise, it exits with 1.
-#
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit build system type.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit 0 ;;
- --version | -v )
- echo "$version" ; exit 0 ;;
- --help | --h* | -h )
- echo "$usage"; exit 0 ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help" >&2
- exit 1 ;;
- * )
- break ;;
- esac
-done
-
-if test $# != 0; then
- echo "$me: too many arguments$help" >&2
- exit 1
-fi
-
-trap 'exit 1' 1 2 15
-
-# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
-# compiler to aid in system detection is discouraged as it requires
-# temporary files to be created and, as you can see below, it is a
-# headache to deal with in a portable fashion.
-
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
-
-# Portable tmp directory creation inspired by the Autoconf team.
-
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ;'
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
- PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- *:NetBSD:*:*)
- # NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
- # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
- # switched to ELF, *-*-netbsd* would select the old
- # object file format. This provides both forward
- # compatibility and a consistent mechanism for selecting the
- # object file format.
- #
- # Note: NetBSD doesn't particularly care about the vendor
- # portion of the name. We always set it to "unknown".
- sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
- armeb) machine=armeb-unknown ;;
- arm*) machine=arm-unknown ;;
- sh3el) machine=shl-unknown ;;
- sh3eb) machine=sh-unknown ;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
- esac
- # The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
- case "${UNAME_MACHINE_ARCH}" in
- arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
- if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep __ELF__ >/dev/null
- then
- # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
- # Return netbsd for either. FIX?
- os=netbsd
- else
- os=netbsdelf
- fi
- ;;
- *)
- os=netbsd
- ;;
- esac
- # The OS release
- # Debian GNU/NetBSD machines have a different userland, and
- # thus, need a distinct triplet. However, they do not need
- # kernel version information, so it can be replaced with a
- # suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
- Debian*)
- release='-gnu'
- ;;
- *)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
- ;;
- esac
- # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
- # contains redundant information, the shorter form:
- # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}"
- exit 0 ;;
- amd64:OpenBSD:*:*)
- echo x86_64-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- amiga:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- arc:OpenBSD:*:*)
- echo mipsel-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- cats:OpenBSD:*:*)
- echo arm-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- hp300:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- luna88k:OpenBSD:*:*)
- echo m88k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mac68k:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- macppc:OpenBSD:*:*)
- echo powerpc-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mvme68k:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mvme88k:OpenBSD:*:*)
- echo m88k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mvmeppc:OpenBSD:*:*)
- echo powerpc-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- pmax:OpenBSD:*:*)
- echo mipsel-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- sgi:OpenBSD:*:*)
- echo mipseb-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- sun3:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- wgrisc:OpenBSD:*:*)
- echo mipsel-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- *:OpenBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- *:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
- exit 0 ;;
- macppc:MirBSD:*:*)
- echo powerppc-unknown-mirbsd${UNAME_RELEASE}
- exit 0 ;;
- *:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
- exit 0 ;;
- alpha:OSF1:*:*)
- case $UNAME_RELEASE in
- *4.0)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- ;;
- *5.*)
- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
- ;;
- esac
- # According to Compaq, /usr/sbin/psrinfo has been available on
- # OSF/1 and Tru64 systems produced since 1995. I hope that
- # covers most systems running today. This code pipes the CPU
- # types through head -n 1, so we only detect the type of CPU 0.
- ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
- case "$ALPHA_CPU_TYPE" in
- "EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
- "EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
- "LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
- "EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
- "EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
- "EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
- "EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
- "EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
- "EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
- "EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
- "EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
- "EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
- "EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
- esac
- # A Pn.n version is a patched version.
- # A Vn.n version is a released version.
- # A Tn.n version is a released field test version.
- # A Xn.n version is an unreleased experimental baselevel.
- # 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- exit 0 ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit 0 ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit 0 ;;
- Amiga*:UNIX_System_V:4.0:*)
- echo m68k-unknown-sysv4
- exit 0;;
- *:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
- exit 0 ;;
- *:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
- exit 0 ;;
- *:OS/390:*:*)
- echo i370-ibm-openedition
- exit 0 ;;
- *:OS400:*:*)
- echo powerpc-ibm-os400
- exit 0 ;;
- arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
- exit 0;;
- SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
- echo hppa1.1-hitachi-hiuxmpp
- exit 0;;
- Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
- # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
- if test "`(/bin/universe) 2>/dev/null`" = att ; then
- echo pyramid-pyramid-sysv3
- else
- echo pyramid-pyramid-bsd
- fi
- exit 0 ;;
- NILE*:*:*:dcosx)
- echo pyramid-pyramid-svr4
- exit 0 ;;
- DRS?6000:unix:4.0:6*)
- echo sparc-icl-nx6
- exit 0 ;;
- DRS?6000:UNIX_SV:4.2*:7*)
- case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7 && exit 0 ;;
- esac ;;
- sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- i86pc:SunOS:5.*:*)
- echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- sun4*:SunOS:6*:*)
- # According to config.sub, this is the proper way to canonicalize
- # SunOS6. Hard to guess exactly what SunOS6 will be like, but
- # it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- sun4*:SunOS:*:*)
- case "`/usr/bin/arch -k`" in
- Series*|S4*)
- UNAME_RELEASE=`uname -v`
- ;;
- esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit 0 ;;
- sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
- exit 0 ;;
- sun*:*:4.2BSD:*)
- UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
- case "`/bin/arch`" in
- sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
- ;;
- sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
- ;;
- esac
- exit 0 ;;
- aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
- exit 0 ;;
- # The situation for MiNT is a little confusing. The machine name
- # can be virtually everything (everything which is not
- # "atarist" or "atariste" at least should have a processor
- # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
- # to the lowercase version "mint" (or "freemint"). Finally
- # the system name "TOS" denotes a system which is actually not
- # MiNT. But MiNT is downward compatible to TOS, so this should
- # be no problem.
- atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit 0 ;;
- atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit 0 ;;
- *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit 0 ;;
- milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit 0 ;;
- hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit 0 ;;
- *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit 0 ;;
- m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
- exit 0 ;;
- powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
- exit 0 ;;
- RISC*:Mach:*:*)
- echo mips-dec-mach_bsd4.3
- exit 0 ;;
- RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
- exit 0 ;;
- VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
- exit 0 ;;
- 2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
- exit 0 ;;
- mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-#ifdef __cplusplus
-#include <stdio.h> /* for printf() prototype */
- int main (int argc, char *argv[]) {
-#else
- int main (argc, argv) int argc; char *argv[]; {
-#endif
- #if defined (host_mips) && defined (MIPSEB)
- #if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
- #endif
- #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
- #endif
- #endif
- exit (-1);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c \
- && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
- && exit 0
- echo mips-mips-riscos${UNAME_RELEASE}
- exit 0 ;;
- Motorola:PowerMAX_OS:*:*)
- echo powerpc-motorola-powermax
- exit 0 ;;
- Motorola:*:4.3:PL8-*)
- echo powerpc-harris-powermax
- exit 0 ;;
- Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
- echo powerpc-harris-powermax
- exit 0 ;;
- Night_Hawk:Power_UNIX:*:*)
- echo powerpc-harris-powerunix
- exit 0 ;;
- m88k:CX/UX:7*:*)
- echo m88k-harris-cxux7
- exit 0 ;;
- m88k:*:4*:R4*)
- echo m88k-motorola-sysv4
- exit 0 ;;
- m88k:*:3*:R3*)
- echo m88k-motorola-sysv3
- exit 0 ;;
- AViiON:dgux:*:*)
- # DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
- then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
- then
- echo m88k-dg-dgux${UNAME_RELEASE}
- else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
- fi
- else
- echo i586-dg-dgux${UNAME_RELEASE}
- fi
- exit 0 ;;
- M88*:DolphinOS:*:*) # DolphinOS (SVR3)
- echo m88k-dolphin-sysv3
- exit 0 ;;
- M88*:*:R3*:*)
- # Delta 88k system running SVR3
- echo m88k-motorola-sysv3
- exit 0 ;;
- XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
- echo m88k-tektronix-sysv3
- exit 0 ;;
- Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
- echo m68k-tektronix-bsd
- exit 0 ;;
- *:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit 0 ;;
- ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
- i*86:AIX:*:*)
- echo i386-ibm-aix
- exit 0 ;;
- ia64:AIX:*:*)
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit 0 ;;
- *:AIX:2:3)
- if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <sys/systemcfg.h>
-
- main()
- {
- if (!__power_pc())
- exit(1);
- puts("powerpc-ibm-aix3.2.5");
- exit(0);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
- echo rs6000-ibm-aix3.2.5
- elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
- echo rs6000-ibm-aix3.2.4
- else
- echo rs6000-ibm-aix3.2
- fi
- exit 0 ;;
- *:AIX:*:[45])
- IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
- IBM_ARCH=rs6000
- else
- IBM_ARCH=powerpc
- fi
- if [ -x /usr/bin/oslevel ] ; then
- IBM_REV=`/usr/bin/oslevel`
- else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
- fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit 0 ;;
- *:AIX:*:*)
- echo rs6000-ibm-aix
- exit 0 ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
- echo romp-ibm-bsd4.4
- exit 0 ;;
- ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit 0 ;; # report: romp-ibm BSD 4.3
- *:BOSX:*:*)
- echo rs6000-bull-bosx
- exit 0 ;;
- DPX/2?00:B.O.S.:*:*)
- echo m68k-bull-sysv3
- exit 0 ;;
- 9000/[34]??:4.3bsd:1.*:*)
- echo m68k-hp-bsd
- exit 0 ;;
- hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
- echo m68k-hp-bsd4.4
- exit 0 ;;
- 9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/[678][0-9][0-9])
- if [ -x /usr/bin/getconf ]; then
- sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
- 532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
- esac ;;
- esac
- fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
-
- #define _HPUX_SOURCE
- #include <stdlib.h>
- #include <unistd.h>
-
- int main ()
- {
- #if defined(_SC_KERNEL_BITS)
- long bits = sysconf(_SC_KERNEL_BITS);
- #endif
- long cpu = sysconf (_SC_CPU_VERSION);
-
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
- case CPU_PA_RISC2_0:
- #if defined(_SC_KERNEL_BITS)
- switch (bits)
- {
- case 64: puts ("hppa2.0w"); break;
- case 32: puts ("hppa2.0n"); break;
- default: puts ("hppa2.0"); break;
- } break;
- #else /* !defined(_SC_KERNEL_BITS) */
- puts ("hppa2.0"); break;
- #endif
- default: puts ("hppa1.0"); break;
- }
- exit (0);
- }
-EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
- test -z "$HP_ARCH" && HP_ARCH=hppa
- fi ;;
- esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
- then
- # avoid double evaluation of $set_cc_for_build
- test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
- then
- HP_ARCH="hppa2.0w"
- else
- HP_ARCH="hppa64"
- fi
- fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit 0 ;;
- ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
- exit 0 ;;
- 3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <unistd.h>
- int
- main ()
- {
- long cpu = sysconf (_SC_CPU_VERSION);
- /* The order matters, because CPU_IS_HP_MC68K erroneously returns
- true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
- results, however. */
- if (CPU_IS_PA_RISC (cpu))
- {
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
- case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
- default: puts ("hppa-hitachi-hiuxwe2"); break;
- }
- }
- else if (CPU_IS_HP_MC68K (cpu))
- puts ("m68k-hitachi-hiuxwe2");
- else puts ("unknown-hitachi-hiuxwe2");
- exit (0);
- }
-EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
- echo unknown-hitachi-hiuxwe2
- exit 0 ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
- echo hppa1.1-hp-bsd
- exit 0 ;;
- 9000/8??:4.3bsd:*:*)
- echo hppa1.0-hp-bsd
- exit 0 ;;
- *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
- echo hppa1.0-hp-mpeix
- exit 0 ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
- echo hppa1.1-hp-osf
- exit 0 ;;
- hp8??:OSF1:*:*)
- echo hppa1.0-hp-osf
- exit 0 ;;
- i*86:OSF1:*:*)
- if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
- else
- echo ${UNAME_MACHINE}-unknown-osf1
- fi
- exit 0 ;;
- parisc*:Lites*:*:*)
- echo hppa1.1-hp-lites
- exit 0 ;;
- C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
- echo c1-convex-bsd
- exit 0 ;;
- C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit 0 ;;
- C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
- echo c34-convex-bsd
- exit 0 ;;
- C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
- echo c38-convex-bsd
- exit 0 ;;
- C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
- echo c4-convex-bsd
- exit 0 ;;
- CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
- | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
- -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
- -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- *:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
- F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit 0 ;;
- 5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit 0 ;;
- i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit 0 ;;
- sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit 0 ;;
- *:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit 0 ;;
- *:FreeBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit 0 ;;
- i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
- exit 0 ;;
- i*:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
- exit 0 ;;
- i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
- exit 0 ;;
- x86:Interix*:[34]*)
- echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
- exit 0 ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit 0 ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit 0 ;;
- i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
- exit 0 ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
- exit 0 ;;
- prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- *:GNU:*:*)
- # the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit 0 ;;
- *:GNU/*:*:*)
- # other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
- exit 0 ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
- exit 0 ;;
- arm*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
- cris:Linux:*:*)
- echo cris-axis-linux-gnu
- exit 0 ;;
- ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
- m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
- m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
- mips:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips
- #undef mipsel
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mipsel
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips
- #else
- CPU=
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
- ;;
- mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips64
- #undef mips64el
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mips64el
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips64
- #else
- CPU=
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
- ;;
- ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
- exit 0 ;;
- ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
- exit 0 ;;
- alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
- EV5) UNAME_MACHINE=alphaev5 ;;
- EV56) UNAME_MACHINE=alphaev56 ;;
- PCA56) UNAME_MACHINE=alphapca56 ;;
- PCA57) UNAME_MACHINE=alphapca56 ;;
- EV6) UNAME_MACHINE=alphaev6 ;;
- EV67) UNAME_MACHINE=alphaev67 ;;
- EV68*) UNAME_MACHINE=alphaev68 ;;
- esac
- objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
- exit 0 ;;
- parisc:Linux:*:* | hppa:Linux:*:*)
- # Look for CPU level
- case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-gnu ;;
- PA8*) echo hppa2.0-unknown-linux-gnu ;;
- *) echo hppa-unknown-linux-gnu ;;
- esac
- exit 0 ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
- exit 0 ;;
- s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
- exit 0 ;;
- sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
- sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
- sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
- x86_64:Linux:*:*)
- echo x86_64-unknown-linux-gnu
- exit 0 ;;
- i*86:Linux:*:*)
- # The BFD linker knows what the default object file format is, so
- # first see if it will tell us. cd to the root directory to prevent
- # problems with other programs or directories called `ld' in the path.
- # Set LC_ALL=C to ensure ld outputs messages in English.
- ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
- | sed -ne '/supported targets:/!d
- s/[ ][ ]*/ /g
- s/.*supported targets: *//
- s/ .*//
- p'`
- case "$ld_supported_targets" in
- elf32-i386)
- TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
- ;;
- a.out-i386-linux)
- echo "${UNAME_MACHINE}-pc-linux-gnuaout"
- exit 0 ;;
- coff-i386)
- echo "${UNAME_MACHINE}-pc-linux-gnucoff"
- exit 0 ;;
- "")
- # Either a pre-BFD a.out linker (linux-gnuoldld) or
- # one that does not give us useful --help.
- echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
- exit 0 ;;
- esac
- # Determine whether the default compiler is a.out or elf
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <features.h>
- #ifdef __ELF__
- # ifdef __GLIBC__
- # if __GLIBC__ >= 2
- LIBC=gnu
- # else
- LIBC=gnulibc1
- # endif
- # else
- LIBC=gnulibc1
- # endif
- #else
- #ifdef __INTEL_COMPILER
- LIBC=gnu
- #else
- LIBC=gnuaout
- #endif
- #endif
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
- test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
- test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
- ;;
- i*86:DYNIX/ptx:4*:*)
- # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
- # earlier versions are messed up and put the nodename in both
- # sysname and nodename.
- echo i386-sequent-sysv4
- exit 0 ;;
- i*86:UNIX_SV:4.2MP:2.*)
- # Unixware is an offshoot of SVR4, but it has its own version
- # number series starting with 2...
- # I am not positive that other SVR4 systems won't match this,
- # I just have to hope. -- rms.
- # Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit 0 ;;
- i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
- # is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
- exit 0 ;;
- i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
- exit 0 ;;
- i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
- exit 0 ;;
- i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
- exit 0 ;;
- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit 0 ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
- if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
- else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
- fi
- exit 0 ;;
- i*86:*:5:[78]*)
- case `/bin/uname -X | grep "^Machine"` in
- *486*) UNAME_MACHINE=i486 ;;
- *Pentium) UNAME_MACHINE=i586 ;;
- *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
- esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit 0 ;;
- i*86:*:3.2:*)
- if test -f /usr/options/cb.name; then
- UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
- elif /bin/uname -X 2>/dev/null >/dev/null ; then
- UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
- (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
- (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
- && UNAME_MACHINE=i586
- (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
- && UNAME_MACHINE=i686
- (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
- && UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
- else
- echo ${UNAME_MACHINE}-pc-sysv32
- fi
- exit 0 ;;
- pc:*:*:*)
- # Left here for compatibility:
- # uname -m prints for DJGPP always 'pc', but it prints nothing about
- # the processor, so we play safe by assuming i386.
- echo i386-pc-msdosdjgpp
- exit 0 ;;
- Intel:Mach:3*:*)
- echo i386-pc-mach3
- exit 0 ;;
- paragon:*:*:*)
- echo i860-intel-osf1
- exit 0 ;;
- i860:*:4.*:*) # i860-SVR4
- if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
- else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
- fi
- exit 0 ;;
- mini*:CTIX:SYS*5:*)
- # "miniframe"
- echo m68010-convergent-sysv
- exit 0 ;;
- mc68k:UNIX:SYSTEM5:3.51m)
- echo m68k-convergent-sysv
- exit 0 ;;
- M680?0:D-NIX:5.3:*)
- echo m68k-diab-dnix
- exit 0 ;;
- M68*:*:R3V[5678]*:*)
- test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
- 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
- OS_REL=''
- test -r /etc/.relid \
- && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && echo i486-ncr-sysv4.3${OS_REL} && exit 0
- /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
- 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && echo i486-ncr-sysv4 && exit 0 ;;
- m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- mc68030:UNIX_System_V:4.*:*)
- echo m68k-atari-sysv4
- exit 0 ;;
- TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
- exit 0 ;;
- RM*:ReliantUNIX-*:*:*)
- echo mips-sni-sysv4
- exit 0 ;;
- RM*:SINIX-*:*:*)
- echo mips-sni-sysv4
- exit 0 ;;
- *:SINIX-*:*:*)
- if uname -p 2>/dev/null >/dev/null ; then
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
- else
- echo ns32k-sni-sysv
- fi
- exit 0 ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit 0 ;;
- *:UNIX_System_V:4*:FTX*)
- # From Gerald Hewes <hewes@openmarket.com>.
- # How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit 0 ;;
- *:*:*:FTX*)
- # From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit 0 ;;
- *:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo hppa1.1-stratus-vos
- exit 0 ;;
- mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
- exit 0 ;;
- news*:NEWS-OS:6*:*)
- echo mips-sony-newsos6
- exit 0 ;;
- R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
- else
- echo mips-unknown-sysv${UNAME_RELEASE}
- fi
- exit 0 ;;
- BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
- echo powerpc-be-beos
- exit 0 ;;
- BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
- echo powerpc-apple-beos
- exit 0 ;;
- BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
- echo i586-pc-beos
- exit 0 ;;
- SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
- exit 0 ;;
- SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
- exit 0 ;;
- SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
- exit 0 ;;
- Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit 0 ;;
- *:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit 0 ;;
- *:Darwin:*:*)
- case `uname -p` in
- *86) UNAME_PROCESSOR=i686 ;;
- powerpc) UNAME_PROCESSOR=powerpc ;;
- esac
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit 0 ;;
- *:procnto*:*:* | *:QNX:[0123456789]*:*)
- UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
- UNAME_PROCESSOR=i386
- UNAME_MACHINE=pc
- fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit 0 ;;
- *:QNX:*:4*)
- echo i386-pc-qnx
- exit 0 ;;
- NSR-?:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
- exit 0 ;;
- *:NonStop-UX:*:*)
- echo mips-compaq-nonstopux
- exit 0 ;;
- BS2000:POSIX*:*:*)
- echo bs2000-siemens-sysv
- exit 0 ;;
- DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit 0 ;;
- *:Plan9:*:*)
- # "uname -m" is not consistent, so use $cputype instead. 386
- # is converted to i386 for consistency with other x86
- # operating systems.
- if test "$cputype" = "386"; then
- UNAME_MACHINE=i386
- else
- UNAME_MACHINE="$cputype"
- fi
- echo ${UNAME_MACHINE}-unknown-plan9
- exit 0 ;;
- *:TOPS-10:*:*)
- echo pdp10-unknown-tops10
- exit 0 ;;
- *:TENEX:*:*)
- echo pdp10-unknown-tenex
- exit 0 ;;
- KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
- echo pdp10-dec-tops20
- exit 0 ;;
- XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
- echo pdp10-xkl-tops20
- exit 0 ;;
- *:TOPS-20:*:*)
- echo pdp10-unknown-tops20
- exit 0 ;;
- *:ITS:*:*)
- echo pdp10-unknown-its
- exit 0 ;;
- SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
- exit 0 ;;
- *:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
- exit 0 ;;
- *:*VMS:*:*)
- UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
- A*) echo alpha-dec-vms && exit 0 ;;
- I*) echo ia64-dec-vms && exit 0 ;;
- V*) echo vax-dec-vms && exit 0 ;;
- esac
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
- I don't know.... */
- printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
- printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
- "4"
-#else
- ""
-#endif
- ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
- printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
- int version;
- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- if (version < 4)
- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
- else
- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
- exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
- printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
- printf ("ns32k-encore-mach\n"); exit (0);
-#else
- printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
- printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
- printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
- printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
- struct utsname un;
-
- uname(&un);
-
- if (strncmp(un.version, "V2", 2) == 0) {
- printf ("i386-sequent-ptx2\n"); exit (0);
- }
- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
- printf ("i386-sequent-ptx1\n"); exit (0);
- }
- printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-# include <sys/param.h>
-# if defined (BSD)
-# if BSD == 43
- printf ("vax-dec-bsd4.3\n"); exit (0);
-# else
-# if BSD == 199006
- printf ("vax-dec-bsd4.3reno\n"); exit (0);
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# endif
-# else
- printf ("vax-dec-bsd\n"); exit (0);
-# endif
-# else
- printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
- printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
- exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
- case `getsysinfo -f cpu_type` in
- c1*)
- echo c1-convex-bsd
- exit 0 ;;
- c2*)
- if getsysinfo -f scalar_acc
- then echo c32-convex-bsd
- else echo c2-convex-bsd
- fi
- exit 0 ;;
- c34*)
- echo c34-convex-bsd
- exit 0 ;;
- c38*)
- echo c38-convex-bsd
- exit 0 ;;
- c4*)
- echo c4-convex-bsd
- exit 0 ;;
- esac
-fi
-
-cat >&2 <<EOF
-$0: unable to guess system type
-
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
-
- ftp://ftp.gnu.org/pub/gnu/config/
-
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
-
-config.guess timestamp = $timestamp
-
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
-/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
-
-hostinfo = `(hostinfo) 2>/dev/null`
-/bin/universe = `(/bin/universe) 2>/dev/null`
-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
-/bin/arch = `(/bin/arch) 2>/dev/null`
-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
-EOF
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/main/editline/config.h.in b/main/editline/config.h.in
deleted file mode 100644
index 151fb226d..000000000
--- a/main/editline/config.h.in
+++ /dev/null
@@ -1,21 +0,0 @@
-#undef SUNOS
-#undef CYGWIN
-
-#undef HAVE_SYS_CDEFS_H
-#undef HAVE_TERMCAP_H
-#undef HAVE_CURSES_H
-#undef HAVE_NCURSES_H
-#undef HAVE_TERM_H
-#undef HAVE_VIS_H
-#undef HAVE_ISSETUGID
-
-#undef HAVE_STRLCAT
-#undef HAVE_STRLCPY
-#undef HAVE_FGETLN
-#undef HAVE_STRVIS
-#undef HAVE_STRUNVIS
-
-#include "sys.h"
-#ifdef CYGWIN
-# include "cygdef.h"
-#endif
diff --git a/main/editline/config.sub b/main/editline/config.sub
deleted file mode 100755
index 838237e98..000000000
--- a/main/editline/config.sub
+++ /dev/null
@@ -1,1412 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
-# Free Software Foundation, Inc.
-
-timestamp='2001-09-14'
-
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine. It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Please send patches to <config-patches@gnu.org>.
-#
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support. The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
- $0 [OPTION] ALIAS
-
-Canonicalize a configuration name.
-
-Operation modes:
- -h, --help print this help, then exit
- -t, --time-stamp print date of last modification, then exit
- -v, --version print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
-Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
- case $1 in
- --time-stamp | --time* | -t )
- echo "$timestamp" ; exit 0 ;;
- --version | -v )
- echo "$version" ; exit 0 ;;
- --help | --h* | -h )
- echo "$usage"; exit 0 ;;
- -- ) # Stop option processing
- shift; break ;;
- - ) # Use stdin as input.
- break ;;
- -* )
- echo "$me: invalid option $1$help"
- exit 1 ;;
-
- *local*)
- # First pass through any local machine types.
- echo $1
- exit 0;;
-
- * )
- break ;;
- esac
-done
-
-case $# in
- 0) echo "$me: missing argument$help" >&2
- exit 1;;
- 1) ;;
- *) echo "$me: too many arguments$help" >&2
- exit 1;;
-esac
-
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
- os=-$maybe_os
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- *)
- basic_machine=`echo $1 | sed 's/-[^-]*$//'`
- if [ $basic_machine != $1 ]
- then os=`echo $1 | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
-
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work. We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
- -sun*os*)
- # Prevent following clause from handling this invalid input.
- ;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis)
- os=
- basic_machine=$1
- ;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
- ;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*)
- os=-lynxos
- ;;
- -ptx*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
- ;;
- -windowsnt*)
- os=`echo $os | sed -e 's/windowsnt/winnt/'`
- ;;
- -psos*)
- os=-psos
- ;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
-esac
-
-# Decode aliases for certain CPU-COMPANY combinations.
-case $basic_machine in
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- 1750a | 580 \
- | a29k \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
- | c4x | clipper \
- | d10v | d30v | dsp16xx \
- | fr30 \
- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | i370 | i860 | i960 | ia64 \
- | m32r | m68000 | m68k | m88k | mcore \
- | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
- | mips64vr4100 | mips64vr4100el | mips64vr4300 \
- | mips64vr4300el | mips64vr5000 | mips64vr5000el \
- | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
- | mipsisa32 \
- | mn10200 | mn10300 \
- | ns16k | ns32k \
- | openrisc \
- | pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
- | pyramid \
- | s390 | s390x \
- | sh | sh[34] | sh[34]eb | shbe | shle \
- | sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \
- | stormy16 | strongarm \
- | tahoe | thumb | tic80 | tron \
- | v850 \
- | we32k \
- | x86 | xscale \
- | z8k)
- basic_machine=$basic_machine-unknown
- ;;
- m6811 | m68hc11 | m6812 | m68hc12)
- # Motorola 68HC11/12.
- basic_machine=$basic_machine-unknown
- os=-none
- ;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
- ;;
-
- # We use `pc' rather than `unknown'
- # because (1) that's what they normally are, and
- # (2) the word "unknown" tends to confuse beginning users.
- i*86 | x86_64)
- basic_machine=$basic_machine-pc
- ;;
- # Object if more than one company name word.
- *-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alphapca5[67]-* | arc-* \
- | arm-* | armbe-* | armle-* | armv*-* \
- | avr-* \
- | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c54x-* \
- | clipper-* | cray2-* | cydra-* \
- | d10v-* | d30v-* \
- | elxsi-* \
- | f30[01]-* | f700-* | fr30-* | fx80-* \
- | h8300-* | h8500-* \
- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
- | i*86-* | i860-* | i960-* | ia64-* \
- | m32r-* \
- | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | mcore-* \
- | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
- | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
- | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
- | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
- | none-* | np1-* | ns16k-* | ns32k-* \
- | orion-* \
- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
- | pyramid-* \
- | romp-* | rs6000-* \
- | s390-* | s390x-* \
- | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \
- | sparc-* | sparc64-* | sparc86x-* | sparclite-* \
- | sparcv9-* | sparcv9b-* | stormy16-* | strongarm-* | sv1-* \
- | t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
- | v850-* | vax-* \
- | we32k-* \
- | x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \
- | ymp-* \
- | z8k-*)
- ;;
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-unknown
- os=-bsd
- ;;
- 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- basic_machine=m68000-att
- ;;
- 3b*)
- basic_machine=we32k-att
- ;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
- alliant | fx80)
- basic_machine=fx80-alliant
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- ;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
- amiga | amiga-*)
- basic_machine=m68k-unknown
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- convex-c1)
- basic_machine=c1-convex
- os=-bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- os=-bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- os=-bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- os=-bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- os=-bsd
- ;;
- cray | ymp)
- basic_machine=ymp-cray
- os=-unicos
- ;;
- cray2)
- basic_machine=cray2-cray
- os=-unicos
- ;;
- [cjt]90)
- basic_machine=${basic_machine}-cray
- os=-unicos
- ;;
- crds | unos)
- basic_machine=m68k-crds
- ;;
- cris | cris-* | etrax*)
- basic_machine=cris-axis
- ;;
- da30 | da30-*)
- basic_machine=m68k-da30
- ;;
- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
- ;;
- delta | 3300 | motorola-3300 | motorola-delta \
- | 3300-motorola | delta-motorola)
- basic_machine=m68k-motorola
- ;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- dpx20 | dpx20-*)
- basic_machine=rs6000-bull
- os=-bosx
- ;;
- dpx2* | dpx2*-bull)
- basic_machine=m68k-bull
- os=-sysv3
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
- ;;
- encore | umax | mmax)
- basic_machine=ns32k-encore
- ;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
- ;;
- fx2800)
- basic_machine=i860-alliant
- ;;
- genix)
- basic_machine=ns32k-ns
- ;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
- ;;
- h3050r* | hiux*)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
- ;;
- hp300-*)
- basic_machine=m68k-hp
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
- ;;
- hp3k9[0-9][0-9] | hp9[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k2[0-9][0-9] | hp9k31[0-9])
- basic_machine=m68000-hp
- ;;
- hp9k3[2-9][0-9])
- basic_machine=m68k-hp
- ;;
- hp9k6[0-9][0-9] | hp6[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hp9k7[0-79][0-9] | hp7[0-79][0-9])
- basic_machine=hppa1.1-hp
- ;;
- hp9k78[0-9] | hp78[0-9])
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
- # FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][13679] | hp8[0-9][13679])
- basic_machine=hppa1.1-hp
- ;;
- hp9k8[0-9][0-9] | hp8[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hppa-next)
- os=-nextstep3
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
- i370-ibm* | ibm*)
- basic_machine=i370-ibm
- ;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
- i*86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv32
- ;;
- i*86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv4
- ;;
- i*86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv
- ;;
- i*86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-solaris2
- ;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
- ;;
- i386-vsta | vsta)
- basic_machine=i386-unknown
- os=-vsta
- ;;
- iris | iris4d)
- basic_machine=mips-sgi
- case $os in
- -irix*)
- ;;
- *)
- os=-irix4
- ;;
- esac
- ;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
- m88k-omron*)
- basic_machine=m88k-omron
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
- ;;
- mingw32)
- basic_machine=i386-pc
- os=-mingw32
- ;;
- miniframe)
- basic_machine=m68000-convergent
- ;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
- mipsel*-linux*)
- basic_machine=mipsel-unknown
- os=-linux-gnu
- ;;
- mips*-linux*)
- basic_machine=mips-unknown
- os=-linux-gnu
- ;;
- mips3*-*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
- ;;
- mips3*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
- ;;
- mmix*)
- basic_machine=mmix-knuth
- os=-mmixware
- ;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
- ;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
- ;;
- news-3600 | risc-news)
- basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
- ;;
- next | m*-next )
- basic_machine=m68k-next
- case $os in
- -nextstep* )
- ;;
- -ns2*)
- os=-nextstep2
- ;;
- *)
- os=-nextstep3
- ;;
- esac
- ;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
- np1)
- basic_machine=np1-gould
- ;;
- nsr-tandem)
- basic_machine=nsr-tandem
- ;;
- op50n-* | op60c-*)
- basic_machine=hppa1.1-oki
- os=-proelf
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
- ;;
- pa-hitachi)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- pbd)
- basic_machine=sparc-tti
- ;;
- pbb)
- basic_machine=m68k-tti
- ;;
- pc532 | pc532-*)
- basic_machine=ns32k-pc532
- ;;
- pentium | p5 | k5 | k6 | nexgen)
- basic_machine=i586-pc
- ;;
- pentiumpro | p6 | 6x86 | athlon)
- basic_machine=i686-pc
- ;;
- pentiumii | pentium2)
- basic_machine=i686-pc
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-*)
- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumii-* | pentium2-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pn)
- basic_machine=pn-gould
- ;;
- power) basic_machine=power-ibm
- ;;
- ppc) basic_machine=powerpc-unknown
- ;;
- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppcle | powerpclittle | ppc-le | powerpc-little)
- basic_machine=powerpcle-unknown
- ;;
- ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64) basic_machine=powerpc64-unknown
- ;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64le | powerpc64little | ppc64-le | powerpc64-little)
- basic_machine=powerpc64le-unknown
- ;;
- ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ps2)
- basic_machine=i386-ibm
- ;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- rm[46]00)
- basic_machine=mips-siemens
- ;;
- rtpc | rtpc-*)
- basic_machine=romp-ibm
- ;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
- ;;
- sequent)
- basic_machine=i386-sequent
- ;;
- sh)
- basic_machine=sh-hitachi
- os=-hms
- ;;
- sparclite-wrs)
- basic_machine=sparclite-wrs
- os=-vxworks
- ;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
- ;;
- spur)
- basic_machine=spur-unknown
- ;;
- st2000)
- basic_machine=m68k-tandem
- ;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
- ;;
- sun2)
- basic_machine=m68000-sun
- ;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
- ;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
- ;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
- ;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
- ;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
- ;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
- ;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
- ;;
- sun3 | sun3-*)
- basic_machine=m68k-sun
- ;;
- sun4)
- basic_machine=sparc-sun
- ;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
- ;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
- ;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
- ;;
- t3e)
- basic_machine=t3e-cray
- os=-unicos
- ;;
- tic54x | c54x*)
- basic_machine=tic54x-unknown
- os=-coff
- ;;
- tx39)
- basic_machine=mipstx39-unknown
- ;;
- tx39el)
- basic_machine=mipstx39el-unknown
- ;;
- tower | tower-32)
- basic_machine=m68k-ncr
- ;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
- ;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
- ;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
- ;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
- ;;
- vms)
- basic_machine=vax-dec
- os=-vms
- ;;
- vpp*|vx|vx-*)
- basic_machine=f301-fujitsu
- ;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
- ;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
- ;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
- ;;
- w65*)
- basic_machine=w65-wdc
- os=-none
- ;;
- w89k-*)
- basic_machine=hppa1.1-winbond
- os=-proelf
- ;;
- windows32)
- basic_machine=i386-pc
- os=-windows32-msvcrt
- ;;
- xmp)
- basic_machine=xmp-cray
- os=-unicos
- ;;
- xps | xps100)
- basic_machine=xps100-honeywell
- ;;
- z8k-*-coff)
- basic_machine=z8k-unknown
- os=-sim
- ;;
- none)
- basic_machine=none-none
- os=-none
- ;;
-
-# Here we handle the default manufacturer of certain CPU types. It is in
-# some cases the only manufacturer, in others, it is the most popular.
- w89k)
- basic_machine=hppa1.1-winbond
- ;;
- op50n)
- basic_machine=hppa1.1-oki
- ;;
- op60c)
- basic_machine=hppa1.1-oki
- ;;
- mips)
- if [ x$os = x-linux-gnu ]; then
- basic_machine=mips-unknown
- else
- basic_machine=mips-mips
- fi
- ;;
- romp)
- basic_machine=romp-ibm
- ;;
- rs6000)
- basic_machine=rs6000-ibm
- ;;
- vax)
- basic_machine=vax-dec
- ;;
- pdp10)
- # there are many clones, so DEC is not a safe bet
- basic_machine=pdp10-unknown
- ;;
- pdp11)
- basic_machine=pdp11-dec
- ;;
- we32k)
- basic_machine=we32k-att
- ;;
- sh3 | sh4 | sh3eb | sh4eb)
- basic_machine=sh-unknown
- ;;
- sparc | sparcv9 | sparcv9b)
- basic_machine=sparc-sun
- ;;
- cydra)
- basic_machine=cydra-cydrome
- ;;
- orion)
- basic_machine=orion-highlevel
- ;;
- orion105)
- basic_machine=clipper-highlevel
- ;;
- mac | mpw | mac-mpw)
- basic_machine=m68k-apple
- ;;
- pmac | pmac-mpw)
- basic_machine=powerpc-apple
- ;;
- c4x*)
- basic_machine=c4x-none
- os=-coff
- ;;
- *-unknown)
- # Make sure to match an already-canonicalized machine name.
- ;;
- *)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
- *-digital*)
- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
- ;;
- *-commodore*)
- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
- ;;
- *)
- ;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if [ x"$os" != x"" ]
-then
-case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
- # -solaris* is a basic system type, with this one exception.
- -solaris1 | -solaris1.*)
- os=`echo $os | sed -e 's|solaris1|sunos4|'`
- ;;
- -solaris)
- os=-solaris2
- ;;
- -svr4*)
- os=-sysv4
- ;;
- -unixware*)
- os=-sysv4.2uw
- ;;
- -gnu/linux*)
- os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
- ;;
- # First accept the basic system types.
- # The portable systems comes first.
- # Each alternative MUST END IN A *, to match a version number.
- # -sysv* is not here because it comes later, after sysvr4.
- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* \
- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
- | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* \
- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
- | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
- | -os2* | -vos*)
- # Remember, each alternative MUST END IN *, to match a version number.
- ;;
- -qnx*)
- case $basic_machine in
- x86-* | i*86-*)
- ;;
- *)
- os=-nto$os
- ;;
- esac
- ;;
- -nto*)
- os=-nto-qnx
- ;;
- -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
- ;;
- -mac*)
- os=`echo $os | sed -e 's|mac|macos|'`
- ;;
- -linux*)
- os=`echo $os | sed -e 's|linux|linux-gnu|'`
- ;;
- -sunos5*)
- os=`echo $os | sed -e 's|sunos5|solaris2|'`
- ;;
- -sunos6*)
- os=`echo $os | sed -e 's|sunos6|solaris3|'`
- ;;
- -opened*)
- os=-openedition
- ;;
- -wince*)
- os=-wince
- ;;
- -osfrose*)
- os=-osfrose
- ;;
- -osf*)
- os=-osf
- ;;
- -utek*)
- os=-bsd
- ;;
- -dynix*)
- os=-bsd
- ;;
- -acis*)
- os=-aos
- ;;
- -386bsd)
- os=-bsd
- ;;
- -ctix* | -uts*)
- os=-sysv
- ;;
- -ns2 )
- os=-nextstep2
- ;;
- -nsk*)
- os=-nsk
- ;;
- # Preserve the version number of sinix5.
- -sinix5.*)
- os=`echo $os | sed -e 's|sinix|sysv|'`
- ;;
- -sinix*)
- os=-sysv4
- ;;
- -triton*)
- os=-sysv3
- ;;
- -oss*)
- os=-sysv3
- ;;
- -svr4)
- os=-sysv4
- ;;
- -svr3)
- os=-sysv3
- ;;
- -sysvr4)
- os=-sysv4
- ;;
- # This must come after -sysvr4.
- -sysv*)
- ;;
- -ose*)
- os=-ose
- ;;
- -es1800*)
- os=-ose
- ;;
- -xenix)
- os=-xenix
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- os=-mint
- ;;
- -none)
- ;;
- *)
- # Get rid of the `-' at the beginning of $os.
- os=`echo $os | sed 's/[^-]*-//'`
- echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
- exit 1
- ;;
-esac
-else
-
-# Here we handle the default operating systems that come with various machines.
-# The value should be what the vendor currently ships out the door with their
-# machine or put another way, the most popular os provided with the machine.
-
-# Note that if you're going to try to match "-MANUFACTURER" here (say,
-# "-sun"), then you have to tell the case statement up towards the top
-# that MANUFACTURER isn't an operating system. Otherwise, code above
-# will signal an error saying that MANUFACTURER isn't an operating
-# system, and we'll never get to this point.
-
-case $basic_machine in
- *-acorn)
- os=-riscix1.2
- ;;
- arm*-rebel)
- os=-linux
- ;;
- arm*-semi)
- os=-aout
- ;;
- pdp10-*)
- os=-tops20
- ;;
- pdp11-*)
- os=-none
- ;;
- *-dec | vax-*)
- os=-ultrix4.2
- ;;
- m68*-apollo)
- os=-domain
- ;;
- i386-sun)
- os=-sunos4.0.2
- ;;
- m68000-sun)
- os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
- ;;
- m68*-cisco)
- os=-aout
- ;;
- mips*-cisco)
- os=-elf
- ;;
- mips*-*)
- os=-elf
- ;;
- *-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
- ;;
- sparc-* | *-sun)
- os=-sunos4.1.1
- ;;
- *-be)
- os=-beos
- ;;
- *-ibm)
- os=-aix
- ;;
- *-wec)
- os=-proelf
- ;;
- *-winbond)
- os=-proelf
- ;;
- *-oki)
- os=-proelf
- ;;
- *-hp)
- os=-hpux
- ;;
- *-hitachi)
- os=-hiux
- ;;
- i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
- ;;
- *-cbm)
- os=-amigaos
- ;;
- *-dg)
- os=-dgux
- ;;
- *-dolphin)
- os=-sysv3
- ;;
- m68k-ccur)
- os=-rtu
- ;;
- m88k-omron*)
- os=-luna
- ;;
- *-next )
- os=-nextstep
- ;;
- *-sequent)
- os=-ptx
- ;;
- *-crds)
- os=-unos
- ;;
- *-ns)
- os=-genix
- ;;
- i370-*)
- os=-mvs
- ;;
- *-next)
- os=-nextstep3
- ;;
- *-gould)
- os=-sysv
- ;;
- *-highlevel)
- os=-bsd
- ;;
- *-encore)
- os=-bsd
- ;;
- *-sgi)
- os=-irix
- ;;
- *-siemens)
- os=-sysv4
- ;;
- *-masscomp)
- os=-rtu
- ;;
- f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
- ;;
- *-rom68k)
- os=-coff
- ;;
- *-*bug)
- os=-coff
- ;;
- *-apple)
- os=-macos
- ;;
- *-atari*)
- os=-mint
- ;;
- *)
- os=-none
- ;;
-esac
-fi
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer. We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
- *-unknown)
- case $os in
- -riscix*)
- vendor=acorn
- ;;
- -sunos*)
- vendor=sun
- ;;
- -aix*)
- vendor=ibm
- ;;
- -beos*)
- vendor=be
- ;;
- -hpux*)
- vendor=hp
- ;;
- -mpeix*)
- vendor=hp
- ;;
- -hiux*)
- vendor=hitachi
- ;;
- -unos*)
- vendor=crds
- ;;
- -dgux*)
- vendor=dg
- ;;
- -luna*)
- vendor=omron
- ;;
- -genix*)
- vendor=ns
- ;;
- -mvs* | -opened*)
- vendor=ibm
- ;;
- -ptx*)
- vendor=sequent
- ;;
- -vxsim* | -vxworks*)
- vendor=wrs
- ;;
- -aux*)
- vendor=apple
- ;;
- -hms*)
- vendor=hitachi
- ;;
- -mpw* | -macos*)
- vendor=apple
- ;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- vendor=atari
- ;;
- -vos*)
- vendor=stratus
- ;;
- esac
- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
- ;;
-esac
-
-echo $basic_machine$os
-exit 0
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/main/editline/configure b/main/editline/configure
deleted file mode 100755
index d570bf679..000000000
--- a/main/editline/configure
+++ /dev/null
@@ -1,2459 +0,0 @@
-#! /bin/sh
-
-# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.13
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
-#
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-
-# Defaults:
-ac_help=
-ac_default_prefix=/usr/local
-# Any additions from configure.in:
-ac_help="$ac_help
- --disable-readline Disable readline compatibility"
-ac_help="$ac_help
- --enable-debug Enable debugging code"
-
-# Initialize some variables set by options.
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
-exec_prefix=NONE
-host=NONE
-no_create=
-nonopt=NONE
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-target=NONE
-verbose=
-x_includes=NONE
-x_libraries=NONE
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
-
-ac_prev=
-for ac_option
-do
-
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval "$ac_prev=\$ac_option"
- ac_prev=
- continue
- fi
-
- case "$ac_option" in
- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) ac_optarg= ;;
- esac
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case "$ac_option" in
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
-
- -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
- | --da=*)
- datadir="$ac_optarg" ;;
-
- -disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- eval "enable_${ac_feature}=no" ;;
-
- -enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "enable_${ac_feature}='$ac_optarg'" ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he)
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
- --cache-file=FILE cache test results in FILE
- --help print this message
- --no-create do not create output files
- --quiet, --silent do not print \`checking...' messages
- --version print the version of autoconf that created configure
-Directory and file names:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
- --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data in DIR
- [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data in DIR
- [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
- --infodir=DIR info documentation in DIR [PREFIX/info]
- --mandir=DIR man documentation in DIR [PREFIX/man]
- --srcdir=DIR find the sources in DIR [configure dir or ..]
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM
- run sed PROGRAM on installed program names
-EOF
- cat << EOF
-Host type:
- --build=BUILD configure for building on BUILD [BUILD=HOST]
- --host=HOST configure for HOST [guessed]
- --target=TARGET configure for TARGET [TARGET=HOST]
-Features and packages:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --x-includes=DIR X include files are in DIR
- --x-libraries=DIR X library files are in DIR
-EOF
- if test -n "$ac_help"; then
- echo "--enable and --with options recognized:$ac_help"
- fi
- exit 0 ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir="$ac_optarg" ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir="$ac_optarg" ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst \
- | --locals | --local | --loca | --loc | --lo)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* \
- | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix="$ac_optarg" ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix="$ac_optarg" ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir="$ac_optarg" ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.13"
- exit 0 ;;
-
- -with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "with_${ac_package}='$ac_optarg'" ;;
-
- -without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- eval "with_${ac_package}=no" ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes="$ac_optarg" ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries="$ac_optarg" ;;
-
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
- ;;
-
- *)
- if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
- echo "configure: warning: $ac_option: invalid host type" 1>&2
- fi
- if test "x$nonopt" != xNONE; then
- { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
- fi
- nonopt="$ac_option"
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
-fi
-exec 5>./config.log
-
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
-
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
-do
- case "$ac_arg" in
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c) ;;
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- *) ac_configure_args="$ac_configure_args $ac_arg" ;;
- esac
-done
-
-# NLS nuisances.
-# Only set these to C if already set. These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
-
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=Makefile.in
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then its parent.
- ac_prog=$0
- ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
- test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
- srcdir=$ac_confdir
- if test ! -r $srcdir/$ac_unique_file; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
- if test "$ac_srcdir_defaulted" = yes; then
- { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
- else
- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
- fi
-fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
-
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
-fi
-for ac_site_file in $CONFIG_SITE; do
- if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
- . "$ac_site_file"
- fi
-done
-
-if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
-else
- echo "creating cache $cache_file"
- > $cache_file
-fi
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-ac_exeext=
-ac_objext=o
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
- fi
-else
- ac_n= ac_c='\c' ac_t=
-fi
-
-
-
-CFLAGS=$CFLAGS
-# Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:534: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="gcc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:564: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_prog_rejected=no
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# -gt 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- set dummy "$ac_dir/$ac_word" "$@"
- shift
- ac_cv_prog_CC="$@"
- fi
-fi
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
- if test -z "$CC"; then
- case "`uname -s`" in
- *win32* | *WIN32*)
- # Extract the first word of "cl", so it can be a program name with args.
-set dummy cl; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:615: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="cl"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
- ;;
- esac
- fi
- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:647: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-cat > conftest.$ac_ext << EOF
-
-#line 658 "configure"
-#include "confdefs.h"
-
-main(){return(0);}
-EOF
-if { (eval echo configure:663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- ac_cv_prog_cc_works=yes
- # If we can't run a trivial program, we are probably using a cross compiler.
- if (./conftest; exit) 2>/dev/null; then
- ac_cv_prog_cc_cross=no
- else
- ac_cv_prog_cc_cross=yes
- fi
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cc_works=no
-fi
-rm -fr conftest*
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
-if test $ac_cv_prog_cc_works = no; then
- { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
-fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:689: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
-echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:694: checking whether we are using GNU C" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
-EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:703: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
-else
- ac_cv_prog_gcc=no
-fi
-fi
-
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
-
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
-else
- GCC=
-fi
-
-ac_test_CFLAGS="${CFLAGS+set}"
-ac_save_CFLAGS="$CFLAGS"
-CFLAGS=
-echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:722: checking whether ${CC-cc} accepts -g" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
- ac_cv_prog_cc_g=yes
-else
- ac_cv_prog_cc_g=no
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-
-if test "x$CFLAGS" = "x" ; then
- no_CFLAGS="yes"
-fi
-if test "x$no_CFLAGS" = "xyes" -a "x$GCC" = "xyes" ; then
- CFLAGS="-Wall -pipe -g3"
-fi
-A_CFLAGS=""
-
-S_CFLAGS="-fPIC -DPIC"
-
-echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:764: checking how to run the C preprocessor" >&5
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
-if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- # This must be in double quotes, not single quotes, because CPP may get
- # substituted into the Makefile and "${CC-cc}" will confuse make.
- CPP="${CC-cc} -E"
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp.
- cat > conftest.$ac_ext <<EOF
-#line 779 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:785: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -E -traditional-cpp"
- cat > conftest.$ac_ext <<EOF
-#line 796 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:802: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -nologo -E"
- cat > conftest.$ac_ext <<EOF
-#line 813 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:819: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP=/lib/cpp
-fi
-rm -f conftest*
-fi
-rm -f conftest*
-fi
-rm -f conftest*
- ac_cv_prog_CPP="$CPP"
-fi
- CPP="$ac_cv_prog_CPP"
-else
- ac_cv_prog_CPP="$CPP"
-fi
-echo "$ac_t""$CPP" 1>&6
-
-for ac_prog in mawk gawk nawk awk
-do
-# Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:848: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$AWK"; then
- ac_cv_prog_AWK="$AWK" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_AWK="$ac_prog"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-AWK="$ac_cv_prog_AWK"
-if test -n "$AWK"; then
- echo "$ac_t""$AWK" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-test -n "$AWK" && break
-done
-
-
-ac_aux_dir=
-for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
- if test -f $ac_dir/install-sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f $ac_dir/install.sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
-fi
-ac_config_guess=$ac_aux_dir/config.guess
-ac_config_sub=$ac_aux_dir/config.sub
-ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
-
-
-# Make sure we can run config.sub.
-if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
-else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:904: checking host system type" >&5
-
-host_alias=$host
-case "$host_alias" in
-NONE)
- case $nonopt in
- NONE)
- if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
- else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
- fi ;;
- *) host_alias=$nonopt ;;
- esac ;;
-esac
-
-host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-echo "$ac_t""$host" 1>&6
-
-case "${host}" in
- *-*-darwin*)
- CFLAGS="$CFLAGS -fno-common -no-cpp-precomp"
- ABI="macho"
- ;;
- *-*-freebsd*)
- ABI="elf"
- ;;
- *-*-linux* | *cygwin*)
- if echo ${host} | grep -q cygwin ; then \
- echo "cygwin detected"; \
- S_CFLAGS=""; \
- echo "/* cygdef.h. Generated automatically by configure. */
-#ifndef _CYGDEF_H_
-#define _CYGDEF_H_ 1
-#include <sys/ioctl.h>
-#define __linux__ 1
-
-
-typedef void (*sig_t)(int);
-
-
-#endif /* _CYGDEF_H_ */" > cygdef.h; \
- echo "
- #define CYGWIN 1
-" > confdefs.h; \
- fi
- ABI="elf"
- ;;
- *-*-netbsd*)
- echo $ac_n "checking ABI""... $ac_c" 1>&6
-echo "configure:955: checking ABI" >&5
- cat > conftest.$ac_ext <<EOF
-#line 957 "configure"
-#include "confdefs.h"
-#ifdef __ELF__
- yes
-#endif
-
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "yes" >/dev/null 2>&1; then
- rm -rf conftest*
- ABI="elf"
-else
- rm -rf conftest*
- ABI="aout"
-fi
-rm -f conftest*
-
- echo "$ac_t""$ABI" 1>&6
- ;;
- *-*-solaris2*)
- ABI="elf"
- cat >> confdefs.h <<\EOF
-#define SUNOS 1
-EOF
-
- ;;
- *)
- echo "$ac_t""Unsupported operating system: ${host}" 1>&6
- ABI="elf"
- ;;
-esac
-
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# ./install, which can be erroneously created by make from ./install.sh.
-echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1001: checking for a BSD compatible install" >&5
-if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
- for ac_dir in $PATH; do
- # Account for people who put trailing slashes in PATH elements.
- case "$ac_dir/" in
- /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- if test -f $ac_dir/$ac_prog; then
- if test $ac_prog = install &&
- grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- else
- ac_cv_path_install="$ac_dir/$ac_prog -c"
- break 2
- fi
- fi
- done
- ;;
- esac
- done
- IFS="$ac_save_IFS"
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL="$ac_cv_path_install"
- else
- # As a last resort, use the slow shell script. We don't cache a
- # path for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the path is relative.
- INSTALL="$ac_install_sh"
- fi
-fi
-echo "$ac_t""$INSTALL" 1>&6
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-# Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1056: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_RANLIB="ranlib"
- break
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
-fi
-fi
-RANLIB="$ac_cv_prog_RANLIB"
-if test -n "$RANLIB"; then
- echo "$ac_t""$RANLIB" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-# Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1086: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- case "$AR" in
- /*)
- ac_cv_path_AR="$AR" # Let the user override the test with a path.
- ;;
- ?:/*)
- ac_cv_path_AR="$AR" # Let the user override the test with a dos path.
- ;;
- *)
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_path_AR="$ac_dir/$ac_word"
- break
- fi
- done
- IFS="$ac_save_ifs"
- ;;
-esac
-fi
-AR="$ac_cv_path_AR"
-if test -n "$AR"; then
- echo "$ac_t""$AR" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-
-echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6
-echo "configure:1120: checking for tgetent in -ltermcap" >&5
-ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ltermcap $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1128 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char tgetent();
-
-int main() {
-tgetent()
-; return 0; }
-EOF
-if { (eval echo configure:1139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo termcap | sed -e 's/[^a-zA-Z0-9_]/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-ltermcap $LIBS"
-
-else
- echo "$ac_t""no" 1>&6
-\
- echo $ac_n "checking for tgetent in -ltinfo""... $ac_c" 1>&6
-echo "configure:1166: checking for tgetent in -ltinfo" >&5
-ac_lib_var=`echo tinfo'_'tgetent | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ltinfo $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1174 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char tgetent();
-
-int main() {
-tgetent()
-; return 0; }
-EOF
-if { (eval echo configure:1185: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo tinfo | sed -e 's/^a-zA-Z0-9_/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-ltinfo $LIBS"
-
-else
- echo "$ac_t""no" 1>&6
-\
- echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6
-echo "configure:1212: checking for tgetent in -lcurses" >&5
-ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lcurses $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1220 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char tgetent();
-
-int main() {
-tgetent()
-; return 0; }
-EOF
-if { (eval echo configure:1231: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo curses | sed -e 's/^a-zA-Z0-9_/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-lcurses $LIBS"
-
-else
- echo "$ac_t""no" 1>&6
-\
- echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6
-echo "configure:1258: checking for tgetent in -lncurses" >&5
-ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lncurses $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1266 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char tgetent();
-
-int main() {
-tgetent()
-; return 0; }
-EOF
-if { (eval echo configure:1277: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo ncurses | sed -e 's/^a-zA-Z0-9_/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-lncurses $LIBS"
-
-else
- echo "$ac_t""no" 1>&6
-\
- { echo "configure: error: termcap support not found" 1>&2; exit 1; }
-fi
-
-fi
-
-fi
-
-fi
-
-
-for ac_hdr in termcap.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1317: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1322 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1327: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-\
- for ac_hdr in term.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1355: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1360 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1365: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-\
- echo "$ac_t""Need term.h since termcap.h is missing" 1>&6
-fi
-done
-
- for ac_hdr in curses.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1397: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1402 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1407: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-\
- for ac_hdr in ncurses.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1435: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1440 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1445: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-\
- echo "$ac_t""Need curses.h or ncurses.h" 1>&6
-fi
-done
-
-fi
-done
-
-fi
-done
-
-
-for ac_hdr in sys/cdefs.h vis.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1484: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1489 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1494: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
-
-for ac_func in issetugid
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1524: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1529 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:1552: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
-for ac_func in strlcat
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1579: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1584 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:1607: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-CCSRCS="$CCSRCS np/strlcat.c"
-fi
-done
-
-for ac_func in strlcpy
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1635: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1640 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:1663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-CCSRCS="$CCSRCS np/strlcpy.c"
-fi
-done
-
-for ac_func in fgetln
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1691: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1696 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:1719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-CCSRCS="$CCSRCS np/fgetln.c"
-fi
-done
-
-for ac_func in strvis
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1747: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1752 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:1775: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-CCSRCS="$CCSRCS np/vis.c"
-fi
-done
-
-for ac_func in strunvis
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1803: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1808 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:1831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-CCSRCS="$CCSRCS np/unvis.c"
-fi
-done
-
-
-cat > conftest.$ac_ext <<EOF
-#line 1858 "configure"
-#include "confdefs.h"
-#include <sys/cdefs.h>
-#ifdef __RCSID
- yes
-#endif
-
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "yes" >/dev/null 2>&1; then
- :
-else
- rm -rf conftest*
- CPPFLAGS="$CPPFLAGS '-D__RCSID(x)='"
-fi
-rm -f conftest*
-
-
-cat > conftest.$ac_ext <<EOF
-#line 1877 "configure"
-#include "confdefs.h"
-#include <sys/cdefs.h>
-#ifdef __COPYRIGHT
- yes
-#endif
-
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "yes" >/dev/null 2>&1; then
- :
-else
- rm -rf conftest*
- CPPFLAGS="$CPPFLAGS '-D__COPYRIGHT(x)='"
-fi
-rm -f conftest*
-
-
-cat > conftest.$ac_ext <<EOF
-#line 1896 "configure"
-#include "confdefs.h"
-#include <sys/cdefs.h>
-#ifdef __RENAME
- yes
-#endif
-
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "yes" >/dev/null 2>&1; then
- :
-else
- rm -rf conftest*
- CPPFLAGS="$CPPFLAGS '-D__RENAME(x)='"
-fi
-rm -f conftest*
-
-
-cat > conftest.$ac_ext <<EOF
-#line 1915 "configure"
-#include "confdefs.h"
-#include <sys/cdefs.h>
-#ifdef _DIAGASSERT
- yes
-#endif
-
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "yes" >/dev/null 2>&1; then
- :
-else
- rm -rf conftest*
- CPPFLAGS="$CPPFLAGS '-D_DIAGASSERT(x)='"
-fi
-rm -f conftest*
-
-
-# Check whether --enable-readline or --disable-readline was given.
-if test "${enable_readline+set}" = set; then
- enableval="$enable_readline"
- if test "x$enable_readline" != "xyes" ; then
- enable_readline="no"
-fi
-
-else
- enable_readline="yes"
-
-fi
-
-
-# Check whether --enable-debug or --disable-debug was given.
-if test "${enable_debug+set}" = set; then
- enableval="$enable_debug"
- if test "x$enable_debug" != "xyes" ; then
- enable_debug="no"
-fi
-
-else
- enable_debug="no"
-
-fi
-
-if test "x$enable_debug" = "xyes" ; then
- CPPFLAGS="$CPPFLAGS -DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG"
- CPPFLAGS="$CPPFLAGS -DDEBUG_REFRESH -DDEBUG_PASTE"
-else
- CFLAGS="$CFLAGS -O"
-fi
-
-
-
-ACSRCS="common.c emacs.c vi.c"
-BCSRCS="chared.c el.c hist.c key.c map.c parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c"
-CCSRCS="$CCSRCS history.c tokenizer.c"
-
-AGCSRCS="fcns.c help.c"
-BGCSRCS="editline.c"
-
-HDRS="chared.h el.h hist.h key.h map.h parse.h prompt.h refresh.h search.h sig.h sys.h term.h tokenizer.h tty.h"
-
-IHDRS="histedit.h"
-
-IHDR_LINKS=
-
-AGHDRS="common.h emacs.h vi.h"
-BGHDRS="fcns.h help.h"
-
-HDR_DIRS="include"
-
-MAN3="editline.3"
-MAN5="editrc.5"
-
-MAN3_LINKS=
-for i in el_init.3 el_end.3 el_reset.3 el_gets.3 el_getc.3 el_push.3 \
- el_parse.3 el_set.3 el_get.3 el_source.3 el_resize.3 el_line.3 \
- el_insertstr.3 el_deletestr.3 history_init.3 history_end.3 \
- history.3 ; do
- MAN3_LINKS="$MAN3_LINKS editline.3 $i"
-done
-
-MAN_DIRS="man/man3 man/man5"
-
-LIB_DIRS="lib"
-LIB_MAJOR="2"
-LIB_MINOR="6"
-LIB_A="libedit.a"
-LIB_A_LINKS=
-
-if test "x$ABI" = "xelf" ; then
- LIB_S="libedit.so.$LIB_MAJOR"
- LIB_S_LINK="libedit.so"
- LIB_S_LINKS="$LIB_S $LIB_S_LINK"
- S_LDFLAGS="-shared"
-elif test "x$ABI" = "xaout" ; then
- LIB_S="libedit.so.$LIB_MAJOR.$LIB_MINOR"
- LIB_S_LINKS=
- S_LDFLAGS="-shared"
-elif test "x$ABI" = "xmacho" ; then
- S_LDFLAGS="-shared"
- LIB_S="libedit.$LIB_MAJOR.dylib"
- LIB_S_LINK="libedit.dylib"
- LIB_S_LINKS="$LIB_S $LIB_S_LINK"
- if test "x$prefix" = "xNONE" ; then
- S_LDFLAGS="-undefined suppress -flat_namespace -dynamiclib -compatibility_version $LIB_MAJOR -current_version $LIB_MAJOR -install_name /usr/local/lib/$LIB_S"
- else
- S_LDFLAGS="-undefined suppress -flat_namespace -dynamiclib -compatibility_version $LIB_MAJOR -current_version $LIB_MAJOR -install_name $prefix/lib/$LIB_S"
- fi
-fi
-
-TEST="TEST/test"
-TCSRCS="TEST/test.c"
-
-if test "x$enable_readline" = "xyes" ; then
- CCSRCS="$CCSRCS readline.c"
- IHDRS="$IHDRS readline/readline.h"
- IHDR_LINKS="readline.h readline/history.h"
- HDR_DIRS="$HDR_DIRS include/readline"
- LIB_A_LINKS="$LIB_A_LINKS libedit.a libreadline.a"
- if test "x$ABI" = "xelf" ; then
- LIB_S_LINKS="$LIB_S_LINKS $LIB_S_LINK libreadline.so"
- elif test "x$ABI" = "xaout" ; then
- LIB_S_LINKS="$LIB_S_LINKS $LIB_S libreadline.so.$LIB_MAJOR.$LIB_MINOR"
- elif test "x$ABI" = "xmacho" ; then
- LIB_S_LINKS="$LIB_S_LINKS $LIB_S_LINK libreadline.dylib"
- fi
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
- if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
- else
- echo "not updating unwritable cache $cache_file"
- fi
-fi
-rm -f confcache
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
-fi
-
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
-
-DEFS=-DHAVE_CONFIG_H
-
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
-
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS <<EOF
-#! /bin/sh
-# Generated automatically by configure.
-# Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# $0 $ac_configure_args
-#
-# Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
-
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
-do
- case "\$ac_option" in
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
- exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
- -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.13"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
- esac
-done
-
-ac_given_srcdir=$srcdir
-ac_given_INSTALL="$INSTALL"
-
-trap 'rm -fr `echo "Makefile makelist config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
-EOF
-cat >> $CONFIG_STATUS <<EOF
-
-# Protect against being on the right side of a sed subst in config.status.
-sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
- s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@SHELL@%$SHELL%g
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@FFLAGS@%$FFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@CC@%$CC%g
-s%@A_CFLAGS@%$A_CFLAGS%g
-s%@S_CFLAGS@%$S_CFLAGS%g
-s%@CPP@%$CPP%g
-s%@AWK@%$AWK%g
-s%@host@%$host%g
-s%@host_alias@%$host_alias%g
-s%@host_cpu@%$host_cpu%g
-s%@host_vendor@%$host_vendor%g
-s%@host_os@%$host_os%g
-s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
-s%@INSTALL_DATA@%$INSTALL_DATA%g
-s%@RANLIB@%$RANLIB%g
-s%@AR@%$AR%g
-s%@ACSRCS@%$ACSRCS%g
-s%@BCSRCS@%$BCSRCS%g
-s%@CCSRCS@%$CCSRCS%g
-s%@AGCSRCS@%$AGCSRCS%g
-s%@BGCSRCS@%$BGCSRCS%g
-s%@HDRS@%$HDRS%g
-s%@IHDRS@%$IHDRS%g
-s%@IHDR_LINKS@%$IHDR_LINKS%g
-s%@AGHDRS@%$AGHDRS%g
-s%@BGHDRS@%$BGHDRS%g
-s%@HDR_DIRS@%$HDR_DIRS%g
-s%@MAN3@%$MAN3%g
-s%@MAN5@%$MAN5%g
-s%@MAN3_LINKS@%$MAN3_LINKS%g
-s%@MAN_DIRS@%$MAN_DIRS%g
-s%@LIB_DIRS@%$LIB_DIRS%g
-s%@LIB_VER@%$LIB_VER%g
-s%@LIB_A@%$LIB_A%g
-s%@LIB_A_LINKS@%$LIB_A_LINKS%g
-s%@LIB_S@%$LIB_S%g
-s%@LIB_S_LINKS@%$LIB_S_LINKS%g
-s%@S_LDFLAGS@%$S_LDFLAGS%g
-s%@TEST@%$TEST%g
-s%@TCSRCS@%$TCSRCS%g
-
-CEOF
-EOF
-
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
- else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
- fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
- else
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f conftest.s$ac_file"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
- fi
- ac_file=`expr $ac_file + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_cmds`
- fi
-done
-if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
-fi
-EOF
-
-cat >> $CONFIG_STATUS <<EOF
-
-CONFIG_FILES=\${CONFIG_FILES-"Makefile makelist"}
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
- esac
-
- # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
-
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
- # A "../" for each directory in $ac_dir_suffix.
- ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
- else
- ac_dir_suffix= ac_dots=
- fi
-
- case "$ac_given_srcdir" in
- .) srcdir=.
- if test -z "$ac_dots"; then top_srcdir=.
- else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
- /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
- *) # Relative path.
- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
- top_srcdir="$ac_dots$ac_given_srcdir" ;;
- esac
-
- case "$ac_given_INSTALL" in
- [/$]*) INSTALL="$ac_given_INSTALL" ;;
- *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
- esac
-
- echo creating "$ac_file"
- rm -f "$ac_file"
- configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
- case "$ac_file" in
- *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
- *) ac_comsub= ;;
- esac
-
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-s%@INSTALL@%$INSTALL%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
-
-# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
-# NAME is the cpp macro being defined and VALUE is the value it is being given.
-#
-# ac_d sets the value in "#define NAME VALUE" lines.
-ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
-ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
-ac_dC='\3'
-ac_dD='%g'
-# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
-ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
-ac_uB='\([ ]\)%\1#\2define\3'
-ac_uC=' '
-ac_uD='\4%g'
-# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
-ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
-ac_eB='$%\1#\2define\3'
-ac_eC=' '
-ac_eD='%g'
-
-if test "${CONFIG_HEADERS+set}" != set; then
-EOF
-cat >> $CONFIG_STATUS <<EOF
- CONFIG_HEADERS="config.h"
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-fi
-for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
- esac
-
- echo creating $ac_file
-
- rm -f conftest.frag conftest.in conftest.out
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- cat $ac_file_inputs > conftest.in
-
-EOF
-
-# Transform confdefs.h into a sed script conftest.vals that substitutes
-# the proper values into config.h.in to produce config.h. And first:
-# Protect against being on the right side of a sed subst in config.status.
-# Protect against being in an unquoted here document in config.status.
-rm -f conftest.vals
-cat > conftest.hdr <<\EOF
-s/[\\&%]/\\&/g
-s%[\\$`]%\\&%g
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
-s%ac_d%ac_u%gp
-s%ac_u%ac_e%gp
-EOF
-sed -n -f conftest.hdr confdefs.h > conftest.vals
-rm -f conftest.hdr
-
-# This sed command replaces #undef with comments. This is necessary, for
-# example, in the case of _POSIX_SOURCE, which is predefined and required
-# on some systems where configure will not decide to define it.
-cat >> conftest.vals <<\EOF
-s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
-EOF
-
-# Break up conftest.vals because some shells have a limit on
-# the size of here documents, and old seds have small limits too.
-
-rm -f conftest.tail
-while :
-do
- ac_lines=`grep -c . conftest.vals`
- # grep -c gives empty output for an empty file on some AIX systems.
- if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
- # Write a limited-size here document to conftest.frag.
- echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
- sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
- echo 'CEOF
- sed -f conftest.frag conftest.in > conftest.out
- rm -f conftest.in
- mv conftest.out conftest.in
-' >> $CONFIG_STATUS
- sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
- rm -f conftest.vals
- mv conftest.tail conftest.vals
-done
-rm -f conftest.vals
-
-cat >> $CONFIG_STATUS <<\EOF
- rm -f conftest.frag conftest.h
- echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
- cat conftest.in >> conftest.h
- rm -f conftest.in
- if cmp -s $ac_file conftest.h 2>/dev/null; then
- echo "$ac_file is unchanged"
- rm -f conftest.h
- else
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- fi
- rm -f $ac_file
- mv conftest.h $ac_file
- fi
-fi; done
-
-EOF
-cat >> $CONFIG_STATUS <<EOF
-
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-
-exit 0
-EOF
-chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
-
-
diff --git a/main/editline/configure.in b/main/editline/configure.in
deleted file mode 100644
index c1f87b842..000000000
--- a/main/editline/configure.in
+++ /dev/null
@@ -1,278 +0,0 @@
-dnl
-dnl Process this file with autoconf to produce a configure script.
-dnl
-AC_INIT(Makefile.in)
-
-dnl If CFLAGS isn't defined and using gcc, set CFLAGS to something reasonable.
-dnl Otherwise, just prevent autoconf from molesting CFLAGS.
-CFLAGS=$CFLAGS
-AC_PROG_CC
-if test "x$CFLAGS" = "x" ; then
- no_CFLAGS="yes"
-fi
-if test "x$no_CFLAGS" = "xyes" -a "x$GCC" = "xyes" ; then
- CFLAGS="-Wall -pipe -g3"
-fi
-A_CFLAGS=""
-AC_SUBST(A_CFLAGS)
-S_CFLAGS="-fPIC -DPIC"
-AC_SUBST(S_CFLAGS)
-AC_PROG_CPP
-AC_PROG_AWK
-
-dnl Platform-specific settings. The ABI can probably be determined
-dnl programmatically, but doing so is error-prone, which makes it generally
-dnl not worth the trouble.
-AC_CANONICAL_HOST
-case "${host}" in
- *-*-darwin*)
- CFLAGS="$CFLAGS -fno-common -no-cpp-precomp"
- ABI="macho"
- ;;
- *-*-freebsd*)
- ABI="elf"
- ;;
- *-*-linux* | *cygwin*)
- if echo ${host} | grep -q cygwin ; then \
- echo "cygwin detected"; \
- S_CFLAGS=""; \
- echo "/* cygdef.h. Generated automatically by configure. */
-#ifndef _CYGDEF_H_
-#define _CYGDEF_H_ 1
-#include <sys/ioctl.h>
-#define __linux__ 1
-
-
-typedef void (*sig_t)(int);
-
-
-#endif /* _CYGDEF_H_ */" > cygdef.h; \
- echo "
- #define CYGWIN 1
-" > confdefs.h; \
- fi
- ABI="elf"
- ;;
- *-*-netbsd*)
- AC_MSG_CHECKING(ABI)
- AC_EGREP_CPP(yes,
-[#ifdef __ELF__
- yes
-#endif
-],
- ABI="elf",
- ABI="aout")
- AC_MSG_RESULT($ABI)
- ;;
- *-*-solaris2*)
- ABI="elf"
- AC_DEFINE(SUNOS)
- ;;
- *)
- AC_MSG_RESULT(Unsupported operating system: ${host})
- ABI="elf"
- ;;
-esac
-
-AC_PROG_INSTALL
-AC_PROG_RANLIB
-AC_PATH_PROG(AR, ar, , $PATH)
-
-dnl Search for termcap access routines in termcap, tinfo, curses, and ncurses.
-AC_CHECK_LIB(termcap, tgetent, , \
- AC_CHECK_LIB(tinfo, tgetent, , \
- AC_CHECK_LIB(curses, tgetent, , \
- AC_CHECK_LIB(ncurses, tgetent, , \
- AC_MSG_ERROR(termcap support not found)))))
-
-dnl Use termcap.h if it exists; otherwise we need both term.h and [n]curses.h.
-AC_CHECK_HEADERS(termcap.h, , \
- AC_CHECK_HEADERS(term.h, , \
- AC_MSG_RESULT(Need term.h since termcap.h is missing))
- AC_CHECK_HEADERS(curses.h, , \
- AC_CHECK_HEADERS(ncurses.h, , \
- AC_MSG_RESULT(Need curses.h or ncurses.h))))
-
-AC_CHECK_HEADERS(sys/cdefs.h vis.h)
-
-AC_CHECK_FUNCS(issetugid)
-AC_CHECK_FUNCS(strlcat, , CCSRCS="$CCSRCS np/strlcat.c")
-AC_CHECK_FUNCS(strlcpy, , CCSRCS="$CCSRCS np/strlcpy.c")
-AC_CHECK_FUNCS(fgetln, , CCSRCS="$CCSRCS np/fgetln.c")
-AC_CHECK_FUNCS(strvis, , CCSRCS="$CCSRCS np/vis.c")
-AC_CHECK_FUNCS(strunvis, , CCSRCS="$CCSRCS np/unvis.c")
-
-AC_EGREP_CPP(yes,
-[#include <sys/cdefs.h>
-#ifdef __RCSID
- yes
-#endif
-], , [CPPFLAGS="$CPPFLAGS '-D__RCSID(x)='"])
-
-AC_EGREP_CPP(yes,
-[#include <sys/cdefs.h>
-#ifdef __COPYRIGHT
- yes
-#endif
-], , [CPPFLAGS="$CPPFLAGS '-D__COPYRIGHT(x)='"])
-
-AC_EGREP_CPP(yes,
-[#include <sys/cdefs.h>
-#ifdef __RENAME
- yes
-#endif
-], , [CPPFLAGS="$CPPFLAGS '-D__RENAME(x)='"])
-
-AC_EGREP_CPP(yes,
-[#include <sys/cdefs.h>
-#ifdef _DIAGASSERT
- yes
-#endif
-], , [CPPFLAGS="$CPPFLAGS '-D_DIAGASSERT(x)='"])
-
-dnl Enable readline compatibility by default.
-AC_ARG_ENABLE(readline, [ --disable-readline Disable readline compatibility],
-if test "x$enable_readline" != "xyes" ; then
- enable_readline="no"
-fi
-,
-enable_readline="yes"
-)
-
-dnl Optionally enable debugging.
-AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging code],
-if test "x$enable_debug" != "xyes" ; then
- enable_debug="no"
-fi
-,
-enable_debug="no"
-)
-if test "x$enable_debug" = "xyes" ; then
- CPPFLAGS="$CPPFLAGS -DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG"
- CPPFLAGS="$CPPFLAGS -DDEBUG_REFRESH -DDEBUG_PASTE"
-else
- CFLAGS="$CFLAGS -O"
-fi
-
-
-dnl
-dnl File lists. This is done here instead of in the Makefile in order to avoid
-dnl the need for conditionals.
-dnl
-
-dnl .c files.
-ACSRCS="common.c emacs.c vi.c"
-BCSRCS="chared.c el.c hist.c key.c map.c parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c"
-CCSRCS="$CCSRCS history.c tokenizer.c"
-
-dnl Generated .c files.
-AGCSRCS="fcns.c help.c"
-BGCSRCS="editline.c"
-
-dnl .h files.
-HDRS="chared.h el.h hist.h key.h map.h parse.h prompt.h refresh.h search.h sig.h sys.h term.h tokenizer.h tty.h"
-
-dnl Installed .h files.
-IHDRS="histedit.h"
-
-dnl Installed headers for readline compatibility.
-IHDR_LINKS=
-
-dnl Generated .h files.
-AGHDRS="common.h emacs.h vi.h"
-BGHDRS="fcns.h help.h"
-
-dnl Header installation directories.
-HDR_DIRS="include"
-
-dnl Man pages.
-MAN3="editline.3"
-MAN5="editrc.5"
-
-MAN3_LINKS=
-for i in el_init.3 el_end.3 el_reset.3 el_gets.3 el_getc.3 el_push.3 \
- el_parse.3 el_set.3 el_get.3 el_source.3 el_resize.3 el_line.3 \
- el_insertstr.3 el_deletestr.3 history_init.3 history_end.3 \
- history.3 ; do
- MAN3_LINKS="$MAN3_LINKS editline.3 $i"
-done
-
-dnl Man page installation directories.
-MAN_DIRS="man/man3 man/man5"
-
-dnl Library settings.
-LIB_DIRS="lib"
-LIB_MAJOR="2"
-LIB_MINOR="6"
-LIB_A="libedit.a"
-LIB_A_LINKS=
-
-if test "x$ABI" = "xelf" ; then
- LIB_S="libedit.so.$LIB_MAJOR"
- LIB_S_LINK="libedit.so"
- LIB_S_LINKS="$LIB_S $LIB_S_LINK"
- S_LDFLAGS="-shared"
-elif test "x$ABI" = "xaout" ; then
- LIB_S="libedit.so.$LIB_MAJOR.$LIB_MINOR"
- LIB_S_LINKS=
- S_LDFLAGS="-shared"
-elif test "x$ABI" = "xmacho" ; then
- S_LDFLAGS="-shared"
- LIB_S="libedit.$LIB_MAJOR.dylib"
- LIB_S_LINK="libedit.dylib"
- LIB_S_LINKS="$LIB_S $LIB_S_LINK"
- if test "x$prefix" = "xNONE" ; then
- S_LDFLAGS="-undefined suppress -flat_namespace -dynamiclib -compatibility_version $LIB_MAJOR -current_version $LIB_MAJOR -install_name /usr/local/lib/$LIB_S"
- else
- S_LDFLAGS="-undefined suppress -flat_namespace -dynamiclib -compatibility_version $LIB_MAJOR -current_version $LIB_MAJOR -install_name $prefix/lib/$LIB_S"
- fi
-fi
-
-dnl Test program.
-TEST="TEST/test"
-TCSRCS="TEST/test.c"
-
-dnl Add files to the lists if readline compatibility is enabled.
-if test "x$enable_readline" = "xyes" ; then
- CCSRCS="$CCSRCS readline.c"
- IHDRS="$IHDRS readline/readline.h"
- IHDR_LINKS="readline.h readline/history.h"
- HDR_DIRS="$HDR_DIRS include/readline"
- LIB_A_LINKS="$LIB_A_LINKS libedit.a libreadline.a"
- if test "x$ABI" = "xelf" ; then
- LIB_S_LINKS="$LIB_S_LINKS $LIB_S_LINK libreadline.so"
- elif test "x$ABI" = "xaout" ; then
- LIB_S_LINKS="$LIB_S_LINKS $LIB_S libreadline.so.$LIB_MAJOR.$LIB_MINOR"
- elif test "x$ABI" = "xmacho" ; then
- LIB_S_LINKS="$LIB_S_LINKS $LIB_S_LINK libreadline.dylib"
- fi
-fi
-
-AC_SUBST(ACSRCS)
-AC_SUBST(BCSRCS)
-AC_SUBST(CCSRCS)
-AC_SUBST(AGCSRCS)
-AC_SUBST(BGCSRCS)
-AC_SUBST(HDRS)
-AC_SUBST(IHDRS)
-AC_SUBST(IHDR_LINKS)
-AC_SUBST(AGHDRS)
-AC_SUBST(BGHDRS)
-AC_SUBST(HDR_DIRS)
-AC_SUBST(MAN3)
-AC_SUBST(MAN5)
-AC_SUBST(MAN3_LINKS)
-AC_SUBST(MAN_DIRS)
-AC_SUBST(LIB_DIRS)
-AC_SUBST(LIB_VER)
-AC_SUBST(LIB_A)
-AC_SUBST(LIB_A_LINKS)
-AC_SUBST(LIB_S)
-AC_SUBST(LIB_S_LINKS)
-AC_SUBST(S_LDFLAGS)
-AC_SUBST(TEST)
-AC_SUBST(TCSRCS)
-
-AC_CONFIG_HEADER(config.h)
-AC_OUTPUT([Makefile makelist])
-
diff --git a/main/editline/editline.3 b/main/editline/editline.3
deleted file mode 100644
index 28f6ddb84..000000000
--- a/main/editline/editline.3
+++ /dev/null
@@ -1,646 +0,0 @@
-.\" $NetBSD: editline.3,v 1.25 2002/01/15 02:46:22 wiz Exp $
-.\"
-.\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc.
-.\" All rights reserved.
-.\"
-.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the NetBSD
-.\" Foundation, Inc. and its contributors.
-.\" 4. Neither the name of The NetBSD Foundation nor the names of its
-.\" contributors may be used to endorse or promote products derived
-.\" from this software without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-.\" POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd November 12, 1999
-.Os
-.Dt EDITLINE 3
-.Sh NAME
-.Nm editline ,
-.Nm el_init ,
-.Nm el_end ,
-.Nm el_reset ,
-.Nm el_gets ,
-.Nm el_getc ,
-.Nm el_push ,
-.Nm el_parse ,
-.Nm el_set ,
-.Nm el_source ,
-.Nm el_resize ,
-.Nm el_line ,
-.Nm el_insertstr ,
-.Nm el_deletestr ,
-.Nm history_init ,
-.Nm history_end ,
-.Nm history
-.Nd line editor and history functions
-.Sh LIBRARY
-.Lb libedit
-.Sh SYNOPSIS
-.Fd #include <histedit.h>
-.Ft EditLine *
-.Fn el_init "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr"
-.Ft void
-.Fn el_end "EditLine *e"
-.Ft void
-.Fn el_reset "EditLine *e"
-.Ft const char *
-.Fn el_gets "EditLine *e" "int *count"
-.Ft int
-.Fn el_getc "EditLine *e" "char *ch"
-.Ft void
-.Fn el_push "EditLine *e" "const char *str"
-.Ft int
-.Fn el_parse "EditLine *e" "int argc" "char *argv[]"
-.Ft int
-.Fn el_set "EditLine *e" "int op" "..."
-.Ft int
-.Fn el_get "EditLine *e" "int op" "void *result"
-.Ft int
-.Fn el_source "EditLine *e" "const char *file"
-.Ft void
-.Fn el_resize "EditLine *e"
-.Ft const LineInfo *
-.Fn el_line "EditLine *e"
-.Ft int
-.Fn el_insertstr "EditLine *e" "const char *str"
-.Ft void
-.Fn el_deletestr "EditLine *e" "int count"
-.Ft History *
-.Fn history_init
-.Ft void
-.Fn history_end "History *h"
-.Ft int
-.Fn history "History *h" "HistEvent *ev" "int op" "..."
-.Sh DESCRIPTION
-The
-.Nm
-library provides generic line editing and history functions,
-similar to those found in
-.Xr sh 1 .
-.Pp
-These functions are available in the
-.Nm libedit
-library (which needs the
-.Nm libtermcap
-library).
-Programs should be linked with
-.Fl ledit ltermcap .
-.Sh LINE EDITING FUNCTIONS
-The line editing functions use a common data structure,
-.Fa EditLine ,
-which is created by
-.Fn el_init
-and freed by
-.Fn el_end .
-.Pp
-The following functions are available:
-.Bl -tag -width 4n
-.It Fn el_init
-Initialise the line editor, and return a data structure
-to be used by all other line editing functions.
-.Fa prog
-is the name of the invoking program, used when reading the
-.Xr editrc 5
-file to determine which settings to use.
-.Fa fin ,
-.Fa fout
-and
-.Fa ferr
-are the input, output, and error streams (respectively) to use.
-In this documentation, references to
-.Dq the tty
-are actually to this input/output stream combination.
-.It Fn el_end
-Clean up and finish with
-.Fa e ,
-assumed to have been created with
-.Fn el_init .
-.It Fn el_reset
-Reset the tty and the parser.
-This should be called after an error which may have upset the tty's
-state.
-.It Fn el_gets
-Read a line from the tty.
-.Fa count
-is modified to contain the number of characters read.
-Returns the line read if successful, or
-.Dv NULL
-if no characters were read or if an error occurred.
-.It Fn el_getc
-Read a character from the tty.
-.Fa ch
-is modified to contain the character read.
-Returns the number of characters read if successful, -1 otherwise.
-.It Fn el_push
-Pushes
-.Fa str
-back onto the input stream.
-This is used by the macro expansion mechanism.
-Refer to the description of
-.Ic bind
-.Fl s
-in
-.Xr editrc 5
-for more information.
-.It Fn el_parse
-Parses the
-.Fa argv
-array (which is
-.Fa argc
-elements in size)
-to execute builtin
-.Nm
-commands.
-If the command is prefixed with
-.Dq prog :
-then
-.Fn el_parse
-will only execute the command if
-.Dq prog
-matches the
-.Fa prog
-argument supplied to
-.Fn el_init .
-The return value is
--1 if the command is unknown,
-0 if there was no error or
-.Dq prog
-didn't match, or
-1 if the command returned an error.
-Refer to
-.Xr editrc 5
-for more information.
-.It Fn el_set
-Set
-.Nm
-parameters.
-.Fa op
-determines which parameter to set, and each operation has its
-own parameter list.
-.Pp
-The following values for
-.Fa op
-are supported, along with the required argument list:
-.Bl -tag -width 4n
-.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
-Define prompt printing function as
-.Fa f ,
-which is to return a string that contains the prompt.
-.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)"
-Define right side prompt printing function as
-.Fa f ,
-which is to return a string that contains the prompt.
-.It Dv EL_TERMINAL , Fa "const char *type"
-Define terminal type of the tty to be
-.Fa type ,
-or to
-.Ev TERM
-if
-.Fa type
-is
-.Dv NULL .
-.It Dv EL_EDITOR , Fa "const char *mode"
-Set editing mode to
-.Fa mode ,
-which must be one of
-.Dq emacs
-or
-.Dq vi .
-.It Dv EL_SIGNAL , Fa "int flag"
-If
-.Fa flag
-is non-zero,
-.Nm
-will install its own signal handler for the following signals when
-reading command input:
-.Dv SIGCONT ,
-.Dv SIGHUP ,
-.Dv SIGINT ,
-.Dv SIGQUIT ,
-.Dv SIGSTOP ,
-.Dv SIGTERM ,
-.Dv SIGTSTP ,
-and
-.Dv SIGWINCH .
-Otherwise, the current signal handlers will be used.
-.It Dv EL_BIND , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
-Perform the
-.Ic bind
-builtin command.
-Refer to
-.Xr editrc 5
-for more information.
-.It Dv EL_ECHOTC , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
-Perform the
-.Ic echotc
-builtin command.
-Refer to
-.Xr editrc 5
-for more information.
-.It Dv EL_SETTC , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
-Perform the
-.Ic settc
-builtin command.
-Refer to
-.Xr editrc 5
-for more information.
-.It Dv EL_SETTY , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
-Perform the
-.Ic setty
-builtin command.
-Refer to
-.Xr editrc 5
-for more information.
-.It Dv EL_TELLTC , Xo
-.Fa "const char *" ,
-.Fa "..." ,
-.Dv NULL
-.Xc
-Perform the
-.Ic telltc
-builtin command.
-Refer to
-.Xr editrc 5
-for more information.
-.It Dv EL_ADDFN , Xo
-.Fa "const char *name" ,
-.Fa "const char *help" ,
-.Fa "unsigned char (*func)(EditLine *e, int ch)
-.Xc
-Add a user defined function,
-.Fn func ,
-referred to as
-.Fa name
-which is invoked when a key which is bound to
-.Fa name
-is entered.
-.Fa help
-is a description of
-.Fa name .
-At invocation time,
-.Fa ch
-is the key which caused the invocation.
-The return value of
-.Fn func
-should be one of:
-.Bl -tag -width "CC_REDISPLAY"
-.It Dv CC_NORM
-Add a normal character.
-.It Dv CC_NEWLINE
-End of line was entered.
-.It Dv CC_EOF
-EOF was entered.
-.It Dv CC_ARGHACK
-Expecting further command input as arguments, do nothing visually.
-.It Dv CC_REFRESH
-Refresh display.
-.It Dv CC_REFRESH_BEEP
-Refresh display, and beep.
-.It Dv CC_CURSOR
-Cursor moved, so update and perform
-.Dv CC_REFRESH .
-.It Dv CC_REDISPLAY
-Redisplay entire input line.
-This is useful if a key binding outputs extra information.
-.It Dv CC_ERROR
-An error occurred.
-Beep, and flush tty.
-.It Dv CC_FATAL
-Fatal error, reset tty to known state.
-.El
-.It Dv EL_HIST , Xo
-.Fa "History *(*func)(History *, int op, ...)" ,
-.Fa "const char *ptr"
-.Xc
-Defines which history function to use, which is usually
-.Fn history .
-.Fa ptr
-should be the value returned by
-.Fn history_init .
-.It Dv EL_EDITMODE , Fa "int flag"
-If
-.Fa flag
-is non-zero,
-editing is enabled (the default).
-Note that this is only an indication, and does not
-affect the operation of
-.Nm "" .
-At this time, it is the caller's responsibility to
-check this
-(using
-.Fn el_get )
-to determine if editing should be enabled or not.
-.It Dv EL_GETCFN , Fa "int (*f)(EditLine *, char *c)"
-Define the character reading function as
-.Fa f ,
-which is to return the number of characters read and store them in
-.Fa c .
-This function is called internally by
-.Fn el_gets
-and
-.Fn el_getc .
-The builtin function can be set or restored with the special function
-name ``EL_BUILTIN_GETCFN''.
-.It Dv EL_CLIENTDATA , Fa "void *data"
-Register
-.Fa data
-to be associated with this EditLine structure. It can be retrieved with
-the corresponding
-.Fn el_get
-call.
-.El
-.It Fn el_get
-Get
-.Nm
-parameters.
-.Fa op
-determines which parameter to retrieve into
-.Fa result .
-.Pp
-The following values for
-.Fa op
-are supported, along with actual type of
-.Fa result :
-.Bl -tag -width 4n
-.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
-Return a pointer to the function that displays the prompt.
-.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)"
-Return a pointer to the function that displays the rightside prompt.
-.It Dv EL_EDITOR , Fa "const char *"
-Return the name of the editor, which will be one of
-.Dq emacs
-or
-.Dq vi .
-.It Dv EL_SIGNAL , Fa "int *"
-Return non-zero if
-.Nm
-has installed private signal handlers (see
-.Fn el_get
-above).
-.It Dv EL_EDITMODE, Fa "int *"
-Return non-zero if editing is enabled.
-.It Dv EL_GETCFN, Fa "int (**f)(EditLine *, char *)"
-Return a pointer to the function that read characters, which is equal to
-``EL_BUILTIN_GETCFN'' in the case of the default builtin function.
-.It Dv EL_CLIENTDATA , Fa "void **data"
-Retrieve
-.Fa data
-previously registered with the corresponding
-.Fn el_set
-call.
-.El
-.It Fn el_source
-Initialise
-.Nm
-by reading the contents of
-.Fa file .
-.Fn el_parse
-is called for each line in
-.Fa file .
-If
-.Fa file
-is
-.Dv NULL ,
-try
-.Pa $PWD/.editrc
-then
-.Pa $HOME/.editrc .
-Refer to
-.Xr editrc 5
-for details on the format of
-.Fa file .
-.It Fn el_resize
-Must be called if the terminal size changes.
-If
-.Dv EL_SIGNAL
-has been set with
-.Fn el_set ,
-then this is done automatically.
-Otherwise, it's the responsibility of the application to call
-.Fn el_resize
-on the appropriate occasions.
-.It Fn el_line
-Return the editing information for the current line in a
-.Fa LineInfo
-structure, which is defined as follows:
-.Bd -literal
-typedef struct lineinfo {
- const char *buffer; /* address of buffer */
- const char *cursor; /* address of cursor */
- const char *lastchar; /* address of last character */
-} LineInfo;
-.Ed
-.It Fn el_insertstr
-Insert
-.Fa str
-into the line at the cursor.
-Returns -1 if
-.Fa str
-is empty or won't fit, and 0 otherwise.
-.It Fn el_deletestr
-Delete
-.Fa num
-characters before the cursor.
-.El
-.Sh HISTORY LIST FUNCTIONS
-The history functions use a common data structure,
-.Fa History ,
-which is created by
-.Fn history_init
-and freed by
-.Fn history_end .
-.Pp
-The following functions are available:
-.Bl -tag -width 4n
-.It Fn history_init
-Initialise the history list, and return a data structure
-to be used by all other history list functions.
-.It Fn history_end
-Clean up and finish with
-.Fa h ,
-assumed to have been created with
-.Fn history_init .
-.It Fn history
-Perform operation
-.Fa op
-on the history list, with optional arguments as needed by the
-operation.
-.Fa ev
-is changed accordingly to operation.
-The following values for
-.Fa op
-are supported, along with the required argument list:
-.Bl -tag -width 4n
-.It Dv H_SETSIZE , Fa "int size"
-Set size of history to
-.Fa size
-elements.
-.It Dv H_GETSIZE
-Get number of events currently in history.
-.It Dv H_END
-Cleans up and finishes with
-.Fa h ,
-assumed to be created with
-.Fn history_init .
-.It Dv H_CLEAR
-Clear the history.
-.It Dv H_FUNC , Xo
-.Fa "void *ptr" ,
-.Fa "history_gfun_t first" ,
-.Fa "history_gfun_t next" ,
-.Fa "history_gfun_t last" ,
-.Fa "history_gfun_t prev" ,
-.Fa "history_gfun_t curr" ,
-.Fa "history_sfun_t set" ,
-.Fa "history_vfun_t clear" ,
-.Fa "history_efun_t enter" ,
-.Fa "history_efun_t add"
-.Xc
-Define functions to perform various history operations.
-.Fa ptr
-is the argument given to a function when it's invoked.
-.It Dv H_FIRST
-Return the first element in the history.
-.It Dv H_LAST
-Return the last element in the history.
-.It Dv H_PREV
-Return the previous element in the history.
-.It Dv H_NEXT
-Return the next element in the history.
-.It Dv H_CURR
-Return the current element in the history.
-.It Dv H_SET
-Set the cursor to point to the requested element.
-.It Dv H_ADD , Fa "const char *str"
-Append
-.Fa str
-to the current element of the history, or create an element with
-.It Dv H_APPEND , Fa "const char *str"
-Append
-.Fa str
-to the last new element of the history.
-.It Dv H_ENTER , Fa "const char *str"
-Add
-.Fa str
-as a new element to the history, and, if necessary,
-removing the oldest entry to keep the list to the created size.
-.It Dv H_PREV_STR , Fa "const char *str"
-Return the closest previous event that starts with
-.Fa str .
-.It Dv H_NEXT_STR , Fa "const char *str"
-Return the closest next event that starts with
-.Fa str .
-.It Dv H_PREV_EVENT , Fa "int e"
-Return the previous event numbered
-.Fa e .
-.It Dv H_NEXT_EVENT , Fa "int e"
-Return the next event numbered
-.Fa e .
-.It Dv H_LOAD , Fa "const char *file"
-Load the history list stored in
-.Fa file .
-.It Dv H_SAVE , Fa "const char *file"
-Save the history list to
-.Fa file .
-.El
-.Pp
-.Fn history
-returns 0 if the operation
-.Fa op
-succeeds. Otherwise, -1 is returned and
-.Fa ev
-is updated to contain more details about the error.
-.El
-.\"XXX.Sh EXAMPLES
-.\"XXX: provide some examples
-.Sh SEE ALSO
-.Xr sh 1 ,
-.Xr signal 3 ,
-.Xr termcap 3 ,
-.Xr editrc 5
-.Sh HISTORY
-The
-.Nm
-library first appeared in
-.Bx 4.4 .
-.Dv CC_REDISPLAY
-appeared in
-.Nx 1.3 .
-.Dv CC_REFRESH_BEEP ,
-.Dv EL_EDITMODE
-and the readline emulation appeared in
-.Nx 1.4 .
-.Dv EL_RPROMPT
-appeared in
-.Nx 1.5 .
-.Sh AUTHORS
-The
-.Nm
-library was written by Christos Zoulas.
-Luke Mewburn wrote this manual and implemented
-.Dv CC_REDISPLAY ,
-.Dv CC_REFRESH_BEEP ,
-.Dv EL_EDITMODE ,
-and
-.Dv EL_RPROMPT .
-Jaromir Dolecek implemented the readline emulation.
-.Sh BUGS
-The tokenization functions are not publicly defined in
-.Fd <histedit.h> .
-.Pp
-At this time, it is the responsibility of the caller to
-check the result of the
-.Dv EL_EDITMODE
-operation of
-.Fn el_get
-(after an
-.Fn el_source
-or
-.Fn el_parse )
-to determine if
-.Nm
-should be used for further input.
-I.e.,
-.Dv EL_EDITMODE
-is purely an indication of the result of the most recent
-.Xr editrc 5
-.Ic edit
-command.
diff --git a/main/editline/editrc.5 b/main/editline/editrc.5
deleted file mode 100644
index ddd12897b..000000000
--- a/main/editline/editrc.5
+++ /dev/null
@@ -1,491 +0,0 @@
-.\" $NetBSD: editrc.5,v 1.12 2002/01/15 02:46:44 wiz Exp $
-.\"
-.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
-.\" All rights reserved.
-.\"
-.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the NetBSD
-.\" Foundation, Inc. and its contributors.
-.\" 4. Neither the name of The NetBSD Foundation nor the names of its
-.\" contributors may be used to endorse or promote products derived
-.\" from this software without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-.\" POSSIBILITY OF SUCH DAMAGE.
-.\"
-.Dd November 8, 2000
-.Os
-.Dt EDITRC 5
-.Sh NAME
-.Nm editrc
-.Nd configuration file for editline library
-.Sh SYNOPSIS
-.Nm
-.Sh DESCRIPTION
-The
-.Nm
-file defines various settings to be used by the
-.Xr editline 3
-library.
-.Pp
-The format of each line is:
-.Dl [prog:]command [arg [...]]
-.Pp
-.Ar command
-is one of the
-.Xr editline 3
-builtin commands.
-Refer to
-.Sx BUILTIN COMMANDS
-for more information.
-.Pp
-.Ar prog
-is the program name string that a program defines when it calls
-.Xr el_init 3
-to setup
-.Xr editline 3 ,
-which is usually
-.Va argv[0] .
-.Ar command
-will be executed for any program which matches
-.Ar prog .
-.Pp
-.Ar prog
-may also be a
-.Xr regex 3
-style
-regular expression, in which case
-.Ar command
-will be executed for any program that matches the regular expression.
-.Pp
-If
-.Ar prog
-is absent,
-.Ar command
-is executed for all programs.
-.Sh BUILTIN COMMANDS
-The
-.Nm editline
-library has some builtin commands, which affect the way
-that the line editing and history functions operate.
-These are based on similar named builtins present in the
-.Xr tcsh 1
-shell.
-.Pp
-The following builtin commands are available:
-.Bl -tag -width 4n
-.It Ic bind Xo
-.Op Fl a
-.Op Fl e
-.Op Fl k
-.Op Fl l
-.Op Fl r
-.Op Fl s
-.Op Fl v
-.Op Ar key Op Ar command
-.Xc
-Without options, list all bound keys, and the editor command to which
-each is bound.
-If
-.Ar key
-is supplied, show the bindings for
-.Ar key .
-If
-.Ar key command
-is supplied, bind
-.Ar command
-to
-.Ar key .
-Options include:
-.Bl -tag -width 4n
-.It Fl e
-Bind all keys to the standard GNU Emacs-like bindings.
-.It Fl v
-Bind all keys to the standard
-.Xr vi 1 -like
-bindings.
-.It Fl a
-List or change key bindings in the
-.Xr vi 1
-mode alternate (command mode) key map.
-.It Fl k
-.Ar key
-is interpreted as a symbolic arrow key name, which may be one of
-.Sq up ,
-.Sq down ,
-.Sq left
-or
-.Sq right .
-.It Fl l
-List all editor commands and a short description of each.
-.It Fl r
-Remove a key's binding.
-.It Fl s
-.Ar command
-is taken as a literal string and treated as terminal input when
-.Ar key
-is typed.
-Bound keys in
-.Ar command
-are themselves reinterpreted, and this continues for ten levels of
-interpretation.
-.El
-.Pp
-.Ar command
-may be one of the commands documented in
-.Sx "EDITOR COMMANDS"
-below, or another key.
-.Pp
-.Ar key
-and
-.Ar command
-can contain control characters of the form
-.Sm off
-.Sq No ^ Ar character
-.Sm on
-.Po
-e.g.
-.Sq ^A
-.Pc ,
-and the following backslashed escape sequences:
-.Pp
-.Bl -tag -compact -offset indent -width 4n
-.It Ic \ea
-Bell
-.It Ic \eb
-Backspace
-.It Ic \ee
-Escape
-.It Ic \ef
-Formfeed
-.It Ic \en
-Newline
-.It Ic \er
-Carriage return
-.It Ic \et
-Horizontal tab
-.It Ic \ev
-Vertical tab
-.Sm off
-.It Sy \e Ar nnn
-.Sm on
-The ASCII character corresponding to the octal number
-.Ar nnn .
-.El
-.Pp
-.Sq \e
-nullifies the special meaning of the following character,
-if it has any, notably
-.Sq \e
-and
-.Sq ^ .
-.It Ic echotc Xo
-.Op Fl sv
-.Ar arg
-.Ar ...
-.Xc
-Exercise terminal capabilities given in
-.Ar arg Ar ... .
-If
-.Ar arg
-is
-.Sq baud ,
-.Sq cols ,
-.Sq lines ,
-.Sq rows ,
-.Sq meta or
-.Sq tabs ,
-the value of that capability is printed, with
-.Dq yes
-or
-.Dq no
-indicating that the terminal does or does not have that capability.
-.Pp
-.Fl s
-returns an emptry string for non-existent capabilities, rather than
-causing an error.
-.Fl v
-causes messages to be verbose.
-.It Ic edit Op Li on | Li off
-Enable or disable the
-.Nm editline
-functionality in a program.
-.It Ic history
-List the history.
-.It Ic telltc
-List the values of all the terminal capabilities (see
-.Xr termcap 5 ) .
-.It Ic settc Ar cap Ar val
-Set the terminal capability
-.Ar cap
-to
-.Ar val ,
-as defined in
-.Xr termcap 5 .
-No sanity checking is done.
-.It Ic setty Xo
-.Op Fl a
-.Op Fl d
-.Op Fl q
-.Op Fl x
-.Op Ar +mode
-.Op Ar -mode
-.Op Ar mode
-.Xc
-Control which tty modes that
-.Nm
-won't allow the user to change.
-.Fl d ,
-.Fl q
-or
-.Fl x
-tells
-.Ic setty
-to act on the
-.Sq edit ,
-.Sq quote
-or
-.Sq execute
-set of tty modes respectively; defaulting to
-.Fl x .
-.Pp
-Without other arguments,
-.Ic setty
-lists the modes in the chosen set which are fixed on
-.Po
-.Sq +mode
-.Pc
-or off
-.Po
-.Sq -mode
-.Pc .
-.Fl a
-lists all tty modes in the chosen set regardless of the setting.
-With
-.Ar +mode ,
-.Ar -mode
-or
-.Ar mode ,
-fixes
-.Ar mode
-on or off or removes control of
-.Ar mode
-in the chosen set.
-.El
-.Sh EDITOR COMMANDS
-The following editor commands are available for use in key bindings:
-.\" Section automatically generated with makelist
-.Bl -tag -width 4n
-.It Ic vi-paste-next
-Vi paste previous deletion to the right of the cursor.
-.It Ic vi-paste-prev
-Vi paste previous deletion to the left of the cursor.
-.It Ic vi-prev-space-word
-Vi move to the previous space delimited word.
-.It Ic vi-prev-word
-Vi move to the previous word.
-.It Ic vi-next-space-word
-Vi move to the next space delimited word.
-.It Ic vi-next-word
-Vi move to the next word.
-.It Ic vi-change-case
-Vi change case of character under the cursor and advance one character.
-.It Ic vi-change-meta
-Vi change prefix command.
-.It Ic vi-insert-at-bol
-Vi enter insert mode at the beginning of line.
-.It Ic vi-replace-char
-Vi replace character under the cursor with the next character typed.
-.It Ic vi-replace-mode
-Vi enter replace mode.
-.It Ic vi-substitute-char
-Vi replace character under the cursor and enter insert mode.
-.It Ic vi-substitute-line
-Vi substitute entire line.
-.It Ic vi-change-to-eol
-Vi change to end of line.
-.It Ic vi-insert
-Vi enter insert mode.
-.It Ic vi-add
-Vi enter insert mode after the cursor.
-.It Ic vi-add-at-eol
-Vi enter insert mode at end of line.
-.It Ic vi-delete-meta
-Vi delete prefix command.
-.It Ic vi-end-word
-Vi move to the end of the current space delimited word.
-.It Ic vi-to-end-word
-Vi move to the end of the current word.
-.It Ic vi-undo
-Vi undo last change.
-.It Ic vi-command-mode
-Vi enter command mode (use alternative key bindings).
-.It Ic vi-zero
-Vi move to the beginning of line.
-.It Ic vi-delete-prev-char
-Vi move to previous character (backspace).
-.It Ic vi-list-or-eof
-Vi list choices for completion or indicate end of file if empty line.
-.It Ic vi-kill-line-prev
-Vi cut from beginning of line to cursor.
-.It Ic vi-search-prev
-Vi search history previous.
-.It Ic vi-search-next
-Vi search history next.
-.It Ic vi-repeat-search-next
-Vi repeat current search in the same search direction.
-.It Ic vi-repeat-search-prev
-Vi repeat current search in the opposite search direction.
-.It Ic vi-next-char
-Vi move to the character specified next.
-.It Ic vi-prev-char
-Vi move to the character specified previous.
-.It Ic vi-to-next-char
-Vi move up to the character specified next.
-.It Ic vi-to-prev-char
-Vi move up to the character specified previous.
-.It Ic vi-repeat-next-char
-Vi repeat current character search in the same search direction.
-.It Ic vi-repeat-prev-char
-Vi repeat current character search in the opposite search direction.
-.It Ic em-delete-or-list
-Delete character under cursor or list completions if at end of line.
-.It Ic em-delete-next-word
-Cut from cursor to end of current word.
-.It Ic em-yank
-Paste cut buffer at cursor position.
-.It Ic em-kill-line
-Cut the entire line and save in cut buffer.
-.It Ic em-kill-region
-Cut area between mark and cursor and save in cut buffer.
-.It Ic em-copy-region
-Copy area between mark and cursor to cut buffer.
-.It Ic em-gosmacs-traspose
-Exchange the two characters before the cursor.
-.It Ic em-next-word
-Move next to end of current word.
-.It Ic em-upper-case
-Uppercase the characters from cursor to end of current word.
-.It Ic em-capitol-case
-Capitalize the characters from cursor to end of current word.
-.It Ic em-lower-case
-Lowercase the characters from cursor to end of current word.
-.It Ic em-set-mark
-Set the mark at cursor.
-.It Ic em-exchange-mark
-Exchange the cursor and mark.
-.It Ic em-universal-argument
-Universal argument (argument times 4).
-.It Ic em-meta-next
-Add 8th bit to next character typed.
-.It Ic em-toggle-overwrite
-Switch from insert to overwrite mode or vice versa.
-.It Ic em-copy-prev-word
-Copy current word to cursor.
-.It Ic em-inc-search-next
-Emacs incremental next search.
-.It Ic em-inc-search-prev
-Emacs incremental reverse search.
-.It Ic ed-end-of-file
-Indicate end of file.
-.It Ic ed-insert
-Add character to the line.
-.It Ic ed-delete-prev-word
-Delete from beginning of current word to cursor.
-.It Ic ed-delete-next-char
-Delete character under cursor.
-.It Ic ed-kill-line
-Cut to the end of line.
-.It Ic ed-move-to-end
-Move cursor to the end of line.
-.It Ic ed-move-to-beg
-Move cursor to the beginning of line.
-.It Ic ed-transpose-chars
-Exchange the character to the left of the cursor with the one under it.
-.It Ic ed-next-char
-Move to the right one character.
-.It Ic ed-prev-word
-Move to the beginning of the current word.
-.It Ic ed-prev-char
-Move to the left one character.
-.It Ic ed-quoted-insert
-Add the next character typed verbatim.
-.It Ic ed-digit
-Adds to argument or enters a digit.
-.It Ic ed-argument-digit
-Digit that starts argument.
-.It Ic ed-unassigned
-Indicates unbound character.
-.It Ic ed-tty-sigint
-Tty interrupt character.
-.It Ic ed-tty-dsusp
-Tty delayed suspend character.
-.It Ic ed-tty-flush-output
-Tty flush output characters.
-.It Ic ed-tty-sigquit
-Tty quit character.
-.It Ic ed-tty-sigtstp
-Tty suspend character.
-.It Ic ed-tty-stop-output
-Tty disallow output characters.
-.It Ic ed-tty-start-output
-Tty allow output characters.
-.It Ic ed-newline
-Execute command.
-.It Ic ed-delete-prev-char
-Delete the character to the left of the cursor.
-.It Ic ed-clear-screen
-Clear screen leaving current line at the top.
-.It Ic ed-redisplay
-Redisplay everything.
-.It Ic ed-start-over
-Erase current line and start from scratch.
-.It Ic ed-sequence-lead-in
-First character in a bound sequence.
-.It Ic ed-prev-history
-Move to the previous history line.
-.It Ic ed-next-history
-Move to the next history line.
-.It Ic ed-search-prev-history
-Search previous in history for a line matching the current.
-.It Ic ed-search-next-history
-Search next in history for a line matching the current.
-.It Ic ed-prev-line
-Move up one line.
-.It Ic ed-next-line
-Move down one line.
-.It Ic ed-command
-Editline extended command.
-.El
-.\" End of section automatically generated with makelist
-.Sh SEE ALSO
-.Xr editline 3 ,
-.Xr regex 3 ,
-.Xr termcap 5
-.Sh AUTHORS
-The
-.Nm editline
-library was written by Christos Zoulas,
-and this manual was written by Luke Mewburn,
-with some sections inspired by
-.Xr tcsh 1 .
diff --git a/main/editline/el.c b/main/editline/el.c
deleted file mode 100644
index 514316fbe..000000000
--- a/main/editline/el.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/* $NetBSD: el.c,v 1.29 2002/03/18 16:00:52 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
-#else
-__RCSID("$NetBSD: el.c,v 1.29 2002/03/18 16:00:52 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * el.c: EditLine interface functions
- */
-#include <sys/types.h>
-#include <sys/param.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include "el.h"
-
-/* el_init():
- * Initialize editline and set default parameters.
- */
-public EditLine *
-el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
-{
-
- EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
-
- if (el == NULL)
- return (NULL);
-
- memset(el, 0, sizeof(EditLine));
-
- el->el_infd = fileno(fin);
- el->el_outfile = fout;
- el->el_errfile = ferr;
- el->el_prog = strdup(prog);
-
- /*
- * Initialize all the modules. Order is important!!!
- */
- el->el_flags = 0;
-
- if (term_init(el) == -1) {
- free(el->el_prog);
- el_free(el);
- return NULL;
- }
- (void) key_init(el);
- (void) map_init(el);
- if (tty_init(el) == -1)
- el->el_flags |= NO_TTY;
- (void) ch_init(el);
- (void) search_init(el);
- (void) hist_init(el);
- (void) prompt_init(el);
- (void) sig_init(el);
- (void) read_init(el);
-
- return (el);
-}
-
-
-/* el_end():
- * Clean up.
- */
-public void
-el_end(EditLine *el)
-{
-
- if (el == NULL)
- return;
-
- el_reset(el);
-
- term_end(el);
- key_end(el);
- map_end(el);
- tty_end(el);
- ch_end(el);
- search_end(el);
- hist_end(el);
- prompt_end(el);
- sig_end(el);
-
- if (el->el_prog)
- el_free((ptr_t) el->el_prog);
- el_free((ptr_t) el);
-}
-
-
-/* el_reset():
- * Reset the tty and the parser
- */
-public void
-el_reset(EditLine *el)
-{
-
- tty_cookedmode(el);
- ch_reset(el); /* XXX: Do we want that? */
-}
-
-
-/* el_set():
- * set the editline parameters
- */
-public int
-el_set(EditLine *el, int op, ...)
-{
- va_list va;
- int rv = 0;
-
- if (el == NULL)
- return (-1);
- va_start(va, op);
-
- switch (op) {
- case EL_PROMPT:
- case EL_RPROMPT:
- rv = prompt_set(el, va_arg(va, el_pfunc_t), op);
- break;
-
- case EL_TERMINAL:
- rv = term_set(el, va_arg(va, char *));
- break;
-
- case EL_EDITOR:
- rv = map_set_editor(el, va_arg(va, char *));
- break;
-
- case EL_SIGNAL:
- if (va_arg(va, int))
- el->el_flags |= HANDLE_SIGNALS;
- else
- el->el_flags &= ~HANDLE_SIGNALS;
- break;
-
- case EL_BIND:
- case EL_TELLTC:
- case EL_SETTC:
- case EL_ECHOTC:
- case EL_SETTY:
- {
- const char *argv[20];
- int i;
-
- for (i = 1; i < 20; i++)
- if ((argv[i] = va_arg(va, char *)) == NULL)
- break;
-
- switch (op) {
- case EL_BIND:
- argv[0] = "bind";
- rv = map_bind(el, i, argv);
- break;
-
- case EL_TELLTC:
- argv[0] = "telltc";
- rv = term_telltc(el, i, argv);
- break;
-
- case EL_SETTC:
- argv[0] = "settc";
- rv = term_settc(el, i, argv);
- break;
-
- case EL_ECHOTC:
- argv[0] = "echotc";
- rv = term_echotc(el, i, argv);
- break;
-
- case EL_SETTY:
- argv[0] = "setty";
- rv = tty_stty(el, i, argv);
- break;
-
- default:
- rv = -1;
- EL_ABORT((el->el_errfile, "Bad op %d\n", op));
- break;
- }
- break;
- }
-
- case EL_ADDFN:
- {
- char *name = va_arg(va, char *);
- char *help = va_arg(va, char *);
- el_func_t func = va_arg(va, el_func_t);
-
- rv = map_addfunc(el, name, help, func);
- break;
- }
-
- case EL_HIST:
- {
- hist_fun_t func = va_arg(va, hist_fun_t);
- ptr_t ptr = va_arg(va, char *);
-
- rv = hist_set(el, func, ptr);
- break;
- }
-
- case EL_EDITMODE:
- if (va_arg(va, int))
- el->el_flags &= ~EDIT_DISABLED;
- else
- el->el_flags |= EDIT_DISABLED;
- rv = 0;
- break;
-
- case EL_GETCFN:
- {
- el_rfunc_t rc = va_arg(va, el_rfunc_t);
- rv = el_read_setfn(el, rc);
- break;
- }
-
- case EL_CLIENTDATA:
- el->el_data = va_arg(va, void *);
- break;
-
- default:
- rv = -1;
- break;
- }
-
- va_end(va);
- return (rv);
-}
-
-
-/* el_get():
- * retrieve the editline parameters
- */
-public int
-el_get(EditLine *el, int op, void *ret)
-{
- int rv;
-
- if (el == NULL || ret == NULL)
- return (-1);
- switch (op) {
- case EL_PROMPT:
- case EL_RPROMPT:
- rv = prompt_get(el, (el_pfunc_t *) & ret, op);
- break;
-
- case EL_EDITOR:
- rv = map_get_editor(el, (const char **) &ret);
- break;
-
- case EL_SIGNAL:
- *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
- rv = 0;
- break;
-
- case EL_EDITMODE:
- *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
- rv = 0;
- break;
-
-#if 0 /* XXX */
- case EL_TERMINAL:
- rv = term_get(el, (const char *) &ret);
- break;
-
- case EL_BIND:
- case EL_TELLTC:
- case EL_SETTC:
- case EL_ECHOTC:
- case EL_SETTY:
- {
- char *argv[20];
- int i;
-
- for (i = 1; i < 20; i++)
- if ((argv[i] = va_arg(va, char *)) == NULL)
- break;
-
- switch (op) {
- case EL_BIND:
- argv[0] = "bind";
- rv = map_bind(el, i, argv);
- break;
-
- case EL_TELLTC:
- argv[0] = "telltc";
- rv = term_telltc(el, i, argv);
- break;
-
- case EL_SETTC:
- argv[0] = "settc";
- rv = term_settc(el, i, argv);
- break;
-
- case EL_ECHOTC:
- argv[0] = "echotc";
- rv = term_echotc(el, i, argv);
- break;
-
- case EL_SETTY:
- argv[0] = "setty";
- rv = tty_stty(el, i, argv);
- break;
-
- default:
- rv = -1;
- EL_ABORT((el->errfile, "Bad op %d\n", op));
- break;
- }
- break;
- }
-
- case EL_ADDFN:
- {
- char *name = va_arg(va, char *);
- char *help = va_arg(va, char *);
- el_func_t func = va_arg(va, el_func_t);
-
- rv = map_addfunc(el, name, help, func);
- break;
- }
-
- case EL_HIST:
- {
- hist_fun_t func = va_arg(va, hist_fun_t);
- ptr_t ptr = va_arg(va, char *);
- rv = hist_set(el, func, ptr);
- }
- break;
-#endif /* XXX */
-
- case EL_GETCFN:
- *((el_rfunc_t *)ret) = el_read_getfn(el);
- rv = 0;
- break;
-
- case EL_CLIENTDATA:
- *((void **)ret) = el->el_data;
- rv = 0;
- break;
-
- default:
- rv = -1;
- }
-
- return (rv);
-}
-
-
-/* el_line():
- * Return editing info
- */
-public const LineInfo *
-el_line(EditLine *el)
-{
-
- return (const LineInfo *) (void *) &el->el_line;
-}
-
-
-/* el_source():
- * Source a file
- */
-public int
-el_source(EditLine *el, const char *fname)
-{
- FILE *fp;
- size_t len;
- char *ptr;
-
- fp = NULL;
- if (fname == NULL) {
-#ifdef HAVE_ISSETUGID
- static const char elpath[] = "/.editrc";
- char path[MAXPATHLEN];
-
- if (issetugid())
- return (-1);
- if ((ptr = getenv("HOME")) == NULL)
- return (-1);
- if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
- return (-1);
- if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
- return (-1);
- fname = path;
-#else
- /*
- * If issetugid() is missing, always return an error, in order
- * to keep from inadvertently opening up the user to a security
- * hole.
- */
- return (-1);
-#endif
- }
- if (fp == NULL)
- fp = fopen(fname, "r");
- if (fp == NULL)
- return (-1);
-
- while ((ptr = fgetln(fp, &len)) != NULL) {
- if (len > 0 && ptr[len - 1] == '\n')
- --len;
- ptr[len] = '\0';
- if (parse_line(el, ptr) == -1) {
- (void) fclose(fp);
- return (-1);
- }
- }
-
- (void) fclose(fp);
- return (0);
-}
-
-
-/* el_resize():
- * Called from program when terminal is resized
- */
-public void
-el_resize(EditLine *el)
-{
- int lins, cols;
- sigset_t oset, nset;
-
- (void) sigemptyset(&nset);
- (void) sigaddset(&nset, SIGWINCH);
- (void) sigprocmask(SIG_BLOCK, &nset, &oset);
-
- /* get the correct window size */
- if (term_get_size(el, &lins, &cols))
- term_change_size(el, lins, cols);
-
- (void) sigprocmask(SIG_SETMASK, &oset, NULL);
-}
-
-
-/* el_beep():
- * Called from the program to beep
- */
-public void
-el_beep(EditLine *el)
-{
-
- term_beep(el);
-}
-
-
-/* el_editmode()
- * Set the state of EDIT_DISABLED from the `edit' command.
- */
-protected int
-/*ARGSUSED*/
-el_editmode(EditLine *el, int argc, const char **argv)
-{
- const char *how;
-
- if (argv == NULL || argc != 2 || argv[1] == NULL)
- return (-1);
-
- how = argv[1];
- if (strcmp(how, "on") == 0)
- el->el_flags &= ~EDIT_DISABLED;
- else if (strcmp(how, "off") == 0)
- el->el_flags |= EDIT_DISABLED;
- else {
- (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
- return (-1);
- }
- return (0);
-}
diff --git a/main/editline/el.h b/main/editline/el.h
deleted file mode 100644
index 641081e87..000000000
--- a/main/editline/el.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* $NetBSD: el.h,v 1.11 2002/03/18 16:00:52 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)el.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.h: Internal structures.
- */
-#ifndef _h_el
-#define _h_el
-/*
- * Local defaults
- */
-#define KSHVI
-#define VIDEFAULT
-#define ANCHOR
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#define EL_BUFSIZ 1024 /* Maximum line size */
-
-#define HANDLE_SIGNALS 1<<0
-#define NO_TTY 1<<1
-#define EDIT_DISABLED 1<<2
-
-typedef int bool_t; /* True or not */
-
-typedef unsigned char el_action_t; /* Index to command array */
-
-typedef struct coord_t { /* Position on the screen */
- int h;
- int v;
-} coord_t;
-
-typedef struct el_line_t {
- char *buffer; /* Input line */
- char *cursor; /* Cursor position */
- char *lastchar; /* Last character */
- const char *limit; /* Max position */
-} el_line_t;
-
-/*
- * Editor state
- */
-typedef struct el_state_t {
- int inputmode; /* What mode are we in? */
- int doingarg; /* Are we getting an argument? */
- int argument; /* Numeric argument */
- int metanext; /* Is the next char a meta char */
- el_action_t lastcmd; /* Previous command */
-} el_state_t;
-
-/*
- * Until we come up with something better...
- */
-#define el_malloc(a) malloc(a)
-#define el_realloc(a,b) realloc(a, b)
-#define el_free(a) free(a)
-
-#include "tty.h"
-#include "prompt.h"
-#include "key.h"
-#include "term.h"
-#include "refresh.h"
-#include "chared.h"
-#include "common.h"
-#include "search.h"
-#include "hist.h"
-#include "map.h"
-#include "parse.h"
-#include "sig.h"
-#include "help.h"
-#include "read.h"
-
-struct editline {
- char *el_prog; /* the program name */
- FILE *el_outfile; /* Stdio stuff */
- FILE *el_errfile; /* Stdio stuff */
- int el_infd; /* Input file descriptor */
- int el_flags; /* Various flags. */
- coord_t el_cursor; /* Cursor location */
- char **el_display; /* Real screen image = what is there */
- char **el_vdisplay; /* Virtual screen image = what we see */
- void *el_data; /* Client data */
- el_line_t el_line; /* The current line information */
- el_state_t el_state; /* Current editor state */
- el_term_t el_term; /* Terminal dependent stuff */
- el_tty_t el_tty; /* Tty dependent stuff */
- el_refresh_t el_refresh; /* Refresh stuff */
- el_prompt_t el_prompt; /* Prompt stuff */
- el_prompt_t el_rprompt; /* Prompt stuff */
- el_chared_t el_chared; /* Characted editor stuff */
- el_map_t el_map; /* Key mapping stuff */
- el_key_t el_key; /* Key binding stuff */
- el_history_t el_history; /* History stuff */
- el_search_t el_search; /* Search stuff */
- el_signal_t el_signal; /* Signal handling stuff */
- el_read_t el_read; /* Character reading stuff */
-};
-
-protected int el_editmode(EditLine *, int, const char **);
-
-#ifdef DEBUG
-#define EL_ABORT(a) (void) (fprintf(el->el_errfile, "%s, %d: ", \
- __FILE__, __LINE__), fprintf a, abort())
-#else
-#define EL_ABORT(a) abort()
-#endif
-#endif /* _h_el */
diff --git a/main/editline/emacs.c b/main/editline/emacs.c
deleted file mode 100644
index f520d024b..000000000
--- a/main/editline/emacs.c
+++ /dev/null
@@ -1,488 +0,0 @@
-/* $NetBSD: emacs.c,v 1.10 2002/03/18 16:00:52 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: emacs.c,v 1.10 2002/03/18 16:00:52 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * emacs.c: Emacs functions
- */
-#include "el.h"
-
-/* em_delete_or_list():
- * Delete character under cursor or list completions if at end of line
- * [^D]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_delete_or_list(EditLine *el, int c)
-{
-
- if (el->el_line.cursor == el->el_line.lastchar) {
- /* if I'm at the end */
- if (el->el_line.cursor == el->el_line.buffer) {
- /* and the beginning */
- term_overwrite(el, STReof, 4); /* then do a EOF */
- term__flush();
- return (CC_EOF);
- } else {
- /*
- * Here we could list completions, but it is an
- * error right now
- */
- term_beep(el);
- return (CC_ERROR);
- }
- } else {
- c_delafter(el, el->el_state.argument); /* delete after dot */
- if (el->el_line.cursor > el->el_line.lastchar)
- el->el_line.cursor = el->el_line.lastchar;
- /* bounds check */
- return (CC_REFRESH);
- }
-}
-
-
-/* em_delete_next_word():
- * Cut from cursor to end of current word
- * [M-d]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_delete_next_word(EditLine *el, int c)
-{
- char *cp, *p, *kp;
-
- if (el->el_line.cursor == el->el_line.lastchar)
- return (CC_ERROR);
-
- cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
- el->el_state.argument, ce__isword);
-
- for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
- /* save the text */
- *kp++ = *p;
- el->el_chared.c_kill.last = kp;
-
- c_delafter(el, cp - el->el_line.cursor); /* delete after dot */
- if (el->el_line.cursor > el->el_line.lastchar)
- el->el_line.cursor = el->el_line.lastchar;
- /* bounds check */
- return (CC_REFRESH);
-}
-
-
-/* em_yank():
- * Paste cut buffer at cursor position
- * [^Y]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_yank(EditLine *el, int c)
-{
- char *kp, *cp;
-
- if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) {
- if (!ch_enlargebufs(el, 1))
- return (CC_ERROR);
- }
-
- if (el->el_line.lastchar +
- (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
- el->el_line.limit)
- return (CC_ERROR);
-
- el->el_chared.c_kill.mark = el->el_line.cursor;
- cp = el->el_line.cursor;
-
- /* open the space, */
- c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
- /* copy the chars */
- for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
- *cp++ = *kp;
-
- /* if an arg, cursor at beginning else cursor at end */
- if (el->el_state.argument == 1)
- el->el_line.cursor = cp;
-
- return (CC_REFRESH);
-}
-
-
-/* em_kill_line():
- * Cut the entire line and save in cut buffer
- * [^U]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_kill_line(EditLine *el, int c)
-{
- char *kp, *cp;
-
- cp = el->el_line.buffer;
- kp = el->el_chared.c_kill.buf;
- while (cp < el->el_line.lastchar)
- *kp++ = *cp++; /* copy it */
- el->el_chared.c_kill.last = kp;
- /* zap! -- delete all of it */
- el->el_line.lastchar = el->el_line.buffer;
- el->el_line.cursor = el->el_line.buffer;
- return (CC_REFRESH);
-}
-
-
-/* em_kill_region():
- * Cut area between mark and cursor and save in cut buffer
- * [^W]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_kill_region(EditLine *el, int c)
-{
- char *kp, *cp;
-
- if (!el->el_chared.c_kill.mark)
- return (CC_ERROR);
-
- if (el->el_chared.c_kill.mark > el->el_line.cursor) {
- cp = el->el_line.cursor;
- kp = el->el_chared.c_kill.buf;
- while (cp < el->el_chared.c_kill.mark)
- *kp++ = *cp++; /* copy it */
- el->el_chared.c_kill.last = kp;
- c_delafter(el, cp - el->el_line.cursor);
- } else { /* mark is before cursor */
- cp = el->el_chared.c_kill.mark;
- kp = el->el_chared.c_kill.buf;
- while (cp < el->el_line.cursor)
- *kp++ = *cp++; /* copy it */
- el->el_chared.c_kill.last = kp;
- c_delbefore(el, cp - el->el_chared.c_kill.mark);
- el->el_line.cursor = el->el_chared.c_kill.mark;
- }
- return (CC_REFRESH);
-}
-
-
-/* em_copy_region():
- * Copy area between mark and cursor to cut buffer
- * [M-W]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_copy_region(EditLine *el, int c)
-{
- char *kp, *cp;
-
- if (el->el_chared.c_kill.mark)
- return (CC_ERROR);
-
- if (el->el_chared.c_kill.mark > el->el_line.cursor) {
- cp = el->el_line.cursor;
- kp = el->el_chared.c_kill.buf;
- while (cp < el->el_chared.c_kill.mark)
- *kp++ = *cp++; /* copy it */
- el->el_chared.c_kill.last = kp;
- } else {
- cp = el->el_chared.c_kill.mark;
- kp = el->el_chared.c_kill.buf;
- while (cp < el->el_line.cursor)
- *kp++ = *cp++; /* copy it */
- el->el_chared.c_kill.last = kp;
- }
- return (CC_NORM);
-}
-
-
-/* em_gosmacs_traspose():
- * Exchange the two characters before the cursor
- * Gosling emacs transpose chars [^T]
- */
-protected el_action_t
-em_gosmacs_traspose(EditLine *el, int c)
-{
-
- if (el->el_line.cursor > &el->el_line.buffer[1]) {
- /* must have at least two chars entered */
- c = el->el_line.cursor[-2];
- el->el_line.cursor[-2] = el->el_line.cursor[-1];
- el->el_line.cursor[-1] = c;
- return (CC_REFRESH);
- } else
- return (CC_ERROR);
-}
-
-
-/* em_next_word():
- * Move next to end of current word
- * [M-f]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_next_word(EditLine *el, int c)
-{
- if (el->el_line.cursor == el->el_line.lastchar)
- return (CC_ERROR);
-
- el->el_line.cursor = c__next_word(el->el_line.cursor,
- el->el_line.lastchar,
- el->el_state.argument,
- ce__isword);
-
- if (el->el_map.type == MAP_VI)
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
-}
-
-
-/* em_upper_case():
- * Uppercase the characters from cursor to end of current word
- * [M-u]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_upper_case(EditLine *el, int c)
-{
- char *cp, *ep;
-
- ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
- el->el_state.argument, ce__isword);
-
- for (cp = el->el_line.cursor; cp < ep; cp++)
- if (islower((unsigned char) *cp))
- *cp = toupper(*cp);
-
- el->el_line.cursor = ep;
- if (el->el_line.cursor > el->el_line.lastchar)
- el->el_line.cursor = el->el_line.lastchar;
- return (CC_REFRESH);
-}
-
-
-/* em_capitol_case():
- * Capitalize the characters from cursor to end of current word
- * [M-c]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_capitol_case(EditLine *el, int c)
-{
- char *cp, *ep;
-
- ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
- el->el_state.argument, ce__isword);
-
- for (cp = el->el_line.cursor; cp < ep; cp++) {
- if (isalpha((unsigned char) *cp)) {
- if (islower((unsigned char) *cp))
- *cp = toupper(*cp);
- cp++;
- break;
- }
- }
- for (; cp < ep; cp++)
- if (isupper((unsigned char) *cp))
- *cp = tolower(*cp);
-
- el->el_line.cursor = ep;
- if (el->el_line.cursor > el->el_line.lastchar)
- el->el_line.cursor = el->el_line.lastchar;
- return (CC_REFRESH);
-}
-
-
-/* em_lower_case():
- * Lowercase the characters from cursor to end of current word
- * [M-l]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_lower_case(EditLine *el, int c)
-{
- char *cp, *ep;
-
- ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
- el->el_state.argument, ce__isword);
-
- for (cp = el->el_line.cursor; cp < ep; cp++)
- if (isupper((unsigned char) *cp))
- *cp = tolower(*cp);
-
- el->el_line.cursor = ep;
- if (el->el_line.cursor > el->el_line.lastchar)
- el->el_line.cursor = el->el_line.lastchar;
- return (CC_REFRESH);
-}
-
-
-/* em_set_mark():
- * Set the mark at cursor
- * [^@]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_set_mark(EditLine *el, int c)
-{
-
- el->el_chared.c_kill.mark = el->el_line.cursor;
- return (CC_NORM);
-}
-
-
-/* em_exchange_mark():
- * Exchange the cursor and mark
- * [^X^X]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_exchange_mark(EditLine *el, int c)
-{
- char *cp;
-
- cp = el->el_line.cursor;
- el->el_line.cursor = el->el_chared.c_kill.mark;
- el->el_chared.c_kill.mark = cp;
- return (CC_CURSOR);
-}
-
-
-/* em_universal_argument():
- * Universal argument (argument times 4)
- * [^U]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_universal_argument(EditLine *el, int c)
-{ /* multiply current argument by 4 */
-
- if (el->el_state.argument > 1000000)
- return (CC_ERROR);
- el->el_state.doingarg = 1;
- el->el_state.argument *= 4;
- return (CC_ARGHACK);
-}
-
-
-/* em_meta_next():
- * Add 8th bit to next character typed
- * [<ESC>]
- */
-protected el_action_t
-/*ARGSUSED*/
-em_meta_next(EditLine *el, int c)
-{
-
- el->el_state.metanext = 1;
- return (CC_ARGHACK);
-}
-
-
-/* em_toggle_overwrite():
- * Switch from insert to overwrite mode or vice versa
- */
-protected el_action_t
-/*ARGSUSED*/
-em_toggle_overwrite(EditLine *el, int c)
-{
-
- el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
- MODE_REPLACE : MODE_INSERT;
- return (CC_NORM);
-}
-
-
-/* em_copy_prev_word():
- * Copy current word to cursor
- */
-protected el_action_t
-/*ARGSUSED*/
-em_copy_prev_word(EditLine *el, int c)
-{
- char *cp, *oldc, *dp;
-
- if (el->el_line.cursor == el->el_line.buffer)
- return (CC_ERROR);
-
- oldc = el->el_line.cursor;
- /* does a bounds check */
- cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
- el->el_state.argument, ce__isword);
-
- c_insert(el, oldc - cp);
- for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
- *dp++ = *cp;
-
- el->el_line.cursor = dp;/* put cursor at end */
-
- return (CC_REFRESH);
-}
-
-
-/* em_inc_search_next():
- * Emacs incremental next search
- */
-protected el_action_t
-/*ARGSUSED*/
-em_inc_search_next(EditLine *el, int c)
-{
-
- el->el_search.patlen = 0;
- return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
-}
-
-
-/* em_inc_search_prev():
- * Emacs incremental reverse search
- */
-protected el_action_t
-/*ARGSUSED*/
-em_inc_search_prev(EditLine *el, int c)
-{
-
- el->el_search.patlen = 0;
- return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
-}
diff --git a/main/editline/hist.c b/main/editline/hist.c
deleted file mode 100644
index 11f39ae10..000000000
--- a/main/editline/hist.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/* $NetBSD: hist.c,v 1.10 2002/03/18 16:00:53 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: hist.c,v 1.10 2002/03/18 16:00:53 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * hist.c: History access functions
- */
-#include <stdlib.h>
-#include "el.h"
-
-/* hist_init():
- * Initialization function.
- */
-protected int
-hist_init(EditLine *el)
-{
-
- el->el_history.fun = NULL;
- el->el_history.ref = NULL;
- el->el_history.buf = (char *) el_malloc(EL_BUFSIZ);
- el->el_history.sz = EL_BUFSIZ;
- if (el->el_history.buf == NULL)
- return (-1);
- el->el_history.last = el->el_history.buf;
- return (0);
-}
-
-
-/* hist_end():
- * clean up history;
- */
-protected void
-hist_end(EditLine *el)
-{
-
- el_free((ptr_t) el->el_history.buf);
- el->el_history.buf = NULL;
-}
-
-
-/* hist_set():
- * Set new history interface
- */
-protected int
-hist_set(EditLine *el, hist_fun_t fun, ptr_t ptr)
-{
-
- el->el_history.ref = ptr;
- el->el_history.fun = fun;
- return (0);
-}
-
-
-/* hist_get():
- * Get a history line and update it in the buffer.
- * eventno tells us the event to get.
- */
-protected el_action_t
-hist_get(EditLine *el)
-{
- const char *hp;
- int h;
-
- if (el->el_history.eventno == 0) { /* if really the current line */
- (void) strncpy(el->el_line.buffer, el->el_history.buf,
- el->el_history.sz - 1);
- el->el_line.lastchar = el->el_line.buffer +
- (el->el_history.last - el->el_history.buf);
-
-#ifdef KSHVI
- if (el->el_map.type == MAP_VI)
- el->el_line.cursor = el->el_line.buffer;
- else
-#endif /* KSHVI */
- el->el_line.cursor = el->el_line.lastchar;
-
- return (CC_REFRESH);
- }
- if (el->el_history.ref == NULL)
- return (CC_ERROR);
-
- hp = HIST_FIRST(el);
-
- if (hp == NULL)
- return (CC_ERROR);
-
- for (h = 1; h < el->el_history.eventno; h++)
- if ((hp = HIST_NEXT(el)) == NULL) {
- el->el_history.eventno = h;
- return (CC_ERROR);
- }
- (void) strncpy(el->el_line.buffer, hp,
- (size_t)(el->el_line.limit - el->el_line.buffer));
- el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
-
- if (el->el_line.lastchar > el->el_line.buffer) {
- if (el->el_line.lastchar[-1] == '\n')
- el->el_line.lastchar--;
- if ((el->el_line.lastchar > el->el_line.buffer)&&(el->el_line.lastchar[-1] == ' ')) /* bill heckel */
- el->el_line.lastchar--;
- if (el->el_line.lastchar < el->el_line.buffer)
- el->el_line.lastchar = el->el_line.buffer;
- }
-#ifdef KSHVI
- if (el->el_map.type == MAP_VI)
- el->el_line.cursor = el->el_line.buffer;
- else
-#endif /* KSHVI */
- el->el_line.cursor = el->el_line.lastchar;
-
- return (CC_REFRESH);
-}
-
-
-/* hist_list()
- * List history entries
- */
-protected int
-/*ARGSUSED*/
-hist_list(EditLine *el, int argc, const char **argv)
-{
- const char *str;
-
- if (el->el_history.ref == NULL)
- return (-1);
- for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
- (void) fprintf(el->el_outfile, "%d %s",
- el->el_history.ev.num, str);
- return (0);
-}
-
-/* hist_enlargebuf()
- * Enlarge history buffer to specified value. Called from el_enlargebufs().
- * Return 0 for failure, 1 for success.
- */
-protected int
-/*ARGSUSED*/
-hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
-{
- char *newbuf;
-
- newbuf = realloc(el->el_history.buf, newsz);
- if (!newbuf)
- return 0;
-
- (void) memset(&newbuf[oldsz], '\0', newsz - oldsz);
-
- el->el_history.last = newbuf +
- (el->el_history.last - el->el_history.buf);
- el->el_history.buf = newbuf;
- el->el_history.sz = newsz;
-
- return 1;
-}
diff --git a/main/editline/hist.h b/main/editline/hist.h
deleted file mode 100644
index 5fdccd08e..000000000
--- a/main/editline/hist.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* $NetBSD: hist.h,v 1.7 2002/03/18 16:00:53 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)hist.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.hist.c: History functions
- */
-#ifndef _h_el_hist
-#define _h_el_hist
-
-#include "histedit.h"
-
-typedef int (*hist_fun_t)(ptr_t, HistEvent *, int, ...);
-
-typedef struct el_history_t {
- char *buf; /* The history buffer */
- size_t sz; /* Size of history buffer */
- char *last; /* The last character */
- int eventno; /* Event we are looking for */
- ptr_t ref; /* Argument for history fcns */
- hist_fun_t fun; /* Event access */
- HistEvent ev; /* Event cookie */
-} el_history_t;
-
-#define HIST_FUN(el, fn, arg) \
- ((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \
- fn, arg)) == -1) ? NULL : (el)->el_history.ev.str)
-
-#define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL)
-#define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL)
-#define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL)
-#define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL)
-#define HIST_EVENT(el, num) HIST_FUN(el, H_EVENT, num)
-#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname)
-#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname)
-
-protected int hist_init(EditLine *);
-protected void hist_end(EditLine *);
-protected el_action_t hist_get(EditLine *);
-protected int hist_set(EditLine *, hist_fun_t, ptr_t);
-protected int hist_list(EditLine *, int, const char **);
-protected int hist_enlargebuf(EditLine *, size_t, size_t);
-
-#endif /* _h_el_hist */
diff --git a/main/editline/histedit.h b/main/editline/histedit.h
deleted file mode 100644
index e387e3b81..000000000
--- a/main/editline/histedit.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/* $NetBSD: histedit.h,v 1.19 2002/03/18 16:00:54 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)histedit.h 8.2 (Berkeley) 1/3/94
- */
-
-/*
- * histedit.h: Line editor and history interface.
- */
-#ifndef _HISTEDIT_H_
-#define _HISTEDIT_H_
-
-#define LIBEDIT_MAJOR 2
-#define LIBEDIT_MINOR 6
-
-#include <sys/types.h>
-#include <stdio.h>
-
-/*
- * ==== Editing ====
- */
-typedef struct editline EditLine;
-
-/*
- * For user-defined function interface
- */
-typedef struct lineinfo {
- char *buffer;
- char *cursor;
- char *lastchar;
-} LineInfo;
-
-
-/*
- * EditLine editor function return codes.
- * For user-defined function interface
- */
-#define CC_NORM 0
-#define CC_NEWLINE 1
-#define CC_EOF 2
-#define CC_ARGHACK 3
-#define CC_REFRESH 4
-#define CC_CURSOR 5
-#define CC_ERROR 6
-#define CC_FATAL 7
-#define CC_REDISPLAY 8
-#define CC_REFRESH_BEEP 9
-
-/*
- * Initialization, cleanup, and resetting
- */
-EditLine *el_init(const char *, FILE *, FILE *, FILE *);
-void el_reset(EditLine *);
-void el_end(EditLine *);
-
-
-/*
- * Get a line, a character or push a string back in the input queue
- */
-const char *el_gets(EditLine *, int *);
-int el_getc(EditLine *, char *);
-void el_push(EditLine *, char *);
-
-/*
- * Beep!
- */
-void el_beep(EditLine *);
-
-/*
- * High level function internals control
- * Parses argc, argv array and executes builtin editline commands
- */
-int el_parse(EditLine *, int, const char **);
-
-/*
- * Low level editline access functions
- */
-int el_set(EditLine *, int, ...);
-int el_get(EditLine *, int, void *);
-
-/*
- * el_set/el_get parameters
- */
-#define EL_PROMPT 0 /* , el_pfunc_t); */
-#define EL_TERMINAL 1 /* , const char *); */
-#define EL_EDITOR 2 /* , const char *); */
-#define EL_SIGNAL 3 /* , int); */
-#define EL_BIND 4 /* , const char *, ..., NULL); */
-#define EL_TELLTC 5 /* , const char *, ..., NULL); */
-#define EL_SETTC 6 /* , const char *, ..., NULL); */
-#define EL_ECHOTC 7 /* , const char *, ..., NULL); */
-#define EL_SETTY 8 /* , const char *, ..., NULL); */
-#define EL_ADDFN 9 /* , const char *, const char * */
- /* , el_func_t); */
-#define EL_HIST 10 /* , hist_fun_t, const char *); */
-#define EL_EDITMODE 11 /* , int); */
-#define EL_RPROMPT 12 /* , el_pfunc_t); */
-#define EL_GETCFN 13 /* , el_rfunc_t); */
-#define EL_CLIENTDATA 14 /* , void *); */
-
-#define EL_BUILTIN_GETCFN (NULL)
-
-/*
- * Source named file or $PWD/.editrc or $HOME/.editrc
- */
-int el_source(EditLine *, const char *);
-
-/*
- * Must be called when the terminal changes size; If EL_SIGNAL
- * is set this is done automatically otherwise it is the responsibility
- * of the application
- */
-void el_resize(EditLine *);
-
-
-/*
- * User-defined function interface.
- */
-const LineInfo *el_line(EditLine *);
-int el_insertstr(EditLine *, const char *);
-void el_deletestr(EditLine *, int);
-
-/*
- * ==== History ====
- */
-
-typedef struct history History;
-
-typedef struct HistEvent {
- int num;
- const char *str;
-} HistEvent;
-
-/*
- * History access functions.
- */
-History * history_init(void);
-void history_end(History *);
-
-int history(History *, HistEvent *, int, ...);
-
-#define H_FUNC 0 /* , UTSL */
-#define H_SETSIZE 1 /* , const int); */
-#define H_GETSIZE 2 /* , void); */
-#define H_FIRST 3 /* , void); */
-#define H_LAST 4 /* , void); */
-#define H_PREV 5 /* , void); */
-#define H_NEXT 6 /* , void); */
-#define H_CURR 8 /* , const int); */
-#define H_SET 7 /* , void); */
-#define H_ADD 9 /* , const char *); */
-#define H_ENTER 10 /* , const char *); */
-#define H_APPEND 11 /* , const char *); */
-#define H_END 12 /* , void); */
-#define H_NEXT_STR 13 /* , const char *); */
-#define H_PREV_STR 14 /* , const char *); */
-#define H_NEXT_EVENT 15 /* , const int); */
-#define H_PREV_EVENT 16 /* , const int); */
-#define H_LOAD 17 /* , const char *); */
-#define H_SAVE 18 /* , const char *); */
-#define H_CLEAR 19 /* , void); */
-
-#endif /* _HISTEDIT_H_ */
diff --git a/main/editline/history.c b/main/editline/history.c
deleted file mode 100644
index f133d2eb0..000000000
--- a/main/editline/history.c
+++ /dev/null
@@ -1,875 +0,0 @@
-/* $NetBSD: history.c,v 1.19 2002/03/18 16:00:54 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: history.c,v 1.19 2002/03/18 16:00:54 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * hist.c: History access functions
- */
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#ifdef HAVE_VIS_H
-#include <vis.h>
-#else
-#include "np/vis.h"
-#endif
-#include <sys/stat.h>
-
-static const char hist_cookie[] = "_HiStOrY_V2_\n";
-
-#include "histedit.h"
-
-typedef int (*history_gfun_t)(ptr_t, HistEvent *);
-typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *);
-typedef void (*history_vfun_t)(ptr_t, HistEvent *);
-typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int);
-
-struct history {
- ptr_t h_ref; /* Argument for history fcns */
- int h_ent; /* Last entry point for history */
- history_gfun_t h_first; /* Get the first element */
- history_gfun_t h_next; /* Get the next element */
- history_gfun_t h_last; /* Get the last element */
- history_gfun_t h_prev; /* Get the previous element */
- history_gfun_t h_curr; /* Get the current element */
- history_sfun_t h_set; /* Set the current element */
- history_vfun_t h_clear; /* Clear the history list */
- history_efun_t h_enter; /* Add an element */
- history_efun_t h_add; /* Append to an element */
-};
-#define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
-#define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
-#define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
-#define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
-#define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
-#define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
-#define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
-#define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
-#define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
-
-#define h_malloc(a) malloc(a)
-#define h_realloc(a, b) realloc((a), (b))
-#define h_free(a) free(a)
-
-typedef struct {
- int num;
- char *str;
-} HistEventPrivate;
-
-
-
-private int history_setsize(History *, HistEvent *, int);
-private int history_getsize(History *, HistEvent *);
-private int history_set_fun(History *, History *);
-private int history_load(History *, const char *);
-private int history_save(History *, const char *);
-private int history_prev_event(History *, HistEvent *, int);
-private int history_next_event(History *, HistEvent *, int);
-private int history_next_string(History *, HistEvent *, const char *);
-private int history_prev_string(History *, HistEvent *, const char *);
-
-
-/***********************************************************************/
-
-/*
- * Builtin- history implementation
- */
-typedef struct hentry_t {
- HistEvent ev; /* What we return */
- struct hentry_t *next; /* Next entry */
- struct hentry_t *prev; /* Previous entry */
-} hentry_t;
-
-typedef struct history_t {
- hentry_t list; /* Fake list header element */
- hentry_t *cursor; /* Current element in the list */
- int max; /* Maximum number of events */
- int cur; /* Current number of events */
- int eventid; /* For generation of unique event id */
-} history_t;
-
-private int history_def_first(ptr_t, HistEvent *);
-private int history_def_last(ptr_t, HistEvent *);
-private int history_def_next(ptr_t, HistEvent *);
-private int history_def_prev(ptr_t, HistEvent *);
-private int history_def_curr(ptr_t, HistEvent *);
-private int history_def_set(ptr_t, HistEvent *, const int n);
-private int history_def_enter(ptr_t, HistEvent *, const char *);
-private int history_def_add(ptr_t, HistEvent *, const char *);
-private void history_def_init(ptr_t *, HistEvent *, int);
-private void history_def_clear(ptr_t, HistEvent *);
-private int history_def_insert(history_t *, HistEvent *, const char *);
-private void history_def_delete(history_t *, HistEvent *, hentry_t *);
-
-#define history_def_setsize(p, num)(void) (((history_t *) p)->max = (num))
-#define history_def_getsize(p) (((history_t *) p)->cur)
-
-#define he_strerror(code) he_errlist[code]
-#define he_seterrev(evp, code) {\
- evp->num = code;\
- evp->str = he_strerror(code);\
- }
-
-/* error messages */
-static const char *const he_errlist[] = {
- "OK",
- "unknown error",
- "malloc() failed",
- "first event not found",
- "last event not found",
- "empty list",
- "no next event",
- "no previous event",
- "current event is invalid",
- "event not found",
- "can't read history from file",
- "can't write history",
- "required parameter(s) not supplied",
- "history size negative",
- "function not allowed with other history-functions-set the default",
- "bad parameters"
-};
-/* error codes */
-#define _HE_OK 0
-#define _HE_UNKNOWN 1
-#define _HE_MALLOC_FAILED 2
-#define _HE_FIRST_NOTFOUND 3
-#define _HE_LAST_NOTFOUND 4
-#define _HE_EMPTY_LIST 5
-#define _HE_END_REACHED 6
-#define _HE_START_REACHED 7
-#define _HE_CURR_INVALID 8
-#define _HE_NOT_FOUND 9
-#define _HE_HIST_READ 10
-#define _HE_HIST_WRITE 11
-#define _HE_PARAM_MISSING 12
-#define _HE_SIZE_NEGATIVE 13
-#define _HE_NOT_ALLOWED 14
-#define _HE_BAD_PARAM 15
-
-/* history_def_first():
- * Default function to return the first event in the history.
- */
-private int
-history_def_first(ptr_t p, HistEvent *ev)
-{
- history_t *h = (history_t *) p;
-
- h->cursor = h->list.next;
- if (h->cursor != &h->list)
- *ev = h->cursor->ev;
- else {
- he_seterrev(ev, _HE_FIRST_NOTFOUND);
- return (-1);
- }
-
- return (0);
-}
-
-
-/* history_def_last():
- * Default function to return the last event in the history.
- */
-private int
-history_def_last(ptr_t p, HistEvent *ev)
-{
- history_t *h = (history_t *) p;
-
- h->cursor = h->list.prev;
- if (h->cursor != &h->list)
- *ev = h->cursor->ev;
- else {
- he_seterrev(ev, _HE_LAST_NOTFOUND);
- return (-1);
- }
-
- return (0);
-}
-
-
-/* history_def_next():
- * Default function to return the next event in the history.
- */
-private int
-history_def_next(ptr_t p, HistEvent *ev)
-{
- history_t *h = (history_t *) p;
-
- if (h->cursor != &h->list)
- h->cursor = h->cursor->next;
- else {
- he_seterrev(ev, _HE_EMPTY_LIST);
- return (-1);
- }
-
- if (h->cursor != &h->list)
- *ev = h->cursor->ev;
- else {
- he_seterrev(ev, _HE_END_REACHED);
- return (-1);
- }
-
- return (0);
-}
-
-
-/* history_def_prev():
- * Default function to return the previous event in the history.
- */
-private int
-history_def_prev(ptr_t p, HistEvent *ev)
-{
- history_t *h = (history_t *) p;
-
- if (h->cursor != &h->list)
- h->cursor = h->cursor->prev;
- else {
- he_seterrev(ev,
- (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
- return (-1);
- }
-
- if (h->cursor != &h->list)
- *ev = h->cursor->ev;
- else {
- he_seterrev(ev, _HE_START_REACHED);
- return (-1);
- }
-
- return (0);
-}
-
-
-/* history_def_curr():
- * Default function to return the current event in the history.
- */
-private int
-history_def_curr(ptr_t p, HistEvent *ev)
-{
- history_t *h = (history_t *) p;
-
- if (h->cursor != &h->list)
- *ev = h->cursor->ev;
- else {
- he_seterrev(ev,
- (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
- return (-1);
- }
-
- return (0);
-}
-
-
-/* history_def_set():
- * Default function to set the current event in the history to the
- * given one.
- */
-private int
-history_def_set(ptr_t p, HistEvent *ev, const int n)
-{
- history_t *h = (history_t *) p;
-
- if (h->cur == 0) {
- he_seterrev(ev, _HE_EMPTY_LIST);
- return (-1);
- }
- if (h->cursor == &h->list || h->cursor->ev.num != n) {
- for (h->cursor = h->list.next; h->cursor != &h->list;
- h->cursor = h->cursor->next)
- if (h->cursor->ev.num == n)
- break;
- }
- if (h->cursor == &h->list) {
- he_seterrev(ev, _HE_NOT_FOUND);
- return (-1);
- }
- return (0);
-}
-
-
-/* history_def_add():
- * Append string to element
- */
-private int
-history_def_add(ptr_t p, HistEvent *ev, const char *str)
-{
- history_t *h = (history_t *) p;
- size_t len;
- char *s;
- HistEventPrivate *evp = (void *)&h->cursor->ev;
-
- if (h->cursor == &h->list)
- return (history_def_enter(p, ev, str));
- len = strlen(evp->str) + strlen(str) + 1;
- s = (char *) h_malloc(len);
- if (!s) {
- he_seterrev(ev, _HE_MALLOC_FAILED);
- return (-1);
- }
- (void) strlcpy(s, h->cursor->ev.str, len);
- (void) strlcat(s, str, len);
- h_free(evp->str);
- evp->str = s;
- *ev = h->cursor->ev;
- return (0);
-}
-
-
-/* history_def_delete():
- * Delete element hp of the h list
- */
-/* ARGSUSED */
-private void
-history_def_delete(history_t *h, HistEvent *ev, hentry_t *hp)
-{
- HistEventPrivate *evp = (void *)&hp->ev;
- if (hp == &h->list)
- abort();
- hp->prev->next = hp->next;
- hp->next->prev = hp->prev;
- h_free((ptr_t) evp->str);
- h_free(hp);
- h->cur--;
-}
-
-
-/* history_def_insert():
- * Insert element with string str in the h list
- */
-private int
-history_def_insert(history_t *h, HistEvent *ev, const char *str)
-{
-
- h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
- if (h->cursor)
- h->cursor->ev.str = strdup(str);
- if (!h->cursor || !h->cursor->ev.str) {
- he_seterrev(ev, _HE_MALLOC_FAILED);
- return (-1);
- }
- h->cursor->ev.num = ++h->eventid;
- h->cursor->next = h->list.next;
- h->cursor->prev = &h->list;
- h->list.next->prev = h->cursor;
- h->list.next = h->cursor;
- h->cur++;
-
- *ev = h->cursor->ev;
- return (0);
-}
-
-
-/* history_def_enter():
- * Default function to enter an item in the history
- */
-private int
-history_def_enter(ptr_t p, HistEvent *ev, const char *str)
-{
- history_t *h = (history_t *) p;
-
- if (history_def_insert(h, ev, str) == -1)
- return (-1); /* error, keep error message */
-
- /*
- * Always keep at least one entry.
- * This way we don't have to check for the empty list.
- */
- while (h->cur > h->max && h->cur > 0)
- history_def_delete(h, ev, h->list.prev);
-
- return (0);
-}
-
-
-/* history_def_init():
- * Default history initialization function
- */
-/* ARGSUSED */
-private void
-history_def_init(ptr_t *p, HistEvent *ev, int n)
-{
- history_t *h = (history_t *) h_malloc(sizeof(history_t));
-
- if (n <= 0)
- n = 0;
- h->eventid = 0;
- h->cur = 0;
- h->max = n;
- h->list.next = h->list.prev = &h->list;
- h->list.ev.str = NULL;
- h->list.ev.num = 0;
- h->cursor = &h->list;
- *p = (ptr_t) h;
-}
-
-
-/* history_def_clear():
- * Default history cleanup function
- */
-private void
-history_def_clear(ptr_t p, HistEvent *ev)
-{
- history_t *h = (history_t *) p;
-
- while (h->list.prev != &h->list)
- history_def_delete(h, ev, h->list.prev);
- h->eventid = 0;
- h->cur = 0;
-}
-
-
-
-
-/************************************************************************/
-
-/* history_init():
- * Initialization function.
- */
-public History *
-history_init(void)
-{
- History *h = (History *) h_malloc(sizeof(History));
- HistEvent ev;
-
- history_def_init(&h->h_ref, &ev, 0);
- h->h_ent = -1;
- h->h_next = history_def_next;
- h->h_first = history_def_first;
- h->h_last = history_def_last;
- h->h_prev = history_def_prev;
- h->h_curr = history_def_curr;
- h->h_set = history_def_set;
- h->h_clear = history_def_clear;
- h->h_enter = history_def_enter;
- h->h_add = history_def_add;
-
- return (h);
-}
-
-
-/* history_end():
- * clean up history;
- */
-public void
-history_end(History *h)
-{
- HistEvent ev;
-
- if (h->h_next == history_def_next)
- history_def_clear(h->h_ref, &ev);
-}
-
-
-
-/* history_setsize():
- * Set history number of events
- */
-private int
-history_setsize(History *h, HistEvent *ev, int num)
-{
-
- if (h->h_next != history_def_next) {
- he_seterrev(ev, _HE_NOT_ALLOWED);
- return (-1);
- }
- if (num < 0) {
- he_seterrev(ev, _HE_BAD_PARAM);
- return (-1);
- }
- history_def_setsize(h->h_ref, num);
- return (0);
-}
-
-
-/* history_getsize():
- * Get number of events currently in history
- */
-private int
-history_getsize(History *h, HistEvent *ev)
-{
- int retval = 0;
-
- if (h->h_next != history_def_next) {
- he_seterrev(ev, _HE_NOT_ALLOWED);
- return (-1);
- }
- retval = history_def_getsize(h->h_ref);
- if (retval < -1) {
- he_seterrev(ev, _HE_SIZE_NEGATIVE);
- return (-1);
- }
- ev->num = retval;
- return (0);
-}
-
-
-/* history_set_fun():
- * Set history functions
- */
-private int
-history_set_fun(History *h, History *nh)
-{
- HistEvent ev;
-
- if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
- nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
- nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
- nh->h_ref == NULL) {
- if (h->h_next != history_def_next) {
- history_def_init(&h->h_ref, &ev, 0);
- h->h_first = history_def_first;
- h->h_next = history_def_next;
- h->h_last = history_def_last;
- h->h_prev = history_def_prev;
- h->h_curr = history_def_curr;
- h->h_set = history_def_set;
- h->h_clear = history_def_clear;
- h->h_enter = history_def_enter;
- h->h_add = history_def_add;
- }
- return (-1);
- }
- if (h->h_next == history_def_next)
- history_def_clear(h->h_ref, &ev);
-
- h->h_ent = -1;
- h->h_first = nh->h_first;
- h->h_next = nh->h_next;
- h->h_last = nh->h_last;
- h->h_prev = nh->h_prev;
- h->h_curr = nh->h_curr;
- h->h_set = nh->h_set;
- h->h_clear = nh->h_clear;
- h->h_enter = nh->h_enter;
- h->h_add = nh->h_add;
-
- return (0);
-}
-
-
-/* history_load():
- * History load function
- */
-private int
-history_load(History *h, const char *fname)
-{
- FILE *fp;
- char *line;
- size_t sz, max_size;
- char *ptr;
- int i = -1;
- HistEvent ev;
-
- if ((fp = fopen(fname, "r")) == NULL)
- return (i);
-
- if ((line = fgetln(fp, &sz)) == NULL)
- goto done;
-
- if (strncmp(line, hist_cookie, sz) != 0)
- goto done;
-
- ptr = h_malloc(max_size = 1024);
- for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
- char c = line[sz];
-
- if (sz != 0 && line[sz - 1] == '\n')
- line[--sz] = '\0';
- else
- line[sz] = '\0';
-
- if (max_size < sz) {
- max_size = (sz + 1023) & ~1023;
- ptr = h_realloc(ptr, max_size);
- }
- (void) strunvis(ptr, line);
- line[sz] = c;
- HENTER(h, &ev, ptr);
- }
- h_free(ptr);
-
-done:
- (void) fclose(fp);
- return (i);
-}
-
-
-/* history_save():
- * History save function
- */
-private int
-history_save(History *h, const char *fname)
-{
- FILE *fp;
- HistEvent ev;
- int i = 0, retval;
- size_t len, max_size;
- char *ptr;
-
- if ((fp = fopen(fname, "w")) == NULL)
- return (-1);
-
- (void) fchmod(fileno(fp), S_IRUSR|S_IWUSR);
- (void) fputs(hist_cookie, fp);
- ptr = h_malloc(max_size = 1024);
- for (retval = HLAST(h, &ev);
- retval != -1;
- retval = HPREV(h, &ev), i++) {
- len = strlen(ev.str) * 4;
- if (len >= max_size) {
- max_size = (len + 1023) & 1023;
- ptr = h_realloc(ptr, max_size);
- }
- (void) strvis(ptr, ev.str, VIS_WHITE);
- (void) fprintf(fp, "%s\n", ev.str);
- }
- h_free(ptr);
- (void) fclose(fp);
- return (i);
-}
-
-
-/* history_prev_event():
- * Find the previous event, with number given
- */
-private int
-history_prev_event(History *h, HistEvent *ev, int num)
-{
- int retval;
-
- for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
- if (ev->num == num)
- return (0);
-
- he_seterrev(ev, _HE_NOT_FOUND);
- return (-1);
-}
-
-
-/* history_next_event():
- * Find the next event, with number given
- */
-private int
-history_next_event(History *h, HistEvent *ev, int num)
-{
- int retval;
-
- for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
- if (ev->num == num)
- return (0);
-
- he_seterrev(ev, _HE_NOT_FOUND);
- return (-1);
-}
-
-
-/* history_prev_string():
- * Find the previous event beginning with string
- */
-private int
-history_prev_string(History *h, HistEvent *ev, const char *str)
-{
- size_t len = strlen(str);
- int retval;
-
- for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
- if (strncmp(str, ev->str, len) == 0)
- return (0);
-
- he_seterrev(ev, _HE_NOT_FOUND);
- return (-1);
-}
-
-
-/* history_next_string():
- * Find the next event beginning with string
- */
-private int
-history_next_string(History *h, HistEvent *ev, const char *str)
-{
- size_t len = strlen(str);
- int retval;
-
- for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
- if (strncmp(str, ev->str, len) == 0)
- return (0);
-
- he_seterrev(ev, _HE_NOT_FOUND);
- return (-1);
-}
-
-
-/* history():
- * User interface to history functions.
- */
-int
-history(History *h, HistEvent *ev, int fun, ...)
-{
- va_list va;
- const char *str;
- int retval;
-
- va_start(va, fun);
-
- he_seterrev(ev, _HE_OK);
-
- switch (fun) {
- case H_GETSIZE:
- retval = history_getsize(h, ev);
- break;
-
- case H_SETSIZE:
- retval = history_setsize(h, ev, va_arg(va, int));
- break;
-
- case H_ADD:
- str = va_arg(va, const char *);
- retval = HADD(h, ev, str);
- break;
-
- case H_ENTER:
- str = va_arg(va, const char *);
- if ((retval = HENTER(h, ev, str)) != -1)
- h->h_ent = ev->num;
- break;
-
- case H_APPEND:
- str = va_arg(va, const char *);
- if ((retval = HSET(h, ev, h->h_ent)) != -1)
- retval = HADD(h, ev, str);
- break;
-
- case H_FIRST:
- retval = HFIRST(h, ev);
- break;
-
- case H_NEXT:
- retval = HNEXT(h, ev);
- break;
-
- case H_LAST:
- retval = HLAST(h, ev);
- break;
-
- case H_PREV:
- retval = HPREV(h, ev);
- break;
-
- case H_CURR:
- retval = HCURR(h, ev);
- break;
-
- case H_SET:
- retval = HSET(h, ev, va_arg(va, const int));
- break;
-
- case H_CLEAR:
- HCLEAR(h, ev);
- retval = 0;
- break;
-
- case H_LOAD:
- retval = history_load(h, va_arg(va, const char *));
- if (retval == -1)
- he_seterrev(ev, _HE_HIST_READ);
- break;
-
- case H_SAVE:
- retval = history_save(h, va_arg(va, const char *));
- if (retval == -1)
- he_seterrev(ev, _HE_HIST_WRITE);
- break;
-
- case H_PREV_EVENT:
- retval = history_prev_event(h, ev, va_arg(va, int));
- break;
-
- case H_NEXT_EVENT:
- retval = history_next_event(h, ev, va_arg(va, int));
- break;
-
- case H_PREV_STR:
- retval = history_prev_string(h, ev, va_arg(va, const char *));
- break;
-
- case H_NEXT_STR:
- retval = history_next_string(h, ev, va_arg(va, const char *));
- break;
-
- case H_FUNC:
- {
- History hf;
-
- hf.h_ref = va_arg(va, ptr_t);
- h->h_ent = -1;
- hf.h_first = va_arg(va, history_gfun_t);
- hf.h_next = va_arg(va, history_gfun_t);
- hf.h_last = va_arg(va, history_gfun_t);
- hf.h_prev = va_arg(va, history_gfun_t);
- hf.h_curr = va_arg(va, history_gfun_t);
- hf.h_set = va_arg(va, history_sfun_t);
- hf.h_clear = va_arg(va, history_vfun_t);
- hf.h_enter = va_arg(va, history_efun_t);
- hf.h_add = va_arg(va, history_efun_t);
-
- if ((retval = history_set_fun(h, &hf)) == -1)
- he_seterrev(ev, _HE_PARAM_MISSING);
- break;
- }
-
- case H_END:
- history_end(h);
- retval = 0;
- break;
-
- default:
- retval = -1;
- he_seterrev(ev, _HE_UNKNOWN);
- break;
- }
- va_end(va);
- return (retval);
-}
diff --git a/main/editline/install-sh b/main/editline/install-sh
deleted file mode 100755
index ebc66913e..000000000
--- a/main/editline/install-sh
+++ /dev/null
@@ -1,250 +0,0 @@
-#! /bin/sh
-#
-# install - install a program, script, or datafile
-# This comes from X11R5 (mit/util/scripts/install.sh).
-#
-# Copyright 1991 by the Massachusetts Institute of Technology
-#
-# Permission to use, copy, modify, distribute, and sell this software and its
-# documentation for any purpose is hereby granted without fee, provided that
-# the above copyright notice appear in all copies and that both that
-# copyright notice and this permission notice appear in supporting
-# documentation, and that the name of M.I.T. not be used in advertising or
-# publicity pertaining to distribution of the software without specific,
-# written prior permission. M.I.T. makes no representations about the
-# suitability of this software for any purpose. It is provided "as is"
-# without express or implied warranty.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch. It can only install one file at a time, a restriction
-# shared with many OS's install programs.
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-transformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
- case $1 in
- -c) instcmd="$cpprog"
- shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd="$stripprog"
- shift
- continue;;
-
- -t=*) transformarg=`echo $1 | sed 's/-t=//'`
- shift
- continue;;
-
- -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
- shift
- continue;;
-
- *) if [ x"$src" = x ]
- then
- src=$1
- else
- # this colon is to work around a 386BSD /bin/sh bug
- :
- dst=$1
- fi
- shift
- continue;;
- esac
-done
-
-if [ x"$src" = x ]
-then
- echo "install: no input file specified"
- exit 1
-else
- true
-fi
-
-if [ x"$dir_arg" != x ]; then
- dst=$src
- src=""
-
- if [ -d $dst ]; then
- instcmd=:
- else
- instcmd=mkdir
- fi
-else
-
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
-# if $src (and thus $dsttmp) contains '*'.
-
- if [ -f $src -o -d $src ]
- then
- true
- else
- echo "install: $src does not exist"
- exit 1
- fi
-
- if [ x"$dst" = x ]
- then
- echo "install: no destination specified"
- exit 1
- else
- true
- fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
- if [ -d $dst ]
- then
- dst="$dst"/`basename $src`
- else
- true
- fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-# this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='
-'
-IFS="${IFS-${defaultIFS}}"
-
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
-
-pathcomp=''
-
-while [ $# -ne 0 ] ; do
- pathcomp="${pathcomp}${1}"
- shift
-
- if [ ! -d "${pathcomp}" ] ;
- then
- $mkdirprog "${pathcomp}"
- else
- true
- fi
-
- pathcomp="${pathcomp}/"
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
- $doit $instcmd $dst &&
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
- if [ x"$transformarg" = x ]
- then
- dstfile=`basename $dst`
- else
- dstfile=`basename $dst $transformbasename |
- sed $transformarg`$transformbasename
- fi
-
-# don't allow the sed command to completely eliminate the filename
-
- if [ x"$dstfile" = x ]
- then
- dstfile=`basename $dst`
- else
- true
- fi
-
-# Make a temp file name in the proper directory.
-
- dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
- $doit $instcmd $src $dsttmp &&
-
- trap "rm -f ${dsttmp}" 0 &&
-
-# and set any options; do chmod last to preserve setuid bits
-
-# If any of these fail, we abort the whole thing. If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
-
-# Now rename the file to the real destination.
-
- $doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
-
-fi &&
-
-
-exit 0
diff --git a/main/editline/key.c b/main/editline/key.c
deleted file mode 100644
index 0dcdf4191..000000000
--- a/main/editline/key.c
+++ /dev/null
@@ -1,687 +0,0 @@
-/* $NetBSD: key.c,v 1.13 2002/03/18 16:00:55 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: key.c,v 1.13 2002/03/18 16:00:55 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * key.c: This module contains the procedures for maintaining
- * the extended-key map.
- *
- * An extended-key (key) is a sequence of keystrokes introduced
- * with an sequence introducer and consisting of an arbitrary
- * number of characters. This module maintains a map (the el->el_key.map)
- * to convert these extended-key sequences into input strs
- * (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
- *
- * Warning:
- * If key is a substr of some other keys, then the longer
- * keys are lost!! That is, if the keys "abcd" and "abcef"
- * are in el->el_key.map, adding the key "abc" will cause the first two
- * definitions to be lost.
- *
- * Restrictions:
- * -------------
- * 1) It is not possible to have one key that is a
- * substr of another.
- */
-#include <string.h>
-#include <stdlib.h>
-
-#include "el.h"
-
-/*
- * The Nodes of the el->el_key.map. The el->el_key.map is a linked list
- * of these node elements
- */
-struct key_node_t {
- char ch; /* single character of key */
- int type; /* node type */
- key_value_t val; /* command code or pointer to str, */
- /* if this is a leaf */
- struct key_node_t *next; /* ptr to next char of this key */
- struct key_node_t *sibling; /* ptr to another key with same prefix*/
-};
-
-private int node_trav(EditLine *, key_node_t *, char *,
- key_value_t *);
-private int node__try(EditLine *, key_node_t *, const char *,
- key_value_t *, int);
-private key_node_t *node__get(int);
-private void node__put(EditLine *, key_node_t *);
-private int node__delete(EditLine *, key_node_t **, const char *);
-private int node_lookup(EditLine *, const char *, key_node_t *,
- int);
-private int node_enum(EditLine *, key_node_t *, int);
-private int key__decode_char(char *, int, int);
-
-#define KEY_BUFSIZ EL_BUFSIZ
-
-
-/* key_init():
- * Initialize the key maps
- */
-protected int
-key_init(EditLine *el)
-{
-
- el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ);
- if (el->el_key.buf == NULL)
- return (-1);
- el->el_key.map = NULL;
- key_reset(el);
- return (0);
-}
-
-
-/* key_end():
- * Free the key maps
- */
-protected void
-key_end(EditLine *el)
-{
-
- el_free((ptr_t) el->el_key.buf);
- el->el_key.buf = NULL;
- node__put(el, el->el_key.map);
- el->el_key.map = NULL;
-}
-
-
-/* key_map_cmd():
- * Associate cmd with a key value
- */
-protected key_value_t *
-key_map_cmd(EditLine *el, int cmd)
-{
-
- el->el_key.val.cmd = (el_action_t) cmd;
- return (&el->el_key.val);
-}
-
-
-/* key_map_str():
- * Associate str with a key value
- */
-protected key_value_t *
-key_map_str(EditLine *el, char *str)
-{
-
- el->el_key.val.str = str;
- return (&el->el_key.val);
-}
-
-
-/* key_reset():
- * Takes all nodes on el->el_key.map and puts them on free list. Then
- * initializes el->el_key.map with arrow keys
- * [Always bind the ansi arrow keys?]
- */
-protected void
-key_reset(EditLine *el)
-{
-
- node__put(el, el->el_key.map);
- el->el_key.map = NULL;
- return;
-}
-
-
-/* key_get():
- * Calls the recursive function with entry point el->el_key.map
- * Looks up *ch in map and then reads characters until a
- * complete match is found or a mismatch occurs. Returns the
- * type of the match found (XK_STR, XK_CMD, or XK_EXE).
- * Returns NULL in val.str and XK_STR for no match.
- * The last character read is returned in *ch.
- */
-protected int
-key_get(EditLine *el, char *ch, key_value_t *val)
-{
-
- return (node_trav(el, el->el_key.map, ch, val));
-}
-
-
-/* key_add():
- * Adds key to the el->el_key.map and associates the value in val with it.
- * If key is already is in el->el_key.map, the new code is applied to the
- * existing key. Ntype specifies if code is a command, an
- * out str or a unix command.
- */
-protected void
-key_add(EditLine *el, const char *key, key_value_t *val, int ntype)
-{
-
- if (key[0] == '\0') {
- (void) fprintf(el->el_errfile,
- "key_add: Null extended-key not allowed.\n");
- return;
- }
- if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) {
- (void) fprintf(el->el_errfile,
- "key_add: sequence-lead-in command not allowed\n");
- return;
- }
- if (el->el_key.map == NULL)
- /* tree is initially empty. Set up new node to match key[0] */
- el->el_key.map = node__get(key[0]);
- /* it is properly initialized */
-
- /* Now recurse through el->el_key.map */
- (void) node__try(el, el->el_key.map, key, val, ntype);
- return;
-}
-
-
-/* key_clear():
- *
- */
-protected void
-key_clear(EditLine *el, el_action_t *map, const char *in)
-{
-
- if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) &&
- ((map == el->el_map.key &&
- el->el_map.alt[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN) ||
- (map == el->el_map.alt &&
- el->el_map.key[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN)))
- (void) key_delete(el, in);
-}
-
-
-/* key_delete():
- * Delete the key and all longer keys staring with key, if
- * they exists.
- */
-protected int
-key_delete(EditLine *el, const char *key)
-{
-
- if (key[0] == '\0') {
- (void) fprintf(el->el_errfile,
- "key_delete: Null extended-key not allowed.\n");
- return (-1);
- }
- if (el->el_key.map == NULL)
- return (0);
-
- (void) node__delete(el, &el->el_key.map, key);
- return (0);
-}
-
-
-/* key_print():
- * Print the binding associated with key key.
- * Print entire el->el_key.map if null
- */
-protected void
-key_print(EditLine *el, const char *key)
-{
-
- /* do nothing if el->el_key.map is empty and null key specified */
- if (el->el_key.map == NULL && *key == 0)
- return;
-
- el->el_key.buf[0] = '"';
- if (node_lookup(el, key, el->el_key.map, 1) <= -1)
- /* key is not bound */
- (void) fprintf(el->el_errfile, "Unbound extended key \"%s\"\n",
- key);
- return;
-}
-
-
-/* node_trav():
- * recursively traverses node in tree until match or mismatch is
- * found. May read in more characters.
- */
-private int
-node_trav(EditLine *el, key_node_t *ptr, char *ch, key_value_t *val)
-{
-
- if (ptr->ch == *ch) {
- /* match found */
- if (ptr->next) {
- /* key not complete so get next char */
- if (el_getc(el, ch) != 1) { /* if EOF or error */
- val->cmd = ED_END_OF_FILE;
- return (XK_CMD);
- /* PWP: Pretend we just read an end-of-file */
- }
- return (node_trav(el, ptr->next, ch, val));
- } else {
- *val = ptr->val;
- if (ptr->type != XK_CMD)
- *ch = '\0';
- return (ptr->type);
- }
- } else {
- /* no match found here */
- if (ptr->sibling) {
- /* try next sibling */
- return (node_trav(el, ptr->sibling, ch, val));
- } else {
- /* no next sibling -- mismatch */
- val->str = NULL;
- return (XK_STR);
- }
- }
-}
-
-
-/* node__try():
- * Find a node that matches *str or allocate a new one
- */
-private int
-node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int ntype)
-{
-
- if (ptr->ch != *str) {
- key_node_t *xm;
-
- for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
- if (xm->sibling->ch == *str)
- break;
- if (xm->sibling == NULL)
- xm->sibling = node__get(*str); /* setup new node */
- ptr = xm->sibling;
- }
- if (*++str == '\0') {
- /* we're there */
- if (ptr->next != NULL) {
- node__put(el, ptr->next);
- /* lose longer keys with this prefix */
- ptr->next = NULL;
- }
- switch (ptr->type) {
- case XK_CMD:
- case XK_NOD:
- break;
- case XK_STR:
- case XK_EXE:
- if (ptr->val.str)
- el_free((ptr_t) ptr->val.str);
- break;
- default:
- EL_ABORT((el->el_errfile, "Bad XK_ type %d\n",
- ptr->type));
- break;
- }
-
- switch (ptr->type = ntype) {
- case XK_CMD:
- ptr->val = *val;
- break;
- case XK_STR:
- case XK_EXE:
- ptr->val.str = strdup(val->str);
- break;
- default:
- EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
- break;
- }
- } else {
- /* still more chars to go */
- if (ptr->next == NULL)
- ptr->next = node__get(*str); /* setup new node */
- (void) node__try(el, ptr->next, str, val, ntype);
- }
- return (0);
-}
-
-
-/* node__delete():
- * Delete node that matches str
- */
-private int
-node__delete(EditLine *el, key_node_t **inptr, const char *str)
-{
- key_node_t *ptr;
- key_node_t *prev_ptr = NULL;
-
- ptr = *inptr;
-
- if (ptr->ch != *str) {
- key_node_t *xm;
-
- for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
- if (xm->sibling->ch == *str)
- break;
- if (xm->sibling == NULL)
- return (0);
- prev_ptr = xm;
- ptr = xm->sibling;
- }
- if (*++str == '\0') {
- /* we're there */
- if (prev_ptr == NULL)
- *inptr = ptr->sibling;
- else
- prev_ptr->sibling = ptr->sibling;
- ptr->sibling = NULL;
- node__put(el, ptr);
- return (1);
- } else if (ptr->next != NULL &&
- node__delete(el, &ptr->next, str) == 1) {
- if (ptr->next != NULL)
- return (0);
- if (prev_ptr == NULL)
- *inptr = ptr->sibling;
- else
- prev_ptr->sibling = ptr->sibling;
- ptr->sibling = NULL;
- node__put(el, ptr);
- return (1);
- } else {
- return (0);
- }
-}
-
-
-/* node__put():
- * Puts a tree of nodes onto free list using free(3).
- */
-private void
-node__put(EditLine *el, key_node_t *ptr)
-{
- if (ptr == NULL)
- return;
-
- if (ptr->next != NULL) {
- node__put(el, ptr->next);
- ptr->next = NULL;
- }
- node__put(el, ptr->sibling);
-
- switch (ptr->type) {
- case XK_CMD:
- case XK_NOD:
- break;
- case XK_EXE:
- case XK_STR:
- if (ptr->val.str != NULL)
- el_free((ptr_t) ptr->val.str);
- break;
- default:
- EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ptr->type));
- break;
- }
- el_free((ptr_t) ptr);
-}
-
-
-/* node__get():
- * Returns pointer to an key_node_t for ch.
- */
-private key_node_t *
-node__get(int ch)
-{
- key_node_t *ptr;
-
- ptr = (key_node_t *) el_malloc((size_t) sizeof(key_node_t));
- if (ptr == NULL)
- return NULL;
- ptr->ch = ch;
- ptr->type = XK_NOD;
- ptr->val.str = NULL;
- ptr->next = NULL;
- ptr->sibling = NULL;
- return (ptr);
-}
-
-
-
-/* node_lookup():
- * look for the str starting at node ptr.
- * Print if last node
- */
-private int
-node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt)
-{
- int ncnt;
-
- if (ptr == NULL)
- return (-1); /* cannot have null ptr */
-
- if (*str == 0) {
- /* no more chars in str. node_enum from here. */
- (void) node_enum(el, ptr, cnt);
- return (0);
- } else {
- /* If match put this char into el->el_key.buf. Recurse */
- if (ptr->ch == *str) {
- /* match found */
- ncnt = key__decode_char(el->el_key.buf, cnt,
- (unsigned char) ptr->ch);
- if (ptr->next != NULL)
- /* not yet at leaf */
- return (node_lookup(el, str + 1, ptr->next,
- ncnt + 1));
- else {
- /* next node is null so key should be complete */
- if (str[1] == 0) {
- el->el_key.buf[ncnt + 1] = '"';
- el->el_key.buf[ncnt + 2] = '\0';
- key_kprint(el, el->el_key.buf,
- &ptr->val, ptr->type);
- return (0);
- } else
- return (-1);
- /* mismatch -- str still has chars */
- }
- } else {
- /* no match found try sibling */
- if (ptr->sibling)
- return (node_lookup(el, str, ptr->sibling,
- cnt));
- else
- return (-1);
- }
- }
-}
-
-
-/* node_enum():
- * Traverse the node printing the characters it is bound in buffer
- */
-private int
-node_enum(EditLine *el, key_node_t *ptr, int cnt)
-{
- int ncnt;
-
- if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */
- el->el_key.buf[++cnt] = '"';
- el->el_key.buf[++cnt] = '\0';
- (void) fprintf(el->el_errfile,
- "Some extended keys too long for internal print buffer");
- (void) fprintf(el->el_errfile, " \"%s...\"\n", el->el_key.buf);
- return (0);
- }
- if (ptr == NULL) {
-#ifdef DEBUG_EDIT
- (void) fprintf(el->el_errfile,
- "node_enum: BUG!! Null ptr passed\n!");
-#endif
- return (-1);
- }
- /* put this char at end of str */
- ncnt = key__decode_char(el->el_key.buf, cnt, (unsigned char) ptr->ch);
- if (ptr->next == NULL) {
- /* print this key and function */
- el->el_key.buf[ncnt + 1] = '"';
- el->el_key.buf[ncnt + 2] = '\0';
- key_kprint(el, el->el_key.buf, &ptr->val, ptr->type);
- } else
- (void) node_enum(el, ptr->next, ncnt + 1);
-
- /* go to sibling if there is one */
- if (ptr->sibling)
- (void) node_enum(el, ptr->sibling, cnt);
- return (0);
-}
-
-
-/* key_kprint():
- * Print the specified key and its associated
- * function specified by val
- */
-protected void
-key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype)
-{
- el_bindings_t *fp;
- char unparsbuf[EL_BUFSIZ];
- static const char fmt[] = "%-15s-> %s\n";
-
- if (val != NULL)
- switch (ntype) {
- case XK_STR:
- case XK_EXE:
- (void) fprintf(el->el_outfile, fmt, key,
- key__decode_str(val->str, unparsbuf,
- ntype == XK_STR ? "\"\"" : "[]"));
- break;
- case XK_CMD:
- for (fp = el->el_map.help; fp->name; fp++)
- if (val->cmd == fp->func) {
- (void) fprintf(el->el_outfile, fmt,
- key, fp->name);
- break;
- }
-#ifdef DEBUG_KEY
- if (fp->name == NULL)
- (void) fprintf(el->el_outfile,
- "BUG! Command not found.\n");
-#endif
-
- break;
- default:
- EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
- break;
- }
- else
- (void) fprintf(el->el_outfile, fmt, key, "no input");
-}
-
-
-/* key__decode_char():
- * Put a printable form of char in buf.
- */
-private int
-key__decode_char(char *buf, int cnt, int ch)
-{
- if (ch == 0) {
- buf[cnt++] = '^';
- buf[cnt] = '@';
- return (cnt);
- }
- if (iscntrl(ch)) {
- buf[cnt++] = '^';
- if (ch == '\177')
- buf[cnt] = '?';
- else
- buf[cnt] = ch | 0100;
- } else if (ch == '^') {
- buf[cnt++] = '\\';
- buf[cnt] = '^';
- } else if (ch == '\\') {
- buf[cnt++] = '\\';
- buf[cnt] = '\\';
- } else if (ch == ' ' || (isprint(ch) && !isspace(ch))) {
- buf[cnt] = ch;
- } else {
- buf[cnt++] = '\\';
- buf[cnt++] = (((unsigned int) ch >> 6) & 7) + '0';
- buf[cnt++] = (((unsigned int) ch >> 3) & 7) + '0';
- buf[cnt] = (ch & 7) + '0';
- }
- return (cnt);
-}
-
-
-/* key__decode_str():
- * Make a printable version of the ey
- */
-protected char *
-key__decode_str(const char *str, char *buf, const char *sep)
-{
- char *b;
- const char *p;
-
- b = buf;
- if (sep[0] != '\0')
- *b++ = sep[0];
- if (*str == 0) {
- *b++ = '^';
- *b++ = '@';
- if (sep[0] != '\0' && sep[1] != '\0')
- *b++ = sep[1];
- *b++ = 0;
- return (buf);
- }
- for (p = str; *p != 0; p++) {
- if (iscntrl((unsigned char) *p)) {
- *b++ = '^';
- if (*p == '\177')
- *b++ = '?';
- else
- *b++ = *p | 0100;
- } else if (*p == '^' || *p == '\\') {
- *b++ = '\\';
- *b++ = *p;
- } else if (*p == ' ' || (isprint((unsigned char) *p) &&
- !isspace((unsigned char) *p))) {
- *b++ = *p;
- } else {
- *b++ = '\\';
- *b++ = (((unsigned int) *p >> 6) & 7) + '0';
- *b++ = (((unsigned int) *p >> 3) & 7) + '0';
- *b++ = (*p & 7) + '0';
- }
- }
- if (sep[0] != '\0' && sep[1] != '\0')
- *b++ = sep[1];
- *b++ = 0;
- return (buf); /* should check for overflow */
-}
diff --git a/main/editline/key.h b/main/editline/key.h
deleted file mode 100644
index 80d8626b8..000000000
--- a/main/editline/key.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* $NetBSD: key.h,v 1.6 2002/03/18 16:00:55 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)key.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.key.h: Key macro header
- */
-#ifndef _h_el_key
-#define _h_el_key
-
-typedef union key_value_t {
- el_action_t cmd; /* If it is a command the # */
- char *str; /* If it is a string... */
-} key_value_t;
-
-typedef struct key_node_t key_node_t;
-
-typedef struct el_key_t {
- char *buf; /* Key print buffer */
- key_node_t *map; /* Key map */
- key_value_t val; /* Local conversion buffer */
-} el_key_t;
-
-#define XK_CMD 0
-#define XK_STR 1
-#define XK_NOD 2
-#define XK_EXE 3
-
-protected int key_init(EditLine *);
-protected void key_end(EditLine *);
-protected key_value_t *key_map_cmd(EditLine *, int);
-protected key_value_t *key_map_str(EditLine *, char *);
-protected void key_reset(EditLine *);
-protected int key_get(EditLine *, char *, key_value_t *);
-protected void key_add(EditLine *, const char *, key_value_t *, int);
-protected void key_clear(EditLine *, el_action_t *, const char *);
-protected int key_delete(EditLine *, const char *);
-protected void key_print(EditLine *, const char *);
-protected void key_kprint(EditLine *, const char *, key_value_t *,
- int);
-protected char *key__decode_str(const char *, char *, const char *);
-
-#endif /* _h_el_key */
diff --git a/main/editline/makelist.in b/main/editline/makelist.in
deleted file mode 100644
index 9a44dc75b..000000000
--- a/main/editline/makelist.in
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/bin/sh -
-# $NetBSD: makelist,v 1.7 2001/01/09 19:22:31 jdolecek Exp $
-#
-# Copyright (c) 1992, 1993
-# The Regents of the University of California. All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Christos Zoulas of Cornell University.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-# must display the following acknowledgement:
-# This product includes software developed by the University of
-# California, Berkeley and its contributors.
-# 4. Neither the name of the University nor the names of its contributors
-# may be used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# @(#)makelist 5.3 (Berkeley) 6/4/93
-
-# makelist.sh: Automatically generate header files...
-
-AWK=@AWK@
-USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh|-m <filenames>"
-
-if [ "x$1" = "x" ]
-then
- echo $USAGE 1>&2
- exit 1
-fi
-
-FLAG="$1"
-shift
-
-FILES="$@"
-
-case $FLAG in
-
-# generate foo.h file from foo.c
-#
--h)
- set - `echo $FILES | sed -e 's/\\./_/g'`
- hdr="_h_`basename $1`"
- cat $FILES | $AWK '
- BEGIN {
- printf("/* Automatically generated file, do not edit */\n");
- printf("#ifndef %s\n#define %s\n", "'$hdr'", "'$hdr'");
- }
- /\(\):/ {
- pr = substr($2, 1, 2);
- if (pr == "vi" || pr == "em" || pr == "ed") {
- name = substr($2, 1, length($2) - 3);
-#
-# XXX: need a space between name and prototype so that -fc and -fh
-# parsing is much easier
-#
- printf("protected el_action_t\t%s (EditLine *, int);\n", name);
- }
- }
- END {
- printf("#endif /* %s */\n", "'$hdr'");
- }'
- ;;
-
-# generate help.c from various .c files
-#
--bc)
- cat $FILES | $AWK '
- BEGIN {
- printf("/* Automatically generated file, do not edit */\n");
- printf("#include \"sys.h\"\n#include \"el.h\"\n");
- printf("private const struct el_bindings_t el_func_help[] = {\n");
- low = "abcdefghijklmnopqrstuvwxyz_";
- high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
- for (i = 1; i <= length(low); i++)
- tr[substr(low, i, 1)] = substr(high, i, 1);
- }
- /\(\):/ {
- pr = substr($2, 1, 2);
- if (pr == "vi" || pr == "em" || pr == "ed") {
- name = substr($2, 1, length($2) - 3);
- uname = "";
- fname = "";
- for (i = 1; i <= length(name); i++) {
- s = substr(name, i, 1);
- uname = uname tr[s];
- if (s == "_")
- s = "-";
- fname = fname s;
- }
-
- printf(" { %-30.30s %-30.30s\n","\"" fname "\",", uname ",");
- ok = 1;
- }
- }
- /^ \*/ {
- if (ok) {
- printf(" \"");
- for (i = 2; i < NF; i++)
- printf("%s ", $i);
- printf("%s\" },\n", $i);
- ok = 0;
- }
- }
- END {
- printf(" { NULL, 0, NULL }\n");
- printf("};\n");
- printf("\nprotected const el_bindings_t* help__get()");
- printf("{ return el_func_help; }\n");
- }'
- ;;
-
-# generate help.h from various .c files
-#
--bh)
- $AWK '
- BEGIN {
- printf("/* Automatically generated file, do not edit */\n");
- printf("#ifndef _h_help_c\n#define _h_help_c\n");
- printf("protected const el_bindings_t *help__get(void);\n");
- printf("#endif /* _h_help_c */\n");
- }' /dev/null
- ;;
-
-# generate fcns.h from various .h files
-#
--fh)
- cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
- sort | tr '[:lower:]' '[:upper:]' | $AWK '
- BEGIN {
- printf("/* Automatically generated file, do not edit */\n");
- printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
- count = 0;
- }
- {
- printf("#define\t%-30.30s\t%3d\n", $1, count++);
- }
- END {
- printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count);
-
- printf("typedef el_action_t (*el_func_t)(EditLine *, int);");
- printf("\nprotected const el_func_t* func__get(void);\n");
- printf("#endif /* _h_fcns_c */\n");
- }'
- ;;
-
-# generate fcns.c from various .h files
-#
--fc)
- cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK '
- BEGIN {
- printf("/* Automatically generated file, do not edit */\n");
- printf("#include \"sys.h\"\n#include \"el.h\"\n");
- printf("private const el_func_t el_func[] = {");
- maxlen = 80;
- needn = 1;
- len = 0;
- }
- {
- clen = 25 + 2;
- len += clen;
- if (len >= maxlen)
- needn = 1;
- if (needn) {
- printf("\n ");
- needn = 0;
- len = 4 + clen;
- }
- s = $1 ",";
- printf("%-26.26s ", s);
- }
- END {
- printf("\n};\n");
- printf("\nprotected const el_func_t* func__get() { return el_func; }\n");
- }'
- ;;
-
-# generate editline.c from various .c files
-#
--e)
- echo "$FILES" | tr ' ' '\012' | $AWK '
- BEGIN {
- printf("/* Automatically generated file, do not edit */\n");
- printf("#define protected static\n");
- printf("#define SCCSID\n");
- }
- {
- printf("#include \"%s\"\n", $1);
- }'
- ;;
-
-# generate man page fragment from various .c files
-#
--m)
- cat $FILES | $AWK '
- BEGIN {
- printf(".\\\" Section automatically generated with makelist\n");
- printf(".Bl -tag -width 4n\n");
- }
- /\(\):/ {
- pr = substr($2, 1, 2);
- if (pr == "vi" || pr == "em" || pr == "ed") {
- name = substr($2, 1, length($2) - 3);
- fname = "";
- for (i = 1; i <= length(name); i++) {
- s = substr(name, i, 1);
- if (s == "_")
- s = "-";
- fname = fname s;
- }
-
- printf(".It Ic %s\n", fname);
- ok = 1;
- }
- }
- /^ \*/ {
- if (ok) {
- for (i = 2; i < NF; i++)
- printf("%s ", $i);
- printf("%s.\n", $i);
- ok = 0;
- }
- }
- END {
- printf(".El\n");
- printf(".\\\" End of section automatically generated with makelist\n");
- }'
- ;;
-
-*)
- echo $USAGE 1>&2
- exit 1
- ;;
-
-esac
diff --git a/main/editline/map.c b/main/editline/map.c
deleted file mode 100644
index 4187cb597..000000000
--- a/main/editline/map.c
+++ /dev/null
@@ -1,1418 +0,0 @@
-/* $NetBSD: map.c,v 1.15 2002/03/18 16:00:55 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: map.c,v 1.15 2002/03/18 16:00:55 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * map.c: Editor function definitions
- */
-#include <stdlib.h>
-#include "el.h"
-
-#define N_KEYS 256
-
-private void map_print_key(EditLine *, el_action_t *, const char *);
-private void map_print_some_keys(EditLine *, el_action_t *, int, int);
-private void map_print_all_keys(EditLine *);
-private void map_init_nls(EditLine *);
-private void map_init_meta(EditLine *);
-
-/* keymap tables ; should be N_KEYS*sizeof(KEYCMD) bytes long */
-
-
-private const el_action_t el_map_emacs[] = {
- /* 0 */ EM_SET_MARK, /* ^@ */
- /* 1 */ ED_MOVE_TO_BEG, /* ^A */
- /* 2 */ ED_PREV_CHAR, /* ^B */
- /* 3 */ ED_TTY_SIGINT, /* ^C */
- /* 4 */ EM_DELETE_OR_LIST, /* ^D */
- /* 5 */ ED_MOVE_TO_END, /* ^E */
- /* 6 */ ED_NEXT_CHAR, /* ^F */
- /* 7 */ ED_UNASSIGNED, /* ^G */
- /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */
- /* 9 */ ED_UNASSIGNED, /* ^I */
- /* 10 */ ED_NEWLINE, /* ^J */
- /* 11 */ ED_KILL_LINE, /* ^K */
- /* 12 */ ED_CLEAR_SCREEN, /* ^L */
- /* 13 */ ED_NEWLINE, /* ^M */
- /* 14 */ ED_NEXT_HISTORY, /* ^N */
- /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */
- /* 16 */ ED_PREV_HISTORY, /* ^P */
- /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
- /* 18 */ ED_REDISPLAY, /* ^R */
- /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
- /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */
- /* 21 */ EM_KILL_LINE, /* ^U */
- /* 22 */ ED_QUOTED_INSERT, /* ^V */
- /* 23 */ EM_KILL_REGION, /* ^W */
- /* 24 */ ED_SEQUENCE_LEAD_IN, /* ^X */
- /* 25 */ EM_YANK, /* ^Y */
- /* 26 */ ED_TTY_SIGTSTP, /* ^Z */
- /* 27 */ EM_META_NEXT, /* ^[ */
- /* 28 */ ED_TTY_SIGQUIT, /* ^\ */
- /* 29 */ ED_TTY_DSUSP, /* ^] */
- /* 30 */ ED_UNASSIGNED, /* ^^ */
- /* 31 */ ED_UNASSIGNED, /* ^_ */
- /* 32 */ ED_INSERT, /* SPACE */
- /* 33 */ ED_INSERT, /* ! */
- /* 34 */ ED_INSERT, /* " */
- /* 35 */ ED_INSERT, /* # */
- /* 36 */ ED_INSERT, /* $ */
- /* 37 */ ED_INSERT, /* % */
- /* 38 */ ED_INSERT, /* & */
- /* 39 */ ED_INSERT, /* ' */
- /* 40 */ ED_INSERT, /* ( */
- /* 41 */ ED_INSERT, /* ) */
- /* 42 */ ED_INSERT, /* * */
- /* 43 */ ED_INSERT, /* + */
- /* 44 */ ED_INSERT, /* , */
- /* 45 */ ED_INSERT, /* - */
- /* 46 */ ED_INSERT, /* . */
- /* 47 */ ED_INSERT, /* / */
- /* 48 */ ED_DIGIT, /* 0 */
- /* 49 */ ED_DIGIT, /* 1 */
- /* 50 */ ED_DIGIT, /* 2 */
- /* 51 */ ED_DIGIT, /* 3 */
- /* 52 */ ED_DIGIT, /* 4 */
- /* 53 */ ED_DIGIT, /* 5 */
- /* 54 */ ED_DIGIT, /* 6 */
- /* 55 */ ED_DIGIT, /* 7 */
- /* 56 */ ED_DIGIT, /* 8 */
- /* 57 */ ED_DIGIT, /* 9 */
- /* 58 */ ED_INSERT, /* : */
- /* 59 */ ED_INSERT, /* ; */
- /* 60 */ ED_INSERT, /* < */
- /* 61 */ ED_INSERT, /* = */
- /* 62 */ ED_INSERT, /* > */
- /* 63 */ ED_INSERT, /* ? */
- /* 64 */ ED_INSERT, /* @ */
- /* 65 */ ED_INSERT, /* A */
- /* 66 */ ED_INSERT, /* B */
- /* 67 */ ED_INSERT, /* C */
- /* 68 */ ED_INSERT, /* D */
- /* 69 */ ED_INSERT, /* E */
- /* 70 */ ED_INSERT, /* F */
- /* 71 */ ED_INSERT, /* G */
- /* 72 */ ED_INSERT, /* H */
- /* 73 */ ED_INSERT, /* I */
- /* 74 */ ED_INSERT, /* J */
- /* 75 */ ED_INSERT, /* K */
- /* 76 */ ED_INSERT, /* L */
- /* 77 */ ED_INSERT, /* M */
- /* 78 */ ED_INSERT, /* N */
- /* 79 */ ED_INSERT, /* O */
- /* 80 */ ED_INSERT, /* P */
- /* 81 */ ED_INSERT, /* Q */
- /* 82 */ ED_INSERT, /* R */
- /* 83 */ ED_INSERT, /* S */
- /* 84 */ ED_INSERT, /* T */
- /* 85 */ ED_INSERT, /* U */
- /* 86 */ ED_INSERT, /* V */
- /* 87 */ ED_INSERT, /* W */
- /* 88 */ ED_INSERT, /* X */
- /* 89 */ ED_INSERT, /* Y */
- /* 90 */ ED_INSERT, /* Z */
- /* 91 */ ED_INSERT, /* [ */
- /* 92 */ ED_INSERT, /* \ */
- /* 93 */ ED_INSERT, /* ] */
- /* 94 */ ED_INSERT, /* ^ */
- /* 95 */ ED_INSERT, /* _ */
- /* 96 */ ED_INSERT, /* ` */
- /* 97 */ ED_INSERT, /* a */
- /* 98 */ ED_INSERT, /* b */
- /* 99 */ ED_INSERT, /* c */
- /* 100 */ ED_INSERT, /* d */
- /* 101 */ ED_INSERT, /* e */
- /* 102 */ ED_INSERT, /* f */
- /* 103 */ ED_INSERT, /* g */
- /* 104 */ ED_INSERT, /* h */
- /* 105 */ ED_INSERT, /* i */
- /* 106 */ ED_INSERT, /* j */
- /* 107 */ ED_INSERT, /* k */
- /* 108 */ ED_INSERT, /* l */
- /* 109 */ ED_INSERT, /* m */
- /* 110 */ ED_INSERT, /* n */
- /* 111 */ ED_INSERT, /* o */
- /* 112 */ ED_INSERT, /* p */
- /* 113 */ ED_INSERT, /* q */
- /* 114 */ ED_INSERT, /* r */
- /* 115 */ ED_INSERT, /* s */
- /* 116 */ ED_INSERT, /* t */
- /* 117 */ ED_INSERT, /* u */
- /* 118 */ ED_INSERT, /* v */
- /* 119 */ ED_INSERT, /* w */
- /* 120 */ ED_INSERT, /* x */
- /* 121 */ ED_INSERT, /* y */
- /* 122 */ ED_INSERT, /* z */
- /* 123 */ ED_INSERT, /* { */
- /* 124 */ ED_INSERT, /* | */
- /* 125 */ ED_INSERT, /* } */
- /* 126 */ ED_INSERT, /* ~ */
- /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */
- /* 128 */ ED_UNASSIGNED, /* M-^@ */
- /* 129 */ ED_UNASSIGNED, /* M-^A */
- /* 130 */ ED_UNASSIGNED, /* M-^B */
- /* 131 */ ED_UNASSIGNED, /* M-^C */
- /* 132 */ ED_UNASSIGNED, /* M-^D */
- /* 133 */ ED_UNASSIGNED, /* M-^E */
- /* 134 */ ED_UNASSIGNED, /* M-^F */
- /* 135 */ ED_UNASSIGNED, /* M-^G */
- /* 136 */ ED_DELETE_PREV_WORD, /* M-^H */
- /* 137 */ ED_UNASSIGNED, /* M-^I */
- /* 138 */ ED_UNASSIGNED, /* M-^J */
- /* 139 */ ED_UNASSIGNED, /* M-^K */
- /* 140 */ ED_CLEAR_SCREEN, /* M-^L */
- /* 141 */ ED_UNASSIGNED, /* M-^M */
- /* 142 */ ED_UNASSIGNED, /* M-^N */
- /* 143 */ ED_UNASSIGNED, /* M-^O */
- /* 144 */ ED_UNASSIGNED, /* M-^P */
- /* 145 */ ED_UNASSIGNED, /* M-^Q */
- /* 146 */ ED_UNASSIGNED, /* M-^R */
- /* 147 */ ED_UNASSIGNED, /* M-^S */
- /* 148 */ ED_UNASSIGNED, /* M-^T */
- /* 149 */ ED_UNASSIGNED, /* M-^U */
- /* 150 */ ED_UNASSIGNED, /* M-^V */
- /* 151 */ ED_UNASSIGNED, /* M-^W */
- /* 152 */ ED_UNASSIGNED, /* M-^X */
- /* 153 */ ED_UNASSIGNED, /* M-^Y */
- /* 154 */ ED_UNASSIGNED, /* M-^Z */
- /* 155 */ ED_UNASSIGNED, /* M-^[ */
- /* 156 */ ED_UNASSIGNED, /* M-^\ */
- /* 157 */ ED_UNASSIGNED, /* M-^] */
- /* 158 */ ED_UNASSIGNED, /* M-^^ */
- /* 159 */ EM_COPY_PREV_WORD, /* M-^_ */
- /* 160 */ ED_UNASSIGNED, /* M-SPACE */
- /* 161 */ ED_UNASSIGNED, /* M-! */
- /* 162 */ ED_UNASSIGNED, /* M-" */
- /* 163 */ ED_UNASSIGNED, /* M-# */
- /* 164 */ ED_UNASSIGNED, /* M-$ */
- /* 165 */ ED_UNASSIGNED, /* M-% */
- /* 166 */ ED_UNASSIGNED, /* M-& */
- /* 167 */ ED_UNASSIGNED, /* M-' */
- /* 168 */ ED_UNASSIGNED, /* M-( */
- /* 169 */ ED_UNASSIGNED, /* M-) */
- /* 170 */ ED_UNASSIGNED, /* M-* */
- /* 171 */ ED_UNASSIGNED, /* M-+ */
- /* 172 */ ED_UNASSIGNED, /* M-, */
- /* 173 */ ED_UNASSIGNED, /* M-- */
- /* 174 */ ED_UNASSIGNED, /* M-. */
- /* 175 */ ED_UNASSIGNED, /* M-/ */
- /* 176 */ ED_ARGUMENT_DIGIT, /* M-0 */
- /* 177 */ ED_ARGUMENT_DIGIT, /* M-1 */
- /* 178 */ ED_ARGUMENT_DIGIT, /* M-2 */
- /* 179 */ ED_ARGUMENT_DIGIT, /* M-3 */
- /* 180 */ ED_ARGUMENT_DIGIT, /* M-4 */
- /* 181 */ ED_ARGUMENT_DIGIT, /* M-5 */
- /* 182 */ ED_ARGUMENT_DIGIT, /* M-6 */
- /* 183 */ ED_ARGUMENT_DIGIT, /* M-7 */
- /* 184 */ ED_ARGUMENT_DIGIT, /* M-8 */
- /* 185 */ ED_ARGUMENT_DIGIT, /* M-9 */
- /* 186 */ ED_UNASSIGNED, /* M-: */
- /* 187 */ ED_UNASSIGNED, /* M-; */
- /* 188 */ ED_UNASSIGNED, /* M-< */
- /* 189 */ ED_UNASSIGNED, /* M-= */
- /* 190 */ ED_UNASSIGNED, /* M-> */
- /* 191 */ ED_UNASSIGNED, /* M-? */
- /* 192 */ ED_UNASSIGNED, /* M-@ */
- /* 193 */ ED_UNASSIGNED, /* M-A */
- /* 194 */ ED_PREV_WORD, /* M-B */
- /* 195 */ EM_CAPITOL_CASE, /* M-C */
- /* 196 */ EM_DELETE_NEXT_WORD, /* M-D */
- /* 197 */ ED_UNASSIGNED, /* M-E */
- /* 198 */ EM_NEXT_WORD, /* M-F */
- /* 199 */ ED_UNASSIGNED, /* M-G */
- /* 200 */ ED_UNASSIGNED, /* M-H */
- /* 201 */ ED_UNASSIGNED, /* M-I */
- /* 202 */ ED_UNASSIGNED, /* M-J */
- /* 203 */ ED_UNASSIGNED, /* M-K */
- /* 204 */ EM_LOWER_CASE, /* M-L */
- /* 205 */ ED_UNASSIGNED, /* M-M */
- /* 206 */ ED_SEARCH_NEXT_HISTORY, /* M-N */
- /* 207 */ ED_SEQUENCE_LEAD_IN, /* M-O */
- /* 208 */ ED_SEARCH_PREV_HISTORY, /* M-P */
- /* 209 */ ED_UNASSIGNED, /* M-Q */
- /* 210 */ ED_UNASSIGNED, /* M-R */
- /* 211 */ ED_UNASSIGNED, /* M-S */
- /* 212 */ ED_UNASSIGNED, /* M-T */
- /* 213 */ EM_UPPER_CASE, /* M-U */
- /* 214 */ ED_UNASSIGNED, /* M-V */
- /* 215 */ EM_COPY_REGION, /* M-W */
- /* 216 */ ED_COMMAND, /* M-X */
- /* 217 */ ED_UNASSIGNED, /* M-Y */
- /* 218 */ ED_UNASSIGNED, /* M-Z */
- /* 219 */ ED_SEQUENCE_LEAD_IN, /* M-[ */
- /* 220 */ ED_UNASSIGNED, /* M-\ */
- /* 221 */ ED_UNASSIGNED, /* M-] */
- /* 222 */ ED_UNASSIGNED, /* M-^ */
- /* 223 */ ED_UNASSIGNED, /* M-_ */
- /* 223 */ ED_UNASSIGNED, /* M-` */
- /* 224 */ ED_UNASSIGNED, /* M-a */
- /* 225 */ ED_PREV_WORD, /* M-b */
- /* 226 */ EM_CAPITOL_CASE, /* M-c */
- /* 227 */ EM_DELETE_NEXT_WORD, /* M-d */
- /* 228 */ ED_UNASSIGNED, /* M-e */
- /* 229 */ EM_NEXT_WORD, /* M-f */
- /* 230 */ ED_UNASSIGNED, /* M-g */
- /* 231 */ ED_UNASSIGNED, /* M-h */
- /* 232 */ ED_UNASSIGNED, /* M-i */
- /* 233 */ ED_UNASSIGNED, /* M-j */
- /* 234 */ ED_UNASSIGNED, /* M-k */
- /* 235 */ EM_LOWER_CASE, /* M-l */
- /* 236 */ ED_UNASSIGNED, /* M-m */
- /* 237 */ ED_SEARCH_NEXT_HISTORY, /* M-n */
- /* 238 */ ED_UNASSIGNED, /* M-o */
- /* 239 */ ED_SEARCH_PREV_HISTORY, /* M-p */
- /* 240 */ ED_UNASSIGNED, /* M-q */
- /* 241 */ ED_UNASSIGNED, /* M-r */
- /* 242 */ ED_UNASSIGNED, /* M-s */
- /* 243 */ ED_UNASSIGNED, /* M-t */
- /* 244 */ EM_UPPER_CASE, /* M-u */
- /* 245 */ ED_UNASSIGNED, /* M-v */
- /* 246 */ EM_COPY_REGION, /* M-w */
- /* 247 */ ED_COMMAND, /* M-x */
- /* 248 */ ED_UNASSIGNED, /* M-y */
- /* 249 */ ED_UNASSIGNED, /* M-z */
- /* 250 */ ED_UNASSIGNED, /* M-{ */
- /* 251 */ ED_UNASSIGNED, /* M-| */
- /* 252 */ ED_UNASSIGNED, /* M-} */
- /* 253 */ ED_UNASSIGNED, /* M-~ */
- /* 254 */ ED_DELETE_PREV_WORD /* M-^? */
- /* 255 */
-};
-
-
-/*
- * keymap table for vi. Each index into above tbl; should be
- * N_KEYS entries long. Vi mode uses a sticky-extend to do command mode:
- * insert mode characters are in the normal keymap, and command mode
- * in the extended keymap.
- */
-private const el_action_t el_map_vi_insert[] = {
-#ifdef KSHVI
- /* 0 */ ED_UNASSIGNED, /* ^@ */
- /* 1 */ ED_INSERT, /* ^A */
- /* 2 */ ED_INSERT, /* ^B */
- /* 3 */ ED_INSERT, /* ^C */
- /* 4 */ VI_LIST_OR_EOF, /* ^D */
- /* 5 */ ED_INSERT, /* ^E */
- /* 6 */ ED_INSERT, /* ^F */
- /* 7 */ ED_INSERT, /* ^G */
- /* 8 */ VI_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */
- /* 9 */ ED_INSERT, /* ^I */ /* Tab Key */
- /* 10 */ ED_NEWLINE, /* ^J */
- /* 11 */ ED_INSERT, /* ^K */
- /* 12 */ ED_INSERT, /* ^L */
- /* 13 */ ED_NEWLINE, /* ^M */
- /* 14 */ ED_INSERT, /* ^N */
- /* 15 */ ED_INSERT, /* ^O */
- /* 16 */ ED_INSERT, /* ^P */
- /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
- /* 18 */ ED_INSERT, /* ^R */
- /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
- /* 20 */ ED_INSERT, /* ^T */
- /* 21 */ VI_KILL_LINE_PREV, /* ^U */
- /* 22 */ ED_QUOTED_INSERT, /* ^V */
- /* 23 */ ED_DELETE_PREV_WORD, /* ^W */
- /* ED_DELETE_PREV_WORD: Only until strt edit pos */
- /* 24 */ ED_INSERT, /* ^X */
- /* 25 */ ED_INSERT, /* ^Y */
- /* 26 */ ED_INSERT, /* ^Z */
- /* 27 */ VI_COMMAND_MODE, /* ^[ */ /* [ Esc ] key */
- /* 28 */ ED_TTY_SIGQUIT, /* ^\ */
- /* 29 */ ED_INSERT, /* ^] */
- /* 30 */ ED_INSERT, /* ^^ */
- /* 31 */ ED_INSERT, /* ^_ */
-#else /* !KSHVI */
- /*
- * NOTE: These mappings do NOT Correspond well
- * to the KSH VI editing assignments.
- * On the other and they are convenient and
- * many people have have gotten used to them.
- */
- /* 0 */ ED_UNASSIGNED, /* ^@ */
- /* 1 */ ED_MOVE_TO_BEG, /* ^A */
- /* 2 */ ED_PREV_CHAR, /* ^B */
- /* 3 */ ED_TTY_SIGINT, /* ^C */
- /* 4 */ VI_LIST_OR_EOF, /* ^D */
- /* 5 */ ED_MOVE_TO_END, /* ^E */
- /* 6 */ ED_NEXT_CHAR, /* ^F */
- /* 7 */ ED_UNASSIGNED, /* ^G */
- /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */
- /* 9 */ ED_UNASSIGNED, /* ^I */ /* Tab Key */
- /* 10 */ ED_NEWLINE, /* ^J */
- /* 11 */ ED_KILL_LINE, /* ^K */
- /* 12 */ ED_CLEAR_SCREEN, /* ^L */
- /* 13 */ ED_NEWLINE, /* ^M */
- /* 14 */ ED_NEXT_HISTORY, /* ^N */
- /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */
- /* 16 */ ED_PREV_HISTORY, /* ^P */
- /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
- /* 18 */ ED_REDISPLAY, /* ^R */
- /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
- /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */
- /* 21 */ VI_KILL_LINE_PREV, /* ^U */
- /* 22 */ ED_QUOTED_INSERT, /* ^V */
- /* 23 */ ED_DELETE_PREV_WORD, /* ^W */
- /* 24 */ ED_UNASSIGNED, /* ^X */
- /* 25 */ ED_TTY_DSUSP, /* ^Y */
- /* 26 */ ED_TTY_SIGTSTP, /* ^Z */
- /* 27 */ VI_COMMAND_MODE, /* ^[ */
- /* 28 */ ED_TTY_SIGQUIT, /* ^\ */
- /* 29 */ ED_UNASSIGNED, /* ^] */
- /* 30 */ ED_UNASSIGNED, /* ^^ */
- /* 31 */ ED_UNASSIGNED, /* ^_ */
-#endif /* KSHVI */
- /* 32 */ ED_INSERT, /* SPACE */
- /* 33 */ ED_INSERT, /* ! */
- /* 34 */ ED_INSERT, /* " */
- /* 35 */ ED_INSERT, /* # */
- /* 36 */ ED_INSERT, /* $ */
- /* 37 */ ED_INSERT, /* % */
- /* 38 */ ED_INSERT, /* & */
- /* 39 */ ED_INSERT, /* ' */
- /* 40 */ ED_INSERT, /* ( */
- /* 41 */ ED_INSERT, /* ) */
- /* 42 */ ED_INSERT, /* * */
- /* 43 */ ED_INSERT, /* + */
- /* 44 */ ED_INSERT, /* , */
- /* 45 */ ED_INSERT, /* - */
- /* 46 */ ED_INSERT, /* . */
- /* 47 */ ED_INSERT, /* / */
- /* 48 */ ED_INSERT, /* 0 */
- /* 49 */ ED_INSERT, /* 1 */
- /* 50 */ ED_INSERT, /* 2 */
- /* 51 */ ED_INSERT, /* 3 */
- /* 52 */ ED_INSERT, /* 4 */
- /* 53 */ ED_INSERT, /* 5 */
- /* 54 */ ED_INSERT, /* 6 */
- /* 55 */ ED_INSERT, /* 7 */
- /* 56 */ ED_INSERT, /* 8 */
- /* 57 */ ED_INSERT, /* 9 */
- /* 58 */ ED_INSERT, /* : */
- /* 59 */ ED_INSERT, /* ; */
- /* 60 */ ED_INSERT, /* < */
- /* 61 */ ED_INSERT, /* = */
- /* 62 */ ED_INSERT, /* > */
- /* 63 */ ED_INSERT, /* ? */
- /* 64 */ ED_INSERT, /* @ */
- /* 65 */ ED_INSERT, /* A */
- /* 66 */ ED_INSERT, /* B */
- /* 67 */ ED_INSERT, /* C */
- /* 68 */ ED_INSERT, /* D */
- /* 69 */ ED_INSERT, /* E */
- /* 70 */ ED_INSERT, /* F */
- /* 71 */ ED_INSERT, /* G */
- /* 72 */ ED_INSERT, /* H */
- /* 73 */ ED_INSERT, /* I */
- /* 74 */ ED_INSERT, /* J */
- /* 75 */ ED_INSERT, /* K */
- /* 76 */ ED_INSERT, /* L */
- /* 77 */ ED_INSERT, /* M */
- /* 78 */ ED_INSERT, /* N */
- /* 79 */ ED_INSERT, /* O */
- /* 80 */ ED_INSERT, /* P */
- /* 81 */ ED_INSERT, /* Q */
- /* 82 */ ED_INSERT, /* R */
- /* 83 */ ED_INSERT, /* S */
- /* 84 */ ED_INSERT, /* T */
- /* 85 */ ED_INSERT, /* U */
- /* 86 */ ED_INSERT, /* V */
- /* 87 */ ED_INSERT, /* W */
- /* 88 */ ED_INSERT, /* X */
- /* 89 */ ED_INSERT, /* Y */
- /* 90 */ ED_INSERT, /* Z */
- /* 91 */ ED_INSERT, /* [ */
- /* 92 */ ED_INSERT, /* \ */
- /* 93 */ ED_INSERT, /* ] */
- /* 94 */ ED_INSERT, /* ^ */
- /* 95 */ ED_INSERT, /* _ */
- /* 96 */ ED_INSERT, /* ` */
- /* 97 */ ED_INSERT, /* a */
- /* 98 */ ED_INSERT, /* b */
- /* 99 */ ED_INSERT, /* c */
- /* 100 */ ED_INSERT, /* d */
- /* 101 */ ED_INSERT, /* e */
- /* 102 */ ED_INSERT, /* f */
- /* 103 */ ED_INSERT, /* g */
- /* 104 */ ED_INSERT, /* h */
- /* 105 */ ED_INSERT, /* i */
- /* 106 */ ED_INSERT, /* j */
- /* 107 */ ED_INSERT, /* k */
- /* 108 */ ED_INSERT, /* l */
- /* 109 */ ED_INSERT, /* m */
- /* 110 */ ED_INSERT, /* n */
- /* 111 */ ED_INSERT, /* o */
- /* 112 */ ED_INSERT, /* p */
- /* 113 */ ED_INSERT, /* q */
- /* 114 */ ED_INSERT, /* r */
- /* 115 */ ED_INSERT, /* s */
- /* 116 */ ED_INSERT, /* t */
- /* 117 */ ED_INSERT, /* u */
- /* 118 */ ED_INSERT, /* v */
- /* 119 */ ED_INSERT, /* w */
- /* 120 */ ED_INSERT, /* x */
- /* 121 */ ED_INSERT, /* y */
- /* 122 */ ED_INSERT, /* z */
- /* 123 */ ED_INSERT, /* { */
- /* 124 */ ED_INSERT, /* | */
- /* 125 */ ED_INSERT, /* } */
- /* 126 */ ED_INSERT, /* ~ */
- /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */
- /* 128 */ ED_UNASSIGNED, /* M-^@ */
- /* 129 */ ED_UNASSIGNED, /* M-^A */
- /* 130 */ ED_UNASSIGNED, /* M-^B */
- /* 131 */ ED_UNASSIGNED, /* M-^C */
- /* 132 */ ED_UNASSIGNED, /* M-^D */
- /* 133 */ ED_UNASSIGNED, /* M-^E */
- /* 134 */ ED_UNASSIGNED, /* M-^F */
- /* 135 */ ED_UNASSIGNED, /* M-^G */
- /* 136 */ ED_UNASSIGNED, /* M-^H */
- /* 137 */ ED_UNASSIGNED, /* M-^I */
- /* 138 */ ED_UNASSIGNED, /* M-^J */
- /* 139 */ ED_UNASSIGNED, /* M-^K */
- /* 140 */ ED_UNASSIGNED, /* M-^L */
- /* 141 */ ED_UNASSIGNED, /* M-^M */
- /* 142 */ ED_UNASSIGNED, /* M-^N */
- /* 143 */ ED_UNASSIGNED, /* M-^O */
- /* 144 */ ED_UNASSIGNED, /* M-^P */
- /* 145 */ ED_UNASSIGNED, /* M-^Q */
- /* 146 */ ED_UNASSIGNED, /* M-^R */
- /* 147 */ ED_UNASSIGNED, /* M-^S */
- /* 148 */ ED_UNASSIGNED, /* M-^T */
- /* 149 */ ED_UNASSIGNED, /* M-^U */
- /* 150 */ ED_UNASSIGNED, /* M-^V */
- /* 151 */ ED_UNASSIGNED, /* M-^W */
- /* 152 */ ED_UNASSIGNED, /* M-^X */
- /* 153 */ ED_UNASSIGNED, /* M-^Y */
- /* 154 */ ED_UNASSIGNED, /* M-^Z */
- /* 155 */ ED_UNASSIGNED, /* M-^[ */
- /* 156 */ ED_UNASSIGNED, /* M-^\ */
- /* 157 */ ED_UNASSIGNED, /* M-^] */
- /* 158 */ ED_UNASSIGNED, /* M-^^ */
- /* 159 */ ED_UNASSIGNED, /* M-^_ */
- /* 160 */ ED_UNASSIGNED, /* M-SPACE */
- /* 161 */ ED_UNASSIGNED, /* M-! */
- /* 162 */ ED_UNASSIGNED, /* M-" */
- /* 163 */ ED_UNASSIGNED, /* M-# */
- /* 164 */ ED_UNASSIGNED, /* M-$ */
- /* 165 */ ED_UNASSIGNED, /* M-% */
- /* 166 */ ED_UNASSIGNED, /* M-& */
- /* 167 */ ED_UNASSIGNED, /* M-' */
- /* 168 */ ED_UNASSIGNED, /* M-( */
- /* 169 */ ED_UNASSIGNED, /* M-) */
- /* 170 */ ED_UNASSIGNED, /* M-* */
- /* 171 */ ED_UNASSIGNED, /* M-+ */
- /* 172 */ ED_UNASSIGNED, /* M-, */
- /* 173 */ ED_UNASSIGNED, /* M-- */
- /* 174 */ ED_UNASSIGNED, /* M-. */
- /* 175 */ ED_UNASSIGNED, /* M-/ */
- /* 176 */ ED_UNASSIGNED, /* M-0 */
- /* 177 */ ED_UNASSIGNED, /* M-1 */
- /* 178 */ ED_UNASSIGNED, /* M-2 */
- /* 179 */ ED_UNASSIGNED, /* M-3 */
- /* 180 */ ED_UNASSIGNED, /* M-4 */
- /* 181 */ ED_UNASSIGNED, /* M-5 */
- /* 182 */ ED_UNASSIGNED, /* M-6 */
- /* 183 */ ED_UNASSIGNED, /* M-7 */
- /* 184 */ ED_UNASSIGNED, /* M-8 */
- /* 185 */ ED_UNASSIGNED, /* M-9 */
- /* 186 */ ED_UNASSIGNED, /* M-: */
- /* 187 */ ED_UNASSIGNED, /* M-; */
- /* 188 */ ED_UNASSIGNED, /* M-< */
- /* 189 */ ED_UNASSIGNED, /* M-= */
- /* 190 */ ED_UNASSIGNED, /* M-> */
- /* 191 */ ED_UNASSIGNED, /* M-? */
- /* 192 */ ED_UNASSIGNED, /* M-@ */
- /* 193 */ ED_UNASSIGNED, /* M-A */
- /* 194 */ ED_UNASSIGNED, /* M-B */
- /* 195 */ ED_UNASSIGNED, /* M-C */
- /* 196 */ ED_UNASSIGNED, /* M-D */
- /* 197 */ ED_UNASSIGNED, /* M-E */
- /* 198 */ ED_UNASSIGNED, /* M-F */
- /* 199 */ ED_UNASSIGNED, /* M-G */
- /* 200 */ ED_UNASSIGNED, /* M-H */
- /* 201 */ ED_UNASSIGNED, /* M-I */
- /* 202 */ ED_UNASSIGNED, /* M-J */
- /* 203 */ ED_UNASSIGNED, /* M-K */
- /* 204 */ ED_UNASSIGNED, /* M-L */
- /* 205 */ ED_UNASSIGNED, /* M-M */
- /* 206 */ ED_UNASSIGNED, /* M-N */
- /* 207 */ ED_UNASSIGNED, /* M-O */
- /* 208 */ ED_UNASSIGNED, /* M-P */
- /* 209 */ ED_UNASSIGNED, /* M-Q */
- /* 210 */ ED_UNASSIGNED, /* M-R */
- /* 211 */ ED_UNASSIGNED, /* M-S */
- /* 212 */ ED_UNASSIGNED, /* M-T */
- /* 213 */ ED_UNASSIGNED, /* M-U */
- /* 214 */ ED_UNASSIGNED, /* M-V */
- /* 215 */ ED_UNASSIGNED, /* M-W */
- /* 216 */ ED_UNASSIGNED, /* M-X */
- /* 217 */ ED_UNASSIGNED, /* M-Y */
- /* 218 */ ED_UNASSIGNED, /* M-Z */
- /* 219 */ ED_UNASSIGNED, /* M-[ */
- /* 220 */ ED_UNASSIGNED, /* M-\ */
- /* 221 */ ED_UNASSIGNED, /* M-] */
- /* 222 */ ED_UNASSIGNED, /* M-^ */
- /* 223 */ ED_UNASSIGNED, /* M-_ */
- /* 224 */ ED_UNASSIGNED, /* M-` */
- /* 225 */ ED_UNASSIGNED, /* M-a */
- /* 226 */ ED_UNASSIGNED, /* M-b */
- /* 227 */ ED_UNASSIGNED, /* M-c */
- /* 228 */ ED_UNASSIGNED, /* M-d */
- /* 229 */ ED_UNASSIGNED, /* M-e */
- /* 230 */ ED_UNASSIGNED, /* M-f */
- /* 231 */ ED_UNASSIGNED, /* M-g */
- /* 232 */ ED_UNASSIGNED, /* M-h */
- /* 233 */ ED_UNASSIGNED, /* M-i */
- /* 234 */ ED_UNASSIGNED, /* M-j */
- /* 235 */ ED_UNASSIGNED, /* M-k */
- /* 236 */ ED_UNASSIGNED, /* M-l */
- /* 237 */ ED_UNASSIGNED, /* M-m */
- /* 238 */ ED_UNASSIGNED, /* M-n */
- /* 239 */ ED_UNASSIGNED, /* M-o */
- /* 240 */ ED_UNASSIGNED, /* M-p */
- /* 241 */ ED_UNASSIGNED, /* M-q */
- /* 242 */ ED_UNASSIGNED, /* M-r */
- /* 243 */ ED_UNASSIGNED, /* M-s */
- /* 244 */ ED_UNASSIGNED, /* M-t */
- /* 245 */ ED_UNASSIGNED, /* M-u */
- /* 246 */ ED_UNASSIGNED, /* M-v */
- /* 247 */ ED_UNASSIGNED, /* M-w */
- /* 248 */ ED_UNASSIGNED, /* M-x */
- /* 249 */ ED_UNASSIGNED, /* M-y */
- /* 250 */ ED_UNASSIGNED, /* M-z */
- /* 251 */ ED_UNASSIGNED, /* M-{ */
- /* 252 */ ED_UNASSIGNED, /* M-| */
- /* 253 */ ED_UNASSIGNED, /* M-} */
- /* 254 */ ED_UNASSIGNED, /* M-~ */
- /* 255 */ ED_UNASSIGNED /* M-^? */
-};
-
-private const el_action_t el_map_vi_command[] = {
- /* 0 */ ED_UNASSIGNED, /* ^@ */
- /* 1 */ ED_MOVE_TO_BEG, /* ^A */
- /* 2 */ ED_UNASSIGNED, /* ^B */
- /* 3 */ ED_TTY_SIGINT, /* ^C */
- /* 4 */ ED_UNASSIGNED, /* ^D */
- /* 5 */ ED_MOVE_TO_END, /* ^E */
- /* 6 */ ED_UNASSIGNED, /* ^F */
- /* 7 */ ED_UNASSIGNED, /* ^G */
- /* 8 */ ED_PREV_CHAR, /* ^H */
- /* 9 */ ED_UNASSIGNED, /* ^I */
- /* 10 */ ED_NEWLINE, /* ^J */
- /* 11 */ ED_KILL_LINE, /* ^K */
- /* 12 */ ED_CLEAR_SCREEN, /* ^L */
- /* 13 */ ED_NEWLINE, /* ^M */
- /* 14 */ ED_NEXT_HISTORY, /* ^N */
- /* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */
- /* 16 */ ED_PREV_HISTORY, /* ^P */
- /* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
- /* 18 */ ED_REDISPLAY, /* ^R */
- /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
- /* 20 */ ED_UNASSIGNED, /* ^T */
- /* 21 */ VI_KILL_LINE_PREV, /* ^U */
- /* 22 */ ED_UNASSIGNED, /* ^V */
- /* 23 */ ED_DELETE_PREV_WORD, /* ^W */
- /* 24 */ ED_UNASSIGNED, /* ^X */
- /* 25 */ ED_UNASSIGNED, /* ^Y */
- /* 26 */ ED_UNASSIGNED, /* ^Z */
- /* 27 */ EM_META_NEXT, /* ^[ */
- /* 28 */ ED_TTY_SIGQUIT, /* ^\ */
- /* 29 */ ED_UNASSIGNED, /* ^] */
- /* 30 */ ED_UNASSIGNED, /* ^^ */
- /* 31 */ ED_UNASSIGNED, /* ^_ */
- /* 32 */ ED_NEXT_CHAR, /* SPACE */
- /* 33 */ ED_UNASSIGNED, /* ! */
- /* 34 */ ED_UNASSIGNED, /* " */
- /* 35 */ ED_UNASSIGNED, /* # */
- /* 36 */ ED_MOVE_TO_END, /* $ */
- /* 37 */ ED_UNASSIGNED, /* % */
- /* 38 */ ED_UNASSIGNED, /* & */
- /* 39 */ ED_UNASSIGNED, /* ' */
- /* 40 */ ED_UNASSIGNED, /* ( */
- /* 41 */ ED_UNASSIGNED, /* ) */
- /* 42 */ ED_UNASSIGNED, /* * */
- /* 43 */ ED_NEXT_HISTORY, /* + */
- /* 44 */ VI_REPEAT_PREV_CHAR, /* , */
- /* 45 */ ED_PREV_HISTORY, /* - */
- /* 46 */ ED_UNASSIGNED, /* . */
- /* 47 */ VI_SEARCH_PREV, /* / */
- /* 48 */ VI_ZERO, /* 0 */
- /* 49 */ ED_ARGUMENT_DIGIT, /* 1 */
- /* 50 */ ED_ARGUMENT_DIGIT, /* 2 */
- /* 51 */ ED_ARGUMENT_DIGIT, /* 3 */
- /* 52 */ ED_ARGUMENT_DIGIT, /* 4 */
- /* 53 */ ED_ARGUMENT_DIGIT, /* 5 */
- /* 54 */ ED_ARGUMENT_DIGIT, /* 6 */
- /* 55 */ ED_ARGUMENT_DIGIT, /* 7 */
- /* 56 */ ED_ARGUMENT_DIGIT, /* 8 */
- /* 57 */ ED_ARGUMENT_DIGIT, /* 9 */
- /* 58 */ ED_COMMAND, /* : */
- /* 59 */ VI_REPEAT_NEXT_CHAR, /* ; */
- /* 60 */ ED_UNASSIGNED, /* < */
- /* 61 */ ED_UNASSIGNED, /* = */
- /* 62 */ ED_UNASSIGNED, /* > */
- /* 63 */ VI_SEARCH_NEXT, /* ? */
- /* 64 */ ED_UNASSIGNED, /* @ */
- /* 65 */ VI_ADD_AT_EOL, /* A */
- /* 66 */ VI_PREV_SPACE_WORD, /* B */
- /* 67 */ VI_CHANGE_TO_EOL, /* C */
- /* 68 */ ED_KILL_LINE, /* D */
- /* 69 */ VI_TO_END_WORD, /* E */
- /* 70 */ VI_PREV_CHAR, /* F */
- /* 71 */ ED_UNASSIGNED, /* G */
- /* 72 */ ED_UNASSIGNED, /* H */
- /* 73 */ VI_INSERT_AT_BOL, /* I */
- /* 74 */ ED_SEARCH_NEXT_HISTORY, /* J */
- /* 75 */ ED_SEARCH_PREV_HISTORY, /* K */
- /* 76 */ ED_UNASSIGNED, /* L */
- /* 77 */ ED_UNASSIGNED, /* M */
- /* 78 */ VI_REPEAT_SEARCH_PREV, /* N */
- /* 79 */ ED_SEQUENCE_LEAD_IN, /* O */
- /* 80 */ VI_PASTE_PREV, /* P */
- /* 81 */ ED_UNASSIGNED, /* Q */
- /* 82 */ VI_REPLACE_MODE, /* R */
- /* 83 */ VI_SUBSTITUTE_LINE, /* S */
- /* 84 */ VI_TO_PREV_CHAR, /* T */
- /* 85 */ ED_UNASSIGNED, /* U */
- /* 86 */ ED_UNASSIGNED, /* V */
- /* 87 */ VI_NEXT_SPACE_WORD, /* W */
- /* 88 */ ED_DELETE_PREV_CHAR, /* X */
- /* 89 */ ED_UNASSIGNED, /* Y */
- /* 90 */ ED_UNASSIGNED, /* Z */
- /* 91 */ ED_SEQUENCE_LEAD_IN, /* [ */
- /* 92 */ ED_UNASSIGNED, /* \ */
- /* 93 */ ED_UNASSIGNED, /* ] */
- /* 94 */ ED_MOVE_TO_BEG, /* ^ */
- /* 95 */ ED_UNASSIGNED, /* _ */
- /* 96 */ ED_UNASSIGNED, /* ` */
- /* 97 */ VI_ADD, /* a */
- /* 98 */ VI_PREV_WORD, /* b */
- /* 99 */ VI_CHANGE_META, /* c */
- /* 100 */ VI_DELETE_META, /* d */
- /* 101 */ VI_END_WORD, /* e */
- /* 102 */ VI_NEXT_CHAR, /* f */
- /* 103 */ ED_UNASSIGNED, /* g */
- /* 104 */ ED_PREV_CHAR, /* h */
- /* 105 */ VI_INSERT, /* i */
- /* 106 */ ED_NEXT_HISTORY, /* j */
- /* 107 */ ED_PREV_HISTORY, /* k */
- /* 108 */ ED_NEXT_CHAR, /* l */
- /* 109 */ ED_UNASSIGNED, /* m */
- /* 110 */ VI_REPEAT_SEARCH_NEXT, /* n */
- /* 111 */ ED_UNASSIGNED, /* o */
- /* 112 */ VI_PASTE_NEXT, /* p */
- /* 113 */ ED_UNASSIGNED, /* q */
- /* 114 */ VI_REPLACE_CHAR, /* r */
- /* 115 */ VI_SUBSTITUTE_CHAR, /* s */
- /* 116 */ VI_TO_NEXT_CHAR, /* t */
- /* 117 */ VI_UNDO, /* u */
- /* 118 */ ED_UNASSIGNED, /* v */
- /* 119 */ VI_NEXT_WORD, /* w */
- /* 120 */ ED_DELETE_NEXT_CHAR, /* x */
- /* 121 */ ED_UNASSIGNED, /* y */
- /* 122 */ ED_UNASSIGNED, /* z */
- /* 123 */ ED_UNASSIGNED, /* { */
- /* 124 */ ED_UNASSIGNED, /* | */
- /* 125 */ ED_UNASSIGNED, /* } */
- /* 126 */ VI_CHANGE_CASE, /* ~ */
- /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */
- /* 128 */ ED_UNASSIGNED, /* M-^@ */
- /* 129 */ ED_UNASSIGNED, /* M-^A */
- /* 130 */ ED_UNASSIGNED, /* M-^B */
- /* 131 */ ED_UNASSIGNED, /* M-^C */
- /* 132 */ ED_UNASSIGNED, /* M-^D */
- /* 133 */ ED_UNASSIGNED, /* M-^E */
- /* 134 */ ED_UNASSIGNED, /* M-^F */
- /* 135 */ ED_UNASSIGNED, /* M-^G */
- /* 136 */ ED_UNASSIGNED, /* M-^H */
- /* 137 */ ED_UNASSIGNED, /* M-^I */
- /* 138 */ ED_UNASSIGNED, /* M-^J */
- /* 139 */ ED_UNASSIGNED, /* M-^K */
- /* 140 */ ED_UNASSIGNED, /* M-^L */
- /* 141 */ ED_UNASSIGNED, /* M-^M */
- /* 142 */ ED_UNASSIGNED, /* M-^N */
- /* 143 */ ED_UNASSIGNED, /* M-^O */
- /* 144 */ ED_UNASSIGNED, /* M-^P */
- /* 145 */ ED_UNASSIGNED, /* M-^Q */
- /* 146 */ ED_UNASSIGNED, /* M-^R */
- /* 147 */ ED_UNASSIGNED, /* M-^S */
- /* 148 */ ED_UNASSIGNED, /* M-^T */
- /* 149 */ ED_UNASSIGNED, /* M-^U */
- /* 150 */ ED_UNASSIGNED, /* M-^V */
- /* 151 */ ED_UNASSIGNED, /* M-^W */
- /* 152 */ ED_UNASSIGNED, /* M-^X */
- /* 153 */ ED_UNASSIGNED, /* M-^Y */
- /* 154 */ ED_UNASSIGNED, /* M-^Z */
- /* 155 */ ED_UNASSIGNED, /* M-^[ */
- /* 156 */ ED_UNASSIGNED, /* M-^\ */
- /* 157 */ ED_UNASSIGNED, /* M-^] */
- /* 158 */ ED_UNASSIGNED, /* M-^^ */
- /* 159 */ ED_UNASSIGNED, /* M-^_ */
- /* 160 */ ED_UNASSIGNED, /* M-SPACE */
- /* 161 */ ED_UNASSIGNED, /* M-! */
- /* 162 */ ED_UNASSIGNED, /* M-" */
- /* 163 */ ED_UNASSIGNED, /* M-# */
- /* 164 */ ED_UNASSIGNED, /* M-$ */
- /* 165 */ ED_UNASSIGNED, /* M-% */
- /* 166 */ ED_UNASSIGNED, /* M-& */
- /* 167 */ ED_UNASSIGNED, /* M-' */
- /* 168 */ ED_UNASSIGNED, /* M-( */
- /* 169 */ ED_UNASSIGNED, /* M-) */
- /* 170 */ ED_UNASSIGNED, /* M-* */
- /* 171 */ ED_UNASSIGNED, /* M-+ */
- /* 172 */ ED_UNASSIGNED, /* M-, */
- /* 173 */ ED_UNASSIGNED, /* M-- */
- /* 174 */ ED_UNASSIGNED, /* M-. */
- /* 175 */ ED_UNASSIGNED, /* M-/ */
- /* 176 */ ED_UNASSIGNED, /* M-0 */
- /* 177 */ ED_UNASSIGNED, /* M-1 */
- /* 178 */ ED_UNASSIGNED, /* M-2 */
- /* 179 */ ED_UNASSIGNED, /* M-3 */
- /* 180 */ ED_UNASSIGNED, /* M-4 */
- /* 181 */ ED_UNASSIGNED, /* M-5 */
- /* 182 */ ED_UNASSIGNED, /* M-6 */
- /* 183 */ ED_UNASSIGNED, /* M-7 */
- /* 184 */ ED_UNASSIGNED, /* M-8 */
- /* 185 */ ED_UNASSIGNED, /* M-9 */
- /* 186 */ ED_UNASSIGNED, /* M-: */
- /* 187 */ ED_UNASSIGNED, /* M-; */
- /* 188 */ ED_UNASSIGNED, /* M-< */
- /* 189 */ ED_UNASSIGNED, /* M-= */
- /* 190 */ ED_UNASSIGNED, /* M-> */
- /* 191 */ ED_UNASSIGNED, /* M-? */
- /* 192 */ ED_UNASSIGNED, /* M-@ */
- /* 193 */ ED_UNASSIGNED, /* M-A */
- /* 194 */ ED_UNASSIGNED, /* M-B */
- /* 195 */ ED_UNASSIGNED, /* M-C */
- /* 196 */ ED_UNASSIGNED, /* M-D */
- /* 197 */ ED_UNASSIGNED, /* M-E */
- /* 198 */ ED_UNASSIGNED, /* M-F */
- /* 199 */ ED_UNASSIGNED, /* M-G */
- /* 200 */ ED_UNASSIGNED, /* M-H */
- /* 201 */ ED_UNASSIGNED, /* M-I */
- /* 202 */ ED_UNASSIGNED, /* M-J */
- /* 203 */ ED_UNASSIGNED, /* M-K */
- /* 204 */ ED_UNASSIGNED, /* M-L */
- /* 205 */ ED_UNASSIGNED, /* M-M */
- /* 206 */ ED_UNASSIGNED, /* M-N */
- /* 207 */ ED_SEQUENCE_LEAD_IN, /* M-O */
- /* 208 */ ED_UNASSIGNED, /* M-P */
- /* 209 */ ED_UNASSIGNED, /* M-Q */
- /* 210 */ ED_UNASSIGNED, /* M-R */
- /* 211 */ ED_UNASSIGNED, /* M-S */
- /* 212 */ ED_UNASSIGNED, /* M-T */
- /* 213 */ ED_UNASSIGNED, /* M-U */
- /* 214 */ ED_UNASSIGNED, /* M-V */
- /* 215 */ ED_UNASSIGNED, /* M-W */
- /* 216 */ ED_UNASSIGNED, /* M-X */
- /* 217 */ ED_UNASSIGNED, /* M-Y */
- /* 218 */ ED_UNASSIGNED, /* M-Z */
- /* 219 */ ED_SEQUENCE_LEAD_IN, /* M-[ */
- /* 220 */ ED_UNASSIGNED, /* M-\ */
- /* 221 */ ED_UNASSIGNED, /* M-] */
- /* 222 */ ED_UNASSIGNED, /* M-^ */
- /* 223 */ ED_UNASSIGNED, /* M-_ */
- /* 224 */ ED_UNASSIGNED, /* M-` */
- /* 225 */ ED_UNASSIGNED, /* M-a */
- /* 226 */ ED_UNASSIGNED, /* M-b */
- /* 227 */ ED_UNASSIGNED, /* M-c */
- /* 228 */ ED_UNASSIGNED, /* M-d */
- /* 229 */ ED_UNASSIGNED, /* M-e */
- /* 230 */ ED_UNASSIGNED, /* M-f */
- /* 231 */ ED_UNASSIGNED, /* M-g */
- /* 232 */ ED_UNASSIGNED, /* M-h */
- /* 233 */ ED_UNASSIGNED, /* M-i */
- /* 234 */ ED_UNASSIGNED, /* M-j */
- /* 235 */ ED_UNASSIGNED, /* M-k */
- /* 236 */ ED_UNASSIGNED, /* M-l */
- /* 237 */ ED_UNASSIGNED, /* M-m */
- /* 238 */ ED_UNASSIGNED, /* M-n */
- /* 239 */ ED_UNASSIGNED, /* M-o */
- /* 240 */ ED_UNASSIGNED, /* M-p */
- /* 241 */ ED_UNASSIGNED, /* M-q */
- /* 242 */ ED_UNASSIGNED, /* M-r */
- /* 243 */ ED_UNASSIGNED, /* M-s */
- /* 244 */ ED_UNASSIGNED, /* M-t */
- /* 245 */ ED_UNASSIGNED, /* M-u */
- /* 246 */ ED_UNASSIGNED, /* M-v */
- /* 247 */ ED_UNASSIGNED, /* M-w */
- /* 248 */ ED_UNASSIGNED, /* M-x */
- /* 249 */ ED_UNASSIGNED, /* M-y */
- /* 250 */ ED_UNASSIGNED, /* M-z */
- /* 251 */ ED_UNASSIGNED, /* M-{ */
- /* 252 */ ED_UNASSIGNED, /* M-| */
- /* 253 */ ED_UNASSIGNED, /* M-} */
- /* 254 */ ED_UNASSIGNED, /* M-~ */
- /* 255 */ ED_UNASSIGNED /* M-^? */
-};
-
-
-/* map_init():
- * Initialize and allocate the maps
- */
-protected int
-map_init(EditLine *el)
-{
-
- /*
- * Make sure those are correct before starting.
- */
-#ifdef MAP_DEBUG
- if (sizeof(el_map_emacs) != N_KEYS * sizeof(el_action_t))
- EL_ABORT((el->errfile, "Emacs map incorrect\n"));
- if (sizeof(el_map_vi_command) != N_KEYS * sizeof(el_action_t))
- EL_ABORT((el->errfile, "Vi command map incorrect\n"));
- if (sizeof(el_map_vi_insert) != N_KEYS * sizeof(el_action_t))
- EL_ABORT((el->errfile, "Vi insert map incorrect\n"));
-#endif
-
- el->el_map.alt = (el_action_t *)el_malloc(sizeof(el_action_t) * N_KEYS);
- if (el->el_map.alt == NULL)
- return (-1);
- el->el_map.key = (el_action_t *)el_malloc(sizeof(el_action_t) * N_KEYS);
- if (el->el_map.key == NULL)
- return (-1);
- el->el_map.emacs = el_map_emacs;
- el->el_map.vic = el_map_vi_command;
- el->el_map.vii = el_map_vi_insert;
- el->el_map.help = (el_bindings_t *) el_malloc(sizeof(el_bindings_t) *
- EL_NUM_FCNS);
- if (el->el_map.help == NULL)
- return (-1);
- (void) memcpy(el->el_map.help, help__get(),
- sizeof(el_bindings_t) * EL_NUM_FCNS);
- el->el_map.func = (el_func_t *)el_malloc(sizeof(el_func_t) *
- EL_NUM_FCNS);
- if (el->el_map.func == NULL)
- return (-1);
- memcpy(el->el_map.func, func__get(), sizeof(el_func_t) * EL_NUM_FCNS);
- el->el_map.nfunc = EL_NUM_FCNS;
-
-#ifdef VIDEFAULT
- map_init_vi(el);
-#else
- map_init_emacs(el);
-#endif /* VIDEFAULT */
- return (0);
-}
-
-
-/* map_end():
- * Free the space taken by the editor maps
- */
-protected void
-map_end(EditLine *el)
-{
-
- el_free((ptr_t) el->el_map.alt);
- el->el_map.alt = NULL;
- el_free((ptr_t) el->el_map.key);
- el->el_map.key = NULL;
- el->el_map.emacs = NULL;
- el->el_map.vic = NULL;
- el->el_map.vii = NULL;
- el_free((ptr_t) el->el_map.help);
- el->el_map.help = NULL;
- el_free((ptr_t) el->el_map.func);
- el->el_map.func = NULL;
-}
-
-
-/* map_init_nls():
- * Find all the printable keys and bind them to self insert
- */
-private void
-map_init_nls(EditLine *el)
-{
- int i;
-
- el_action_t *map = el->el_map.key;
-
- for (i = 0200; i <= 0377; i++)
- if (isprint(i))
- map[i] = ED_INSERT;
-}
-
-
-/* map_init_meta():
- * Bind all the meta keys to the appropriate ESC-<key> sequence
- */
-private void
-map_init_meta(EditLine *el)
-{
- char buf[3];
- int i;
- el_action_t *map = el->el_map.key;
- el_action_t *alt = el->el_map.alt;
-
- for (i = 0; i <= 0377 && map[i] != EM_META_NEXT; i++)
- continue;
-
- if (i > 0377) {
- for (i = 0; i <= 0377 && alt[i] != EM_META_NEXT; i++)
- continue;
- if (i > 0377) {
- i = 033;
- if (el->el_map.type == MAP_VI)
- map = alt;
- } else
- map = alt;
- }
- buf[0] = (char) i;
- buf[2] = 0;
- for (i = 0200; i <= 0377; i++)
- switch (map[i]) {
- case ED_INSERT:
- case ED_UNASSIGNED:
- case ED_SEQUENCE_LEAD_IN:
- break;
- default:
- buf[1] = i & 0177;
- key_add(el, buf, key_map_cmd(el, (int) map[i]), XK_CMD);
- break;
- }
- map[(int) buf[0]] = ED_SEQUENCE_LEAD_IN;
-}
-
-
-/* map_init_vi():
- * Initialize the vi bindings
- */
-protected void
-map_init_vi(EditLine *el)
-{
- int i;
- el_action_t *key = el->el_map.key;
- el_action_t *alt = el->el_map.alt;
- const el_action_t *vii = el->el_map.vii;
- const el_action_t *vic = el->el_map.vic;
-
- el->el_map.type = MAP_VI;
- el->el_map.current = el->el_map.key;
-
- key_reset(el);
-
- for (i = 0; i < N_KEYS; i++) {
- key[i] = vii[i];
- alt[i] = vic[i];
- }
-
- map_init_meta(el);
- map_init_nls(el);
-
- tty_bind_char(el, 1);
- term_bind_arrow(el);
-}
-
-
-/* map_init_emacs():
- * Initialize the emacs bindings
- */
-protected void
-map_init_emacs(EditLine *el)
-{
- int i;
- char buf[3];
- el_action_t *key = el->el_map.key;
- el_action_t *alt = el->el_map.alt;
- const el_action_t *emacs = el->el_map.emacs;
-
- el->el_map.type = MAP_EMACS;
- el->el_map.current = el->el_map.key;
- key_reset(el);
-
- for (i = 0; i < N_KEYS; i++) {
- key[i] = emacs[i];
- alt[i] = ED_UNASSIGNED;
- }
-
- map_init_meta(el);
- map_init_nls(el);
-
- buf[0] = CONTROL('X');
- buf[1] = CONTROL('X');
- buf[2] = 0;
- key_add(el, buf, key_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD);
-
- tty_bind_char(el, 1);
- term_bind_arrow(el);
-}
-
-
-/* map_set_editor():
- * Set the editor
- */
-protected int
-map_set_editor(EditLine *el, char *editor)
-{
-
- if (strcmp(editor, "emacs") == 0) {
- map_init_emacs(el);
- return (0);
- }
- if (strcmp(editor, "vi") == 0) {
- map_init_vi(el);
- return (0);
- }
- return (-1);
-}
-
-
-/* map_get_editor():
- * Retrieve the editor
- */
-protected int
-map_get_editor(EditLine *el, const char **editor)
-{
-
- if (editor == NULL)
- return (-1);
- switch (el->el_map.type) {
- case MAP_EMACS:
- *editor = "emacs";
- return (0);
- case MAP_VI:
- *editor = "vi";
- return (0);
- }
- return (-1);
-}
-
-
-/* map_print_key():
- * Print the function description for 1 key
- */
-private void
-map_print_key(EditLine *el, el_action_t *map, const char *in)
-{
- char outbuf[EL_BUFSIZ];
- el_bindings_t *bp;
-
- if (in[0] == '\0' || in[1] == '\0') {
- (void) key__decode_str(in, outbuf, "");
- for (bp = el->el_map.help; bp->name != NULL; bp++)
- if (bp->func == map[(unsigned char) *in]) {
- (void) fprintf(el->el_outfile,
- "%s\t->\t%s\n", outbuf, bp->name);
- return;
- }
- } else
- key_print(el, in);
-}
-
-
-/* map_print_some_keys():
- * Print keys from first to last
- */
-private void
-map_print_some_keys(EditLine *el, el_action_t *map, int first, int last)
-{
- el_bindings_t *bp;
- char firstbuf[2], lastbuf[2];
- char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ];
-
- firstbuf[0] = first;
- firstbuf[1] = 0;
- lastbuf[0] = last;
- lastbuf[1] = 0;
- if (map[first] == ED_UNASSIGNED) {
- if (first == last)
- (void) fprintf(el->el_outfile,
- "%-15s-> is undefined\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ));
- return;
- }
- for (bp = el->el_map.help; bp->name != NULL; bp++) {
- if (bp->func == map[first]) {
- if (first == last) {
- (void) fprintf(el->el_outfile, "%-15s-> %s\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ),
- bp->name);
- } else {
- (void) fprintf(el->el_outfile,
- "%-4s to %-7s-> %s\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ),
- key__decode_str(lastbuf, extrabuf, STRQQ),
- bp->name);
- }
- return;
- }
- }
-#ifdef MAP_DEBUG
- if (map == el->el_map.key) {
- (void) fprintf(el->el_outfile,
- "BUG!!! %s isn't bound to anything.\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ));
- (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n",
- first, el->el_map.key[first]);
- } else {
- (void) fprintf(el->el_outfile,
- "BUG!!! %s isn't bound to anything.\n",
- key__decode_str(firstbuf, unparsbuf, STRQQ));
- (void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n",
- first, el->el_map.alt[first]);
- }
-#endif
- EL_ABORT((el->el_errfile, "Error printing keys\n"));
-}
-
-
-/* map_print_all_keys():
- * Print the function description for all keys.
- */
-private void
-map_print_all_keys(EditLine *el)
-{
- int prev, i;
-
- (void) fprintf(el->el_outfile, "Standard key bindings\n");
- prev = 0;
- for (i = 0; i < N_KEYS; i++) {
- if (el->el_map.key[prev] == el->el_map.key[i])
- continue;
- map_print_some_keys(el, el->el_map.key, prev, i - 1);
- prev = i;
- }
- map_print_some_keys(el, el->el_map.key, prev, i - 1);
-
- (void) fprintf(el->el_outfile, "Alternative key bindings\n");
- prev = 0;
- for (i = 0; i < N_KEYS; i++) {
- if (el->el_map.alt[prev] == el->el_map.alt[i])
- continue;
- map_print_some_keys(el, el->el_map.alt, prev, i - 1);
- prev = i;
- }
- map_print_some_keys(el, el->el_map.alt, prev, i - 1);
-
- (void) fprintf(el->el_outfile, "Multi-character bindings\n");
- key_print(el, "");
- (void) fprintf(el->el_outfile, "Arrow key bindings\n");
- term_print_arrow(el, "");
-}
-
-
-/* map_bind():
- * Add/remove/change bindings
- */
-protected int
-map_bind(EditLine *el, int argc, const char **argv)
-{
- el_action_t *map;
- int ntype, rem;
- const char *p;
- char inbuf[EL_BUFSIZ];
- char outbuf[EL_BUFSIZ];
- const char *in = NULL;
- char *out = NULL;
- el_bindings_t *bp;
- int cmd;
- int key;
-
- if (argv == NULL)
- return (-1);
-
- map = el->el_map.key;
- ntype = XK_CMD;
- key = rem = 0;
- for (argc = 1; (p = argv[argc]) != NULL; argc++)
- if (p[0] == '-')
- switch (p[1]) {
- case 'a':
- map = el->el_map.alt;
- break;
-
- case 's':
- ntype = XK_STR;
- break;
-#ifdef notyet
- case 'c':
- ntype = XK_EXE;
- break;
-#endif
- case 'k':
- key = 1;
- break;
-
- case 'r':
- rem = 1;
- break;
-
- case 'v':
- map_init_vi(el);
- return (0);
-
- case 'e':
- map_init_emacs(el);
- return (0);
-
- case 'l':
- for (bp = el->el_map.help; bp->name != NULL;
- bp++)
- (void) fprintf(el->el_outfile,
- "%s\n\t%s\n",
- bp->name, bp->description);
- return (0);
- default:
- (void) fprintf(el->el_errfile,
- "%s: Invalid switch `%c'.\n",
- argv[0], p[1]);
- }
- else
- break;
-
- if (argv[argc] == NULL) {
- map_print_all_keys(el);
- return (0);
- }
- if (key)
- in = argv[argc++];
- else if ((in = parse__string(inbuf, argv[argc++])) == NULL) {
- (void) fprintf(el->el_errfile,
- "%s: Invalid \\ or ^ in instring.\n",
- argv[0]);
- return (-1);
- }
- if (rem) {
- if (key) {
- (void) term_clear_arrow(el, in);
- return (-1);
- }
- if (in[1])
- (void) key_delete(el, in);
- else if (map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN)
- (void) key_delete(el, in);
- else
- map[(unsigned char) *in] = ED_UNASSIGNED;
- return (0);
- }
- if (argv[argc] == NULL) {
- if (key)
- term_print_arrow(el, in);
- else
- map_print_key(el, map, in);
- return (0);
- }
-#ifdef notyet
- if (argv[argc + 1] != NULL) {
- bindkey_usage();
- return (-1);
- }
-#endif
-
- switch (ntype) {
- case XK_STR:
- case XK_EXE:
- if ((out = parse__string(outbuf, argv[argc])) == NULL) {
- (void) fprintf(el->el_errfile,
- "%s: Invalid \\ or ^ in outstring.\n", argv[0]);
- return (-1);
- }
- if (key)
- term_set_arrow(el, in, key_map_str(el, out), ntype);
- else
- key_add(el, in, key_map_str(el, out), ntype);
- map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN;
- break;
-
- case XK_CMD:
- if ((cmd = parse_cmd(el, argv[argc])) == -1) {
- (void) fprintf(el->el_errfile,
- "%s: Invalid command `%s'.\n", argv[0], argv[argc]);
- return (-1);
- }
- if (key)
- term_set_arrow(el, in, key_map_str(el, out), ntype);
- else {
- if (in[1]) {
- key_add(el, in, key_map_cmd(el, cmd), ntype);
- map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN;
- } else {
- key_clear(el, map, in);
- map[(unsigned char) *in] = cmd;
- }
- }
- break;
-
- default:
- EL_ABORT((el->el_errfile, "Bad XK_ type\n", ntype));
- break;
- }
- return (0);
-}
-
-
-/* map_addfunc():
- * add a user defined function
- */
-protected int
-map_addfunc(EditLine *el, const char *name, const char *help, el_func_t func)
-{
- void *p;
- int nf = el->el_map.nfunc + 2;
-
- if (name == NULL || help == NULL || func == NULL)
- return (-1);
-
- if ((p = el_realloc(el->el_map.func, nf * sizeof(el_func_t))) == NULL)
- return (-1);
- el->el_map.func = (el_func_t *) p;
- if ((p = el_realloc(el->el_map.help, nf * sizeof(el_bindings_t)))
- == NULL)
- return (-1);
- el->el_map.help = (el_bindings_t *) p;
-
- nf = el->el_map.nfunc;
- el->el_map.func[nf] = func;
-
- el->el_map.help[nf].name = name;
- el->el_map.help[nf].func = nf;
- el->el_map.help[nf].description = help;
- el->el_map.help[++nf].name = NULL;
- el->el_map.nfunc++;
-
- return (0);
-}
diff --git a/main/editline/map.h b/main/editline/map.h
deleted file mode 100644
index 3c9948ccf..000000000
--- a/main/editline/map.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* $NetBSD: map.h,v 1.7 2002/03/18 16:00:56 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)map.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.map.h: Editor maps
- */
-#ifndef _h_el_map
-#define _h_el_map
-
-typedef struct el_bindings_t { /* for the "bind" shell command */
- const char *name; /* function name for bind command */
- int func; /* function numeric value */
- const char *description; /* description of function */
-} el_bindings_t;
-
-
-typedef struct el_map_t {
- el_action_t *alt; /* The current alternate key map */
- el_action_t *key; /* The current normal key map */
- el_action_t *current; /* The keymap we are using */
- const el_action_t *emacs; /* The default emacs key map */
- const el_action_t *vic; /* The vi command mode key map */
- const el_action_t *vii; /* The vi insert mode key map */
- int type; /* Emacs or vi */
- el_bindings_t *help; /* The help for the editor functions */
- el_func_t *func; /* List of available functions */
- int nfunc; /* The number of functions/help items */
-} el_map_t;
-
-#define MAP_EMACS 0
-#define MAP_VI 1
-
-protected int map_bind(EditLine *, int, const char **);
-protected int map_init(EditLine *);
-protected void map_end(EditLine *);
-protected void map_init_vi(EditLine *);
-protected void map_init_emacs(EditLine *);
-protected int map_set_editor(EditLine *, char *);
-protected int map_get_editor(EditLine *, const char **);
-protected int map_addfunc(EditLine *, const char *, const char *, el_func_t);
-
-#endif /* _h_el_map */
diff --git a/main/editline/np/fgetln.c b/main/editline/np/fgetln.c
deleted file mode 100644
index 93da9914d..000000000
--- a/main/editline/np/fgetln.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* $NetBSD: fgetln.c,v 1.1.1.1 1999/04/12 07:43:21 crooksa Exp $ */
-
-/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Christos Zoulas.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-
-char *
-fgetln(fp, len)
- FILE *fp;
- size_t *len;
-{
- static char *buf = NULL;
- static size_t bufsiz = 0;
- char *ptr;
-
-
- if (buf == NULL) {
- bufsiz = BUFSIZ;
- if ((buf = malloc(bufsiz)) == NULL)
- return NULL;
- }
-
- if (fgets(buf, bufsiz, fp) == NULL)
- return NULL;
- *len = 0;
-
- while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
- size_t nbufsiz = bufsiz + BUFSIZ;
- char *nbuf = realloc(buf, nbufsiz);
-
- if (nbuf == NULL) {
- int oerrno = errno;
- free(buf);
- errno = oerrno;
- buf = NULL;
- return NULL;
- } else
- buf = nbuf;
-
- *len = bufsiz;
- if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL)
- return buf;
-
- bufsiz = nbufsiz;
- }
-
- *len = (ptr - buf) + 1;
- return buf;
-}
diff --git a/main/editline/np/strlcat.c b/main/editline/np/strlcat.c
deleted file mode 100644
index 6c9f1e92d..000000000
--- a/main/editline/np/strlcat.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#if defined(LIBC_SCCS) && !defined(lint)
-static char *rcsid = "$OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD: src/lib/libc/string/strlcat.c,v 1.2.4.2 2001/07/09 23:30:06 obrien Exp $";
-#endif
-
-#include <sys/types.h>
-#include <string.h>
-
-/*
- * Appends src to string dst of size siz (unlike strncat, siz is the
- * full size of dst, not space left). At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
- * Returns strlen(initial dst) + strlen(src); if retval >= siz,
- * truncation occurred.
- */
-size_t strlcat(dst, src, siz)
- char *dst;
- const char *src;
- size_t siz;
-{
- register char *d = dst;
- register const char *s = src;
- register size_t n = siz;
- size_t dlen;
-
- /* Find the end of dst and adjust bytes left but don't go past end */
- while (n-- != 0 && *d != '\0')
- d++;
- dlen = d - dst;
- n = siz - dlen;
-
- if (n == 0)
- return(dlen + strlen(s));
- while (*s != '\0') {
- if (n != 1) {
- *d++ = *s;
- n--;
- }
- s++;
- }
- *d = '\0';
-
- return(dlen + (s - src)); /* count does not include NUL */
-}
diff --git a/main/editline/np/strlcpy.c b/main/editline/np/strlcpy.c
deleted file mode 100644
index 1f154bcf2..000000000
--- a/main/editline/np/strlcpy.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */
-
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $";
-#endif
-#endif /* LIBC_SCCS and not lint */
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.2.4.1 2001/07/09 23:30:06 obrien Exp $";
-#endif
-
-#include <sys/types.h>
-#include <string.h>
-
-/*
- * Copy src to string dst of size siz. At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- */
-size_t strlcpy(dst, src, siz)
- char *dst;
- const char *src;
- size_t siz;
-{
- register char *d = dst;
- register const char *s = src;
- register size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0 && --n != 0) {
- do {
- if ((*d++ = *s++) == 0)
- break;
- } while (--n != 0);
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0) {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
- }
-
- return(s - src - 1); /* count does not include NUL */
-}
diff --git a/main/editline/np/unvis.c b/main/editline/np/unvis.c
deleted file mode 100644
index f43c4c749..000000000
--- a/main/editline/np/unvis.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/* $NetBSD: unvis.c,v 1.22 2002/03/23 17:38:27 christos Exp $ */
-
-/*-
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: unvis.c,v 1.22 2002/03/23 17:38:27 christos Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#define __LIBC12_SOURCE__
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdio.h>
-#include "np/vis.h"
-
-#ifdef __weak_alias
-__weak_alias(strunvis,_strunvis)
-__weak_alias(unvis,_unvis)
-#endif
-
-#ifdef __warn_references
-__warn_references(unvis,
- "warning: reference to compatibility unvis(); include <vis.h> for correct reference")
-#endif
-
-#if !HAVE_VIS_H
-/*
- * decode driven by state machine
- */
-#define S_GROUND 0 /* haven't seen escape char */
-#define S_START 1 /* start decoding special sequence */
-#define S_META 2 /* metachar started (M) */
-#define S_META1 3 /* metachar more, regular char (-) */
-#define S_CTRL 4 /* control char started (^) */
-#define S_OCTAL2 5 /* octal digit 2 */
-#define S_OCTAL3 6 /* octal digit 3 */
-#define S_HEX1 7 /* hex digit */
-#define S_HEX2 8 /* hex digit 2 */
-
-#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
-#define xtod(c) (isdigit(c) ? (c - '0') : ((tolower(c) - 'a') + 10))
-
-int
-unvis(cp, c, astate, flag)
- char *cp;
- int c;
- int *astate, flag;
-{
- return __unvis13(cp, (int)c, astate, flag);
-}
-
-/*
- * unvis - decode characters previously encoded by vis
- */
-int
-__unvis13(cp, c, astate, flag)
- char *cp;
- int c;
- int *astate, flag;
-{
-
- _DIAGASSERT(cp != NULL);
- _DIAGASSERT(astate != NULL);
-
- if (flag & UNVIS_END) {
- if (*astate == S_OCTAL2 || *astate == S_OCTAL3
- || *astate == S_HEX2) {
- *astate = S_GROUND;
- return (UNVIS_VALID);
- }
- return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
- }
-
- switch (*astate) {
-
- case S_GROUND:
- *cp = 0;
- if (c == '\\') {
- *astate = S_START;
- return (0);
- }
- if ((flag & VIS_HTTPSTYLE) && c == '%') {
- *astate = S_HEX1;
- return (0);
- }
- *cp = c;
- return (UNVIS_VALID);
-
- case S_START:
- switch(c) {
- case '\\':
- *cp = c;
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- *cp = (c - '0');
- *astate = S_OCTAL2;
- return (0);
- case 'M':
- *cp = (char)0200;
- *astate = S_META;
- return (0);
- case '^':
- *astate = S_CTRL;
- return (0);
- case 'n':
- *cp = '\n';
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case 'r':
- *cp = '\r';
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case 'b':
- *cp = '\b';
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case 'a':
- *cp = '\007';
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case 'v':
- *cp = '\v';
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case 't':
- *cp = '\t';
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case 'f':
- *cp = '\f';
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case 's':
- *cp = ' ';
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case 'E':
- *cp = '\033';
- *astate = S_GROUND;
- return (UNVIS_VALID);
- case '\n':
- /*
- * hidden newline
- */
- *astate = S_GROUND;
- return (UNVIS_NOCHAR);
- case '$':
- /*
- * hidden marker
- */
- *astate = S_GROUND;
- return (UNVIS_NOCHAR);
- }
- *astate = S_GROUND;
- return (UNVIS_SYNBAD);
-
- case S_META:
- if (c == '-')
- *astate = S_META1;
- else if (c == '^')
- *astate = S_CTRL;
- else {
- *astate = S_GROUND;
- return (UNVIS_SYNBAD);
- }
- return (0);
-
- case S_META1:
- *astate = S_GROUND;
- *cp |= c;
- return (UNVIS_VALID);
-
- case S_CTRL:
- if (c == '?')
- *cp |= 0177;
- else
- *cp |= c & 037;
- *astate = S_GROUND;
- return (UNVIS_VALID);
-
- case S_OCTAL2: /* second possible octal digit */
- if (isoctal(c)) {
- /*
- * yes - and maybe a third
- */
- *cp = (*cp << 3) + (c - '0');
- *astate = S_OCTAL3;
- return (0);
- }
- /*
- * no - done with current sequence, push back passed char
- */
- *astate = S_GROUND;
- return (UNVIS_VALIDPUSH);
-
- case S_OCTAL3: /* third possible octal digit */
- *astate = S_GROUND;
- if (isoctal(c)) {
- *cp = (*cp << 3) + (c - '0');
- return (UNVIS_VALID);
- }
- /*
- * we were done, push back passed char
- */
- return (UNVIS_VALIDPUSH);
- case S_HEX1:
- if (isxdigit(c)) {
- *cp = xtod(c);
- *astate = S_HEX2;
- return (0);
- }
- /*
- * no - done with current sequence, push back passed char
- */
- *astate = S_GROUND;
- return (UNVIS_VALIDPUSH);
- case S_HEX2:
- *astate = S_GROUND;
- if (isxdigit(c)) {
- *cp = xtod(c) | (*cp << 4);
- return (UNVIS_VALID);
- }
- return (UNVIS_VALIDPUSH);
- default:
- /*
- * decoder in unknown state - (probably uninitialized)
- */
- *astate = S_GROUND;
- return (UNVIS_SYNBAD);
- }
-}
-
-/*
- * strunvis - decode src into dst
- *
- * Number of chars decoded into dst is returned, -1 on error.
- * Dst is null terminated.
- */
-
-int
-strunvisx(dst, src, flag)
- char *dst;
- const char *src;
- int flag;
-{
- char c;
- char *start = dst;
- int state = 0;
-
- _DIAGASSERT(src != NULL);
- _DIAGASSERT(dst != NULL);
-
- while ((c = *src++) != '\0') {
- again:
- switch (__unvis13(dst, c, &state, flag)) {
- case UNVIS_VALID:
- dst++;
- break;
- case UNVIS_VALIDPUSH:
- dst++;
- goto again;
- case 0:
- case UNVIS_NOCHAR:
- break;
- default:
- return (-1);
- }
- }
- if (__unvis13(dst, c, &state, UNVIS_END) == UNVIS_VALID)
- dst++;
- *dst = '\0';
- return (dst - start);
-}
-
-int
-strunvis(dst, src)
- char *dst;
- const char *src;
-{
- return strunvisx(dst, src, 0);
-}
-#endif
diff --git a/main/editline/np/vis.c b/main/editline/np/vis.c
deleted file mode 100644
index bd8192440..000000000
--- a/main/editline/np/vis.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/* $NetBSD: vis.c,v 1.22 2002/03/23 17:38:27 christos Exp $ */
-
-/*-
- * Copyright (c) 1999 The NetBSD Foundation, Inc.
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: vis.c,v 1.22 2002/03/23 17:38:27 christos Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include "np/vis.h"
-#include <stdlib.h>
-#include <stdint.h>
-
-#ifdef __weak_alias
-__weak_alias(strsvis,_strsvis)
-__weak_alias(strsvisx,_strsvisx)
-__weak_alias(strvis,_strvis)
-__weak_alias(strvisx,_strvisx)
-__weak_alias(svis,_svis)
-__weak_alias(vis,_vis)
-#endif
-
-#ifndef HAVE_VIS_H
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#undef BELL
-#if defined(__STDC__)
-#define BELL '\a'
-#else
-#define BELL '\007'
-#endif
-
-#ifdef SOLARIS
-#include <alloca.h>
-#endif
-
-#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
-#define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
-#define issafe(c) (c == '\b' || c == BELL || c == '\r')
-#define xtoa(c) "0123456789abcdef"[c]
-
-#define MAXEXTRAS 5
-
-
-#define MAKEEXTRALIST(flag, extra, orig) \
-do { \
- const char *o = orig; \
- char *e; \
- while (*o++) \
- continue; \
- extra = alloca((size_t)((o - orig) + MAXEXTRAS)); \
- for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
- continue; \
- e--; \
- if (flag & VIS_SP) *e++ = ' '; \
- if (flag & VIS_TAB) *e++ = '\t'; \
- if (flag & VIS_NL) *e++ = '\n'; \
- if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
- *e = '\0'; \
-} while (/*CONSTCOND*/0)
-
-
-/*
- * This is HVIS, the macro of vis used to HTTP style (RFC 1808)
- */
-#define HVIS(dst, c, flag, nextc, extra) \
-do \
- if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \
- *dst++ = '%'; \
- *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \
- *dst++ = xtoa((unsigned int)c & 0xf); \
- } else { \
- SVIS(dst, c, flag, nextc, extra); \
- } \
-while (/*CONSTCOND*/0)
-
-/*
- * This is SVIS, the central macro of vis.
- * dst: Pointer to the destination buffer
- * c: Character to encode
- * flag: Flag word
- * nextc: The character following 'c'
- * extra: Pointer to the list of extra characters to be
- * backslash-protected.
- */
-#define SVIS(dst, c, flag, nextc, extra) \
-do { \
- int isextra, isc; \
- isextra = strchr(extra, c) != NULL; \
- if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \
- ((flag & VIS_SAFE) && issafe(c)))) { \
- *dst++ = c; \
- break; \
- } \
- isc = 0; \
- if (flag & VIS_CSTYLE) { \
- switch (c) { \
- case '\n': \
- isc = 1; *dst++ = '\\'; *dst++ = 'n'; \
- break; \
- case '\r': \
- isc = 1; *dst++ = '\\'; *dst++ = 'r'; \
- break; \
- case '\b': \
- isc = 1; *dst++ = '\\'; *dst++ = 'b'; \
- break; \
- case BELL: \
- isc = 1; *dst++ = '\\'; *dst++ = 'a'; \
- break; \
- case '\v': \
- isc = 1; *dst++ = '\\'; *dst++ = 'v'; \
- break; \
- case '\t': \
- isc = 1; *dst++ = '\\'; *dst++ = 't'; \
- break; \
- case '\f': \
- isc = 1; *dst++ = '\\'; *dst++ = 'f'; \
- break; \
- case ' ': \
- isc = 1; *dst++ = '\\'; *dst++ = 's'; \
- break; \
- case '\0': \
- isc = 1; *dst++ = '\\'; *dst++ = '0'; \
- if (isoctal(nextc)) { \
- *dst++ = '0'; \
- *dst++ = '0'; \
- } \
- } \
- } \
- if (isc) break; \
- if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \
- *dst++ = '\\'; \
- *dst++ = (u_char)(((uint32_t)(u_char)c >> 6) & 03) + '0'; \
- *dst++ = (u_char)(((uint32_t)(u_char)c >> 3) & 07) + '0'; \
- *dst++ = (c & 07) + '0'; \
- } else { \
- if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \
- if (c & 0200) { \
- c &= 0177; *dst++ = 'M'; \
- } \
- if (iscntrl(c)) { \
- *dst++ = '^'; \
- if (c == 0177) \
- *dst++ = '?'; \
- else \
- *dst++ = c + '@'; \
- } else { \
- *dst++ = '-'; *dst++ = c; \
- } \
- } \
-} while (/*CONSTCOND*/0)
-
-
-/*
- * svis - visually encode characters, also encoding the characters
- * pointed to by `extra'
- */
-char *
-svis(dst, c, flag, nextc, extra)
- char *dst;
- int c, flag, nextc;
- const char *extra;
-{
- char *nextra;
- _DIAGASSERT(dst != NULL);
- _DIAGASSERT(extra != NULL);
- MAKEEXTRALIST(flag, nextra, extra);
- if (flag & VIS_HTTPSTYLE)
- HVIS(dst, c, flag, nextc, nextra);
- else
- SVIS(dst, c, flag, nextc, nextra);
- *dst = '\0';
- return(dst);
-}
-
-
-/*
- * strsvis, strsvisx - visually encode characters from src into dst
- *
- * Extra is a pointer to a \0-terminated list of characters to
- * be encoded, too. These functions are useful e. g. to
- * encode strings in such a way so that they are not interpreted
- * by a shell.
- *
- * Dst must be 4 times the size of src to account for possible
- * expansion. The length of dst, not including the trailing NULL,
- * is returned.
- *
- * Strsvisx encodes exactly len bytes from src into dst.
- * This is useful for encoding a block of data.
- */
-int
-strsvis(dst, src, flag, extra)
- char *dst;
- const char *src;
- int flag;
- const char *extra;
-{
- char c;
- char *start;
- char *nextra;
-
- _DIAGASSERT(dst != NULL);
- _DIAGASSERT(src != NULL);
- _DIAGASSERT(extra != NULL);
- MAKEEXTRALIST(flag, nextra, extra);
- if (flag & VIS_HTTPSTYLE) {
- for (start = dst; (c = *src++) != '\0'; /* empty */)
- HVIS(dst, c, flag, *src, nextra);
- } else {
- for (start = dst; (c = *src++) != '\0'; /* empty */)
- SVIS(dst, c, flag, *src, nextra);
- }
- *dst = '\0';
- return (dst - start);
-}
-
-
-int
-strsvisx(dst, src, len, flag, extra)
- char *dst;
- const char *src;
- size_t len;
- int flag;
- const char *extra;
-{
- char c;
- char *start;
- char *nextra;
-
- _DIAGASSERT(dst != NULL);
- _DIAGASSERT(src != NULL);
- _DIAGASSERT(extra != NULL);
- MAKEEXTRALIST(flag, nextra, extra);
-
- if (flag & VIS_HTTPSTYLE) {
- for (start = dst; len > 0; len--) {
- c = *src++;
- HVIS(dst, c, flag, len ? *src : '\0', nextra);
- }
- } else {
- for (start = dst; len > 0; len--) {
- c = *src++;
- SVIS(dst, c, flag, len ? *src : '\0', nextra);
- }
- }
- *dst = '\0';
- return (dst - start);
-}
-
-
-/*
- * vis - visually encode characters
- */
-char *
-vis(dst, c, flag, nextc)
- char *dst;
- int c, flag, nextc;
-
-{
- char *extra;
-
- _DIAGASSERT(dst != NULL);
-
- MAKEEXTRALIST(flag, extra, "");
- if (flag & VIS_HTTPSTYLE)
- HVIS(dst, c, flag, nextc, extra);
- else
- SVIS(dst, c, flag, nextc, extra);
- *dst = '\0';
- return (dst);
-}
-
-
-/*
- * strvis, strvisx - visually encode characters from src into dst
- *
- * Dst must be 4 times the size of src to account for possible
- * expansion. The length of dst, not including the trailing NULL,
- * is returned.
- *
- * Strvisx encodes exactly len bytes from src into dst.
- * This is useful for encoding a block of data.
- */
-int
-strvis(dst, src, flag)
- char *dst;
- const char *src;
- int flag;
-{
- char *extra;
-
- MAKEEXTRALIST(flag, extra, "");
- return (strsvis(dst, src, flag, extra));
-}
-
-
-int
-strvisx(dst, src, len, flag)
- char *dst;
- const char *src;
- size_t len;
- int flag;
-{
- char *extra;
-
- MAKEEXTRALIST(flag, extra, "");
- return (strsvisx(dst, src, len, flag, extra));
-}
-#endif
diff --git a/main/editline/np/vis.h b/main/editline/np/vis.h
deleted file mode 100644
index 0739c1dfa..000000000
--- a/main/editline/np/vis.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $NetBSD: vis.h,v 1.12 2002/03/23 17:39:05 christos Exp $ */
-
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)vis.h 8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _VIS_H_
-#define _VIS_H_
-
-/*
- * to select alternate encoding format
- */
-#define VIS_OCTAL 0x01 /* use octal \ddd format */
-#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropiate */
-
-/*
- * to alter set of characters encoded (default is to encode all
- * non-graphic except space, tab, and newline).
- */
-#define VIS_SP 0x04 /* also encode space */
-#define VIS_TAB 0x08 /* also encode tab */
-#define VIS_NL 0x10 /* also encode newline */
-#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
-#define VIS_SAFE 0x20 /* only encode "unsafe" characters */
-
-/*
- * other
- */
-#define VIS_NOSLASH 0x40 /* inhibit printing '\' */
-#define VIS_HTTPSTYLE 0x80 /* http-style escape % HEX HEX */
-
-/*
- * unvis return codes
- */
-#define UNVIS_VALID 1 /* character valid */
-#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */
-#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */
-#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */
-#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */
-
-/*
- * unvis flags
- */
-#define UNVIS_END 1 /* no more characters */
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-char *vis __P((char *, int, int, int));
-char *svis __P((char *, int, int, int, const char *));
-int strvis __P((char *, const char *, int));
-int strsvis __P((char *, const char *, int, const char *));
-int strvisx __P((char *, const char *, size_t, int));
-int strsvisx __P((char *, const char *, size_t, int, const char *));
-int strunvis __P((char *, const char *));
-int strunvisx __P((char *, const char *, int));
-#ifdef __LIBC12_SOURCE__
-int unvis __P((char *, int, int *, int));
-int __unvis13 __P((char *, int, int *, int));
-#else
-int unvis __P((char *, int, int *, int)) __RENAME(__unvis13);
-#endif
-__END_DECLS
-
-#endif /* !_VIS_H_ */
diff --git a/main/editline/parse.c b/main/editline/parse.c
deleted file mode 100644
index 0a34f0b15..000000000
--- a/main/editline/parse.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* $NetBSD: parse.c,v 1.15 2002/03/18 16:00:56 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: parse.c,v 1.15 2002/03/18 16:00:56 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * parse.c: parse an editline extended command
- *
- * commands are:
- *
- * bind
- * echotc
- * edit
- * gettc
- * history
- * settc
- * setty
- */
-#include "el.h"
-#include "tokenizer.h"
-#include <stdlib.h>
-
-private const struct {
- const char *name;
- int (*func)(EditLine *, int, const char **);
-} cmds[] = {
- { "bind", map_bind },
- { "echotc", term_echotc },
- { "edit", el_editmode },
- { "history", hist_list },
- { "telltc", term_telltc },
- { "settc", term_settc },
- { "setty", tty_stty },
- { NULL, NULL }
-};
-
-
-/* parse_line():
- * Parse a line and dispatch it
- */
-protected int
-parse_line(EditLine *el, const char *line)
-{
- const char **argv;
- int argc;
- Tokenizer *tok;
-
- tok = tok_init(NULL);
- tok_line(tok, line, &argc, &argv);
- argc = el_parse(el, argc, argv);
- tok_end(tok);
- return (argc);
-}
-
-
-/* el_parse():
- * Command dispatcher
- */
-public int
-el_parse(EditLine *el, int argc, const char *argv[])
-{
- const char *ptr;
- int i;
-
- if (argc < 1)
- return (-1);
- ptr = strchr(argv[0], ':');
- if (ptr != NULL) {
- char *tprog;
- size_t l;
-
- if (ptr == argv[0])
- return (0);
- l = ptr - argv[0] - 1;
- tprog = (char *) el_malloc(l + 1);
- if (tprog == NULL)
- return (0);
- (void) strncpy(tprog, argv[0], l);
- tprog[l] = '\0';
- ptr++;
- l = el_match(el->el_prog, tprog);
- el_free(tprog);
- if (!l)
- return (0);
- } else
- ptr = argv[0];
-
- for (i = 0; cmds[i].name != NULL; i++)
- if (strcmp(cmds[i].name, ptr) == 0) {
- i = (*cmds[i].func) (el, argc, argv);
- return (-i);
- }
- return (-1);
-}
-
-
-/* parse__escape():
- * Parse a string of the form ^<char> \<odigit> \<char> and return
- * the appropriate character or -1 if the escape is not valid
- */
-protected int
-parse__escape(const char **const ptr)
-{
- const char *p;
- int c;
-
- p = *ptr;
-
- if (p[1] == 0)
- return (-1);
-
- if (*p == '\\') {
- p++;
- switch (*p) {
- case 'a':
- c = '\007'; /* Bell */
- break;
- case 'b':
- c = '\010'; /* Backspace */
- break;
- case 't':
- c = '\011'; /* Horizontal Tab */
- break;
- case 'n':
- c = '\012'; /* New Line */
- break;
- case 'v':
- c = '\013'; /* Vertical Tab */
- break;
- case 'f':
- c = '\014'; /* Form Feed */
- break;
- case 'r':
- c = '\015'; /* Carriage Return */
- break;
- case 'e':
- c = '\033'; /* Escape */
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- {
- int cnt, ch;
-
- for (cnt = 0, c = 0; cnt < 3; cnt++) {
- ch = *p++;
- if (ch < '0' || ch > '7') {
- p--;
- break;
- }
- c = (c << 3) | (ch - '0');
- }
- if ((c & 0xffffff00) != 0)
- return (-1);
- --p;
- break;
- }
- default:
- c = *p;
- break;
- }
- } else if (*p == '^' && isalpha((unsigned char) p[1])) {
- p++;
- c = (*p == '?') ? '\177' : (*p & 0237);
- } else
- c = *p;
- *ptr = ++p;
- return (c);
-}
-/* parse__string():
- * Parse the escapes from in and put the raw string out
- */
-protected char *
-parse__string(char *out, const char *in)
-{
- char *rv = out;
- int n;
-
- for (;;)
- switch (*in) {
- case '\0':
- *out = '\0';
- return (rv);
-
- case '\\':
- case '^':
- if ((n = parse__escape(&in)) == -1)
- return (NULL);
- *out++ = n;
- break;
-
- default:
- *out++ = *in++;
- break;
- }
-}
-
-
-/* parse_cmd():
- * Return the command number for the command string given
- * or -1 if one is not found
- */
-protected int
-parse_cmd(EditLine *el, const char *cmd)
-{
- el_bindings_t *b;
-
- for (b = el->el_map.help; b->name != NULL; b++)
- if (strcmp(b->name, cmd) == 0)
- return (b->func);
- return (-1);
-}
diff --git a/main/editline/parse.h b/main/editline/parse.h
deleted file mode 100644
index 4aaef2f83..000000000
--- a/main/editline/parse.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* $NetBSD: parse.h,v 1.4 2000/09/04 22:06:31 lukem Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)parse.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.parse.h: Parser functions
- */
-#ifndef _h_el_parse
-#define _h_el_parse
-
-protected int parse_line(EditLine *, const char *);
-protected int parse__escape(const char ** const);
-protected char *parse__string(char *, const char *);
-protected int parse_cmd(EditLine *, const char *);
-
-#endif /* _h_el_parse */
diff --git a/main/editline/prompt.c b/main/editline/prompt.c
deleted file mode 100644
index 5c069e17a..000000000
--- a/main/editline/prompt.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/* $NetBSD: prompt.c,v 1.9 2002/03/18 16:00:56 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: prompt.c,v 1.9 2002/03/18 16:00:56 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * prompt.c: Prompt printing functions
- */
-#include <stdio.h>
-#include "el.h"
-
-private char *prompt_default(EditLine *);
-private char *prompt_default_r(EditLine *);
-
-/* prompt_default():
- * Just a default prompt, in case the user did not provide one
- */
-private char *
-/*ARGSUSED*/
-prompt_default(EditLine *el)
-{
- static char a[3] = {'?', ' ', '\0'};
-
- return (a);
-}
-
-
-/* prompt_default_r():
- * Just a default rprompt, in case the user did not provide one
- */
-private char *
-/*ARGSUSED*/
-prompt_default_r(EditLine *el)
-{
- static char a[1] = {'\0'};
-
- return (a);
-}
-
-
-/* prompt_print():
- * Print the prompt and update the prompt position.
- * We use an array of integers in case we want to pass
- * literal escape sequences in the prompt and we want a
- * bit to flag them
- */
-protected void
-prompt_print(EditLine *el, int op)
-{
- el_prompt_t *elp;
- char *p;
-
- if (op == EL_PROMPT)
- elp = &el->el_prompt;
- else
- elp = &el->el_rprompt;
- p = (elp->p_func) (el);
- while (*p)
- re_putc(el, *p++, 1);
-
- elp->p_pos.v = el->el_refresh.r_cursor.v;
- elp->p_pos.h = el->el_refresh.r_cursor.h;
-}
-
-
-/* prompt_init():
- * Initialize the prompt stuff
- */
-protected int
-prompt_init(EditLine *el)
-{
-
- el->el_prompt.p_func = prompt_default;
- el->el_prompt.p_pos.v = 0;
- el->el_prompt.p_pos.h = 0;
- el->el_rprompt.p_func = prompt_default_r;
- el->el_rprompt.p_pos.v = 0;
- el->el_rprompt.p_pos.h = 0;
- return (0);
-}
-
-
-/* prompt_end():
- * Clean up the prompt stuff
- */
-protected void
-/*ARGSUSED*/
-prompt_end(EditLine *el)
-{
-}
-
-
-/* prompt_set():
- * Install a prompt printing function
- */
-protected int
-prompt_set(EditLine *el, el_pfunc_t prf, int op)
-{
- el_prompt_t *p;
-
- if (op == EL_PROMPT)
- p = &el->el_prompt;
- else
- p = &el->el_rprompt;
- if (prf == NULL) {
- if (op == EL_PROMPT)
- p->p_func = prompt_default;
- else
- p->p_func = prompt_default_r;
- } else
- p->p_func = prf;
- p->p_pos.v = 0;
- p->p_pos.h = 0;
- return (0);
-}
-
-
-/* prompt_get():
- * Retrieve the prompt printing function
- */
-protected int
-prompt_get(EditLine *el, el_pfunc_t *prf, int op)
-{
-
- if (prf == NULL)
- return (-1);
- if (op == EL_PROMPT)
- *prf = el->el_prompt.p_func;
- else
- *prf = el->el_rprompt.p_func;
- return (0);
-}
diff --git a/main/editline/prompt.h b/main/editline/prompt.h
deleted file mode 100644
index 08810e22a..000000000
--- a/main/editline/prompt.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* $NetBSD: prompt.h,v 1.5 2000/09/04 22:06:31 lukem Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)prompt.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.prompt.h: Prompt printing stuff
- */
-#ifndef _h_el_prompt
-#define _h_el_prompt
-
-#include "histedit.h"
-
-typedef char * (*el_pfunc_t)(EditLine*);
-
-typedef struct el_prompt_t {
- el_pfunc_t p_func; /* Function to return the prompt */
- coord_t p_pos; /* position in the line after prompt */
-} el_prompt_t;
-
-protected void prompt_print(EditLine *, int);
-protected int prompt_set(EditLine *, el_pfunc_t, int);
-protected int prompt_get(EditLine *, el_pfunc_t *, int);
-protected int prompt_init(EditLine *);
-protected void prompt_end(EditLine *);
-
-#endif /* _h_el_prompt */
diff --git a/main/editline/read.c b/main/editline/read.c
deleted file mode 100644
index 80d51da4a..000000000
--- a/main/editline/read.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/* $NetBSD: read.c,v 1.21 2002/03/18 16:00:57 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: read.c,v 1.21 2002/03/18 16:00:57 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * read.c: Clean this junk up! This is horrible code.
- * Terminal read functions
- */
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include "el.h"
-
-#define OKCMD -1
-
-private int read__fixio(int, int);
-private int read_preread(EditLine *);
-private int read_char(EditLine *, char *);
-private int read_getcmd(EditLine *, el_action_t *, char *);
-
-/* read_init():
- * Initialize the read stuff
- */
-protected int
-read_init(EditLine *el)
-{
- /* builtin read_char */
- el->el_read.read_char = read_char;
- return 0;
-}
-
-
-/* el_read_setfn():
- * Set the read char function to the one provided.
- * If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
- */
-protected int
-el_read_setfn(EditLine *el, el_rfunc_t rc)
-{
- el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
- return 0;
-}
-
-
-/* el_read_getfn():
- * return the current read char function, or EL_BUILTIN_GETCFN
- * if it is the default one
- */
-protected el_rfunc_t
-el_read_getfn(EditLine *el)
-{
- return (el->el_read.read_char == read_char) ?
- EL_BUILTIN_GETCFN : el->el_read.read_char;
-}
-
-
-#ifdef DEBUG_EDIT
-private void
-read_debug(EditLine *el)
-{
-
- if (el->el_line.cursor > el->el_line.lastchar)
- (void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
- if (el->el_line.cursor < el->el_line.buffer)
- (void) fprintf(el->el_errfile, "cursor < buffer\r\n");
- if (el->el_line.cursor > el->el_line.limit)
- (void) fprintf(el->el_errfile, "cursor > limit\r\n");
- if (el->el_line.lastchar > el->el_line.limit)
- (void) fprintf(el->el_errfile, "lastchar > limit\r\n");
- if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
- (void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
-}
-#endif /* DEBUG_EDIT */
-
-
-/* read__fixio():
- * Try to recover from a read error
- */
-/* ARGSUSED */
-private int
-read__fixio(int fd, int e)
-{
-
- switch (e) {
- case -1: /* Make sure that the code is reachable */
-
-#ifdef EWOULDBLOCK
- case EWOULDBLOCK:
-#ifndef TRY_AGAIN
-#define TRY_AGAIN
-#endif
-#endif /* EWOULDBLOCK */
-
-#if defined(POSIX) && defined(EAGAIN)
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EAGAIN:
-#ifndef TRY_AGAIN
-#define TRY_AGAIN
-#endif
-#endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
-#endif /* POSIX && EAGAIN */
-
- e = 0;
-#ifdef TRY_AGAIN
-#if defined(F_SETFL) && defined(O_NDELAY)
- if ((e = fcntl(fd, F_GETFL, 0)) == -1)
- return (-1);
-
- if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
- return (-1);
- else
- e = 1;
-#endif /* F_SETFL && O_NDELAY */
-
-#ifdef FIONBIO
- {
- int zero = 0;
-
- if (ioctl(fd, FIONBIO, (ioctl_t) & zero) == -1)
- return (-1);
- else
- e = 1;
- }
-#endif /* FIONBIO */
-
-#endif /* TRY_AGAIN */
- return (e ? 0 : -1);
-
- case EINTR:
- return (0);
-
- default:
- return (-1);
- }
-}
-
-
-/* read_preread():
- * Try to read the stuff in the input queue;
- */
-private int
-read_preread(EditLine *el)
-{
- int chrs = 0;
-
- if (el->el_chared.c_macro.nline) {
- el_free((ptr_t) el->el_chared.c_macro.nline);
- el->el_chared.c_macro.nline = NULL;
- }
- if (el->el_tty.t_mode == ED_IO)
- return (0);
-
-#ifdef FIONREAD
- (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
- if (chrs > 0) {
- char buf[EL_BUFSIZ];
-
- chrs = read(el->el_infd, buf,
- (size_t) MIN(chrs, EL_BUFSIZ - 1));
- if (chrs > 0) {
- buf[chrs] = '\0';
- el->el_chared.c_macro.nline = strdup(buf);
- el_push(el, el->el_chared.c_macro.nline);
- }
- }
-#endif /* FIONREAD */
-
- return (chrs > 0);
-}
-
-
-/* el_push():
- * Push a macro
- */
-public void
-el_push(EditLine *el, char *str)
-{
- c_macro_t *ma = &el->el_chared.c_macro;
-
- if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
- ma->level++;
- ma->macro[ma->level] = str;
- } else {
- term_beep(el);
- term__flush();
- }
-}
-
-
-/* read_getcmd():
- * Return next command from the input stream.
- */
-private int
-read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
-{
- el_action_t cmd = ED_UNASSIGNED;
- int num;
-
- while (cmd == ED_UNASSIGNED || cmd == ED_SEQUENCE_LEAD_IN) {
- if ((num = el_getc(el, ch)) != 1) /* if EOF or error */
- return (num);
-
-#ifdef KANJI
- if ((*ch & 0200)) {
- el->el_state.metanext = 0;
- cmd = CcViMap[' '];
- break;
- } else
-#endif /* KANJI */
-
- if (el->el_state.metanext) {
- el->el_state.metanext = 0;
- *ch |= 0200;
- }
- cmd = el->el_map.current[(unsigned char) *ch];
- if (cmd == ED_SEQUENCE_LEAD_IN) {
- key_value_t val;
- switch (key_get(el, ch, &val)) {
- case XK_CMD:
- cmd = val.cmd;
- break;
- case XK_STR:
- el_push(el, val.str);
- break;
-#ifdef notyet
- case XK_EXE:
- /* XXX: In the future to run a user function */
- RunCommand(val.str);
- break;
-#endif
- default:
- EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
- break;
- }
- }
- if (el->el_map.alt == NULL)
- el->el_map.current = el->el_map.key;
- }
- *cmdnum = cmd;
- return (OKCMD);
-}
-
-
-/* read_char():
- * Read a character from the tty.
- * XXX This routine is the default, but what you are actually looking for
- * is in main/asterisk.c, in ast_el_read_char(). XXX
- */
-private int
-read_char(EditLine *el, char *cp)
-{
- int num_read;
- int tried = 0;
-
- while ((num_read = read(el->el_infd, cp, 1)) == -1)
- if (!tried && read__fixio(el->el_infd, errno) == 0)
- tried = 1;
- else {
- *cp = '\0';
- return (-1);
- }
-
- return (num_read);
-}
-
-
-/* el_getc():
- * Read a character
- */
-public int
-el_getc(EditLine *el, char *cp)
-{
- int num_read;
- c_macro_t *ma = &el->el_chared.c_macro;
-
- term__flush();
- for (;;) {
- if (ma->level < 0) {
- if (!read_preread(el))
- break;
- }
- if (ma->level < 0)
- break;
-
- if (*ma->macro[ma->level] == 0) {
- ma->level--;
- continue;
- }
- *cp = *ma->macro[ma->level]++ & 0377;
- if (*ma->macro[ma->level] == 0) { /* Needed for QuoteMode
- * On */
- ma->level--;
- }
- return (1);
- }
-
-#ifdef DEBUG_READ
- (void) fprintf(el->el_errfile, "Turning raw mode on\n");
-#endif /* DEBUG_READ */
- if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
- return (0);
-
-#ifdef DEBUG_READ
- (void) fprintf(el->el_errfile, "Reading a character\n");
-#endif /* DEBUG_READ */
- /* See main/asterisk.c: ast_el_read_char() */
- num_read = (*el->el_read.read_char)(el, cp);
-#ifdef DEBUG_READ
- (void) fprintf(el->el_errfile, "Got it %c\n", *cp);
-#endif /* DEBUG_READ */
- return (num_read);
-}
-
-
-public const char *
-el_gets(EditLine *el, int *nread)
-{
- int retval;
- el_action_t cmdnum = 0;
- int num; /* how many chars we have read at NL */
- char ch;
-#ifdef FIONREAD
- c_macro_t *ma = &el->el_chared.c_macro;
-#endif /* FIONREAD */
-
- if (el->el_flags & HANDLE_SIGNALS)
- sig_set(el);
-
- if (el->el_flags & NO_TTY) {
- char *cp = el->el_line.buffer;
- size_t idx;
-
- while ((*el->el_read.read_char)(el, cp) == 1) {
- /* make sure there is space for next character */
- if (cp + 1 >= el->el_line.limit) {
- idx = (cp - el->el_line.buffer);
- if (!ch_enlargebufs(el, 2))
- break;
- cp = &el->el_line.buffer[idx];
- }
- cp++;
- if (cp[-1] == '\r' || cp[-1] == '\n')
- break;
- }
-
- el->el_line.cursor = el->el_line.lastchar = cp;
- *cp = '\0';
- if (nread)
- *nread = el->el_line.cursor - el->el_line.buffer;
- return (el->el_line.buffer);
- }
- re_clear_display(el); /* reset the display stuff */
- ch_reset(el);
-
-#ifdef FIONREAD
- if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
- long chrs = 0;
-
- (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
- if (chrs == 0) {
- if (tty_rawmode(el) < 0) {
- if (nread)
- *nread = 0;
- return (NULL);
- }
- }
- }
-#endif /* FIONREAD */
-
- re_refresh(el); /* print the prompt */
-
- if (el->el_flags & EDIT_DISABLED) {
- char *cp = el->el_line.buffer;
- size_t idx;
-
- term__flush();
-
- while ((*el->el_read.read_char)(el, cp) == 1) {
- /* make sure there is space next character */
- if (cp + 1 >= el->el_line.limit) {
- idx = (cp - el->el_line.buffer);
- if (!ch_enlargebufs(el, 2))
- break;
- cp = &el->el_line.buffer[idx];
- }
- cp++;
- if (cp[-1] == '\r' || cp[-1] == '\n')
- break;
- }
-
- el->el_line.cursor = el->el_line.lastchar = cp;
- *cp = '\0';
- if (nread)
- *nread = el->el_line.cursor - el->el_line.buffer;
- return (el->el_line.buffer);
- }
- for (num = OKCMD; num == OKCMD;) { /* while still editing this
- * line */
-#ifdef DEBUG_EDIT
- read_debug(el);
-#endif /* DEBUG_EDIT */
- /* if EOF or error */
- if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
-#ifdef DEBUG_READ
- (void) fprintf(el->el_errfile,
- "Returning from el_gets %d\n", num);
-#endif /* DEBUG_READ */
- break;
- }
- if ((int) cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */
-#ifdef DEBUG_EDIT
- (void) fprintf(el->el_errfile,
- "ERROR: illegal command from key 0%o\r\n", ch);
-#endif /* DEBUG_EDIT */
- continue; /* try again */
- }
- /* now do the real command */
-#ifdef DEBUG_READ
- {
- el_bindings_t *b;
- for (b = el->el_map.help; b->name; b++)
- if (b->func == cmdnum)
- break;
- if (b->name)
- (void) fprintf(el->el_errfile,
- "Executing %s\n", b->name);
- else
- (void) fprintf(el->el_errfile,
- "Error command = %d\n", cmdnum);
- }
-#endif /* DEBUG_READ */
- retval = (*el->el_map.func[cmdnum]) (el, ch);
-
- /* save the last command here */
- el->el_state.lastcmd = cmdnum;
-
- /* use any return value */
- switch (retval) {
- case CC_CURSOR:
- el->el_state.argument = 1;
- el->el_state.doingarg = 0;
- re_refresh_cursor(el);
- break;
-
- case CC_REDISPLAY:
- re_clear_lines(el);
- re_clear_display(el);
- /* FALLTHROUGH */
-
- case CC_REFRESH:
- el->el_state.argument = 1;
- el->el_state.doingarg = 0;
- re_refresh(el);
- break;
-
- case CC_REFRESH_BEEP:
- el->el_state.argument = 1;
- el->el_state.doingarg = 0;
- re_refresh(el);
- term_beep(el);
- break;
-
- case CC_NORM: /* normal char */
- el->el_state.argument = 1;
- el->el_state.doingarg = 0;
- break;
-
- case CC_ARGHACK: /* Suggested by Rich Salz */
- /* <rsalz@pineapple.bbn.com> */
- break; /* keep going... */
-
- case CC_EOF: /* end of file typed */
- num = 0;
- break;
-
- case CC_NEWLINE: /* normal end of line */
- num = el->el_line.lastchar - el->el_line.buffer;
- break;
-
- case CC_FATAL: /* fatal error, reset to known state */
-#ifdef DEBUG_READ
- (void) fprintf(el->el_errfile,
- "*** editor fatal ERROR ***\r\n\n");
-#endif /* DEBUG_READ */
- /* put (real) cursor in a known place */
- re_clear_display(el); /* reset the display stuff */
- ch_reset(el); /* reset the input pointers */
- re_refresh(el); /* print the prompt again */
- el->el_state.argument = 1;
- el->el_state.doingarg = 0;
- break;
-
- case CC_ERROR:
- default: /* functions we don't know about */
-#ifdef DEBUG_READ
- (void) fprintf(el->el_errfile,
- "*** editor ERROR ***\r\n\n");
-#endif /* DEBUG_READ */
- el->el_state.argument = 1;
- el->el_state.doingarg = 0;
- term_beep(el);
- term__flush();
- break;
- }
- }
-
- /* make sure the tty is set up correctly */
- (void) tty_cookedmode(el);
- term__flush(); /* flush any buffered output */
- if (el->el_flags & HANDLE_SIGNALS)
- sig_clr(el);
- if (nread)
- *nread = num;
- return (num ? el->el_line.buffer : NULL);
-}
diff --git a/main/editline/read.h b/main/editline/read.h
deleted file mode 100644
index b01e77db2..000000000
--- a/main/editline/read.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $NetBSD: read.h,v 1.1 2001/09/27 19:29:50 christos Exp $ */
-
-/*-
- * Copyright (c) 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Anthony Mallet.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * el.read.h: Character reading functions
- */
-#ifndef _h_el_read
-#define _h_el_read
-
-typedef int (*el_rfunc_t)(EditLine *, char *);
-
-typedef struct el_read_t {
- el_rfunc_t read_char; /* Function to read a character */
-} el_read_t;
-
-protected int read_init(EditLine *);
-protected int el_read_setfn(EditLine *, el_rfunc_t);
-protected el_rfunc_t el_read_getfn(EditLine *);
-
-#endif /* _h_el_read */
diff --git a/main/editline/readline.c b/main/editline/readline.c
deleted file mode 100644
index 3a62df628..000000000
--- a/main/editline/readline.c
+++ /dev/null
@@ -1,1664 +0,0 @@
-/* $NetBSD: readline.c,v 1.21 2002/03/18 16:20:36 christos Exp $ */
-
-/*-
- * Copyright (c) 1997 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Jaromir Dolecek.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-__RCSID("$NetBSD: readline.c,v 1.21 2002/03/18 16:20:36 christos Exp $");
-#endif /* not lint && not SCCSID */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <string.h>
-#include <pwd.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-
-#ifdef SOLARIS
-#include <alloca.h>
-#endif
-
-#include "histedit.h"
-#include "readline/readline.h"
-#include "el.h"
-#include "fcns.h" /* for EL_NUM_FCNS */
-
-/* for rl_complete() */
-#define TAB '\r'
-
-/* see comment at the #ifdef for sense of this */
-#define GDB_411_HACK
-
-/* readline compatibility stuff - look at readline sources/documentation */
-/* to see what these variables mean */
-const char *rl_library_version = "EditLine wrapper";
-static char empty[] = { '\0' };
-static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
-static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
- '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
-char *rl_readline_name = empty;
-FILE *rl_instream = NULL;
-FILE *rl_outstream = NULL;
-int rl_point = 0;
-int rl_end = 0;
-char *rl_line_buffer = NULL;
-
-int history_base = 1; /* probably never subject to change */
-int history_length = 0;
-int max_input_history = 0;
-char history_expansion_char = '!';
-char history_subst_char = '^';
-char *history_no_expand_chars = expand_chars;
-Function *history_inhibit_expansion_function = NULL;
-
-int rl_inhibit_completion = 0;
-int rl_attempted_completion_over = 0;
-char *rl_basic_word_break_characters = break_chars;
-char *rl_completer_word_break_characters = NULL;
-char *rl_completer_quote_characters = NULL;
-CPFunction *rl_completion_entry_function = NULL;
-CPPFunction *rl_attempted_completion_function = NULL;
-
-/*
- * This is set to character indicating type of completion being done by
- * rl_complete_internal(); this is available for application completion
- * functions.
- */
-int rl_completion_type = 0;
-
-/*
- * If more than this number of items results from query for possible
- * completions, we ask user if they are sure to really display the list.
- */
-int rl_completion_query_items = 100;
-
-/*
- * List of characters which are word break characters, but should be left
- * in the parsed text when it is passed to the completion function.
- * Shell uses this to help determine what kind of completing to do.
- */
-char *rl_special_prefixes = (char *)NULL;
-
-/*
- * This is the character appended to the completed words if at the end of
- * the line. Default is ' ' (a space).
- */
-int rl_completion_append_character = ' ';
-
-/* stuff below is used internally by libedit for readline emulation */
-
-/* if not zero, non-unique completions always show list of possible matches */
-static int _rl_complete_show_all = 0;
-
-static History *h = NULL;
-static EditLine *e = NULL;
-static int el_rl_complete_cmdnum = 0;
-
-/* internal functions */
-static unsigned char _el_rl_complete(EditLine *, int);
-static char *_get_prompt(EditLine *);
-static HIST_ENTRY *_move_history(int);
-static int _history_search_gen(const char *, int, int);
-static int _history_expand_command(const char *, size_t, char **);
-static char *_rl_compat_sub(const char *, const char *,
- const char *, int);
-static int rl_complete_internal(int);
-static int _rl_qsort_string_compare(const void *, const void *);
-
-/*
- * needed for prompt switching in readline()
- */
-static char *el_rl_prompt = NULL;
-
-
-/* ARGSUSED */
-static char *
-_get_prompt(EditLine *el)
-{
- return (el_rl_prompt);
-}
-
-
-/*
- * generic function for moving around history
- */
-static HIST_ENTRY *
-_move_history(int op)
-{
- HistEvent ev;
- static HIST_ENTRY rl_he;
-
- if (history(h, &ev, op) != 0)
- return (HIST_ENTRY *) NULL;
-
- rl_he.line = ev.str;
- rl_he.data = "";
-
- return (&rl_he);
-}
-
-
-/*
- * READLINE compatibility stuff
- */
-
-/*
- * initialize rl compat stuff
- */
-int
-rl_initialize(void)
-{
- HistEvent ev;
- const LineInfo *li;
- int i;
- int editmode = 1;
- struct termios t;
-
- if (e != NULL)
- el_end(e);
- if (h != NULL)
- history_end(h);
-
- if (!rl_instream)
- rl_instream = stdin;
- if (!rl_outstream)
- rl_outstream = stdout;
-
- /*
- * See if we don't really want to run the editor
- */
- if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
- editmode = 0;
-
- e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
-
- if (!editmode)
- el_set(e, EL_EDITMODE, 0);
-
- h = history_init();
- if (!e || !h)
- return (-1);
-
- history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
- history_length = 0;
- max_input_history = INT_MAX;
- el_set(e, EL_HIST, history, h);
-
- /* for proper prompt printing in readline() */
- el_rl_prompt = strdup("");
- el_set(e, EL_PROMPT, _get_prompt);
- el_set(e, EL_SIGNAL, 1);
-
- /* set default mode to "emacs"-style and read setting afterwards */
- /* so this can be overriden */
- el_set(e, EL_EDITOR, "emacs");
-
- /*
- * Word completition - this has to go AFTER rebinding keys
- * to emacs-style.
- */
- el_set(e, EL_ADDFN, "rl_complete",
- "ReadLine compatible completition function",
- _el_rl_complete);
- el_set(e, EL_BIND, "^I", "rl_complete", NULL);
-
- /*
- * Find out where the rl_complete function was added; this is
- * used later to detect that lastcmd was also rl_complete.
- */
- for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) {
- if (e->el_map.func[i] == _el_rl_complete) {
- el_rl_complete_cmdnum = i;
- break;
- }
- }
-
- /* read settings from configuration file */
- el_source(e, NULL);
-
- /*
- * Unfortunately, some applications really do use rl_point
- * and rl_line_buffer directly.
- */
- li = el_line(e);
- /* a cheesy way to get rid of const cast. */
- rl_line_buffer = memchr(li->buffer, *li->buffer, 1);
- rl_point = rl_end = 0;
-
- return (0);
-}
-
-
-/*
- * read one line from input stream and return it, chomping
- * trailing newline (if there is any)
- */
-char *
-readline(const char *prompt)
-{
- HistEvent ev;
- int count;
- const char *ret;
- char *buf;
-
- if (e == NULL || h == NULL)
- rl_initialize();
-
- /* update prompt accordingly to what has been passed */
- if (!prompt)
- prompt = "";
- if (strcmp(el_rl_prompt, prompt) != 0) {
- free(el_rl_prompt);
- el_rl_prompt = strdup(prompt);
- }
- /* get one line from input stream */
- ret = el_gets(e, &count);
-
- if (ret && count > 0) {
- int lastidx;
-
- buf = strdup(ret);
- lastidx = count - 1;
- if (buf[lastidx] == '\n')
- buf[lastidx] = '\0';
- } else
- buf = NULL;
-
- history(h, &ev, H_GETSIZE);
- history_length = ev.num;
-
- return buf;
-}
-
-/*
- * history functions
- */
-
-/*
- * is normally called before application starts to use
- * history expansion functions
- */
-void
-using_history(void)
-{
- if (h == NULL || e == NULL)
- rl_initialize();
-}
-
-
-/*
- * substitute ``what'' with ``with'', returning resulting string; if
- * globally == 1, substitutes all occurences of what, otherwise only the
- * first one
- */
-static char *
-_rl_compat_sub(const char *str, const char *what, const char *with,
- int globally)
-{
- char *result;
- const char *temp, *new;
- int len, with_len, what_len, add;
- size_t size, i;
-
- result = malloc((size = 16));
- temp = str;
- with_len = strlen(with);
- what_len = strlen(what);
- len = 0;
- do {
- new = strstr(temp, what);
- if (new) {
- i = new - temp;
- add = i + with_len;
- if (i + add + 1 >= size) {
- size += add + 1;
- result = realloc(result, size);
- }
- (void) strncpy(&result[len], temp, i);
- len += i;
- (void) strcpy(&result[len], with); /* safe */
- len += with_len;
- temp = new + what_len;
- } else {
- add = strlen(temp);
- if (len + add + 1 >= size) {
- size += add + 1;
- result = realloc(result, size);
- }
- (void) strcpy(&result[len], temp); /* safe */
- len += add;
- temp = NULL;
- }
- } while (temp && globally);
- result[len] = '\0';
-
- return (result);
-}
-
-
-/*
- * the real function doing history expansion - takes as argument command
- * to do and data upon which the command should be executed
- * does expansion the way I've understood readline documentation
- * word designator ``%'' isn't supported (yet ?)
- *
- * returns 0 if data was not modified, 1 if it was and 2 if the string
- * should be only printed and not executed; in case of error,
- * returns -1 and *result points to NULL
- * it's callers responsibility to free() string returned in *result
- */
-static int
-_history_expand_command(const char *command, size_t cmdlen, char **result)
-{
- char **arr, *tempcmd, *line, *search = NULL, *cmd;
- const char *event_data = NULL;
- static char *from = NULL, *to = NULL;
- int start = -1, end = -1, max, i, idx;
- int h_on = 0, t_on = 0, r_on = 0, e_on = 0, p_on = 0, g_on = 0;
- int event_num = 0, retval;
- size_t cmdsize;
-
- *result = NULL;
-
- cmd = alloca(cmdlen + 1);
- (void) strncpy(cmd, command, cmdlen);
- cmd[cmdlen] = 0;
-
- idx = 1;
- /* find out which event to take */
- if (cmd[idx] == history_expansion_char) {
- event_num = history_length;
- idx++;
- } else {
- int off, num;
- size_t len;
- off = idx;
- while (cmd[off] && !strchr(":^$*-%", cmd[off]))
- off++;
- num = atoi(&cmd[idx]);
- if (num != 0) {
- event_num = num;
- if (num < 0)
- event_num += history_length + 1;
- } else {
- int prefix = 1, curr_num;
- HistEvent ev;
-
- len = off - idx;
- if (cmd[idx] == '?') {
- idx++, len--;
- if (cmd[off - 1] == '?')
- len--;
- else if (cmd[off] != '\n' && cmd[off] != '\0')
- return (-1);
- prefix = 0;
- }
- search = alloca(len + 1);
- (void) strncpy(search, &cmd[idx], len);
- search[len] = '\0';
-
- if (history(h, &ev, H_CURR) != 0)
- return (-1);
- curr_num = ev.num;
-
- if (prefix)
- retval = history_search_prefix(search, -1);
- else
- retval = history_search(search, -1);
-
- if (retval == -1) {
- fprintf(rl_outstream, "%s: Event not found\n",
- search);
- return (-1);
- }
- if (history(h, &ev, H_CURR) != 0)
- return (-1);
- event_data = ev.str;
-
- /* roll back to original position */
- history(h, &ev, H_NEXT_EVENT, curr_num);
- }
- idx = off;
- }
-
- if (!event_data && event_num >= 0) {
- HIST_ENTRY *rl_he;
- rl_he = history_get(event_num);
- if (!rl_he)
- return (0);
- event_data = rl_he->line;
- } else
- return (-1);
-
- if (cmd[idx] != ':')
- return (-1);
- cmd += idx + 1;
-
- /* recognize cmd */
- if (*cmd == '^')
- start = end = 1, cmd++;
- else if (*cmd == '$')
- start = end = -1, cmd++;
- else if (*cmd == '*')
- start = 1, end = -1, cmd++;
- else if (isdigit((unsigned char) *cmd)) {
- const char *temp;
- int shifted = 0;
-
- start = atoi(cmd);
- temp = cmd;
- for (; isdigit((unsigned char) *cmd); cmd++);
- if (temp != cmd)
- shifted = 1;
- if (shifted && *cmd == '-') {
- if (!isdigit((unsigned char) *(cmd + 1)))
- end = -2;
- else {
- end = atoi(cmd + 1);
- for (; isdigit((unsigned char) *cmd); cmd++);
- }
- } else if (shifted && *cmd == '*')
- end = -1, cmd++;
- else if (shifted)
- end = start;
- }
- if (*cmd == ':')
- cmd++;
-
- line = strdup(event_data);
- for (; *cmd; cmd++) {
- if (*cmd == ':')
- continue;
- else if (*cmd == 'h')
- h_on = 1 | g_on, g_on = 0;
- else if (*cmd == 't')
- t_on = 1 | g_on, g_on = 0;
- else if (*cmd == 'r')
- r_on = 1 | g_on, g_on = 0;
- else if (*cmd == 'e')
- e_on = 1 | g_on, g_on = 0;
- else if (*cmd == 'p')
- p_on = 1 | g_on, g_on = 0;
- else if (*cmd == 'g')
- g_on = 2;
- else if (*cmd == 's' || *cmd == '&') {
- char *what, *with, delim;
- int len, from_len;
- size_t size;
-
- if (*cmd == '&' && (from == NULL || to == NULL))
- continue;
- else if (*cmd == 's') {
- delim = *(++cmd), cmd++;
- size = 16;
- what = realloc(from, size);
- len = 0;
- for (; *cmd && *cmd != delim; cmd++) {
- if (*cmd == '\\'
- && *(cmd + 1) == delim)
- cmd++;
- if (len >= size)
- what = realloc(what,
- (size <<= 1));
- what[len++] = *cmd;
- }
- what[len] = '\0';
- from = what;
- if (*what == '\0') {
- free(what);
- if (search)
- from = strdup(search);
- else {
- from = NULL;
- return (-1);
- }
- }
- cmd++; /* shift after delim */
- if (!*cmd)
- continue;
-
- size = 16;
- with = realloc(to, size);
- len = 0;
- from_len = strlen(from);
- for (; *cmd && *cmd != delim; cmd++) {
- if (len + from_len + 1 >= size) {
- size += from_len + 1;
- with = realloc(with, size);
- }
- if (*cmd == '&') {
- /* safe */
- (void) strcpy(&with[len], from);
- len += from_len;
- continue;
- }
- if (*cmd == '\\'
- && (*(cmd + 1) == delim
- || *(cmd + 1) == '&'))
- cmd++;
- with[len++] = *cmd;
- }
- with[len] = '\0';
- to = with;
-
- tempcmd = _rl_compat_sub(line, from, to,
- (g_on) ? 1 : 0);
- free(line);
- line = tempcmd;
- g_on = 0;
- }
- }
- }
-
- arr = history_tokenize(line);
- free(line); /* no more needed */
- if (arr && *arr == NULL)
- free(arr), arr = NULL;
- if (!arr)
- return (-1);
-
- /* find out max valid idx to array of array */
- max = 0;
- for (i = 0; arr[i]; i++)
- max++;
- max--;
-
- /* set boundaries to something relevant */
- if (start < 0)
- start = 1;
- if (end < 0)
- end = max - ((end < -1) ? 1 : 0);
-
- /* check boundaries ... */
- if (start > max || end > max || start > end)
- return (-1);
-
- for (i = 0; i <= max; i++) {
- char *temp;
- if (h_on && (i == 1 || h_on > 1) &&
- (temp = strrchr(arr[i], '/')))
- *(temp + 1) = '\0';
- if (t_on && (i == 1 || t_on > 1) &&
- (temp = strrchr(arr[i], '/')))
- (void) strcpy(arr[i], temp + 1);
- if (r_on && (i == 1 || r_on > 1) &&
- (temp = strrchr(arr[i], '.')))
- *temp = '\0';
- if (e_on && (i == 1 || e_on > 1) &&
- (temp = strrchr(arr[i], '.')))
- (void) strcpy(arr[i], temp);
- }
-
- cmdsize = 1, cmdlen = 0;
- tempcmd = malloc(cmdsize);
- for (i = start; start <= i && i <= end; i++) {
- int arr_len;
-
- arr_len = strlen(arr[i]);
- if (cmdlen + arr_len + 1 >= cmdsize) {
- cmdsize += arr_len + 1;
- tempcmd = realloc(tempcmd, cmdsize);
- }
- (void) strcpy(&tempcmd[cmdlen], arr[i]); /* safe */
- cmdlen += arr_len;
- tempcmd[cmdlen++] = ' '; /* add a space */
- }
- while (cmdlen > 0 && isspace((unsigned char) tempcmd[cmdlen - 1]))
- cmdlen--;
- tempcmd[cmdlen] = '\0';
-
- *result = tempcmd;
-
- for (i = 0; i <= max; i++)
- free(arr[i]);
- free(arr), arr = (char **) NULL;
- return (p_on) ? 2 : 1;
-}
-
-
-/*
- * csh-style history expansion
- */
-int
-history_expand(char *str, char **output)
-{
- int i, retval = 0, idx;
- size_t size;
- char *temp, *result;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- *output = strdup(str); /* do it early */
-
- if (str[0] == history_subst_char) {
- /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
- temp = alloca(4 + strlen(str) + 1);
- temp[0] = temp[1] = history_expansion_char;
- temp[2] = ':';
- temp[3] = 's';
- (void) strcpy(temp + 4, str);
- str = temp;
- }
-#define ADD_STRING(what, len) \
- { \
- if (idx + len + 1 > size) \
- result = realloc(result, (size += len + 1)); \
- (void)strncpy(&result[idx], what, len); \
- idx += len; \
- result[idx] = '\0'; \
- }
-
- result = NULL;
- size = idx = 0;
- for (i = 0; str[i];) {
- int start, j, loop_again;
- size_t len;
-
- loop_again = 1;
- start = j = i;
-loop:
- for (; str[j]; j++) {
- if (str[j] == '\\' &&
- str[j + 1] == history_expansion_char) {
- (void) strcpy(&str[j], &str[j + 1]);
- continue;
- }
- if (!loop_again) {
- if (str[j] == '?') {
- while (str[j] && str[++j] != '?');
- if (str[j] == '?')
- j++;
- } else if (isspace((unsigned char) str[j]))
- break;
- }
- if (str[j] == history_expansion_char
- && !strchr(history_no_expand_chars, str[j + 1])
- && (!history_inhibit_expansion_function ||
- (*history_inhibit_expansion_function)(str, j) == 0))
- break;
- }
-
- if (str[j] && str[j + 1] != '#' && loop_again) {
- i = j;
- j++;
- if (str[j] == history_expansion_char)
- j++;
- loop_again = 0;
- goto loop;
- }
- len = i - start;
- temp = &str[start];
- ADD_STRING(temp, len);
-
- if (str[i] == '\0' || str[i] != history_expansion_char
- || str[i + 1] == '#') {
- len = j - i;
- temp = &str[i];
- ADD_STRING(temp, len);
- if (start == 0)
- retval = 0;
- else
- retval = 1;
- break;
- }
- retval = _history_expand_command(&str[i], (size_t) (j - i),
- &temp);
- if (retval != -1) {
- len = strlen(temp);
- ADD_STRING(temp, len);
- }
- i = j;
- } /* for(i ...) */
-
- if (retval == 2) {
- add_history(temp);
-#ifdef GDB_411_HACK
- /* gdb 4.11 has been shipped with readline, where */
- /* history_expand() returned -1 when the line */
- /* should not be executed; in readline 2.1+ */
- /* it should return 2 in such a case */
- retval = -1;
-#endif
- }
- free(*output);
- *output = result;
-
- return (retval);
-}
-
-
-/*
- * Parse the string into individual tokens, similarily to how shell would do it.
- */
-char **
-history_tokenize(const char *str)
-{
- int size = 1, result_idx = 0, i, start;
- size_t len;
- char **result = NULL, *temp, delim = '\0';
-
- for (i = 0; str[i]; i++) {
- while (isspace((unsigned char) str[i]))
- i++;
- start = i;
- for (; str[i]; i++) {
- if (str[i] == '\\') {
- if (str[i+1] != '\0')
- i++;
- } else if (str[i] == delim)
- delim = '\0';
- else if (!delim &&
- (isspace((unsigned char) str[i]) ||
- strchr("()<>;&|$", str[i])))
- break;
- else if (!delim && strchr("'`\"", str[i]))
- delim = str[i];
- }
-
- if (result_idx + 2 >= size) {
- size <<= 1;
- result = realloc(result, size * sizeof(char *));
- }
- len = i - start;
- temp = malloc(len + 1);
- (void) strncpy(temp, &str[start], len);
- temp[len] = '\0';
- result[result_idx++] = temp;
- result[result_idx] = NULL;
- }
-
- return (result);
-}
-
-
-/*
- * limit size of history record to ``max'' events
- */
-void
-stifle_history(int max)
-{
- HistEvent ev;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- if (history(h, &ev, H_SETSIZE, max) == 0)
- max_input_history = max;
-}
-
-
-/*
- * "unlimit" size of history - set the limit to maximum allowed int value
- */
-int
-unstifle_history(void)
-{
- HistEvent ev;
- int omax;
-
- history(h, &ev, H_SETSIZE, INT_MAX);
- omax = max_input_history;
- max_input_history = INT_MAX;
- return (omax); /* some value _must_ be returned */
-}
-
-
-int
-history_is_stifled(void)
-{
-
- /* cannot return true answer */
- return (max_input_history != INT_MAX);
-}
-
-
-/*
- * read history from a file given
- */
-int
-read_history(const char *filename)
-{
- HistEvent ev;
-
- if (h == NULL || e == NULL)
- rl_initialize();
- return (history(h, &ev, H_LOAD, filename));
-}
-
-
-/*
- * write history to a file given
- */
-int
-write_history(const char *filename)
-{
- HistEvent ev;
-
- if (h == NULL || e == NULL)
- rl_initialize();
- return (history(h, &ev, H_SAVE, filename));
-}
-
-
-/*
- * returns history ``num''th event
- *
- * returned pointer points to static variable
- */
-HIST_ENTRY *
-history_get(int num)
-{
- static HIST_ENTRY she;
- HistEvent ev;
- int i = 1, curr_num;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- /* rewind to beginning */
- if (history(h, &ev, H_CURR) != 0)
- return (NULL);
- curr_num = ev.num;
- if (history(h, &ev, H_LAST) != 0)
- return (NULL); /* error */
- while (i < num && history(h, &ev, H_PREV) == 0)
- i++;
- if (i != num)
- return (NULL); /* not so many entries */
-
- she.line = ev.str;
- she.data = NULL;
-
- /* rewind history to the same event it was before */
- (void) history(h, &ev, H_FIRST);
- (void) history(h, &ev, H_NEXT_EVENT, curr_num);
-
- return (&she);
-}
-
-
-/*
- * add the line to history table
- */
-int
-add_history(const char *line)
-{
- HistEvent ev;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- (void) history(h, &ev, H_ENTER, line);
- if (history(h, &ev, H_GETSIZE) == 0)
- history_length = ev.num;
-
- return (!(history_length > 0)); /* return 0 if all is okay */
-}
-
-
-/*
- * clear the history list - delete all entries
- */
-void
-clear_history(void)
-{
- HistEvent ev;
-
- history(h, &ev, H_CLEAR);
-}
-
-
-/*
- * returns offset of the current history event
- */
-int
-where_history(void)
-{
- HistEvent ev;
- int curr_num, off;
-
- if (history(h, &ev, H_CURR) != 0)
- return (0);
- curr_num = ev.num;
-
- history(h, &ev, H_FIRST);
- off = 1;
- while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
- off++;
-
- return (off);
-}
-
-
-/*
- * returns current history event or NULL if there is no such event
- */
-HIST_ENTRY *
-current_history(void)
-{
-
- return (_move_history(H_CURR));
-}
-
-
-/*
- * returns total number of bytes history events' data are using
- */
-int
-history_total_bytes(void)
-{
- HistEvent ev;
- int curr_num, size;
-
- if (history(h, &ev, H_CURR) != 0)
- return (-1);
- curr_num = ev.num;
-
- history(h, &ev, H_FIRST);
- size = 0;
- do
- size += strlen(ev.str);
- while (history(h, &ev, H_NEXT) == 0);
-
- /* get to the same position as before */
- history(h, &ev, H_PREV_EVENT, curr_num);
-
- return (size);
-}
-
-
-/*
- * sets the position in the history list to ``pos''
- */
-int
-history_set_pos(int pos)
-{
- HistEvent ev;
- int off, curr_num;
-
- if (pos > history_length || pos < 0)
- return (-1);
-
- history(h, &ev, H_CURR);
- curr_num = ev.num;
- history(h, &ev, H_FIRST);
- off = 0;
- while (off < pos && history(h, &ev, H_NEXT) == 0)
- off++;
-
- if (off != pos) { /* do a rollback in case of error */
- history(h, &ev, H_FIRST);
- history(h, &ev, H_NEXT_EVENT, curr_num);
- return (-1);
- }
- return (0);
-}
-
-
-/*
- * returns previous event in history and shifts pointer accordingly
- */
-HIST_ENTRY *
-previous_history(void)
-{
-
- return (_move_history(H_PREV));
-}
-
-
-/*
- * returns next event in history and shifts pointer accordingly
- */
-HIST_ENTRY *
-next_history(void)
-{
-
- return (_move_history(H_NEXT));
-}
-
-
-/*
- * generic history search function
- */
-static int
-_history_search_gen(const char *str, int direction, int pos)
-{
- HistEvent ev;
- const char *strp;
- int curr_num;
-
- if (history(h, &ev, H_CURR) != 0)
- return (-1);
- curr_num = ev.num;
-
- for (;;) {
- strp = strstr(ev.str, str);
- if (strp && (pos < 0 || &ev.str[pos] == strp))
- return (int) (strp - ev.str);
- if (history(h, &ev, direction < 0 ? H_PREV : H_NEXT) != 0)
- break;
- }
-
- history(h, &ev, direction < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
-
- return (-1);
-}
-
-
-/*
- * searches for first history event containing the str
- */
-int
-history_search(const char *str, int direction)
-{
-
- return (_history_search_gen(str, direction, -1));
-}
-
-
-/*
- * searches for first history event beginning with str
- */
-int
-history_search_prefix(const char *str, int direction)
-{
-
- return (_history_search_gen(str, direction, 0));
-}
-
-
-/*
- * search for event in history containing str, starting at offset
- * abs(pos); continue backward, if pos<0, forward otherwise
- */
-/* ARGSUSED */
-int
-history_search_pos(const char *str, int direction, int pos)
-{
- HistEvent ev;
- int curr_num, off;
-
- off = (pos > 0) ? pos : -pos;
- pos = (pos > 0) ? 1 : -1;
-
- if (history(h, &ev, H_CURR) != 0)
- return (-1);
- curr_num = ev.num;
-
- if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
- return (-1);
-
-
- for (;;) {
- if (strstr(ev.str, str))
- return (off);
- if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
- break;
- }
-
- /* set "current" pointer back to previous state */
- history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
-
- return (-1);
-}
-
-
-/********************************/
-/* completition functions */
-
-/*
- * does tilde expansion of strings of type ``~user/foo''
- * if ``user'' isn't valid user name or ``txt'' doesn't start
- * w/ '~', returns pointer to strdup()ed copy of ``txt''
- *
- * it's callers's responsibility to free() returned string
- */
-char *
-tilde_expand(char *txt)
-{
- struct passwd *pass;
- char *temp;
- size_t len = 0;
-
- if (txt[0] != '~')
- return (strdup(txt));
-
- temp = strchr(txt + 1, '/');
- if (temp == NULL)
- temp = strdup(txt + 1);
- else {
- len = temp - txt + 1; /* text until string after slash */
- temp = malloc(len);
- (void) strncpy(temp, txt + 1, len - 2);
- temp[len - 2] = '\0';
- }
- pass = getpwnam(temp);
- free(temp); /* value no more needed */
- if (pass == NULL)
- return (strdup(txt));
-
- /* update pointer txt to point at string immedially following */
- /* first slash */
- txt += len;
-
- temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1);
- (void) sprintf(temp, "%s/%s", pass->pw_dir, txt);
-
- return (temp);
-}
-
-
-/*
- * return first found file name starting by the ``text'' or NULL if no
- * such file can be found.
- * The first ``state'' matches are ignored.
- *
- * it's caller's responsibility to free returned string
- */
-char *
-filename_completion_function(const char *text, int state)
-{
- DIR *dir = NULL;
- char *filename = NULL, *dirname = NULL;
- size_t filename_len = 0;
- struct dirent *entry;
- char *temp;
- size_t len;
-
- temp = strrchr(text, '/');
- if (temp) {
- temp++;
- filename = realloc(filename, strlen(temp) + 1);
- (void) strcpy(filename, temp);
- len = temp - text; /* including last slash */
- dirname = realloc(dirname, len + 1);
- (void) strncpy(dirname, text, len);
- dirname[len] = '\0';
- } else {
- filename = strdup(text);
- dirname = NULL;
- }
-
- /* support for ``~user'' syntax */
- if (dirname && *dirname == '~') {
- temp = tilde_expand(dirname);
- dirname = realloc(dirname, strlen(temp) + 1);
- (void) strcpy(dirname, temp); /* safe */
- free(temp); /* no longer needed */
- }
- /* will be used in cycle */
- filename_len = strlen(filename);
-
- dir = opendir(dirname ? dirname : ".");
- if (!dir)
- return (NULL); /* cannot open the directory */
-
- /* find the match */
- while ((entry = readdir(dir)) != NULL) {
- /* otherwise, get first entry where first */
- /* filename_len characters are equal */
- if (
-#if defined(__SVR4) || defined(__linux__)
- strlen(entry->d_name) >= filename_len
-#else
- entry->d_namlen >= filename_len
-#endif
- && strncmp(entry->d_name, filename,
- filename_len) == 0
- && (state-- == 0))
- break;
- }
-
- if (entry) { /* match found */
-
- struct stat stbuf;
-#if defined(__SVR4) || defined(__linux__)
- len = strlen(entry->d_name) +
-#else
- len = entry->d_namlen +
-#endif
- ((dirname) ? strlen(dirname) : 0) + 1 + 1;
- temp = malloc(len);
- (void) sprintf(temp, "%s%s",
- dirname ? dirname : "", entry->d_name); /* safe */
-
- /* test, if it's directory */
- if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode))
- strcat(temp, "/"); /* safe */
- } else
- temp = NULL;
- closedir(dir);
-
- return (temp);
-}
-
-
-/*
- * a completion generator for usernames; returns _first_ username
- * which starts with supplied text
- * text contains a partial username preceded by random character
- * (usually '~'); state is ignored
- * it's callers responsibility to free returned value
- */
-char *
-username_completion_function(const char *text, int state)
-{
- struct passwd *pwd;
-
- if (text[0] == '\0')
- return (NULL);
-
- if (*text == '~')
- text++;
-
- if (state == 0)
- setpwent();
-
- while ((pwd = getpwent()) && text[0] == pwd->pw_name[0]
- && strcmp(text, pwd->pw_name) == 0);
-
- if (pwd == NULL) {
- endpwent();
- return (NULL);
- }
- return (strdup(pwd->pw_name));
-}
-
-
-/*
- * el-compatible wrapper around rl_complete; needed for key binding
- */
-/* ARGSUSED */
-static unsigned char
-_el_rl_complete(EditLine *el, int ch)
-{
- return (unsigned char) rl_complete(0, ch);
-}
-
-
-/*
- * returns list of completitions for text given
- */
-char **
-completion_matches(const char *text, CPFunction *genfunc)
-{
- char **match_list = NULL, *retstr, *prevstr;
- size_t match_list_len, max_equal, which, i;
- int matches;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- matches = 0;
- match_list_len = 1;
- while ((retstr = (*genfunc) (text, matches)) != NULL) {
- if (matches + 1 >= match_list_len) {
- match_list_len <<= 1;
- match_list = realloc(match_list,
- match_list_len * sizeof(char *));
- }
- match_list[++matches] = retstr;
- }
-
- if (!match_list)
- return (char **) NULL; /* nothing found */
-
- /* find least denominator and insert it to match_list[0] */
- which = 2;
- prevstr = match_list[1];
- max_equal = strlen(prevstr);
- for (; which <= matches; which++) {
- for (i = 0; i < max_equal &&
- prevstr[i] == match_list[which][i]; i++)
- continue;
- max_equal = i;
- }
-
- retstr = malloc(max_equal + 1);
- (void) strncpy(retstr, match_list[1], max_equal);
- retstr[max_equal] = '\0';
- match_list[0] = retstr;
-
- /* add NULL as last pointer to the array */
- if (matches + 1 >= match_list_len)
- match_list = realloc(match_list,
- (match_list_len + 1) * sizeof(char *));
- match_list[matches + 1] = (char *) NULL;
-
- return (match_list);
-}
-
-/*
- * Sort function for qsort(). Just wrapper around strcasecmp().
- */
-static int
-_rl_qsort_string_compare(i1, i2)
- const void *i1, *i2;
-{
- /* LINTED const castaway */
- const char *s1 = ((const char **)i1)[0];
- /* LINTED const castaway */
- const char *s2 = ((const char **)i2)[0];
-
- return strcasecmp(s1, s2);
-}
-
-/*
- * Display list of strings in columnar format on readline's output stream.
- * 'matches' is list of strings, 'len' is number of strings in 'matches',
- * 'max' is maximum length of string in 'matches'.
- */
-void
-rl_display_match_list (matches, len, max)
- char **matches;
- int len, max;
-{
- int i, idx, limit, count;
- int screenwidth = e->el_term.t_size.h;
-
- /*
- * Find out how many entries can be put on one line, count
- * with two spaces between strings.
- */
- limit = screenwidth / (max + 2);
- if (limit == 0)
- limit = 1;
-
- /* how many lines of output */
- count = len / limit;
- if (count * limit < len)
- count++;
-
- /* Sort the items if they are not already sorted. */
- qsort(&matches[1], (size_t)(len - 1), sizeof(char *),
- _rl_qsort_string_compare);
-
- idx = 1;
- for(; count > 0; count--) {
- for(i=0; i < limit && matches[idx]; i++, idx++)
- fprintf(e->el_outfile, "%-*s ", max, matches[idx]);
- fprintf(e->el_outfile, "\n");
- }
-}
-
-/*
- * Complete the word at or before point, called by rl_complete()
- * 'what_to_do' says what to do with the completion.
- * `?' means list the possible completions.
- * TAB means do standard completion.
- * `*' means insert all of the possible completions.
- * `!' means to do standard completion, and list all possible completions if
- * there is more than one.
- *
- * Note: '*' support is not implemented
- */
-static int
-rl_complete_internal(int what_to_do)
-{
- CPFunction *complet_func;
- const LineInfo *li;
- char *temp, **matches;
- const char *ctemp;
- size_t len;
-
- rl_completion_type = what_to_do;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- complet_func = rl_completion_entry_function;
- if (!complet_func)
- complet_func = filename_completion_function;
-
- /* We now look backwards for the start of a filename/variable word */
- li = el_line(e);
- ctemp = (const char *) li->cursor;
- while (ctemp > li->buffer
- && !strchr(rl_basic_word_break_characters, ctemp[-1])
- && (!rl_special_prefixes
- || !strchr(rl_special_prefixes, ctemp[-1]) ) )
- ctemp--;
-
- len = li->cursor - ctemp;
- temp = alloca(len + 1);
- (void) strncpy(temp, ctemp, len);
- temp[len] = '\0';
-
- /* these can be used by function called in completion_matches() */
- /* or (*rl_attempted_completion_function)() */
- rl_point = li->cursor - li->buffer;
- rl_end = li->lastchar - li->buffer;
-
- if (!rl_attempted_completion_function)
- matches = completion_matches(temp, complet_func);
- else {
- int end = li->cursor - li->buffer;
- matches = (*rl_attempted_completion_function) (temp, (int)
- (end - len), end);
- }
-
- if (matches) {
- int i, retval = CC_REFRESH;
- int matches_num, maxlen, match_len, match_display=1;
-
- /*
- * Only replace the completed string with common part of
- * possible matches if there is possible completion.
- */
- if (matches[0][0] != '\0') {
- el_deletestr(e, (int) len);
- el_insertstr(e, matches[0]);
- }
-
- if (what_to_do == '?')
- goto display_matches;
-
- if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
- /*
- * We found exact match. Add a space after
- * it, unless we do filename completition and the
- * object is a directory.
- */
- size_t alen = strlen(matches[0]);
- if ((complet_func != filename_completion_function
- || (alen > 0 && (matches[0])[alen - 1] != '/'))
- && rl_completion_append_character) {
- char buf[2];
- buf[0] = rl_completion_append_character;
- buf[1] = '\0';
- el_insertstr(e, buf);
- }
- } else if (what_to_do == '!') {
- display_matches:
- /*
- * More than one match and requested to list possible
- * matches.
- */
-
- for(i=1, maxlen=0; matches[i]; i++) {
- match_len = strlen(matches[i]);
- if (match_len > maxlen)
- maxlen = match_len;
- }
- matches_num = i - 1;
-
- /* newline to get on next line from command line */
- fprintf(e->el_outfile, "\n");
-
- /*
- * If there are too many items, ask user for display
- * confirmation.
- */
- if (matches_num > rl_completion_query_items) {
- fprintf(e->el_outfile,
- "Display all %d possibilities? (y or n) ",
- matches_num);
- fflush(e->el_outfile);
- if (getc(stdin) != 'y')
- match_display = 0;
- fprintf(e->el_outfile, "\n");
- }
-
- if (match_display)
- rl_display_match_list(matches, matches_num,
- maxlen);
- retval = CC_REDISPLAY;
- } else if (matches[0][0]) {
- /*
- * There was some common match, but the name was
- * not complete enough. Next tab will print possible
- * completions.
- */
- el_beep(e);
- } else {
- /* lcd is not a valid object - further specification */
- /* is needed */
- el_beep(e);
- retval = CC_NORM;
- }
-
- /* free elements of array and the array itself */
- for (i = 0; matches[i]; i++)
- free(matches[i]);
- free(matches), matches = NULL;
-
- return (retval);
- }
- return (CC_NORM);
-}
-
-
-/*
- * complete word at current point
- */
-int
-rl_complete(int ignore, int invoking_key)
-{
- if (h == NULL || e == NULL)
- rl_initialize();
-
- if (rl_inhibit_completion) {
- rl_insert(ignore, invoking_key);
- return (CC_REFRESH);
- } else if (e->el_state.lastcmd == el_rl_complete_cmdnum)
- return rl_complete_internal('?');
- else if (_rl_complete_show_all)
- return rl_complete_internal('!');
- else
- return (rl_complete_internal(TAB));
-}
-
-
-/*
- * misc other functions
- */
-
-/*
- * bind key c to readline-type function func
- */
-int
-rl_bind_key(int c, int func(int, int))
-{
- int retval = -1;
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- if (func == rl_insert) {
- /* XXX notice there is no range checking of ``c'' */
- e->el_map.key[c] = ED_INSERT;
- retval = 0;
- }
- return (retval);
-}
-
-
-/*
- * read one key from input - handles chars pushed back
- * to input stream also
- */
-int
-rl_read_key(void)
-{
- char fooarr[2 * sizeof(int)];
-
- if (e == NULL || h == NULL)
- rl_initialize();
-
- return (el_getc(e, fooarr));
-}
-
-
-/*
- * reset the terminal
- */
-/* ARGSUSED */
-void
-rl_reset_terminal(const char *p)
-{
-
- if (h == NULL || e == NULL)
- rl_initialize();
- el_reset(e);
-}
-
-
-/*
- * insert character ``c'' back into input stream, ``count'' times
- */
-int
-rl_insert(int count, int c)
-{
- char arr[2];
-
- if (h == NULL || e == NULL)
- rl_initialize();
-
- /* XXX - int -> char conversion can lose on multichars */
- arr[0] = c;
- arr[1] = '\0';
-
- for (; count > 0; count--)
- el_push(e, arr);
-
- return (0);
-}
diff --git a/main/editline/readline/readline.h b/main/editline/readline/readline.h
deleted file mode 100644
index 7485dde40..000000000
--- a/main/editline/readline/readline.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* $NetBSD: readline.h,v 1.1 2001/01/05 21:15:50 jdolecek Exp $ */
-
-/*-
- * Copyright (c) 1997 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Jaromir Dolecek.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _READLINE_H_
-#define _READLINE_H_
-
-#include <sys/types.h>
-
-/* list of readline stuff supported by editline library's readline wrapper */
-
-/* typedefs */
-typedef int Function(const char *, int);
-typedef void VFunction(void);
-typedef char *CPFunction(const char *, int);
-typedef char **CPPFunction(const char *, int, int);
-
-typedef struct _hist_entry {
- const char *line;
- const char *data;
-} HIST_ENTRY;
-
-/* global variables used by readline enabled applications */
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern const char *rl_library_version;
-extern char *rl_readline_name;
-extern FILE *rl_instream;
-extern FILE *rl_outstream;
-extern char *rl_line_buffer;
-extern int rl_point, rl_end;
-extern int history_base, history_length;
-extern int max_input_history;
-extern char *rl_basic_word_break_characters;
-extern char *rl_completer_word_break_characters;
-extern char *rl_completer_quote_characters;
-extern CPFunction *rl_completion_entry_function;
-extern CPPFunction *rl_attempted_completion_function;
-extern int rl_completion_type;
-extern int rl_completion_query_items;
-extern char *rl_special_prefixes;
-extern int rl_completion_append_character;
-
-/* supported functions */
-char *readline(const char *);
-int rl_initialize(void);
-
-void using_history(void);
-int add_history(const char *);
-void clear_history(void);
-void stifle_history(int);
-int unstifle_history(void);
-int history_is_stifled(void);
-int where_history(void);
-HIST_ENTRY *current_history(void);
-HIST_ENTRY *history_get(int);
-int history_total_bytes(void);
-int history_set_pos(int);
-HIST_ENTRY *previous_history(void);
-HIST_ENTRY *next_history(void);
-int history_search(const char *, int);
-int history_search_prefix(const char *, int);
-int history_search_pos(const char *, int, int);
-int read_history(const char *);
-int write_history(const char *);
-int history_expand(char *, char **);
-char **history_tokenize(const char *);
-
-char *tilde_expand(char *);
-char *filename_completion_function(const char *, int);
-char *username_completion_function(const char *, int);
-int rl_complete(int, int);
-int rl_read_key(void);
-char **completion_matches(const char *, CPFunction *);
-void rl_display_match_list(char **, int, int);
-
-int rl_insert(int, int);
-void rl_reset_terminal(const char *);
-int rl_bind_key(int, int (*)(int, int));
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _READLINE_H_ */
diff --git a/main/editline/refresh.c b/main/editline/refresh.c
deleted file mode 100644
index 935117741..000000000
--- a/main/editline/refresh.c
+++ /dev/null
@@ -1,1104 +0,0 @@
-/* $NetBSD: refresh.c,v 1.18 2002/03/18 16:00:58 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: refresh.c,v 1.18 2002/03/18 16:00:58 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * refresh.c: Lower level screen refreshing functions
- */
-#include <stdio.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "el.h"
-
-private void re_addc(EditLine *, int);
-private void re_update_line(EditLine *, char *, char *, int);
-private void re_insert (EditLine *, char *, int, int, char *, int);
-private void re_delete(EditLine *, char *, int, int, int);
-private void re_fastputc(EditLine *, int);
-private void re__strncopy(char *, char *, size_t);
-private void re__copy_and_pad(char *, const char *, size_t);
-
-#ifdef DEBUG_REFRESH
-private void re_printstr(EditLine *, char *, char *, char *);
-#define __F el->el_errfile
-#define ELRE_ASSERT(a, b, c) do \
- if (a) { \
- (void) fprintf b; \
- c; \
- } \
- while (0)
-#define ELRE_DEBUG(a, b) ELRE_ASSERT(a,b,;)
-
-/* re_printstr():
- * Print a string on the debugging pty
- */
-private void
-re_printstr(EditLine *el, char *str, char *f, char *t)
-{
-
- ELRE_DEBUG(1, (__F, "%s:\"", str));
- while (f < t)
- ELRE_DEBUG(1, (__F, "%c", *f++ & 0177));
- ELRE_DEBUG(1, (__F, "\"\r\n"));
-}
-#else
-#define ELRE_ASSERT(a, b, c)
-#define ELRE_DEBUG(a, b)
-#endif
-
-
-/* re_addc():
- * Draw c, expanding tabs, control chars etc.
- */
-private void
-re_addc(EditLine *el, int c)
-{
-
- if (isprint(c)) {
- re_putc(el, c, 1);
- return;
- }
- if (c == '\n') { /* expand the newline */
- int oldv = el->el_refresh.r_cursor.v;
- re_putc(el, '\0', 0); /* assure end of line */
- if (oldv == el->el_refresh.r_cursor.v) { /* XXX */
- el->el_refresh.r_cursor.h = 0; /* reset cursor pos */
- el->el_refresh.r_cursor.v++;
- }
- return;
- }
- if (c == '\t') { /* expand the tab */
- for (;;) {
- re_putc(el, ' ', 1);
- if ((el->el_refresh.r_cursor.h & 07) == 0)
- break; /* go until tab stop */
- }
- } else if (iscntrl(c)) {
- re_putc(el, '^', 1);
- if (c == '\177')
- re_putc(el, '?', 1);
- else
- /* uncontrolify it; works only for iso8859-1 like sets */
- re_putc(el, (c | 0100), 1);
- } else {
- re_putc(el, '\\', 1);
- re_putc(el, (int) ((((unsigned int) c >> 6) & 07) + '0'), 1);
- re_putc(el, (int) ((((unsigned int) c >> 3) & 07) + '0'), 1);
- re_putc(el, (c & 07) + '0', 1);
- }
-}
-
-
-/* re_putc():
- * Draw the character given
- */
-protected void
-re_putc(EditLine *el, int c, int shift)
-{
-
- ELRE_DEBUG(1, (__F, "printing %3.3o '%c'\r\n", c, c));
-
- el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c;
- if (!shift)
- return;
-
- el->el_refresh.r_cursor.h++; /* advance to next place */
- if (el->el_refresh.r_cursor.h >= el->el_term.t_size.h) {
- el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_term.t_size.h] = '\0';
- /* assure end of line */
- el->el_refresh.r_cursor.h = 0; /* reset it. */
-
- /*
- * If we would overflow (input is longer than terminal size),
- * emulate scroll by dropping first line and shuffling the rest.
- * We do this via pointer shuffling - it's safe in this case
- * and we avoid memcpy().
- */
- if (el->el_refresh.r_cursor.v + 1 >= el->el_term.t_size.v) {
- int i, lins = el->el_term.t_size.v;
- char *firstline = el->el_vdisplay[0];
-
- for(i=1; i < lins; i++)
- el->el_vdisplay[i-1] = el->el_vdisplay[i];
-
- firstline[0] = '\0'; /* empty the string */
- el->el_vdisplay[i-1] = firstline;
- } else
- el->el_refresh.r_cursor.v++;
-
- ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_term.t_size.v,
- (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n",
- el->el_refresh.r_cursor.v, el->el_term.t_size.v),
- abort());
- }
-}
-
-
-/* re_refresh():
- * draws the new virtual screen image from the current input
- * line, then goes line-by-line changing the real image to the new
- * virtual image. The routine to re-draw a line can be replaced
- * easily in hopes of a smarter one being placed there.
- */
-protected void
-re_refresh(EditLine *el)
-{
- int i, rhdiff;
- char *cp, *st;
- coord_t cur;
-#ifdef notyet
- size_t termsz;
-#endif
-
- ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%s:\r\n",
- el->el_line.buffer));
-
- /* reset the Drawing cursor */
- el->el_refresh.r_cursor.h = 0;
- el->el_refresh.r_cursor.v = 0;
-
- /* temporarily draw rprompt to calculate its size */
- prompt_print(el, EL_RPROMPT);
-
- /* reset the Drawing cursor */
- el->el_refresh.r_cursor.h = 0;
- el->el_refresh.r_cursor.v = 0;
-
- cur.h = -1; /* set flag in case I'm not set */
- cur.v = 0;
-
- prompt_print(el, EL_PROMPT);
-
- /* draw the current input buffer */
-#if notyet
- termsz = el->el_term.t_size.h * el->el_term.t_size.v;
- if (el->el_line.lastchar - el->el_line.buffer > termsz) {
- /*
- * If line is longer than terminal, process only part
- * of line which would influence display.
- */
- size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz;
-
- st = el->el_line.lastchar - rem
- - (termsz - (((rem / el->el_term.t_size.v) - 1)
- * el->el_term.t_size.v));
- } else
-#endif
- st = el->el_line.buffer;
-
- for (cp = st; cp < el->el_line.lastchar; cp++) {
- if (cp == el->el_line.cursor) {
- /* save for later */
- cur.h = el->el_refresh.r_cursor.h;
- cur.v = el->el_refresh.r_cursor.v;
- }
- re_addc(el, (unsigned char) *cp);
- }
-
- if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */
- cur.h = el->el_refresh.r_cursor.h;
- cur.v = el->el_refresh.r_cursor.v;
- }
- rhdiff = el->el_term.t_size.h - el->el_refresh.r_cursor.h -
- el->el_rprompt.p_pos.h;
- if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v &&
- !el->el_refresh.r_cursor.v && rhdiff > 1) {
- /*
- * have a right-hand side prompt that will fit
- * on the end of the first line with at least
- * one character gap to the input buffer.
- */
- while (--rhdiff > 0) /* pad out with spaces */
- re_putc(el, ' ', 1);
- prompt_print(el, EL_RPROMPT);
- } else {
- el->el_rprompt.p_pos.h = 0; /* flag "not using rprompt" */
- el->el_rprompt.p_pos.v = 0;
- }
-
- re_putc(el, '\0', 0); /* make line ended with NUL, no cursor shift */
-
- el->el_refresh.r_newcv = el->el_refresh.r_cursor.v;
-
- ELRE_DEBUG(1, (__F,
- "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n",
- el->el_term.t_size.h, el->el_refresh.r_cursor.h,
- el->el_refresh.r_cursor.v, el->el_vdisplay[0]));
-
- ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv));
- for (i = 0; i <= el->el_refresh.r_newcv; i++) {
- /* NOTE THAT re_update_line MAY CHANGE el_display[i] */
- re_update_line(el, el->el_display[i], el->el_vdisplay[i], i);
-
- /*
- * Copy the new line to be the current one, and pad out with
- * spaces to the full width of the terminal so that if we try
- * moving the cursor by writing the character that is at the
- * end of the screen line, it won't be a NUL or some old
- * leftover stuff.
- */
- re__copy_and_pad(el->el_display[i], el->el_vdisplay[i],
- (size_t) el->el_term.t_size.h);
- }
- ELRE_DEBUG(1, (__F,
- "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n",
- el->el_refresh.r_cursor.v, el->el_refresh.r_oldcv, i));
-
- if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv)
- for (; i <= el->el_refresh.r_oldcv; i++) {
- term_move_to_line(el, i);
- term_move_to_char(el, 0);
- term_clear_EOL(el, (int) strlen(el->el_display[i]));
-#ifdef DEBUG_REFRESH
- term_overwrite(el, "C\b", 2);
-#endif /* DEBUG_REFRESH */
- el->el_display[i][0] = '\0';
- }
-
- el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */
- ELRE_DEBUG(1, (__F,
- "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n",
- el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v,
- cur.h, cur.v));
- term_move_to_line(el, cur.v); /* go to where the cursor is */
- term_move_to_char(el, cur.h);
-}
-
-
-/* re_goto_bottom():
- * used to go to last used screen line
- */
-protected void
-re_goto_bottom(EditLine *el)
-{
-
- term_move_to_line(el, el->el_refresh.r_oldcv);
- term__putc('\r');
- term__putc('\n');
- re_clear_display(el);
- term__flush();
-}
-
-
-/* re_insert():
- * insert num characters of s into d (in front of the character)
- * at dat, maximum length of d is dlen
- */
-private void
-/*ARGSUSED*/
-re_insert(EditLine *el, char *d, int dat, int dlen, char *s, int num)
-{
- char *a, *b;
-
- if (num <= 0)
- return;
- if (num > dlen - dat)
- num = dlen - dat;
-
- ELRE_DEBUG(1,
- (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n",
- num, dat, dlen, d));
- ELRE_DEBUG(1, (__F, "s == \"%s\"n", s));
-
- /* open up the space for num chars */
- if (num > 0) {
- b = d + dlen - 1;
- a = b - num;
- while (a >= &d[dat])
- *b-- = *a--;
- d[dlen] = '\0'; /* just in case */
- }
- ELRE_DEBUG(1, (__F,
- "re_insert() after insert: %d at %d max %d, d == \"%s\"\n",
- num, dat, dlen, d));
- ELRE_DEBUG(1, (__F, "s == \"%s\"n", s));
-
- /* copy the characters */
- for (a = d + dat; (a < d + dlen) && (num > 0); num--)
- *a++ = *s++;
-
- ELRE_DEBUG(1,
- (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n",
- num, dat, dlen, d, s));
- ELRE_DEBUG(1, (__F, "s == \"%s\"n", s));
-}
-
-
-/* re_delete():
- * delete num characters d at dat, maximum length of d is dlen
- */
-private void
-/*ARGSUSED*/
-re_delete(EditLine *el, char *d, int dat, int dlen, int num)
-{
- char *a, *b;
-
- if (num <= 0)
- return;
- if (dat + num >= dlen) {
- d[dat] = '\0';
- return;
- }
- ELRE_DEBUG(1,
- (__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n",
- num, dat, dlen, d));
-
- /* open up the space for num chars */
- if (num > 0) {
- b = d + dat;
- a = b + num;
- while (a < &d[dlen])
- *b++ = *a++;
- d[dlen] = '\0'; /* just in case */
- }
- ELRE_DEBUG(1,
- (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n",
- num, dat, dlen, d));
-}
-
-
-/* re__strncopy():
- * Like strncpy without padding.
- */
-private void
-re__strncopy(char *a, char *b, size_t n)
-{
-
- while (n-- && *b)
- *a++ = *b++;
-}
-
-
-/*****************************************************************
- re_update_line() is based on finding the middle difference of each line
- on the screen; vis:
-
- /old first difference
- /beginning of line | /old last same /old EOL
- v v v v
-old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
-new: eddie> Oh, my little buggy says to me, as lurgid as
- ^ ^ ^ ^
- \beginning of line | \new last same \new end of line
- \new first difference
-
- all are character pointers for the sake of speed. Special cases for
- no differences, as well as for end of line additions must be handled.
-**************************************************************** */
-
-/* Minimum at which doing an insert it "worth it". This should be about
- * half the "cost" of going into insert mode, inserting a character, and
- * going back out. This should really be calculated from the termcap
- * data... For the moment, a good number for ANSI terminals.
- */
-#define MIN_END_KEEP 4
-
-private void
-re_update_line(EditLine *el, char *old, char *new, int i)
-{
- char *o, *n, *p, c;
- char *ofd, *ols, *oe, *nfd, *nls, *ne;
- char *osb, *ose, *nsb, *nse;
- int fx, sx;
-
- /*
- * find first diff
- */
- for (o = old, n = new; *o && (*o == *n); o++, n++)
- continue;
- ofd = o;
- nfd = n;
-
- /*
- * Find the end of both old and new
- */
- while (*o)
- o++;
- /*
- * Remove any trailing blanks off of the end, being careful not to
- * back up past the beginning.
- */
- while (ofd < o) {
- if (o[-1] != ' ')
- break;
- o--;
- }
- oe = o;
- *oe = '\0';
-
- while (*n)
- n++;
-
- /* remove blanks from end of new */
- while (nfd < n) {
- if (n[-1] != ' ')
- break;
- n--;
- }
- ne = n;
- *ne = '\0';
-
- /*
- * if no diff, continue to next line of redraw
- */
- if (*ofd == '\0' && *nfd == '\0') {
- ELRE_DEBUG(1, (__F, "no difference.\r\n"));
- return;
- }
- /*
- * find last same pointer
- */
- while ((o > ofd) && (n > nfd) && (*--o == *--n))
- continue;
- ols = ++o;
- nls = ++n;
-
- /*
- * find same begining and same end
- */
- osb = ols;
- nsb = nls;
- ose = ols;
- nse = nls;
-
- /*
- * case 1: insert: scan from nfd to nls looking for *ofd
- */
- if (*ofd) {
- for (c = *ofd, n = nfd; n < nls; n++) {
- if (c == *n) {
- for (o = ofd, p = n;
- p < nls && o < ols && *o == *p;
- o++, p++)
- continue;
- /*
- * if the new match is longer and it's worth
- * keeping, then we take it
- */
- if (((nse - nsb) < (p - n)) &&
- (2 * (p - n) > n - nfd)) {
- nsb = n;
- nse = p;
- osb = ofd;
- ose = o;
- }
- }
- }
- }
- /*
- * case 2: delete: scan from ofd to ols looking for *nfd
- */
- if (*nfd) {
- for (c = *nfd, o = ofd; o < ols; o++) {
- if (c == *o) {
- for (n = nfd, p = o;
- p < ols && n < nls && *p == *n;
- p++, n++)
- continue;
- /*
- * if the new match is longer and it's worth
- * keeping, then we take it
- */
- if (((ose - osb) < (p - o)) &&
- (2 * (p - o) > o - ofd)) {
- nsb = nfd;
- nse = n;
- osb = o;
- ose = p;
- }
- }
- }
- }
- /*
- * Pragmatics I: If old trailing whitespace or not enough characters to
- * save to be worth it, then don't save the last same info.
- */
- if ((oe - ols) < MIN_END_KEEP) {
- ols = oe;
- nls = ne;
- }
- /*
- * Pragmatics II: if the terminal isn't smart enough, make the data
- * dumber so the smart update doesn't try anything fancy
- */
-
- /*
- * fx is the number of characters we need to insert/delete: in the
- * beginning to bring the two same begins together
- */
- fx = (nsb - nfd) - (osb - ofd);
- /*
- * sx is the number of characters we need to insert/delete: in the
- * end to bring the two same last parts together
- */
- sx = (nls - nse) - (ols - ose);
-
- if (!EL_CAN_INSERT) {
- if (fx > 0) {
- osb = ols;
- ose = ols;
- nsb = nls;
- nse = nls;
- }
- if (sx > 0) {
- ols = oe;
- nls = ne;
- }
- if ((ols - ofd) < (nls - nfd)) {
- ols = oe;
- nls = ne;
- }
- }
- if (!EL_CAN_DELETE) {
- if (fx < 0) {
- osb = ols;
- ose = ols;
- nsb = nls;
- nse = nls;
- }
- if (sx < 0) {
- ols = oe;
- nls = ne;
- }
- if ((ols - ofd) > (nls - nfd)) {
- ols = oe;
- nls = ne;
- }
- }
- /*
- * Pragmatics III: make sure the middle shifted pointers are correct if
- * they don't point to anything (we may have moved ols or nls).
- */
- /* if the change isn't worth it, don't bother */
- /* was: if (osb == ose) */
- if ((ose - osb) < MIN_END_KEEP) {
- osb = ols;
- ose = ols;
- nsb = nls;
- nse = nls;
- }
- /*
- * Now that we are done with pragmatics we recompute fx, sx
- */
- fx = (nsb - nfd) - (osb - ofd);
- sx = (nls - nse) - (ols - ose);
-
- ELRE_DEBUG(1, (__F, "\n"));
- ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n",
- ofd - old, osb - old, ose - old, ols - old, oe - old));
- ELRE_DEBUG(1, (__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
- nfd - new, nsb - new, nse - new, nls - new, ne - new));
- ELRE_DEBUG(1, (__F,
- "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n"));
- ELRE_DEBUG(1, (__F,
- "xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n"));
-#ifdef DEBUG_REFRESH
- re_printstr(el, "old- oe", old, oe);
- re_printstr(el, "new- ne", new, ne);
- re_printstr(el, "old-ofd", old, ofd);
- re_printstr(el, "new-nfd", new, nfd);
- re_printstr(el, "ofd-osb", ofd, osb);
- re_printstr(el, "nfd-nsb", nfd, nsb);
- re_printstr(el, "osb-ose", osb, ose);
- re_printstr(el, "nsb-nse", nsb, nse);
- re_printstr(el, "ose-ols", ose, ols);
- re_printstr(el, "nse-nls", nse, nls);
- re_printstr(el, "ols- oe", ols, oe);
- re_printstr(el, "nls- ne", nls, ne);
-#endif /* DEBUG_REFRESH */
-
- /*
- * el_cursor.v to this line i MUST be in this routine so that if we
- * don't have to change the line, we don't move to it. el_cursor.h to
- * first diff char
- */
- term_move_to_line(el, i);
-
- /*
- * at this point we have something like this:
- *
- * /old /ofd /osb /ose /ols /oe
- * v.....................v v..................v v........v
- * eddie> Oh, my fredded gruntle-buggy is to me, as foo var lurgid as
- * eddie> Oh, my fredded quiux buggy is to me, as gruntle-lurgid as
- * ^.....................^ ^..................^ ^........^
- * \new \nfd \nsb \nse \nls \ne
- *
- * fx is the difference in length between the chars between nfd and
- * nsb, and the chars between ofd and osb, and is thus the number of
- * characters to delete if < 0 (new is shorter than old, as above),
- * or insert (new is longer than short).
- *
- * sx is the same for the second differences.
- */
-
- /*
- * if we have a net insert on the first difference, AND inserting the
- * net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful
- * character (which is ne if nls != ne, otherwise is nse) off the edge
- * of the screen (el->el_term.t_size.h) else we do the deletes first
- * so that we keep everything we need to.
- */
-
- /*
- * if the last same is the same like the end, there is no last same
- * part, otherwise we want to keep the last same part set p to the
- * last useful old character
- */
- p = (ols != oe) ? oe : ose;
-
- /*
- * if (There is a diffence in the beginning) && (we need to insert
- * characters) && (the number of characters to insert is less than
- * the term width)
- * We need to do an insert!
- * else if (we need to delete characters)
- * We need to delete characters!
- * else
- * No insert or delete
- */
- if ((nsb != nfd) && fx > 0 &&
- ((p - old) + fx <= el->el_term.t_size.h)) {
- ELRE_DEBUG(1,
- (__F, "first diff insert at %d...\r\n", nfd - new));
- /*
- * Move to the first char to insert, where the first diff is.
- */
- term_move_to_char(el, nfd - new);
- /*
- * Check if we have stuff to keep at end
- */
- if (nsb != ne) {
- ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
- /*
- * insert fx chars of new starting at nfd
- */
- if (fx > 0) {
- ELRE_DEBUG(!EL_CAN_INSERT, (__F,
- "ERROR: cannot insert in early first diff\n"));
- term_insertwrite(el, nfd, fx);
- re_insert(el, old, ofd - old,
- el->el_term.t_size.h, nfd, fx);
- }
- /*
- * write (nsb-nfd) - fx chars of new starting at
- * (nfd + fx)
- */
- term_overwrite(el, nfd + fx, (nsb - nfd) - fx);
- re__strncopy(ofd + fx, nfd + fx,
- (size_t) ((nsb - nfd) - fx));
- } else {
- ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
- term_overwrite(el, nfd, (nsb - nfd));
- re__strncopy(ofd, nfd, (size_t) (nsb - nfd));
- /*
- * Done
- */
- return;
- }
- } else if (fx < 0) {
- ELRE_DEBUG(1,
- (__F, "first diff delete at %d...\r\n", ofd - old));
- /*
- * move to the first char to delete where the first diff is
- */
- term_move_to_char(el, ofd - old);
- /*
- * Check if we have stuff to save
- */
- if (osb != oe) {
- ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
- /*
- * fx is less than zero *always* here but we check
- * for code symmetry
- */
- if (fx < 0) {
- ELRE_DEBUG(!EL_CAN_DELETE, (__F,
- "ERROR: cannot delete in first diff\n"));
- term_deletechars(el, -fx);
- re_delete(el, old, ofd - old,
- el->el_term.t_size.h, -fx);
- }
- /*
- * write (nsb-nfd) chars of new starting at nfd
- */
- term_overwrite(el, nfd, (nsb - nfd));
- re__strncopy(ofd, nfd, (size_t) (nsb - nfd));
-
- } else {
- ELRE_DEBUG(1, (__F,
- "but with nothing left to save\r\n"));
- /*
- * write (nsb-nfd) chars of new starting at nfd
- */
- term_overwrite(el, nfd, (nsb - nfd));
- ELRE_DEBUG(1, (__F,
- "cleareol %d\n", (oe - old) - (ne - new)));
- term_clear_EOL(el, (oe - old) - (ne - new));
- /*
- * Done
- */
- return;
- }
- } else
- fx = 0;
-
- if (sx < 0 && (ose - old) + fx < el->el_term.t_size.h) {
- ELRE_DEBUG(1, (__F,
- "second diff delete at %d...\r\n", (ose - old) + fx));
- /*
- * Check if we have stuff to delete
- */
- /*
- * fx is the number of characters inserted (+) or deleted (-)
- */
-
- term_move_to_char(el, (ose - old) + fx);
- /*
- * Check if we have stuff to save
- */
- if (ols != oe) {
- ELRE_DEBUG(1, (__F, "with stuff to save at end\r\n"));
- /*
- * Again a duplicate test.
- */
- if (sx < 0) {
- ELRE_DEBUG(!EL_CAN_DELETE, (__F,
- "ERROR: cannot delete in second diff\n"));
- term_deletechars(el, -sx);
- }
- /*
- * write (nls-nse) chars of new starting at nse
- */
- term_overwrite(el, nse, (nls - nse));
- } else {
- ELRE_DEBUG(1, (__F,
- "but with nothing left to save\r\n"));
- term_overwrite(el, nse, (nls - nse));
- ELRE_DEBUG(1, (__F,
- "cleareol %d\n", (oe - old) - (ne - new)));
- if ((oe - old) - (ne - new) != 0)
- term_clear_EOL(el, (oe - old) - (ne - new));
- }
- }
- /*
- * if we have a first insert AND WE HAVEN'T ALREADY DONE IT...
- */
- if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
- ELRE_DEBUG(1, (__F, "late first diff insert at %d...\r\n",
- nfd - new));
-
- term_move_to_char(el, nfd - new);
- /*
- * Check if we have stuff to keep at the end
- */
- if (nsb != ne) {
- ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
- /*
- * We have to recalculate fx here because we set it
- * to zero above as a flag saying that we hadn't done
- * an early first insert.
- */
- fx = (nsb - nfd) - (osb - ofd);
- if (fx > 0) {
- /*
- * insert fx chars of new starting at nfd
- */
- ELRE_DEBUG(!EL_CAN_INSERT, (__F,
- "ERROR: cannot insert in late first diff\n"));
- term_insertwrite(el, nfd, fx);
- re_insert(el, old, ofd - old,
- el->el_term.t_size.h, nfd, fx);
- }
- /*
- * write (nsb-nfd) - fx chars of new starting at
- * (nfd + fx)
- */
- term_overwrite(el, nfd + fx, (nsb - nfd) - fx);
- re__strncopy(ofd + fx, nfd + fx,
- (size_t) ((nsb - nfd) - fx));
- } else {
- ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
- term_overwrite(el, nfd, (nsb - nfd));
- re__strncopy(ofd, nfd, (size_t) (nsb - nfd));
- }
- }
- /*
- * line is now NEW up to nse
- */
- if (sx >= 0) {
- ELRE_DEBUG(1, (__F,
- "second diff insert at %d...\r\n", nse - new));
- term_move_to_char(el, nse - new);
- if (ols != oe) {
- ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n"));
- if (sx > 0) {
- /* insert sx chars of new starting at nse */
- ELRE_DEBUG(!EL_CAN_INSERT, (__F,
- "ERROR: cannot insert in second diff\n"));
- term_insertwrite(el, nse, sx);
- }
- /*
- * write (nls-nse) - sx chars of new starting at
- * (nse + sx)
- */
- term_overwrite(el, nse + sx, (nls - nse) - sx);
- } else {
- ELRE_DEBUG(1, (__F, "without anything to save\r\n"));
- term_overwrite(el, nse, (nls - nse));
-
- /*
- * No need to do a clear-to-end here because we were
- * doing a second insert, so we will have over
- * written all of the old string.
- */
- }
- }
- ELRE_DEBUG(1, (__F, "done.\r\n"));
-}
-
-
-/* re__copy_and_pad():
- * Copy string and pad with spaces
- */
-private void
-re__copy_and_pad(char *dst, const char *src, size_t width)
-{
- int i;
-
- for (i = 0; i < width; i++) {
- if (*src == '\0')
- break;
- *dst++ = *src++;
- }
-
- for (; i < width; i++)
- *dst++ = ' ';
-
- *dst = '\0';
-}
-
-
-/* re_refresh_cursor():
- * Move to the new cursor position
- */
-protected void
-re_refresh_cursor(EditLine *el)
-{
- char *cp, c;
- int h, v, th;
-
- /* first we must find where the cursor is... */
- h = el->el_prompt.p_pos.h;
- v = el->el_prompt.p_pos.v;
- th = el->el_term.t_size.h; /* optimize for speed */
-
- /* do input buffer to el->el_line.cursor */
- for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) {
- c = *cp;
- h++; /* all chars at least this long */
-
- if (c == '\n') {/* handle newline in data part too */
- h = 0;
- v++;
- } else {
- if (c == '\t') { /* if a tab, to next tab stop */
- while (h & 07) {
- h++;
- }
- } else if (iscntrl((unsigned char) c)) {
- /* if control char */
- h++;
- if (h > th) { /* if overflow, compensate */
- h = 1;
- v++;
- }
- } else if (!isprint((unsigned char) c)) {
- h += 3;
- if (h > th) { /* if overflow, compensate */
- h = h - th;
- v++;
- }
- }
- }
-
- if (h >= th) { /* check, extra long tabs picked up here also */
- h = 0;
- v++;
- }
- }
-
- /* now go there */
- term_move_to_line(el, v);
- term_move_to_char(el, h);
- term__flush();
-}
-
-
-/* re_fastputc():
- * Add a character fast.
- */
-private void
-re_fastputc(EditLine *el, int c)
-{
-
- term__putc(c);
- el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
- if (el->el_cursor.h >= el->el_term.t_size.h) {
- /* if we must overflow */
- el->el_cursor.h = 0;
-
- /*
- * If we would overflow (input is longer than terminal size),
- * emulate scroll by dropping first line and shuffling the rest.
- * We do this via pointer shuffling - it's safe in this case
- * and we avoid memcpy().
- */
- if (el->el_cursor.v + 1 >= el->el_term.t_size.v) {
- int i, lins = el->el_term.t_size.v;
- char *firstline = el->el_display[0];
-
- for(i=1; i < lins; i++)
- el->el_display[i-1] = el->el_display[i];
-
- re__copy_and_pad(firstline, "", 0);
- el->el_display[i-1] = firstline;
- } else {
- el->el_cursor.v++;
- el->el_refresh.r_oldcv++;
- }
- if (EL_HAS_AUTO_MARGINS) {
- if (EL_HAS_MAGIC_MARGINS) {
- term__putc(' ');
- term__putc('\b');
- }
- } else {
- term__putc('\r');
- term__putc('\n');
- }
- }
-}
-
-
-/* re_fastaddc():
- * we added just one char, handle it fast.
- * Assumes that screen cursor == real cursor
- */
-protected void
-re_fastaddc(EditLine *el)
-{
- char c;
- int rhdiff;
-
- c = el->el_line.cursor[-1];
-
- if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) {
- re_refresh(el); /* too hard to handle */
- return;
- }
- rhdiff = el->el_term.t_size.h - el->el_cursor.h -
- el->el_rprompt.p_pos.h;
- if (el->el_rprompt.p_pos.h && rhdiff < 3) {
- re_refresh(el); /* clear out rprompt if less than 1 char gap */
- return;
- } /* else (only do at end of line, no TAB) */
- if (iscntrl((unsigned char) c)) { /* if control char, do caret */
- char mc = (c == '\177') ? '?' : (c | 0100);
- re_fastputc(el, '^');
- re_fastputc(el, mc);
- } else if (isprint((unsigned char) c)) { /* normal char */
- re_fastputc(el, c);
- } else {
- re_fastputc(el, '\\');
- re_fastputc(el, (int) ((((unsigned int) c >> 6) & 7) + '0'));
- re_fastputc(el, (int) ((((unsigned int) c >> 3) & 7) + '0'));
- re_fastputc(el, (c & 7) + '0');
- }
- term__flush();
-}
-
-
-/* re_clear_display():
- * clear the screen buffers so that new new prompt starts fresh.
- */
-protected void
-re_clear_display(EditLine *el)
-{
- int i;
-
- el->el_cursor.v = 0;
- el->el_cursor.h = 0;
- for (i = 0; i < el->el_term.t_size.v; i++)
- el->el_display[i][0] = '\0';
- el->el_refresh.r_oldcv = 0;
-}
-
-
-/* re_clear_lines():
- * Make sure all lines are *really* blank
- */
-protected void
-re_clear_lines(EditLine *el)
-{
-
- if (EL_CAN_CEOL) {
- int i;
- term_move_to_char(el, 0);
- for (i = 0; i <= el->el_refresh.r_oldcv; i++) {
- /* for each line on the screen */
- term_move_to_line(el, i);
- term_clear_EOL(el, el->el_term.t_size.h);
- }
- term_move_to_line(el, 0);
- } else {
- term_move_to_line(el, el->el_refresh.r_oldcv);
- /* go to last line */
- term__putc('\r'); /* go to BOL */
- term__putc('\n'); /* go to new line */
- }
-}
diff --git a/main/editline/refresh.h b/main/editline/refresh.h
deleted file mode 100644
index 33c0887c1..000000000
--- a/main/editline/refresh.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* $NetBSD: refresh.h,v 1.4 2001/01/10 07:45:42 jdolecek Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)refresh.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.refresh.h: Screen refresh functions
- */
-#ifndef _h_el_refresh
-#define _h_el_refresh
-
-#include "histedit.h"
-
-typedef struct {
- coord_t r_cursor; /* Refresh cursor position */
- int r_oldcv; /* Vertical locations */
- int r_newcv;
-} el_refresh_t;
-
-protected void re_putc(EditLine *, int, int);
-protected void re_clear_lines(EditLine *);
-protected void re_clear_display(EditLine *);
-protected void re_refresh(EditLine *);
-protected void re_refresh_cursor(EditLine *);
-protected void re_fastaddc(EditLine *);
-protected void re_goto_bottom(EditLine *);
-
-#endif /* _h_el_refresh */
diff --git a/main/editline/search.c b/main/editline/search.c
deleted file mode 100644
index 7c1cb84ef..000000000
--- a/main/editline/search.c
+++ /dev/null
@@ -1,649 +0,0 @@
-/* $NetBSD: search.c,v 1.12 2002/03/18 16:00:58 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: search.c,v 1.12 2002/03/18 16:00:58 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * search.c: History and character search functions
- */
-#include <stdlib.h>
-#if defined(REGEX)
-#include <regex.h>
-#elif defined(REGEXP)
-#include <regexp.h>
-#endif
-#include "el.h"
-
-/*
- * Adjust cursor in vi mode to include the character under it
- */
-#define EL_CURSOR(el) \
- ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \
- ((el)->el_map.current == (el)->el_map.alt)))
-
-/* search_init():
- * Initialize the search stuff
- */
-protected int
-search_init(EditLine *el)
-{
-
- el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ);
- if (el->el_search.patbuf == NULL)
- return (-1);
- el->el_search.patlen = 0;
- el->el_search.patdir = -1;
- el->el_search.chacha = '\0';
- el->el_search.chadir = -1;
- return (0);
-}
-
-
-/* search_end():
- * Initialize the search stuff
- */
-protected void
-search_end(EditLine *el)
-{
-
- el_free((ptr_t) el->el_search.patbuf);
- el->el_search.patbuf = NULL;
-}
-
-
-#ifdef REGEXP
-/* regerror():
- * Handle regular expression errors
- */
-public void
-/*ARGSUSED*/
-regerror(const char *msg)
-{
-}
-#endif
-
-
-/* el_match():
- * Return if string matches pattern
- */
-protected int
-el_match(const char *str, const char *pat)
-{
-#if defined (REGEX)
- regex_t re;
- int rv;
-#elif defined (REGEXP)
- regexp *rp;
- int rv;
-#else
- extern char *re_comp(const char *);
- extern int re_exec(const char *);
-#endif
-
- if (strstr(str, pat) != NULL)
- return (1);
-
-#if defined(REGEX)
- if (regcomp(&re, pat, 0) == 0) {
- rv = regexec(&re, str, 0, NULL, 0) == 0;
- regfree(&re);
- } else {
- rv = 0;
- }
- return (rv);
-#elif defined(REGEXP)
- if ((re = regcomp(pat)) != NULL) {
- rv = regexec(re, str);
- free((ptr_t) re);
- } else {
- rv = 0;
- }
- return (rv);
-#else
- if (re_comp(pat) != NULL)
- return (0);
- else
- return (re_exec(str) == 1);
-#endif
-}
-
-
-/* c_hmatch():
- * return True if the pattern matches the prefix
- */
-protected int
-c_hmatch(EditLine *el, const char *str)
-{
-#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "match `%s' with `%s'\n",
- el->el_search.patbuf, str);
-#endif /* SDEBUG */
-
- return (el_match(str, el->el_search.patbuf));
-}
-
-
-/* c_setpat():
- * Set the history seatch pattern
- */
-protected void
-c_setpat(EditLine *el)
-{
- if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY &&
- el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) {
- el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer;
- if (el->el_search.patlen >= EL_BUFSIZ)
- el->el_search.patlen = EL_BUFSIZ - 1;
- if (el->el_search.patlen != 0) {
- (void) strncpy(el->el_search.patbuf, el->el_line.buffer,
- el->el_search.patlen);
- el->el_search.patbuf[el->el_search.patlen] = '\0';
- } else
- el->el_search.patlen = strlen(el->el_search.patbuf);
- }
-#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "\neventno = %d\n",
- el->el_history.eventno);
- (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen);
- (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n",
- el->el_search.patbuf);
- (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n",
- EL_CURSOR(el) - el->el_line.buffer,
- el->el_line.lastchar - el->el_line.buffer);
-#endif
-}
-
-
-/* ce_inc_search():
- * Emacs incremental search
- */
-protected el_action_t
-ce_inc_search(EditLine *el, int dir)
-{
- static const char STRfwd[] = {'f', 'w', 'd', '\0'},
- STRbck[] = {'b', 'c', 'k', '\0'};
- static char pchar = ':';/* ':' = normal, '?' = failed */
- static char endcmd[2] = {'\0', '\0'};
- char ch, *ocursor = el->el_line.cursor, oldpchar = pchar;
- const char *cp;
-
- el_action_t ret = CC_NORM;
-
- int ohisteventno = el->el_history.eventno;
- int oldpatlen = el->el_search.patlen;
- int newdir = dir;
- int done, redo;
-
- if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 +
- el->el_search.patlen >= el->el_line.limit)
- return (CC_ERROR);
-
- for (;;) {
-
- if (el->el_search.patlen == 0) { /* first round */
- pchar = ':';
-#ifdef ANCHOR
- el->el_search.patbuf[el->el_search.patlen++] = '.';
- el->el_search.patbuf[el->el_search.patlen++] = '*';
-#endif
- }
- done = redo = 0;
- *el->el_line.lastchar++ = '\n';
- for (cp = (newdir == ED_SEARCH_PREV_HISTORY) ? STRbck : STRfwd;
- *cp; *el->el_line.lastchar++ = *cp++)
- continue;
- *el->el_line.lastchar++ = pchar;
- for (cp = &el->el_search.patbuf[1];
- cp < &el->el_search.patbuf[el->el_search.patlen];
- *el->el_line.lastchar++ = *cp++)
- continue;
- *el->el_line.lastchar = '\0';
- re_refresh(el);
-
- if (el_getc(el, &ch) != 1)
- return (ed_end_of_file(el, 0));
-
- switch (el->el_map.current[(unsigned char) ch]) {
- case ED_INSERT:
- case ED_DIGIT:
- if (el->el_search.patlen > EL_BUFSIZ - 3)
- term_beep(el);
- else {
- el->el_search.patbuf[el->el_search.patlen++] =
- ch;
- *el->el_line.lastchar++ = ch;
- *el->el_line.lastchar = '\0';
- re_refresh(el);
- }
- break;
-
- case EM_INC_SEARCH_NEXT:
- newdir = ED_SEARCH_NEXT_HISTORY;
- redo++;
- break;
-
- case EM_INC_SEARCH_PREV:
- newdir = ED_SEARCH_PREV_HISTORY;
- redo++;
- break;
-
- case ED_DELETE_PREV_CHAR:
- if (el->el_search.patlen > 1)
- done++;
- else
- term_beep(el);
- break;
-
- default:
- switch (ch) {
- case 0007: /* ^G: Abort */
- ret = CC_ERROR;
- done++;
- break;
-
- case 0027: /* ^W: Append word */
- /* No can do if globbing characters in pattern */
- for (cp = &el->el_search.patbuf[1];; cp++)
- if (cp >= &el->el_search.patbuf[el->el_search.patlen]) {
- el->el_line.cursor +=
- el->el_search.patlen - 1;
- cp = c__next_word(el->el_line.cursor,
- el->el_line.lastchar, 1,
- ce__isword);
- while (el->el_line.cursor < cp &&
- *el->el_line.cursor != '\n') {
- if (el->el_search.patlen >
- EL_BUFSIZ - 3) {
- term_beep(el);
- break;
- }
- el->el_search.patbuf[el->el_search.patlen++] =
- *el->el_line.cursor;
- *el->el_line.lastchar++ =
- *el->el_line.cursor++;
- }
- el->el_line.cursor = ocursor;
- *el->el_line.lastchar = '\0';
- re_refresh(el);
- break;
- } else if (isglob(*cp)) {
- term_beep(el);
- break;
- }
- break;
-
- default: /* Terminate and execute cmd */
- endcmd[0] = ch;
- el_push(el, endcmd);
- /* FALLTHROUGH */
-
- case 0033: /* ESC: Terminate */
- ret = CC_REFRESH;
- done++;
- break;
- }
- break;
- }
-
- while (el->el_line.lastchar > el->el_line.buffer &&
- *el->el_line.lastchar != '\n')
- *el->el_line.lastchar-- = '\0';
- *el->el_line.lastchar = '\0';
-
- if (!done) {
-
- /* Can't search if unmatched '[' */
- for (cp = &el->el_search.patbuf[el->el_search.patlen-1],
- ch = ']';
- cp > el->el_search.patbuf;
- cp--)
- if (*cp == '[' || *cp == ']') {
- ch = *cp;
- break;
- }
- if (el->el_search.patlen > 1 && ch != '[') {
- if (redo && newdir == dir) {
- if (pchar == '?') { /* wrap around */
- el->el_history.eventno =
- newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff;
- if (hist_get(el) == CC_ERROR)
- /* el->el_history.event
- * no was fixed by
- * first call */
- (void) hist_get(el);
- el->el_line.cursor = newdir ==
- ED_SEARCH_PREV_HISTORY ?
- el->el_line.lastchar :
- el->el_line.buffer;
- } else
- el->el_line.cursor +=
- newdir ==
- ED_SEARCH_PREV_HISTORY ?
- -1 : 1;
- }
-#ifdef ANCHOR
- el->el_search.patbuf[el->el_search.patlen++] =
- '.';
- el->el_search.patbuf[el->el_search.patlen++] =
- '*';
-#endif
- el->el_search.patbuf[el->el_search.patlen] =
- '\0';
- if (el->el_line.cursor < el->el_line.buffer ||
- el->el_line.cursor > el->el_line.lastchar ||
- (ret = ce_search_line(el,
- &el->el_search.patbuf[1],
- newdir)) == CC_ERROR) {
- /* avoid c_setpat */
- el->el_state.lastcmd =
- (el_action_t) newdir;
- ret = newdir == ED_SEARCH_PREV_HISTORY ?
- ed_search_prev_history(el, 0) :
- ed_search_next_history(el, 0);
- if (ret != CC_ERROR) {
- el->el_line.cursor = newdir ==
- ED_SEARCH_PREV_HISTORY ?
- el->el_line.lastchar :
- el->el_line.buffer;
- (void) ce_search_line(el,
- &el->el_search.patbuf[1],
- newdir);
- }
- }
- el->el_search.patbuf[--el->el_search.patlen] =
- '\0';
- if (ret == CC_ERROR) {
- term_beep(el);
- if (el->el_history.eventno !=
- ohisteventno) {
- el->el_history.eventno =
- ohisteventno;
- if (hist_get(el) == CC_ERROR)
- return (CC_ERROR);
- }
- el->el_line.cursor = ocursor;
- pchar = '?';
- } else {
- pchar = ':';
- }
- }
- ret = ce_inc_search(el, newdir);
-
- if (ret == CC_ERROR && pchar == '?' && oldpchar == ':')
- /*
- * break abort of failed search at last
- * non-failed
- */
- ret = CC_NORM;
-
- }
- if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
- /* restore on normal return or error exit */
- pchar = oldpchar;
- el->el_search.patlen = oldpatlen;
- if (el->el_history.eventno != ohisteventno) {
- el->el_history.eventno = ohisteventno;
- if (hist_get(el) == CC_ERROR)
- return (CC_ERROR);
- }
- el->el_line.cursor = ocursor;
- if (ret == CC_ERROR)
- re_refresh(el);
- }
- if (done || ret != CC_NORM)
- return (ret);
- }
-}
-
-
-/* cv_search():
- * Vi search.
- */
-protected el_action_t
-cv_search(EditLine *el, int dir)
-{
- char ch;
- char tmpbuf[EL_BUFSIZ];
- int tmplen;
-
- tmplen = 0;
-#ifdef ANCHOR
- tmpbuf[tmplen++] = '.';
- tmpbuf[tmplen++] = '*';
-#endif
-
- el->el_line.buffer[0] = '\0';
- el->el_line.lastchar = el->el_line.buffer;
- el->el_line.cursor = el->el_line.buffer;
- el->el_search.patdir = dir;
-
- c_insert(el, 2); /* prompt + '\n' */
- *el->el_line.cursor++ = '\n';
- *el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?';
- re_refresh(el);
-
-#ifdef ANCHOR
-#define LEN 2
-#else
-#define LEN 0
-#endif
-
- tmplen = c_gets(el, &tmpbuf[LEN]) + LEN;
- ch = tmpbuf[tmplen];
- tmpbuf[tmplen] = '\0';
-
- if (tmplen == LEN) {
- /*
- * Use the old pattern, but wild-card it.
- */
- if (el->el_search.patlen == 0) {
- el->el_line.buffer[0] = '\0';
- el->el_line.lastchar = el->el_line.buffer;
- el->el_line.cursor = el->el_line.buffer;
- re_refresh(el);
- return (CC_ERROR);
- }
-#ifdef ANCHOR
- if (el->el_search.patbuf[0] != '.' &&
- el->el_search.patbuf[0] != '*') {
- (void) strncpy(tmpbuf, el->el_search.patbuf,
- sizeof(tmpbuf) - 1);
- el->el_search.patbuf[0] = '.';
- el->el_search.patbuf[1] = '*';
- (void) strncpy(&el->el_search.patbuf[2], tmpbuf,
- EL_BUFSIZ - 3);
- el->el_search.patlen++;
- el->el_search.patbuf[el->el_search.patlen++] = '.';
- el->el_search.patbuf[el->el_search.patlen++] = '*';
- el->el_search.patbuf[el->el_search.patlen] = '\0';
- }
-#endif
- } else {
-#ifdef ANCHOR
- tmpbuf[tmplen++] = '.';
- tmpbuf[tmplen++] = '*';
-#endif
- tmpbuf[tmplen] = '\0';
- (void) strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1);
- el->el_search.patlen = tmplen;
- }
- el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */
- el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer;
- if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
- ed_search_next_history(el, 0)) == CC_ERROR) {
- re_refresh(el);
- return (CC_ERROR);
- } else {
- if (ch == 0033) {
- re_refresh(el);
- *el->el_line.lastchar++ = '\n';
- *el->el_line.lastchar = '\0';
- re_goto_bottom(el);
- return (CC_NEWLINE);
- } else
- return (CC_REFRESH);
- }
-}
-
-
-/* ce_search_line():
- * Look for a pattern inside a line
- */
-protected el_action_t
-ce_search_line(EditLine *el, char *pattern, int dir)
-{
- char *cp;
-
- if (dir == ED_SEARCH_PREV_HISTORY) {
- for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--)
- if (el_match(cp, pattern)) {
- el->el_line.cursor = cp;
- return (CC_NORM);
- }
- return (CC_ERROR);
- } else {
- for (cp = el->el_line.cursor; *cp != '\0' &&
- cp < el->el_line.limit; cp++)
- if (el_match(cp, pattern)) {
- el->el_line.cursor = cp;
- return (CC_NORM);
- }
- return (CC_ERROR);
- }
-}
-
-
-/* cv_repeat_srch():
- * Vi repeat search
- */
-protected el_action_t
-cv_repeat_srch(EditLine *el, int c)
-{
-
-#ifdef SDEBUG
- (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n",
- c, el->el_search.patlen, el->el_search.patbuf);
-#endif
-
- el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */
- el->el_line.lastchar = el->el_line.buffer;
-
- switch (c) {
- case ED_SEARCH_NEXT_HISTORY:
- return (ed_search_next_history(el, 0));
- case ED_SEARCH_PREV_HISTORY:
- return (ed_search_prev_history(el, 0));
- default:
- return (CC_ERROR);
- }
-}
-
-
-/* cv_csearch_back():
- * Vi character search reverse
- */
-protected el_action_t
-cv_csearch_back(EditLine *el, int ch, int count, int tflag)
-{
- char *cp;
-
- cp = el->el_line.cursor;
- while (count--) {
- if (*cp == ch)
- cp--;
- while (cp > el->el_line.buffer && *cp != ch)
- cp--;
- }
-
- if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch))
- return (CC_ERROR);
-
- if (*cp == ch && tflag)
- cp++;
-
- el->el_line.cursor = cp;
-
- if (el->el_chared.c_vcmd.action & DELETE) {
- el->el_line.cursor++;
- cv_delfini(el);
- return (CC_REFRESH);
- }
- re_refresh_cursor(el);
- return (CC_NORM);
-}
-
-
-/* cv_csearch_fwd():
- * Vi character search forward
- */
-protected el_action_t
-cv_csearch_fwd(EditLine *el, int ch, int count, int tflag)
-{
- char *cp;
-
- cp = el->el_line.cursor;
- while (count--) {
- if (*cp == ch)
- cp++;
- while (cp < el->el_line.lastchar && *cp != ch)
- cp++;
- }
-
- if (cp >= el->el_line.lastchar)
- return (CC_ERROR);
-
- if (*cp == ch && tflag)
- cp--;
-
- el->el_line.cursor = cp;
-
- if (el->el_chared.c_vcmd.action & DELETE) {
- el->el_line.cursor++;
- cv_delfini(el);
- return (CC_REFRESH);
- }
- re_refresh_cursor(el);
- return (CC_NORM);
-}
diff --git a/main/editline/search.h b/main/editline/search.h
deleted file mode 100644
index 676bbe2e3..000000000
--- a/main/editline/search.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* $NetBSD: search.h,v 1.5 2000/09/04 22:06:32 lukem Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)search.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.search.h: Line and history searching utilities
- */
-#ifndef _h_el_search
-#define _h_el_search
-
-#include "histedit.h"
-
-typedef struct el_search_t {
- char *patbuf; /* The pattern buffer */
- size_t patlen; /* Length of the pattern buffer */
- int patdir; /* Direction of the last search */
- int chadir; /* Character search direction */
- char chacha; /* Character we are looking for */
-} el_search_t;
-
-
-protected int el_match(const char *, const char *);
-protected int search_init(EditLine *);
-protected void search_end(EditLine *);
-protected int c_hmatch(EditLine *, const char *);
-protected void c_setpat(EditLine *);
-protected el_action_t ce_inc_search(EditLine *, int);
-protected el_action_t cv_search(EditLine *, int);
-protected el_action_t ce_search_line(EditLine *, char *, int);
-protected el_action_t cv_repeat_srch(EditLine *, int);
-protected el_action_t cv_csearch_back(EditLine *, int, int, int);
-protected el_action_t cv_csearch_fwd(EditLine *, int, int, int);
-
-#endif /* _h_el_search */
diff --git a/main/editline/sig.c b/main/editline/sig.c
deleted file mode 100644
index 0acba1247..000000000
--- a/main/editline/sig.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/* $NetBSD: sig.c,v 1.9 2002/03/18 16:00:58 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: sig.c,v 1.9 2002/03/18 16:00:58 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * sig.c: Signal handling stuff.
- * our policy is to trap all signals, set a good state
- * and pass the ball to our caller.
- */
-#include "el.h"
-#include <stdlib.h>
-
-private EditLine *sel = NULL;
-
-private const int sighdl[] = {
-#define _DO(a) (a),
- ALLSIGS
-#undef _DO
- - 1
-};
-
-private void sig_handler(int);
-
-/* sig_handler():
- * This is the handler called for all signals
- * XXX: we cannot pass any data so we just store the old editline
- * state in a private variable
- */
-private void
-sig_handler(int signo)
-{
- int i;
- sigset_t nset, oset;
-
- (void) sigemptyset(&nset);
- (void) sigaddset(&nset, signo);
- (void) sigprocmask(SIG_BLOCK, &nset, &oset);
-
- switch (signo) {
- case SIGCONT:
- tty_rawmode(sel);
- if (ed_redisplay(sel, 0) == CC_REFRESH)
- re_refresh(sel);
- term__flush();
- break;
-
- case SIGWINCH:
- el_resize(sel);
- break;
-
- default:
- tty_cookedmode(sel);
- break;
- }
-
- for (i = 0; sighdl[i] != -1; i++)
- if (signo == sighdl[i])
- break;
-
- (void) signal(signo, sel->el_signal[i]);
- (void) sigprocmask(SIG_SETMASK, &oset, NULL);
- (void) kill(0, signo);
-}
-
-
-/* sig_init():
- * Initialize all signal stuff
- */
-protected int
-sig_init(EditLine *el)
-{
- int i;
- sigset_t nset, oset;
-
- (void) sigemptyset(&nset);
-#define _DO(a) (void) sigaddset(&nset, a);
- ALLSIGS
-#undef _DO
- (void) sigprocmask(SIG_BLOCK, &nset, &oset);
-
-#define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t))
-
- el->el_signal = (sig_t *) el_malloc(SIGSIZE);
- if (el->el_signal == NULL)
- return (-1);
- for (i = 0; sighdl[i] != -1; i++)
- el->el_signal[i] = SIG_ERR;
-
- (void) sigprocmask(SIG_SETMASK, &oset, NULL);
-
- return (0);
-}
-
-
-/* sig_end():
- * Clear all signal stuff
- */
-protected void
-sig_end(EditLine *el)
-{
-
- el_free((ptr_t) el->el_signal);
- el->el_signal = NULL;
-}
-
-
-/* sig_set():
- * set all the signal handlers
- */
-protected void
-sig_set(EditLine *el)
-{
- int i;
- sigset_t nset, oset;
-
- (void) sigemptyset(&nset);
-#define _DO(a) (void) sigaddset(&nset, a);
- ALLSIGS
-#undef _DO
- (void) sigprocmask(SIG_BLOCK, &nset, &oset);
-
- for (i = 0; sighdl[i] != -1; i++) {
- sig_t s;
- /* This could happen if we get interrupted */
- if ((s = signal(sighdl[i], sig_handler)) != sig_handler)
- el->el_signal[i] = s;
- }
- sel = el;
- (void) sigprocmask(SIG_SETMASK, &oset, NULL);
-}
-
-
-/* sig_clr():
- * clear all the signal handlers
- */
-protected void
-sig_clr(EditLine *el)
-{
- int i;
- sigset_t nset, oset;
-
- (void) sigemptyset(&nset);
-#define _DO(a) (void) sigaddset(&nset, a);
- ALLSIGS
-#undef _DO
- (void) sigprocmask(SIG_BLOCK, &nset, &oset);
-
- for (i = 0; sighdl[i] != -1; i++)
- if (el->el_signal[i] != SIG_ERR)
- (void) signal(sighdl[i], el->el_signal[i]);
-
- sel = NULL; /* we are going to die if the handler is
- * called */
- (void) sigprocmask(SIG_SETMASK, &oset, NULL);
-}
diff --git a/main/editline/sig.h b/main/editline/sig.h
deleted file mode 100644
index e7231b65c..000000000
--- a/main/editline/sig.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* $NetBSD: sig.h,v 1.3 2000/09/04 22:06:32 lukem Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)sig.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.sig.h: Signal handling functions
- */
-#ifndef _h_el_sig
-#define _h_el_sig
-
-#include <signal.h>
-
-#include "histedit.h"
-
-/*
- * Define here all the signals we are going to handle
- * The _DO macro is used to iterate in the source code
- */
-#define ALLSIGS \
- _DO(SIGINT) \
- _DO(SIGTSTP) \
- _DO(SIGSTOP) \
- _DO(SIGQUIT) \
- _DO(SIGHUP) \
- _DO(SIGTERM) \
- _DO(SIGCONT) \
- _DO(SIGWINCH)
-
-typedef sig_t *el_signal_t;
-
-protected void sig_end(EditLine*);
-protected int sig_init(EditLine*);
-protected void sig_set(EditLine*);
-protected void sig_clr(EditLine*);
-
-#endif /* _h_el_sig */
diff --git a/main/editline/sys.h b/main/editline/sys.h
deleted file mode 100644
index a306d1df7..000000000
--- a/main/editline/sys.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $NetBSD: sys.h,v 1.5 2002/03/18 16:00:59 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)sys.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * sys.h: Put all the stupid compiler and system dependencies here...
- */
-#ifndef _h_sys
-#define _h_sys
-
-#ifndef public
-# define public /* Externally visible functions/variables */
-#endif
-
-#ifndef private
-# define private static /* Always hidden internals */
-#endif
-
-#ifndef protected
-# define protected /* Redefined from elsewhere to "static" */
- /* When we want to hide everything */
-#endif
-
-#ifndef _PTR_T
-# define _PTR_T
-typedef void *ptr_t;
-#endif
-
-#ifndef _IOCTL_T
-# define _IOCTL_T
-typedef void *ioctl_t;
-#endif
-
-#include <stdio.h>
-
-#ifndef HAVE_STRLCAT
-#define strlcat libedit_strlcat
-size_t strlcat(char *dst, const char *src, size_t size);
-#endif
-
-#ifndef HAVE_STRLCPY
-#define strlcpy libedit_strlcpy
-size_t strlcpy(char *dst, const char *src, size_t size);
-#endif
-
-#ifndef HAVE_FGETLN
-#define fgetln libedit_fgetln
-char *fgetln(FILE *fp, size_t *len);
-#endif
-
-#define REGEX /* Use POSIX.2 regular expression functions */
-#undef REGEXP /* Use UNIX V8 regular expression functions */
-
-#ifdef SUNOS
-# undef REGEX
-# undef REGEXP
-# include <malloc.h>
-typedef void (*sig_t)(int);
-# ifdef __GNUC__
-/*
- * Broken hdrs.
- */
-#ifndef SOLARIS
-extern int tgetent(const char *bp, char *name);
-extern int tgetflag(const char *id);
-extern int tgetnum(const char *id);
-extern char *tgetstr(const char *id, char **area);
-#endif
-extern char *tgoto(const char *cap, int col, int row);
-extern int tputs(const char *str, int affcnt, int (*putc)(int));
-extern char *getenv(const char *);
-extern int fprintf(FILE *, const char *, ...);
-extern int sigsetmask(int);
-extern int sigblock(int);
-extern int fputc(int, FILE *);
-extern int fgetc(FILE *);
-extern int fflush(FILE *);
-extern int tolower(int);
-extern int toupper(int);
-extern int errno, sys_nerr;
-extern char *sys_errlist[];
-extern void perror(const char *);
-# include <string.h>
-# define strerror(e) sys_errlist[e]
-# endif
-# ifdef SABER
-extern ptr_t memcpy(ptr_t, const ptr_t, size_t);
-extern ptr_t memset(ptr_t, int, size_t);
-# endif
-extern char *fgetline(FILE *, int *);
-#endif
-
-#ifdef HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif
-
-#endif /* _h_sys */
diff --git a/main/editline/term.c b/main/editline/term.c
deleted file mode 100644
index fb627cabb..000000000
--- a/main/editline/term.c
+++ /dev/null
@@ -1,1587 +0,0 @@
-/* $NetBSD: term.c,v 1.35 2002/03/18 16:00:59 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95";
-#else
-__RCSID("$NetBSD: term.c,v 1.35 2002/03/18 16:00:59 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * term.c: Editor/termcap-curses interface
- * We have to declare a static variable here, since the
- * termcap putchar routine does not take an argument!
- */
-#include <stdio.h>
-#include <signal.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#ifdef HAVE_TERMCAP_H
-#include <termcap.h>
-#endif
-#ifdef HAVE_CURSES_H
-#include <curses.h>
-#endif
-#ifdef HAVE_NCURSES_H
-#include <ncurses.h>
-#endif
-#if defined(HAVE_TERM_H)
-#include "term.h"
-/* Can not use /usr/include/term.h because of a lot of incompatibilities, so just define some prototypes */
-extern int tgetent(char *, const char *);
-extern int tgetflag(const char *);
-extern int tgetnum(const char *);
-extern char *tgetstr(const char *, char **);
-extern int tputs (const char *, int, int (*)(int));
-extern char *tgoto (const char *, int, int);
-#endif /* defined(HAVE_TERM_H) */
-#include <sys/types.h>
-#include <sys/ioctl.h>
-
-#include "el.h"
-
-/*
- * IMPORTANT NOTE: these routines are allowed to look at the current screen
- * and the current possition assuming that it is correct. If this is not
- * true, then the update will be WRONG! This is (should be) a valid
- * assumption...
- */
-
-#define TC_BUFSIZE 2048
-
-#define GoodStr(a) (el->el_term.t_str[a] != NULL && \
- el->el_term.t_str[a][0] != '\0')
-#define Str(a) el->el_term.t_str[a]
-#define Val(a) el->el_term.t_val[a]
-
-#ifdef notdef
-private const struct {
- const char *b_name;
- int b_rate;
-} baud_rate[] = {
-#ifdef B0
- { "0", B0 },
-#endif
-#ifdef B50
- { "50", B50 },
-#endif
-#ifdef B75
- { "75", B75 },
-#endif
-#ifdef B110
- { "110", B110 },
-#endif
-#ifdef B134
- { "134", B134 },
-#endif
-#ifdef B150
- { "150", B150 },
-#endif
-#ifdef B200
- { "200", B200 },
-#endif
-#ifdef B300
- { "300", B300 },
-#endif
-#ifdef B600
- { "600", B600 },
-#endif
-#ifdef B900
- { "900", B900 },
-#endif
-#ifdef B1200
- { "1200", B1200 },
-#endif
-#ifdef B1800
- { "1800", B1800 },
-#endif
-#ifdef B2400
- { "2400", B2400 },
-#endif
-#ifdef B3600
- { "3600", B3600 },
-#endif
-#ifdef B4800
- { "4800", B4800 },
-#endif
-#ifdef B7200
- { "7200", B7200 },
-#endif
-#ifdef B9600
- { "9600", B9600 },
-#endif
-#ifdef EXTA
- { "19200", EXTA },
-#endif
-#ifdef B19200
- { "19200", B19200 },
-#endif
-#ifdef EXTB
- { "38400", EXTB },
-#endif
-#ifdef B38400
- { "38400", B38400 },
-#endif
- { NULL, 0 }
-};
-#endif
-
-private const struct termcapstr {
- const char *name;
- const char *long_name;
-} tstr[] = {
-#define T_al 0
- { "al", "add new blank line" },
-#define T_bl 1
- { "bl", "audible bell" },
-#define T_cd 2
- { "cd", "clear to bottom" },
-#define T_ce 3
- { "ce", "clear to end of line" },
-#define T_ch 4
- { "ch", "cursor to horiz pos" },
-#define T_cl 5
- { "cl", "clear screen" },
-#define T_dc 6
- { "dc", "delete a character" },
-#define T_dl 7
- { "dl", "delete a line" },
-#define T_dm 8
- { "dm", "start delete mode" },
-#define T_ed 9
- { "ed", "end delete mode" },
-#define T_ei 10
- { "ei", "end insert mode" },
-#define T_fs 11
- { "fs", "cursor from status line" },
-#define T_ho 12
- { "ho", "home cursor" },
-#define T_ic 13
- { "ic", "insert character" },
-#define T_im 14
- { "im", "start insert mode" },
-#define T_ip 15
- { "ip", "insert padding" },
-#define T_kd 16
- { "kd", "sends cursor down" },
-#define T_kl 17
- { "kl", "sends cursor left" },
-#define T_kr 18
- { "kr", "sends cursor right" },
-#define T_ku 19
- { "ku", "sends cursor up" },
-#define T_md 20
- { "md", "begin bold" },
-#define T_me 21
- { "me", "end attributes" },
-#define T_nd 22
- { "nd", "non destructive space" },
-#define T_se 23
- { "se", "end standout" },
-#define T_so 24
- { "so", "begin standout" },
-#define T_ts 25
- { "ts", "cursor to status line" },
-#define T_up 26
- { "up", "cursor up one" },
-#define T_us 27
- { "us", "begin underline" },
-#define T_ue 28
- { "ue", "end underline" },
-#define T_vb 29
- { "vb", "visible bell" },
-#define T_DC 30
- { "DC", "delete multiple chars" },
-#define T_DO 31
- { "DO", "cursor down multiple" },
-#define T_IC 32
- { "IC", "insert multiple chars" },
-#define T_LE 33
- { "LE", "cursor left multiple" },
-#define T_RI 34
- { "RI", "cursor right multiple" },
-#define T_UP 35
- { "UP", "cursor up multiple" },
-#define T_kh 36
- { "kh", "send cursor home" },
-#define T_at7 37
- { "@7", "send cursor end" },
-#define T_str 38
- { NULL, NULL }
-};
-
-private const struct termcapval {
- const char *name;
- const char *long_name;
-} tval[] = {
-#define T_am 0
- { "am", "has automatic margins" },
-#define T_pt 1
- { "pt", "has physical tabs" },
-#define T_li 2
- { "li", "Number of lines" },
-#define T_co 3
- { "co", "Number of columns" },
-#define T_km 4
- { "km", "Has meta key" },
-#define T_xt 5
- { "xt", "Tab chars destructive" },
-#define T_xn 6
- { "xn", "newline ignored at right margin" },
-#define T_MT 7
- { "MT", "Has meta key" }, /* XXX? */
-#define T_val 8
- { NULL, NULL, }
-};
-/* do two or more of the attributes use me */
-
-private void term_setflags(EditLine *);
-private int term_rebuffer_display(EditLine *);
-private void term_free_display(EditLine *);
-private int term_alloc_display(EditLine *);
-private void term_alloc(EditLine *, const struct termcapstr *, const char *);
-private void term_init_arrow(EditLine *);
-private void term_reset_arrow(EditLine *);
-
-
-private FILE *term_outfile = NULL; /* XXX: How do we fix that? */
-
-
-/* term_setflags():
- * Set the terminal capability flags
- */
-private void
-term_setflags(EditLine *el)
-{
- EL_FLAGS = 0;
- if (el->el_tty.t_tabs)
- EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0;
-
- EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0;
- EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0;
- EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0;
- EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ?
- TERM_CAN_INSERT : 0;
- EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP)) ? TERM_CAN_UP : 0;
- EL_FLAGS |= Val(T_am) ? TERM_HAS_AUTO_MARGINS : 0;
- EL_FLAGS |= Val(T_xn) ? TERM_HAS_MAGIC_MARGINS : 0;
-
- if (GoodStr(T_me) && GoodStr(T_ue))
- EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ?
- TERM_CAN_ME : 0;
- else
- EL_FLAGS &= ~TERM_CAN_ME;
- if (GoodStr(T_me) && GoodStr(T_se))
- EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ?
- TERM_CAN_ME : 0;
-
-
-#ifdef DEBUG_SCREEN
- if (!EL_CAN_UP) {
- (void) fprintf(el->el_errfile,
- "WARNING: Your terminal cannot move up.\n");
- (void) fprintf(el->el_errfile,
- "Editing may be odd for long lines.\n");
- }
- if (!EL_CAN_CEOL)
- (void) fprintf(el->el_errfile, "no clear EOL capability.\n");
- if (!EL_CAN_DELETE)
- (void) fprintf(el->el_errfile, "no delete char capability.\n");
- if (!EL_CAN_INSERT)
- (void) fprintf(el->el_errfile, "no insert char capability.\n");
-#endif /* DEBUG_SCREEN */
-}
-
-
-/* term_init():
- * Initialize the terminal stuff
- */
-protected int
-term_init(EditLine *el)
-{
-
- el->el_term.t_buf = (char *) el_malloc(TC_BUFSIZE);
- if (el->el_term.t_buf == NULL)
- return (-1);
- el->el_term.t_cap = (char *) el_malloc(TC_BUFSIZE);
- if (el->el_term.t_cap == NULL)
- return (-1);
- el->el_term.t_fkey = (fkey_t *) el_malloc(A_K_NKEYS * sizeof(fkey_t));
- if (el->el_term.t_fkey == NULL)
- return (-1);
- el->el_term.t_loc = 0;
- el->el_term.t_str = (char **) el_malloc(T_str * sizeof(char *));
- if (el->el_term.t_str == NULL)
- return (-1);
- (void) memset(el->el_term.t_str, 0, T_str * sizeof(char *));
- el->el_term.t_val = (int *) el_malloc(T_val * sizeof(int));
- if (el->el_term.t_val == NULL)
- return (-1);
- (void) memset(el->el_term.t_val, 0, T_val * sizeof(int));
- term_outfile = el->el_outfile;
- (void) term_set(el, NULL);
- term_init_arrow(el);
- return (0);
-}
-/* term_end():
- * Clean up the terminal stuff
- */
-protected void
-term_end(EditLine *el)
-{
-
- el_free((ptr_t) el->el_term.t_buf);
- el->el_term.t_buf = NULL;
- el_free((ptr_t) el->el_term.t_cap);
- el->el_term.t_cap = NULL;
- el_free((ptr_t) el->el_term.t_fkey);
- el->el_term.t_fkey = NULL;
- el->el_term.t_loc = 0;
- el_free((ptr_t) el->el_term.t_str);
- el->el_term.t_str = NULL;
- el_free((ptr_t) el->el_term.t_val);
- el->el_term.t_val = NULL;
- term_free_display(el);
-}
-
-
-/* term_alloc():
- * Maintain a string pool for termcap strings
- */
-private void
-term_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
-{
- char termbuf[TC_BUFSIZE];
- int tlen, clen;
- char **tlist = el->el_term.t_str;
- char **tmp, **str = &tlist[t - tstr];
-
- if (cap == NULL || *cap == '\0') {
- *str = NULL;
- return;
- } else
- clen = strlen(cap);
-
- tlen = *str == NULL ? 0 : strlen(*str);
-
- /*
- * New string is shorter; no need to allocate space
- */
- if (clen <= tlen) {
- (void) strcpy(*str, cap); /* XXX strcpy is safe */
- return;
- }
- /*
- * New string is longer; see if we have enough space to append
- */
- if (el->el_term.t_loc + 3 < TC_BUFSIZE) {
- /* XXX strcpy is safe */
- (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc],
- cap);
- el->el_term.t_loc += clen + 1; /* one for \0 */
- return;
- }
- /*
- * Compact our buffer; no need to check compaction, cause we know it
- * fits...
- */
- tlen = 0;
- for (tmp = tlist; tmp < &tlist[T_str]; tmp++)
- if (*tmp != NULL && *tmp != '\0' && *tmp != *str) {
- char *ptr;
-
- for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++)
- continue;
- termbuf[tlen++] = '\0';
- }
- memcpy(el->el_term.t_buf, termbuf, TC_BUFSIZE);
- el->el_term.t_loc = tlen;
- if (el->el_term.t_loc + 3 >= TC_BUFSIZE) {
- (void) fprintf(el->el_errfile,
- "Out of termcap string space.\n");
- return;
- }
- /* XXX strcpy is safe */
- (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap);
- el->el_term.t_loc += clen + 1; /* one for \0 */
- return;
-}
-
-
-/* term_rebuffer_display():
- * Rebuffer the display after the screen changed size
- */
-private int
-term_rebuffer_display(EditLine *el)
-{
- coord_t *c = &el->el_term.t_size;
-
- term_free_display(el);
-
- c->h = Val(T_co);
- c->v = Val(T_li);
-
- if (term_alloc_display(el) == -1)
- return (-1);
- return (0);
-}
-
-
-/* term_alloc_display():
- * Allocate a new display.
- */
-private int
-term_alloc_display(EditLine *el)
-{
- int i;
- char **b;
- coord_t *c = &el->el_term.t_size;
-
- b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1)));
- if (b == NULL)
- return (-1);
- for (i = 0; i < c->v; i++) {
- b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1)));
- if (b[i] == NULL)
- return (-1);
- }
- b[c->v] = NULL;
- el->el_display = b;
-
- b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1)));
- if (b == NULL)
- return (-1);
- for (i = 0; i < c->v; i++) {
- b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1)));
- if (b[i] == NULL)
- return (-1);
- }
- b[c->v] = NULL;
- el->el_vdisplay = b;
- return (0);
-}
-
-
-/* term_free_display():
- * Free the display buffers
- */
-private void
-term_free_display(EditLine *el)
-{
- char **b;
- char **bufp;
-
- b = el->el_display;
- el->el_display = NULL;
- if (b != NULL) {
- for (bufp = b; *bufp != NULL; bufp++)
- el_free((ptr_t) * bufp);
- el_free((ptr_t) b);
- }
- b = el->el_vdisplay;
- el->el_vdisplay = NULL;
- if (b != NULL) {
- for (bufp = b; *bufp != NULL; bufp++)
- el_free((ptr_t) * bufp);
- el_free((ptr_t) b);
- }
-}
-
-
-/* term_move_to_line():
- * move to line <where> (first line == 0)
- * as efficiently as possible
- */
-protected void
-term_move_to_line(EditLine *el, int where)
-{
- int del;
-
- if (where == el->el_cursor.v)
- return;
-
- if (where > el->el_term.t_size.v) {
-#ifdef DEBUG_SCREEN
- (void) fprintf(el->el_errfile,
- "term_move_to_line: where is ridiculous: %d\r\n", where);
-#endif /* DEBUG_SCREEN */
- return;
- }
- if ((del = where - el->el_cursor.v) > 0) {
- while (del > 0) {
- if (EL_HAS_AUTO_MARGINS &&
- el->el_display[el->el_cursor.v][0] != '\0') {
- /* move without newline */
- term_move_to_char(el, el->el_term.t_size.h - 1);
- term_overwrite(el,
- &el->el_display[el->el_cursor.v][el->el_cursor.h],
- 1);
- /* updates Cursor */
- del--;
- } else {
- if ((del > 1) && GoodStr(T_DO)) {
- (void) tputs(tgoto(Str(T_DO), del, del),
- del, term__putc);
- del = 0;
- } else {
- for (; del > 0; del--)
- term__putc('\n');
- /* because the \n will become \r\n */
- el->el_cursor.h = 0;
- }
- }
- }
- } else { /* del < 0 */
- if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
- (void) tputs(tgoto(Str(T_UP), -del, -del), -del,
- term__putc);
- else {
- if (GoodStr(T_up))
- for (; del < 0; del++)
- (void) tputs(Str(T_up), 1, term__putc);
- }
- }
- el->el_cursor.v = where;/* now where is here */
-}
-
-
-/* term_move_to_char():
- * Move to the character position specified
- */
-protected void
-term_move_to_char(EditLine *el, int where)
-{
- int del, i;
-
-mc_again:
- if (where == el->el_cursor.h)
- return;
-
- if (where > el->el_term.t_size.h) {
-#ifdef DEBUG_SCREEN
- (void) fprintf(el->el_errfile,
- "term_move_to_char: where is riduculous: %d\r\n", where);
-#endif /* DEBUG_SCREEN */
- return;
- }
- if (!where) { /* if where is first column */
- term__putc('\r'); /* do a CR */
- el->el_cursor.h = 0;
- return;
- }
- del = where - el->el_cursor.h;
-
- if ((del < -4 || del > 4) && GoodStr(T_ch))
- /* go there directly */
- (void) tputs(tgoto(Str(T_ch), where, where), where, term__putc);
- else {
- if (del > 0) { /* moving forward */
- if ((del > 4) && GoodStr(T_RI))
- (void) tputs(tgoto(Str(T_RI), del, del),
- del, term__putc);
- else {
- /* if I can do tabs, use them */
- if (EL_CAN_TAB) {
- if ((el->el_cursor.h & 0370) !=
- (where & 0370)) {
- /* if not within tab stop */
- for (i =
- (el->el_cursor.h & 0370);
- i < (where & 0370);
- i += 8)
- term__putc('\t');
- /* then tab over */
- el->el_cursor.h = where & 0370;
- }
- }
- /*
- * it's usually cheaper to just write the
- * chars, so we do.
- */
- /*
- * NOTE THAT term_overwrite() WILL CHANGE
- * el->el_cursor.h!!!
- */
- term_overwrite(el,
- &el->el_display[el->el_cursor.v][el->el_cursor.h],
- where - el->el_cursor.h);
-
- }
- } else { /* del < 0 := moving backward */
- if ((-del > 4) && GoodStr(T_LE))
- (void) tputs(tgoto(Str(T_LE), -del, -del),
- -del, term__putc);
- else { /* can't go directly there */
- /*
- * if the "cost" is greater than the "cost"
- * from col 0
- */
- if (EL_CAN_TAB ?
- (-del > (((unsigned int) where >> 3) +
- (where & 07)))
- : (-del > where)) {
- term__putc('\r'); /* do a CR */
- el->el_cursor.h = 0;
- goto mc_again; /* and try again */
- }
- for (i = 0; i < -del; i++)
- term__putc('\b');
- }
- }
- }
- el->el_cursor.h = where; /* now where is here */
-}
-
-
-/* term_overwrite():
- * Overstrike num characters
- */
-protected void
-term_overwrite(EditLine *el, const char *cp, int n)
-{
- if (n <= 0)
- return; /* catch bugs */
-
- if (n > el->el_term.t_size.h) {
-#ifdef DEBUG_SCREEN
- (void) fprintf(el->el_errfile,
- "term_overwrite: n is riduculous: %d\r\n", n);
-#endif /* DEBUG_SCREEN */
- return;
- }
- do {
- term__putc(*cp++);
- el->el_cursor.h++;
- } while (--n);
-
- if (el->el_cursor.h >= el->el_term.t_size.h) { /* wrap? */
- if (EL_HAS_AUTO_MARGINS) { /* yes */
- el->el_cursor.h = 0;
- el->el_cursor.v++;
- if (EL_HAS_MAGIC_MARGINS) {
- /* force the wrap to avoid the "magic"
- * situation */
- char c;
- if ((c = el->el_display[el->el_cursor.v][el->el_cursor.h])
- != '\0')
- term_overwrite(el, &c, 1);
- else
- term__putc(' ');
- el->el_cursor.h = 1;
- }
- } else /* no wrap, but cursor stays on screen */
- el->el_cursor.h = el->el_term.t_size.h;
- }
-}
-
-
-/* term_deletechars():
- * Delete num characters
- */
-protected void
-term_deletechars(EditLine *el, int num)
-{
- if (num <= 0)
- return;
-
- if (!EL_CAN_DELETE) {
-#ifdef DEBUG_EDIT
- (void) fprintf(el->el_errfile, " ERROR: cannot delete \n");
-#endif /* DEBUG_EDIT */
- return;
- }
- if (num > el->el_term.t_size.h) {
-#ifdef DEBUG_SCREEN
- (void) fprintf(el->el_errfile,
- "term_deletechars: num is riduculous: %d\r\n", num);
-#endif /* DEBUG_SCREEN */
- return;
- }
- if (GoodStr(T_DC)) /* if I have multiple delete */
- if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more
- * expen. */
- (void) tputs(tgoto(Str(T_DC), num, num),
- num, term__putc);
- return;
- }
- if (GoodStr(T_dm)) /* if I have delete mode */
- (void) tputs(Str(T_dm), 1, term__putc);
-
- if (GoodStr(T_dc)) /* else do one at a time */
- while (num--)
- (void) tputs(Str(T_dc), 1, term__putc);
-
- if (GoodStr(T_ed)) /* if I have delete mode */
- (void) tputs(Str(T_ed), 1, term__putc);
-}
-
-
-/* term_insertwrite():
- * Puts terminal in insert character mode or inserts num
- * characters in the line
- */
-protected void
-term_insertwrite(EditLine *el, char *cp, int num)
-{
- if (num <= 0)
- return;
- if (!EL_CAN_INSERT) {
-#ifdef DEBUG_EDIT
- (void) fprintf(el->el_errfile, " ERROR: cannot insert \n");
-#endif /* DEBUG_EDIT */
- return;
- }
- if (num > el->el_term.t_size.h) {
-#ifdef DEBUG_SCREEN
- (void) fprintf(el->el_errfile,
- "StartInsert: num is riduculous: %d\r\n", num);
-#endif /* DEBUG_SCREEN */
- return;
- }
- if (GoodStr(T_IC)) /* if I have multiple insert */
- if ((num > 1) || !GoodStr(T_ic)) {
- /* if ic would be more expensive */
- (void) tputs(tgoto(Str(T_IC), num, num),
- num, term__putc);
- term_overwrite(el, cp, num);
- /* this updates el_cursor.h */
- return;
- }
- if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */
- (void) tputs(Str(T_im), 1, term__putc);
-
- el->el_cursor.h += num;
- do
- term__putc(*cp++);
- while (--num);
-
- if (GoodStr(T_ip)) /* have to make num chars insert */
- (void) tputs(Str(T_ip), 1, term__putc);
-
- (void) tputs(Str(T_ei), 1, term__putc);
- return;
- }
- do {
- if (GoodStr(T_ic)) /* have to make num chars insert */
- (void) tputs(Str(T_ic), 1, term__putc);
- /* insert a char */
-
- term__putc(*cp++);
-
- el->el_cursor.h++;
-
- if (GoodStr(T_ip)) /* have to make num chars insert */
- (void) tputs(Str(T_ip), 1, term__putc);
- /* pad the inserted char */
-
- } while (--num);
-}
-
-
-/* term_clear_EOL():
- * clear to end of line. There are num characters to clear
- */
-protected void
-term_clear_EOL(EditLine *el, int num)
-{
- int i;
-
- if (EL_CAN_CEOL && GoodStr(T_ce))
- (void) tputs(Str(T_ce), 1, term__putc);
- else {
- for (i = 0; i < num; i++)
- term__putc(' ');
- el->el_cursor.h += num; /* have written num spaces */
- }
-}
-
-
-/* term_clear_screen():
- * Clear the screen
- */
-protected void
-term_clear_screen(EditLine *el)
-{ /* clear the whole screen and home */
-
- if (GoodStr(T_cl))
- /* send the clear screen code */
- (void) tputs(Str(T_cl), Val(T_li), term__putc);
- else if (GoodStr(T_ho) && GoodStr(T_cd)) {
- (void) tputs(Str(T_ho), Val(T_li), term__putc); /* home */
- /* clear to bottom of screen */
- (void) tputs(Str(T_cd), Val(T_li), term__putc);
- } else {
- term__putc('\r');
- term__putc('\n');
- }
-}
-
-
-/* term_beep():
- * Beep the way the terminal wants us
- */
-protected void
-term_beep(EditLine *el)
-{
- if (GoodStr(T_bl))
- /* what termcap says we should use */
- (void) tputs(Str(T_bl), 1, term__putc);
- else
- term__putc('\007'); /* an ASCII bell; ^G */
-}
-
-
-#ifdef notdef
-/* term_clear_to_bottom():
- * Clear to the bottom of the screen
- */
-protected void
-term_clear_to_bottom(EditLine *el)
-{
- if (GoodStr(T_cd))
- (void) tputs(Str(T_cd), Val(T_li), term__putc);
- else if (GoodStr(T_ce))
- (void) tputs(Str(T_ce), Val(T_li), term__putc);
-}
-#endif
-
-
-/* term_set():
- * Read in the terminal capabilities from the requested terminal
- */
-protected int
-term_set(EditLine *el, const char *term)
-{
- int i;
- char buf[TC_BUFSIZE];
- char *area;
- const struct termcapstr *t;
- sigset_t oset, nset;
- int lins, cols;
-
- (void) sigemptyset(&nset);
- (void) sigaddset(&nset, SIGWINCH);
- (void) sigprocmask(SIG_BLOCK, &nset, &oset);
-
- area = buf;
-
-
- if (term == NULL)
- term = getenv("TERM");
-
- if (!term || !term[0])
- term = "dumb";
-
- if (strcmp(term, "emacs") == 0)
- el->el_flags |= EDIT_DISABLED;
-
- memset(el->el_term.t_cap, 0, TC_BUFSIZE);
-
- i = tgetent(el->el_term.t_cap, term);
-
- if (i <= 0) {
- if (i == -1)
- (void) fprintf(el->el_errfile,
- "Cannot read termcap database;\n");
- else if (i == 0)
- (void) fprintf(el->el_errfile,
- "No entry for terminal type \"%s\";\n", term);
- (void) fprintf(el->el_errfile,
- "using dumb terminal settings.\n");
- Val(T_co) = 80; /* do a dumb terminal */
- Val(T_pt) = Val(T_km) = Val(T_li) = 0;
- Val(T_xt) = Val(T_MT);
- for (t = tstr; t->name != NULL; t++)
- term_alloc(el, t, NULL);
- } else {
- /* auto/magic margins */
- Val(T_am) = tgetflag("am");
- Val(T_xn) = tgetflag("xn");
- /* Can we tab */
- Val(T_pt) = tgetflag("pt");
- Val(T_xt) = tgetflag("xt");
- /* do we have a meta? */
- Val(T_km) = tgetflag("km");
- Val(T_MT) = tgetflag("MT");
- /* Get the size */
- Val(T_co) = tgetnum("co");
- Val(T_li) = tgetnum("li");
- for (t = tstr; t->name != NULL; t++)
- term_alloc(el, t, tgetstr((char *)t->name, &area));
- }
-
- if (Val(T_co) < 2)
- Val(T_co) = 80; /* just in case */
- if (Val(T_li) < 1)
- Val(T_li) = 24;
-
- el->el_term.t_size.v = Val(T_co);
- el->el_term.t_size.h = Val(T_li);
-
- term_setflags(el);
-
- /* get the correct window size */
- (void) term_get_size(el, &lins, &cols);
- if (term_change_size(el, lins, cols) == -1)
- return (-1);
- (void) sigprocmask(SIG_SETMASK, &oset, NULL);
- term_bind_arrow(el);
- return (i <= 0 ? -1 : 0);
-}
-
-
-/* term_get_size():
- * Return the new window size in lines and cols, and
- * true if the size was changed.
- */
-protected int
-term_get_size(EditLine *el, int *lins, int *cols)
-{
-
- *cols = Val(T_co);
- *lins = Val(T_li);
-
-#ifdef TIOCGWINSZ
- {
- struct winsize ws;
- if (ioctl(el->el_infd, TIOCGWINSZ, (ioctl_t) & ws) != -1) {
- if (ws.ws_col)
- *cols = ws.ws_col;
- if (ws.ws_row)
- *lins = ws.ws_row;
- }
- }
-#endif
-#ifdef TIOCGSIZE
- {
- struct ttysize ts;
- if (ioctl(el->el_infd, TIOCGSIZE, (ioctl_t) & ts) != -1) {
- if (ts.ts_cols)
- *cols = ts.ts_cols;
- if (ts.ts_lines)
- *lins = ts.ts_lines;
- }
- }
-#endif
- return (Val(T_co) != *cols || Val(T_li) != *lins);
-}
-
-
-/* term_change_size():
- * Change the size of the terminal
- */
-protected int
-term_change_size(EditLine *el, int lins, int cols)
-{
- /*
- * Just in case
- */
- Val(T_co) = (cols < 2) ? 80 : cols;
- Val(T_li) = (lins < 1) ? 24 : lins;
-
- /* re-make display buffers */
- if (term_rebuffer_display(el) == -1)
- return (-1);
- re_clear_display(el);
- return (0);
-}
-
-
-/* term_init_arrow():
- * Initialize the arrow key bindings from termcap
- */
-private void
-term_init_arrow(EditLine *el)
-{
- fkey_t *arrow = el->el_term.t_fkey;
-
- arrow[A_K_DN].name = "down";
- arrow[A_K_DN].key = T_kd;
- arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY;
- arrow[A_K_DN].type = XK_CMD;
-
- arrow[A_K_UP].name = "up";
- arrow[A_K_UP].key = T_ku;
- arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY;
- arrow[A_K_UP].type = XK_CMD;
-
- arrow[A_K_LT].name = "left";
- arrow[A_K_LT].key = T_kl;
- arrow[A_K_LT].fun.cmd = ED_PREV_CHAR;
- arrow[A_K_LT].type = XK_CMD;
-
- arrow[A_K_RT].name = "right";
- arrow[A_K_RT].key = T_kr;
- arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR;
- arrow[A_K_RT].type = XK_CMD;
-
- arrow[A_K_HO].name = "home";
- arrow[A_K_HO].key = T_kh;
- arrow[A_K_HO].fun.cmd = ED_MOVE_TO_BEG;
- arrow[A_K_HO].type = XK_CMD;
-
- arrow[A_K_EN].name = "end";
- arrow[A_K_EN].key = T_at7;
- arrow[A_K_EN].fun.cmd = ED_MOVE_TO_END;
- arrow[A_K_EN].type = XK_CMD;
-}
-
-
-/* term_reset_arrow():
- * Reset arrow key bindings
- */
-private void
-term_reset_arrow(EditLine *el)
-{
- fkey_t *arrow = el->el_term.t_fkey;
- static const char strA[] = {033, '[', 'A', '\0'};
- static const char strB[] = {033, '[', 'B', '\0'};
- static const char strC[] = {033, '[', 'C', '\0'};
- static const char strD[] = {033, '[', 'D', '\0'};
- static const char strH[] = {033, '[', 'H', '\0'};
- static const char strF[] = {033, '[', 'F', '\0'};
- static const char stOA[] = {033, 'O', 'A', '\0'};
- static const char stOB[] = {033, 'O', 'B', '\0'};
- static const char stOC[] = {033, 'O', 'C', '\0'};
- static const char stOD[] = {033, 'O', 'D', '\0'};
- static const char stOH[] = {033, 'O', 'H', '\0'};
- static const char stOF[] = {033, 'O', 'F', '\0'};
-
- key_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
- key_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
- key_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
- key_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
- key_add(el, strH, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
- key_add(el, strF, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
- key_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
- key_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
- key_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
- key_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
- key_add(el, stOH, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
- key_add(el, stOF, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
-
- if (el->el_map.type == MAP_VI) {
- key_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type);
- key_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type);
- key_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type);
- key_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type);
- key_add(el, &strH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type);
- key_add(el, &strF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type);
- key_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type);
- key_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type);
- key_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type);
- key_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type);
- key_add(el, &stOH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type);
- key_add(el, &stOF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type);
- }
-}
-
-
-/* term_set_arrow():
- * Set an arrow key binding
- */
-protected int
-term_set_arrow(EditLine *el, const char *name, key_value_t *fun, int type)
-{
- fkey_t *arrow = el->el_term.t_fkey;
- int i;
-
- for (i = 0; i < A_K_NKEYS; i++)
- if (strcmp(name, arrow[i].name) == 0) {
- arrow[i].fun = *fun;
- arrow[i].type = type;
- return (0);
- }
- return (-1);
-}
-
-
-/* term_clear_arrow():
- * Clear an arrow key binding
- */
-protected int
-term_clear_arrow(EditLine *el, const char *name)
-{
- fkey_t *arrow = el->el_term.t_fkey;
- int i;
-
- for (i = 0; i < A_K_NKEYS; i++)
- if (strcmp(name, arrow[i].name) == 0) {
- arrow[i].type = XK_NOD;
- return (0);
- }
- return (-1);
-}
-
-
-/* term_print_arrow():
- * Print the arrow key bindings
- */
-protected void
-term_print_arrow(EditLine *el, const char *name)
-{
- int i;
- fkey_t *arrow = el->el_term.t_fkey;
-
- for (i = 0; i < A_K_NKEYS; i++)
- if (*name == '\0' || strcmp(name, arrow[i].name) == 0)
- if (arrow[i].type != XK_NOD)
- key_kprint(el, arrow[i].name, &arrow[i].fun,
- arrow[i].type);
-}
-
-
-/* term_bind_arrow():
- * Bind the arrow keys
- */
-protected void
-term_bind_arrow(EditLine *el)
-{
- el_action_t *map;
- const el_action_t *dmap;
- int i, j;
- char *p;
- fkey_t *arrow = el->el_term.t_fkey;
-
- /* Check if the components needed are initialized */
- if (el->el_term.t_buf == NULL || el->el_map.key == NULL)
- return;
-
- map = el->el_map.type == MAP_VI ? el->el_map.alt : el->el_map.key;
- dmap = el->el_map.type == MAP_VI ? el->el_map.vic : el->el_map.emacs;
-
- term_reset_arrow(el);
-
- for (i = 0; i < A_K_NKEYS; i++) {
- p = el->el_term.t_str[arrow[i].key];
- if (p && *p) {
- j = (unsigned char) *p;
- /*
- * Assign the arrow keys only if:
- *
- * 1. They are multi-character arrow keys and the user
- * has not re-assigned the leading character, or
- * has re-assigned the leading character to be
- * ED_SEQUENCE_LEAD_IN
- * 2. They are single arrow keys pointing to an
- * unassigned key.
- */
- if (arrow[i].type == XK_NOD)
- key_clear(el, map, p);
- else {
- if (p[1] && (dmap[j] == map[j] ||
- map[j] == ED_SEQUENCE_LEAD_IN)) {
- key_add(el, p, &arrow[i].fun,
- arrow[i].type);
- map[j] = ED_SEQUENCE_LEAD_IN;
- } else if (map[j] == ED_UNASSIGNED) {
- key_clear(el, map, p);
- if (arrow[i].type == XK_CMD)
- map[j] = arrow[i].fun.cmd;
- else
- key_add(el, p, &arrow[i].fun,
- arrow[i].type);
- }
- }
- }
- }
-}
-
-
-/* term__putc():
- * Add a character
- */
-protected int
-term__putc(int c)
-{
-
- return (fputc(c, term_outfile));
-}
-
-
-/* term__flush():
- * Flush output
- */
-protected void
-term__flush(void)
-{
-
- (void) fflush(term_outfile);
-}
-
-
-/* term_telltc():
- * Print the current termcap characteristics
- */
-protected int
-/*ARGSUSED*/
-term_telltc(EditLine *el, int argc, const char **argv)
-{
- const struct termcapstr *t;
- char **ts;
- char upbuf[EL_BUFSIZ];
-
- (void) fprintf(el->el_outfile, "\n\tYour terminal has the\n");
- (void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n");
- (void) fprintf(el->el_outfile, "\tIt has %d columns and %d lines\n",
- Val(T_co), Val(T_li));
- (void) fprintf(el->el_outfile,
- "\tIt has %s meta key\n", EL_HAS_META ? "a" : "no");
- (void) fprintf(el->el_outfile,
- "\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not ");
- (void) fprintf(el->el_outfile, "\tIt %s automatic margins\n",
- EL_HAS_AUTO_MARGINS ? "has" : "does not have");
- if (EL_HAS_AUTO_MARGINS)
- (void) fprintf(el->el_outfile, "\tIt %s magic margins\n",
- EL_HAS_MAGIC_MARGINS ? "has" : "does not have");
-
- for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++)
- (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n",
- t->long_name,
- t->name, *ts && **ts ?
- key__decode_str(*ts, upbuf, "") : "(empty)");
- (void) fputc('\n', el->el_outfile);
- return (0);
-}
-
-
-/* term_settc():
- * Change the current terminal characteristics
- */
-protected int
-/*ARGSUSED*/
-term_settc(EditLine *el, int argc, const char **argv)
-{
- const struct termcapstr *ts;
- const struct termcapval *tv;
- const char *what, *how;
-
- if (argv == NULL || argv[1] == NULL || argv[2] == NULL)
- return (-1);
-
- what = argv[1];
- how = argv[2];
-
- /*
- * Do the strings first
- */
- for (ts = tstr; ts->name != NULL; ts++)
- if (strcmp(ts->name, what) == 0)
- break;
-
- if (ts->name != NULL) {
- term_alloc(el, ts, how);
- term_setflags(el);
- return (0);
- }
- /*
- * Do the numeric ones second
- */
- for (tv = tval; tv->name != NULL; tv++)
- if (strcmp(tv->name, what) == 0)
- break;
-
- if (tv->name != NULL) {
- if (tv == &tval[T_pt] || tv == &tval[T_km] ||
- tv == &tval[T_am] || tv == &tval[T_xn]) {
- if (strcmp(how, "yes") == 0)
- el->el_term.t_val[tv - tval] = 1;
- else if (strcmp(how, "no") == 0)
- el->el_term.t_val[tv - tval] = 0;
- else {
- (void) fprintf(el->el_errfile,
- "settc: Bad value `%s'.\n", how);
- return (-1);
- }
- term_setflags(el);
- if (term_change_size(el, Val(T_li), Val(T_co)) == -1)
- return (-1);
- return (0);
- } else {
- long i;
- char *ep;
-
- i = strtol(how, &ep, 10);
- if (*ep != '\0') {
- (void) fprintf(el->el_errfile,
- "settc: Bad value `%s'.\n", how);
- return (-1);
- }
- el->el_term.t_val[tv - tval] = (int) i;
- el->el_term.t_size.v = Val(T_co);
- el->el_term.t_size.h = Val(T_li);
- if (tv == &tval[T_co] || tv == &tval[T_li])
- if (term_change_size(el, Val(T_li), Val(T_co))
- == -1)
- return (-1);
- return (0);
- }
- }
- return (-1);
-}
-
-
-/* term_echotc():
- * Print the termcap string out with variable substitution
- */
-protected int
-/*ARGSUSED*/
-term_echotc(EditLine *el, int argc, const char **argv)
-{
- char *cap, *scap, *ep;
- int arg_need, arg_cols, arg_rows;
- int verbose = 0, silent = 0;
- char *area;
- static const char fmts[] = "%s\n", fmtd[] = "%d\n";
- const struct termcapstr *t;
- char buf[TC_BUFSIZE];
- long i;
-
- area = buf;
-
- if (argv == NULL || argv[1] == NULL)
- return (-1);
- argv++;
-
- if (argv[0][0] == '-') {
- switch (argv[0][1]) {
- case 'v':
- verbose = 1;
- break;
- case 's':
- silent = 1;
- break;
- default:
- /* stderror(ERR_NAME | ERR_TCUSAGE); */
- break;
- }
- argv++;
- }
- if (!*argv || *argv[0] == '\0')
- return (0);
- if (strcmp(*argv, "tabs") == 0) {
- (void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no");
- return (0);
- } else if (strcmp(*argv, "meta") == 0) {
- (void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no");
- return (0);
- } else if (strcmp(*argv, "xn") == 0) {
- (void) fprintf(el->el_outfile, fmts, EL_HAS_MAGIC_MARGINS ?
- "yes" : "no");
- return (0);
- } else if (strcmp(*argv, "am") == 0) {
- (void) fprintf(el->el_outfile, fmts, EL_HAS_AUTO_MARGINS ?
- "yes" : "no");
- return (0);
- } else if (strcmp(*argv, "baud") == 0) {
-#ifdef notdef
- int i;
-
- for (i = 0; baud_rate[i].b_name != NULL; i++)
- if (el->el_tty.t_speed == baud_rate[i].b_rate) {
- (void) fprintf(el->el_outfile, fmts,
- baud_rate[i].b_name);
- return (0);
- }
- (void) fprintf(el->el_outfile, fmtd, 0);
-#else
- (void) fprintf(el->el_outfile, fmtd, (int) el->el_tty.t_speed);
-#endif
- return (0);
- } else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) {
- (void) fprintf(el->el_outfile, fmtd, Val(T_li));
- return (0);
- } else if (strcmp(*argv, "cols") == 0) {
- (void) fprintf(el->el_outfile, fmtd, Val(T_co));
- return (0);
- }
- /*
- * Try to use our local definition first
- */
- scap = NULL;
- for (t = tstr; t->name != NULL; t++)
- if (strcmp(t->name, *argv) == 0) {
- scap = el->el_term.t_str[t - tstr];
- break;
- }
- if (t->name == NULL)
- scap = tgetstr((char *)argv, &area);
- if (!scap || scap[0] == '\0') {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Termcap parameter `%s' not found.\n",
- *argv);
- return (-1);
- }
- /*
- * Count home many values we need for this capability.
- */
- for (cap = scap, arg_need = 0; *cap; cap++)
- if (*cap == '%')
- switch (*++cap) {
- case 'd':
- case '2':
- case '3':
- case '.':
- case '+':
- arg_need++;
- break;
- case '%':
- case '>':
- case 'i':
- case 'r':
- case 'n':
- case 'B':
- case 'D':
- break;
- default:
- /*
- * hpux has lot's of them...
- */
- if (verbose)
- (void) fprintf(el->el_errfile,
- "echotc: Warning: unknown termcap %% `%c'.\n",
- *cap);
- /* This is bad, but I won't complain */
- break;
- }
-
- switch (arg_need) {
- case 0:
- argv++;
- if (*argv && *argv[0]) {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Warning: Extra argument `%s'.\n",
- *argv);
- return (-1);
- }
- (void) tputs(scap, 1, term__putc);
- break;
- case 1:
- argv++;
- if (!*argv || *argv[0] == '\0') {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Warning: Missing argument.\n");
- return (-1);
- }
- arg_cols = 0;
- i = strtol(*argv, &ep, 10);
- if (*ep != '\0' || i < 0) {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Bad value `%s' for rows.\n",
- *argv);
- return (-1);
- }
- arg_rows = (int) i;
- argv++;
- if (*argv && *argv[0]) {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Warning: Extra argument `%s'.\n",
- *argv);
- return (-1);
- }
- (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc);
- break;
- default:
- /* This is wrong, but I will ignore it... */
- if (verbose)
- (void) fprintf(el->el_errfile,
- "echotc: Warning: Too many required arguments (%d).\n",
- arg_need);
- /* FALLTHROUGH */
- case 2:
- argv++;
- if (!*argv || *argv[0] == '\0') {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Warning: Missing argument.\n");
- return (-1);
- }
- i = strtol(*argv, &ep, 10);
- if (*ep != '\0' || i < 0) {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Bad value `%s' for cols.\n",
- *argv);
- return (-1);
- }
- arg_cols = (int) i;
- argv++;
- if (!*argv || *argv[0] == '\0') {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Warning: Missing argument.\n");
- return (-1);
- }
- i = strtol(*argv, &ep, 10);
- if (*ep != '\0' || i < 0) {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Bad value `%s' for rows.\n",
- *argv);
- return (-1);
- }
- arg_rows = (int) i;
- if (*ep != '\0') {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Bad value `%s'.\n", *argv);
- return (-1);
- }
- argv++;
- if (*argv && *argv[0]) {
- if (!silent)
- (void) fprintf(el->el_errfile,
- "echotc: Warning: Extra argument `%s'.\n",
- *argv);
- return (-1);
- }
- (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows,
- term__putc);
- break;
- }
- return (0);
-}
diff --git a/main/editline/term.h b/main/editline/term.h
deleted file mode 100644
index 47e08e84b..000000000
--- a/main/editline/term.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* $NetBSD: term.h,v 1.13 2002/03/18 16:01:00 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)term.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.term.h: Termcap header
- */
-#ifndef _h_el_term
-#define _h_el_term
-
-#include "histedit.h"
-
-typedef struct { /* Symbolic function key bindings */
- const char *name; /* name of the key */
- int key; /* Index in termcap table */
- key_value_t fun; /* Function bound to it */
- int type; /* Type of function */
-} fkey_t;
-
-typedef struct {
- coord_t t_size; /* # lines and cols */
- int t_flags;
-#define TERM_CAN_INSERT 0x001 /* Has insert cap */
-#define TERM_CAN_DELETE 0x002 /* Has delete cap */
-#define TERM_CAN_CEOL 0x004 /* Has CEOL cap */
-#define TERM_CAN_TAB 0x008 /* Can use tabs */
-#define TERM_CAN_ME 0x010 /* Can turn all attrs. */
-#define TERM_CAN_UP 0x020 /* Can move up */
-#define TERM_HAS_META 0x040 /* Has a meta key */
-#define TERM_HAS_AUTO_MARGINS 0x080 /* Has auto margins */
-#define TERM_HAS_MAGIC_MARGINS 0x100 /* Has magic margins */
- char *t_buf; /* Termcap buffer */
- int t_loc; /* location used */
- char **t_str; /* termcap strings */
- int *t_val; /* termcap values */
- char *t_cap; /* Termcap buffer */
- fkey_t *t_fkey; /* Array of keys */
-} el_term_t;
-
-/*
- * fKey indexes
- */
-#define A_K_DN 0
-#define A_K_UP 1
-#define A_K_LT 2
-#define A_K_RT 3
-#define A_K_HO 4
-#define A_K_EN 5
-#define A_K_NKEYS 6
-
-protected void term_move_to_line(EditLine *, int);
-protected void term_move_to_char(EditLine *, int);
-protected void term_clear_EOL(EditLine *, int);
-protected void term_overwrite(EditLine *, const char *, int);
-protected void term_insertwrite(EditLine *, char *, int);
-protected void term_deletechars(EditLine *, int);
-protected void term_clear_screen(EditLine *);
-protected void term_beep(EditLine *);
-protected int term_change_size(EditLine *, int, int);
-protected int term_get_size(EditLine *, int *, int *);
-protected int term_init(EditLine *);
-protected void term_bind_arrow(EditLine *);
-protected void term_print_arrow(EditLine *, const char *);
-protected int term_clear_arrow(EditLine *, const char *);
-protected int term_set_arrow(EditLine *, const char *, key_value_t *, int);
-protected void term_end(EditLine *);
-protected int term_set(EditLine *, const char *);
-protected int term_settc(EditLine *, int, const char **);
-protected int term_telltc(EditLine *, int, const char **);
-protected int term_echotc(EditLine *, int, const char **);
-protected int term__putc(int);
-protected void term__flush(void);
-
-/*
- * Easy access macros
- */
-#define EL_FLAGS (el)->el_term.t_flags
-
-#define EL_CAN_INSERT (EL_FLAGS & TERM_CAN_INSERT)
-#define EL_CAN_DELETE (EL_FLAGS & TERM_CAN_DELETE)
-#define EL_CAN_CEOL (EL_FLAGS & TERM_CAN_CEOL)
-#define EL_CAN_TAB (EL_FLAGS & TERM_CAN_TAB)
-#define EL_CAN_ME (EL_FLAGS & TERM_CAN_ME)
-#define EL_HAS_META (EL_FLAGS & TERM_HAS_META)
-#define EL_HAS_AUTO_MARGINS (EL_FLAGS & TERM_HAS_AUTO_MARGINS)
-#define EL_HAS_MAGIC_MARGINS (EL_FLAGS & TERM_HAS_MAGIC_MARGINS)
-
-#endif /* _h_el_term */
diff --git a/main/editline/tokenizer.c b/main/editline/tokenizer.c
deleted file mode 100644
index f0de39bc9..000000000
--- a/main/editline/tokenizer.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/* $NetBSD: tokenizer.c,v 1.10 2002/03/18 16:01:00 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: tokenizer.c,v 1.10 2002/03/18 16:01:00 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * tokenize.c: Bourne shell like tokenizer
- */
-#include <string.h>
-#include <stdlib.h>
-#include "tokenizer.h"
-
-typedef enum {
- Q_none, Q_single, Q_double, Q_one, Q_doubleone
-} quote_t;
-
-#define IFS "\t \n"
-
-#define TOK_KEEP 1
-#define TOK_EAT 2
-
-#define WINCR 20
-#define AINCR 10
-
-#define tok_malloc(a) malloc(a)
-#define tok_free(a) free(a)
-#define tok_realloc(a, b) realloc(a, b)
-
-
-struct tokenizer {
- char *ifs; /* In field separator */
- int argc, amax; /* Current and maximum number of args */
- char **argv; /* Argument list */
- char *wptr, *wmax; /* Space and limit on the word buffer */
- char *wstart; /* Beginning of next word */
- char *wspace; /* Space of word buffer */
- quote_t quote; /* Quoting state */
- int flags; /* flags; */
-};
-
-
-private void tok_finish(Tokenizer *);
-
-
-/* tok_finish():
- * Finish a word in the tokenizer.
- */
-private void
-tok_finish(Tokenizer *tok)
-{
-
- *tok->wptr = '\0';
- if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) {
- tok->argv[tok->argc++] = tok->wstart;
- tok->argv[tok->argc] = NULL;
- tok->wstart = ++tok->wptr;
- }
- tok->flags &= ~TOK_KEEP;
-}
-
-
-/* tok_init():
- * Initialize the tokenizer
- */
-public Tokenizer *
-tok_init(const char *ifs)
-{
- Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer));
-
- tok->ifs = strdup(ifs ? ifs : IFS);
- tok->argc = 0;
- tok->amax = AINCR;
- tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax);
- if (tok->argv == NULL)
- return (NULL);
- tok->argv[0] = NULL;
- tok->wspace = (char *) tok_malloc(WINCR);
- if (tok->wspace == NULL)
- return (NULL);
- tok->wmax = tok->wspace + WINCR;
- tok->wstart = tok->wspace;
- tok->wptr = tok->wspace;
- tok->flags = 0;
- tok->quote = Q_none;
-
- return (tok);
-}
-
-
-/* tok_reset():
- * Reset the tokenizer
- */
-public void
-tok_reset(Tokenizer *tok)
-{
-
- tok->argc = 0;
- tok->wstart = tok->wspace;
- tok->wptr = tok->wspace;
- tok->flags = 0;
- tok->quote = Q_none;
-}
-
-
-/* tok_end():
- * Clean up
- */
-public void
-tok_end(Tokenizer *tok)
-{
-
- tok_free((ptr_t) tok->ifs);
- tok_free((ptr_t) tok->wspace);
- tok_free((ptr_t) tok->argv);
- tok_free((ptr_t) tok);
-}
-
-
-
-/* tok_line():
- * Bourne shell like tokenizing
- * Return:
- * -1: Internal error
- * 3: Quoted return
- * 2: Unmatched double quote
- * 1: Unmatched single quote
- * 0: Ok
- */
-public int
-tok_line(Tokenizer *tok, const char *line, int *argc, const char ***argv)
-{
- const char *ptr;
-
- for (;;) {
- switch (*(ptr = line++)) {
- case '\'':
- tok->flags |= TOK_KEEP;
- tok->flags &= ~TOK_EAT;
- switch (tok->quote) {
- case Q_none:
- tok->quote = Q_single; /* Enter single quote
- * mode */
- break;
-
- case Q_single: /* Exit single quote mode */
- tok->quote = Q_none;
- break;
-
- case Q_one: /* Quote this ' */
- tok->quote = Q_none;
- *tok->wptr++ = *ptr;
- break;
-
- case Q_double: /* Stay in double quote mode */
- *tok->wptr++ = *ptr;
- break;
-
- case Q_doubleone: /* Quote this ' */
- tok->quote = Q_double;
- *tok->wptr++ = *ptr;
- break;
-
- default:
- return (-1);
- }
- break;
-
- case '"':
- tok->flags &= ~TOK_EAT;
- tok->flags |= TOK_KEEP;
- switch (tok->quote) {
- case Q_none: /* Enter double quote mode */
- tok->quote = Q_double;
- break;
-
- case Q_double: /* Exit double quote mode */
- tok->quote = Q_none;
- break;
-
- case Q_one: /* Quote this " */
- tok->quote = Q_none;
- *tok->wptr++ = *ptr;
- break;
-
- case Q_single: /* Stay in single quote mode */
- *tok->wptr++ = *ptr;
- break;
-
- case Q_doubleone: /* Quote this " */
- tok->quote = Q_double;
- *tok->wptr++ = *ptr;
- break;
-
- default:
- return (-1);
- }
- break;
-
- case '\\':
- tok->flags |= TOK_KEEP;
- tok->flags &= ~TOK_EAT;
- switch (tok->quote) {
- case Q_none: /* Quote next character */
- tok->quote = Q_one;
- break;
-
- case Q_double: /* Quote next character */
- tok->quote = Q_doubleone;
- break;
-
- case Q_one: /* Quote this, restore state */
- *tok->wptr++ = *ptr;
- tok->quote = Q_none;
- break;
-
- case Q_single: /* Stay in single quote mode */
- *tok->wptr++ = *ptr;
- break;
-
- case Q_doubleone: /* Quote this \ */
- tok->quote = Q_double;
- *tok->wptr++ = *ptr;
- break;
-
- default:
- return (-1);
- }
- break;
-
- case '\n':
- tok->flags &= ~TOK_EAT;
- switch (tok->quote) {
- case Q_none:
- tok_finish(tok);
- *argv = (const char **)tok->argv;
- *argc = tok->argc;
- return (0);
-
- case Q_single:
- case Q_double:
- *tok->wptr++ = *ptr; /* Add the return */
- break;
-
- case Q_doubleone: /* Back to double, eat the '\n' */
- tok->flags |= TOK_EAT;
- tok->quote = Q_double;
- break;
-
- case Q_one: /* No quote, more eat the '\n' */
- tok->flags |= TOK_EAT;
- tok->quote = Q_none;
- break;
-
- default:
- return (0);
- }
- break;
-
- case '\0':
- switch (tok->quote) {
- case Q_none:
- /* Finish word and return */
- if (tok->flags & TOK_EAT) {
- tok->flags &= ~TOK_EAT;
- return (3);
- }
- tok_finish(tok);
- *argv = (const char **)tok->argv;
- *argc = tok->argc;
- return (0);
-
- case Q_single:
- return (1);
-
- case Q_double:
- return (2);
-
- case Q_doubleone:
- tok->quote = Q_double;
- *tok->wptr++ = *ptr;
- break;
-
- case Q_one:
- tok->quote = Q_none;
- *tok->wptr++ = *ptr;
- break;
-
- default:
- return (-1);
- }
- break;
-
- default:
- tok->flags &= ~TOK_EAT;
- switch (tok->quote) {
- case Q_none:
- if (strchr(tok->ifs, *ptr) != NULL)
- tok_finish(tok);
- else
- *tok->wptr++ = *ptr;
- break;
-
- case Q_single:
- case Q_double:
- *tok->wptr++ = *ptr;
- break;
-
-
- case Q_doubleone:
- *tok->wptr++ = '\\';
- tok->quote = Q_double;
- *tok->wptr++ = *ptr;
- break;
-
- case Q_one:
- tok->quote = Q_none;
- *tok->wptr++ = *ptr;
- break;
-
- default:
- return (-1);
-
- }
- break;
- }
-
- if (tok->wptr >= tok->wmax - 4) {
- size_t size = tok->wmax - tok->wspace + WINCR;
- char *s = (char *) tok_realloc(tok->wspace, size);
- if (s == NULL)
- return (-1);
-
- if (s != tok->wspace) {
- int i;
- for (i = 0; i < tok->argc; i++) {
- tok->argv[i] =
- (tok->argv[i] - tok->wspace) + s;
- }
- tok->wptr = (tok->wptr - tok->wspace) + s;
- tok->wstart = (tok->wstart - tok->wspace) + s;
- tok->wspace = s;
- }
- tok->wmax = s + size;
- }
- if (tok->argc >= tok->amax - 4) {
- char **p;
- tok->amax += AINCR;
- p = (char **) tok_realloc(tok->argv,
- tok->amax * sizeof(char *));
- if (p == NULL)
- return (-1);
- tok->argv = p;
- }
- }
-}
diff --git a/main/editline/tokenizer.h b/main/editline/tokenizer.h
deleted file mode 100644
index 7cc7a3346..000000000
--- a/main/editline/tokenizer.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* $NetBSD: tokenizer.h,v 1.5 2002/03/18 16:01:00 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)tokenizer.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * tokenizer.h: Header file for tokenizer routines
- */
-#ifndef _h_tokenizer
-#define _h_tokenizer
-
-typedef struct tokenizer Tokenizer;
-
-Tokenizer *tok_init(const char *);
-void tok_reset(Tokenizer *);
-void tok_end(Tokenizer *);
-int tok_line(Tokenizer *, const char *, int *, const char ***);
-
-#endif /* _h_tokenizer */
diff --git a/main/editline/tty.c b/main/editline/tty.c
deleted file mode 100644
index 256cf780b..000000000
--- a/main/editline/tty.c
+++ /dev/null
@@ -1,1182 +0,0 @@
-/* $NetBSD: tty.c,v 1.16 2002/03/18 16:01:01 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: tty.c,v 1.16 2002/03/18 16:01:01 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * tty.c: tty interface stuff
- */
-#include "tty.h"
-#include "el.h"
-
-typedef struct ttymodes_t {
- const char *m_name;
- u_int m_value;
- int m_type;
-} ttymodes_t;
-
-typedef struct ttymap_t {
- int nch, och; /* Internal and termio rep of chars */
- el_action_t bind[3]; /* emacs, vi, and vi-cmd */
-} ttymap_t;
-
-
-private const ttyperm_t ttyperm = {
- {
- {"iflag:", ICRNL, (INLCR | IGNCR)},
- {"oflag:", (OPOST | ONLCR), ONLRET},
- {"cflag:", 0, 0},
- {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
- (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
- {"chars:", 0, 0},
- },
- {
- {"iflag:", (INLCR | ICRNL), IGNCR},
- {"oflag:", (OPOST | ONLCR), ONLRET},
- {"cflag:", 0, 0},
- {"lflag:", ISIG,
- (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
- {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
- C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
- C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
- },
- {
- {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
- {"oflag:", 0, 0},
- {"cflag:", 0, 0},
- {"lflag:", 0, ISIG | IEXTEN},
- {"chars:", 0, 0},
- }
-};
-
-private const ttychar_t ttychar = {
- {
- CINTR, CQUIT, CERASE, CKILL,
- CEOF, CEOL, CEOL2, CSWTCH,
- CDSWTCH, CERASE2, CSTART, CSTOP,
- CWERASE, CSUSP, CDSUSP, CREPRINT,
- CDISCARD, CLNEXT, CSTATUS, CPAGE,
- CPGOFF, CKILL2, CBRK, CMIN,
- CTIME
- },
- {
- CINTR, CQUIT, CERASE, CKILL,
- _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
- _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
- _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
- CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
- _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
- 0
- },
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0
- }
-};
-
-private const ttymap_t tty_map[] = {
-#ifdef VERASE
- {C_ERASE, VERASE,
- {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
-#endif /* VERASE */
-#ifdef VERASE2
- {C_ERASE2, VERASE2,
- {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
-#endif /* VERASE2 */
-#ifdef VKILL
- {C_KILL, VKILL,
- {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
-#endif /* VKILL */
-#ifdef VKILL2
- {C_KILL2, VKILL2,
- {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
-#endif /* VKILL2 */
-#ifdef VEOF
- {C_EOF, VEOF,
- {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
-#endif /* VEOF */
-#ifdef VWERASE
- {C_WERASE, VWERASE,
- {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
-#endif /* VWERASE */
-#ifdef VREPRINT
- {C_REPRINT, VREPRINT,
- {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
-#endif /* VREPRINT */
-#ifdef VLNEXT
- {C_LNEXT, VLNEXT,
- {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
-#endif /* VLNEXT */
- {-1, -1,
- {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
-};
-
-private const ttymodes_t ttymodes[] = {
-#ifdef IGNBRK
- {"ignbrk", IGNBRK, MD_INP},
-#endif /* IGNBRK */
-#ifdef BRKINT
- {"brkint", BRKINT, MD_INP},
-#endif /* BRKINT */
-#ifdef IGNPAR
- {"ignpar", IGNPAR, MD_INP},
-#endif /* IGNPAR */
-#ifdef PARMRK
- {"parmrk", PARMRK, MD_INP},
-#endif /* PARMRK */
-#ifdef INPCK
- {"inpck", INPCK, MD_INP},
-#endif /* INPCK */
-#ifdef ISTRIP
- {"istrip", ISTRIP, MD_INP},
-#endif /* ISTRIP */
-#ifdef INLCR
- {"inlcr", INLCR, MD_INP},
-#endif /* INLCR */
-#ifdef IGNCR
- {"igncr", IGNCR, MD_INP},
-#endif /* IGNCR */
-#ifdef ICRNL
- {"icrnl", ICRNL, MD_INP},
-#endif /* ICRNL */
-#ifdef IUCLC
- {"iuclc", IUCLC, MD_INP},
-#endif /* IUCLC */
-#ifdef IXON
- {"ixon", IXON, MD_INP},
-#endif /* IXON */
-#ifdef IXANY
- {"ixany", IXANY, MD_INP},
-#endif /* IXANY */
-#ifdef IXOFF
- {"ixoff", IXOFF, MD_INP},
-#endif /* IXOFF */
-#ifdef IMAXBEL
- {"imaxbel", IMAXBEL, MD_INP},
-#endif /* IMAXBEL */
-
-#ifdef OPOST
- {"opost", OPOST, MD_OUT},
-#endif /* OPOST */
-#ifdef OLCUC
- {"olcuc", OLCUC, MD_OUT},
-#endif /* OLCUC */
-#ifdef ONLCR
- {"onlcr", ONLCR, MD_OUT},
-#endif /* ONLCR */
-#ifdef OCRNL
- {"ocrnl", OCRNL, MD_OUT},
-#endif /* OCRNL */
-#ifdef ONOCR
- {"onocr", ONOCR, MD_OUT},
-#endif /* ONOCR */
-#ifdef ONOEOT
- {"onoeot", ONOEOT, MD_OUT},
-#endif /* ONOEOT */
-#ifdef ONLRET
- {"onlret", ONLRET, MD_OUT},
-#endif /* ONLRET */
-#ifdef OFILL
- {"ofill", OFILL, MD_OUT},
-#endif /* OFILL */
-#ifdef OFDEL
- {"ofdel", OFDEL, MD_OUT},
-#endif /* OFDEL */
-#ifdef NLDLY
- {"nldly", NLDLY, MD_OUT},
-#endif /* NLDLY */
-#ifdef CRDLY
- {"crdly", CRDLY, MD_OUT},
-#endif /* CRDLY */
-#ifdef TABDLY
- {"tabdly", TABDLY, MD_OUT},
-#endif /* TABDLY */
-#ifdef XTABS
- {"xtabs", XTABS, MD_OUT},
-#endif /* XTABS */
-#ifdef BSDLY
- {"bsdly", BSDLY, MD_OUT},
-#endif /* BSDLY */
-#ifdef VTDLY
- {"vtdly", VTDLY, MD_OUT},
-#endif /* VTDLY */
-#ifdef FFDLY
- {"ffdly", FFDLY, MD_OUT},
-#endif /* FFDLY */
-#ifdef PAGEOUT
- {"pageout", PAGEOUT, MD_OUT},
-#endif /* PAGEOUT */
-#ifdef WRAP
- {"wrap", WRAP, MD_OUT},
-#endif /* WRAP */
-
-#ifdef CIGNORE
- {"cignore", CIGNORE, MD_CTL},
-#endif /* CBAUD */
-#ifdef CBAUD
- {"cbaud", CBAUD, MD_CTL},
-#endif /* CBAUD */
-#ifdef CSTOPB
- {"cstopb", CSTOPB, MD_CTL},
-#endif /* CSTOPB */
-#ifdef CREAD
- {"cread", CREAD, MD_CTL},
-#endif /* CREAD */
-#ifdef PARENB
- {"parenb", PARENB, MD_CTL},
-#endif /* PARENB */
-#ifdef PARODD
- {"parodd", PARODD, MD_CTL},
-#endif /* PARODD */
-#ifdef HUPCL
- {"hupcl", HUPCL, MD_CTL},
-#endif /* HUPCL */
-#ifdef CLOCAL
- {"clocal", CLOCAL, MD_CTL},
-#endif /* CLOCAL */
-#ifdef LOBLK
- {"loblk", LOBLK, MD_CTL},
-#endif /* LOBLK */
-#ifdef CIBAUD
- {"cibaud", CIBAUD, MD_CTL},
-#endif /* CIBAUD */
-#ifdef CRTSCTS
-#ifdef CCTS_OFLOW
- {"ccts_oflow", CCTS_OFLOW, MD_CTL},
-#else
- {"crtscts", CRTSCTS, MD_CTL},
-#endif /* CCTS_OFLOW */
-#endif /* CRTSCTS */
-#ifdef CRTS_IFLOW
- {"crts_iflow", CRTS_IFLOW, MD_CTL},
-#endif /* CRTS_IFLOW */
-#ifdef CDTRCTS
- {"cdtrcts", CDTRCTS, MD_CTL},
-#endif /* CDTRCTS */
-#ifdef MDMBUF
- {"mdmbuf", MDMBUF, MD_CTL},
-#endif /* MDMBUF */
-#ifdef RCV1EN
- {"rcv1en", RCV1EN, MD_CTL},
-#endif /* RCV1EN */
-#ifdef XMT1EN
- {"xmt1en", XMT1EN, MD_CTL},
-#endif /* XMT1EN */
-
-#ifdef ISIG
- {"isig", ISIG, MD_LIN},
-#endif /* ISIG */
-#ifdef ICANON
- {"icanon", ICANON, MD_LIN},
-#endif /* ICANON */
-#ifdef XCASE
- {"xcase", XCASE, MD_LIN},
-#endif /* XCASE */
-#ifdef ECHO
- {"echo", ECHO, MD_LIN},
-#endif /* ECHO */
-#ifdef ECHOE
- {"echoe", ECHOE, MD_LIN},
-#endif /* ECHOE */
-#ifdef ECHOK
- {"echok", ECHOK, MD_LIN},
-#endif /* ECHOK */
-#ifdef ECHONL
- {"echonl", ECHONL, MD_LIN},
-#endif /* ECHONL */
-#ifdef NOFLSH
- {"noflsh", NOFLSH, MD_LIN},
-#endif /* NOFLSH */
-#ifdef TOSTOP
- {"tostop", TOSTOP, MD_LIN},
-#endif /* TOSTOP */
-#ifdef ECHOCTL
- {"echoctl", ECHOCTL, MD_LIN},
-#endif /* ECHOCTL */
-#ifdef ECHOPRT
- {"echoprt", ECHOPRT, MD_LIN},
-#endif /* ECHOPRT */
-#ifdef ECHOKE
- {"echoke", ECHOKE, MD_LIN},
-#endif /* ECHOKE */
-#ifdef DEFECHO
- {"defecho", DEFECHO, MD_LIN},
-#endif /* DEFECHO */
-#ifdef FLUSHO
- {"flusho", FLUSHO, MD_LIN},
-#endif /* FLUSHO */
-#ifdef PENDIN
- {"pendin", PENDIN, MD_LIN},
-#endif /* PENDIN */
-#ifdef IEXTEN
- {"iexten", IEXTEN, MD_LIN},
-#endif /* IEXTEN */
-#ifdef NOKERNINFO
- {"nokerninfo", NOKERNINFO, MD_LIN},
-#endif /* NOKERNINFO */
-#ifdef ALTWERASE
- {"altwerase", ALTWERASE, MD_LIN},
-#endif /* ALTWERASE */
-#ifdef EXTPROC
- {"extproc", EXTPROC, MD_LIN},
-#endif /* EXTPROC */
-
-#if defined(VINTR)
- {"intr", C_SH(C_INTR), MD_CHAR},
-#endif /* VINTR */
-#if defined(VQUIT)
- {"quit", C_SH(C_QUIT), MD_CHAR},
-#endif /* VQUIT */
-#if defined(VERASE)
- {"erase", C_SH(C_ERASE), MD_CHAR},
-#endif /* VERASE */
-#if defined(VKILL)
- {"kill", C_SH(C_KILL), MD_CHAR},
-#endif /* VKILL */
-#if defined(VEOF)
- {"eof", C_SH(C_EOF), MD_CHAR},
-#endif /* VEOF */
-#if defined(VEOL)
- {"eol", C_SH(C_EOL), MD_CHAR},
-#endif /* VEOL */
-#if defined(VEOL2)
- {"eol2", C_SH(C_EOL2), MD_CHAR},
-#endif /* VEOL2 */
-#if defined(VSWTCH)
- {"swtch", C_SH(C_SWTCH), MD_CHAR},
-#endif /* VSWTCH */
-#if defined(VDSWTCH)
- {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
-#endif /* VDSWTCH */
-#if defined(VERASE2)
- {"erase2", C_SH(C_ERASE2), MD_CHAR},
-#endif /* VERASE2 */
-#if defined(VSTART)
- {"start", C_SH(C_START), MD_CHAR},
-#endif /* VSTART */
-#if defined(VSTOP)
- {"stop", C_SH(C_STOP), MD_CHAR},
-#endif /* VSTOP */
-#if defined(VWERASE)
- {"werase", C_SH(C_WERASE), MD_CHAR},
-#endif /* VWERASE */
-#if defined(VSUSP)
- {"susp", C_SH(C_SUSP), MD_CHAR},
-#endif /* VSUSP */
-#if defined(VDSUSP)
- {"dsusp", C_SH(C_DSUSP), MD_CHAR},
-#endif /* VDSUSP */
-#if defined(VREPRINT)
- {"reprint", C_SH(C_REPRINT), MD_CHAR},
-#endif /* VREPRINT */
-#if defined(VDISCARD)
- {"discard", C_SH(C_DISCARD), MD_CHAR},
-#endif /* VDISCARD */
-#if defined(VLNEXT)
- {"lnext", C_SH(C_LNEXT), MD_CHAR},
-#endif /* VLNEXT */
-#if defined(VSTATUS)
- {"status", C_SH(C_STATUS), MD_CHAR},
-#endif /* VSTATUS */
-#if defined(VPAGE)
- {"page", C_SH(C_PAGE), MD_CHAR},
-#endif /* VPAGE */
-#if defined(VPGOFF)
- {"pgoff", C_SH(C_PGOFF), MD_CHAR},
-#endif /* VPGOFF */
-#if defined(VKILL2)
- {"kill2", C_SH(C_KILL2), MD_CHAR},
-#endif /* VKILL2 */
-#if defined(VBRK)
- {"brk", C_SH(C_BRK), MD_CHAR},
-#endif /* VBRK */
-#if defined(VMIN)
- {"min", C_SH(C_MIN), MD_CHAR},
-#endif /* VMIN */
-#if defined(VTIME)
- {"time", C_SH(C_TIME), MD_CHAR},
-#endif /* VTIME */
- {NULL, 0, -1},
-};
-
-
-
-#define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
-#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
-
-#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
-#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
-#define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
-
-private void tty__getchar(struct termios *, unsigned char *);
-private void tty__setchar(struct termios *, unsigned char *);
-private speed_t tty__getspeed(struct termios *);
-private int tty_setup(EditLine *);
-
-#define t_qu t_ts
-
-
-/* tty_setup():
- * Get the tty parameters and initialize the editing state
- */
-private int
-tty_setup(EditLine *el)
-{
- int rst = 1;
-
- if (el->el_flags & EDIT_DISABLED)
- return (0);
-
- if (tty_getty(el, &el->el_tty.t_ed) == -1) {
-#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile,
- "tty_setup: tty_getty: %s\n", strerror(errno));
-#endif /* DEBUG_TTY */
- return (-1);
- }
- el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
-
- el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
- el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
- el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
-
- el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
- el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
-
- el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
- el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
-
- el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
- el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
-
- el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
- el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
-
- /*
- * Reset the tty chars to reasonable defaults
- * If they are disabled, then enable them.
- */
- if (rst) {
- if (tty__cooked_mode(&el->el_tty.t_ts)) {
- tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
- /*
- * Don't affect CMIN and CTIME for the editor mode
- */
- for (rst = 0; rst < C_NCC - 2; rst++)
- if (el->el_tty.t_c[TS_IO][rst] !=
- el->el_tty.t_vdisable
- && el->el_tty.t_c[ED_IO][rst] !=
- el->el_tty.t_vdisable)
- el->el_tty.t_c[ED_IO][rst] =
- el->el_tty.t_c[TS_IO][rst];
- for (rst = 0; rst < C_NCC; rst++)
- if (el->el_tty.t_c[TS_IO][rst] !=
- el->el_tty.t_vdisable)
- el->el_tty.t_c[EX_IO][rst] =
- el->el_tty.t_c[TS_IO][rst];
- }
- tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
- if (tty_setty(el, &el->el_tty.t_ex) == -1) {
-#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile,
- "tty_setup: tty_setty: %s\n",
- strerror(errno));
-#endif /* DEBUG_TTY */
- return (-1);
- }
- } else
- tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
-
- el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
- el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
-
- el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
- el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
-
- el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
- el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
-
- el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
- el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
-
- tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
- tty_bind_char(el, 1);
- return (0);
-}
-
-protected int
-tty_init(EditLine *el)
-{
-
- el->el_tty.t_mode = EX_IO;
- el->el_tty.t_vdisable = _POSIX_VDISABLE;
- (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
- (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
- return (tty_setup(el));
-}
-
-
-/* tty_end():
- * Restore the tty to its original settings
- */
-protected void
-/*ARGSUSED*/
-tty_end(EditLine *el)
-{
-
- /* XXX: Maybe reset to an initial state? */
-}
-
-
-/* tty__getspeed():
- * Get the tty speed
- */
-private speed_t
-tty__getspeed(struct termios *td)
-{
- speed_t spd;
-
- if ((spd = cfgetispeed(td)) == 0)
- spd = cfgetospeed(td);
- return (spd);
-}
-
-
-/* tty__getchar():
- * Get the tty characters
- */
-private void
-tty__getchar(struct termios *td, unsigned char *s)
-{
-
-#ifdef VINTR
- s[C_INTR] = td->c_cc[VINTR];
-#endif /* VINTR */
-#ifdef VQUIT
- s[C_QUIT] = td->c_cc[VQUIT];
-#endif /* VQUIT */
-#ifdef VERASE
- s[C_ERASE] = td->c_cc[VERASE];
-#endif /* VERASE */
-#ifdef VKILL
- s[C_KILL] = td->c_cc[VKILL];
-#endif /* VKILL */
-#ifdef VEOF
- s[C_EOF] = td->c_cc[VEOF];
-#endif /* VEOF */
-#ifdef VEOL
- s[C_EOL] = td->c_cc[VEOL];
-#endif /* VEOL */
-#ifdef VEOL2
- s[C_EOL2] = td->c_cc[VEOL2];
-#endif /* VEOL2 */
-#ifdef VSWTCH
- s[C_SWTCH] = td->c_cc[VSWTCH];
-#endif /* VSWTCH */
-#ifdef VDSWTCH
- s[C_DSWTCH] = td->c_cc[VDSWTCH];
-#endif /* VDSWTCH */
-#ifdef VERASE2
- s[C_ERASE2] = td->c_cc[VERASE2];
-#endif /* VERASE2 */
-#ifdef VSTART
- s[C_START] = td->c_cc[VSTART];
-#endif /* VSTART */
-#ifdef VSTOP
- s[C_STOP] = td->c_cc[VSTOP];
-#endif /* VSTOP */
-#ifdef VWERASE
- s[C_WERASE] = td->c_cc[VWERASE];
-#endif /* VWERASE */
-#ifdef VSUSP
- s[C_SUSP] = td->c_cc[VSUSP];
-#endif /* VSUSP */
-#ifdef VDSUSP
- s[C_DSUSP] = td->c_cc[VDSUSP];
-#endif /* VDSUSP */
-#ifdef VREPRINT
- s[C_REPRINT] = td->c_cc[VREPRINT];
-#endif /* VREPRINT */
-#ifdef VDISCARD
- s[C_DISCARD] = td->c_cc[VDISCARD];
-#endif /* VDISCARD */
-#ifdef VLNEXT
- s[C_LNEXT] = td->c_cc[VLNEXT];
-#endif /* VLNEXT */
-#ifdef VSTATUS
- s[C_STATUS] = td->c_cc[VSTATUS];
-#endif /* VSTATUS */
-#ifdef VPAGE
- s[C_PAGE] = td->c_cc[VPAGE];
-#endif /* VPAGE */
-#ifdef VPGOFF
- s[C_PGOFF] = td->c_cc[VPGOFF];
-#endif /* VPGOFF */
-#ifdef VKILL2
- s[C_KILL2] = td->c_cc[VKILL2];
-#endif /* KILL2 */
-#ifdef VMIN
- s[C_MIN] = td->c_cc[VMIN];
-#endif /* VMIN */
-#ifdef VTIME
- s[C_TIME] = td->c_cc[VTIME];
-#endif /* VTIME */
-} /* tty__getchar */
-
-
-/* tty__setchar():
- * Set the tty characters
- */
-private void
-tty__setchar(struct termios *td, unsigned char *s)
-{
-
-#ifdef VINTR
- td->c_cc[VINTR] = s[C_INTR];
-#endif /* VINTR */
-#ifdef VQUIT
- td->c_cc[VQUIT] = s[C_QUIT];
-#endif /* VQUIT */
-#ifdef VERASE
- td->c_cc[VERASE] = s[C_ERASE];
-#endif /* VERASE */
-#ifdef VKILL
- td->c_cc[VKILL] = s[C_KILL];
-#endif /* VKILL */
-#ifdef VEOF
- td->c_cc[VEOF] = s[C_EOF];
-#endif /* VEOF */
-#ifdef VEOL
- td->c_cc[VEOL] = s[C_EOL];
-#endif /* VEOL */
-#ifdef VEOL2
- td->c_cc[VEOL2] = s[C_EOL2];
-#endif /* VEOL2 */
-#ifdef VSWTCH
- td->c_cc[VSWTCH] = s[C_SWTCH];
-#endif /* VSWTCH */
-#ifdef VDSWTCH
- td->c_cc[VDSWTCH] = s[C_DSWTCH];
-#endif /* VDSWTCH */
-#ifdef VERASE2
- td->c_cc[VERASE2] = s[C_ERASE2];
-#endif /* VERASE2 */
-#ifdef VSTART
- td->c_cc[VSTART] = s[C_START];
-#endif /* VSTART */
-#ifdef VSTOP
- td->c_cc[VSTOP] = s[C_STOP];
-#endif /* VSTOP */
-#ifdef VWERASE
- td->c_cc[VWERASE] = s[C_WERASE];
-#endif /* VWERASE */
-#ifdef VSUSP
- td->c_cc[VSUSP] = s[C_SUSP];
-#endif /* VSUSP */
-#ifdef VDSUSP
- td->c_cc[VDSUSP] = s[C_DSUSP];
-#endif /* VDSUSP */
-#ifdef VREPRINT
- td->c_cc[VREPRINT] = s[C_REPRINT];
-#endif /* VREPRINT */
-#ifdef VDISCARD
- td->c_cc[VDISCARD] = s[C_DISCARD];
-#endif /* VDISCARD */
-#ifdef VLNEXT
- td->c_cc[VLNEXT] = s[C_LNEXT];
-#endif /* VLNEXT */
-#ifdef VSTATUS
- td->c_cc[VSTATUS] = s[C_STATUS];
-#endif /* VSTATUS */
-#ifdef VPAGE
- td->c_cc[VPAGE] = s[C_PAGE];
-#endif /* VPAGE */
-#ifdef VPGOFF
- td->c_cc[VPGOFF] = s[C_PGOFF];
-#endif /* VPGOFF */
-#ifdef VKILL2
- td->c_cc[VKILL2] = s[C_KILL2];
-#endif /* VKILL2 */
-#ifdef VMIN
- td->c_cc[VMIN] = s[C_MIN];
-#endif /* VMIN */
-#ifdef VTIME
- td->c_cc[VTIME] = s[C_TIME];
-#endif /* VTIME */
-} /* tty__setchar */
-
-
-/* tty_bind_char():
- * Rebind the editline functions
- */
-protected void
-tty_bind_char(EditLine *el, int force)
-{
-
- unsigned char *t_n = el->el_tty.t_c[ED_IO];
- unsigned char *t_o = el->el_tty.t_ed.c_cc;
- unsigned char new[2], old[2];
- const ttymap_t *tp;
- el_action_t *map, *alt;
- const el_action_t *dmap, *dalt;
- new[1] = old[1] = '\0';
-
- map = el->el_map.key;
- alt = el->el_map.alt;
- if (el->el_map.type == MAP_VI) {
- dmap = el->el_map.vii;
- dalt = el->el_map.vic;
- } else {
- dmap = el->el_map.emacs;
- dalt = NULL;
- }
-
- for (tp = tty_map; tp->nch != -1; tp++) {
- new[0] = t_n[tp->nch];
- old[0] = t_o[tp->och];
- if (new[0] == old[0] && !force)
- continue;
- /* Put the old default binding back, and set the new binding */
- key_clear(el, map, (char *)old);
- map[old[0]] = dmap[old[0]];
- key_clear(el, map, (char *)new);
- /* MAP_VI == 1, MAP_EMACS == 0... */
- map[new[0]] = tp->bind[el->el_map.type];
- if (dalt) {
- key_clear(el, alt, (char *)old);
- alt[old[0]] = dalt[old[0]];
- key_clear(el, alt, (char *)new);
- alt[new[0]] = tp->bind[el->el_map.type + 1];
- }
- }
-}
-
-
-/* tty_rawmode():
- * Set terminal into 1 character at a time mode.
- */
-protected int
-tty_rawmode(EditLine *el)
-{
-
- if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
- return (0);
-
- if (el->el_flags & EDIT_DISABLED)
- return (0);
-
- if (tty_getty(el, &el->el_tty.t_ts) == -1) {
-#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n",
- strerror(errno));
-#endif /* DEBUG_TTY */
- return (-1);
- }
- /*
- * We always keep up with the eight bit setting and the speed of the
- * tty. But only we only believe changes that are made to cooked mode!
- */
- el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
- el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
-
- if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
- tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
- (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
- (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
- (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
- (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
- }
- if (tty__cooked_mode(&el->el_tty.t_ts)) {
- if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
- el->el_tty.t_ex.c_cflag =
- el->el_tty.t_ts.c_cflag;
- el->el_tty.t_ex.c_cflag &=
- ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
- el->el_tty.t_ex.c_cflag |=
- el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
-
- el->el_tty.t_ed.c_cflag =
- el->el_tty.t_ts.c_cflag;
- el->el_tty.t_ed.c_cflag &=
- ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
- el->el_tty.t_ed.c_cflag |=
- el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
- }
- if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
- (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
- el->el_tty.t_ex.c_lflag =
- el->el_tty.t_ts.c_lflag;
- el->el_tty.t_ex.c_lflag &=
- ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
- el->el_tty.t_ex.c_lflag |=
- el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
-
- el->el_tty.t_ed.c_lflag =
- el->el_tty.t_ts.c_lflag;
- el->el_tty.t_ed.c_lflag &=
- ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
- el->el_tty.t_ed.c_lflag |=
- el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
- }
- if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
- (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
- el->el_tty.t_ex.c_iflag =
- el->el_tty.t_ts.c_iflag;
- el->el_tty.t_ex.c_iflag &=
- ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
- el->el_tty.t_ex.c_iflag |=
- el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
-
- el->el_tty.t_ed.c_iflag =
- el->el_tty.t_ts.c_iflag;
- el->el_tty.t_ed.c_iflag &=
- ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
- el->el_tty.t_ed.c_iflag |=
- el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
- }
- if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
- (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
- el->el_tty.t_ex.c_oflag =
- el->el_tty.t_ts.c_oflag;
- el->el_tty.t_ex.c_oflag &=
- ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
- el->el_tty.t_ex.c_oflag |=
- el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
-
- el->el_tty.t_ed.c_oflag =
- el->el_tty.t_ts.c_oflag;
- el->el_tty.t_ed.c_oflag &=
- ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
- el->el_tty.t_ed.c_oflag |=
- el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
- }
- if (tty__gettabs(&el->el_tty.t_ex) == 0)
- el->el_tty.t_tabs = 0;
- else
- el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
-
- {
- int i;
-
- tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
- /*
- * Check if the user made any changes.
- * If he did, then propagate the changes to the
- * edit and execute data structures.
- */
- for (i = 0; i < C_NCC; i++)
- if (el->el_tty.t_c[TS_IO][i] !=
- el->el_tty.t_c[EX_IO][i])
- break;
-
- if (i != C_NCC) {
- /*
- * Propagate changes only to the unprotected
- * chars that have been modified just now.
- */
- for (i = 0; i < C_NCC; i++) {
- if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
- && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
- el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
- if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
- el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
- }
- tty_bind_char(el, 0);
- tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
-
- for (i = 0; i < C_NCC; i++) {
- if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
- && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
- el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
- if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
- el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
- }
- tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
- }
- }
- }
- if (tty_setty(el, &el->el_tty.t_ed) == -1) {
-#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
- strerror(errno));
-#endif /* DEBUG_TTY */
- return (-1);
- }
- el->el_tty.t_mode = ED_IO;
- return (0);
-}
-
-
-/* tty_cookedmode():
- * Set the tty back to normal mode
- */
-protected int
-tty_cookedmode(EditLine *el)
-{ /* set tty in normal setup */
-
- if (el->el_tty.t_mode == EX_IO)
- return (0);
-
- if (el->el_flags & EDIT_DISABLED)
- return (0);
-
- if (tty_setty(el, &el->el_tty.t_ex) == -1) {
-#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile,
- "tty_cookedmode: tty_setty: %s\n",
- strerror(errno));
-#endif /* DEBUG_TTY */
- return (-1);
- }
- el->el_tty.t_mode = EX_IO;
- return (0);
-}
-
-
-/* tty_quotemode():
- * Turn on quote mode
- */
-protected int
-tty_quotemode(EditLine *el)
-{
- if (el->el_tty.t_mode == QU_IO)
- return (0);
-
- el->el_tty.t_qu = el->el_tty.t_ed;
-
- el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
- el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
-
- el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
- el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
-
- el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
- el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
-
- el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
- el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
-
- if (tty_setty(el, &el->el_tty.t_qu) == -1) {
-#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
- strerror(errno));
-#endif /* DEBUG_TTY */
- return (-1);
- }
- el->el_tty.t_mode = QU_IO;
- return (0);
-}
-
-
-/* tty_noquotemode():
- * Turn off quote mode
- */
-protected int
-tty_noquotemode(EditLine *el)
-{
-
- if (el->el_tty.t_mode != QU_IO)
- return (0);
- if (tty_setty(el, &el->el_tty.t_ed) == -1) {
-#ifdef DEBUG_TTY
- (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
- strerror(errno));
-#endif /* DEBUG_TTY */
- return (-1);
- }
- el->el_tty.t_mode = ED_IO;
- return (0);
-}
-
-
-/* tty_stty():
- * Stty builtin
- */
-protected int
-/*ARGSUSED*/
-tty_stty(EditLine *el, int argc, const char **argv)
-{
- const ttymodes_t *m;
- char x;
- int aflag = 0;
- const char *s, *d;
- const char *name;
- int z = EX_IO;
-
- if (argv == NULL)
- return (-1);
- name = *argv++;
-
- while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
- switch (argv[0][1]) {
- case 'a':
- aflag++;
- argv++;
- break;
- case 'd':
- argv++;
- z = ED_IO;
- break;
- case 'x':
- argv++;
- z = EX_IO;
- break;
- case 'q':
- argv++;
- z = QU_IO;
- break;
- default:
- (void) fprintf(el->el_errfile,
- "%s: Unknown switch `%c'.\n",
- name, argv[0][1]);
- return (-1);
- }
-
- if (!argv || !*argv) {
- int i = -1;
- int len = 0, st = 0, cu;
- for (m = ttymodes; m->m_name; m++) {
- if (m->m_type != i) {
- (void) fprintf(el->el_outfile, "%s%s",
- i != -1 ? "\n" : "",
- el->el_tty.t_t[z][m->m_type].t_name);
- i = m->m_type;
- st = len =
- strlen(el->el_tty.t_t[z][m->m_type].t_name);
- }
- x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
- ? '+' : '\0';
- x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
- ? '-' : x;
-
- if (x != '\0' || aflag) {
-
- cu = strlen(m->m_name) + (x != '\0') + 1;
-
- if (len + cu >= el->el_term.t_size.h) {
- (void) fprintf(el->el_outfile, "\n%*s",
- st, "");
- len = st + cu;
- } else
- len += cu;
-
- if (x != '\0')
- (void) fprintf(el->el_outfile, "%c%s ",
- x, m->m_name);
- else
- (void) fprintf(el->el_outfile, "%s ",
- m->m_name);
- }
- }
- (void) fprintf(el->el_outfile, "\n");
- return (0);
- }
- while (argv && (s = *argv++)) {
- switch (*s) {
- case '+':
- case '-':
- x = *s++;
- break;
- default:
- x = '\0';
- break;
- }
- d = s;
- for (m = ttymodes; m->m_name; m++)
- if (strcmp(m->m_name, d) == 0)
- break;
-
- if (!m->m_name) {
- (void) fprintf(el->el_errfile,
- "%s: Invalid argument `%s'.\n", name, d);
- return (-1);
- }
- switch (x) {
- case '+':
- el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
- el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
- break;
- case '-':
- el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
- el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
- break;
- default:
- el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
- el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
- break;
- }
- }
- return (0);
-}
-
-
-#ifdef notyet
-/* tty_printchar():
- * DEbugging routine to print the tty characters
- */
-private void
-tty_printchar(EditLine *el, unsigned char *s)
-{
- ttyperm_t *m;
- int i;
-
- for (i = 0; i < C_NCC; i++) {
- for (m = el->el_tty.t_t; m->m_name; m++)
- if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
- break;
- if (m->m_name)
- (void) fprintf(el->el_errfile, "%s ^%c ",
- m->m_name, s[i] + 'A' - 1);
- if (i % 5 == 0)
- (void) fprintf(el->el_errfile, "\n");
- }
- (void) fprintf(el->el_errfile, "\n");
-}
-#endif /* notyet */
diff --git a/main/editline/tty.h b/main/editline/tty.h
deleted file mode 100644
index e9597fceb..000000000
--- a/main/editline/tty.h
+++ /dev/null
@@ -1,484 +0,0 @@
-/* $NetBSD: tty.h,v 1.9 2002/03/18 16:01:01 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)tty.h 8.1 (Berkeley) 6/4/93
- */
-
-/*
- * el.tty.h: Local terminal header
- */
-#ifndef _h_el_tty
-#define _h_el_tty
-
-#include "histedit.h"
-#include <termios.h>
-#include <unistd.h>
-
-/* Define our own since everyone gets it wrong! */
-#define CONTROL(A) ((A) & 037)
-
-/*
- * Aix compatible names
- */
-# if defined(VWERSE) && !defined(VWERASE)
-# define VWERASE VWERSE
-# endif /* VWERSE && !VWERASE */
-
-# if defined(VDISCRD) && !defined(VDISCARD)
-# define VDISCARD VDISCRD
-# endif /* VDISCRD && !VDISCARD */
-
-# if defined(VFLUSHO) && !defined(VDISCARD)
-# define VDISCARD VFLUSHO
-# endif /* VFLUSHO && VDISCARD */
-
-# if defined(VSTRT) && !defined(VSTART)
-# define VSTART VSTRT
-# endif /* VSTRT && ! VSTART */
-
-# if defined(VSTAT) && !defined(VSTATUS)
-# define VSTATUS VSTAT
-# endif /* VSTAT && ! VSTATUS */
-
-# ifndef ONLRET
-# define ONLRET 0
-# endif /* ONLRET */
-
-# ifndef TAB3
-# ifdef OXTABS
-# define TAB3 OXTABS
-# else
-# define TAB3 0
-# endif /* OXTABS */
-# endif /* !TAB3 */
-
-# if defined(OXTABS) && !defined(XTABS)
-# define XTABS OXTABS
-# endif /* OXTABS && !XTABS */
-
-# ifndef ONLCR
-# define ONLCR 0
-# endif /* ONLCR */
-
-# ifndef IEXTEN
-# define IEXTEN 0
-# endif /* IEXTEN */
-
-# ifndef ECHOCTL
-# define ECHOCTL 0
-# endif /* ECHOCTL */
-
-# ifndef PARENB
-# define PARENB 0
-# endif /* PARENB */
-
-# ifndef EXTPROC
-# define EXTPROC 0
-# endif /* EXTPROC */
-
-# ifndef FLUSHO
-# define FLUSHO 0
-# endif /* FLUSHO */
-
-
-# if defined(VDISABLE) && !defined(_POSIX_VDISABLE)
-# define _POSIX_VDISABLE VDISABLE
-# endif /* VDISABLE && ! _POSIX_VDISABLE */
-
-/*
- * Work around ISC's definition of IEXTEN which is
- * XCASE!
- */
-# ifdef ISC
-# if defined(IEXTEN) && defined(XCASE)
-# if IEXTEN == XCASE
-# undef IEXTEN
-# define IEXTEN 0
-# endif /* IEXTEN == XCASE */
-# endif /* IEXTEN && XCASE */
-# if defined(IEXTEN) && !defined(XCASE)
-# define XCASE IEXTEN
-# undef IEXTEN
-# define IEXTEN 0
-# endif /* IEXTEN && !XCASE */
-# endif /* ISC */
-
-/*
- * Work around convex weirdness where turning off IEXTEN makes us
- * lose all postprocessing!
- */
-#if defined(convex) || defined(__convex__)
-# if defined(IEXTEN) && IEXTEN != 0
-# undef IEXTEN
-# define IEXTEN 0
-# endif /* IEXTEN != 0 */
-#endif /* convex || __convex__ */
-
-/*
- * So that we don't lose job control.
- */
-#ifdef __SVR4
-# undef CSWTCH
-#endif
-
-#ifndef _POSIX_VDISABLE
-# define _POSIX_VDISABLE ((unsigned char) -1)
-#endif /* _POSIX_VDISABLE */
-
-#if !defined(CREPRINT) && defined(CRPRNT)
-# define CREPRINT CRPRNT
-#endif /* !CREPRINT && CRPRNT */
-#if !defined(CDISCARD) && defined(CFLUSH)
-# define CDISCARD CFLUSH
-#endif /* !CDISCARD && CFLUSH */
-
-#ifndef CINTR
-# define CINTR CONTROL('c')
-#endif /* CINTR */
-#ifndef CQUIT
-# define CQUIT 034 /* ^\ */
-#endif /* CQUIT */
-#ifndef CERASE
-# define CERASE 0177 /* ^? */
-#endif /* CERASE */
-#ifndef CKILL
-# define CKILL CONTROL('u')
-#endif /* CKILL */
-#ifndef CEOF
-# define CEOF CONTROL('d')
-#endif /* CEOF */
-#ifndef CEOL
-# define CEOL _POSIX_VDISABLE
-#endif /* CEOL */
-#ifndef CEOL2
-# define CEOL2 _POSIX_VDISABLE
-#endif /* CEOL2 */
-#ifndef CSWTCH
-# define CSWTCH _POSIX_VDISABLE
-#endif /* CSWTCH */
-#ifndef CDSWTCH
-# define CDSWTCH _POSIX_VDISABLE
-#endif /* CDSWTCH */
-#ifndef CERASE2
-# define CERASE2 _POSIX_VDISABLE
-#endif /* CERASE2 */
-#ifndef CSTART
-# define CSTART CONTROL('q')
-#endif /* CSTART */
-#ifndef CSTOP
-# define CSTOP CONTROL('s')
-#endif /* CSTOP */
-#ifndef CSUSP
-# define CSUSP CONTROL('z')
-#endif /* CSUSP */
-#ifndef CDSUSP
-# define CDSUSP CONTROL('y')
-#endif /* CDSUSP */
-
-#ifdef hpux
-
-# ifndef CREPRINT
-# define CREPRINT _POSIX_VDISABLE
-# endif /* CREPRINT */
-# ifndef CDISCARD
-# define CDISCARD _POSIX_VDISABLE
-# endif /* CDISCARD */
-# ifndef CLNEXT
-# define CLNEXT _POSIX_VDISABLE
-# endif /* CLNEXT */
-# ifndef CWERASE
-# define CWERASE _POSIX_VDISABLE
-# endif /* CWERASE */
-
-#else /* !hpux */
-
-# ifndef CREPRINT
-# define CREPRINT CONTROL('r')
-# endif /* CREPRINT */
-# ifndef CDISCARD
-# define CDISCARD CONTROL('o')
-# endif /* CDISCARD */
-# ifndef CLNEXT
-# define CLNEXT CONTROL('v')
-# endif /* CLNEXT */
-# ifndef CWERASE
-# define CWERASE CONTROL('w')
-# endif /* CWERASE */
-
-#endif /* hpux */
-
-#ifndef CSTATUS
-# define CSTATUS CONTROL('t')
-#endif /* CSTATUS */
-#ifndef CPAGE
-# define CPAGE ' '
-#endif /* CPAGE */
-#ifndef CPGOFF
-# define CPGOFF CONTROL('m')
-#endif /* CPGOFF */
-#ifndef CKILL2
-# define CKILL2 _POSIX_VDISABLE
-#endif /* CKILL2 */
-#ifndef CBRK
-# ifndef masscomp
-# define CBRK 0377
-# else
-# define CBRK '\0'
-# endif /* masscomp */
-#endif /* CBRK */
-#ifndef CMIN
-# define CMIN CEOF
-#endif /* CMIN */
-#ifndef CTIME
-# define CTIME CEOL
-#endif /* CTIME */
-
-/*
- * Fix for sun inconsistency. On termio VSUSP and the rest of the
- * ttychars > NCC are defined. So we undefine them.
- */
-#if defined(TERMIO) || defined(POSIX)
-# if defined(POSIX) && defined(NCCS)
-# define NUMCC NCCS
-# else
-# ifdef NCC
-# define NUMCC NCC
-# endif /* NCC */
-# endif /* POSIX && NCCS */
-# ifdef NUMCC
-# ifdef VINTR
-# if NUMCC <= VINTR
-# undef VINTR
-# endif /* NUMCC <= VINTR */
-# endif /* VINTR */
-# ifdef VQUIT
-# if NUMCC <= VQUIT
-# undef VQUIT
-# endif /* NUMCC <= VQUIT */
-# endif /* VQUIT */
-# ifdef VERASE
-# if NUMCC <= VERASE
-# undef VERASE
-# endif /* NUMCC <= VERASE */
-# endif /* VERASE */
-# ifdef VKILL
-# if NUMCC <= VKILL
-# undef VKILL
-# endif /* NUMCC <= VKILL */
-# endif /* VKILL */
-# ifdef VEOF
-# if NUMCC <= VEOF
-# undef VEOF
-# endif /* NUMCC <= VEOF */
-# endif /* VEOF */
-# ifdef VEOL
-# if NUMCC <= VEOL
-# undef VEOL
-# endif /* NUMCC <= VEOL */
-# endif /* VEOL */
-# ifdef VEOL2
-# if NUMCC <= VEOL2
-# undef VEOL2
-# endif /* NUMCC <= VEOL2 */
-# endif /* VEOL2 */
-# ifdef VSWTCH
-# if NUMCC <= VSWTCH
-# undef VSWTCH
-# endif /* NUMCC <= VSWTCH */
-# endif /* VSWTCH */
-# ifdef VDSWTCH
-# if NUMCC <= VDSWTCH
-# undef VDSWTCH
-# endif /* NUMCC <= VDSWTCH */
-# endif /* VDSWTCH */
-# ifdef VERASE2
-# if NUMCC <= VERASE2
-# undef VERASE2
-# endif /* NUMCC <= VERASE2 */
-# endif /* VERASE2 */
-# ifdef VSTART
-# if NUMCC <= VSTART
-# undef VSTART
-# endif /* NUMCC <= VSTART */
-# endif /* VSTART */
-# ifdef VSTOP
-# if NUMCC <= VSTOP
-# undef VSTOP
-# endif /* NUMCC <= VSTOP */
-# endif /* VSTOP */
-# ifdef VWERASE
-# if NUMCC <= VWERASE
-# undef VWERASE
-# endif /* NUMCC <= VWERASE */
-# endif /* VWERASE */
-# ifdef VSUSP
-# if NUMCC <= VSUSP
-# undef VSUSP
-# endif /* NUMCC <= VSUSP */
-# endif /* VSUSP */
-# ifdef VDSUSP
-# if NUMCC <= VDSUSP
-# undef VDSUSP
-# endif /* NUMCC <= VDSUSP */
-# endif /* VDSUSP */
-# ifdef VREPRINT
-# if NUMCC <= VREPRINT
-# undef VREPRINT
-# endif /* NUMCC <= VREPRINT */
-# endif /* VREPRINT */
-# ifdef VDISCARD
-# if NUMCC <= VDISCARD
-# undef VDISCARD
-# endif /* NUMCC <= VDISCARD */
-# endif /* VDISCARD */
-# ifdef VLNEXT
-# if NUMCC <= VLNEXT
-# undef VLNEXT
-# endif /* NUMCC <= VLNEXT */
-# endif /* VLNEXT */
-# ifdef VSTATUS
-# if NUMCC <= VSTATUS
-# undef VSTATUS
-# endif /* NUMCC <= VSTATUS */
-# endif /* VSTATUS */
-# ifdef VPAGE
-# if NUMCC <= VPAGE
-# undef VPAGE
-# endif /* NUMCC <= VPAGE */
-# endif /* VPAGE */
-# ifdef VPGOFF
-# if NUMCC <= VPGOFF
-# undef VPGOFF
-# endif /* NUMCC <= VPGOFF */
-# endif /* VPGOFF */
-# ifdef VKILL2
-# if NUMCC <= VKILL2
-# undef VKILL2
-# endif /* NUMCC <= VKILL2 */
-# endif /* VKILL2 */
-# ifdef VBRK
-# if NUMCC <= VBRK
-# undef VBRK
-# endif /* NUMCC <= VBRK */
-# endif /* VBRK */
-# ifdef VMIN
-# if NUMCC <= VMIN
-# undef VMIN
-# endif /* NUMCC <= VMIN */
-# endif /* VMIN */
-# ifdef VTIME
-# if NUMCC <= VTIME
-# undef VTIME
-# endif /* NUMCC <= VTIME */
-# endif /* VTIME */
-# endif /* NUMCC */
-#endif /* !POSIX */
-
-#define C_INTR 0
-#define C_QUIT 1
-#define C_ERASE 2
-#define C_KILL 3
-#define C_EOF 4
-#define C_EOL 5
-#define C_EOL2 6
-#define C_SWTCH 7
-#define C_DSWTCH 8
-#define C_ERASE2 9
-#define C_START 10
-#define C_STOP 11
-#define C_WERASE 12
-#define C_SUSP 13
-#define C_DSUSP 14
-#define C_REPRINT 15
-#define C_DISCARD 16
-#define C_LNEXT 17
-#define C_STATUS 18
-#define C_PAGE 19
-#define C_PGOFF 20
-#define C_KILL2 21
-#define C_BRK 22
-#define C_MIN 23
-#define C_TIME 24
-#define C_NCC 25
-#define C_SH(A) (1 << (A))
-
-/*
- * Terminal dependend data structures
- */
-#define EX_IO 0 /* while we are executing */
-#define ED_IO 1 /* while we are editing */
-#define TS_IO 2 /* new mode from terminal */
-#define QU_IO 2 /* used only for quoted chars */
-#define NN_IO 3 /* The number of entries */
-
-#define MD_INP 0
-#define MD_OUT 1
-#define MD_CTL 2
-#define MD_LIN 3
-#define MD_CHAR 4
-#define MD_NN 5
-
-typedef struct {
- const char *t_name;
- u_int t_setmask;
- u_int t_clrmask;
-} ttyperm_t[NN_IO][MD_NN];
-
-typedef unsigned char ttychar_t[NN_IO][C_NCC];
-
-protected int tty_init(EditLine *);
-protected void tty_end(EditLine *);
-protected int tty_stty(EditLine *, int, const char **);
-protected int tty_rawmode(EditLine *);
-protected int tty_cookedmode(EditLine *);
-protected int tty_quotemode(EditLine *);
-protected int tty_noquotemode(EditLine *);
-protected void tty_bind_char(EditLine *, int);
-
-typedef struct {
- ttyperm_t t_t;
- ttychar_t t_c;
- struct termios t_ex, t_ed, t_ts;
- int t_tabs;
- int t_eight;
- speed_t t_speed;
- int t_mode;
- unsigned char t_vdisable;
-} el_tty_t;
-
-
-#endif /* _h_el_tty */
diff --git a/main/editline/vi.c b/main/editline/vi.c
deleted file mode 100644
index 5683c7de0..000000000
--- a/main/editline/vi.c
+++ /dev/null
@@ -1,941 +0,0 @@
-/* $NetBSD: vi.c,v 1.9 2002/03/18 16:01:01 christos Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Christos Zoulas of Cornell University.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-#if !defined(lint) && !defined(SCCSID)
-#if 0
-static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: vi.c,v 1.9 2002/03/18 16:01:01 christos Exp $");
-#endif
-#endif /* not lint && not SCCSID */
-
-/*
- * vi.c: Vi mode commands.
- */
-#include "el.h"
-
-private el_action_t cv_action(EditLine *, int);
-private el_action_t cv_paste(EditLine *, int);
-
-/* cv_action():
- * Handle vi actions.
- */
-private el_action_t
-cv_action(EditLine *el, int c)
-{
- char *cp, *kp;
-
- if (el->el_chared.c_vcmd.action & DELETE) {
- el->el_chared.c_vcmd.action = NOP;
- el->el_chared.c_vcmd.pos = 0;
-
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
- kp = el->el_chared.c_undo.buf;
- for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
- *kp++ = *cp;
- el->el_chared.c_undo.dsize++;
- }
-
- el->el_chared.c_undo.action = INSERT;
- el->el_chared.c_undo.ptr = el->el_line.buffer;
- el->el_line.lastchar = el->el_line.buffer;
- el->el_line.cursor = el->el_line.buffer;
- if (c & INSERT)
- el->el_map.current = el->el_map.key;
-
- return (CC_REFRESH);
- }
- el->el_chared.c_vcmd.pos = el->el_line.cursor;
- el->el_chared.c_vcmd.action = c;
- return (CC_ARGHACK);
-
-#ifdef notdef
- /*
- * I don't think that this is needed. But we keep it for now
- */
- else
- if (el_chared.c_vcmd.action == NOP) {
- el->el_chared.c_vcmd.pos = el->el_line.cursor;
- el->el_chared.c_vcmd.action = c;
- return (CC_ARGHACK);
- } else {
- el->el_chared.c_vcmd.action = 0;
- el->el_chared.c_vcmd.pos = 0;
- return (CC_ERROR);
- }
-#endif
-}
-
-
-/* cv_paste():
- * Paste previous deletion before or after the cursor
- */
-private el_action_t
-cv_paste(EditLine *el, int c)
-{
- char *ptr;
- c_undo_t *un = &el->el_chared.c_undo;
-
-#ifdef DEBUG_PASTE
- (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
- un->action, un->buf, un->isize, un->dsize);
-#endif
- if (un->isize == 0)
- return (CC_ERROR);
-
- if (!c && el->el_line.cursor < el->el_line.lastchar)
- el->el_line.cursor++;
- ptr = el->el_line.cursor;
-
- c_insert(el, (int) un->isize);
- if (el->el_line.cursor + un->isize > el->el_line.lastchar)
- return (CC_ERROR);
- (void) memcpy(ptr, un->buf, un->isize);
- return (CC_REFRESH);
-}
-
-
-/* vi_paste_next():
- * Vi paste previous deletion to the right of the cursor
- * [p]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_paste_next(EditLine *el, int c)
-{
-
- return (cv_paste(el, 0));
-}
-
-
-/* vi_paste_prev():
- * Vi paste previous deletion to the left of the cursor
- * [P]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_paste_prev(EditLine *el, int c)
-{
-
- return (cv_paste(el, 1));
-}
-
-
-/* vi_prev_space_word():
- * Vi move to the previous space delimited word
- * [B]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_prev_space_word(EditLine *el, int c)
-{
-
- if (el->el_line.cursor == el->el_line.buffer)
- return (CC_ERROR);
-
- el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
- el->el_line.buffer,
- el->el_state.argument,
- cv__isword);
-
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
-}
-
-
-/* vi_prev_word():
- * Vi move to the previous word
- * [B]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_prev_word(EditLine *el, int c)
-{
-
- if (el->el_line.cursor == el->el_line.buffer)
- return (CC_ERROR);
-
- el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
- el->el_line.buffer,
- el->el_state.argument,
- ce__isword);
-
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
-}
-
-
-/* vi_next_space_word():
- * Vi move to the next space delimited word
- * [W]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_next_space_word(EditLine *el, int c)
-{
-
- if (el->el_line.cursor == el->el_line.lastchar)
- return (CC_ERROR);
-
- el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
- el->el_line.lastchar,
- el->el_state.argument,
- cv__isword);
-
- if (el->el_map.type == MAP_VI)
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
-}
-
-
-/* vi_next_word():
- * Vi move to the next word
- * [w]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_next_word(EditLine *el, int c)
-{
-
- if (el->el_line.cursor == el->el_line.lastchar)
- return (CC_ERROR);
-
- el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
- el->el_line.lastchar,
- el->el_state.argument,
- ce__isword);
-
- if (el->el_map.type == MAP_VI)
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
-}
-
-
-/* vi_change_case():
- * Vi change case of character under the cursor and advance one character
- * [~]
- */
-protected el_action_t
-vi_change_case(EditLine *el, int c)
-{
-
- if (el->el_line.cursor < el->el_line.lastchar) {
- c = *el->el_line.cursor;
- if (isupper(c))
- *el->el_line.cursor++ = tolower(c);
- else if (islower(c))
- *el->el_line.cursor++ = toupper(c);
- else
- el->el_line.cursor++;
- re_fastaddc(el);
- return (CC_NORM);
- }
- return (CC_ERROR);
-}
-
-
-/* vi_change_meta():
- * Vi change prefix command
- * [c]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_change_meta(EditLine *el, int c)
-{
-
- /*
- * Delete with insert == change: first we delete and then we leave in
- * insert mode.
- */
- return (cv_action(el, DELETE | INSERT));
-}
-
-
-/* vi_insert_at_bol():
- * Vi enter insert mode at the beginning of line
- * [I]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_insert_at_bol(EditLine *el, int c)
-{
-
- el->el_line.cursor = el->el_line.buffer;
- el->el_chared.c_vcmd.ins = el->el_line.cursor;
-
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.action = DELETE;
-
- el->el_map.current = el->el_map.key;
- return (CC_CURSOR);
-}
-
-
-/* vi_replace_char():
- * Vi replace character under the cursor with the next character typed
- * [r]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_replace_char(EditLine *el, int c)
-{
-
- el->el_map.current = el->el_map.key;
- el->el_state.inputmode = MODE_REPLACE_1;
- el->el_chared.c_undo.action = CHANGE;
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
- return (CC_NORM);
-}
-
-
-/* vi_replace_mode():
- * Vi enter replace mode
- * [R]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_replace_mode(EditLine *el, int c)
-{
-
- el->el_map.current = el->el_map.key;
- el->el_state.inputmode = MODE_REPLACE;
- el->el_chared.c_undo.action = CHANGE;
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
- return (CC_NORM);
-}
-
-
-/* vi_substitute_char():
- * Vi replace character under the cursor and enter insert mode
- * [r]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_substitute_char(EditLine *el, int c)
-{
-
- c_delafter(el, el->el_state.argument);
- el->el_map.current = el->el_map.key;
- return (CC_REFRESH);
-}
-
-
-/* vi_substitute_line():
- * Vi substitute entire line
- * [S]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_substitute_line(EditLine *el, int c)
-{
-
- (void) em_kill_line(el, 0);
- el->el_map.current = el->el_map.key;
- return (CC_REFRESH);
-}
-
-
-/* vi_change_to_eol():
- * Vi change to end of line
- * [C]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_change_to_eol(EditLine *el, int c)
-{
-
- (void) ed_kill_line(el, 0);
- el->el_map.current = el->el_map.key;
- return (CC_REFRESH);
-}
-
-
-/* vi_insert():
- * Vi enter insert mode
- * [i]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_insert(EditLine *el, int c)
-{
-
- el->el_map.current = el->el_map.key;
-
- el->el_chared.c_vcmd.ins = el->el_line.cursor;
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.action = DELETE;
-
- return (CC_NORM);
-}
-
-
-/* vi_add():
- * Vi enter insert mode after the cursor
- * [a]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_add(EditLine *el, int c)
-{
- int ret;
-
- el->el_map.current = el->el_map.key;
- if (el->el_line.cursor < el->el_line.lastchar) {
- el->el_line.cursor++;
- if (el->el_line.cursor > el->el_line.lastchar)
- el->el_line.cursor = el->el_line.lastchar;
- ret = CC_CURSOR;
- } else
- ret = CC_NORM;
-
- el->el_chared.c_vcmd.ins = el->el_line.cursor;
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.action = DELETE;
-
- return (ret);
-}
-
-
-/* vi_add_at_eol():
- * Vi enter insert mode at end of line
- * [A]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_add_at_eol(EditLine *el, int c)
-{
-
- el->el_map.current = el->el_map.key;
- el->el_line.cursor = el->el_line.lastchar;
-
- /* Mark where insertion begins */
- el->el_chared.c_vcmd.ins = el->el_line.lastchar;
- el->el_chared.c_undo.ptr = el->el_line.lastchar;
- el->el_chared.c_undo.action = DELETE;
- return (CC_CURSOR);
-}
-
-
-/* vi_delete_meta():
- * Vi delete prefix command
- * [d]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_delete_meta(EditLine *el, int c)
-{
-
- return (cv_action(el, DELETE));
-}
-
-
-/* vi_end_word():
- * Vi move to the end of the current space delimited word
- * [E]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_end_word(EditLine *el, int c)
-{
-
- if (el->el_line.cursor == el->el_line.lastchar)
- return (CC_ERROR);
-
- el->el_line.cursor = cv__endword(el->el_line.cursor,
- el->el_line.lastchar, el->el_state.argument);
-
- if (el->el_chared.c_vcmd.action & DELETE) {
- el->el_line.cursor++;
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
-}
-
-
-/* vi_to_end_word():
- * Vi move to the end of the current word
- * [e]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_to_end_word(EditLine *el, int c)
-{
-
- if (el->el_line.cursor == el->el_line.lastchar)
- return (CC_ERROR);
-
- el->el_line.cursor = cv__endword(el->el_line.cursor,
- el->el_line.lastchar, el->el_state.argument);
-
- if (el->el_chared.c_vcmd.action & DELETE) {
- el->el_line.cursor++;
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
-}
-
-
-/* vi_undo():
- * Vi undo last change
- * [u]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_undo(EditLine *el, int c)
-{
- char *cp, *kp;
- char temp;
- int i, size;
- c_undo_t *un = &el->el_chared.c_undo;
-
-#ifdef DEBUG_UNDO
- (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
- un->action, un->buf, un->isize, un->dsize);
-#endif
- switch (un->action) {
- case DELETE:
- if (un->dsize == 0)
- return (CC_NORM);
-
- (void) memcpy(un->buf, un->ptr, un->dsize);
- for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
- *cp = cp[un->dsize];
-
- el->el_line.lastchar -= un->dsize;
- el->el_line.cursor = un->ptr;
-
- un->action = INSERT;
- un->isize = un->dsize;
- un->dsize = 0;
- break;
-
- case DELETE | INSERT:
- size = un->isize - un->dsize;
- if (size > 0)
- i = un->dsize;
- else
- i = un->isize;
- cp = un->ptr;
- kp = un->buf;
- while (i-- > 0) {
- temp = *kp;
- *kp++ = *cp;
- *cp++ = temp;
- }
- if (size > 0) {
- el->el_line.cursor = cp;
- c_insert(el, size);
- while (size-- > 0 && cp < el->el_line.lastchar) {
- temp = *kp;
- *kp++ = *cp;
- *cp++ = temp;
- }
- } else if (size < 0) {
- size = -size;
- for (; cp <= el->el_line.lastchar; cp++) {
- *kp++ = *cp;
- *cp = cp[size];
- }
- el->el_line.lastchar -= size;
- }
- el->el_line.cursor = un->ptr;
- i = un->dsize;
- un->dsize = un->isize;
- un->isize = i;
- break;
-
- case INSERT:
- if (un->isize == 0)
- return (CC_NORM);
-
- el->el_line.cursor = un->ptr;
- c_insert(el, (int) un->isize);
- (void) memcpy(un->ptr, un->buf, un->isize);
- un->action = DELETE;
- un->dsize = un->isize;
- un->isize = 0;
- break;
-
- case CHANGE:
- if (un->isize == 0)
- return (CC_NORM);
-
- el->el_line.cursor = un->ptr;
- size = (int) (el->el_line.cursor - el->el_line.lastchar);
- if (size < un->isize)
- size = un->isize;
- cp = un->ptr;
- kp = un->buf;
- for (i = 0; i < size; i++) {
- temp = *kp;
- *kp++ = *cp;
- *cp++ = temp;
- }
- un->dsize = 0;
- break;
-
- default:
- return (CC_ERROR);
- }
-
- return (CC_REFRESH);
-}
-
-
-/* vi_command_mode():
- * Vi enter command mode (use alternative key bindings)
- * [<ESC>]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_command_mode(EditLine *el, int c)
-{
- int size;
-
- /* [Esc] cancels pending action */
- el->el_chared.c_vcmd.ins = 0;
- el->el_chared.c_vcmd.action = NOP;
- el->el_chared.c_vcmd.pos = 0;
-
- el->el_state.doingarg = 0;
- size = el->el_chared.c_undo.ptr - el->el_line.cursor;
- if (size < 0)
- size = -size;
- if (el->el_chared.c_undo.action == (INSERT | DELETE) ||
- el->el_chared.c_undo.action == DELETE)
- el->el_chared.c_undo.dsize = size;
- else
- el->el_chared.c_undo.isize = size;
-
- el->el_state.inputmode = MODE_INSERT;
- el->el_map.current = el->el_map.alt;
-#ifdef VI_MOVE
- if (el->el_line.cursor > el->el_line.buffer)
- el->el_line.cursor--;
-#endif
- return (CC_CURSOR);
-}
-
-
-/* vi_zero():
- * Vi move to the beginning of line
- * [0]
- */
-protected el_action_t
-vi_zero(EditLine *el, int c)
-{
-
- if (el->el_state.doingarg) {
- if (el->el_state.argument > 1000000)
- return (CC_ERROR);
- el->el_state.argument =
- (el->el_state.argument * 10) + (c - '0');
- return (CC_ARGHACK);
- } else {
- el->el_line.cursor = el->el_line.buffer;
- if (el->el_chared.c_vcmd.action & DELETE) {
- cv_delfini(el);
- return (CC_REFRESH);
- }
- return (CC_CURSOR);
- }
-}
-
-
-/* vi_delete_prev_char():
- * Vi move to previous character (backspace)
- * [^H]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_delete_prev_char(EditLine *el, int c)
-{
-
- if (el->el_chared.c_vcmd.ins == 0)
- return (CC_ERROR);
-
- if (el->el_chared.c_vcmd.ins >
- el->el_line.cursor - el->el_state.argument)
- return (CC_ERROR);
-
- c_delbefore(el, el->el_state.argument);
- el->el_line.cursor -= el->el_state.argument;
-
- return (CC_REFRESH);
-}
-
-
-/* vi_list_or_eof():
- * Vi list choices for completion or indicate end of file if empty line
- * [^D]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_list_or_eof(EditLine *el, int c)
-{
-
-#ifdef notyet
- if (el->el_line.cursor == el->el_line.lastchar &&
- el->el_line.cursor == el->el_line.buffer) {
-#endif
- term_overwrite(el, STReof, 4); /* then do a EOF */
- term__flush();
- return (CC_EOF);
-#ifdef notyet
- } else {
- re_goto_bottom(el);
- *el->el_line.lastchar = '\0'; /* just in case */
- return (CC_LIST_CHOICES);
- }
-#endif
-}
-
-
-/* vi_kill_line_prev():
- * Vi cut from beginning of line to cursor
- * [^U]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_kill_line_prev(EditLine *el, int c)
-{
- char *kp, *cp;
-
- cp = el->el_line.buffer;
- kp = el->el_chared.c_kill.buf;
- while (cp < el->el_line.cursor)
- *kp++ = *cp++; /* copy it */
- el->el_chared.c_kill.last = kp;
- c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
- el->el_line.cursor = el->el_line.buffer; /* zap! */
- return (CC_REFRESH);
-}
-
-
-/* vi_search_prev():
- * Vi search history previous
- * [?]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_search_prev(EditLine *el, int c)
-{
-
- return (cv_search(el, ED_SEARCH_PREV_HISTORY));
-}
-
-
-/* vi_search_next():
- * Vi search history next
- * [/]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_search_next(EditLine *el, int c)
-{
-
- return (cv_search(el, ED_SEARCH_NEXT_HISTORY));
-}
-
-
-/* vi_repeat_search_next():
- * Vi repeat current search in the same search direction
- * [n]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_repeat_search_next(EditLine *el, int c)
-{
-
- if (el->el_search.patlen == 0)
- return (CC_ERROR);
- else
- return (cv_repeat_srch(el, el->el_search.patdir));
-}
-
-
-/* vi_repeat_search_prev():
- * Vi repeat current search in the opposite search direction
- * [N]
- */
-/*ARGSUSED*/
-protected el_action_t
-vi_repeat_search_prev(EditLine *el, int c)
-{
-
- if (el->el_search.patlen == 0)
- return (CC_ERROR);
- else
- return (cv_repeat_srch(el,
- el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
- ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
-}
-
-
-/* vi_next_char():
- * Vi move to the character specified next
- * [f]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_next_char(EditLine *el, int c)
-{
- char ch;
-
- if (el_getc(el, &ch) != 1)
- return (ed_end_of_file(el, 0));
-
- el->el_search.chadir = CHAR_FWD;
- el->el_search.chacha = ch;
-
- return (cv_csearch_fwd(el, ch, el->el_state.argument, 0));
-
-}
-
-
-/* vi_prev_char():
- * Vi move to the character specified previous
- * [F]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_prev_char(EditLine *el, int c)
-{
- char ch;
-
- if (el_getc(el, &ch) != 1)
- return (ed_end_of_file(el, 0));
-
- el->el_search.chadir = CHAR_BACK;
- el->el_search.chacha = ch;
-
- return (cv_csearch_back(el, ch, el->el_state.argument, 0));
-}
-
-
-/* vi_to_next_char():
- * Vi move up to the character specified next
- * [t]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_to_next_char(EditLine *el, int c)
-{
- char ch;
-
- if (el_getc(el, &ch) != 1)
- return (ed_end_of_file(el, 0));
-
- return (cv_csearch_fwd(el, ch, el->el_state.argument, 1));
-
-}
-
-
-/* vi_to_prev_char():
- * Vi move up to the character specified previous
- * [T]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_to_prev_char(EditLine *el, int c)
-{
- char ch;
-
- if (el_getc(el, &ch) != 1)
- return (ed_end_of_file(el, 0));
-
- return (cv_csearch_back(el, ch, el->el_state.argument, 1));
-}
-
-
-/* vi_repeat_next_char():
- * Vi repeat current character search in the same search direction
- * [;]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_repeat_next_char(EditLine *el, int c)
-{
-
- if (el->el_search.chacha == 0)
- return (CC_ERROR);
-
- return (el->el_search.chadir == CHAR_FWD
- ? cv_csearch_fwd(el, el->el_search.chacha,
- el->el_state.argument, 0)
- : cv_csearch_back(el, el->el_search.chacha,
- el->el_state.argument, 0));
-}
-
-
-/* vi_repeat_prev_char():
- * Vi repeat current character search in the opposite search direction
- * [,]
- */
-protected el_action_t
-/*ARGSUSED*/
-vi_repeat_prev_char(EditLine *el, int c)
-{
-
- if (el->el_search.chacha == 0)
- return (CC_ERROR);
-
- return el->el_search.chadir == CHAR_BACK ?
- cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
- cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
-}
diff --git a/main/enum.c b/main/enum.c
deleted file mode 100644
index 3fa0bb977..000000000
--- a/main/enum.c
+++ /dev/null
@@ -1,671 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * Funding provided by nic.at
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief ENUM Support for Asterisk
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * \arg Funding provided by nic.at
- *
- * \par Enum standards
- *
- * - NAPTR records: http://ietf.nri.reston.va.us/rfc/rfc2915.txt
- * - DNS SRV records: http://www.ietf.org/rfc/rfc2782.txt
- * - ENUM http://www.ietf.org/rfc/rfc3761.txt
- * - ENUM for H.323: http://www.ietf.org/rfc/rfc3762.txt
- * - ENUM SIP: http://www.ietf.org/rfc/rfc3764.txt
- * - IANA ENUM Services: http://www.iana.org/assignments/enum-services
- *
- * \par Possible improvement
- * \todo Implement a caching mechanism for multile enum lookups
- * - See http://bugs.digium.com/view.php?id=6739
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#if __APPLE_CC__ >= 1495
-#include <arpa/nameser_compat.h>
-#endif
-#include <resolv.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <regex.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/enum.h"
-#include "asterisk/dns.h"
-#include "asterisk/channel.h"
-#include "asterisk/config.h"
-#include "asterisk/utils.h"
-
-#ifdef __APPLE__
-#undef T_NAPTR
-#define T_NAPTR 35
-#endif
-
-#ifdef __APPLE__
-#undef T_TXT
-#define T_TXT 16
-#endif
-
-#define TOPLEV "e164.arpa." /*!< The IETF Enum standard root, managed by the ITU */
-
-/* Linked list from config file */
-static struct enum_search {
- char toplev[512];
- struct enum_search *next;
-} *toplevs;
-
-static int enumver;
-
-AST_MUTEX_DEFINE_STATIC(enumlock);
-
-struct naptr {
- unsigned short order;
- unsigned short pref;
-} __attribute__((__packed__));
-
-/*! \brief Parse NAPTR record information elements */
-static unsigned int parse_ie(char *data, unsigned int maxdatalen, unsigned char *src, unsigned int srclen)
-{
- unsigned int len, olen;
-
- len = olen = (unsigned int) src[0];
- src++;
- srclen--;
-
- if (len > srclen) {
- ast_log(LOG_WARNING, "ENUM parsing failed: Wanted %d characters, got %d\n", len, srclen);
- return -1;
- }
-
- if (len > maxdatalen)
- len = maxdatalen;
- memcpy(data, src, len);
-
- return olen + 1;
-}
-
-/*! \brief Parse DNS NAPTR record used in ENUM ---*/
-static int parse_naptr(char *dst, int dstsize, char *tech, int techsize, unsigned char *answer, int len, char *naptrinput)
-{
- char tech_return[80];
- unsigned char *oanswer = answer;
- char flags[512] = "";
- char services[512] = "";
- char *p;
- char regexp[512] = "";
- char repl[512] = "";
- char temp[512] = "";
- char delim;
- char *delim2;
- char *pattern, *subst, *d;
- int res;
- int regexp_len, size, backref;
- int d_len = sizeof(temp) - 1;
- regex_t preg;
- regmatch_t pmatch[9];
-
- tech_return[0] = '\0';
-
- dst[0] = '\0';
-
- if (len < sizeof(struct naptr)) {
- ast_log(LOG_WARNING, "NAPTR record length too short\n");
- return -1;
- }
- answer += sizeof(struct naptr);
- len -= sizeof(struct naptr);
- if ((res = parse_ie(flags, sizeof(flags) - 1, answer, len)) < 0) {
- ast_log(LOG_WARNING, "Failed to get flags from NAPTR record\n");
- return -1;
- } else {
- answer += res;
- len -= res;
- }
- if ((res = parse_ie(services, sizeof(services) - 1, answer, len)) < 0) {
- ast_log(LOG_WARNING, "Failed to get services from NAPTR record\n");
- return -1;
- } else {
- answer += res;
- len -= res;
- }
- if ((res = parse_ie(regexp, sizeof(regexp) - 1, answer, len)) < 0) {
- ast_log(LOG_WARNING, "Failed to get regexp from NAPTR record\n");
- return -1;
- } else {
- answer += res;
- len -= res;
- }
-
- if ((res = dn_expand(oanswer, answer + len, answer, repl, sizeof(repl) - 1)) < 0) {
- ast_log(LOG_WARNING, "Failed to expand hostname\n");
- return -1;
- }
-
- if (option_debug > 2) /* Advanced NAPTR debugging */
- ast_log(LOG_DEBUG, "NAPTR input='%s', flags='%s', services='%s', regexp='%s', repl='%s'\n",
- naptrinput, flags, services, regexp, repl);
-
- if (tolower(flags[0]) != 'u') {
- ast_log(LOG_WARNING, "NAPTR Flag must be 'U' or 'u'.\n");
- return -1;
- }
-
- p = strstr(services, "e2u+");
- if (p == NULL)
- p = strstr(services, "E2U+");
- if (p){
- p = p + 4;
- if (strchr(p, ':')){
- p = strchr(p, ':') + 1;
- }
- ast_copy_string(tech_return, p, sizeof(tech_return));
- } else {
-
- p = strstr(services, "+e2u");
- if (p == NULL)
- p = strstr(services, "+E2U");
- if (p) {
- *p = 0;
- p = strchr(services, ':');
- if (p)
- *p = 0;
- ast_copy_string(tech_return, services, sizeof(tech_return));
- }
- }
-
- /* DEDBUGGING STUB
- ast_copy_string(regexp, "!^\\+43(.*)$!\\1@bla.fasel!", sizeof(regexp) - 1);
- */
-
- regexp_len = strlen(regexp);
- if (regexp_len < 7) {
- ast_log(LOG_WARNING, "Regex too short to be meaningful.\n");
- return -1;
- }
-
-
- delim = regexp[0];
- delim2 = strchr(regexp + 1, delim);
- if ((delim2 == NULL) || (regexp[regexp_len-1] != delim)) {
- ast_log(LOG_WARNING, "Regex delimiter error (on \"%s\").\n",regexp);
- return -1;
- }
-
- pattern = regexp + 1;
- *delim2 = 0;
- subst = delim2 + 1;
- regexp[regexp_len-1] = 0;
-
-/*
- * now do the regex wizardry.
- */
-
- if (regcomp(&preg, pattern, REG_EXTENDED | REG_NEWLINE)) {
- ast_log(LOG_WARNING, "NAPTR Regex compilation error (regex = \"%s\").\n",regexp);
- return -1;
- }
-
- if (preg.re_nsub > 9) {
- ast_log(LOG_WARNING, "NAPTR Regex compilation error: too many subs.\n");
- regfree(&preg);
- return -1;
- }
-
- if (regexec(&preg, naptrinput, 9, pmatch, 0)) {
- ast_log(LOG_WARNING, "NAPTR Regex match failed.\n");
- regfree(&preg);
- return -1;
- }
- regfree(&preg);
-
- d = temp;
- d_len--;
- while (*subst && (d_len > 0)) {
- if ((subst[0] == '\\') && isdigit(subst[1]) && (pmatch[subst[1]-'0'].rm_so != -1)) {
- backref = subst[1]-'0';
- size = pmatch[backref].rm_eo - pmatch[backref].rm_so;
- if (size > d_len) {
- ast_log(LOG_WARNING, "Not enough space during NAPTR regex substitution.\n");
- return -1;
- }
- memcpy(d, naptrinput + pmatch[backref].rm_so, size);
- d += size;
- d_len -= size;
- subst += 2;
- } else if (isprint(*subst)) {
- *d++ = *subst++;
- d_len--;
- } else {
- ast_log(LOG_WARNING, "Error during regex substitution.\n");
- return -1;
- }
- }
- *d = 0;
- ast_copy_string(dst, temp, dstsize);
- dst[dstsize - 1] = '\0';
-
- if (*tech != '\0'){ /* check if it is requested NAPTR */
- if (!strncasecmp(tech, "ALL", techsize)){
- return 1; /* return or count any RR */
- }
- if (!strncasecmp(tech_return, tech, sizeof(tech_return)<techsize?sizeof(tech_return):techsize)){
- ast_copy_string(tech, tech_return, techsize);
- return 1; /* we got out RR */
- } else { /* go to the next RR in the DNS answer */
- return 0;
- }
- }
-
- /* tech was not specified, return first parsed RR */
- ast_copy_string(tech, tech_return, techsize);
-
- return 1;
-}
-
-/* do not return requested value, just count RRs and return thei number in dst */
-#define ENUMLOOKUP_OPTIONS_COUNT 1
-
-struct enum_naptr_rr {
- struct naptr naptr; /* order and preference of RR */
- char *result; /* result of naptr parsing,e.g.: tel:+5553 */
- char *tech; /* Technology (from URL scheme) */
- int sort_pos; /* sort position */
-};
-
-struct enum_context {
- char *dst; /* Destination part of URL from ENUM */
- int dstlen; /* Length */
- char *tech; /* Technology (from URL scheme) */
- int techlen; /* Length */
- char *txt; /* TXT record in TXT lookup */
- int txtlen; /* Length */
- char *naptrinput; /* The number to lookup */
- int position; /* used as counter for RRs or specifies position of required RR */
- int options; /* options , see ENUMLOOKUP_OPTIONS_* defined above */
- struct enum_naptr_rr *naptr_rrs; /* array of parsed NAPTR RRs */
- int naptr_rrs_count; /* Size of array naptr_rrs */
-};
-
-/*! \brief Callback for TXT record lookup */
-static int txt_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
-{
- struct enum_context *c = (struct enum_context *)context;
-
- if (answer == NULL) {
- c->txt = NULL;
- c->txtlen = 0;
- return 0;
- }
-
- /* skip over first byte, as for some reason it's a vertical tab character */
- answer += 1;
- len -= 1;
-
- /* answer is not null-terminated, but should be */
- /* this is safe to do, as answer has extra bytes on the end we can
- * safely overwrite with a null */
- answer[len] = '\0';
- /* now increment len so that len includes the null, so that we can
- * compare apples to apples */
- len +=1;
-
- /* finally, copy the answer into c->txt */
- ast_copy_string(c->txt, (const char *) answer, len < c->txtlen ? len : (c->txtlen));
-
- /* just to be safe, let's make sure c->txt is null terminated */
- c->txt[(c->txtlen)-1] = '\0';
-
- return 1;
-}
-
-/*! \brief Callback from ENUM lookup function */
-static int enum_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
-{
- struct enum_context *c = context;
- void *p = NULL;
- int res;
-
- res = parse_naptr(c->dst, c->dstlen, c->tech, c->techlen, answer, len, c->naptrinput);
-
- if (res < 0) {
- ast_log(LOG_WARNING, "Failed to parse naptr :(\n");
- return -1;
- } else if (res > 0 && !ast_strlen_zero(c->dst)){ /* ok, we got needed NAPTR */
- if (c->options & ENUMLOOKUP_OPTIONS_COUNT){ /* counting RRs */
- c->position++;
- snprintf(c->dst, c->dstlen, "%d", c->position);
- } else {
- if ((p = ast_realloc(c->naptr_rrs, sizeof(*c->naptr_rrs) * (c->naptr_rrs_count + 1)))) {
- c->naptr_rrs = p;
- memcpy(&c->naptr_rrs[c->naptr_rrs_count].naptr, answer, sizeof(c->naptr_rrs->naptr));
- c->naptr_rrs[c->naptr_rrs_count].result = strdup(c->dst);
- c->naptr_rrs[c->naptr_rrs_count].tech = strdup(c->tech);
- c->naptr_rrs[c->naptr_rrs_count].sort_pos = c->naptr_rrs_count;
- c->naptr_rrs_count++;
- }
- c->dst[0] = 0;
- }
- return 0;
- }
-
- if (c->options & ENUMLOOKUP_OPTIONS_COUNT) { /* counting RRs */
- snprintf(c->dst, c->dstlen, "%d", c->position);
- }
-
- return 0;
-}
-
-/*! \brief ENUM lookup */
-int ast_get_enum(struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen, char* suffix, char* options, unsigned int record)
-{
- struct enum_context context;
- char tmp[259 + 512];
- char naptrinput[512];
- int pos = strlen(number) - 1;
- int newpos = 0;
- int ret = -1;
- struct enum_search *s = NULL;
- int version = -1;
- /* for ISN rewrite */
- char *p1 = NULL;
- char *p2 = NULL;
- int k = 0;
- int i = 0;
- int z = 0;
-
- ast_copy_string(naptrinput, number[0] == 'n' ? number+1 : number, sizeof(naptrinput));
-
- context.naptrinput = naptrinput; /* The number */
- context.dst = dst; /* Return string */
- context.dstlen = dstlen;
- context.tech = tech;
- context.techlen = techlen;
- context.options = 0;
- context.position = record;
- context.naptr_rrs = NULL;
- context.naptr_rrs_count = 0;
-
- if (options != NULL) {
- if (*options == 'c') {
- context.options = ENUMLOOKUP_OPTIONS_COUNT;
- context.position = 0;
- }
- }
-
- ast_log(LOG_DEBUG, "ast_get_enum(): n='%s', tech='%s', suffix='%s', options='%d', record='%d'\n",
- number, tech, suffix, context.options, context.position);
-
- if (pos > 128)
- pos = 128;
-
- /* ISN rewrite */
- p1 = strchr(number, '*');
-
- if (number[0] == 'n') { /* do not perform ISN rewrite ('n' is testing flag) */
- p1 = NULL;
- k = 1; /* strip 'n' from number */
- }
-
- if (p1 != NULL) {
- p2 = p1+1;
- while (p1 > number){
- p1--;
- tmp[newpos++] = *p1;
- tmp[newpos++] = '.';
- }
- if (*p2) {
- while(*p2 && newpos < 128){
- tmp[newpos++] = *p2;
- p2++;
- }
- tmp[newpos++] = '.';
- }
-
- } else {
- while (pos >= k) {
- if (isdigit(number[pos])) {
- tmp[newpos++] = number[pos];
- tmp[newpos++] = '.';
- }
- pos--;
- }
- }
-
- if (chan && ast_autoservice_start(chan) < 0)
- return -1;
-
- if(suffix) {
- ast_copy_string(tmp + newpos, suffix, sizeof(tmp) - newpos);
- ret = ast_search_dns(&context, tmp, C_IN, T_NAPTR, enum_callback);
- ast_log(LOG_DEBUG, "ast_get_enum: ast_search_dns(%s) returned %d\n", tmp, ret);
- } else {
- ret = -1; /* this is actually dead code since the demise of app_enum.c */
- for (;;) {
- ast_mutex_lock(&enumlock);
- if (version != enumver) {
- /* Ooh, a reload... */
- s = toplevs;
- version = enumver;
- } else {
- s = s->next;
- }
- ast_mutex_unlock(&enumlock);
-
- if (!s)
- break;
-
- ast_copy_string(tmp + newpos, s->toplev, sizeof(tmp) - newpos);
- ret = ast_search_dns(&context, tmp, C_IN, T_NAPTR, enum_callback);
- ast_log(LOG_DEBUG, "ast_get_enum: ast_search_dns(%s) returned %d\n", tmp, ret);
- if (ret > 0)
- break;
- }
- }
-
- if (ret < 0) {
- ast_log(LOG_DEBUG, "No such number found: %s (%s)\n", tmp, strerror(errno));
- strcpy(dst, "0");
- ret = 0;
- }
-
- if (context.naptr_rrs_count >= context.position && ! (context.options & ENUMLOOKUP_OPTIONS_COUNT)) {
- /* sort array by NAPTR order/preference */
- for (k = 0; k < context.naptr_rrs_count; k++) {
- for (i = 0; i < context.naptr_rrs_count; i++) {
- /* use order first and then preference to compare */
- if ((ntohs(context.naptr_rrs[k].naptr.order) < ntohs(context.naptr_rrs[i].naptr.order)
- && context.naptr_rrs[k].sort_pos > context.naptr_rrs[i].sort_pos)
- || (ntohs(context.naptr_rrs[k].naptr.order) > ntohs(context.naptr_rrs[i].naptr.order)
- && context.naptr_rrs[k].sort_pos < context.naptr_rrs[i].sort_pos)){
- z = context.naptr_rrs[k].sort_pos;
- context.naptr_rrs[k].sort_pos = context.naptr_rrs[i].sort_pos;
- context.naptr_rrs[i].sort_pos = z;
- continue;
- }
- if (ntohs(context.naptr_rrs[k].naptr.order) == ntohs(context.naptr_rrs[i].naptr.order)) {
- if ((ntohs(context.naptr_rrs[k].naptr.pref) < ntohs(context.naptr_rrs[i].naptr.pref)
- && context.naptr_rrs[k].sort_pos > context.naptr_rrs[i].sort_pos)
- || (ntohs(context.naptr_rrs[k].naptr.pref) > ntohs(context.naptr_rrs[i].naptr.pref)
- && context.naptr_rrs[k].sort_pos < context.naptr_rrs[i].sort_pos)){
- z = context.naptr_rrs[k].sort_pos;
- context.naptr_rrs[k].sort_pos = context.naptr_rrs[i].sort_pos;
- context.naptr_rrs[i].sort_pos = z;
- }
- }
- }
- }
- for (k = 0; k < context.naptr_rrs_count; k++) {
- if (context.naptr_rrs[k].sort_pos == context.position-1) {
- ast_copy_string(context.dst, context.naptr_rrs[k].result, dstlen);
- ast_copy_string(context.tech, context.naptr_rrs[k].tech, techlen);
- break;
- }
- }
- } else if (!(context.options & ENUMLOOKUP_OPTIONS_COUNT)) {
- context.dst[0] = 0;
- }
- if (chan)
- ret |= ast_autoservice_stop(chan);
-
- for (k = 0; k < context.naptr_rrs_count; k++) {
- free(context.naptr_rrs[k].result);
- free(context.naptr_rrs[k].tech);
- }
-
- free(context.naptr_rrs);
-
- return ret;
-}
-
-/*! \brief Get TXT record from DNS.
- Really has nothing to do with enum, but anyway...
- */
-int ast_get_txt(struct ast_channel *chan, const char *number, char *dst, int dstlen, char *tech, int techlen, char *txt, int txtlen)
-{
- struct enum_context context;
- char tmp[259 + 512];
- char naptrinput[512] = "+";
- int pos = strlen(number) - 1;
- int newpos = 0;
- int ret = -1;
- struct enum_search *s = NULL;
- int version = -1;
-
- strncat(naptrinput, number, sizeof(naptrinput) - 2);
-
- context.naptrinput = naptrinput;
- context.dst = dst;
- context.dstlen = dstlen;
- context.tech = tech;
- context.techlen = techlen;
- context.txt = txt;
- context.txtlen = txtlen;
-
- if (pos > 128)
- pos = 128;
- while (pos >= 0) {
- tmp[newpos++] = number[pos--];
- tmp[newpos++] = '.';
- }
-
- if (chan && ast_autoservice_start(chan) < 0)
- return -1;
-
- for (;;) {
- ast_mutex_lock(&enumlock);
- if (version != enumver) {
- /* Ooh, a reload... */
- s = toplevs;
- version = enumver;
- } else {
- s = s->next;
- }
- if (s) {
- ast_copy_string(tmp + newpos, s->toplev, sizeof(tmp) - newpos);
- }
- ast_mutex_unlock(&enumlock);
- if (!s)
- break;
-
- ret = ast_search_dns(&context, tmp, C_IN, T_TXT, txt_callback);
- if (ret > 0)
- break;
- }
- if (ret < 0) {
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "No such number found in ENUM: %s (%s)\n", tmp, strerror(errno));
- ret = 0;
- }
- if (chan)
- ret |= ast_autoservice_stop(chan);
- return ret;
-}
-
-/*! \brief Add enum tree to linked list */
-static struct enum_search *enum_newtoplev(char *s)
-{
- struct enum_search *tmp;
-
- if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
- ast_copy_string(tmp->toplev, s, sizeof(tmp->toplev));
- }
- return tmp;
-}
-
-/*! \brief Initialize the ENUM support subsystem */
-int ast_enum_init(void)
-{
- struct ast_config *cfg;
- struct enum_search *s, *sl;
- struct ast_variable *v;
-
- /* Destroy existing list */
- ast_mutex_lock(&enumlock);
- s = toplevs;
- while(s) {
- sl = s;
- s = s->next;
- free(sl);
- }
- toplevs = NULL;
- cfg = ast_config_load("enum.conf");
- if (cfg) {
- sl = NULL;
- v = ast_variable_browse(cfg, "general");
- while(v) {
- if (!strcasecmp(v->name, "search")) {
- s = enum_newtoplev(v->value);
- if (s) {
- if (sl)
- sl->next = s;
- else
- toplevs = s;
- sl = s;
- }
- }
- v = v->next;
- }
- ast_config_destroy(cfg);
- } else {
- toplevs = enum_newtoplev(TOPLEV);
- }
- enumver++;
- ast_mutex_unlock(&enumlock);
- return 0;
-}
-
-int ast_enum_reload(void)
-{
- return ast_enum_init();
-}
diff --git a/main/file.c b/main/file.c
deleted file mode 100644
index 5836e21e3..000000000
--- a/main/file.c
+++ /dev/null
@@ -1,1392 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Generic File Format Support.
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "asterisk/frame.h"
-#include "asterisk/file.h"
-#include "asterisk/cli.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/sched.h"
-#include "asterisk/options.h"
-#include "asterisk/translate.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/app.h"
-#include "asterisk/pbx.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/module.h"
-#include "asterisk/astobj2.h"
-
-/*
- * The following variable controls the layout of localized sound files.
- * If 0, use the historical layout with prefix just before the filename
- * (i.e. digits/en/1.gsm , digits/it/1.gsm or default to digits/1.gsm),
- * if 1 put the prefix at the beginning of the filename
- * (i.e. en/digits/1.gsm, it/digits/1.gsm or default to digits/1.gsm).
- * The latter permits a language to be entirely in one directory.
- */
-int ast_language_is_prefix;
-
-static AST_LIST_HEAD_STATIC(formats, ast_format);
-
-int __ast_format_register(const struct ast_format *f, struct ast_module *mod)
-{
- struct ast_format *tmp;
-
- if (AST_LIST_LOCK(&formats)) {
- ast_log(LOG_WARNING, "Unable to lock format list\n");
- return -1;
- }
- AST_LIST_TRAVERSE(&formats, tmp, list) {
- if (!strcasecmp(f->name, tmp->name)) {
- AST_LIST_UNLOCK(&formats);
- ast_log(LOG_WARNING, "Tried to register '%s' format, already registered\n", f->name);
- return -1;
- }
- }
- if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
- AST_LIST_UNLOCK(&formats);
- return -1;
- }
- *tmp = *f;
- tmp->module = mod;
- if (tmp->buf_size) {
- /*
- * Align buf_size properly, rounding up to the machine-specific
- * alignment for pointers.
- */
- struct _test_align { void *a, *b; } p;
- int align = (char *)&p.b - (char *)&p.a;
- tmp->buf_size = ((f->buf_size + align - 1)/align)*align;
- }
-
- memset(&tmp->list, 0, sizeof(tmp->list));
-
- AST_LIST_INSERT_HEAD(&formats, tmp, list);
- AST_LIST_UNLOCK(&formats);
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Registered file format %s, extension(s) %s\n", f->name, f->exts);
-
- return 0;
-}
-
-int ast_format_unregister(const char *name)
-{
- struct ast_format *tmp;
- int res = -1;
-
- if (AST_LIST_LOCK(&formats)) {
- ast_log(LOG_WARNING, "Unable to lock format list\n");
- return -1;
- }
- AST_LIST_TRAVERSE_SAFE_BEGIN(&formats, tmp, list) {
- if (!strcasecmp(name, tmp->name)) {
- AST_LIST_REMOVE_CURRENT(&formats, list);
- free(tmp);
- res = 0;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&formats);
-
- if (!res) {
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Unregistered format %s\n", name);
- } else
- ast_log(LOG_WARNING, "Tried to unregister format %s, already unregistered\n", name);
-
- return res;
-}
-
-int ast_stopstream(struct ast_channel *tmp)
-{
- ast_channel_lock(tmp);
-
- /* Stop a running stream if there is one */
- if (tmp->stream) {
- ast_closestream(tmp->stream);
- tmp->stream = NULL;
- if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat))
- ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
- }
- /* Stop the video stream too */
- if (tmp->vstream != NULL) {
- ast_closestream(tmp->vstream);
- tmp->vstream = NULL;
- }
-
- ast_channel_unlock(tmp);
-
- return 0;
-}
-
-int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
-{
- int res = -1;
- int alt = 0;
- if (f->frametype == AST_FRAME_VIDEO) {
- if (fs->fmt->format < AST_FORMAT_MAX_AUDIO) {
- /* This is the audio portion. Call the video one... */
- if (!fs->vfs && fs->filename) {
- const char *type = ast_getformatname(f->subclass & ~0x1);
- fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode);
- ast_log(LOG_DEBUG, "Opened video output file\n");
- }
- if (fs->vfs)
- return ast_writestream(fs->vfs, f);
- /* else ignore */
- return 0;
- } else {
- /* Might / might not have mark set */
- alt = 1;
- }
- } else if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
- return -1;
- }
- if (((fs->fmt->format | alt) & f->subclass) == f->subclass) {
- res = fs->fmt->write(fs, f);
- if (res < 0)
- ast_log(LOG_WARNING, "Natural write failed\n");
- else if (res > 0)
- ast_log(LOG_WARNING, "Huh??\n");
- } else {
- /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't
- the one we've setup a translator for, we do the "wrong thing" XXX */
- if (fs->trans && f->subclass != fs->lastwriteformat) {
- ast_translator_free_path(fs->trans);
- fs->trans = NULL;
- }
- if (!fs->trans)
- fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass);
- if (!fs->trans)
- ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n",
- fs->fmt->name, ast_getformatname(f->subclass));
- else {
- struct ast_frame *trf;
- fs->lastwriteformat = f->subclass;
- /* Get the translated frame but don't consume the original in case they're using it on another stream */
- trf = ast_translate(fs->trans, f, 0);
- if (trf) {
- res = fs->fmt->write(fs, trf);
- ast_frfree(trf);
- if (res)
- ast_log(LOG_WARNING, "Translated frame write failed\n");
- } else
- res = 0;
- }
- }
- return res;
-}
-
-static int copy(const char *infile, const char *outfile)
-{
- int ifd, ofd, len;
- char buf[4096]; /* XXX make it lerger. */
-
- if ((ifd = open(infile, O_RDONLY)) < 0) {
- ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile);
- return -1;
- }
- if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) {
- ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile);
- close(ifd);
- return -1;
- }
- while ( (len = read(ifd, buf, sizeof(buf)) ) ) {
- int res;
- if (len < 0) {
- ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
- break;
- }
- /* XXX handle partial writes */
- res = write(ofd, buf, len);
- if (res != len) {
- ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
- len = -1; /* error marker */
- break;
- }
- }
- close(ifd);
- close(ofd);
- if (len < 0) {
- unlink(outfile);
- return -1; /* error */
- }
- return 0; /* success */
-}
-
-/*!
- * \brief construct a filename. Absolute pathnames are preserved,
- * relative names are prefixed by the sounds/ directory.
- * The wav49 suffix is replaced by 'WAV'.
- * Returns a malloc'ed string to be freed by the caller.
- */
-static char *build_filename(const char *filename, const char *ext)
-{
- char *fn = NULL;
-
- if (!strcmp(ext, "wav49"))
- ext = "WAV";
-
- if (filename[0] == '/') {
- if (asprintf(&fn, "%s.%s", filename, ext) < 0) {
- ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
- fn = NULL;
- }
- } else {
- if (asprintf(&fn, "%s/sounds/%s.%s",
- ast_config_AST_DATA_DIR, filename, ext) < 0) {
- ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
- fn = NULL;
- }
- }
- return fn;
-}
-
-/* compare type against the list 'exts' */
-/* XXX need a better algorithm */
-static int exts_compare(const char *exts, const char *type)
-{
- char tmp[256];
- char *stringp = tmp, *ext;
-
- ast_copy_string(tmp, exts, sizeof(tmp));
- while ((ext = strsep(&stringp, "|"))) {
- if (!strcmp(ext, type))
- return 1;
- }
-
- return 0;
-}
-
-static void filestream_destructor(void *arg)
-{
- char *cmd = NULL;
- size_t size = 0;
- struct ast_filestream *f = arg;
-
- /* Stop a running stream if there is one */
- if (f->owner) {
- if (f->fmt->format < AST_FORMAT_MAX_AUDIO) {
- f->owner->stream = NULL;
- AST_SCHED_DEL(f->owner->sched, f->owner->streamid);
-#ifdef HAVE_DAHDI
- ast_settimeout(f->owner, 0, NULL, NULL);
-#endif
- } else {
- f->owner->vstream = NULL;
- AST_SCHED_DEL(f->owner->sched, f->owner->vstreamid);
- }
- }
- /* destroy the translator on exit */
- if (f->trans)
- ast_translator_free_path(f->trans);
-
- if (f->realfilename && f->filename) {
- size = strlen(f->filename) + strlen(f->realfilename) + 15;
- cmd = alloca(size);
- memset(cmd,0,size);
- snprintf(cmd,size,"/bin/mv -f %s %s",f->filename,f->realfilename);
- ast_safe_system(cmd);
- }
-
- if (f->filename)
- free(f->filename);
- if (f->realfilename)
- free(f->realfilename);
- if (f->fmt->close)
- f->fmt->close(f);
- if (f->f)
- fclose(f->f);
- if (f->vfs)
- ast_closestream(f->vfs);
- if (f->orig_chan_name)
- free((void *) f->orig_chan_name);
- ast_module_unref(f->fmt->module);
-}
-
-static struct ast_filestream *get_filestream(struct ast_format *fmt, FILE *bfile)
-{
- struct ast_filestream *s;
-
- int l = sizeof(*s) + fmt->buf_size + fmt->desc_size; /* total allocation size */
- if ( (s = ao2_alloc(l, filestream_destructor)) == NULL)
- return NULL;
- s->fmt = fmt;
- s->f = bfile;
-
- if (fmt->desc_size)
- s->_private = ((char *)(s+1)) + fmt->buf_size;
- if (fmt->buf_size)
- s->buf = (char *)(s+1);
- s->fr.src = fmt->name;
- return s;
-}
-
-/*
- * Default implementations of open and rewrite.
- * Only use them if you don't have expensive stuff to do.
- */
-enum wrap_fn { WRAP_OPEN, WRAP_REWRITE };
-
-static int fn_wrapper(struct ast_filestream *s, const char *comment, enum wrap_fn mode)
-{
- struct ast_format *f = s->fmt;
- int ret = -1;
-
- if (mode == WRAP_OPEN && f->open && f->open(s))
- ast_log(LOG_WARNING, "Unable to open format %s\n", f->name);
- else if (mode == WRAP_REWRITE && f->rewrite && f->rewrite(s, comment))
- ast_log(LOG_WARNING, "Unable to rewrite format %s\n", f->name);
- else {
- /* preliminary checks succeed. update usecount */
- ast_module_ref(f->module);
- ret = 0;
- }
- return ret;
-}
-
-static int rewrite_wrapper(struct ast_filestream *s, const char *comment)
-{
- return fn_wrapper(s, comment, WRAP_REWRITE);
-}
-
-static int open_wrapper(struct ast_filestream *s)
-{
- return fn_wrapper(s, NULL, WRAP_OPEN);
-}
-
-enum file_action {
- ACTION_EXISTS = 1, /* return matching format if file exists, 0 otherwise */
- ACTION_DELETE, /* delete file, return 0 on success, -1 on error */
- ACTION_RENAME, /* rename file. return 0 on success, -1 on error */
- ACTION_OPEN,
- ACTION_COPY /* copy file. return 0 on success, -1 on error */
-};
-
-/*!
- * \brief perform various actions on a file. Second argument
- * arg2 depends on the command:
- * unused for EXISTS and DELETE
- * destination file name (const char *) for COPY and RENAME
- * struct ast_channel * for OPEN
- * if fmt is NULL, OPEN will return the first matching entry,
- * whereas other functions will run on all matching entries.
- */
-static int ast_filehelper(const char *filename, const void *arg2, const char *fmt, const enum file_action action)
-{
- struct ast_format *f;
- int res = (action == ACTION_EXISTS) ? 0 : -1;
-
- if (AST_LIST_LOCK(&formats)) {
- ast_log(LOG_WARNING, "Unable to lock format list\n");
- return res;
- }
- /* Check for a specific format */
- AST_LIST_TRAVERSE(&formats, f, list) {
- char *stringp, *ext = NULL;
-
- if (fmt && !exts_compare(f->exts, fmt))
- continue;
-
- /* Look for a file matching the supported extensions.
- * The file must exist, and for OPEN, must match
- * one of the formats supported by the channel.
- */
- stringp = ast_strdupa(f->exts); /* this is in the stack so does not need to be freed */
- while ( (ext = strsep(&stringp, "|")) ) {
- struct stat st;
- char *fn = build_filename(filename, ext);
-
- if (fn == NULL)
- continue;
-
- if ( stat(fn, &st) ) { /* file not existent */
- free(fn);
- continue;
- }
- /* for 'OPEN' we need to be sure that the format matches
- * what the channel can process
- */
- if (action == ACTION_OPEN) {
- struct ast_channel *chan = (struct ast_channel *)arg2;
- FILE *bfile;
- struct ast_filestream *s;
-
- if ( !(chan->writeformat & f->format) &&
- !(f->format >= AST_FORMAT_MAX_AUDIO && fmt)) {
- free(fn);
- continue; /* not a supported format */
- }
- if ( (bfile = fopen(fn, "r")) == NULL) {
- free(fn);
- continue; /* cannot open file */
- }
- s = get_filestream(f, bfile);
- if (!s) {
- fclose(bfile);
- free(fn); /* cannot allocate descriptor */
- continue;
- }
- if (open_wrapper(s)) {
- free(fn);
- ast_closestream(s);
- continue; /* cannot run open on file */
- }
- /* ok this is good for OPEN */
- res = 1; /* found */
- s->lasttimeout = -1;
- s->fmt = f;
- s->trans = NULL;
- s->filename = NULL;
- if (s->fmt->format < AST_FORMAT_MAX_AUDIO) {
- if (chan->stream)
- ast_closestream(chan->stream);
- chan->stream = s;
- } else {
- if (chan->vstream)
- ast_closestream(chan->vstream);
- chan->vstream = s;
- }
- free(fn);
- break;
- }
- switch (action) {
- case ACTION_OPEN:
- break; /* will never get here */
-
- case ACTION_EXISTS: /* return the matching format */
- res |= f->format;
- break;
-
- case ACTION_DELETE:
- if ( (res = unlink(fn)) )
- ast_log(LOG_WARNING, "unlink(%s) failed: %s\n", fn, strerror(errno));
- break;
-
- case ACTION_RENAME:
- case ACTION_COPY: {
- char *nfn = build_filename((const char *)arg2, ext);
- if (!nfn)
- ast_log(LOG_WARNING, "Out of memory\n");
- else {
- res = action == ACTION_COPY ? copy(fn, nfn) : rename(fn, nfn);
- if (res)
- ast_log(LOG_WARNING, "%s(%s,%s) failed: %s\n",
- action == ACTION_COPY ? "copy" : "rename",
- fn, nfn, strerror(errno));
- free(nfn);
- }
- }
- break;
-
- default:
- ast_log(LOG_WARNING, "Unknown helper %d\n", action);
- }
- free(fn);
- }
- }
- AST_LIST_UNLOCK(&formats);
- return res;
-}
-
-static int is_absolute_path(const char *filename)
-{
- return filename[0] == '/';
-}
-
-static int fileexists_test(const char *filename, const char *fmt, const char *lang,
- char *buf, int buflen)
-{
- if (buf == NULL) {
- return -1;
- }
-
- if (ast_language_is_prefix && !is_absolute_path(filename)) { /* new layout */
- if (lang) {
- snprintf(buf, buflen, "%s/%s", lang, filename);
- } else {
- snprintf(buf, buflen, "%s", filename);
- }
- } else { /* old layout */
- strcpy(buf, filename); /* first copy the full string */
- if (lang) {
- /* insert the language and suffix if needed */
- const char *c = strrchr(filename, '/');
- int offset = c ? c - filename + 1 : 0; /* points right after the last '/' */
- snprintf(buf + offset, buflen - offset, "%s/%s", lang, filename + offset);
- }
- }
-
- return ast_filehelper(buf, NULL, fmt, ACTION_EXISTS);
-}
-
-/*!
- * \brief helper routine to locate a file with a given format
- * and language preference.
- * Try preflang, preflang with stripped '_' suffix, or NULL.
- * In the standard asterisk, language goes just before the last component.
- * In an alternative configuration, the language should be a prefix
- * to the actual filename.
- *
- * The last parameter(s) point to a buffer of sufficient size,
- * which on success is filled with the matching filename.
- */
-static int fileexists_core(const char *filename, const char *fmt, const char *preflang,
- char *buf, int buflen)
-{
- int res = -1;
- char *lang = NULL;
-
- if (buf == NULL) {
- return -1;
- }
-
- /* We try languages in the following order:
- * preflang (may include dialect)
- * lang (preflang without dialect - if any)
- * <none>
- * default (unless the same as preflang or lang without dialect)
- */
-
- /* Try preferred language */
- if (!ast_strlen_zero(preflang)) {
- /* try the preflang exactly as it was requested */
- if ((res = fileexists_test(filename, fmt, preflang, buf, buflen)) > 0) {
- return res;
- } else {
- /* try without a dialect */
- char *postfix = NULL;
- postfix = lang = ast_strdupa(preflang);
-
- strsep(&postfix, "_");
- if (postfix) {
- if ((res = fileexists_test(filename, fmt, lang, buf, buflen)) > 0) {
- return res;
- }
- }
- }
- }
-
- /* Try without any language */
- if ((res = fileexists_test(filename, fmt, NULL, buf, buflen)) > 0) {
- return res;
- }
-
- /* Finally try the default language unless it was already tried before */
- if ((ast_strlen_zero(preflang) || strcmp(preflang, DEFAULT_LANGUAGE)) && (ast_strlen_zero(lang) || strcmp(lang, DEFAULT_LANGUAGE))) {
- if ((res = fileexists_test(filename, fmt, DEFAULT_LANGUAGE, buf, buflen)) > 0) {
- return res;
- }
- }
-
- return 0;
-}
-
-struct ast_filestream *ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
-{
- return ast_openstream_full(chan, filename, preflang, 0);
-}
-
-struct ast_filestream *ast_openstream_full(struct ast_channel *chan, const char *filename, const char *preflang, int asis)
-{
- /*
- * Use fileexists_core() to find a file in a compatible
- * language and format, set up a suitable translator,
- * and open the stream.
- */
- int fmts, res, buflen;
- char *buf;
-
- if (!asis) {
- /* do this first, otherwise we detect the wrong writeformat */
- ast_stopstream(chan);
- if (chan->generator)
- ast_deactivate_generator(chan);
- }
- if (preflang == NULL)
- preflang = "";
- buflen = strlen(preflang) + strlen(filename) + 4;
- buf = alloca(buflen);
- if (buf == NULL)
- return NULL;
- fmts = fileexists_core(filename, NULL, preflang, buf, buflen);
- if (fmts > 0)
- fmts &= AST_FORMAT_AUDIO_MASK;
- if (fmts < 1) {
- ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
- return NULL;
- }
- chan->oldwriteformat = chan->writeformat;
- /* Set the channel to a format we can work with */
- res = ast_set_write_format(chan, fmts);
- res = ast_filehelper(buf, chan, NULL, ACTION_OPEN);
- if (res >= 0)
- return chan->stream;
- return NULL;
-}
-
-struct ast_filestream *ast_openvstream(struct ast_channel *chan, const char *filename, const char *preflang)
-{
- /* As above, but for video. But here we don't have translators
- * so we must enforce a format.
- */
- unsigned int format;
- char *buf;
- int buflen;
-
- if (preflang == NULL)
- preflang = "";
- buflen = strlen(preflang) + strlen(filename) + 4;
- buf = alloca(buflen);
- if (buf == NULL)
- return NULL;
-
- for (format = AST_FORMAT_MAX_AUDIO << 1; format <= AST_FORMAT_MAX_VIDEO; format = format << 1) {
- int fd;
- const char *fmt;
-
- if (!(chan->nativeformats & format))
- continue;
- fmt = ast_getformatname(format);
- if ( fileexists_core(filename, fmt, preflang, buf, buflen) < 1) /* no valid format */
- continue;
- fd = ast_filehelper(buf, chan, fmt, ACTION_OPEN);
- if (fd >= 0)
- return chan->vstream;
- ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename);
- }
- return NULL;
-}
-
-struct ast_frame *ast_readframe(struct ast_filestream *s)
-{
- struct ast_frame *f = NULL;
- int whennext = 0;
- if (s && s->fmt)
- f = s->fmt->read(s, &whennext);
- if (f) {
- ast_set_flag(f, AST_FRFLAG_FROM_FILESTREAM);
- ao2_ref(s, +1);
- }
- return f;
-}
-
-enum fsread_res {
- FSREAD_FAILURE,
- FSREAD_SUCCESS_SCHED,
- FSREAD_SUCCESS_NOSCHED,
-};
-
-static int ast_fsread_audio(const void *data);
-
-static enum fsread_res ast_readaudio_callback(struct ast_filestream *s)
-{
- int whennext = 0;
-
- while (!whennext) {
- struct ast_frame *fr;
-
- if (s->orig_chan_name && strcasecmp(s->owner->name, s->orig_chan_name))
- goto return_failure;
-
- fr = s->fmt->read(s, &whennext);
- if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) {
- if (fr)
- ast_log(LOG_WARNING, "Failed to write frame\n");
- goto return_failure;
- }
- }
- if (whennext != s->lasttimeout) {
-#ifdef HAVE_DAHDI
- if (s->owner->timingfd > -1) {
- int zap_timer_samples = whennext;
- int rate;
- /* whennext is in samples, but DAHDI timers operate in 8 kHz samples. */
- if ((rate = ast_format_rate(s->fmt->format)) != 8000) {
- float factor;
- factor = ((float) rate) / ((float) 8000.0);
- zap_timer_samples = (int) ( ((float) zap_timer_samples) / factor );
- }
- ast_settimeout(s->owner, zap_timer_samples, ast_fsread_audio, s);
- } else
-#endif
- s->owner->streamid = ast_sched_add(s->owner->sched,
- whennext / (ast_format_rate(s->fmt->format) / 1000),
- ast_fsread_audio, s);
- s->lasttimeout = whennext;
- return FSREAD_SUCCESS_NOSCHED;
- }
- return FSREAD_SUCCESS_SCHED;
-
-return_failure:
- s->owner->streamid = -1;
-#ifdef HAVE_DAHDI
- ast_settimeout(s->owner, 0, NULL, NULL);
-#endif
- return FSREAD_FAILURE;
-}
-
-static int ast_fsread_audio(const void *data)
-{
- struct ast_filestream *fs = (struct ast_filestream *)data;
- enum fsread_res res;
-
- res = ast_readaudio_callback(fs);
-
- if (res == FSREAD_SUCCESS_SCHED)
- return 1;
-
- return 0;
-}
-
-static int ast_fsread_video(const void *data);
-
-static enum fsread_res ast_readvideo_callback(struct ast_filestream *s)
-{
- int whennext = 0;
-
- while (!whennext) {
- struct ast_frame *fr = s->fmt->read(s, &whennext);
- if (!fr || ast_write(s->owner, fr)) { /* no stream or error, as above */
- if (fr)
- ast_log(LOG_WARNING, "Failed to write frame\n");
- s->owner->vstreamid = -1;
- return FSREAD_FAILURE;
- }
- }
-
- if (whennext != s->lasttimeout) {
- s->owner->vstreamid = ast_sched_add(s->owner->sched,
- whennext / (ast_format_rate(s->fmt->format) / 1000),
- ast_fsread_video, s);
- s->lasttimeout = whennext;
- return FSREAD_SUCCESS_NOSCHED;
- }
-
- return FSREAD_SUCCESS_SCHED;
-}
-
-static int ast_fsread_video(const void *data)
-{
- struct ast_filestream *fs = (struct ast_filestream *)data;
- enum fsread_res res;
-
- res = ast_readvideo_callback(fs);
-
- if (res == FSREAD_SUCCESS_SCHED)
- return 1;
-
- return 0;
-}
-
-int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
-{
- s->owner = chan;
- return 0;
-}
-
-int ast_playstream(struct ast_filestream *s)
-{
- enum fsread_res res;
-
- if (s->fmt->format < AST_FORMAT_MAX_AUDIO)
- res = ast_readaudio_callback(s);
- else
- res = ast_readvideo_callback(s);
-
- return (res == FSREAD_FAILURE) ? -1 : 0;
-}
-
-int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
-{
- return fs->fmt->seek(fs, sample_offset, whence);
-}
-
-int ast_truncstream(struct ast_filestream *fs)
-{
- return fs->fmt->trunc(fs);
-}
-
-off_t ast_tellstream(struct ast_filestream *fs)
-{
- return fs->fmt->tell(fs);
-}
-
-int ast_stream_fastforward(struct ast_filestream *fs, off_t ms)
-{
- return ast_seekstream(fs, ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR);
-}
-
-int ast_stream_rewind(struct ast_filestream *fs, off_t ms)
-{
- return ast_seekstream(fs, -ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR);
-}
-
-int ast_closestream(struct ast_filestream *f)
-{
-
- if (ast_test_flag(&f->fr, AST_FRFLAG_FROM_FILESTREAM)) {
- /* If this flag is still set, it essentially means that the reference
- * count of f is non-zero. We can't destroy this filestream until
- * whatever is using the filestream's frame has finished.
- *
- * Since this was called, however, we need to remove the reference from
- * when this filestream was first allocated. That way, when the embedded
- * frame is freed, the refcount will reach 0 and we can finish destroying
- * this filestream properly.
- */
- ao2_ref(f, -1);
- return 0;
- }
-
- ao2_ref(f, -1);
- return 0;
-}
-
-
-/*
- * Look the various language-specific places where a file could exist.
- */
-int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
-{
- char *buf;
- int buflen;
-
- if (preflang == NULL)
- preflang = "";
- buflen = strlen(preflang) + strlen(filename) + 4; /* room for everything */
- buf = alloca(buflen);
- if (buf == NULL)
- return 0;
- return fileexists_core(filename, fmt, preflang, buf, buflen);
-}
-
-int ast_filedelete(const char *filename, const char *fmt)
-{
- return ast_filehelper(filename, NULL, fmt, ACTION_DELETE);
-}
-
-int ast_filerename(const char *filename, const char *filename2, const char *fmt)
-{
- return ast_filehelper(filename, filename2, fmt, ACTION_RENAME);
-}
-
-int ast_filecopy(const char *filename, const char *filename2, const char *fmt)
-{
- return ast_filehelper(filename, filename2, fmt, ACTION_COPY);
-}
-
-int ast_streamfile(struct ast_channel *chan, const char *filename, const char *preflang)
-{
- struct ast_filestream *fs;
- struct ast_filestream *vfs=NULL;
- char fmt[256];
-
- fs = ast_openstream(chan, filename, preflang);
- if (fs)
- vfs = ast_openvstream(chan, filename, preflang);
- if (vfs)
- ast_log(LOG_DEBUG, "Ooh, found a video stream, too, format %s\n", ast_getformatname(vfs->fmt->format));
- if (fs){
- int res;
- if (ast_test_flag(chan, AST_FLAG_MASQ_NOSTREAM))
- fs->orig_chan_name = ast_strdup(chan->name);
- if (ast_applystream(chan, fs))
- return -1;
- if (vfs && ast_applystream(chan, vfs))
- return -1;
- res = ast_playstream(fs);
- if (!res && vfs)
- res = ast_playstream(vfs);
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "<%s> Playing '%s' (language '%s')\n", chan->name, filename, preflang ? preflang : "default");
-
- return res;
- }
- ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), chan->nativeformats), strerror(errno));
- return -1;
-}
-
-struct ast_filestream *ast_readfile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
-{
- FILE *bfile;
- struct ast_format *f;
- struct ast_filestream *fs = NULL;
- char *fn;
-
- if (AST_LIST_LOCK(&formats)) {
- ast_log(LOG_WARNING, "Unable to lock format list\n");
- return NULL;
- }
-
- AST_LIST_TRAVERSE(&formats, f, list) {
- fs = NULL;
- if (!exts_compare(f->exts, type))
- continue;
-
- fn = build_filename(filename, type);
- errno = 0;
- bfile = fopen(fn, "r");
- if (!bfile || (fs = get_filestream(f, bfile)) == NULL ||
- open_wrapper(fs) ) {
- ast_log(LOG_WARNING, "Unable to open %s\n", fn);
- if (fs) {
- ast_closestream(fs);
- }
- fs = NULL;
- bfile = NULL;
- free(fn);
- continue;
- }
- /* found it */
- fs->trans = NULL;
- fs->fmt = f;
- fs->flags = flags;
- fs->mode = mode;
- fs->filename = strdup(filename);
- fs->vfs = NULL;
- break;
- }
-
- AST_LIST_UNLOCK(&formats);
- if (!fs)
- ast_log(LOG_WARNING, "No such format '%s'\n", type);
-
- return fs;
-}
-
-struct ast_filestream *ast_writefile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
-{
- int fd, myflags = 0;
- /* compiler claims this variable can be used before initialization... */
- FILE *bfile = NULL;
- struct ast_format *f;
- struct ast_filestream *fs = NULL;
- char *buf = NULL;
- size_t size = 0;
- int format_found = 0;
-
- if (AST_LIST_LOCK(&formats)) {
- ast_log(LOG_WARNING, "Unable to lock format list\n");
- return NULL;
- }
-
- /* set the O_TRUNC flag if and only if there is no O_APPEND specified */
- /* We really can't use O_APPEND as it will break WAV header updates */
- if (flags & O_APPEND) {
- flags &= ~O_APPEND;
- } else {
- myflags = O_TRUNC;
- }
-
- myflags |= O_WRONLY | O_CREAT;
-
- /* XXX need to fix this - we should just do the fopen,
- * not open followed by fdopen()
- */
- AST_LIST_TRAVERSE(&formats, f, list) {
- char *fn, *orig_fn = NULL;
- if (fs)
- break;
-
- if (!exts_compare(f->exts, type))
- continue;
- else
- format_found = 1;
-
- fn = build_filename(filename, type);
- fd = open(fn, flags | myflags, mode);
- if (fd > -1) {
- /* fdopen() the resulting file stream */
- bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w");
- if (!bfile) {
- ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno));
- close(fd);
- fd = -1;
- }
- }
-
- if (ast_opt_cache_record_files && (fd > -1)) {
- char *c;
-
- fclose(bfile); /* this also closes fd */
- /*
- We touch orig_fn just as a place-holder so other things (like vmail) see the file is there.
- What we are really doing is writing to record_cache_dir until we are done then we will mv the file into place.
- */
- orig_fn = ast_strdupa(fn);
- for (c = fn; *c; c++)
- if (*c == '/')
- *c = '_';
-
- size = strlen(fn) + strlen(record_cache_dir) + 2;
- buf = alloca(size);
- strcpy(buf, record_cache_dir);
- strcat(buf, "/");
- strcat(buf, fn);
- free(fn);
- fn = buf;
- fd = open(fn, flags | myflags, mode);
- if (fd > -1) {
- /* fdopen() the resulting file stream */
- bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w");
- if (!bfile) {
- ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno));
- close(fd);
- fd = -1;
- }
- }
- }
- if (fd > -1) {
- errno = 0;
- fs = get_filestream(f, bfile);
- if (!fs || rewrite_wrapper(fs, comment)) {
- ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn);
- close(fd);
- if (orig_fn) {
- unlink(fn);
- unlink(orig_fn);
- }
- if (fs) {
- ast_closestream(fs);
- fs = NULL;
- }
- continue;
- }
- fs->trans = NULL;
- fs->fmt = f;
- fs->flags = flags;
- fs->mode = mode;
- if (orig_fn) {
- fs->realfilename = strdup(orig_fn);
- fs->filename = strdup(fn);
- } else {
- fs->realfilename = NULL;
- fs->filename = strdup(filename);
- }
- fs->vfs = NULL;
- /* If truncated, we'll be at the beginning; if not truncated, then append */
- f->seek(fs, 0, SEEK_END);
- } else if (errno != EEXIST) {
- ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno));
- if (orig_fn)
- unlink(orig_fn);
- }
- /* if buf != NULL then fn is already free and pointing to it */
- if (!buf)
- free(fn);
- }
-
- AST_LIST_UNLOCK(&formats);
-
- if (!format_found)
- ast_log(LOG_WARNING, "No such format '%s'\n", type);
-
- return fs;
-}
-
-/*!
- * \brief the core of all waitstream() functions
- */
-static int waitstream_core(struct ast_channel *c, const char *breakon,
- const char *forward, const char *rewind, int skip_ms,
- int audiofd, int cmdfd, const char *context)
-{
- const char *orig_chan_name = NULL;
- int err = 0;
-
- if (!breakon)
- breakon = "";
- if (!forward)
- forward = "";
- if (!rewind)
- rewind = "";
-
- /* Switch the channel to end DTMF frame only. waitstream_core doesn't care about the start of DTMF. */
- ast_set_flag(c, AST_FLAG_END_DTMF_ONLY);
-
- if (ast_test_flag(c, AST_FLAG_MASQ_NOSTREAM))
- orig_chan_name = ast_strdupa(c->name);
-
- while (c->stream) {
- int res;
- int ms;
-
- if (orig_chan_name && strcasecmp(orig_chan_name, c->name)) {
- ast_stopstream(c);
- err = 1;
- break;
- }
-
- ms = ast_sched_wait(c->sched);
-
- if (ms < 0 && !c->timingfunc) {
- ast_stopstream(c);
- break;
- }
- if (ms < 0)
- ms = 1000;
- if (cmdfd < 0) {
- res = ast_waitfor(c, ms);
- if (res < 0) {
- ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return res;
- }
- } else {
- int outfd;
- struct ast_channel *rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
- if (!rchan && (outfd < 0) && (ms)) {
- /* Continue */
- if (errno == EINTR)
- continue;
- ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return -1;
- } else if (outfd > -1) { /* this requires cmdfd set */
- /* The FD we were watching has something waiting */
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return 1;
- }
- /* if rchan is set, it is 'c' */
- res = rchan ? 1 : 0; /* map into 'res' values */
- }
- if (res > 0) {
- struct ast_frame *fr = ast_read(c);
- if (!fr) {
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return -1;
- }
- switch(fr->frametype) {
- case AST_FRAME_DTMF_END:
- if (context) {
- const char exten[2] = { fr->subclass, '\0' };
- if (ast_exists_extension(c, context, exten, 1, c->cid.cid_num)) {
- res = fr->subclass;
- ast_frfree(fr);
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return res;
- }
- } else {
- res = fr->subclass;
- if (strchr(forward,res)) {
- ast_stream_fastforward(c->stream, skip_ms);
- } else if (strchr(rewind,res)) {
- ast_stream_rewind(c->stream, skip_ms);
- } else if (strchr(breakon, res)) {
- ast_frfree(fr);
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return res;
- }
- }
- break;
- case AST_FRAME_CONTROL:
- switch(fr->subclass) {
- case AST_CONTROL_HANGUP:
- case AST_CONTROL_BUSY:
- case AST_CONTROL_CONGESTION:
- ast_frfree(fr);
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
- return -1;
- case AST_CONTROL_RINGING:
- case AST_CONTROL_ANSWER:
- case AST_CONTROL_VIDUPDATE:
- case AST_CONTROL_SRCUPDATE:
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
- /* Unimportant */
- break;
- default:
- ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
- }
- break;
- case AST_FRAME_VOICE:
- /* Write audio if appropriate */
- if (audiofd > -1) {
- if (write(audiofd, fr->data, fr->datalen) < 0) {
- ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
- }
- }
- default:
- /* Ignore all others */
- break;
- }
- ast_frfree(fr);
- }
- ast_sched_runq(c->sched);
- }
-
- ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
-
- return (err || c->_softhangup) ? -1 : 0;
-}
-
-int ast_waitstream_fr(struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int ms)
-{
- return waitstream_core(c, breakon, forward, rewind, ms,
- -1 /* no audiofd */, -1 /* no cmdfd */, NULL /* no context */);
-}
-
-int ast_waitstream(struct ast_channel *c, const char *breakon)
-{
- return waitstream_core(c, breakon, NULL, NULL, 0, -1, -1, NULL);
-}
-
-int ast_waitstream_full(struct ast_channel *c, const char *breakon, int audiofd, int cmdfd)
-{
- return waitstream_core(c, breakon, NULL, NULL, 0,
- audiofd, cmdfd, NULL /* no context */);
-}
-
-int ast_waitstream_exten(struct ast_channel *c, const char *context)
-{
- /* Waitstream, with return in the case of a valid 1 digit extension */
- /* in the current or specified context being pressed */
-
- if (!context)
- context = c->context;
- return waitstream_core(c, NULL, NULL, NULL, 0,
- -1, -1, context);
-}
-
-void ast_filestream_frame_freed(struct ast_frame *fr)
-{
- struct ast_filestream *fs;
-
- ast_clear_flag(fr, AST_FRFLAG_FROM_FILESTREAM);
-
- fs = (struct ast_filestream *) (((char *) fr) - offsetof(struct ast_filestream, fr));
-
- ao2_ref(fs, -1);
-}
-
-/*
- * if the file name is non-empty, try to play it.
- * Return 0 if success, -1 if error, digit if interrupted by a digit.
- * If digits == "" then we can simply check for non-zero.
- */
-int ast_stream_and_wait(struct ast_channel *chan, const char *file,
- const char *language, const char *digits)
-{
- int res = 0;
- if (!ast_strlen_zero(file)) {
- res = ast_streamfile(chan, file, language);
- if (!res)
- res = ast_waitstream(chan, digits);
- }
- return res;
-}
-
-static int show_file_formats(int fd, int argc, char *argv[])
-{
-#define FORMAT "%-10s %-10s %-20s\n"
-#define FORMAT2 "%-10s %-10s %-20s\n"
- struct ast_format *f;
- int count_fmt = 0;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- ast_cli(fd, FORMAT, "Format", "Name", "Extensions");
-
- if (AST_LIST_LOCK(&formats)) {
- ast_log(LOG_WARNING, "Unable to lock format list\n");
- return -1;
- }
-
- AST_LIST_TRAVERSE(&formats, f, list) {
- ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts);
- count_fmt++;
- }
- AST_LIST_UNLOCK(&formats);
- ast_cli(fd, "%d file formats registered.\n", count_fmt);
- return RESULT_SUCCESS;
-#undef FORMAT
-#undef FORMAT2
-}
-
-static int show_file_formats_deprecated(int fd, int argc, char *argv[])
-{
-#define FORMAT "%-10s %-10s %-20s\n"
-#define FORMAT2 "%-10s %-10s %-20s\n"
- struct ast_format *f;
- int count_fmt = 0;
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_cli(fd, FORMAT, "Format", "Name", "Extensions");
-
- if (AST_LIST_LOCK(&formats)) {
- ast_log(LOG_WARNING, "Unable to lock format list\n");
- return -1;
- }
-
- AST_LIST_TRAVERSE(&formats, f, list) {
- ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts);
- count_fmt++;
- }
- AST_LIST_UNLOCK(&formats);
- ast_cli(fd, "%d file formats registered.\n", count_fmt);
- return RESULT_SUCCESS;
-#undef FORMAT
-#undef FORMAT2
-}
-
-char show_file_formats_usage[] =
-"Usage: core show file formats\n"
-" Displays currently registered file formats (if any)\n";
-
-struct ast_cli_entry cli_show_file_formats_deprecated = {
- { "show", "file", "formats" },
- show_file_formats_deprecated, NULL,
- NULL };
-
-struct ast_cli_entry cli_file[] = {
- { { "core", "show", "file", "formats" },
- show_file_formats, "Displays file formats",
- show_file_formats_usage, NULL, &cli_show_file_formats_deprecated },
-};
-
-int ast_file_init(void)
-{
- ast_cli_register_multiple(cli_file, sizeof(cli_file) / sizeof(struct ast_cli_entry));
- return 0;
-}
diff --git a/main/fixedjitterbuf.c b/main/fixedjitterbuf.c
deleted file mode 100644
index 1d7a5cc30..000000000
--- a/main/fixedjitterbuf.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (C) 2005, Attractel OOD
- *
- * Contributors:
- * Slav Klenov <slav@securax.org>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- *
- * A license has been granted to Digium (via disclaimer) for the use of
- * this code.
- */
-
-/*! \file
- *
- * \brief Jitterbuffering algorithm.
- *
- * \author Slav Klenov <slav@securax.org>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "asterisk/utils.h"
-#include "fixedjitterbuf.h"
-
-#undef FIXED_JB_DEBUG
-
-#ifdef FIXED_JB_DEBUG
-#define ASSERT(a)
-#else
-#define ASSERT(a) assert(a)
-#endif
-
-/*! \brief private fixed_jb structure */
-struct fixed_jb
-{
- struct fixed_jb_frame *frames;
- struct fixed_jb_frame *tail;
- struct fixed_jb_conf conf;
- long rxcore;
- long delay;
- long next_delivery;
- int force_resynch;
-};
-
-
-static struct fixed_jb_frame *alloc_jb_frame(struct fixed_jb *jb);
-static void release_jb_frame(struct fixed_jb *jb, struct fixed_jb_frame *frame);
-static void get_jb_head(struct fixed_jb *jb, struct fixed_jb_frame *frame);
-static int resynch_jb(struct fixed_jb *jb, void *data, long ms, long ts, long now);
-
-static inline struct fixed_jb_frame *alloc_jb_frame(struct fixed_jb *jb)
-{
- return ast_calloc(1, sizeof(struct fixed_jb_frame));
-}
-
-static inline void release_jb_frame(struct fixed_jb *jb, struct fixed_jb_frame *frame)
-{
- free(frame);
-}
-
-static void get_jb_head(struct fixed_jb *jb, struct fixed_jb_frame *frame)
-{
- struct fixed_jb_frame *fr;
-
- /* unlink the frame */
- fr = jb->frames;
- jb->frames = fr->next;
- if (jb->frames) {
- jb->frames->prev = NULL;
- } else {
- /* the jb is empty - update tail */
- jb->tail = NULL;
- }
-
- /* update next */
- jb->next_delivery = fr->delivery + fr->ms;
-
- /* copy the destination */
- memcpy(frame, fr, sizeof(struct fixed_jb_frame));
-
- /* and release the frame */
- release_jb_frame(jb, fr);
-}
-
-
-struct fixed_jb *fixed_jb_new(struct fixed_jb_conf *conf)
-{
- struct fixed_jb *jb;
-
- if (!(jb = ast_calloc(1, sizeof(*jb))))
- return NULL;
-
- /* First copy our config */
- memcpy(&jb->conf, conf, sizeof(struct fixed_jb_conf));
-
- /* we dont need the passed config anymore - continue working with the saved one */
- conf = &jb->conf;
-
- /* validate the configuration */
- if (conf->jbsize < 1)
- conf->jbsize = FIXED_JB_SIZE_DEFAULT;
-
- if (conf->resync_threshold < 1)
- conf->resync_threshold = FIXED_JB_RESYNCH_THRESHOLD_DEFAULT;
-
- /* Set the constant delay to the jitterbuf */
- jb->delay = conf->jbsize;
-
- return jb;
-}
-
-
-void fixed_jb_destroy(struct fixed_jb *jb)
-{
- /* jitterbuf MUST be empty before it can be destroyed */
- ASSERT(jb->frames == NULL);
-
- free(jb);
-}
-
-
-static int resynch_jb(struct fixed_jb *jb, void *data, long ms, long ts, long now)
-{
- long diff, offset;
- struct fixed_jb_frame *frame;
-
- /* If jb is empty, just reinitialize the jb */
- if (!jb->frames) {
- /* debug check: tail should also be NULL */
- ASSERT(jb->tail == NULL);
-
- return fixed_jb_put_first(jb, data, ms, ts, now);
- }
-
- /* Adjust all jb state just as the new frame is with delivery = the delivery of the last
- frame (e.g. this one with max delivery) + the length of the last frame. */
-
- /* Get the diff in timestamps */
- diff = ts - jb->tail->ts;
-
- /* Ideally this should be just the length of the last frame. The deviation is the desired
- offset */
- offset = diff - jb->tail->ms;
-
- /* Do we really need to resynch, or this is just a frame for dropping? */
- if (!jb->force_resynch && (offset < jb->conf.resync_threshold && offset > -jb->conf.resync_threshold))
- return FIXED_JB_DROP;
-
- /* Reset the force resynch flag */
- jb->force_resynch = 0;
-
- /* apply the offset to the jb state */
- jb->rxcore -= offset;
- frame = jb->frames;
- while (frame) {
- frame->ts += offset;
- frame = frame->next;
- }
-
- /* now jb_put() should add the frame at a last position */
- return fixed_jb_put(jb, data, ms, ts, now);
-}
-
-
-void fixed_jb_set_force_resynch(struct fixed_jb *jb)
-{
- jb->force_resynch = 1;
-}
-
-
-int fixed_jb_put_first(struct fixed_jb *jb, void *data, long ms, long ts, long now)
-{
- /* this is our first frame - set the base of the receivers time */
- jb->rxcore = now - ts;
-
- /* init next for a first time - it should be the time the first frame should be played */
- jb->next_delivery = now + jb->delay;
-
- /* put the frame */
- return fixed_jb_put(jb, data, ms, ts, now);
-}
-
-
-int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now)
-{
- struct fixed_jb_frame *frame, *next, *newframe;
- long delivery;
-
- /* debug check the validity of the input params */
- ASSERT(data != NULL);
- /* do not allow frames shorter than 2 ms */
- ASSERT(ms >= 2);
- ASSERT(ts >= 0);
- ASSERT(now >= 0);
-
- delivery = jb->rxcore + jb->delay + ts;
-
- /* check if the new frame is not too late */
- if (delivery < jb->next_delivery) {
- /* should drop the frame, but let first resynch_jb() check if this is not a jump in ts, or
- the force resynch flag was not set. */
- return resynch_jb(jb, data, ms, ts, now);
- }
-
- /* what if the delivery time is bigger than next + delay? Seems like a frame for the future.
- However, allow more resync_threshold ms in advance */
- if (delivery > jb->next_delivery + jb->delay + jb->conf.resync_threshold) {
- /* should drop the frame, but let first resynch_jb() check if this is not a jump in ts, or
- the force resynch flag was not set. */
- return resynch_jb(jb, data, ms, ts, now);
- }
-
- /* find the right place in the frames list, sorted by delivery time */
- frame = jb->tail;
- while (frame && frame->delivery > delivery) {
- frame = frame->prev;
- }
-
- /* Check if the new delivery time is not covered already by the chosen frame */
- if (frame && (frame->delivery == delivery ||
- delivery < frame->delivery + frame->ms ||
- (frame->next && delivery + ms > frame->next->delivery)))
- {
- /* TODO: Should we check for resynch here? Be careful to do not allow threshold smaller than
- the size of the jb */
-
- /* should drop the frame, but let first resynch_jb() check if this is not a jump in ts, or
- the force resynch flag was not set. */
- return resynch_jb(jb, data, ms, ts, now);
- }
-
- /* Reset the force resynch flag */
- jb->force_resynch = 0;
-
- /* Get a new frame */
- newframe = alloc_jb_frame(jb);
- newframe->data = data;
- newframe->ts = ts;
- newframe->ms = ms;
- newframe->delivery = delivery;
-
- /* and insert it right on place */
- if (frame) {
- next = frame->next;
- frame->next = newframe;
- if (next) {
- newframe->next = next;
- next->prev = newframe;
- } else {
- /* insert after the last frame - should update tail */
- jb->tail = newframe;
- newframe->next = NULL;
- }
- newframe->prev = frame;
-
- return FIXED_JB_OK;
- } else if (!jb->frames) {
- /* the frame list is empty or thats just the first frame ever */
- /* tail should also be NULL is that case */
- ASSERT(jb->tail == NULL);
- jb->frames = jb->tail = newframe;
- newframe->next = NULL;
- newframe->prev = NULL;
-
- return FIXED_JB_OK;
- } else {
- /* insert on a first position - should update frames head */
- newframe->next = jb->frames;
- newframe->prev = NULL;
- jb->frames->prev = newframe;
- jb->frames = newframe;
-
- return FIXED_JB_OK;
- }
-}
-
-
-int fixed_jb_get(struct fixed_jb *jb, struct fixed_jb_frame *frame, long now, long interpl)
-{
- ASSERT(now >= 0);
- ASSERT(interpl >= 2);
-
- if (now < jb->next_delivery) {
- /* too early for the next frame */
- return FIXED_JB_NOFRAME;
- }
-
- /* Is the jb empty? */
- if (!jb->frames) {
- /* should interpolate a frame */
- /* update next */
- jb->next_delivery += interpl;
-
- return FIXED_JB_INTERP;
- }
-
- /* Isn't it too late for the first frame available in the jb? */
- if (now > jb->frames->delivery + jb->frames->ms) {
- /* yes - should drop this frame and update next to point the next frame (get_jb_head() does it) */
- get_jb_head(jb, frame);
-
- return FIXED_JB_DROP;
- }
-
- /* isn't it too early to play the first frame available? */
- if (now < jb->frames->delivery) {
- /* yes - should interpolate one frame */
- /* update next */
- jb->next_delivery += interpl;
-
- return FIXED_JB_INTERP;
- }
-
- /* we have a frame for playing now (get_jb_head() updates next) */
- get_jb_head(jb, frame);
-
- return FIXED_JB_OK;
-}
-
-
-long fixed_jb_next(struct fixed_jb *jb)
-{
- return jb->next_delivery;
-}
-
-
-int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout)
-{
- if (!jb->frames)
- return FIXED_JB_NOFRAME;
-
- get_jb_head(jb, frameout);
-
- return FIXED_JB_OK;
-}
diff --git a/main/fixedjitterbuf.h b/main/fixedjitterbuf.h
deleted file mode 100644
index 868e24b66..000000000
--- a/main/fixedjitterbuf.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2005, Attractel OOD
- *
- * Contributors:
- * Slav Klenov <slav@securax.org>
- *
- * Copyright on this file is disclaimed to Digium for inclusion in Asterisk
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Jitterbuffering algorithm.
- *
- */
-
-#ifndef _FIXEDJITTERBUF_H_
-#define _FIXEDJITTERBUF_H_
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-
-/* return codes */
-enum {
- FIXED_JB_OK,
- FIXED_JB_DROP,
- FIXED_JB_INTERP,
- FIXED_JB_NOFRAME
-};
-
-
-/* defaults */
-#define FIXED_JB_SIZE_DEFAULT 200
-#define FIXED_JB_RESYNCH_THRESHOLD_DEFAULT 1000
-
-
-/* jb configuration properties */
-struct fixed_jb_conf
-{
- long jbsize;
- long resync_threshold;
-};
-
-
-struct fixed_jb_frame
-{
- void *data;
- long ts;
- long ms;
- long delivery;
- struct fixed_jb_frame *next;
- struct fixed_jb_frame *prev;
-};
-
-
-struct fixed_jb;
-
-
-/* jb interface */
-
-struct fixed_jb * fixed_jb_new(struct fixed_jb_conf *conf);
-
-void fixed_jb_destroy(struct fixed_jb *jb);
-
-int fixed_jb_put_first(struct fixed_jb *jb, void *data, long ms, long ts, long now);
-
-int fixed_jb_put(struct fixed_jb *jb, void *data, long ms, long ts, long now);
-
-int fixed_jb_get(struct fixed_jb *jb, struct fixed_jb_frame *frame, long now, long interpl);
-
-long fixed_jb_next(struct fixed_jb *jb);
-
-int fixed_jb_remove(struct fixed_jb *jb, struct fixed_jb_frame *frameout);
-
-void fixed_jb_set_force_resynch(struct fixed_jb *jb);
-
-#if defined(__cplusplus) || defined(c_plusplus)
-}
-#endif
-
-#endif /* _FIXEDJITTERBUF_H_ */
diff --git a/main/frame.c b/main/frame.c
deleted file mode 100644
index b73782096..000000000
--- a/main/frame.c
+++ /dev/null
@@ -1,1607 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Frame and codec manipulation routines
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include "asterisk/lock.h"
-#include "asterisk/frame.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/channel.h"
-#include "asterisk/cli.h"
-#include "asterisk/term.h"
-#include "asterisk/utils.h"
-#include "asterisk/threadstorage.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/translate.h"
-#include "asterisk/dsp.h"
-#include "asterisk/file.h"
-
-#ifdef TRACE_FRAMES
-static int headers;
-static AST_LIST_HEAD_STATIC(headerlist, ast_frame);
-#endif
-
-#if !defined(LOW_MEMORY)
-static void frame_cache_cleanup(void *data);
-
-/*! \brief A per-thread cache of frame headers */
-AST_THREADSTORAGE_CUSTOM(frame_cache, frame_cache_init, frame_cache_cleanup);
-
-/*!
- * \brief Maximum ast_frame cache size
- *
- * In most cases where the frame header cache will be useful, the size
- * of the cache will stay very small. However, it is not always the case that
- * the same thread that allocates the frame will be the one freeing them, so
- * sometimes a thread will never have any frames in its cache, or the cache
- * will never be pulled from. For the latter case, we limit the maximum size.
- */
-#define FRAME_CACHE_MAX_SIZE 10
-
-/*! \brief This is just so ast_frames, a list head struct for holding a list of
- * ast_frame structures, is defined. */
-AST_LIST_HEAD_NOLOCK(ast_frames, ast_frame);
-
-struct ast_frame_cache {
- struct ast_frames list;
- size_t size;
-};
-#endif
-
-#define SMOOTHER_SIZE 8000
-
-enum frame_type {
- TYPE_HIGH, /* 0x0 */
- TYPE_LOW, /* 0x1 */
- TYPE_SILENCE, /* 0x2 */
- TYPE_DONTSEND /* 0x3 */
-};
-
-#define TYPE_MASK 0x3
-
-struct ast_smoother {
- int size;
- int format;
- int readdata;
- int optimizablestream;
- int flags;
- float samplesperbyte;
- struct ast_frame f;
- struct timeval delivery;
- char data[SMOOTHER_SIZE];
- char framedata[SMOOTHER_SIZE + AST_FRIENDLY_OFFSET];
- struct ast_frame *opt;
- int len;
-};
-
-/*! \brief Definition of supported media formats (codecs) */
-static struct ast_format_list AST_FORMAT_LIST[] = { /*!< Bit number: comment - Bit numbers are hard coded in show_codec() */
- { 1, AST_FORMAT_G723_1 , "g723" , "G.723.1", 24, 30, 300, 30, 30 }, /*!< 1 */
- { 1, AST_FORMAT_GSM, "gsm" , "GSM", 33, 20, 300, 20, 20 }, /*!< 2: codec_gsm.c */
- { 1, AST_FORMAT_ULAW, "ulaw", "G.711 u-law", 80, 10, 150, 10, 20 }, /*!< 3: codec_ulaw.c */
- { 1, AST_FORMAT_ALAW, "alaw", "G.711 A-law", 80, 10, 150, 10, 20 }, /*!< 4: codec_alaw.c */
- { 1, AST_FORMAT_G726, "g726", "G.726 RFC3551", 40, 10, 300, 10, 20 }, /*!< 5: codec_g726.c */
- { 1, AST_FORMAT_ADPCM, "adpcm" , "ADPCM", 40, 10, 300, 10, 20 }, /*!< 6: codec_adpcm.c */
- { 1, AST_FORMAT_SLINEAR, "slin", "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< 7 */
- { 1, AST_FORMAT_LPC10, "lpc10", "LPC10", 7, 20, 20, 20, 20 }, /*!< 8: codec_lpc10.c */
- { 1, AST_FORMAT_G729A, "g729", "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!< 9: Binary commercial distribution */
- { 1, AST_FORMAT_SPEEX, "speex", "SpeeX", 10, 10, 60, 10, 20 }, /*!< 10: codec_speex.c */
- { 1, AST_FORMAT_ILBC, "ilbc", "iLBC", 50, 30, 30, 30, 30 }, /*!< 11: codec_ilbc.c */ /* inc=30ms - workaround */
- { 1, AST_FORMAT_G726_AAL2, "g726aal2", "G.726 AAL2", 40, 10, 300, 10, 20 }, /*!< 12: codec_g726.c */
- { 1, AST_FORMAT_G722, "g722", "G722"}, /*!< 13 */
- { 0, 0, "nothing", "undefined" },
- { 0, 0, "nothing", "undefined" },
- { 0, 0, "nothing", "undefined" },
- { 0, 0, "nothing", "undefined" },
- { 0, AST_FORMAT_MAX_AUDIO, "maxaudio", "Maximum audio format" },
- { 1, AST_FORMAT_JPEG, "jpeg", "JPEG image"}, /*!< 17: See format_jpeg.c */
- { 1, AST_FORMAT_PNG, "png", "PNG image"}, /*!< 18: Image format */
- { 1, AST_FORMAT_H261, "h261", "H.261 Video" }, /*!< 19: Video Passthrough */
- { 1, AST_FORMAT_H263, "h263", "H.263 Video" }, /*!< 20: Passthrough support, see format_h263.c */
- { 1, AST_FORMAT_H263_PLUS, "h263p", "H.263+ Video" }, /*!< 21: See format_h263.c */
- { 1, AST_FORMAT_H264, "h264", "H.264 Video" }, /*!< 22: Passthrough support, see format_h263.c */
- { 0, 0, "nothing", "undefined" },
- { 0, 0, "nothing", "undefined" },
- { 0, 0, "nothing", "undefined" },
- { 0, AST_FORMAT_MAX_VIDEO, "maxvideo", "Maximum video format" },
-};
-
-struct ast_frame ast_null_frame = { AST_FRAME_NULL, };
-
-void ast_smoother_reset(struct ast_smoother *s, int size)
-{
- memset(s, 0, sizeof(*s));
- s->size = size;
-}
-
-struct ast_smoother *ast_smoother_new(int size)
-{
- struct ast_smoother *s;
- if (size < 1)
- return NULL;
- if ((s = ast_malloc(sizeof(*s))))
- ast_smoother_reset(s, size);
- return s;
-}
-
-int ast_smoother_get_flags(struct ast_smoother *s)
-{
- return s->flags;
-}
-
-void ast_smoother_set_flags(struct ast_smoother *s, int flags)
-{
- s->flags = flags;
-}
-
-int ast_smoother_test_flag(struct ast_smoother *s, int flag)
-{
- return (s->flags & flag);
-}
-
-int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
-{
- if (f->frametype != AST_FRAME_VOICE) {
- ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
- return -1;
- }
- if (!s->format) {
- s->format = f->subclass;
- s->samplesperbyte = (float)f->samples / (float)f->datalen;
- } else if (s->format != f->subclass) {
- ast_log(LOG_WARNING, "Smoother was working on %d format frames, now trying to feed %d?\n", s->format, f->subclass);
- return -1;
- }
- if (s->len + f->datalen > SMOOTHER_SIZE) {
- ast_log(LOG_WARNING, "Out of smoother space\n");
- return -1;
- }
- if (((f->datalen == s->size) || ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729)))
- && !s->opt && (f->offset >= AST_MIN_OFFSET)) {
- if (!s->len) {
- /* Optimize by sending the frame we just got
- on the next read, thus eliminating the douple
- copy */
- if (swap)
- ast_swapcopy_samples(f->data, f->data, f->samples);
- s->opt = f;
- return 0;
- }
- }
- if (s->flags & AST_SMOOTHER_FLAG_G729) {
- if (s->len % 10) {
- ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
- return 0;
- }
- }
- if (swap)
- ast_swapcopy_samples(s->data+s->len, f->data, f->samples);
- else
- memcpy(s->data + s->len, f->data, f->datalen);
- /* If either side is empty, reset the delivery time */
- if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) /* XXX really ? */
- s->delivery = f->delivery;
- s->len += f->datalen;
- return 0;
-}
-
-struct ast_frame *ast_smoother_read(struct ast_smoother *s)
-{
- struct ast_frame *opt;
- int len;
-
- /* IF we have an optimization frame, send it */
- if (s->opt) {
- if (s->opt->offset < AST_FRIENDLY_OFFSET)
- ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
- s->opt->offset);
- opt = s->opt;
- s->opt = NULL;
- return opt;
- }
-
- /* Make sure we have enough data */
- if (s->len < s->size) {
- /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
- if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->size % 10)))
- return NULL;
- }
- len = s->size;
- if (len > s->len)
- len = s->len;
- /* Make frame */
- s->f.frametype = AST_FRAME_VOICE;
- s->f.subclass = s->format;
- s->f.data = s->framedata + AST_FRIENDLY_OFFSET;
- s->f.offset = AST_FRIENDLY_OFFSET;
- s->f.datalen = len;
- /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
- s->f.samples = len * s->samplesperbyte; /* XXX rounding */
- s->f.delivery = s->delivery;
- /* Fill Data */
- memcpy(s->f.data, s->data, len);
- s->len -= len;
- /* Move remaining data to the front if applicable */
- if (s->len) {
- /* In principle this should all be fine because if we are sending
- G.729 VAD, the next timestamp will take over anyawy */
- memmove(s->data, s->data + len, s->len);
- if (!ast_tvzero(s->delivery)) {
- /* If we have delivery time, increment it, otherwise, leave it at 0 */
- s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
- }
- }
- /* Return frame */
- return &s->f;
-}
-
-void ast_smoother_free(struct ast_smoother *s)
-{
- free(s);
-}
-
-static struct ast_frame *ast_frame_header_new(void)
-{
- struct ast_frame *f;
-
-#if !defined(LOW_MEMORY)
- struct ast_frame_cache *frames;
-
- if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
- if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
- size_t mallocd_len = f->mallocd_hdr_len;
- memset(f, 0, sizeof(*f));
- f->mallocd_hdr_len = mallocd_len;
- f->mallocd = AST_MALLOCD_HDR;
- frames->size--;
- return f;
- }
- }
- if (!(f = ast_calloc_cache(1, sizeof(*f))))
- return NULL;
-#else
- if (!(f = ast_calloc(1, sizeof(*f))))
- return NULL;
-#endif
-
- f->mallocd_hdr_len = sizeof(*f);
-#ifdef TRACE_FRAMES
- AST_LIST_LOCK(&headerlist);
- headers++;
- AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
- AST_LIST_UNLOCK(&headerlist);
-#endif
-
- return f;
-}
-
-#if !defined(LOW_MEMORY)
-static void frame_cache_cleanup(void *data)
-{
- struct ast_frame_cache *frames = data;
- struct ast_frame *f;
-
- while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
- free(f);
-
- free(frames);
-}
-#endif
-
-void ast_frame_free(struct ast_frame *fr, int cache)
-{
- if (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR)) {
- ast_translate_frame_freed(fr);
- } else if (ast_test_flag(fr, AST_FRFLAG_FROM_DSP)) {
- ast_dsp_frame_freed(fr);
- } else if (ast_test_flag(fr, AST_FRFLAG_FROM_FILESTREAM)) {
- ast_filestream_frame_freed(fr);
- }
-
- if (!fr->mallocd)
- return;
-
-#if !defined(LOW_MEMORY)
- if (cache && fr->mallocd == AST_MALLOCD_HDR) {
- /* Cool, only the header is malloc'd, let's just cache those for now
- * to keep things simple... */
- struct ast_frame_cache *frames;
-
- if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))
- && frames->size < FRAME_CACHE_MAX_SIZE) {
- AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
- frames->size++;
- return;
- }
- }
-#endif
-
- if (fr->mallocd & AST_MALLOCD_DATA) {
- if (fr->data)
- free(fr->data - fr->offset);
- }
- if (fr->mallocd & AST_MALLOCD_SRC) {
- if (fr->src)
- free((char *)fr->src);
- }
- if (fr->mallocd & AST_MALLOCD_HDR) {
-#ifdef TRACE_FRAMES
- AST_LIST_LOCK(&headerlist);
- headers--;
- AST_LIST_REMOVE(&headerlist, fr, frame_list);
- AST_LIST_UNLOCK(&headerlist);
-#endif
- free(fr);
- }
-}
-
-/*!
- * \brief 'isolates' a frame by duplicating non-malloc'ed components
- * (header, src, data).
- * On return all components are malloc'ed
- */
-struct ast_frame *ast_frisolate(struct ast_frame *fr)
-{
- struct ast_frame *out;
- void *newdata;
-
- ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
- ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
-
- if (!(fr->mallocd & AST_MALLOCD_HDR)) {
- /* Allocate a new header if needed */
- if (!(out = ast_frame_header_new()))
- return NULL;
- out->frametype = fr->frametype;
- out->subclass = fr->subclass;
- out->datalen = fr->datalen;
- out->samples = fr->samples;
- out->offset = fr->offset;
- out->data = fr->data;
- /* Copy the timing data */
- ast_copy_flags(out, fr, AST_FRFLAG_HAS_TIMING_INFO);
- if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
- out->ts = fr->ts;
- out->len = fr->len;
- out->seqno = fr->seqno;
- }
- } else
- out = fr;
-
- if (!(fr->mallocd & AST_MALLOCD_SRC)) {
- if (fr->src) {
- if (!(out->src = ast_strdup(fr->src))) {
- if (out != fr)
- free(out);
- return NULL;
- }
- }
- } else
- out->src = fr->src;
-
- if (!(fr->mallocd & AST_MALLOCD_DATA)) {
- if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
- if (out->src != fr->src)
- free((void *) out->src);
- if (out != fr)
- free(out);
- return NULL;
- }
- newdata += AST_FRIENDLY_OFFSET;
- out->offset = AST_FRIENDLY_OFFSET;
- out->datalen = fr->datalen;
- memcpy(newdata, fr->data, fr->datalen);
- out->data = newdata;
- }
-
- out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
-
- return out;
-}
-
-struct ast_frame *ast_frdup(const struct ast_frame *f)
-{
- struct ast_frame *out = NULL;
- int len, srclen = 0;
- void *buf = NULL;
-
-#if !defined(LOW_MEMORY)
- struct ast_frame_cache *frames;
-#endif
-
- /* Start with standard stuff */
- len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
- /* If we have a source, add space for it */
- /*
- * XXX Watch out here - if we receive a src which is not terminated
- * properly, we can be easily attacked. Should limit the size we deal with.
- */
- if (f->src)
- srclen = strlen(f->src);
- if (srclen > 0)
- len += srclen + 1;
-
-#if !defined(LOW_MEMORY)
- if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
- AST_LIST_TRAVERSE_SAFE_BEGIN(&frames->list, out, frame_list) {
- if (out->mallocd_hdr_len >= len) {
- size_t mallocd_len = out->mallocd_hdr_len;
- AST_LIST_REMOVE_CURRENT(&frames->list, frame_list);
- memset(out, 0, sizeof(*out));
- out->mallocd_hdr_len = mallocd_len;
- buf = out;
- frames->size--;
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- }
-#endif
-
- if (!buf) {
- if (!(buf = ast_calloc_cache(1, len)))
- return NULL;
- out = buf;
- out->mallocd_hdr_len = len;
- }
-
- out->frametype = f->frametype;
- out->subclass = f->subclass;
- out->datalen = f->datalen;
- out->samples = f->samples;
- out->delivery = f->delivery;
- /* Set us as having malloc'd header only, so it will eventually
- get freed. */
- out->mallocd = AST_MALLOCD_HDR;
- out->offset = AST_FRIENDLY_OFFSET;
- if (out->datalen) {
- out->data = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
- memcpy(out->data, f->data, out->datalen);
- }
- if (srclen > 0) {
- /* This may seem a little strange, but it's to avoid a gcc (4.2.4) compiler warning */
- char *src;
- out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
- src = (char *) out->src;
- /* Must have space since we allocated for it */
- strcpy(src, f->src);
- }
- ast_copy_flags(out, f, AST_FRFLAG_HAS_TIMING_INFO);
- out->ts = f->ts;
- out->len = f->len;
- out->seqno = f->seqno;
- return out;
-}
-
-void ast_swapcopy_samples(void *dst, const void *src, int samples)
-{
- int i;
- unsigned short *dst_s = dst;
- const unsigned short *src_s = src;
-
- for (i = 0; i < samples; i++)
- dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
-}
-
-
-struct ast_format_list *ast_get_format_list_index(int index)
-{
- return &AST_FORMAT_LIST[index];
-}
-
-struct ast_format_list *ast_get_format_list(size_t *size)
-{
- *size = (sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]));
- return AST_FORMAT_LIST;
-}
-
-char* ast_getformatname(int format)
-{
- int x;
- char *ret = "unknown";
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == format) {
- ret = AST_FORMAT_LIST[x].name;
- break;
- }
- }
- return ret;
-}
-
-char *ast_getformatname_multiple(char *buf, size_t size, int format)
-{
- int x;
- unsigned len;
- char *start, *end = buf;
-
- if (!size)
- return buf;
- snprintf(end, size, "0x%x (", format);
- len = strlen(end);
- end += len;
- size -= len;
- start = end;
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if (AST_FORMAT_LIST[x].visible && (AST_FORMAT_LIST[x].bits & format)) {
- snprintf(end, size,"%s|",AST_FORMAT_LIST[x].name);
- len = strlen(end);
- end += len;
- size -= len;
- }
- }
- if (start == end)
- snprintf(start, size, "nothing)");
- else if (size > 1)
- *(end -1) = ')';
- return buf;
-}
-
-static struct ast_codec_alias_table {
- char *alias;
- char *realname;
-} ast_codec_alias_table[] = {
- { "slinear", "slin"},
- { "g723.1", "g723"},
-};
-
-static const char *ast_expand_codec_alias(const char *in)
-{
- int x;
-
- for (x = 0; x < sizeof(ast_codec_alias_table) / sizeof(ast_codec_alias_table[0]); x++) {
- if(!strcmp(in,ast_codec_alias_table[x].alias))
- return ast_codec_alias_table[x].realname;
- }
- return in;
-}
-
-int ast_getformatbyname(const char *name)
-{
- int x, all, format = 0;
-
- all = strcasecmp(name, "all") ? 0 : 1;
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if(AST_FORMAT_LIST[x].visible && (all ||
- !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
- !strcasecmp(AST_FORMAT_LIST[x].name,ast_expand_codec_alias(name)))) {
- format |= AST_FORMAT_LIST[x].bits;
- if(!all)
- break;
- }
- }
-
- return format;
-}
-
-char *ast_codec2str(int codec)
-{
- int x;
- char *ret = "unknown";
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if(AST_FORMAT_LIST[x].visible && AST_FORMAT_LIST[x].bits == codec) {
- ret = AST_FORMAT_LIST[x].desc;
- break;
- }
- }
- return ret;
-}
-
-static int show_codecs_deprecated(int fd, int argc, char *argv[])
-{
- int i, found=0;
- char hex[25];
-
- if ((argc < 2) || (argc > 3))
- return RESULT_SHOWUSAGE;
-
- if (!ast_opt_dont_warn)
- ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
- "\tIt does not indicate anything about your configuration.\n");
-
- ast_cli(fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
- ast_cli(fd, "--------------------------------------------------------------------------------\n");
- if ((argc == 2) || (!strcasecmp(argv[1],"audio"))) {
- found = 1;
- for (i=0;i<13;i++) {
- snprintf(hex,25,"(0x%x)",1<<i);
- ast_cli(fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
- }
- }
-
- if ((argc == 2) || (!strcasecmp(argv[1],"image"))) {
- found = 1;
- for (i=16;i<18;i++) {
- snprintf(hex,25,"(0x%x)",1<<i);
- ast_cli(fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
- }
- }
-
- if ((argc == 2) || (!strcasecmp(argv[1],"video"))) {
- found = 1;
- for (i=18;i<22;i++) {
- snprintf(hex,25,"(0x%x)",1<<i);
- ast_cli(fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
- }
- }
-
- if (! found)
- return RESULT_SHOWUSAGE;
- else
- return RESULT_SUCCESS;
-}
-
-static int show_codecs(int fd, int argc, char *argv[])
-{
- int i, found=0;
- char hex[25];
-
- if ((argc < 3) || (argc > 4))
- return RESULT_SHOWUSAGE;
-
- if (!ast_opt_dont_warn)
- ast_cli(fd, "Disclaimer: this command is for informational purposes only.\n"
- "\tIt does not indicate anything about your configuration.\n");
-
- ast_cli(fd, "%11s %9s %10s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESC");
- ast_cli(fd, "--------------------------------------------------------------------------------\n");
- if ((argc == 3) || (!strcasecmp(argv[3],"audio"))) {
- found = 1;
- for (i=0;i<13;i++) {
- snprintf(hex,25,"(0x%x)",1<<i);
- ast_cli(fd, "%11u (1 << %2d) %10s audio %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
- }
- }
-
- if ((argc == 3) || (!strcasecmp(argv[3],"image"))) {
- found = 1;
- for (i=16;i<18;i++) {
- snprintf(hex,25,"(0x%x)",1<<i);
- ast_cli(fd, "%11u (1 << %2d) %10s image %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
- }
- }
-
- if ((argc == 3) || (!strcasecmp(argv[3],"video"))) {
- found = 1;
- for (i=18;i<22;i++) {
- snprintf(hex,25,"(0x%x)",1<<i);
- ast_cli(fd, "%11u (1 << %2d) %10s video %8s (%s)\n",1 << i,i,hex,ast_getformatname(1<<i),ast_codec2str(1<<i));
- }
- }
-
- if (! found)
- return RESULT_SHOWUSAGE;
- else
- return RESULT_SUCCESS;
-}
-
-static char frame_show_codecs_usage[] =
-"Usage: core show codecs [audio|video|image]\n"
-" Displays codec mapping\n";
-
-static int show_codec_n_deprecated(int fd, int argc, char *argv[])
-{
- int codec, i, found=0;
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
-
- if (sscanf(argv[2],"%d",&codec) != 1)
- return RESULT_SHOWUSAGE;
-
- for (i = 0; i < 32; i++)
- if (codec & (1 << i)) {
- found = 1;
- ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
- }
-
- if (!found)
- ast_cli(fd, "Codec %d not found\n", codec);
-
- return RESULT_SUCCESS;
-}
-
-static int show_codec_n(int fd, int argc, char *argv[])
-{
- int codec, i, found=0;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- if (sscanf(argv[3],"%d",&codec) != 1)
- return RESULT_SHOWUSAGE;
-
- for (i = 0; i < 32; i++)
- if (codec & (1 << i)) {
- found = 1;
- ast_cli(fd, "%11u (1 << %2d) %s\n",1 << i,i,ast_codec2str(1<<i));
- }
-
- if (!found)
- ast_cli(fd, "Codec %d not found\n", codec);
-
- return RESULT_SUCCESS;
-}
-
-static char frame_show_codec_n_usage[] =
-"Usage: core show codec <number>\n"
-" Displays codec mapping\n";
-
-/*! Dump a frame for debugging purposes */
-void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
-{
- const char noname[] = "unknown";
- char ftype[40] = "Unknown Frametype";
- char cft[80];
- char subclass[40] = "Unknown Subclass";
- char csub[80];
- char moreinfo[40] = "";
- char cn[60];
- char cp[40];
- char cmn[40];
-
- if (!name)
- name = noname;
-
-
- if (!f) {
- ast_verbose("%s [ %s (NULL) ] [%s]\n",
- term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
- term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
- term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
- return;
- }
- /* XXX We should probably print one each of voice and video when the format changes XXX */
- if (f->frametype == AST_FRAME_VOICE)
- return;
- if (f->frametype == AST_FRAME_VIDEO)
- return;
- switch(f->frametype) {
- case AST_FRAME_DTMF_BEGIN:
- strcpy(ftype, "DTMF Begin");
- subclass[0] = f->subclass;
- subclass[1] = '\0';
- break;
- case AST_FRAME_DTMF_END:
- strcpy(ftype, "DTMF End");
- subclass[0] = f->subclass;
- subclass[1] = '\0';
- break;
- case AST_FRAME_CONTROL:
- strcpy(ftype, "Control");
- switch(f->subclass) {
- case AST_CONTROL_HANGUP:
- strcpy(subclass, "Hangup");
- break;
- case AST_CONTROL_RING:
- strcpy(subclass, "Ring");
- break;
- case AST_CONTROL_RINGING:
- strcpy(subclass, "Ringing");
- break;
- case AST_CONTROL_ANSWER:
- strcpy(subclass, "Answer");
- break;
- case AST_CONTROL_BUSY:
- strcpy(subclass, "Busy");
- break;
- case AST_CONTROL_TAKEOFFHOOK:
- strcpy(subclass, "Take Off Hook");
- break;
- case AST_CONTROL_OFFHOOK:
- strcpy(subclass, "Line Off Hook");
- break;
- case AST_CONTROL_CONGESTION:
- strcpy(subclass, "Congestion");
- break;
- case AST_CONTROL_FLASH:
- strcpy(subclass, "Flash");
- break;
- case AST_CONTROL_WINK:
- strcpy(subclass, "Wink");
- break;
- case AST_CONTROL_OPTION:
- strcpy(subclass, "Option");
- break;
- case AST_CONTROL_RADIO_KEY:
- strcpy(subclass, "Key Radio");
- break;
- case AST_CONTROL_RADIO_UNKEY:
- strcpy(subclass, "Unkey Radio");
- break;
- case -1:
- strcpy(subclass, "Stop generators");
- break;
- default:
- snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass);
- }
- break;
- case AST_FRAME_NULL:
- strcpy(ftype, "Null Frame");
- strcpy(subclass, "N/A");
- break;
- case AST_FRAME_IAX:
- /* Should never happen */
- strcpy(ftype, "IAX Specific");
- snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass);
- break;
- case AST_FRAME_TEXT:
- strcpy(ftype, "Text");
- strcpy(subclass, "N/A");
- ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
- break;
- case AST_FRAME_IMAGE:
- strcpy(ftype, "Image");
- snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass));
- break;
- case AST_FRAME_HTML:
- strcpy(ftype, "HTML");
- switch(f->subclass) {
- case AST_HTML_URL:
- strcpy(subclass, "URL");
- ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
- break;
- case AST_HTML_DATA:
- strcpy(subclass, "Data");
- break;
- case AST_HTML_BEGIN:
- strcpy(subclass, "Begin");
- break;
- case AST_HTML_END:
- strcpy(subclass, "End");
- break;
- case AST_HTML_LDCOMPLETE:
- strcpy(subclass, "Load Complete");
- break;
- case AST_HTML_NOSUPPORT:
- strcpy(subclass, "No Support");
- break;
- case AST_HTML_LINKURL:
- strcpy(subclass, "Link URL");
- ast_copy_string(moreinfo, f->data, sizeof(moreinfo));
- break;
- case AST_HTML_UNLINK:
- strcpy(subclass, "Unlink");
- break;
- case AST_HTML_LINKREJECT:
- strcpy(subclass, "Link Reject");
- break;
- default:
- snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass);
- break;
- }
- break;
- case AST_FRAME_MODEM:
- strcpy(ftype, "Modem");
- switch (f->subclass) {
- case AST_MODEM_T38:
- strcpy(subclass, "T.38");
- break;
- case AST_MODEM_V150:
- strcpy(subclass, "V.150");
- break;
- default:
- snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass);
- break;
- }
- break;
- default:
- snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
- }
- if (!ast_strlen_zero(moreinfo))
- ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
- term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
- term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
- f->frametype,
- term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
- f->subclass,
- term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
- term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
- else
- ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
- term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
- term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
- f->frametype,
- term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
- f->subclass,
- term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
-}
-
-
-#ifdef TRACE_FRAMES
-static int show_frame_stats(int fd, int argc, char *argv[])
-{
- struct ast_frame *f;
- int x=1;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- AST_LIST_LOCK(&headerlist);
- ast_cli(fd, " Framer Statistics \n");
- ast_cli(fd, "---------------------------\n");
- ast_cli(fd, "Total allocated headers: %d\n", headers);
- ast_cli(fd, "Queue Dump:\n");
- AST_LIST_TRAVERSE(&headerlist, f, frame_list)
- ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
- AST_LIST_UNLOCK(&headerlist);
- return RESULT_SUCCESS;
-}
-
-static char frame_stats_usage[] =
-"Usage: core show frame stats\n"
-" Displays debugging statistics from framer\n";
-#endif
-
-/* Builtin Asterisk CLI-commands for debugging */
-static struct ast_cli_entry cli_show_codecs = {
- { "show", "codecs", NULL },
- show_codecs_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_audio_codecs = {
- { "show", "audio", "codecs", NULL },
- show_codecs_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_video_codecs = {
- { "show", "video", "codecs", NULL },
- show_codecs_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_image_codecs = {
- { "show", "image", "codecs", NULL },
- show_codecs_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_codec = {
- { "show", "codec", NULL },
- show_codec_n_deprecated, NULL,
- NULL };
-
-#ifdef TRACE_FRAMES
-static struct ast_cli_entry cli_show_frame_stats = {
- { "show", "frame", "stats", NULL },
- show_frame_stats, NULL,
- NULL };
-#endif
-
-static struct ast_cli_entry my_clis[] = {
- { { "core", "show", "codecs", NULL },
- show_codecs, "Displays a list of codecs",
- frame_show_codecs_usage, NULL, &cli_show_codecs },
-
- { { "core", "show", "audio", "codecs", NULL },
- show_codecs, "Displays a list of audio codecs",
- frame_show_codecs_usage, NULL, &cli_show_audio_codecs },
-
- { { "core", "show", "video", "codecs", NULL },
- show_codecs, "Displays a list of video codecs",
- frame_show_codecs_usage, NULL, &cli_show_video_codecs },
-
- { { "core", "show", "image", "codecs", NULL },
- show_codecs, "Displays a list of image codecs",
- frame_show_codecs_usage, NULL, &cli_show_image_codecs },
-
- { { "core", "show", "codec", NULL },
- show_codec_n, "Shows a specific codec",
- frame_show_codec_n_usage, NULL, &cli_show_codec },
-
-#ifdef TRACE_FRAMES
- { { "core", "show", "frame", "stats", NULL },
- show_frame_stats, "Shows frame statistics",
- frame_stats_usage, NULL, &cli_show_frame_stats },
-#endif
-};
-
-int init_framer(void)
-{
- ast_cli_register_multiple(my_clis, sizeof(my_clis) / sizeof(struct ast_cli_entry));
- return 0;
-}
-
-void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
-{
- int x, differential = (int) 'A', mem;
- char *from, *to;
-
- if(right) {
- from = pref->order;
- to = buf;
- mem = size;
- } else {
- to = pref->order;
- from = buf;
- mem = 32;
- }
-
- memset(to, 0, mem);
- for (x = 0; x < 32 ; x++) {
- if(!from[x])
- break;
- to[x] = right ? (from[x] + differential) : (from[x] - differential);
- }
-}
-
-int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
-{
- int x, codec;
- size_t total_len, slen;
- char *formatname;
-
- memset(buf,0,size);
- total_len = size;
- buf[0] = '(';
- total_len--;
- for(x = 0; x < 32 ; x++) {
- if(total_len <= 0)
- break;
- if(!(codec = ast_codec_pref_index(pref,x)))
- break;
- if((formatname = ast_getformatname(codec))) {
- slen = strlen(formatname);
- if(slen > total_len)
- break;
- strncat(buf, formatname, total_len - 1); /* safe */
- total_len -= slen;
- }
- if(total_len && x < 31 && ast_codec_pref_index(pref , x + 1)) {
- strncat(buf, "|", total_len - 1); /* safe */
- total_len--;
- }
- }
- if(total_len) {
- strncat(buf, ")", total_len - 1); /* safe */
- total_len--;
- }
-
- return size - total_len;
-}
-
-int ast_codec_pref_index(struct ast_codec_pref *pref, int index)
-{
- int slot = 0;
-
-
- if((index >= 0) && (index < sizeof(pref->order))) {
- slot = pref->order[index];
- }
-
- return slot ? AST_FORMAT_LIST[slot-1].bits : 0;
-}
-
-/*! \brief Remove codec from pref list */
-void ast_codec_pref_remove(struct ast_codec_pref *pref, int format)
-{
- struct ast_codec_pref oldorder;
- int x, y = 0;
- int slot;
- int size;
-
- if(!pref->order[0])
- return;
-
- memcpy(&oldorder, pref, sizeof(oldorder));
- memset(pref, 0, sizeof(*pref));
-
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- slot = oldorder.order[x];
- size = oldorder.framing[x];
- if(! slot)
- break;
- if(AST_FORMAT_LIST[slot-1].bits != format) {
- pref->order[y] = slot;
- pref->framing[y++] = size;
- }
- }
-
-}
-
-/*! \brief Append codec to list */
-int ast_codec_pref_append(struct ast_codec_pref *pref, int format)
-{
- int x, newindex = 0;
-
- ast_codec_pref_remove(pref, format);
-
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if(AST_FORMAT_LIST[x].bits == format) {
- newindex = x + 1;
- break;
- }
- }
-
- if(newindex) {
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if(!pref->order[x]) {
- pref->order[x] = newindex;
- break;
- }
- }
- }
-
- return x;
-}
-
-/*! \brief Prepend codec to list */
-void ast_codec_pref_prepend(struct ast_codec_pref *pref, int format, int only_if_existing)
-{
- int x, newindex = 0;
-
- /* First step is to get the codecs "index number" */
- for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
- if (AST_FORMAT_LIST[x].bits == format) {
- newindex = x + 1;
- break;
- }
- }
- /* Done if its unknown */
- if (!newindex)
- return;
-
- /* Now find any existing occurrence, or the end */
- for (x = 0; x < 32; x++) {
- if (!pref->order[x] || pref->order[x] == newindex)
- break;
- }
-
- if (only_if_existing && !pref->order[x])
- return;
-
- /* Move down to make space to insert - either all the way to the end,
- or as far as the existing location (which will be overwritten) */
- for (; x > 0; x--) {
- pref->order[x] = pref->order[x - 1];
- pref->framing[x] = pref->framing[x - 1];
- }
-
- /* And insert the new entry */
- pref->order[0] = newindex;
- pref->framing[0] = 0; /* ? */
-}
-
-/*! \brief Set packet size for codec */
-int ast_codec_pref_setsize(struct ast_codec_pref *pref, int format, int framems)
-{
- int x, index = -1;
-
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if(AST_FORMAT_LIST[x].bits == format) {
- index = x;
- break;
- }
- }
-
- if(index < 0)
- return -1;
-
- /* size validation */
- if(!framems)
- framems = AST_FORMAT_LIST[index].def_ms;
-
- if(AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
- framems -= framems % AST_FORMAT_LIST[index].inc_ms;
-
- if(framems < AST_FORMAT_LIST[index].min_ms)
- framems = AST_FORMAT_LIST[index].min_ms;
-
- if(framems > AST_FORMAT_LIST[index].max_ms)
- framems = AST_FORMAT_LIST[index].max_ms;
-
-
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if(pref->order[x] == (index + 1)) {
- pref->framing[x] = framems;
- break;
- }
- }
-
- return x;
-}
-
-/*! \brief Get packet size for codec */
-struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, int format)
-{
- int x, index = -1, framems = 0;
- struct ast_format_list fmt = {0};
-
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if(AST_FORMAT_LIST[x].bits == format) {
- fmt = AST_FORMAT_LIST[x];
- index = x;
- break;
- }
- }
-
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- if(pref->order[x] == (index + 1)) {
- framems = pref->framing[x];
- break;
- }
- }
-
- /* size validation */
- if(!framems)
- framems = AST_FORMAT_LIST[index].def_ms;
-
- if(AST_FORMAT_LIST[index].inc_ms && framems % AST_FORMAT_LIST[index].inc_ms) /* avoid division by zero */
- framems -= framems % AST_FORMAT_LIST[index].inc_ms;
-
- if(framems < AST_FORMAT_LIST[index].min_ms)
- framems = AST_FORMAT_LIST[index].min_ms;
-
- if(framems > AST_FORMAT_LIST[index].max_ms)
- framems = AST_FORMAT_LIST[index].max_ms;
-
- fmt.cur_ms = framems;
-
- return fmt;
-}
-
-/*! \brief Pick a codec */
-int ast_codec_choose(struct ast_codec_pref *pref, int formats, int find_best)
-{
- int x, ret = 0, slot;
-
- for (x = 0; x < sizeof(AST_FORMAT_LIST) / sizeof(AST_FORMAT_LIST[0]); x++) {
- slot = pref->order[x];
-
- if (!slot)
- break;
- if (formats & AST_FORMAT_LIST[slot-1].bits) {
- ret = AST_FORMAT_LIST[slot-1].bits;
- break;
- }
- }
- if(ret & AST_FORMAT_AUDIO_MASK)
- return ret;
-
- if (option_debug > 3)
- ast_log(LOG_DEBUG, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
-
- return find_best ? ast_best_codec(formats) : 0;
-}
-
-void ast_parse_allow_disallow(struct ast_codec_pref *pref, int *mask, const char *list, int allowing)
-{
- char *parse = NULL, *this = NULL, *psize = NULL;
- int format = 0, framems = 0;
-
- parse = ast_strdupa(list);
- while ((this = strsep(&parse, ","))) {
- framems = 0;
- if ((psize = strrchr(this, ':'))) {
- *psize++ = '\0';
- if (option_debug)
- ast_log(LOG_DEBUG,"Packetization for codec: %s is %s\n", this, psize);
- framems = atoi(psize);
- if (framems < 0)
- framems = 0;
- }
- if (!(format = ast_getformatbyname(this))) {
- ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
- continue;
- }
-
- if (mask) {
- if (allowing)
- *mask |= format;
- else
- *mask &= ~format;
- }
-
- /* Set up a preference list for audio. Do not include video in preferences
- since we can not transcode video and have to use whatever is offered
- */
- if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
- if (strcasecmp(this, "all")) {
- if (allowing) {
- ast_codec_pref_append(pref, format);
- ast_codec_pref_setsize(pref, format, framems);
- }
- else
- ast_codec_pref_remove(pref, format);
- } else if (!allowing) {
- memset(pref, 0, sizeof(*pref));
- }
- }
- }
-}
-
-static int g723_len(unsigned char buf)
-{
- enum frame_type type = buf & TYPE_MASK;
-
- switch(type) {
- case TYPE_DONTSEND:
- return 0;
- break;
- case TYPE_SILENCE:
- return 4;
- break;
- case TYPE_HIGH:
- return 24;
- break;
- case TYPE_LOW:
- return 20;
- break;
- default:
- ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", type);
- }
- return -1;
-}
-
-static int g723_samples(unsigned char *buf, int maxlen)
-{
- int pos = 0;
- int samples = 0;
- int res;
- while(pos < maxlen) {
- res = g723_len(buf[pos]);
- if (res <= 0)
- break;
- samples += 240;
- pos += res;
- }
- return samples;
-}
-
-static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
-{
- int byte = bit / 8; /* byte containing first bit */
- int rem = 8 - (bit % 8); /* remaining bits in first byte */
- unsigned char ret = 0;
-
- if (n <= 0 || n > 8)
- return 0;
-
- if (rem < n) {
- ret = (data[byte] << (n - rem));
- ret |= (data[byte + 1] >> (8 - n + rem));
- } else {
- ret = (data[byte] >> (rem - n));
- }
-
- return (ret & (0xff >> (8 - n)));
-}
-
-static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
-{
- static int SpeexWBSubModeSz[] = {
- 0, 36, 112, 192,
- 352, 0, 0, 0 };
- int off = bit;
- unsigned char c;
-
- /* skip up to two wideband frames */
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- c = get_n_bits_at(data, 3, off + 1);
- off += SpeexWBSubModeSz[c];
-
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- c = get_n_bits_at(data, 3, off + 1);
- off += SpeexWBSubModeSz[c];
-
- if (((len * 8 - off) >= 5) &&
- get_n_bits_at(data, 1, off)) {
- ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
- return -1;
- }
- }
-
- }
- return off - bit;
-}
-
-static int speex_samples(unsigned char *data, int len)
-{
- static int SpeexSubModeSz[] = {
- 5, 43, 119, 160,
- 220, 300, 364, 492,
- 79, 0, 0, 0,
- 0, 0, 0, 0 };
- static int SpeexInBandSz[] = {
- 1, 1, 4, 4,
- 4, 4, 4, 4,
- 8, 8, 16, 16,
- 32, 32, 64, 64 };
- int bit = 0;
- int cnt = 0;
- int off;
- unsigned char c;
-
- while ((len * 8 - bit) >= 5) {
- /* skip wideband frames */
- off = speex_get_wb_sz_at(data, len, bit);
- if (off < 0) {
- ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
- break;
- }
- bit += off;
-
- if ((len * 8 - bit) < 5) {
- ast_log(LOG_WARNING, "Not enough bits remaining after wide band for speex samples.\n");
- break;
- }
-
- /* get control bits */
- c = get_n_bits_at(data, 5, bit);
- bit += 5;
-
- if (c == 15) {
- /* terminator */
- break;
- } else if (c == 14) {
- /* in-band signal; next 4 bits contain signal id */
- c = get_n_bits_at(data, 4, bit);
- bit += 4;
- bit += SpeexInBandSz[c];
- } else if (c == 13) {
- /* user in-band; next 5 bits contain msg len */
- c = get_n_bits_at(data, 5, bit);
- bit += 5;
- bit += c * 8;
- } else if (c > 8) {
- /* unknown */
- break;
- } else {
- /* skip number bits for submode (less the 5 control bits) */
- bit += SpeexSubModeSz[c] - 5;
- cnt += 160; /* new frame */
- }
- }
- return cnt;
-}
-
-int ast_codec_get_samples(struct ast_frame *f)
-{
- int samples=0;
- switch(f->subclass) {
- case AST_FORMAT_SPEEX:
- samples = speex_samples(f->data, f->datalen);
- break;
- case AST_FORMAT_G723_1:
- samples = g723_samples(f->data, f->datalen);
- break;
- case AST_FORMAT_ILBC:
- samples = 240 * (f->datalen / 50);
- break;
- case AST_FORMAT_GSM:
- samples = 160 * (f->datalen / 33);
- break;
- case AST_FORMAT_G729A:
- samples = f->datalen * 8;
- break;
- case AST_FORMAT_SLINEAR:
- samples = f->datalen / 2;
- break;
- case AST_FORMAT_LPC10:
- /* assumes that the RTP packet contains one LPC10 frame */
- samples = 22 * 8;
- samples += (((char *)(f->data))[7] & 0x1) * 8;
- break;
- case AST_FORMAT_ULAW:
- case AST_FORMAT_ALAW:
- samples = f->datalen;
- break;
- case AST_FORMAT_G722:
- case AST_FORMAT_ADPCM:
- case AST_FORMAT_G726:
- case AST_FORMAT_G726_AAL2:
- samples = f->datalen * 2;
- break;
- default:
- ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname(f->subclass));
- }
- return samples;
-}
-
-int ast_codec_get_len(int format, int samples)
-{
- int len = 0;
-
- /* XXX Still need speex, g723, and lpc10 XXX */
- switch(format) {
- case AST_FORMAT_ILBC:
- len = (samples / 240) * 50;
- break;
- case AST_FORMAT_GSM:
- len = (samples / 160) * 33;
- break;
- case AST_FORMAT_G729A:
- len = samples / 8;
- break;
- case AST_FORMAT_SLINEAR:
- len = samples * 2;
- break;
- case AST_FORMAT_ULAW:
- case AST_FORMAT_ALAW:
- len = samples;
- break;
- case AST_FORMAT_G722:
- case AST_FORMAT_ADPCM:
- case AST_FORMAT_G726:
- case AST_FORMAT_G726_AAL2:
- len = samples / 2;
- break;
- default:
- ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
- }
-
- return len;
-}
-
-int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
-{
- int count;
- short *fdata = f->data;
- short adjust_value = abs(adjustment);
-
- if ((f->frametype != AST_FRAME_VOICE) || (f->subclass != AST_FORMAT_SLINEAR))
- return -1;
-
- if (!adjustment)
- return 0;
-
- for (count = 0; count < f->samples; count++) {
- if (adjustment > 0) {
- ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
- } else if (adjustment < 0) {
- ast_slinear_saturated_divide(&fdata[count], &adjust_value);
- }
- }
-
- return 0;
-}
-
-int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
-{
- int count;
- short *data1, *data2;
-
- if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass != AST_FORMAT_SLINEAR))
- return -1;
-
- if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass != AST_FORMAT_SLINEAR))
- return -1;
-
- if (f1->samples != f2->samples)
- return -1;
-
- for (count = 0, data1 = f1->data, data2 = f2->data;
- count < f1->samples;
- count++, data1++, data2++)
- ast_slinear_saturated_add(data1, data2);
-
- return 0;
-}
diff --git a/main/fskmodem.c b/main/fskmodem.c
deleted file mode 100644
index 3ab462886..000000000
--- a/main/fskmodem.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * Includes code and algorithms from the Zapata library.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief FSK Modulator/Demodulator
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * \arg Includes code and algorithms from the Zapata library.
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-
-#include "asterisk/fskmodem.h"
-
-#define NBW 2
-#define BWLIST {75,800}
-#define NF 6
-#define FLIST {1400,1800,1200,2200,1300,2100}
-
-#define STATE_SEARCH_STARTBIT 0
-#define STATE_SEARCH_STARTBIT2 1
-#define STATE_SEARCH_STARTBIT3 2
-#define STATE_GET_BYTE 3
-
-static inline float get_sample(short **buffer, int *len)
-{
- float retval;
- retval = (float) **buffer / 256;
- (*buffer)++;
- (*len)--;
- return retval;
-}
-
-#define GET_SAMPLE get_sample(&buffer, len)
-
-/* Coeficientes para filtros de entrada */
-/* Tabla de coeficientes, generada a partir del programa "mkfilter" */
-/* Formato: coef[IDX_FREC][IDX_BW][IDX_COEF] */
-/* IDX_COEF=0 => 1/GAIN */
-/* IDX_COEF=1-6 => Coeficientes y[n] */
-
-static double coef_in[NF][NBW][8]={
-#include "coef_in.h"
-};
-
-/* Coeficientes para filtro de salida */
-/* Tabla de coeficientes, generada a partir del programa "mkfilter" */
-/* Formato: coef[IDX_BW][IDX_COEF] */
-/* IDX_COEF=0 => 1/GAIN */
-/* IDX_COEF=1-6 => Coeficientes y[n] */
-
-static double coef_out[NBW][8]={
-#include "coef_out.h"
-};
-
-
-/*! Filtro pasa-banda para frecuencia de MARCA */
-static inline float filtroM(fsk_data *fskd,float in)
-{
- int i,j;
- double s;
- double *pc;
-
- pc=&coef_in[fskd->f_mark_idx][fskd->bw][0];
- fskd->fmxv[(fskd->fmp+6)&7]=in*(*pc++);
-
- s=(fskd->fmxv[(fskd->fmp+6)&7] - fskd->fmxv[fskd->fmp]) + 3 * (fskd->fmxv[(fskd->fmp+2)&7] - fskd->fmxv[(fskd->fmp+4)&7]);
- for (i=0,j=fskd->fmp;i<6;i++,j++) s+=fskd->fmyv[j&7]*(*pc++);
- fskd->fmyv[j&7]=s;
- fskd->fmp++; fskd->fmp&=7;
- return s;
-}
-
-/*! Filtro pasa-banda para frecuencia de ESPACIO */
-static inline float filtroS(fsk_data *fskd,float in)
-{
- int i,j;
- double s;
- double *pc;
-
- pc=&coef_in[fskd->f_space_idx][fskd->bw][0];
- fskd->fsxv[(fskd->fsp+6)&7]=in*(*pc++);
-
- s=(fskd->fsxv[(fskd->fsp+6)&7] - fskd->fsxv[fskd->fsp]) + 3 * (fskd->fsxv[(fskd->fsp+2)&7] - fskd->fsxv[(fskd->fsp+4)&7]);
- for (i=0,j=fskd->fsp;i<6;i++,j++) s+=fskd->fsyv[j&7]*(*pc++);
- fskd->fsyv[j&7]=s;
- fskd->fsp++; fskd->fsp&=7;
- return s;
-}
-
-/*! Filtro pasa-bajos para datos demodulados */
-static inline float filtroL(fsk_data *fskd,float in)
-{
- int i,j;
- double s;
- double *pc;
-
- pc=&coef_out[fskd->bw][0];
- fskd->flxv[(fskd->flp + 6) & 7]=in * (*pc++);
-
- s= (fskd->flxv[fskd->flp] + fskd->flxv[(fskd->flp+6)&7]) +
- 6 * (fskd->flxv[(fskd->flp+1)&7] + fskd->flxv[(fskd->flp+5)&7]) +
- 15 * (fskd->flxv[(fskd->flp+2)&7] + fskd->flxv[(fskd->flp+4)&7]) +
- 20 * fskd->flxv[(fskd->flp+3)&7];
-
- for (i=0,j=fskd->flp;i<6;i++,j++) s+=fskd->flyv[j&7]*(*pc++);
- fskd->flyv[j&7]=s;
- fskd->flp++; fskd->flp&=7;
- return s;
-}
-
-static inline int demodulador(fsk_data *fskd, float *retval, float x)
-{
- float xS,xM;
-
- fskd->cola_in[fskd->pcola]=x;
-
- xS=filtroS(fskd,x);
- xM=filtroM(fskd,x);
-
- fskd->cola_filtro[fskd->pcola]=xM-xS;
-
- x=filtroL(fskd,xM*xM - xS*xS);
-
- fskd->cola_demod[fskd->pcola++]=x;
- fskd->pcola &= (NCOLA-1);
-
- *retval = x;
- return(0);
-}
-
-static int get_bit_raw(fsk_data *fskd, short *buffer, int *len)
-{
- /* Esta funcion implementa un DPLL para sincronizarse con los bits */
- float x,spb,spb2,ds;
- int f;
-
- spb=fskd->spb;
- if (fskd->spb == 7) spb = 8000.0 / 1200.0;
- ds=spb/32.;
- spb2=spb/2.;
-
- for (f=0;;){
- if (demodulador(fskd,&x, GET_SAMPLE)) return(-1);
- if ((x*fskd->x0)<0) { /* Transicion */
- if (!f) {
- if (fskd->cont<(spb2)) fskd->cont+=ds; else fskd->cont-=ds;
- f=1;
- }
- }
- fskd->x0=x;
- fskd->cont+=1.;
- if (fskd->cont>spb) {
- fskd->cont-=spb;
- break;
- }
- }
- f=(x>0)?0x80:0;
- return(f);
-}
-
-int fsk_serie(fsk_data *fskd, short *buffer, int *len, int *outbyte)
-{
- int a;
- int i,j,n1,r;
- int samples=0;
- int olen;
- int beginlen=*len;
- int beginlenx;
-
- switch(fskd->state) {
- /* Pick up where we left off */
- case STATE_SEARCH_STARTBIT2:
- goto search_startbit2;
- case STATE_SEARCH_STARTBIT3:
- goto search_startbit3;
- case STATE_GET_BYTE:
- goto getbyte;
- }
- /* Esperamos bit de start */
- do {
-/* this was jesus's nice, reasonable, working (at least with RTTY) code
-to look for the beginning of the start bit. Unfortunately, since TTY/TDD's
-just start sending a start bit with nothing preceding it at the beginning
-of a transmission (what a LOSING design), we cant do it this elegantly */
-/*
- if (demodulador(zap,&x1)) return(-1);
- for(;;) {
- if (demodulador(zap,&x2)) return(-1);
- if (x1>0 && x2<0) break;
- x1=x2;
- }
-*/
-/* this is now the imprecise, losing, but functional code to detect the
-beginning of a start bit in the TDD sceanario. It just looks for sufficient
-level to maybe, perhaps, guess, maybe that its maybe the beginning of
-a start bit, perhaps. This whole thing stinks! */
- beginlenx=beginlen; /* just to avoid unused war warnings */
- if (demodulador(fskd,&fskd->x1,GET_SAMPLE)) return(-1);
- samples++;
- for(;;)
- {
-search_startbit2:
- if (*len <= 0) {
- fskd->state = STATE_SEARCH_STARTBIT2;
- return 0;
- }
- samples++;
- if (demodulador(fskd,&fskd->x2,GET_SAMPLE)) return(-1);
-#if 0
- printf("x2 = %5.5f ", fskd->x2);
-#endif
- if (fskd->x2 < -0.5) break;
- }
-search_startbit3:
- /* Esperamos 0.5 bits antes de usar DPLL */
- i=fskd->spb/2;
- if (*len < i) {
- fskd->state = STATE_SEARCH_STARTBIT3;
- return 0;
- }
- for(;i>0;i--) { if (demodulador(fskd,&fskd->x1,GET_SAMPLE)) return(-1);
-#if 0
- printf("x1 = %5.5f ", fskd->x1);
-#endif
- samples++; }
-
- /* x1 debe ser negativo (confirmación del bit de start) */
-
- } while (fskd->x1>0);
- fskd->state = STATE_GET_BYTE;
-
-getbyte:
-
- /* Need at least 80 samples (for 1200) or
- 1320 (for 45.5) to be sure we'll have a byte */
- if (fskd->nbit < 8) {
- if (*len < 1320)
- return 0;
- } else {
- if (*len < 80)
- return 0;
- }
- /* Leemos ahora los bits de datos */
- j=fskd->nbit;
- for (a=n1=0;j;j--) {
- olen = *len;
- i=get_bit_raw(fskd, buffer, len);
- buffer += (olen - *len);
- if (i == -1) return(-1);
- if (i) n1++;
- a>>=1; a|=i;
- }
- j=8-fskd->nbit;
- a>>=j;
-
- /* Leemos bit de paridad (si existe) y la comprobamos */
- if (fskd->paridad) {
- olen = *len;
- i=get_bit_raw(fskd, buffer, len);
- buffer += (olen - *len);
- if (i == -1) return(-1);
- if (i) n1++;
- if (fskd->paridad==1) { /* paridad=1 (par) */
- if (n1&1) a|=0x100; /* error */
- } else { /* paridad=2 (impar) */
- if (!(n1&1)) a|=0x100; /* error */
- }
- }
-
- /* Leemos bits de STOP. Todos deben ser 1 */
-
- for (j=fskd->nstop;j;j--) {
- r = get_bit_raw(fskd, buffer, len);
- if (r == -1) return(-1);
- if (!r) a|=0x200;
- }
-
- /* Por fin retornamos */
- /* Bit 8 : Error de paridad */
- /* Bit 9 : Error de Framming */
-
- *outbyte = a;
- fskd->state = STATE_SEARCH_STARTBIT;
- return 1;
-}
diff --git a/main/global_datastores.c b/main/global_datastores.c
deleted file mode 100644
index ca04a0fe9..000000000
--- a/main/global_datastores.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2007, Digium, Inc.
- *
- * Mark Michelson <mmichelson@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief globally-accessible datastore information and callbacks
- *
- * \author Mark Michelson <mmichelson@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/global_datastores.h"
-#include "asterisk/linkedlists.h"
-
-static void dialed_interface_destroy(void *data)
-{
- struct ast_dialed_interface *di = NULL;
- AST_LIST_HEAD(, ast_dialed_interface) *dialed_interface_list = data;
-
- if (!dialed_interface_list) {
- return;
- }
-
- AST_LIST_LOCK(dialed_interface_list);
- while ((di = AST_LIST_REMOVE_HEAD(dialed_interface_list, list)))
- ast_free(di);
- AST_LIST_UNLOCK(dialed_interface_list);
-
- AST_LIST_HEAD_DESTROY(dialed_interface_list);
- ast_free(dialed_interface_list);
-}
-
-static void *dialed_interface_duplicate(void *data)
-{
- struct ast_dialed_interface *di = NULL;
- AST_LIST_HEAD(, ast_dialed_interface) *old_list;
- AST_LIST_HEAD(, ast_dialed_interface) *new_list = NULL;
-
- if(!(old_list = data)) {
- return NULL;
- }
-
- if(!(new_list = ast_calloc(1, sizeof(*new_list)))) {
- return NULL;
- }
-
- AST_LIST_HEAD_INIT(new_list);
- AST_LIST_LOCK(old_list);
- AST_LIST_TRAVERSE(old_list, di, list) {
- struct ast_dialed_interface *di2 = ast_calloc(1, sizeof(*di2) + strlen(di->interface));
- if(!di2) {
- AST_LIST_UNLOCK(old_list);
- dialed_interface_destroy(new_list);
- return NULL;
- }
- strcpy(di2->interface, di->interface);
- AST_LIST_INSERT_TAIL(new_list, di2, list);
- }
- AST_LIST_UNLOCK(old_list);
-
- return new_list;
-}
-
-
-static void *dial_features_duplicate(void *data)
-{
- struct ast_dial_features *df = data, *df_copy;
-
- if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
- return NULL;
- }
-
- memcpy(df_copy, df, sizeof(*df));
-
- return df_copy;
-}
-
-static void dial_features_destroy(void *data) {
- struct ast_dial_features *df = data;
- if (df) {
- ast_free(df);
- }
-}
-
-const struct ast_datastore_info dialed_interface_info = {
- .type = "dialed-interface",
- .destroy = dialed_interface_destroy,
- .duplicate = dialed_interface_duplicate,
-};
-
-const struct ast_datastore_info dial_features_info = {
- .type = "dial-features",
- .destroy = dial_features_destroy,
- .duplicate = dial_features_duplicate,
-};
diff --git a/main/http.c b/main/http.c
deleted file mode 100644
index cee1d913c..000000000
--- a/main/http.c
+++ /dev/null
@@ -1,752 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*!
- * \file
- * \brief http server for AMI access
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * This program implements a tiny http server
- * and was inspired by micro-httpd by Jef Poskanzer
- *
- * \ref AstHTTP - AMI over the http protocol
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/signal.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-
-#include "asterisk/cli.h"
-#include "asterisk/http.h"
-#include "asterisk/utils.h"
-#include "asterisk/strings.h"
-#include "asterisk/options.h"
-#include "asterisk/config.h"
-#include "asterisk/version.h"
-#include "asterisk/manager.h"
-
-#define MAX_PREFIX 80
-#define DEFAULT_PREFIX "/asterisk"
-
-struct ast_http_server_instance {
- FILE *f;
- int fd;
- struct sockaddr_in requestor;
- ast_http_callback callback;
-};
-
-AST_RWLOCK_DEFINE_STATIC(uris_lock);
-static struct ast_http_uri *uris;
-
-static int httpfd = -1;
-static pthread_t master = AST_PTHREADT_NULL;
-static char prefix[MAX_PREFIX];
-static int prefix_len;
-static struct sockaddr_in oldsin;
-static int enablestatic;
-
-/*! \brief Limit the kinds of files we're willing to serve up */
-static struct {
- const char *ext;
- const char *mtype;
-} mimetypes[] = {
- { "png", "image/png" },
- { "jpg", "image/jpeg" },
- { "js", "application/x-javascript" },
- { "wav", "audio/x-wav" },
- { "mp3", "audio/mpeg" },
- { "svg", "image/svg+xml" },
- { "svgz", "image/svg+xml" },
- { "gif", "image/gif" },
-};
-
-static const char *ftype2mtype(const char *ftype, char *wkspace, int wkspacelen)
-{
- int x;
- if (ftype) {
- for (x=0;x<sizeof(mimetypes) / sizeof(mimetypes[0]); x++) {
- if (!strcasecmp(ftype, mimetypes[x].ext))
- return mimetypes[x].mtype;
- }
- }
- snprintf(wkspace, wkspacelen, "text/%s", ftype ? ftype : "plain");
- return wkspace;
-}
-
-static char *static_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
-{
- char result[4096];
- char *c=result;
- char *path;
- char *ftype;
- const char *mtype;
- char wkspace[80];
- struct stat st;
- int len;
- int fd;
- void *blob;
-
- /* Yuck. I'm not really sold on this, but if you don't deliver static content it makes your configuration
- substantially more challenging, but this seems like a rather irritating feature creep on Asterisk. */
- if (!enablestatic || ast_strlen_zero(uri))
- goto out403;
- /* Disallow any funny filenames at all */
- if ((uri[0] < 33) || strchr("./|~@#$%^&*() \t", uri[0]))
- goto out403;
- if (strstr(uri, "/.."))
- goto out403;
-
- if ((ftype = strrchr(uri, '.')))
- ftype++;
- mtype = ftype2mtype(ftype, wkspace, sizeof(wkspace));
-
- /* Cap maximum length */
- len = strlen(uri) + strlen(ast_config_AST_DATA_DIR) + strlen("/static-http/") + 5;
- if (len > 1024)
- goto out403;
-
- path = alloca(len);
- sprintf(path, "%s/static-http/%s", ast_config_AST_DATA_DIR, uri);
- if (stat(path, &st))
- goto out404;
- if (S_ISDIR(st.st_mode))
- goto out404;
- fd = open(path, O_RDONLY);
- if (fd < 0)
- goto out403;
-
- len = st.st_size + strlen(mtype) + 40;
-
- blob = malloc(len);
- if (blob) {
- c = blob;
- sprintf(c, "Content-type: %s\r\n\r\n", mtype);
- c += strlen(c);
- *contentlength = read(fd, c, st.st_size);
- if (*contentlength < 0) {
- close(fd);
- free(blob);
- goto out403;
- }
- }
- close(fd);
- return blob;
-
-out404:
- *status = 404;
- *title = strdup("Not Found");
- return ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
-
-out403:
- *status = 403;
- *title = strdup("Access Denied");
- return ast_http_error(403, "Access Denied", NULL, "You do not have permission to access the requested URL.");
-}
-
-
-static char *httpstatus_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
-{
- char result[4096];
- size_t reslen = sizeof(result);
- char *c=result;
- struct ast_variable *v;
-
- ast_build_string(&c, &reslen,
- "\r\n"
- "<title>Asterisk HTTP Status</title>\r\n"
- "<body bgcolor=\"#ffffff\">\r\n"
- "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
- "<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
-
- ast_build_string(&c, &reslen, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
- ast_build_string(&c, &reslen, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
- ast_inet_ntoa(oldsin.sin_addr));
- ast_build_string(&c, &reslen, "<tr><td><i>Bind Port</i></td><td><b>%d</b></td></tr>\r\n",
- ntohs(oldsin.sin_port));
- ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
- v = vars;
- while(v) {
- if (strncasecmp(v->name, "cookie_", 7))
- ast_build_string(&c, &reslen, "<tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
- v = v->next;
- }
- ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
- v = vars;
- while(v) {
- if (!strncasecmp(v->name, "cookie_", 7))
- ast_build_string(&c, &reslen, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
- v = v->next;
- }
- ast_build_string(&c, &reslen, "</table><center><font size=\"-1\"><i>Asterisk and Digium are registered trademarks of Digium, Inc.</i></font></center></body>\r\n");
- return strdup(result);
-}
-
-static struct ast_http_uri statusuri = {
- .callback = httpstatus_callback,
- .description = "Asterisk HTTP General Status",
- .uri = "httpstatus",
- .has_subtree = 0,
-};
-
-static struct ast_http_uri staticuri = {
- .callback = static_callback,
- .description = "Asterisk HTTP Static Delivery",
- .uri = "static",
- .has_subtree = 1,
- .static_content = 1,
-};
-
-char *ast_http_error(int status, const char *title, const char *extra_header, const char *text)
-{
- char *c = NULL;
- if (asprintf(&c,
- "Content-type: text/html\r\n"
- "%s"
- "\r\n"
- "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
- "<html><head>\r\n"
- "<title>%d %s</title>\r\n"
- "</head><body>\r\n"
- "<h1>%s</h1>\r\n"
- "<p>%s</p>\r\n"
- "<hr />\r\n"
- "<address>Asterisk Server</address>\r\n"
- "</body></html>\r\n",
- (extra_header ? extra_header : ""), status, title, title, text) < 0) {
- ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
- c = NULL;
- }
- return c;
-}
-
-int ast_http_uri_link(struct ast_http_uri *urih)
-{
- struct ast_http_uri *prev;
-
- ast_rwlock_wrlock(&uris_lock);
- prev = uris;
- if (!uris || strlen(uris->uri) <= strlen(urih->uri)) {
- urih->next = uris;
- uris = urih;
- } else {
- while (prev->next && (strlen(prev->next->uri) > strlen(urih->uri)))
- prev = prev->next;
- /* Insert it here */
- urih->next = prev->next;
- prev->next = urih;
- }
- ast_rwlock_unlock(&uris_lock);
-
- return 0;
-}
-
-void ast_http_uri_unlink(struct ast_http_uri *urih)
-{
- struct ast_http_uri *prev;
-
- ast_rwlock_wrlock(&uris_lock);
- if (!uris) {
- ast_rwlock_unlock(&uris_lock);
- return;
- }
- prev = uris;
- if (uris == urih) {
- uris = uris->next;
- }
- while(prev->next) {
- if (prev->next == urih) {
- prev->next = urih->next;
- break;
- }
- prev = prev->next;
- }
- ast_rwlock_unlock(&uris_lock);
-}
-
-static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status,
- char **title, int *contentlength, struct ast_variable **cookies,
- unsigned int *static_content)
-{
- char *c;
- char *turi;
- char *params;
- char *var;
- char *val;
- struct ast_http_uri *urih=NULL;
- int len;
- struct ast_variable *vars=NULL, *v, *prev = NULL;
-
-
- params = strchr(uri, '?');
- if (params) {
- *params = '\0';
- params++;
- while ((var = strsep(&params, "&"))) {
- val = strchr(var, '=');
- if (val) {
- *val = '\0';
- val++;
- ast_uri_decode(val);
- } else
- val = "";
- ast_uri_decode(var);
- if ((v = ast_variable_new(var, val))) {
- if (vars)
- prev->next = v;
- else
- vars = v;
- prev = v;
- }
- }
- }
- if (prev)
- prev->next = *cookies;
- else
- vars = *cookies;
- *cookies = NULL;
- ast_uri_decode(uri);
- if (!strncasecmp(uri, prefix, prefix_len)) {
- uri += prefix_len;
- if (!*uri || (*uri == '/')) {
- if (*uri == '/')
- uri++;
- ast_rwlock_rdlock(&uris_lock);
- urih = uris;
- while(urih) {
- len = strlen(urih->uri);
- if (!strncasecmp(urih->uri, uri, len)) {
- if (!uri[len] || uri[len] == '/') {
- turi = uri + len;
- if (*turi == '/')
- turi++;
- if (!*turi || urih->has_subtree) {
- uri = turi;
- break;
- }
- }
- }
- urih = urih->next;
- }
- if (!urih)
- ast_rwlock_unlock(&uris_lock);
- }
- }
- if (urih) {
- if (urih->static_content)
- *static_content = 1;
- c = urih->callback(sin, uri, vars, status, title, contentlength);
- ast_rwlock_unlock(&uris_lock);
- } else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) {
- /* Special case: If no prefix, and no URI, send to /static/index.html */
- c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "Redirecting to /static/index.html.");
- *status = 302;
- *title = strdup("Moved Temporarily");
- } else {
- c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
- *status = 404;
- *title = strdup("Not Found");
- }
- ast_variables_destroy(vars);
- return c;
-}
-
-static struct ast_variable *parse_cookies(char *cookies)
-{
- char *cur;
- struct ast_variable *vars = NULL, *var;
-
- /* Skip Cookie: */
- cookies += 8;
-
- while ((cur = strsep(&cookies, ";"))) {
- char *name, *val;
-
- name = val = cur;
- strsep(&val, "=");
-
- if (ast_strlen_zero(name) || ast_strlen_zero(val)) {
- continue;
- }
-
- name = ast_strip(name);
- val = ast_strip_quoted(val, "\"", "\"");
-
- if (ast_strlen_zero(name) || ast_strlen_zero(val)) {
- continue;
- }
-
- if (option_debug) {
- ast_log(LOG_DEBUG, "mmm ... cookie! Name: '%s' Value: '%s'\n", name, val);
- }
-
- var = ast_variable_new(name, val);
- var->next = vars;
- vars = var;
- }
-
- return vars;
-}
-
-static void *ast_httpd_helper_thread(void *data)
-{
- char buf[4096];
- char cookie[4096];
- char timebuf[256];
- struct ast_http_server_instance *ser = data;
- struct ast_variable *vars = NULL;
- char *uri, *c, *title=NULL;
- int status = 200, contentlength = 0;
- time_t t;
- unsigned int static_content = 0;
-
- if (fgets(buf, sizeof(buf), ser->f)) {
- /* Skip method */
- uri = buf;
- while(*uri && (*uri > 32))
- uri++;
- if (*uri) {
- *uri = '\0';
- uri++;
- }
-
- /* Skip white space */
- while (*uri && (*uri < 33))
- uri++;
-
- if (*uri) {
- c = uri;
- while (*c && (*c > 32))
- c++;
- if (*c) {
- *c = '\0';
- }
- }
-
- while (fgets(cookie, sizeof(cookie), ser->f)) {
- /* Trim trailing characters */
- while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) {
- cookie[strlen(cookie) - 1] = '\0';
- }
- if (ast_strlen_zero(cookie))
- break;
- if (!strncasecmp(cookie, "Cookie: ", 8)) {
- vars = parse_cookies(cookie);
- }
- }
-
- if (*uri) {
- if (!strcasecmp(buf, "get"))
- c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars, &static_content);
- else
- c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
- } else
- c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
-
- /* If they aren't mopped up already, clean up the cookies */
- if (vars)
- ast_variables_destroy(vars);
-
- if (!c)
- c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
- if (c) {
- time(&t);
- strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
- ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
- ast_cli(ser->fd, "Server: Asterisk/%s\r\n", ASTERISK_VERSION);
- ast_cli(ser->fd, "Date: %s\r\n", timebuf);
- ast_cli(ser->fd, "Connection: close\r\n");
- if (!static_content)
- ast_cli(ser->fd, "Cache-Control: no-cache, no-store\r\n");
- /* We set the no-cache headers only for dynamic content.
- * If you want to make sure the static file you requested is not from cache,
- * append a random variable to your GET request. Ex: 'something.html?r=109987734'
- */
-
- if (contentlength) {
- char *tmp;
- tmp = strstr(c, "\r\n\r\n");
- if (tmp) {
- ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
- if (write(ser->fd, c, (tmp + 4 - c)) < 0) {
- ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
- }
- if (write(ser->fd, tmp + 4, contentlength) < 0) {
- ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
- }
- }
- } else
- ast_cli(ser->fd, "%s", c);
- free(c);
- }
- if (title)
- free(title);
- }
- fclose(ser->f);
- free(ser);
- return NULL;
-}
-
-static void *http_root(void *data)
-{
- int fd;
- struct sockaddr_in sin;
- socklen_t sinlen;
- struct ast_http_server_instance *ser;
- pthread_t launched;
- pthread_attr_t attr;
-
- for (;;) {
- int flags;
-
- ast_wait_for_input(httpfd, -1);
- sinlen = sizeof(sin);
- fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen);
- if (fd < 0) {
- if ((errno != EAGAIN) && (errno != EINTR))
- ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
- continue;
- }
- ser = ast_calloc(1, sizeof(*ser));
- if (!ser) {
- ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
- close(fd);
- continue;
- }
- flags = fcntl(fd, F_GETFL);
- fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
- ser->fd = fd;
- memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
- if ((ser->f = fdopen(ser->fd, "w+"))) {
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) {
- ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
- fclose(ser->f);
- free(ser);
- }
- pthread_attr_destroy(&attr);
- } else {
- ast_log(LOG_WARNING, "fdopen failed!\n");
- close(ser->fd);
- free(ser);
- }
- }
- return NULL;
-}
-
-char *ast_http_setcookie(const char *var, const char *val, int expires, char *buf, size_t buflen)
-{
- char *c;
- c = buf;
- ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val);
- if (expires)
- ast_build_string(&c, &buflen, "; Max-Age=%d", expires);
- ast_build_string(&c, &buflen, "\r\n");
- return buf;
-}
-
-
-static void http_server_start(struct sockaddr_in *sin)
-{
- int flags;
- int x = 1;
-
- /* Do nothing if nothing has changed */
- if (!memcmp(&oldsin, sin, sizeof(oldsin))) {
- ast_log(LOG_DEBUG, "Nothing changed in http\n");
- return;
- }
-
- memcpy(&oldsin, sin, sizeof(oldsin));
-
- /* Shutdown a running server if there is one */
- if (master != AST_PTHREADT_NULL) {
- pthread_cancel(master);
- pthread_kill(master, SIGURG);
- pthread_join(master, NULL);
- }
-
- if (httpfd != -1)
- close(httpfd);
-
- /* If there's no new server, stop here */
- if (!sin->sin_family)
- return;
-
-
- httpfd = socket(AF_INET, SOCK_STREAM, 0);
- if (httpfd < 0) {
- ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
- return;
- }
-
- setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
- if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) {
- ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n",
- ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
- strerror(errno));
- close(httpfd);
- httpfd = -1;
- return;
- }
- if (listen(httpfd, 10)) {
- ast_log(LOG_NOTICE, "Unable to listen!\n");
- close(httpfd);
- httpfd = -1;
- return;
- }
- flags = fcntl(httpfd, F_GETFL);
- fcntl(httpfd, F_SETFL, flags | O_NONBLOCK);
- if (ast_pthread_create_background(&master, NULL, http_root, NULL)) {
- ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n",
- ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
- strerror(errno));
- close(httpfd);
- httpfd = -1;
- }
-}
-
-static int __ast_http_load(int reload)
-{
- struct ast_config *cfg;
- struct ast_variable *v;
- int enabled=0;
- int newenablestatic=0;
- struct sockaddr_in sin;
- struct hostent *hp;
- struct ast_hostent ahp;
- char newprefix[MAX_PREFIX];
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_port = htons(8088);
-
- strcpy(newprefix, DEFAULT_PREFIX);
-
- cfg = ast_config_load("http.conf");
- if (cfg) {
- v = ast_variable_browse(cfg, "general");
- while(v) {
- if (!strcasecmp(v->name, "enabled"))
- enabled = ast_true(v->value);
- else if (!strcasecmp(v->name, "enablestatic"))
- newenablestatic = ast_true(v->value);
- else if (!strcasecmp(v->name, "bindport"))
- sin.sin_port = ntohs(atoi(v->value));
- else if (!strcasecmp(v->name, "bindaddr")) {
- if ((hp = ast_gethostbyname(v->value, &ahp))) {
- memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
- } else {
- ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
- }
- } else if (!strcasecmp(v->name, "prefix")) {
- if (!ast_strlen_zero(v->value)) {
- newprefix[0] = '/';
- ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
- } else {
- newprefix[0] = '\0';
- }
-
- }
- v = v->next;
- }
- ast_config_destroy(cfg);
- }
- if (enabled)
- sin.sin_family = AF_INET;
- if (strcmp(prefix, newprefix)) {
- ast_copy_string(prefix, newprefix, sizeof(prefix));
- prefix_len = strlen(prefix);
- }
- enablestatic = newenablestatic;
-
- http_server_start(&sin);
-
-
- return 0;
-}
-
-static int handle_show_http(int fd, int argc, char *argv[])
-{
- struct ast_http_uri *urih;
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
-
- ast_cli(fd, "HTTP Server Status:\n");
- ast_cli(fd, "Prefix: %s\n", prefix);
- if (oldsin.sin_family)
- ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n",
- ast_inet_ntoa(oldsin.sin_addr),
- ntohs(oldsin.sin_port));
- else
- ast_cli(fd, "Server Disabled\n\n");
- ast_cli(fd, "Enabled URI's:\n");
- ast_rwlock_rdlock(&uris_lock);
- urih = uris;
- while(urih){
- ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
- urih = urih->next;
- }
- if (!uris)
- ast_cli(fd, "None.\n");
- ast_rwlock_unlock(&uris_lock);
-
- return RESULT_SUCCESS;
-}
-
-int ast_http_reload(void)
-{
- return __ast_http_load(1);
-}
-
-static char show_http_help[] =
-"Usage: http show status\n"
-" Lists status of internal HTTP engine\n";
-
-static struct ast_cli_entry cli_http[] = {
- { { "http", "show", "status", NULL },
- handle_show_http, "Display HTTP server status",
- show_http_help },
-};
-
-int ast_http_init(void)
-{
- ast_http_uri_link(&statusuri);
- ast_http_uri_link(&staticuri);
- ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry));
-
- return __ast_http_load(0);
-}
diff --git a/main/image.c b/main/image.c
deleted file mode 100644
index 644758495..000000000
--- a/main/image.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Image Management
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "asterisk/sched.h"
-#include "asterisk/options.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/file.h"
-#include "asterisk/image.h"
-#include "asterisk/translate.h"
-#include "asterisk/cli.h"
-#include "asterisk/lock.h"
-
-/* XXX Why don't we just use the formats struct for this? */
-static AST_LIST_HEAD_STATIC(imagers, ast_imager);
-
-int ast_image_register(struct ast_imager *img)
-{
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Registered format '%s' (%s)\n", img->name, img->desc);
- AST_LIST_LOCK(&imagers);
- AST_LIST_INSERT_HEAD(&imagers, img, list);
- AST_LIST_UNLOCK(&imagers);
- return 0;
-}
-
-void ast_image_unregister(struct ast_imager *img)
-{
- struct ast_imager *i;
-
- AST_LIST_LOCK(&imagers);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&imagers, i, list) {
- if (i == img) {
- AST_LIST_REMOVE_CURRENT(&imagers, list);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&imagers);
- if (i && (option_verbose > 1))
- ast_verbose(VERBOSE_PREFIX_2 "Unregistered format '%s' (%s)\n", img->name, img->desc);
-}
-
-int ast_supports_images(struct ast_channel *chan)
-{
- if (!chan || !chan->tech)
- return 0;
- if (!chan->tech->send_image)
- return 0;
- return 1;
-}
-
-static int file_exists(char *filename)
-{
- int res;
- struct stat st;
- res = stat(filename, &st);
- if (!res)
- return st.st_size;
- return 0;
-}
-
-static void make_filename(char *buf, int len, char *filename, const char *preflang, char *ext)
-{
- if (filename[0] == '/') {
- if (!ast_strlen_zero(preflang))
- snprintf(buf, len, "%s-%s.%s", filename, preflang, ext);
- else
- snprintf(buf, len, "%s.%s", filename, ext);
- } else {
- if (!ast_strlen_zero(preflang))
- snprintf(buf, len, "%s/%s/%s-%s.%s", ast_config_AST_DATA_DIR, "images", filename, preflang, ext);
- else
- snprintf(buf, len, "%s/%s/%s.%s", ast_config_AST_DATA_DIR, "images", filename, ext);
- }
-}
-
-struct ast_frame *ast_read_image(char *filename, const char *preflang, int format)
-{
- struct ast_imager *i;
- char buf[256];
- char tmp[80];
- char *e;
- struct ast_imager *found = NULL;
- int fd;
- int len=0;
- struct ast_frame *f = NULL;
-
- AST_LIST_LOCK(&imagers);
- AST_LIST_TRAVERSE(&imagers, i, list) {
- if (i->format & format) {
- char *stringp=NULL;
- ast_copy_string(tmp, i->exts, sizeof(tmp));
- stringp=tmp;
- e = strsep(&stringp, "|");
- while(e) {
- make_filename(buf, sizeof(buf), filename, preflang, e);
- if ((len = file_exists(buf))) {
- found = i;
- break;
- }
- make_filename(buf, sizeof(buf), filename, NULL, e);
- if ((len = file_exists(buf))) {
- found = i;
- break;
- }
- e = strsep(&stringp, "|");
- }
- }
- if (found)
- break;
- }
-
- if (found) {
- fd = open(buf, O_RDONLY);
- if (fd > -1) {
- if (!found->identify || found->identify(fd)) {
- /* Reset file pointer */
- lseek(fd, 0, SEEK_SET);
- f = found->read_image(fd,len);
- } else
- ast_log(LOG_WARNING, "%s does not appear to be a %s file\n", buf, found->name);
- close(fd);
- } else
- ast_log(LOG_WARNING, "Unable to open '%s': %s\n", buf, strerror(errno));
- } else
- ast_log(LOG_WARNING, "Image file '%s' not found\n", filename);
-
- AST_LIST_UNLOCK(&imagers);
-
- return f;
-}
-
-int ast_send_image(struct ast_channel *chan, char *filename)
-{
- struct ast_frame *f;
- int res = -1;
- if (chan->tech->send_image) {
- f = ast_read_image(filename, chan->language, -1);
- if (f) {
- res = chan->tech->send_image(chan, f);
- ast_frfree(f);
- }
- }
- return res;
-}
-
-static int show_image_formats_deprecated(int fd, int argc, char *argv[])
-{
-#define FORMAT "%10s %10s %50s %10s\n"
-#define FORMAT2 "%10s %10s %50s %10s\n"
- struct ast_imager *i;
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_cli(fd, FORMAT, "Name", "Extensions", "Description", "Format");
- AST_LIST_TRAVERSE(&imagers, i, list)
- ast_cli(fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(i->format));
- return RESULT_SUCCESS;
-}
-
-static int show_image_formats(int fd, int argc, char *argv[])
-{
-#define FORMAT "%10s %10s %50s %10s\n"
-#define FORMAT2 "%10s %10s %50s %10s\n"
- struct ast_imager *i;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- ast_cli(fd, FORMAT, "Name", "Extensions", "Description", "Format");
- AST_LIST_TRAVERSE(&imagers, i, list)
- ast_cli(fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(i->format));
- return RESULT_SUCCESS;
-}
-
-struct ast_cli_entry cli_show_image_formats_deprecated = {
- { "show", "image", "formats" },
- show_image_formats_deprecated, NULL,
- NULL };
-
-struct ast_cli_entry cli_image[] = {
- { { "core", "show", "image", "formats" },
- show_image_formats, "Displays image formats",
- "Usage: core show image formats\n"
- " displays currently registered image formats (if any)\n", NULL, &cli_show_image_formats_deprecated },
-};
-
-int ast_image_init(void)
-{
- ast_cli_register_multiple(cli_image, sizeof(cli_image) / sizeof(struct ast_cli_entry));
- return 0;
-}
diff --git a/main/indications.c b/main/indications.c
deleted file mode 100644
index 64f96b5d5..000000000
--- a/main/indications.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2002, Pauline Middelink
- *
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Tone Management
- *
- * \author Pauline Middelink <middelink@polyware.nl>
- *
- * This set of function allow us to play a list of tones on a channel.
- * Each element has two frequencies, which are mixed together and a
- * duration. For silence both frequencies can be set to 0.
- * The playtones can be given as a comma separated string.
- *
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "asterisk/indications.h"
-#include "asterisk/frame.h"
-#include "asterisk/options.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/lock.h"
-#include "asterisk/utils.h"
-
-static int midi_tohz[128] = {
- 8,8,9,9,10,10,11,12,12,13,14,
- 15,16,17,18,19,20,21,23,24,25,
- 27,29,30,32,34,36,38,41,43,46,
- 48,51,55,58,61,65,69,73,77,82,
- 87,92,97,103,110,116,123,130,138,146,
- 155,164,174,184,195,207,220,233,246,261,
- 277,293,311,329,349,369,391,415,440,466,
- 493,523,554,587,622,659,698,739,783,830,
- 880,932,987,1046,1108,1174,1244,1318,1396,1479,
- 1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,
- 2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,
- 4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,
- 8869,9397,9956,10548,11175,11839,12543
- };
-
-struct playtones_item {
- int fac1;
- int init_v2_1;
- int init_v3_1;
- int fac2;
- int init_v2_2;
- int init_v3_2;
- int modulate;
- int duration;
-};
-
-struct playtones_def {
- int vol;
- int reppos;
- int nitems;
- int interruptible;
- struct playtones_item *items;
-};
-
-struct playtones_state {
- int vol;
- int v1_1;
- int v2_1;
- int v3_1;
- int v1_2;
- int v2_2;
- int v3_2;
- int reppos;
- int nitems;
- struct playtones_item *items;
- int npos;
- int oldnpos;
- int pos;
- int origwfmt;
- struct ast_frame f;
- unsigned char offset[AST_FRIENDLY_OFFSET];
- short data[4000];
-};
-
-static void playtones_release(struct ast_channel *chan, void *params)
-{
- struct playtones_state *ps = params;
- if (chan) {
- ast_set_write_format(chan, ps->origwfmt);
- }
- if (ps->items) free(ps->items);
- free(ps);
-}
-
-static void * playtones_alloc(struct ast_channel *chan, void *params)
-{
- struct playtones_def *pd = params;
- struct playtones_state *ps;
- if (!(ps = ast_calloc(1, sizeof(*ps))))
- return NULL;
- ps->origwfmt = chan->writeformat;
- if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
- ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
- playtones_release(NULL, ps);
- ps = NULL;
- } else {
- ps->vol = pd->vol;
- ps->reppos = pd->reppos;
- ps->nitems = pd->nitems;
- ps->items = pd->items;
- ps->oldnpos = -1;
- }
- /* Let interrupts interrupt :) */
- if (pd->interruptible)
- ast_set_flag(chan, AST_FLAG_WRITE_INT);
- else
- ast_clear_flag(chan, AST_FLAG_WRITE_INT);
- return ps;
-}
-
-static int playtones_generator(struct ast_channel *chan, void *data, int len, int samples)
-{
- struct playtones_state *ps = data;
- struct playtones_item *pi;
- int x;
- /* we need to prepare a frame with 16 * timelen samples as we're
- * generating SLIN audio
- */
- len = samples * 2;
- if (len > sizeof(ps->data) / 2 - 1) {
- ast_log(LOG_WARNING, "Can't generate that much data!\n");
- return -1;
- }
- memset(&ps->f, 0, sizeof(ps->f));
-
- pi = &ps->items[ps->npos];
- if (ps->oldnpos != ps->npos) {
- /* Load new parameters */
- ps->v1_1 = 0;
- ps->v2_1 = pi->init_v2_1;
- ps->v3_1 = pi->init_v3_1;
- ps->v1_2 = 0;
- ps->v2_2 = pi->init_v2_2;
- ps->v3_2 = pi->init_v3_2;
- ps->oldnpos = ps->npos;
- }
- for (x=0;x<len/2;x++) {
- ps->v1_1 = ps->v2_1;
- ps->v2_1 = ps->v3_1;
- ps->v3_1 = (pi->fac1 * ps->v2_1 >> 15) - ps->v1_1;
-
- ps->v1_2 = ps->v2_2;
- ps->v2_2 = ps->v3_2;
- ps->v3_2 = (pi->fac2 * ps->v2_2 >> 15) - ps->v1_2;
- if (pi->modulate) {
- int p;
- p = ps->v3_2 - 32768;
- if (p < 0) p = -p;
- p = ((p * 9) / 10) + 1;
- ps->data[x] = (ps->v3_1 * p) >> 15;
- } else
- ps->data[x] = ps->v3_1 + ps->v3_2;
- }
-
- ps->f.frametype = AST_FRAME_VOICE;
- ps->f.subclass = AST_FORMAT_SLINEAR;
- ps->f.datalen = len;
- ps->f.samples = samples;
- ps->f.offset = AST_FRIENDLY_OFFSET;
- ps->f.data = ps->data;
- ps->f.delivery.tv_sec = 0;
- ps->f.delivery.tv_usec = 0;
- ast_write(chan, &ps->f);
-
- ps->pos += x;
- if (pi->duration && ps->pos >= pi->duration * 8) { /* item finished? */
- ps->pos = 0; /* start new item */
- ps->npos++;
- if (ps->npos >= ps->nitems) { /* last item? */
- if (ps->reppos == -1) /* repeat set? */
- return -1;
- ps->npos = ps->reppos; /* redo from top */
- }
- }
- return 0;
-}
-
-static struct ast_generator playtones = {
- alloc: playtones_alloc,
- release: playtones_release,
- generate: playtones_generator,
-};
-
-int ast_playtones_start(struct ast_channel *chan, int vol, const char *playlst, int interruptible)
-{
- char *s, *data = ast_strdupa(playlst); /* cute */
- struct playtones_def d = { vol, -1, 0, 1, NULL};
- char *stringp;
- char *separator;
-
- if (vol < 1)
- d.vol = 7219; /* Default to -8db */
-
- d.interruptible = interruptible;
-
- stringp=data;
- /* the stringp/data is not null here */
- /* check if the data is separated with '|' or with ',' by default */
- if (strchr(stringp,'|'))
- separator = "|";
- else
- separator = ",";
- s = strsep(&stringp,separator);
- while (s && *s) {
- int freq1, freq2, time, modulate=0, midinote=0;
-
- if (s[0]=='!')
- s++;
- else if (d.reppos == -1)
- d.reppos = d.nitems;
- if (sscanf(s, "%d+%d/%d", &freq1, &freq2, &time) == 3) {
- /* f1+f2/time format */
- } else if (sscanf(s, "%d+%d", &freq1, &freq2) == 2) {
- /* f1+f2 format */
- time = 0;
- } else if (sscanf(s, "%d*%d/%d", &freq1, &freq2, &time) == 3) {
- /* f1*f2/time format */
- modulate = 1;
- } else if (sscanf(s, "%d*%d", &freq1, &freq2) == 2) {
- /* f1*f2 format */
- time = 0;
- modulate = 1;
- } else if (sscanf(s, "%d/%d", &freq1, &time) == 2) {
- /* f1/time format */
- freq2 = 0;
- } else if (sscanf(s, "%d", &freq1) == 1) {
- /* f1 format */
- freq2 = 0;
- time = 0;
- } else if (sscanf(s, "M%d+M%d/%d", &freq1, &freq2, &time) == 3) {
- /* Mf1+Mf2/time format */
- midinote = 1;
- } else if (sscanf(s, "M%d+M%d", &freq1, &freq2) == 2) {
- /* Mf1+Mf2 format */
- time = 0;
- midinote = 1;
- } else if (sscanf(s, "M%d*M%d/%d", &freq1, &freq2, &time) == 3) {
- /* Mf1*Mf2/time format */
- modulate = 1;
- midinote = 1;
- } else if (sscanf(s, "M%d*M%d", &freq1, &freq2) == 2) {
- /* Mf1*Mf2 format */
- time = 0;
- modulate = 1;
- midinote = 1;
- } else if (sscanf(s, "M%d/%d", &freq1, &time) == 2) {
- /* Mf1/time format */
- freq2 = -1;
- midinote = 1;
- } else if (sscanf(s, "M%d", &freq1) == 1) {
- /* Mf1 format */
- freq2 = -1;
- time = 0;
- midinote = 1;
- } else {
- ast_log(LOG_WARNING,"%s: tone component '%s' of '%s' is no good\n",chan->name,s,playlst);
- return -1;
- }
-
- if (midinote) {
- /* midi notes must be between 0 and 127 */
- if ((freq1 >= 0) && (freq1 <= 127))
- freq1 = midi_tohz[freq1];
- else
- freq1 = 0;
-
- if ((freq2 >= 0) && (freq2 <= 127))
- freq2 = midi_tohz[freq2];
- else
- freq2 = 0;
- }
-
- if (!(d.items = ast_realloc(d.items, (d.nitems + 1) * sizeof(*d.items)))) {
- return -1;
- }
- d.items[d.nitems].fac1 = 2.0 * cos(2.0 * M_PI * (freq1 / 8000.0)) * 32768.0;
- d.items[d.nitems].init_v2_1 = sin(-4.0 * M_PI * (freq1 / 8000.0)) * d.vol;
- d.items[d.nitems].init_v3_1 = sin(-2.0 * M_PI * (freq1 / 8000.0)) * d.vol;
-
- d.items[d.nitems].fac2 = 2.0 * cos(2.0 * M_PI * (freq2 / 8000.0)) * 32768.0;
- d.items[d.nitems].init_v2_2 = sin(-4.0 * M_PI * (freq2 / 8000.0)) * d.vol;
- d.items[d.nitems].init_v3_2 = sin(-2.0 * M_PI * (freq2 / 8000.0)) * d.vol;
- d.items[d.nitems].duration = time;
- d.items[d.nitems].modulate = modulate;
- d.nitems++;
-
- s = strsep(&stringp,separator);
- }
-
- if (ast_activate_generator(chan, &playtones, &d)) {
- free(d.items);
- return -1;
- }
- return 0;
-}
-
-void ast_playtones_stop(struct ast_channel *chan)
-{
- ast_deactivate_generator(chan);
-}
-
-/*--------------------------------------------*/
-
-static struct tone_zone *tone_zones;
-static struct tone_zone *current_tonezone;
-
-/* Protect the tone_zones list (highly unlikely that two things would change
- * it at the same time, but still! */
-AST_MUTEX_DEFINE_STATIC(tzlock);
-
-struct tone_zone *ast_walk_indications(const struct tone_zone *cur)
-{
- struct tone_zone *tz;
-
- if (cur == NULL)
- return tone_zones;
- ast_mutex_lock(&tzlock);
- for (tz = tone_zones; tz; tz = tz->next)
- if (tz == cur)
- break;
- if (tz)
- tz = tz->next;
- ast_mutex_unlock(&tzlock);
- return tz;
-}
-
-/* Set global indication country */
-int ast_set_indication_country(const char *country)
-{
- if (country) {
- struct tone_zone *z = ast_get_indication_zone(country);
- if (z) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Setting default indication country to '%s'\n",country);
- current_tonezone = z;
- return 0;
- }
- }
- return 1; /* not found */
-}
-
-/* locate tone_zone, given the country. if country == NULL, use the default country */
-struct tone_zone *ast_get_indication_zone(const char *country)
-{
- struct tone_zone *tz;
- int alias_loop = 0;
-
- if (ast_strlen_zero(country)) {
- /* No country specified? Return the default or the first in the list */
- return current_tonezone ? current_tonezone : tone_zones;
- }
-
- ast_mutex_lock(&tzlock);
- do {
- for (tz=tone_zones; tz; tz=tz->next) {
- if (strcasecmp(country,tz->country)==0) {
- /* tone_zone found */
- if (tz->alias && tz->alias[0]) {
- country = tz->alias;
- break;
- }
- ast_mutex_unlock(&tzlock);
- return tz;
- }
- }
- } while (++alias_loop<20 && tz);
- ast_mutex_unlock(&tzlock);
- if (alias_loop==20)
- ast_log(LOG_NOTICE,"Alias loop for '%s' forcefull broken\n",country);
- /* nothing found, sorry */
- return 0;
-}
-
-/* locate a tone_zone_sound, given the tone_zone. if tone_zone == NULL, use the default tone_zone */
-struct tone_zone_sound *ast_get_indication_tone(const struct tone_zone *zone, const char *indication)
-{
- struct tone_zone_sound *ts;
-
- /* we need some tonezone, pick the first */
- if (zone == NULL && current_tonezone)
- zone = current_tonezone; /* default country? */
- if (zone == NULL && tone_zones)
- zone = tone_zones; /* any country? */
- if (zone == NULL)
- return 0; /* not a single country insight */
-
- ast_mutex_lock(&tzlock);
- for (ts=zone->tones; ts; ts=ts->next) {
- if (strcasecmp(indication,ts->name)==0) {
- /* found indication! */
- ast_mutex_unlock(&tzlock);
- return ts;
- }
- }
- /* nothing found, sorry */
- ast_mutex_unlock(&tzlock);
- return 0;
-}
-
-/* helper function to delete a tone_zone in its entirety */
-static inline void free_zone(struct tone_zone* zone)
-{
- while (zone->tones) {
- struct tone_zone_sound *tmp = zone->tones->next;
- free((void*)zone->tones->name);
- free((void*)zone->tones->data);
- free(zone->tones);
- zone->tones = tmp;
- }
- if (zone->ringcadence)
- free(zone->ringcadence);
- free(zone);
-}
-
-/*--------------------------------------------*/
-
-/* add a new country, if country exists, it will be replaced. */
-int ast_register_indication_country(struct tone_zone *zone)
-{
- struct tone_zone *tz,*pz;
-
- ast_mutex_lock(&tzlock);
- for (pz=NULL,tz=tone_zones; tz; pz=tz,tz=tz->next) {
- if (strcasecmp(zone->country,tz->country)==0) {
- /* tone_zone already there, replace */
- zone->next = tz->next;
- if (pz)
- pz->next = zone;
- else
- tone_zones = zone;
- /* if we are replacing the default zone, re-point it */
- if (tz == current_tonezone)
- current_tonezone = zone;
- /* now free the previous zone */
- free_zone(tz);
- ast_mutex_unlock(&tzlock);
- return 0;
- }
- }
- /* country not there, add */
- zone->next = NULL;
- if (pz)
- pz->next = zone;
- else
- tone_zones = zone;
- ast_mutex_unlock(&tzlock);
-
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Registered indication country '%s'\n",zone->country);
- return 0;
-}
-
-/* remove an existing country and all its indications, country must exist.
- * Also, all countries which are an alias for the specified country are removed. */
-int ast_unregister_indication_country(const char *country)
-{
- struct tone_zone *tz, *pz = NULL, *tmp;
- int res = -1;
-
- ast_mutex_lock(&tzlock);
- tz = tone_zones;
- while (tz) {
- if (country==NULL ||
- (strcasecmp(country, tz->country)==0 ||
- strcasecmp(country, tz->alias)==0)) {
- /* tone_zone found, remove */
- tmp = tz->next;
- if (pz)
- pz->next = tmp;
- else
- tone_zones = tmp;
- /* if we are unregistering the default country, w'll notice */
- if (tz == current_tonezone) {
- ast_log(LOG_NOTICE,"Removed default indication country '%s'\n",tz->country);
- current_tonezone = NULL;
- }
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Unregistered indication country '%s'\n",tz->country);
- free_zone(tz);
- if (tone_zones == tz)
- tone_zones = tmp;
- tz = tmp;
- res = 0;
- }
- else {
- /* next zone please */
- pz = tz;
- tz = tz->next;
- }
- }
- ast_mutex_unlock(&tzlock);
- return res;
-}
-
-/* add a new indication to a tone_zone. tone_zone must exist. if the indication already
- * exists, it will be replaced. */
-int ast_register_indication(struct tone_zone *zone, const char *indication, const char *tonelist)
-{
- struct tone_zone_sound *ts,*ps;
-
- /* is it an alias? stop */
- if (zone->alias[0])
- return -1;
-
- ast_mutex_lock(&tzlock);
- for (ps=NULL,ts=zone->tones; ts; ps=ts,ts=ts->next) {
- if (strcasecmp(indication,ts->name)==0) {
- /* indication already there, replace */
- free((void*)ts->name);
- free((void*)ts->data);
- break;
- }
- }
- if (!ts) {
- /* not there, we have to add */
- if (!(ts = ast_malloc(sizeof(*ts)))) {
- ast_mutex_unlock(&tzlock);
- return -2;
- }
- ts->next = NULL;
- }
- if (!(ts->name = ast_strdup(indication)) || !(ts->data = ast_strdup(tonelist))) {
- ast_mutex_unlock(&tzlock);
- return -2;
- }
- if (ps)
- ps->next = ts;
- else
- zone->tones = ts;
- ast_mutex_unlock(&tzlock);
- return 0;
-}
-
-/* remove an existing country's indication. Both country and indication must exist */
-int ast_unregister_indication(struct tone_zone *zone, const char *indication)
-{
- struct tone_zone_sound *ts,*ps = NULL, *tmp;
- int res = -1;
-
- /* is it an alias? stop */
- if (zone->alias[0])
- return -1;
-
- ast_mutex_lock(&tzlock);
- ts = zone->tones;
- while (ts) {
- if (strcasecmp(indication,ts->name)==0) {
- /* indication found */
- tmp = ts->next;
- if (ps)
- ps->next = tmp;
- else
- zone->tones = tmp;
- free((void*)ts->name);
- free((void*)ts->data);
- free(ts);
- ts = tmp;
- res = 0;
- }
- else {
- /* next zone please */
- ps = ts;
- ts = ts->next;
- }
- }
- /* indication not found, goodbye */
- ast_mutex_unlock(&tzlock);
- return res;
-}
diff --git a/main/io.c b/main/io.c
deleted file mode 100644
index ced692180..000000000
--- a/main/io.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief I/O Managment (Derived from Cheops-NG)
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <termios.h>
-#include <string.h>
-#include <sys/ioctl.h>
-
-#include "asterisk/io.h"
-#include "asterisk/logger.h"
-#include "asterisk/utils.h"
-
-#ifdef DEBUG_IO
-#define DEBUG DEBUG_M
-#else
-#define DEBUG(a)
-#endif
-
-/*
- * Kept for each file descriptor
- */
-struct io_rec {
- ast_io_cb callback; /* What is to be called */
- void *data; /* Data to be passed */
- int *id; /* ID number */
-};
-
-/* These two arrays are keyed with
- the same index. it's too bad that
- pollfd doesn't have a callback field
- or something like that. They grow as
- needed, by GROW_SHRINK_SIZE structures
- at once */
-
-#define GROW_SHRINK_SIZE 512
-
-/* Global variables are now in a struct in order to be
- made threadsafe */
-struct io_context {
- /* Poll structure */
- struct pollfd *fds;
- /* Associated I/O records */
- struct io_rec *ior;
- /* First available fd */
- unsigned int fdcnt;
- /* Maximum available fd */
- unsigned int maxfdcnt;
- /* Currently used io callback */
- int current_ioc;
- /* Whether something has been deleted */
- int needshrink;
-};
-
-struct io_context *io_context_create(void)
-{
- /* Create an I/O context */
- struct io_context *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- tmp->needshrink = 0;
- tmp->fdcnt = 0;
- tmp->maxfdcnt = GROW_SHRINK_SIZE/2;
- tmp->current_ioc = -1;
- if (!(tmp->fds = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->fds)))) {
- free(tmp);
- tmp = NULL;
- } else {
- if (!(tmp->ior = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->ior)))) {
- free(tmp->fds);
- free(tmp);
- tmp = NULL;
- }
- }
- }
- return tmp;
-}
-
-void io_context_destroy(struct io_context *ioc)
-{
- /* Free associated memory with an I/O context */
- if (ioc->fds)
- free(ioc->fds);
- if (ioc->ior)
- free(ioc->ior);
- free(ioc);
-}
-
-static int io_grow(struct io_context *ioc)
-{
- /*
- * Grow the size of our arrays. Return 0 on success or
- * -1 on failure
- */
- void *tmp;
- DEBUG(ast_log(LOG_DEBUG, "io_grow()\n"));
- ioc->maxfdcnt += GROW_SHRINK_SIZE;
- if ((tmp = ast_realloc(ioc->ior, (ioc->maxfdcnt + 1) * sizeof(*ioc->ior)))) {
- ioc->ior = tmp;
- if ((tmp = ast_realloc(ioc->fds, (ioc->maxfdcnt + 1) * sizeof(*ioc->fds)))) {
- ioc->fds = tmp;
- } else {
- /*
- * Failed to allocate enough memory for the pollfd. Not
- * really any need to shrink back the iorec's as we'll
- * probably want to grow them again soon when more memory
- * is available, and then they'll already be the right size
- */
- ioc->maxfdcnt -= GROW_SHRINK_SIZE;
- return -1;
- }
- } else {
- /*
- * Memory allocation failure. We return to the old size, and
- * return a failure
- */
- ioc->maxfdcnt -= GROW_SHRINK_SIZE;
- return -1;
- }
- return 0;
-}
-
-int *ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
-{
- /*
- * Add a new I/O entry for this file descriptor
- * with the given event mask, to call callback with
- * data as an argument. Returns NULL on failure.
- */
- int *ret;
- DEBUG(ast_log(LOG_DEBUG, "ast_io_add()\n"));
- if (ioc->fdcnt >= ioc->maxfdcnt) {
- /*
- * We don't have enough space for this entry. We need to
- * reallocate maxfdcnt poll fd's and io_rec's, or back out now.
- */
- if (io_grow(ioc))
- return NULL;
- }
-
- /*
- * At this point, we've got sufficiently large arrays going
- * and we can make an entry for it in the pollfd and io_r
- * structures.
- */
- ioc->fds[ioc->fdcnt].fd = fd;
- ioc->fds[ioc->fdcnt].events = events;
- ioc->fds[ioc->fdcnt].revents = 0;
- ioc->ior[ioc->fdcnt].callback = callback;
- ioc->ior[ioc->fdcnt].data = data;
- if (!(ioc->ior[ioc->fdcnt].id = ast_malloc(sizeof(*ioc->ior[ioc->fdcnt].id)))) {
- /* Bonk if we couldn't allocate an int */
- return NULL;
- }
- *(ioc->ior[ioc->fdcnt].id) = ioc->fdcnt;
- ret = ioc->ior[ioc->fdcnt].id;
- ioc->fdcnt++;
- return ret;
-}
-
-int *ast_io_change(struct io_context *ioc, int *id, int fd, ast_io_cb callback, short events, void *data)
-{
- if (*id < ioc->fdcnt) {
- if (fd > -1)
- ioc->fds[*id].fd = fd;
- if (callback)
- ioc->ior[*id].callback = callback;
- if (events)
- ioc->fds[*id].events = events;
- if (data)
- ioc->ior[*id].data = data;
- return id;
- }
- return NULL;
-}
-
-static int io_shrink(struct io_context *ioc)
-{
- int getfrom;
- int putto = 0;
- /*
- * Bring the fields from the very last entry to cover over
- * the entry we are removing, then decrease the size of the
- * arrays by one.
- */
- for (getfrom = 0; getfrom < ioc->fdcnt; getfrom++) {
- if (ioc->ior[getfrom].id) {
- /* In use, save it */
- if (getfrom != putto) {
- ioc->fds[putto] = ioc->fds[getfrom];
- ioc->ior[putto] = ioc->ior[getfrom];
- *(ioc->ior[putto].id) = putto;
- }
- putto++;
- }
- }
- ioc->fdcnt = putto;
- ioc->needshrink = 0;
- /* FIXME: We should free some memory if we have lots of unused
- io structs */
- return 0;
-}
-
-int ast_io_remove(struct io_context *ioc, int *_id)
-{
- int x;
- if (!_id) {
- ast_log(LOG_WARNING, "Asked to remove NULL?\n");
- return -1;
- }
- for (x = 0; x < ioc->fdcnt; x++) {
- if (ioc->ior[x].id == _id) {
- /* Free the int immediately and set to NULL so we know it's unused now */
- free(ioc->ior[x].id);
- ioc->ior[x].id = NULL;
- ioc->fds[x].events = 0;
- ioc->fds[x].revents = 0;
- ioc->needshrink = 1;
- if (ioc->current_ioc == -1)
- io_shrink(ioc);
- return 0;
- }
- }
-
- ast_log(LOG_NOTICE, "Unable to remove unknown id %p\n", _id);
- return -1;
-}
-
-int ast_io_wait(struct io_context *ioc, int howlong)
-{
- /*
- * Make the poll call, and call
- * the callbacks for anything that needs
- * to be handled
- */
- int res;
- int x;
- int origcnt;
- DEBUG(ast_log(LOG_DEBUG, "ast_io_wait()\n"));
- res = poll(ioc->fds, ioc->fdcnt, howlong);
- if (res > 0) {
- /*
- * At least one event
- */
- origcnt = ioc->fdcnt;
- for(x = 0; x < origcnt; x++) {
- /* Yes, it is possible for an entry to be deleted and still have an
- event waiting if it occurs after the original calling id */
- if (ioc->fds[x].revents && ioc->ior[x].id) {
- /* There's an event waiting */
- ioc->current_ioc = *ioc->ior[x].id;
- if (ioc->ior[x].callback) {
- if (!ioc->ior[x].callback(ioc->ior[x].id, ioc->fds[x].fd, ioc->fds[x].revents, ioc->ior[x].data)) {
- /* Time to delete them since they returned a 0 */
- ast_io_remove(ioc, ioc->ior[x].id);
- }
- }
- ioc->current_ioc = -1;
- }
- }
- if (ioc->needshrink)
- io_shrink(ioc);
- }
- return res;
-}
-
-void ast_io_dump(struct io_context *ioc)
-{
- /*
- * Print some debugging information via
- * the logger interface
- */
- int x;
- ast_log(LOG_DEBUG, "Asterisk IO Dump: %d entries, %d max entries\n", ioc->fdcnt, ioc->maxfdcnt);
- ast_log(LOG_DEBUG, "================================================\n");
- ast_log(LOG_DEBUG, "| ID FD Callback Data Events |\n");
- ast_log(LOG_DEBUG, "+------+------+-----------+-----------+--------+\n");
- for (x = 0; x < ioc->fdcnt; x++) {
- ast_log(LOG_DEBUG, "| %.4d | %.4d | %p | %p | %.6x |\n",
- *ioc->ior[x].id,
- ioc->fds[x].fd,
- ioc->ior[x].callback,
- ioc->ior[x].data,
- ioc->fds[x].events);
- }
- ast_log(LOG_DEBUG, "================================================\n");
-}
-
-/* Unrelated I/O functions */
-
-int ast_hide_password(int fd)
-{
- struct termios tios;
- int res;
- int old;
- if (!isatty(fd))
- return -1;
- res = tcgetattr(fd, &tios);
- if (res < 0)
- return -1;
- old = tios.c_lflag & (ECHO | ECHONL);
- tios.c_lflag &= ~ECHO;
- tios.c_lflag |= ECHONL;
- res = tcsetattr(fd, TCSAFLUSH, &tios);
- if (res < 0)
- return -1;
- return old;
-}
-
-int ast_restore_tty(int fd, int oldstate)
-{
- int res;
- struct termios tios;
- if (oldstate < 0)
- return 0;
- res = tcgetattr(fd, &tios);
- if (res < 0)
- return -1;
- tios.c_lflag &= ~(ECHO | ECHONL);
- tios.c_lflag |= oldstate;
- res = tcsetattr(fd, TCSAFLUSH, &tios);
- if (res < 0)
- return -1;
- return 0;
-}
-
-int ast_get_termcols(int fd)
-{
- struct winsize win;
- int cols = 0;
-
- if (!isatty(fd))
- return -1;
-
- if ( ioctl(fd, TIOCGWINSZ, &win) != -1 ) {
- if ( !cols && win.ws_col > 0 )
- cols = (int) win.ws_col;
- } else {
- /* assume 80 characters if the ioctl fails for some reason */
- cols = 80;
- }
-
- return cols;
-}
-
diff --git a/main/jitterbuf.c b/main/jitterbuf.c
deleted file mode 100644
index 849cffab5..000000000
--- a/main/jitterbuf.c
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2004-2005, Horizon Wimba, Inc.
- *
- * Contributors:
- * Steve Kann <stevek@stevek.com>
- *
- * A license has been granted to Digium (via disclaimer) for the use of
- * this code.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief jitterbuf: an application-independent jitterbuffer
- * \author Steve Kann <stevek@stevek.com>
- *
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "jitterbuf.h"
-#include "asterisk/utils.h"
-
-/*! define these here, just for ancient compiler systems */
-#define JB_LONGMAX 2147483647L
-#define JB_LONGMIN (-JB_LONGMAX - 1L)
-
-#define jb_warn(...) (warnf ? warnf(__VA_ARGS__) : (void)0)
-#define jb_err(...) (errf ? errf(__VA_ARGS__) : (void)0)
-#define jb_dbg(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
-
-#ifdef DEEP_DEBUG
-#define jb_dbg2(...) (dbgf ? dbgf(__VA_ARGS__) : (void)0)
-#else
-#define jb_dbg2(...) ((void)0)
-#endif
-
-static jb_output_function_t warnf, errf, dbgf;
-
-void jb_setoutput(jb_output_function_t err, jb_output_function_t warn, jb_output_function_t dbg)
-{
- errf = err;
- warnf = warn;
- dbgf = dbg;
-}
-
-static void increment_losspct(jitterbuf *jb)
-{
- jb->info.losspct = (100000 + 499 * jb->info.losspct)/500;
-}
-
-static void decrement_losspct(jitterbuf *jb)
-{
- jb->info.losspct = (499 * jb->info.losspct)/500;
-}
-
-void jb_reset(jitterbuf *jb)
-{
- /* only save settings */
- jb_conf s = jb->info.conf;
- memset(jb, 0, sizeof(*jb));
- jb->info.conf = s;
-
- /* initialize length */
- jb->info.current = jb->info.target = JB_TARGET_EXTRA;
- jb->info.silence_begin_ts = -1;
-}
-
-jitterbuf * jb_new()
-{
- jitterbuf *jb;
-
- if (!(jb = ast_malloc(sizeof(*jb))))
- return NULL;
-
- jb_reset(jb);
-
- jb_dbg2("jb_new() = %x\n", jb);
- return jb;
-}
-
-void jb_destroy(jitterbuf *jb)
-{
- jb_frame *frame;
- jb_dbg2("jb_destroy(%x)\n", jb);
-
- /* free all the frames on the "free list" */
- frame = jb->free;
- while (frame != NULL) {
- jb_frame *next = frame->next;
- free(frame);
- frame = next;
- }
-
- /* free ourselves! */
- free(jb);
-}
-
-
-
-#if 0
-static int longcmp(const void *a, const void *b)
-{
- return *(long *)a - *(long *)b;
-}
-#endif
-
-/*! \brief simple history manipulation
- \note maybe later we can make the history buckets variable size, or something? */
-/* drop parameter determines whether we will drop outliers to minimize
- * delay */
-static int history_put(jitterbuf *jb, long ts, long now, long ms)
-{
- long delay = now - (ts - jb->info.resync_offset);
- long threshold = 2 * jb->info.jitter + jb->info.conf.resync_threshold;
- long kicked;
-
- /* don't add special/negative times to history */
- if (ts <= 0)
- return 0;
-
- /* check for drastic change in delay */
- if (jb->info.conf.resync_threshold != -1) {
- if (abs(delay - jb->info.last_delay) > threshold) {
- jb->info.cnt_delay_discont++;
- if (jb->info.cnt_delay_discont > 3) {
- /* resync the jitterbuffer */
- jb->info.cnt_delay_discont = 0;
- jb->hist_ptr = 0;
- jb->hist_maxbuf_valid = 0;
-
- jb_warn("Resyncing the jb. last_delay %ld, this delay %ld, threshold %ld, new offset %ld\n", jb->info.last_delay, delay, threshold, ts - now);
- jb->info.resync_offset = ts - now;
- jb->info.last_delay = delay = 0; /* after resync, frame is right on time */
- } else {
- return -1;
- }
- } else {
- jb->info.last_delay = delay;
- jb->info.cnt_delay_discont = 0;
- }
- }
-
- kicked = jb->history[jb->hist_ptr % JB_HISTORY_SZ];
-
- jb->history[(jb->hist_ptr++) % JB_HISTORY_SZ] = delay;
-
- /* optimization; the max/min buffers don't need to be recalculated, if this packet's
- * entry doesn't change them. This happens if this packet is not involved, _and_ any packet
- * that got kicked out of the history is also not involved
- * We do a number of comparisons, but it's probably still worthwhile, because it will usually
- * succeed, and should be a lot faster than going through all 500 packets in history */
- if (!jb->hist_maxbuf_valid)
- return 0;
-
- /* don't do this until we've filled history
- * (reduces some edge cases below) */
- if (jb->hist_ptr < JB_HISTORY_SZ)
- goto invalidate;
-
- /* if the new delay would go into min */
- if (delay < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
- goto invalidate;
-
- /* or max.. */
- if (delay > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
- goto invalidate;
-
- /* or the kicked delay would be in min */
- if (kicked <= jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1])
- goto invalidate;
-
- if (kicked >= jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1])
- goto invalidate;
-
- /* if we got here, we don't need to invalidate, 'cause this delay didn't
- * affect things */
- return 0;
- /* end optimization */
-
-
-invalidate:
- jb->hist_maxbuf_valid = 0;
- return 0;
-}
-
-static void history_calc_maxbuf(jitterbuf *jb)
-{
- int i,j;
-
- if (jb->hist_ptr == 0)
- return;
-
-
- /* initialize maxbuf/minbuf to the latest value */
- for (i=0;i<JB_HISTORY_MAXBUF_SZ;i++) {
-/*
- * jb->hist_maxbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
- * jb->hist_minbuf[i] = jb->history[(jb->hist_ptr-1) % JB_HISTORY_SZ];
- */
- jb->hist_maxbuf[i] = JB_LONGMIN;
- jb->hist_minbuf[i] = JB_LONGMAX;
- }
-
- /* use insertion sort to populate maxbuf */
- /* we want it to be the top "n" values, in order */
-
- /* start at the beginning, or JB_HISTORY_SZ frames ago */
- i = (jb->hist_ptr > JB_HISTORY_SZ) ? (jb->hist_ptr - JB_HISTORY_SZ) : 0;
-
- for (;i<jb->hist_ptr;i++) {
- long toins = jb->history[i % JB_HISTORY_SZ];
-
- /* if the maxbuf should get this */
- if (toins > jb->hist_maxbuf[JB_HISTORY_MAXBUF_SZ-1]) {
-
- /* insertion-sort it into the maxbuf */
- for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
- /* found where it fits */
- if (toins > jb->hist_maxbuf[j]) {
- /* move over */
- memmove(jb->hist_maxbuf + j + 1, jb->hist_maxbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_maxbuf[0]));
- /* insert */
- jb->hist_maxbuf[j] = toins;
-
- break;
- }
- }
- }
-
- /* if the minbuf should get this */
- if (toins < jb->hist_minbuf[JB_HISTORY_MAXBUF_SZ-1]) {
-
- /* insertion-sort it into the maxbuf */
- for (j=0;j<JB_HISTORY_MAXBUF_SZ;j++) {
- /* found where it fits */
- if (toins < jb->hist_minbuf[j]) {
- /* move over */
- memmove(jb->hist_minbuf + j + 1, jb->hist_minbuf + j, (JB_HISTORY_MAXBUF_SZ - (j + 1)) * sizeof(jb->hist_minbuf[0]));
- /* insert */
- jb->hist_minbuf[j] = toins;
-
- break;
- }
- }
- }
-
- if (0) {
- int k;
- fprintf(stderr, "toins = %ld\n", toins);
- fprintf(stderr, "maxbuf =");
- for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
- fprintf(stderr, "%ld ", jb->hist_maxbuf[k]);
- fprintf(stderr, "\nminbuf =");
- for (k=0;k<JB_HISTORY_MAXBUF_SZ;k++)
- fprintf(stderr, "%ld ", jb->hist_minbuf[k]);
- fprintf(stderr, "\n");
- }
- }
-
- jb->hist_maxbuf_valid = 1;
-}
-
-static void history_get(jitterbuf *jb)
-{
- long max, min, jitter;
- int index;
- int count;
-
- if (!jb->hist_maxbuf_valid)
- history_calc_maxbuf(jb);
-
- /* count is how many items in history we're examining */
- count = (jb->hist_ptr < JB_HISTORY_SZ) ? jb->hist_ptr : JB_HISTORY_SZ;
-
- /* index is the "n"ths highest/lowest that we'll look for */
- index = count * JB_HISTORY_DROPPCT / 100;
-
- /* sanity checks for index */
- if (index > (JB_HISTORY_MAXBUF_SZ - 1))
- index = JB_HISTORY_MAXBUF_SZ - 1;
-
-
- if (index < 0) {
- jb->info.min = 0;
- jb->info.jitter = 0;
- return;
- }
-
- max = jb->hist_maxbuf[index];
- min = jb->hist_minbuf[index];
-
- jitter = max - min;
-
- /* these debug stmts compare the difference between looking at the absolute jitter, and the
- * values we get by throwing away the outliers */
- /*
- fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", index, min, max, jitter);
- fprintf(stderr, "[%d] min=%d, max=%d, jitter=%d\n", 0, jb->hist_minbuf[0], jb->hist_maxbuf[0], jb->hist_maxbuf[0]-jb->hist_minbuf[0]);
- */
-
- jb->info.min = min;
- jb->info.jitter = jitter;
-}
-
-/* returns 1 if frame was inserted into head of queue, 0 otherwise */
-static int queue_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts)
-{
- jb_frame *frame;
- jb_frame *p;
- int head = 0;
- long resync_ts = ts - jb->info.resync_offset;
-
- if ((frame = jb->free)) {
- jb->free = frame->next;
- } else if (!(frame = ast_malloc(sizeof(*frame)))) {
- jb_err("cannot allocate frame\n");
- return 0;
- }
-
- jb->info.frames_cur++;
-
- frame->data = data;
- frame->ts = resync_ts;
- frame->ms = ms;
- frame->type = type;
-
- /*
- * frames are a circular list, jb-frames points to to the lowest ts,
- * jb->frames->prev points to the highest ts
- */
-
- if (!jb->frames) { /* queue is empty */
- jb->frames = frame;
- frame->next = frame;
- frame->prev = frame;
- head = 1;
- } else if (resync_ts < jb->frames->ts) {
- frame->next = jb->frames;
- frame->prev = jb->frames->prev;
-
- frame->next->prev = frame;
- frame->prev->next = frame;
-
- /* frame is out of order */
- jb->info.frames_ooo++;
-
- jb->frames = frame;
- head = 1;
- } else {
- p = jb->frames;
-
- /* frame is out of order */
- if (resync_ts < p->prev->ts) jb->info.frames_ooo++;
-
- while (resync_ts < p->prev->ts && p->prev != jb->frames)
- p = p->prev;
-
- frame->next = p;
- frame->prev = p->prev;
-
- frame->next->prev = frame;
- frame->prev->next = frame;
- }
- return head;
-}
-
-static long queue_next(jitterbuf *jb)
-{
- if (jb->frames)
- return jb->frames->ts;
- else
- return -1;
-}
-
-static long queue_last(jitterbuf *jb)
-{
- if (jb->frames)
- return jb->frames->prev->ts;
- else
- return -1;
-}
-
-static jb_frame *_queue_get(jitterbuf *jb, long ts, int all)
-{
- jb_frame *frame;
- frame = jb->frames;
-
- if (!frame)
- return NULL;
-
- /*jb_warn("queue_get: ASK %ld FIRST %ld\n", ts, frame->ts); */
-
- if (all || ts >= frame->ts) {
- /* remove this frame */
- frame->prev->next = frame->next;
- frame->next->prev = frame->prev;
-
- if (frame->next == frame)
- jb->frames = NULL;
- else
- jb->frames = frame->next;
-
-
- /* insert onto "free" single-linked list */
- frame->next = jb->free;
- jb->free = frame;
-
- jb->info.frames_cur--;
-
- /* we return the frame pointer, even though it's on free list,
- * but caller must copy data */
- return frame;
- }
-
- return NULL;
-}
-
-static jb_frame *queue_get(jitterbuf *jb, long ts)
-{
- return _queue_get(jb,ts,0);
-}
-
-static jb_frame *queue_getall(jitterbuf *jb)
-{
- return _queue_get(jb,0,1);
-}
-
-#if 0
-/* some diagnostics */
-static void jb_dbginfo(jitterbuf *jb)
-{
- if (dbgf == NULL)
- return;
-
- jb_dbg("\njb info: fin=%ld fout=%ld flate=%ld flost=%ld fdrop=%ld fcur=%ld\n",
- jb->info.frames_in, jb->info.frames_out, jb->info.frames_late, jb->info.frames_lost, jb->info.frames_dropped, jb->info.frames_cur);
-
- jb_dbg("jitter=%ld current=%ld target=%ld min=%ld sil=%d len=%d len/fcur=%ld\n",
- jb->info.jitter, jb->info.current, jb->info.target, jb->info.min, jb->info.silence_begin_ts, jb->info.current - jb->info.min,
- jb->info.frames_cur ? (jb->info.current - jb->info.min)/jb->info.frames_cur : -8);
- if (jb->info.frames_in > 0)
- jb_dbg("jb info: Loss PCT = %ld%%, Late PCT = %ld%%\n",
- jb->info.frames_lost * 100/(jb->info.frames_in + jb->info.frames_lost),
- jb->info.frames_late * 100/jb->info.frames_in);
- jb_dbg("jb info: queue %d -> %d. last_ts %d (queue len: %d) last_ms %d\n",
- queue_next(jb),
- queue_last(jb),
- jb->info.next_voice_ts,
- queue_last(jb) - queue_next(jb),
- jb->info.last_voice_ms);
-}
-#endif
-
-#ifdef DEEP_DEBUG
-static void jb_chkqueue(jitterbuf *jb)
-{
- int i=0;
- jb_frame *p = jb->frames;
-
- if (!p) {
- return;
- }
-
- do {
- if (p->next == NULL) {
- jb_err("Queue is BROKEN at item [%d]", i);
- }
- i++;
- p=p->next;
- } while (p->next != jb->frames);
-}
-
-static void jb_dbgqueue(jitterbuf *jb)
-{
- int i=0;
- jb_frame *p = jb->frames;
-
- jb_dbg("queue: ");
-
- if (!p) {
- jb_dbg("EMPTY\n");
- return;
- }
-
- do {
- jb_dbg("[%d]=%ld ", i++, p->ts);
- p=p->next;
- } while (p->next != jb->frames);
-
- jb_dbg("\n");
-}
-#endif
-
-enum jb_return_code jb_put(jitterbuf *jb, void *data, const enum jb_frame_type type, long ms, long ts, long now)
-{
- long numts;
-
- jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now);
-
- jb->info.frames_in++;
-
- if (jb->frames && jb->dropem)
- return JB_DROP;
- jb->dropem = 0;
-
- if (type == JB_TYPE_VOICE) {
- /* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the
- * IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */
- if (history_put(jb,ts,now,ms))
- return JB_DROP;
- }
- numts = 0;
- if (jb->frames)
- numts = jb->frames->prev->ts - jb->frames->ts;
- if (numts >= jb->info.conf.max_jitterbuf) {
- ast_log(LOG_DEBUG, "Attempting to exceed Jitterbuf max %ld timeslots\n",
- jb->info.conf.max_jitterbuf);
- jb->dropem = 1;
- return JB_DROP;
- }
- /* if put into head of queue, caller needs to reschedule */
- if (queue_put(jb,data,type,ms,ts)) {
- return JB_SCHED;
- }
- return JB_OK;
-}
-
-
-static enum jb_return_code _jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
-{
- jb_frame *frame;
- long diff;
- static int dbg_cnt = 0;
-
- /*if ((now - jb_next(jb)) > 2 * jb->info.last_voice_ms) jb_warn("SCHED: %ld", (now - jb_next(jb))); */
- /* get jitter info */
- history_get(jb);
-
- if (dbg_cnt && dbg_cnt % 50 == 0) {
- jb_dbg("\n");
- }
- dbg_cnt++;
-
- /* target */
- jb->info.target = jb->info.jitter + jb->info.min + JB_TARGET_EXTRA;
-
- /* if a hard clamp was requested, use it */
- if ((jb->info.conf.max_jitterbuf) && ((jb->info.target - jb->info.min) > jb->info.conf.max_jitterbuf)) {
- jb_dbg("clamping target from %ld to %ld\n", (jb->info.target - jb->info.min), jb->info.conf.max_jitterbuf);
- jb->info.target = jb->info.min + jb->info.conf.max_jitterbuf;
- }
-
- diff = jb->info.target - jb->info.current;
-
- /* jb_warn("diff = %d lms=%d last = %d now = %d\n", diff, */
- /* jb->info.last_voice_ms, jb->info.last_adjustment, now); */
-
- /* let's work on non-silent case first */
- if (!jb->info.silence_begin_ts) {
- /* we want to grow */
- if ((diff > 0) &&
- /* we haven't grown in the delay length */
- (((jb->info.last_adjustment + JB_ADJUST_DELAY) < now) ||
- /* we need to grow more than the "length" we have left */
- (diff > queue_last(jb) - queue_next(jb)) ) ) {
- /* grow by interp frame length */
- jb->info.current += interpl;
- jb->info.next_voice_ts += interpl;
- jb->info.last_voice_ms = interpl;
- jb->info.last_adjustment = now;
- jb->info.cnt_contig_interp++;
- if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
- jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
- }
- jb_dbg("G");
- return JB_INTERP;
- }
-
- frame = queue_get(jb, jb->info.next_voice_ts - jb->info.current);
-
- /* not a voice frame; just return it. */
- if (frame && frame->type != JB_TYPE_VOICE) {
- if (frame->type == JB_TYPE_SILENCE) {
- jb->info.silence_begin_ts = frame->ts;
- jb->info.cnt_contig_interp = 0;
- }
-
- *frameout = *frame;
- jb->info.frames_out++;
- jb_dbg("o");
- return JB_OK;
- }
-
-
- /* voice frame is later than expected */
- if (frame && frame->ts + jb->info.current < jb->info.next_voice_ts) {
- if (frame->ts + jb->info.current > jb->info.next_voice_ts - jb->info.last_voice_ms) {
- /* either we interpolated past this frame in the last jb_get */
- /* or the frame is still in order, but came a little too quick */
- *frameout = *frame;
- /* reset expectation for next frame */
- jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
- jb->info.frames_out++;
- decrement_losspct(jb);
- jb->info.cnt_contig_interp = 0;
- jb_dbg("v");
- return JB_OK;
- } else {
- /* voice frame is late */
- *frameout = *frame;
- jb->info.frames_out++;
- decrement_losspct(jb);
- jb->info.frames_late++;
- jb->info.frames_lost--;
- jb_dbg("l");
- /*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
- jb_warninfo(jb); */
- return JB_DROP;
- }
- }
-
- /* keep track of frame sizes, to allow for variable sized-frames */
- if (frame && frame->ms > 0) {
- jb->info.last_voice_ms = frame->ms;
- }
-
- /* we want to shrink; shrink at 1 frame / 500ms */
- /* unless we don't have a frame, then shrink 1 frame */
- /* every 80ms (though perhaps we can shrink even faster */
- /* in this case) */
- if (diff < -JB_TARGET_EXTRA &&
- ((!frame && jb->info.last_adjustment + 80 < now) ||
- (jb->info.last_adjustment + 500 < now))) {
-
- jb->info.last_adjustment = now;
- jb->info.cnt_contig_interp = 0;
-
- if (frame) {
- *frameout = *frame;
- /* shrink by frame size we're throwing out */
- jb->info.current -= frame->ms;
- jb->info.frames_out++;
- decrement_losspct(jb);
- jb->info.frames_dropped++;
- jb_dbg("s");
- return JB_DROP;
- } else {
- /* shrink by last_voice_ms */
- jb->info.current -= jb->info.last_voice_ms;
- jb->info.frames_lost++;
- increment_losspct(jb);
- jb_dbg("S");
- return JB_NOFRAME;
- }
- }
-
- /* lost frame */
- if (!frame) {
- /* this is a bit of a hack for now, but if we're close to
- * target, and we find a missing frame, it makes sense to
- * grow, because the frame might just be a bit late;
- * otherwise, we presently get into a pattern where we return
- * INTERP for the lost frame, then it shows up next, and we
- * throw it away because it's late */
- /* I've recently only been able to replicate this using
- * iaxclient talking to app_echo on asterisk. In this case,
- * my outgoing packets go through asterisk's (old)
- * jitterbuffer, and then might get an unusual increasing delay
- * there if it decides to grow?? */
- /* Update: that might have been a different bug, that has been fixed..
- * But, this still seemed like a good idea, except that it ended up making a single actual
- * lost frame get interpolated two or more times, when there was "room" to grow, so it might
- * be a bit of a bad idea overall */
- /*if (diff > -1 * jb->info.last_voice_ms) {
- jb->info.current += jb->info.last_voice_ms;
- jb->info.last_adjustment = now;
- jb_warn("g");
- return JB_INTERP;
- } */
- jb->info.frames_lost++;
- increment_losspct(jb);
- jb->info.next_voice_ts += interpl;
- jb->info.last_voice_ms = interpl;
- jb->info.cnt_contig_interp++;
- if (jb->info.conf.max_contig_interp && jb->info.cnt_contig_interp >= jb->info.conf.max_contig_interp) {
- jb->info.silence_begin_ts = jb->info.next_voice_ts - jb->info.current;
- }
- jb_dbg("L");
- return JB_INTERP;
- }
-
- /* normal case; return the frame, increment stuff */
- *frameout = *frame;
- jb->info.next_voice_ts += frame->ms;
- jb->info.frames_out++;
- jb->info.cnt_contig_interp = 0;
- decrement_losspct(jb);
- jb_dbg("v");
- return JB_OK;
- } else {
- /* TODO: after we get the non-silent case down, we'll make the
- * silent case -- basically, we'll just grow and shrink faster
- * here, plus handle next_voice_ts a bit differently */
-
- /* to disable silent special case altogether, just uncomment this: */
- /* jb->info.silence_begin_ts = 0; */
-
- /* shrink interpl len every 10ms during silence */
- if (diff < -JB_TARGET_EXTRA &&
- jb->info.last_adjustment + 10 <= now) {
- jb->info.current -= interpl;
- jb->info.last_adjustment = now;
- }
-
- frame = queue_get(jb, now - jb->info.current);
- if (!frame) {
- return JB_NOFRAME;
- } else if (frame->type != JB_TYPE_VOICE) {
- /* normal case; in silent mode, got a non-voice frame */
- *frameout = *frame;
- jb->info.frames_out++;
- return JB_OK;
- }
- if (frame->ts < jb->info.silence_begin_ts) {
- /* voice frame is late */
- *frameout = *frame;
- jb->info.frames_out++;
- decrement_losspct(jb);
- jb->info.frames_late++;
- jb->info.frames_lost--;
- jb_dbg("l");
- /*jb_warn("\nlate: wanted=%ld, this=%ld, next=%ld\n", jb->info.next_voice_ts - jb->info.current, frame->ts, queue_next(jb));
- jb_warninfo(jb); */
- return JB_DROP;
- } else {
- /* voice frame */
- /* try setting current to target right away here */
- jb->info.current = jb->info.target;
- jb->info.silence_begin_ts = 0;
- jb->info.next_voice_ts = frame->ts + jb->info.current + frame->ms;
- jb->info.last_voice_ms = frame->ms;
- jb->info.frames_out++;
- decrement_losspct(jb);
- *frameout = *frame;
- jb_dbg("V");
- return JB_OK;
- }
- }
-}
-
-long jb_next(jitterbuf *jb)
-{
- if (jb->info.silence_begin_ts) {
- if (jb->frames) {
- long next = queue_next(jb);
- history_get(jb);
- /* shrink during silence */
- if (jb->info.target - jb->info.current < -JB_TARGET_EXTRA)
- return jb->info.last_adjustment + 10;
- return next + jb->info.target;
- }
- else
- return JB_LONGMAX;
- } else {
- return jb->info.next_voice_ts;
- }
-}
-
-enum jb_return_code jb_get(jitterbuf *jb, jb_frame *frameout, long now, long interpl)
-{
- enum jb_return_code ret = _jb_get(jb, frameout, now, interpl);
-#if 0
- static int lastts=0;
- int thists = ((ret == JB_OK) || (ret == JB_DROP)) ? frameout->ts : 0;
- jb_warn("jb_get(%x,%x,%ld) = %d (%d)\n", jb, frameout, now, ret, thists);
- if (thists && thists < lastts) jb_warn("XXXX timestamp roll-back!!!\n");
- lastts = thists;
-#endif
- if(ret == JB_INTERP)
- frameout->ms = jb->info.last_voice_ms;
-
- return ret;
-}
-
-enum jb_return_code jb_getall(jitterbuf *jb, jb_frame *frameout)
-{
- jb_frame *frame;
- frame = queue_getall(jb);
-
- if (!frame) {
- return JB_NOFRAME;
- }
-
- *frameout = *frame;
- return JB_OK;
-}
-
-
-enum jb_return_code jb_getinfo(jitterbuf *jb, jb_info *stats)
-{
-
- history_get(jb);
-
- *stats = jb->info;
-
- return JB_OK;
-}
-
-enum jb_return_code jb_setconf(jitterbuf *jb, jb_conf *conf)
-{
- /* take selected settings from the struct */
-
- jb->info.conf.max_jitterbuf = conf->max_jitterbuf;
- jb->info.conf.resync_threshold = conf->resync_threshold;
- jb->info.conf.max_contig_interp = conf->max_contig_interp;
-
- return JB_OK;
-}
-
-
diff --git a/main/loader.c b/main/loader.c
deleted file mode 100644
index 60c8a7676..000000000
--- a/main/loader.c
+++ /dev/null
@@ -1,1001 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- * Kevin P. Fleming <kpfleming@digium.com>
- * Luigi Rizzo <rizzo@icir.org>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Module Loader
- * \author Mark Spencer <markster@digium.com>
- * \author Kevin P. Fleming <kpfleming@digium.com>
- * \author Luigi Rizzo <rizzo@icir.org>
- * - See ModMngMnt
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-#include "asterisk/linkedlists.h"
-#include "asterisk/module.h"
-#include "asterisk/options.h"
-#include "asterisk/config.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/term.h"
-#include "asterisk/manager.h"
-#include "asterisk/cdr.h"
-#include "asterisk/enum.h"
-#include "asterisk/rtp.h"
-#include "asterisk/http.h"
-#include "asterisk/lock.h"
-
-#include <dlfcn.h>
-
-#include "asterisk/md5.h"
-#include "asterisk/utils.h"
-
-#ifndef RTLD_NOW
-#define RTLD_NOW 0
-#endif
-
-struct ast_module_user {
- struct ast_channel *chan;
- AST_LIST_ENTRY(ast_module_user) entry;
-};
-
-AST_LIST_HEAD(module_user_list, ast_module_user);
-
-static unsigned char expected_key[] =
-{ 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
- 0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
-
-static char buildopt_sum[33] = AST_BUILDOPT_SUM;
-
-static unsigned int embedding = 1; /* we always start out by registering embedded modules,
- since they are here before we dlopen() any
- */
-
-struct ast_module {
- const struct ast_module_info *info;
- void *lib; /* the shared lib, or NULL if embedded */
- int usecount; /* the number of 'users' currently in this module */
- struct module_user_list users; /* the list of users in the module */
- struct {
- unsigned int running:1;
- unsigned int declined:1;
- } flags;
- AST_LIST_ENTRY(ast_module) entry;
- char resource[0];
-};
-
-static AST_LIST_HEAD_STATIC(module_list, ast_module);
-
-struct loadupdate {
- int (*updater)(void);
- AST_LIST_ENTRY(loadupdate) entry;
-};
-
-static AST_LIST_HEAD_STATIC(updaters, loadupdate);
-
-AST_MUTEX_DEFINE_STATIC(reloadlock);
-
-/* when dynamic modules are being loaded, ast_module_register() will
- need to know what filename the module was loaded from while it
- is being registered
-*/
-struct ast_module *resource_being_loaded;
-
-/* XXX: should we check for duplicate resource names here? */
-
-void ast_module_register(const struct ast_module_info *info)
-{
- struct ast_module *mod;
-
- if (embedding) {
- if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
- return;
- strcpy(mod->resource, info->name);
- } else {
- mod = resource_being_loaded;
- }
-
- mod->info = info;
- AST_LIST_HEAD_INIT(&mod->users);
-
- /* during startup, before the loader has been initialized,
- there are no threads, so there is no need to take the lock
- on this list to manipulate it. it is also possible that it
- might be unsafe to use the list lock at that point... so
- let's avoid it altogether
- */
- if (!embedding)
- AST_LIST_LOCK(&module_list);
-
- /* it is paramount that the new entry be placed at the tail of
- the list, otherwise the code that uses dlopen() to load
- dynamic modules won't be able to find out if the module it
- just opened was registered or failed to load
- */
- AST_LIST_INSERT_TAIL(&module_list, mod, entry);
-
- if (!embedding)
- AST_LIST_UNLOCK(&module_list);
-
- /* give the module a copy of its own handle, for later use in registrations and the like */
- *((struct ast_module **) &(info->self)) = mod;
-}
-
-void ast_module_unregister(const struct ast_module_info *info)
-{
- struct ast_module *mod = NULL;
-
- /* it is assumed that the users list in the module structure
- will already be empty, or we cannot have gotten to this
- point
- */
- AST_LIST_LOCK(&module_list);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
- if (mod->info == info) {
- AST_LIST_REMOVE_CURRENT(&module_list, entry);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&module_list);
-
- if (mod) {
- AST_LIST_HEAD_DESTROY(&mod->users);
- free(mod);
- }
-}
-
-struct ast_module_user *__ast_module_user_add(struct ast_module *mod,
- struct ast_channel *chan)
-{
- struct ast_module_user *u = ast_calloc(1, sizeof(*u));
-
- if (!u)
- return NULL;
-
- u->chan = chan;
-
- AST_LIST_LOCK(&mod->users);
- AST_LIST_INSERT_HEAD(&mod->users, u, entry);
- AST_LIST_UNLOCK(&mod->users);
-
- ast_atomic_fetchadd_int(&mod->usecount, +1);
-
- ast_update_use_count();
-
- return u;
-}
-
-void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
-{
- AST_LIST_LOCK(&mod->users);
- AST_LIST_REMOVE(&mod->users, u, entry);
- AST_LIST_UNLOCK(&mod->users);
- ast_atomic_fetchadd_int(&mod->usecount, -1);
- free(u);
-
- ast_update_use_count();
-}
-
-void __ast_module_user_hangup_all(struct ast_module *mod)
-{
- struct ast_module_user *u;
-
- AST_LIST_LOCK(&mod->users);
- while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
- ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
- ast_atomic_fetchadd_int(&mod->usecount, -1);
- free(u);
- }
- AST_LIST_UNLOCK(&mod->users);
-
- ast_update_use_count();
-}
-
-/*! \note
- * In addition to modules, the reload command handles some extra keywords
- * which are listed here together with the corresponding handlers.
- * This table is also used by the command completion code.
- */
-static struct reload_classes {
- const char *name;
- int (*reload_fn)(void);
-} reload_classes[] = { /* list in alpha order, longest match first for cli completion */
- { "cdr", ast_cdr_engine_reload },
- { "dnsmgr", dnsmgr_reload },
- { "extconfig", read_config_maps },
- { "enum", ast_enum_reload },
- { "manager", reload_manager },
- { "rtp", ast_rtp_reload },
- { "http", ast_http_reload },
- { "logger", logger_reload },
- { NULL, NULL }
-};
-
-static int printdigest(const unsigned char *d)
-{
- int x, pos;
- char buf[256]; /* large enough so we don't have to worry */
-
- for (pos = 0, x = 0; x < 16; x++)
- pos += sprintf(buf + pos, " %02x", *d++);
-
- ast_log(LOG_DEBUG, "Unexpected signature:%s\n", buf);
-
- return 0;
-}
-
-static int key_matches(const unsigned char *key1, const unsigned char *key2)
-{
- int x;
-
- for (x = 0; x < 16; x++) {
- if (key1[x] != key2[x])
- return 0;
- }
-
- return 1;
-}
-
-static int verify_key(const unsigned char *key)
-{
- struct MD5Context c;
- unsigned char digest[16];
-
- MD5Init(&c);
- MD5Update(&c, key, strlen((char *)key));
- MD5Final(digest, &c);
-
- if (key_matches(expected_key, digest))
- return 0;
-
- printdigest(digest);
-
- return -1;
-}
-
-static int resource_name_match(const char *name1_in, const char *name2_in)
-{
- char *name1 = (char *) name1_in;
- char *name2 = (char *) name2_in;
-
- /* trim off any .so extensions */
- if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
- name1 = ast_strdupa(name1);
- name1[strlen(name1) - 3] = '\0';
- }
- if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
- name2 = ast_strdupa(name2);
- name2[strlen(name2) - 3] = '\0';
- }
-
- return strcasecmp(name1, name2);
-}
-
-static struct ast_module *find_resource(const char *resource, int do_lock)
-{
- struct ast_module *cur;
-
- if (do_lock)
- AST_LIST_LOCK(&module_list);
-
- AST_LIST_TRAVERSE(&module_list, cur, entry) {
- if (!resource_name_match(resource, cur->resource))
- break;
- }
-
- if (do_lock)
- AST_LIST_UNLOCK(&module_list);
-
- return cur;
-}
-
-#ifdef LOADABLE_MODULES
-static void unload_dynamic_module(struct ast_module *mod)
-{
- void *lib = mod->lib;
-
- /* WARNING: the structure pointed to by mod is going to
- disappear when this operation succeeds, so we can't
- dereference it */
-
- if (lib)
- while (!dlclose(lib));
-}
-
-static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only)
-{
- char fn[256];
- void *lib;
- struct ast_module *mod;
- char *resource = (char *) resource_in;
- unsigned int wants_global;
-
- if (strcasecmp(resource + strlen(resource) - 3, ".so")) {
- resource = alloca(strlen(resource_in) + 3);
- strcpy(resource, resource_in);
- strcat(resource, ".so");
- }
-
- snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR, resource);
-
- /* make a first load of the module in 'quiet' mode... don't try to resolve
- any symbols, and don't export any symbols. this will allow us to peek into
- the module's info block (if available) to see what flags it has set */
-
- if (!(resource_being_loaded = ast_calloc(1, sizeof(*resource_being_loaded) + strlen(resource) + 1)))
- return NULL;
-
- strcpy(resource_being_loaded->resource, resource);
-
- if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
- ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
- free(resource_being_loaded);
- return NULL;
- }
-
- /* the dlopen() succeeded, let's find out if the module
- registered itself */
- /* note that this will only work properly as long as
- ast_module_register() (which is called by the module's
- constructor) places the new module at the tail of the
- module_list
- */
- if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
- ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
- /* no, it did not, so close it and return */
- while (!dlclose(lib));
- /* note that the module's destructor will call ast_module_unregister(),
- which will free the structure we allocated in resource_being_loaded */
- return NULL;
- }
-
- wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
-
- /* if we are being asked only to load modules that provide global symbols,
- and this one does not, then close it and return */
- if (global_symbols_only && !wants_global) {
- while (!dlclose(lib));
- return NULL;
- }
-
- /* if the system supports RTLD_NOLOAD, we can just 'promote' the flags
- on the already-opened library to what we want... if not, we have to
- close it and start over
- */
-#if defined(HAVE_RTLD_NOLOAD) && !defined(__Darwin__)
- if (!dlopen(fn, RTLD_NOLOAD | (wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
- ast_log(LOG_WARNING, "Unable to promote flags on module '%s': %s\n", resource_in, dlerror());
- while (!dlclose(lib));
- free(resource_being_loaded);
- return NULL;
- }
-#else
- while (!dlclose(lib));
- resource_being_loaded = NULL;
-
- /* start the load process again */
-
- if (!(resource_being_loaded = ast_calloc(1, sizeof(*resource_being_loaded) + strlen(resource) + 1)))
- return NULL;
-
- strcpy(resource_being_loaded->resource, resource);
-
- if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
- ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
- free(resource_being_loaded);
- return NULL;
- }
-
- /* since the module was successfully opened, and it registered itself
- the previous time we did that, we're going to assume it worked this
- time too :) */
-#endif
-
- AST_LIST_LAST(&module_list)->lib = lib;
- resource_being_loaded = NULL;
-
- return AST_LIST_LAST(&module_list);
-}
-#endif
-
-void ast_module_shutdown(void)
-{
- struct ast_module *mod;
- AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module);
-
- /* We have to call the unload() callbacks in reverse order that the modules
- * exist in the module list so it is the reverse order of how they were
- * loaded. */
-
- AST_LIST_LOCK(&module_list);
- while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry)))
- AST_LIST_INSERT_HEAD(&local_module_list, mod, entry);
- AST_LIST_UNLOCK(&module_list);
-
- while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) {
- if (mod->info->unload)
- mod->info->unload();
- /* Since this should only be called when shutting down "gracefully",
- * all channels should be down before we get to this point, meaning
- * there will be no module users left. */
- AST_LIST_HEAD_DESTROY(&mod->users);
- free(mod);
- }
-}
-
-int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
-{
- struct ast_module *mod;
- int res = -1;
- int error = 0;
-
- AST_LIST_LOCK(&module_list);
-
- if (!(mod = find_resource(resource_name, 0))) {
- AST_LIST_UNLOCK(&module_list);
- return 0;
- }
-
- if (!(mod->flags.running || mod->flags.declined))
- error = 1;
-
- if (!mod->lib) {
- ast_log(LOG_WARNING, "Unloading embedded modules is not supported.\n");
- error = 1;
- }
-
- if (!error && (mod->usecount > 0)) {
- if (force)
- ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n",
- resource_name, mod->usecount);
- else {
- ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
- mod->usecount);
- error = 1;
- }
- }
-
- if (!error) {
- __ast_module_user_hangup_all(mod);
- res = mod->info->unload();
-
- if (res) {
- ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
- if (force <= AST_FORCE_FIRM)
- error = 1;
- else
- ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
- }
- }
-
- if (!error)
- mod->flags.running = mod->flags.declined = 0;
-
- AST_LIST_UNLOCK(&module_list);
-
-#ifdef LOADABLE_MODULES
- if (!error)
- unload_dynamic_module(mod);
-#endif
-
- if (!error)
- ast_update_use_count();
-
- return res;
-}
-
-char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
-{
- struct ast_module *cur;
- int i, which=0, l = strlen(word);
- char *ret = NULL;
-
- if (pos != rpos)
- return NULL;
-
- AST_LIST_LOCK(&module_list);
- AST_LIST_TRAVERSE(&module_list, cur, entry) {
- if (!strncasecmp(word, cur->resource, l) &&
- (cur->info->reload || !needsreload) &&
- ++which > state) {
- ret = strdup(cur->resource);
- break;
- }
- }
- AST_LIST_UNLOCK(&module_list);
-
- if (!ret) {
- for (i=0; !ret && reload_classes[i].name; i++) {
- if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
- ret = strdup(reload_classes[i].name);
- }
- }
-
- return ret;
-}
-
-int ast_module_reload(const char *name)
-{
- struct ast_module *cur;
- int res = 0; /* return value. 0 = not found, others, see below */
- int i;
-
- if (ast_mutex_trylock(&reloadlock)) {
- ast_verbose("The previous reload command didn't finish yet\n");
- return -1; /* reload already in progress */
- }
- ast_lastreloadtime = time(NULL);
-
- /* Call "predefined" reload here first */
- for (i = 0; reload_classes[i].name; i++) {
- if (!name || !strcasecmp(name, reload_classes[i].name)) {
- reload_classes[i].reload_fn(); /* XXX should check error ? */
- res = 2; /* found and reloaded */
- }
- }
-
- if (name && res) {
- ast_mutex_unlock(&reloadlock);
- return res;
- }
-
- AST_LIST_LOCK(&module_list);
- AST_LIST_TRAVERSE(&module_list, cur, entry) {
- const struct ast_module_info *info = cur->info;
-
- if (name && resource_name_match(name, cur->resource))
- continue;
-
- if (!cur->flags.running || cur->flags.declined) {
- if (!name)
- continue;
- ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. "
- "Before reloading the module, you must run \"module load %s\" "
- "and fix whatever is preventing the module from being initialized.\n",
- name, name);
- res = 2; /* Don't report that the module was not found */
- break;
- }
-
- if (!info->reload) { /* cannot be reloaded */
- if (res < 1) /* store result if possible */
- res = 1; /* 1 = no reload() method */
- continue;
- }
-
- res = 2;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", cur->resource, info->description);
- info->reload();
- }
- AST_LIST_UNLOCK(&module_list);
-
- ast_mutex_unlock(&reloadlock);
-
- return res;
-}
-
-static unsigned int inspect_module(const struct ast_module *mod)
-{
- if (!mod->info->description) {
- ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
- return 1;
- }
-
- if (!mod->info->key) {
- ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
- return 1;
- }
-
- if (verify_key((unsigned char *) mod->info->key)) {
- ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
- return 1;
- }
-
- if (!ast_test_flag(mod->info, AST_MODFLAG_BUILDSUM)) {
- ast_log(LOG_WARNING, "Module '%s' was not compiled against a recent version of Asterisk and may cause instability.\n", mod->resource);
- } else if (!ast_strlen_zero(mod->info->buildopt_sum) &&
- strcmp(buildopt_sum, mod->info->buildopt_sum)) {
- ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
- ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
- return 1;
- }
-
- return 0;
-}
-
-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only)
-{
- struct ast_module *mod;
- enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
- char tmp[256];
-
- if ((mod = find_resource(resource_name, 0))) {
- if (mod->flags.running) {
- ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
- return AST_MODULE_LOAD_DECLINE;
- }
- if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
- return AST_MODULE_LOAD_SKIP;
- } else {
-#ifdef LOADABLE_MODULES
- if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
- /* don't generate a warning message during load_modules() */
- if (!global_symbols_only) {
- ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
- return AST_MODULE_LOAD_DECLINE;
- } else {
- return AST_MODULE_LOAD_SKIP;
- }
- }
-#else
- ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
- return AST_MODULE_LOAD_DECLINE;
-#endif
- }
-
- if (inspect_module(mod)) {
- ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
-#ifdef LOADABLE_MODULES
- unload_dynamic_module(mod);
-#endif
- return AST_MODULE_LOAD_DECLINE;
- }
-
- mod->flags.declined = 0;
-
- if (mod->info->load)
- res = mod->info->load();
-
- switch (res) {
- case AST_MODULE_LOAD_SUCCESS:
- if (!ast_fully_booted) {
- if (option_verbose)
- ast_verbose("%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
- if (ast_opt_console && !option_verbose)
- ast_verbose( ".");
- } else {
- if (option_verbose)
- ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", resource_name, mod->info->description);
- }
-
- mod->flags.running = 1;
-
- ast_update_use_count();
- break;
- case AST_MODULE_LOAD_DECLINE:
- mod->flags.declined = 1;
- break;
- case AST_MODULE_LOAD_FAILURE:
- break;
- case AST_MODULE_LOAD_SKIP:
- /* modules should never return this value */
- break;
- }
-
- return res;
-}
-
-int ast_load_resource(const char *resource_name)
-{
- AST_LIST_LOCK(&module_list);
- load_resource(resource_name, 0);
- AST_LIST_UNLOCK(&module_list);
-
- return 0;
-}
-
-struct load_order_entry {
- char *resource;
- AST_LIST_ENTRY(load_order_entry) entry;
-};
-
-AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
-
-static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order)
-{
- struct load_order_entry *order;
-
- AST_LIST_TRAVERSE(load_order, order, entry) {
- if (!resource_name_match(order->resource, resource))
- return NULL;
- }
-
- if (!(order = ast_calloc(1, sizeof(*order))))
- return NULL;
-
- order->resource = ast_strdup(resource);
- AST_LIST_INSERT_TAIL(load_order, order, entry);
-
- return order;
-}
-
-static int translate_module_name(char *oldname, char *newname)
-{
- if (!strcasecmp(oldname, "app_zapbarge.so"))
- ast_copy_string(newname, "app_dahdibarge.so", 18);
- else if(!strcasecmp(oldname, "app_zapras.so"))
- ast_copy_string(newname, "app_dahdiras.so", 16);
- else if(!strcasecmp(oldname, "app_zapscan.so"))
- ast_copy_string(newname, "app_dahdiscan.so", 17);
- else if(!strcasecmp(oldname, "codec_zap.so"))
- ast_copy_string(newname, "codec_dahdi.so", 16);
- else
- return -1; /* no use for newname, oldname is fine */
-
- return 0;
-}
-
-
-int load_modules(unsigned int preload_only)
-{
- struct ast_config *cfg;
- struct ast_module *mod;
- struct load_order_entry *order;
- struct ast_variable *v;
- unsigned int load_count;
- struct load_order load_order;
- int res = 0;
-
- int translate_status;
- char newname[18]; /* although this would normally be 80, max length in translate_module_name is 18 */
-#ifdef LOADABLE_MODULES
- struct dirent *dirent;
- DIR *dir;
-#endif
-
- /* all embedded modules have registered themselves by now */
- embedding = 0;
-
- if (option_verbose)
- ast_verbose("Asterisk Dynamic Loader Starting:\n");
-
- AST_LIST_HEAD_INIT_NOLOCK(&load_order);
-
- AST_LIST_LOCK(&module_list);
-
- if (!(cfg = ast_config_load(AST_MODULE_CONFIG))) {
- ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
- goto done;
- }
-
- /* first, find all the modules we have been explicitly requested to load */
- for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
- if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
- translate_status = translate_module_name(v->value, newname);
- if (!translate_status)
- ast_log(LOG_WARNING, "Use of old module name %s is deprecated, please use %s instead.\n", v->value, newname);
- add_to_load_order(translate_status ? v->value : newname, &load_order);
- }
- }
-
- /* check if 'autoload' is on */
- if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
- /* if so, first add all the embedded modules that are not already running to the load order */
- AST_LIST_TRAVERSE(&module_list, mod, entry) {
- /* if it's not embedded, skip it */
- if (mod->lib)
- continue;
-
- if (mod->flags.running)
- continue;
-
- order = add_to_load_order(mod->resource, &load_order);
- }
-
-#ifdef LOADABLE_MODULES
- /* if we are allowed to load dynamic modules, scan the directory for
- for all available modules and add them as well */
- if ((dir = opendir(ast_config_AST_MODULE_DIR))) {
- while ((dirent = readdir(dir))) {
- int ld = strlen(dirent->d_name);
-
- /* Must end in .so to load it. */
-
- if (ld < 4)
- continue;
-
- if (strcasecmp(dirent->d_name + ld - 3, ".so"))
- continue;
-
- /* if there is already a module by this name in the module_list,
- skip this file */
- if (find_resource(dirent->d_name, 0))
- continue;
-
- add_to_load_order(dirent->d_name, &load_order);
- }
-
- closedir(dir);
- } else {
- if (!ast_opt_quiet)
- ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
- ast_config_AST_MODULE_DIR);
- }
-#endif
- }
-
- /* now scan the config for any modules we are prohibited from loading and
- remove them from the load order */
- for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
- if (strcasecmp(v->name, "noload"))
- continue;
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
- translate_status = translate_module_name(v->value, newname);
- if (!resource_name_match(order->resource, translate_status ? v->value : newname)) {
- if (!translate_status)
- ast_log(LOG_WARNING, "Use of old module name %s is deprecated, please use %s instead.\n", v->value, newname);
- AST_LIST_REMOVE_CURRENT(&load_order, entry);
- free(order->resource);
- free(order);
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- }
-
- /* we are done with the config now, all the information we need is in the
- load_order list */
- ast_config_destroy(cfg);
-
- load_count = 0;
- AST_LIST_TRAVERSE(&load_order, order, entry)
- load_count++;
-
- if (load_count)
- ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
-
- /* first, load only modules that provide global symbols */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
- switch (load_resource(order->resource, 1)) {
- case AST_MODULE_LOAD_SUCCESS:
- case AST_MODULE_LOAD_DECLINE:
- AST_LIST_REMOVE_CURRENT(&load_order, entry);
- free(order->resource);
- free(order);
- break;
- case AST_MODULE_LOAD_FAILURE:
- res = -1;
- goto done;
- case AST_MODULE_LOAD_SKIP:
- /* try again later */
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- /* now load everything else */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
- switch (load_resource(order->resource, 0)) {
- case AST_MODULE_LOAD_SUCCESS:
- case AST_MODULE_LOAD_DECLINE:
- AST_LIST_REMOVE_CURRENT(&load_order, entry);
- free(order->resource);
- free(order);
- break;
- case AST_MODULE_LOAD_FAILURE:
- res = -1;
- goto done;
- case AST_MODULE_LOAD_SKIP:
- /* should not happen */
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
-done:
- while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
- free(order->resource);
- free(order);
- }
-
- AST_LIST_UNLOCK(&module_list);
-
- return res;
-}
-
-void ast_update_use_count(void)
-{
- /* Notify any module monitors that the use count for a
- resource has changed */
- struct loadupdate *m;
-
- AST_LIST_LOCK(&updaters);
- AST_LIST_TRAVERSE(&updaters, m, entry)
- m->updater();
- AST_LIST_UNLOCK(&updaters);
-}
-
-int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
- const char *like)
-{
- struct ast_module *cur;
- int unlock = -1;
- int total_mod_loaded = 0;
-
- if (AST_LIST_TRYLOCK(&module_list))
- unlock = 0;
-
- AST_LIST_TRAVERSE(&module_list, cur, entry) {
- total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
- }
-
- if (unlock)
- AST_LIST_UNLOCK(&module_list);
-
- return total_mod_loaded;
-}
-
-int ast_loader_register(int (*v)(void))
-{
- struct loadupdate *tmp;
-
- if (!(tmp = ast_malloc(sizeof(*tmp))))
- return -1;
-
- tmp->updater = v;
- AST_LIST_LOCK(&updaters);
- AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
- AST_LIST_UNLOCK(&updaters);
-
- return 0;
-}
-
-int ast_loader_unregister(int (*v)(void))
-{
- struct loadupdate *cur;
-
- AST_LIST_LOCK(&updaters);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
- if (cur->updater == v) {
- AST_LIST_REMOVE_CURRENT(&updaters, entry);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- AST_LIST_UNLOCK(&updaters);
-
- return cur ? 0 : -1;
-}
-
-struct ast_module *ast_module_ref(struct ast_module *mod)
-{
- ast_atomic_fetchadd_int(&mod->usecount, +1);
- ast_update_use_count();
-
- return mod;
-}
-
-void ast_module_unref(struct ast_module *mod)
-{
- ast_atomic_fetchadd_int(&mod->usecount, -1);
- ast_update_use_count();
-}
diff --git a/main/logger.c b/main/logger.c
deleted file mode 100644
index 0d1ef4b71..000000000
--- a/main/logger.c
+++ /dev/null
@@ -1,939 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Asterisk Logger
- *
- * Logging routines
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/stat.h>
-#if ((defined(AST_DEVMODE)) && (defined(linux)))
-#include <execinfo.h>
-#define MAX_BACKTRACE_FRAMES 20
-#endif
-
-#define SYSLOG_NAMES /* so we can map syslog facilities names to their numeric values,
- from <syslog.h> which is included by logger.h */
-#include <syslog.h>
-
-static int syslog_level_map[] = {
- LOG_DEBUG,
- LOG_INFO, /* arbitrary equivalent of LOG_EVENT */
- LOG_NOTICE,
- LOG_WARNING,
- LOG_ERR,
- LOG_DEBUG,
- LOG_DEBUG
-};
-
-#define SYSLOG_NLEVELS sizeof(syslog_level_map) / sizeof(int)
-
-#include "asterisk/logger.h"
-#include "asterisk/lock.h"
-#include "asterisk/options.h"
-#include "asterisk/channel.h"
-#include "asterisk/config.h"
-#include "asterisk/term.h"
-#include "asterisk/cli.h"
-#include "asterisk/utils.h"
-#include "asterisk/manager.h"
-#include "asterisk/threadstorage.h"
-
-#if defined(__linux__) && !defined(__NR_gettid)
-#include <asm/unistd.h>
-#endif
-
-#if defined(__linux__) && defined(__NR_gettid)
-#define GETTID() syscall(__NR_gettid)
-#else
-#define GETTID() getpid()
-#endif
-
-
-static char dateformat[256] = "%b %e %T"; /* Original Asterisk Format */
-
-static int filesize_reload_needed;
-static int global_logmask = -1;
-
-static struct {
- unsigned int queue_log:1;
- unsigned int event_log:1;
-} logfiles = { 1, 1 };
-
-static char hostname[MAXHOSTNAMELEN];
-
-enum logtypes {
- LOGTYPE_SYSLOG,
- LOGTYPE_FILE,
- LOGTYPE_CONSOLE,
-};
-
-struct logchannel {
- int logmask; /* What to log to this channel */
- int disabled; /* If this channel is disabled or not */
- int facility; /* syslog facility */
- enum logtypes type; /* Type of log channel */
- FILE *fileptr; /* logfile logging file pointer */
- char filename[256]; /* Filename */
- AST_LIST_ENTRY(logchannel) list;
-};
-
-static AST_LIST_HEAD_STATIC(logchannels, logchannel);
-
-static FILE *eventlog;
-static FILE *qlog;
-
-static char *levels[] = {
- "DEBUG",
- "EVENT",
- "NOTICE",
- "WARNING",
- "ERROR",
- "VERBOSE",
- "DTMF"
-};
-
-static int colors[] = {
- COLOR_BRGREEN,
- COLOR_BRBLUE,
- COLOR_YELLOW,
- COLOR_BRRED,
- COLOR_RED,
- COLOR_GREEN,
- COLOR_BRGREEN
-};
-
-AST_THREADSTORAGE(verbose_buf, verbose_buf_init);
-#define VERBOSE_BUF_INIT_SIZE 128
-
-AST_THREADSTORAGE(log_buf, log_buf_init);
-#define LOG_BUF_INIT_SIZE 128
-
-static int make_components(char *s, int lineno)
-{
- char *w;
- int res = 0;
- char *stringp = s;
-
- while ((w = strsep(&stringp, ","))) {
- w = ast_skip_blanks(w);
- if (!strcasecmp(w, "error"))
- res |= (1 << __LOG_ERROR);
- else if (!strcasecmp(w, "warning"))
- res |= (1 << __LOG_WARNING);
- else if (!strcasecmp(w, "notice"))
- res |= (1 << __LOG_NOTICE);
- else if (!strcasecmp(w, "event"))
- res |= (1 << __LOG_EVENT);
- else if (!strcasecmp(w, "debug"))
- res |= (1 << __LOG_DEBUG);
- else if (!strcasecmp(w, "verbose"))
- res |= (1 << __LOG_VERBOSE);
- else if (!strcasecmp(w, "dtmf"))
- res |= (1 << __LOG_DTMF);
- else {
- fprintf(stderr, "Logfile Warning: Unknown keyword '%s' at line %d of logger.conf\n", w, lineno);
- }
- }
-
- return res;
-}
-
-static struct logchannel *make_logchannel(char *channel, char *components, int lineno)
-{
- struct logchannel *chan;
- char *facility;
-#ifndef SOLARIS
- CODE *cptr;
-#endif
-
- if (ast_strlen_zero(channel) || !(chan = ast_calloc(1, sizeof(*chan))))
- return NULL;
-
- if (!strcasecmp(channel, "console")) {
- chan->type = LOGTYPE_CONSOLE;
- } else if (!strncasecmp(channel, "syslog", 6)) {
- /*
- * syntax is:
- * syslog.facility => level,level,level
- */
- facility = strchr(channel, '.');
- if(!facility++ || !facility) {
- facility = "local0";
- }
-
-#ifndef SOLARIS
- /*
- * Walk through the list of facilitynames (defined in sys/syslog.h)
- * to see if we can find the one we have been given
- */
- chan->facility = -1;
- cptr = facilitynames;
- while (cptr->c_name) {
- if (!strcasecmp(facility, cptr->c_name)) {
- chan->facility = cptr->c_val;
- break;
- }
- cptr++;
- }
-#else
- chan->facility = -1;
- if (!strcasecmp(facility, "kern"))
- chan->facility = LOG_KERN;
- else if (!strcasecmp(facility, "USER"))
- chan->facility = LOG_USER;
- else if (!strcasecmp(facility, "MAIL"))
- chan->facility = LOG_MAIL;
- else if (!strcasecmp(facility, "DAEMON"))
- chan->facility = LOG_DAEMON;
- else if (!strcasecmp(facility, "AUTH"))
- chan->facility = LOG_AUTH;
- else if (!strcasecmp(facility, "SYSLOG"))
- chan->facility = LOG_SYSLOG;
- else if (!strcasecmp(facility, "LPR"))
- chan->facility = LOG_LPR;
- else if (!strcasecmp(facility, "NEWS"))
- chan->facility = LOG_NEWS;
- else if (!strcasecmp(facility, "UUCP"))
- chan->facility = LOG_UUCP;
- else if (!strcasecmp(facility, "CRON"))
- chan->facility = LOG_CRON;
- else if (!strcasecmp(facility, "LOCAL0"))
- chan->facility = LOG_LOCAL0;
- else if (!strcasecmp(facility, "LOCAL1"))
- chan->facility = LOG_LOCAL1;
- else if (!strcasecmp(facility, "LOCAL2"))
- chan->facility = LOG_LOCAL2;
- else if (!strcasecmp(facility, "LOCAL3"))
- chan->facility = LOG_LOCAL3;
- else if (!strcasecmp(facility, "LOCAL4"))
- chan->facility = LOG_LOCAL4;
- else if (!strcasecmp(facility, "LOCAL5"))
- chan->facility = LOG_LOCAL5;
- else if (!strcasecmp(facility, "LOCAL6"))
- chan->facility = LOG_LOCAL6;
- else if (!strcasecmp(facility, "LOCAL7"))
- chan->facility = LOG_LOCAL7;
-#endif /* Solaris */
-
- if (0 > chan->facility) {
- fprintf(stderr, "Logger Warning: bad syslog facility in logger.conf\n");
- free(chan);
- return NULL;
- }
-
- chan->type = LOGTYPE_SYSLOG;
- snprintf(chan->filename, sizeof(chan->filename), "%s", channel);
- openlog("asterisk", LOG_PID, chan->facility);
- } else {
- if (channel[0] == '/') {
- if(!ast_strlen_zero(hostname)) {
- snprintf(chan->filename, sizeof(chan->filename) - 1,"%s.%s", channel, hostname);
- } else {
- ast_copy_string(chan->filename, channel, sizeof(chan->filename));
- }
- }
-
- if(!ast_strlen_zero(hostname)) {
- snprintf(chan->filename, sizeof(chan->filename), "%s/%s.%s",(char *)ast_config_AST_LOG_DIR, channel, hostname);
- } else {
- snprintf(chan->filename, sizeof(chan->filename), "%s/%s", (char *)ast_config_AST_LOG_DIR, channel);
- }
- chan->fileptr = fopen(chan->filename, "a");
- if (!chan->fileptr) {
- /* Can't log here, since we're called with a lock */
- fprintf(stderr, "Logger Warning: Unable to open log file '%s': %s\n", chan->filename, strerror(errno));
- }
- chan->type = LOGTYPE_FILE;
- }
- chan->logmask = make_components(components, lineno);
- return chan;
-}
-
-static void init_logger_chain(void)
-{
- struct logchannel *chan;
- struct ast_config *cfg;
- struct ast_variable *var;
- const char *s;
-
- /* delete our list of log channels */
- AST_LIST_LOCK(&logchannels);
- while ((chan = AST_LIST_REMOVE_HEAD(&logchannels, list)))
- free(chan);
- AST_LIST_UNLOCK(&logchannels);
-
- global_logmask = 0;
- errno = 0;
- /* close syslog */
- closelog();
-
- cfg = ast_config_load("logger.conf");
-
- /* If no config file, we're fine, set default options. */
- if (!cfg) {
- if (errno)
- fprintf(stderr, "Unable to open logger.conf: %s; default settings will be used.\n", strerror(errno));
- else
- fprintf(stderr, "Errors detected in logger.conf: see above; default settings will be used.\n");
- if (!(chan = ast_calloc(1, sizeof(*chan))))
- return;
- chan->type = LOGTYPE_CONSOLE;
- chan->logmask = 28; /*warning,notice,error */
- AST_LIST_LOCK(&logchannels);
- AST_LIST_INSERT_HEAD(&logchannels, chan, list);
- AST_LIST_UNLOCK(&logchannels);
- global_logmask |= chan->logmask;
- return;
- }
-
- if ((s = ast_variable_retrieve(cfg, "general", "appendhostname"))) {
- if (ast_true(s)) {
- if (gethostname(hostname, sizeof(hostname) - 1)) {
- ast_copy_string(hostname, "unknown", sizeof(hostname));
- ast_log(LOG_WARNING, "What box has no hostname???\n");
- }
- } else
- hostname[0] = '\0';
- } else
- hostname[0] = '\0';
- if ((s = ast_variable_retrieve(cfg, "general", "dateformat")))
- ast_copy_string(dateformat, s, sizeof(dateformat));
- else
- ast_copy_string(dateformat, "%b %e %T", sizeof(dateformat));
- if ((s = ast_variable_retrieve(cfg, "general", "queue_log")))
- logfiles.queue_log = ast_true(s);
- if ((s = ast_variable_retrieve(cfg, "general", "event_log")))
- logfiles.event_log = ast_true(s);
-
- AST_LIST_LOCK(&logchannels);
- var = ast_variable_browse(cfg, "logfiles");
- for (; var; var = var->next) {
- if (!(chan = make_logchannel(var->name, var->value, var->lineno)))
- continue;
- AST_LIST_INSERT_HEAD(&logchannels, chan, list);
- global_logmask |= chan->logmask;
- }
- AST_LIST_UNLOCK(&logchannels);
-
- ast_config_destroy(cfg);
-}
-
-void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt, ...)
-{
- va_list ap;
- AST_LIST_LOCK(&logchannels);
- if (qlog) {
- va_start(ap, fmt);
- fprintf(qlog, "%ld|%s|%s|%s|%s|", (long)time(NULL), callid, queuename, agent, event);
- vfprintf(qlog, fmt, ap);
- fprintf(qlog, "\n");
- va_end(ap);
- fflush(qlog);
- }
- AST_LIST_UNLOCK(&logchannels);
-}
-
-int reload_logger(int rotate)
-{
- char old[PATH_MAX] = "";
- char new[PATH_MAX];
- int event_rotate = rotate, queue_rotate = rotate;
- struct logchannel *f;
- FILE *myf;
- int x, res = 0;
-
- AST_LIST_LOCK(&logchannels);
-
- if (eventlog)
- fclose(eventlog);
- else
- event_rotate = 0;
- eventlog = NULL;
-
- if (qlog)
- fclose(qlog);
- else
- queue_rotate = 0;
- qlog = NULL;
-
- mkdir((char *)ast_config_AST_LOG_DIR, 0755);
-
- AST_LIST_TRAVERSE(&logchannels, f, list) {
- if (f->disabled) {
- f->disabled = 0; /* Re-enable logging at reload */
- manager_event(EVENT_FLAG_SYSTEM, "LogChannel", "Channel: %s\r\nEnabled: Yes\r\n", f->filename);
- }
- if (f->fileptr && (f->fileptr != stdout) && (f->fileptr != stderr)) {
- fclose(f->fileptr); /* Close file */
- f->fileptr = NULL;
- if (rotate) {
- ast_copy_string(old, f->filename, sizeof(old));
-
- for (x = 0; ; x++) {
- snprintf(new, sizeof(new), "%s.%d", f->filename, x);
- myf = fopen((char *)new, "r");
- if (myf)
- fclose(myf);
- else
- break;
- }
-
- /* do it */
- if (rename(old,new))
- fprintf(stderr, "Unable to rename file '%s' to '%s'\n", old, new);
- }
- }
- }
-
- filesize_reload_needed = 0;
-
- init_logger_chain();
-
- if (logfiles.event_log) {
- snprintf(old, sizeof(old), "%s/%s", (char *)ast_config_AST_LOG_DIR, EVENTLOG);
- if (event_rotate) {
- for (x=0;;x++) {
- snprintf(new, sizeof(new), "%s/%s.%d", (char *)ast_config_AST_LOG_DIR, EVENTLOG,x);
- myf = fopen((char *)new, "r");
- if (myf) /* File exists */
- fclose(myf);
- else
- break;
- }
-
- /* do it */
- if (rename(old,new))
- ast_log(LOG_ERROR, "Unable to rename file '%s' to '%s'\n", old, new);
- }
-
- eventlog = fopen(old, "a");
- if (eventlog) {
- ast_log(LOG_EVENT, "Restarted Asterisk Event Logger\n");
- if (option_verbose)
- ast_verbose("Asterisk Event Logger restarted\n");
- } else {
- ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno));
- res = -1;
- }
- }
-
- if (logfiles.queue_log) {
- snprintf(old, sizeof(old), "%s/%s", (char *)ast_config_AST_LOG_DIR, QUEUELOG);
- if (queue_rotate) {
- for (x = 0; ; x++) {
- snprintf(new, sizeof(new), "%s/%s.%d", (char *)ast_config_AST_LOG_DIR, QUEUELOG, x);
- myf = fopen((char *)new, "r");
- if (myf) /* File exists */
- fclose(myf);
- else
- break;
- }
-
- /* do it */
- if (rename(old, new))
- ast_log(LOG_ERROR, "Unable to rename file '%s' to '%s'\n", old, new);
- }
-
- qlog = fopen(old, "a");
- if (qlog) {
- ast_queue_log("NONE", "NONE", "NONE", "CONFIGRELOAD", "%s", "");
- ast_log(LOG_EVENT, "Restarted Asterisk Queue Logger\n");
- if (option_verbose)
- ast_verbose("Asterisk Queue Logger restarted\n");
- } else {
- ast_log(LOG_ERROR, "Unable to create queue log: %s\n", strerror(errno));
- res = -1;
- }
- }
-
- AST_LIST_UNLOCK(&logchannels);
-
- return res;
-}
-
-/*! \brief Reload the logger module without rotating log files (also used from loader.c during
- a full Asterisk reload) */
-int logger_reload(void)
-{
- if(reload_logger(0))
- return RESULT_FAILURE;
- return RESULT_SUCCESS;
-}
-
-static int handle_logger_reload(int fd, int argc, char *argv[])
-{
- int result = logger_reload();
- if (result == RESULT_FAILURE)
- ast_cli(fd, "Failed to reload the logger\n");
- return result;
-}
-
-static int handle_logger_rotate(int fd, int argc, char *argv[])
-{
- if(reload_logger(1)) {
- ast_cli(fd, "Failed to reload the logger and rotate log files\n");
- return RESULT_FAILURE;
- }
- return RESULT_SUCCESS;
-}
-
-/*! \brief CLI command to show logging system configuration */
-static int handle_logger_show_channels(int fd, int argc, char *argv[])
-{
-#define FORMATL "%-35.35s %-8.8s %-9.9s "
- struct logchannel *chan;
-
- ast_cli(fd,FORMATL, "Channel", "Type", "Status");
- ast_cli(fd, "Configuration\n");
- ast_cli(fd,FORMATL, "-------", "----", "------");
- ast_cli(fd, "-------------\n");
- AST_LIST_LOCK(&logchannels);
- AST_LIST_TRAVERSE(&logchannels, chan, list) {
- ast_cli(fd, FORMATL, chan->filename, chan->type==LOGTYPE_CONSOLE ? "Console" : (chan->type==LOGTYPE_SYSLOG ? "Syslog" : "File"),
- chan->disabled ? "Disabled" : "Enabled");
- ast_cli(fd, " - ");
- if (chan->logmask & (1 << __LOG_DEBUG))
- ast_cli(fd, "Debug ");
- if (chan->logmask & (1 << __LOG_DTMF))
- ast_cli(fd, "DTMF ");
- if (chan->logmask & (1 << __LOG_VERBOSE))
- ast_cli(fd, "Verbose ");
- if (chan->logmask & (1 << __LOG_WARNING))
- ast_cli(fd, "Warning ");
- if (chan->logmask & (1 << __LOG_NOTICE))
- ast_cli(fd, "Notice ");
- if (chan->logmask & (1 << __LOG_ERROR))
- ast_cli(fd, "Error ");
- if (chan->logmask & (1 << __LOG_EVENT))
- ast_cli(fd, "Event ");
- ast_cli(fd, "\n");
- }
- AST_LIST_UNLOCK(&logchannels);
- ast_cli(fd, "\n");
-
- return RESULT_SUCCESS;
-}
-
-struct verb {
- void (*verboser)(const char *string);
- AST_LIST_ENTRY(verb) list;
-};
-
-static AST_LIST_HEAD_STATIC(verbosers, verb);
-
-static char logger_reload_help[] =
-"Usage: logger reload\n"
-" Reloads the logger subsystem state. Use after restarting syslogd(8) if you are using syslog logging.\n";
-
-static char logger_rotate_help[] =
-"Usage: logger rotate\n"
-" Rotates and Reopens the log files.\n";
-
-static char logger_show_channels_help[] =
-"Usage: logger show channels\n"
-" List configured logger channels.\n";
-
-static struct ast_cli_entry cli_logger[] = {
- { { "logger", "show", "channels", NULL },
- handle_logger_show_channels, "List configured log channels",
- logger_show_channels_help },
-
- { { "logger", "reload", NULL },
- handle_logger_reload, "Reopens the log files",
- logger_reload_help },
-
- { { "logger", "rotate", NULL },
- handle_logger_rotate, "Rotates and reopens the log files",
- logger_rotate_help },
-};
-
-static int handle_SIGXFSZ(int sig)
-{
- /* Indicate need to reload */
- filesize_reload_needed = 1;
- return 0;
-}
-
-int init_logger(void)
-{
- char tmp[256];
- int res = 0;
-
- /* auto rotate if sig SIGXFSZ comes a-knockin */
- (void) signal(SIGXFSZ,(void *) handle_SIGXFSZ);
-
- /* register the logger cli commands */
- ast_cli_register_multiple(cli_logger, sizeof(cli_logger) / sizeof(struct ast_cli_entry));
-
- mkdir((char *)ast_config_AST_LOG_DIR, 0755);
-
- /* create log channels */
- init_logger_chain();
-
- /* create the eventlog */
- if (logfiles.event_log) {
- mkdir((char *)ast_config_AST_LOG_DIR, 0755);
- snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_LOG_DIR, EVENTLOG);
- eventlog = fopen((char *)tmp, "a");
- if (eventlog) {
- ast_log(LOG_EVENT, "Started Asterisk Event Logger\n");
- if (option_verbose)
- ast_verbose("Asterisk Event Logger Started %s\n",(char *)tmp);
- } else {
- ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno));
- res = -1;
- }
- }
-
- if (logfiles.queue_log) {
- snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_LOG_DIR, QUEUELOG);
- qlog = fopen(tmp, "a");
- ast_queue_log("NONE", "NONE", "NONE", "QUEUESTART", "%s", "");
- }
- return res;
-}
-
-void close_logger(void)
-{
- struct logchannel *f;
-
- AST_LIST_LOCK(&logchannels);
-
- if (eventlog) {
- fclose(eventlog);
- eventlog = NULL;
- }
-
- if (qlog) {
- fclose(qlog);
- qlog = NULL;
- }
-
- AST_LIST_TRAVERSE(&logchannels, f, list) {
- if (f->fileptr && (f->fileptr != stdout) && (f->fileptr != stderr)) {
- fclose(f->fileptr);
- f->fileptr = NULL;
- }
- }
-
- closelog(); /* syslog */
-
- AST_LIST_UNLOCK(&logchannels);
-
- return;
-}
-
-static void __attribute__((format(printf, 5, 0))) ast_log_vsyslog(int level, const char *file, int line, const char *function, const char *fmt, va_list args)
-{
- char buf[BUFSIZ];
- char *s;
-
- if (level >= SYSLOG_NLEVELS) {
- /* we are locked here, so cannot ast_log() */
- fprintf(stderr, "ast_log_vsyslog called with bogus level: %d\n", level);
- return;
- }
- if (level == __LOG_VERBOSE) {
- snprintf(buf, sizeof(buf), "VERBOSE[%ld]: ", (long)GETTID());
- level = __LOG_DEBUG;
- } else if (level == __LOG_DTMF) {
- snprintf(buf, sizeof(buf), "DTMF[%ld]: ", (long)GETTID());
- level = __LOG_DEBUG;
- } else {
- snprintf(buf, sizeof(buf), "%s[%ld]: %s:%d in %s: ",
- levels[level], (long)GETTID(), file, line, function);
- }
- s = buf + strlen(buf);
- vsnprintf(s, sizeof(buf) - strlen(buf), fmt, args);
- term_strip(s, s, strlen(s) + 1);
- syslog(syslog_level_map[level], "%s", buf);
-}
-
-/*!
- * \brief send log messages to syslog and/or the console
- */
-void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
-{
- struct logchannel *chan;
- struct ast_dynamic_str *buf;
- time_t t;
- struct tm tm;
- char date[256];
-
- va_list ap;
-
- if (!(buf = ast_dynamic_str_thread_get(&log_buf, LOG_BUF_INIT_SIZE)))
- return;
-
- if (AST_LIST_EMPTY(&logchannels))
- {
- /*
- * we don't have the logger chain configured yet,
- * so just log to stdout
- */
- if (level != __LOG_VERBOSE) {
- int res;
- va_start(ap, fmt);
- res = ast_dynamic_str_thread_set_va(&buf, BUFSIZ, &log_buf, fmt, ap);
- va_end(ap);
- if (res != AST_DYNSTR_BUILD_FAILED) {
- term_filter_escapes(buf->str);
- fputs(buf->str, stdout);
- }
- }
- return;
- }
-
- /* don't display LOG_DEBUG messages unless option_verbose _or_ option_debug
- are non-zero; LOG_DEBUG messages can still be displayed if option_debug
- is zero, if option_verbose is non-zero (this allows for 'level zero'
- LOG_DEBUG messages to be displayed, if the logmask on any channel
- allows it)
- */
- if (!option_verbose && !option_debug && (level == __LOG_DEBUG))
- return;
-
- /* Ignore anything that never gets logged anywhere */
- if (!(global_logmask & (1 << level)))
- return;
-
- /* Ignore anything other than the currently debugged file if there is one */
- if ((level == __LOG_DEBUG) && !ast_strlen_zero(debug_filename) && strcasecmp(debug_filename, file))
- return;
-
- time(&t);
- ast_localtime(&t, &tm, NULL);
- strftime(date, sizeof(date), dateformat, &tm);
-
- AST_LIST_LOCK(&logchannels);
-
- if (logfiles.event_log && level == __LOG_EVENT) {
- va_start(ap, fmt);
-
- fprintf(eventlog, "%s asterisk[%ld]: ", date, (long)getpid());
- vfprintf(eventlog, fmt, ap);
- fflush(eventlog);
-
- va_end(ap);
- AST_LIST_UNLOCK(&logchannels);
- return;
- }
-
- AST_LIST_TRAVERSE(&logchannels, chan, list) {
- if (chan->disabled)
- break;
- /* Check syslog channels */
- if (chan->type == LOGTYPE_SYSLOG && (chan->logmask & (1 << level))) {
- va_start(ap, fmt);
- ast_log_vsyslog(level, file, line, function, fmt, ap);
- va_end(ap);
- /* Console channels */
- } else if ((chan->logmask & (1 << level)) && (chan->type == LOGTYPE_CONSOLE)) {
- char linestr[128];
- char tmp1[80], tmp2[80], tmp3[80], tmp4[80];
-
- if (level != __LOG_VERBOSE) {
- int res;
- sprintf(linestr, "%d", line);
- ast_dynamic_str_thread_set(&buf, BUFSIZ, &log_buf,
- "[%s] %s[%ld]: %s:%s %s: ",
- date,
- term_color(tmp1, levels[level], colors[level], 0, sizeof(tmp1)),
- (long)GETTID(),
- term_color(tmp2, file, COLOR_BRWHITE, 0, sizeof(tmp2)),
- term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
- term_color(tmp4, function, COLOR_BRWHITE, 0, sizeof(tmp4)));
- /*filter to the console!*/
- term_filter_escapes(buf->str);
- ast_console_puts_mutable(buf->str);
-
- va_start(ap, fmt);
- res = ast_dynamic_str_thread_set_va(&buf, BUFSIZ, &log_buf, fmt, ap);
- va_end(ap);
- if (res != AST_DYNSTR_BUILD_FAILED)
- ast_console_puts_mutable(buf->str);
- }
- /* File channels */
- } else if ((chan->logmask & (1 << level)) && (chan->fileptr)) {
- int res;
- ast_dynamic_str_thread_set(&buf, BUFSIZ, &log_buf,
- "[%s] %s[%ld] %s: ",
- date, levels[level], (long)GETTID(), file);
- res = fprintf(chan->fileptr, "%s", buf->str);
- if (res <= 0 && !ast_strlen_zero(buf->str)) { /* Error, no characters printed */
- fprintf(stderr,"**** Asterisk Logging Error: ***********\n");
- if (errno == ENOMEM || errno == ENOSPC) {
- fprintf(stderr, "Asterisk logging error: Out of disk space, can't log to log file %s\n", chan->filename);
- } else
- fprintf(stderr, "Logger Warning: Unable to write to log file '%s': %s (disabled)\n", chan->filename, strerror(errno));
- manager_event(EVENT_FLAG_SYSTEM, "LogChannel", "Channel: %s\r\nEnabled: No\r\nReason: %d - %s\r\n", chan->filename, errno, strerror(errno));
- chan->disabled = 1;
- } else {
- int res;
- /* No error message, continue printing */
- va_start(ap, fmt);
- res = ast_dynamic_str_thread_set_va(&buf, BUFSIZ, &log_buf, fmt, ap);
- va_end(ap);
- if (res != AST_DYNSTR_BUILD_FAILED) {
- term_strip(buf->str, buf->str, buf->len);
- fputs(buf->str, chan->fileptr);
- fflush(chan->fileptr);
- }
- }
- }
- }
-
- AST_LIST_UNLOCK(&logchannels);
-
- if (filesize_reload_needed) {
- reload_logger(1);
- ast_log(LOG_EVENT,"Rotated Logs Per SIGXFSZ (Exceeded file size limit)\n");
- if (option_verbose)
- ast_verbose("Rotated Logs Per SIGXFSZ (Exceeded file size limit)\n");
- }
-}
-
-void ast_backtrace(void)
-{
-#ifdef linux
-#ifdef AST_DEVMODE
- int count=0, i=0;
- void **addresses;
- char **strings;
-
- if ((addresses = ast_calloc(MAX_BACKTRACE_FRAMES, sizeof(*addresses)))) {
- count = backtrace(addresses, MAX_BACKTRACE_FRAMES);
- if ((strings = backtrace_symbols(addresses, count))) {
- ast_log(LOG_DEBUG, "Got %d backtrace record%c\n", count, count != 1 ? 's' : ' ');
- for (i=0; i < count ; i++) {
-#if __WORDSIZE == 32
- ast_log(LOG_DEBUG, "#%d: [%08X] %s\n", i, (unsigned int)addresses[i], strings[i]);
-#elif __WORDSIZE == 64
- ast_log(LOG_DEBUG, "#%d: [%016lX] %s\n", i, (unsigned long)addresses[i], strings[i]);
-#endif
- }
- free(strings);
- } else {
- ast_log(LOG_DEBUG, "Could not allocate memory for backtrace\n");
- }
- free(addresses);
- }
-#else
- ast_log(LOG_WARNING, "Must run configure with '--enable-dev-mode' for stack backtraces.\n");
-#endif
-#else /* ndef linux */
- ast_log(LOG_WARNING, "Inline stack backtraces are only available on the Linux platform.\n");
-#endif
-}
-
-void ast_verbose(const char *fmt, ...)
-{
- struct verb *v;
- struct ast_dynamic_str *buf;
- int res;
- va_list ap;
-
- if (ast_opt_timestamp) {
- time_t t;
- struct tm tm;
- char date[40];
- char *datefmt;
-
- time(&t);
- ast_localtime(&t, &tm, NULL);
- strftime(date, sizeof(date), dateformat, &tm);
- datefmt = alloca(strlen(date) + 3 + strlen(fmt) + 1);
- sprintf(datefmt, "%c[%s] %s", 127, date, fmt);
- fmt = datefmt;
- } else {
- char *tmp = alloca(strlen(fmt) + 2);
- sprintf(tmp, "%c%s", 127, fmt);
- fmt = tmp;
- }
-
- if (!(buf = ast_dynamic_str_thread_get(&verbose_buf, VERBOSE_BUF_INIT_SIZE)))
- return;
-
- va_start(ap, fmt);
- res = ast_dynamic_str_thread_set_va(&buf, 0, &verbose_buf, fmt, ap);
- va_end(ap);
-
- if (res == AST_DYNSTR_BUILD_FAILED)
- return;
-
- /* filter out possibly hazardous escape sequences */
- term_filter_escapes(buf->str);
-
- AST_LIST_LOCK(&verbosers);
- AST_LIST_TRAVERSE(&verbosers, v, list)
- v->verboser(buf->str);
- AST_LIST_UNLOCK(&verbosers);
-
- ast_log(LOG_VERBOSE, "%s", buf->str + 1);
-}
-
-int ast_register_verbose(void (*v)(const char *string))
-{
- struct verb *verb;
-
- if (!(verb = ast_malloc(sizeof(*verb))))
- return -1;
-
- verb->verboser = v;
-
- AST_LIST_LOCK(&verbosers);
- AST_LIST_INSERT_HEAD(&verbosers, verb, list);
- AST_LIST_UNLOCK(&verbosers);
-
- return 0;
-}
-
-int ast_unregister_verbose(void (*v)(const char *string))
-{
- struct verb *cur;
-
- AST_LIST_LOCK(&verbosers);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&verbosers, cur, list) {
- if (cur->verboser == v) {
- AST_LIST_REMOVE_CURRENT(&verbosers, list);
- free(cur);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&verbosers);
-
- return cur ? 0 : -1;
-}
diff --git a/main/manager.c b/main/manager.c
deleted file mode 100644
index 7f436ad94..000000000
--- a/main/manager.c
+++ /dev/null
@@ -1,3198 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief The Asterisk Management Interface - AMI
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * Channel Management and more
- *
- * \ref amiconf
- */
-
-/*! \addtogroup Group_AMI AMI functions
-*/
-/*! @{
- Doxygen group */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "asterisk/channel.h"
-#include "asterisk/file.h"
-#include "asterisk/manager.h"
-#include "asterisk/config.h"
-#include "asterisk/callerid.h"
-#include "asterisk/lock.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/cli.h"
-#include "asterisk/app.h"
-#include "asterisk/pbx.h"
-#include "asterisk/md5.h"
-#include "asterisk/acl.h"
-#include "asterisk/utils.h"
-#include "asterisk/http.h"
-#include "asterisk/threadstorage.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/term.h"
-#include "asterisk/astobj2.h"
-
-struct fast_originate_helper {
- char tech[AST_MAX_EXTENSION];
- /*! data can contain a channel name, extension number, username, password, etc. */
- char data[512];
- int timeout;
- int format;
- char app[AST_MAX_APP];
- char appdata[AST_MAX_EXTENSION];
- char cid_name[AST_MAX_EXTENSION];
- char cid_num[AST_MAX_EXTENSION];
- char context[AST_MAX_CONTEXT];
- char exten[AST_MAX_EXTENSION];
- char idtext[AST_MAX_EXTENSION];
- char account[AST_MAX_ACCOUNT_CODE];
- int priority;
- struct ast_variable *vars;
-};
-
-struct eventqent {
- int usecount;
- int category;
- struct eventqent *next;
- char eventdata[1];
-};
-
-static int enabled;
-static int portno = DEFAULT_MANAGER_PORT;
-static int asock = -1;
-static int displayconnects = 1;
-static int timestampevents;
-static int httptimeout = 60;
-
-static pthread_t t;
-static int block_sockets;
-static int num_sessions;
-
-/* Protected by the sessions list lock */
-struct eventqent *master_eventq = NULL;
-
-AST_THREADSTORAGE(manager_event_buf, manager_event_buf_init);
-#define MANAGER_EVENT_BUF_INITSIZE 256
-
-AST_THREADSTORAGE(astman_append_buf, astman_append_buf_init);
-#define ASTMAN_APPEND_BUF_INITSIZE 256
-
-static struct permalias {
- int num;
- char *label;
-} perms[] = {
- { EVENT_FLAG_SYSTEM, "system" },
- { EVENT_FLAG_CALL, "call" },
- { EVENT_FLAG_LOG, "log" },
- { EVENT_FLAG_VERBOSE, "verbose" },
- { EVENT_FLAG_COMMAND, "command" },
- { EVENT_FLAG_AGENT, "agent" },
- { EVENT_FLAG_USER, "user" },
- { EVENT_FLAG_CONFIG, "config" },
- { -1, "all" },
- { 0, "none" },
-};
-
-#define MAX_BLACKLIST_CMD_LEN 2
-static struct {
- char *words[AST_MAX_CMD_LEN];
-} command_blacklist[] = {
- {{ "module", "load", NULL }},
- {{ "module", "unload", NULL }},
- {{ "restart", "gracefully", NULL }},
-};
-
-struct mansession {
- /*! Execution thread */
- pthread_t t;
- /*! Thread lock -- don't use in action callbacks, it's already taken care of */
- ast_mutex_t __lock;
- /*! socket address */
- struct sockaddr_in sin;
- /*! TCP socket */
- int fd;
- /*! Whether an HTTP manager is in use */
- int inuse;
- /*! Whether an HTTP session should be destroyed */
- int needdestroy;
- /*! Whether an HTTP session has someone waiting on events */
- pthread_t waiting_thread;
- /*! Unique manager identifer */
- uint32_t managerid;
- /*! Session timeout if HTTP */
- time_t sessiontimeout;
- /*! Output from manager interface */
- struct ast_dynamic_str *outputstr;
- /*! Logged in username */
- char username[80];
- /*! Authentication challenge */
- char challenge[10];
- /*! Authentication status */
- int authenticated;
- /*! Authorization for reading */
- int readperm;
- /*! Authorization for writing */
- int writeperm;
- /*! Buffer */
- char inbuf[1024];
- int inlen;
- int send_events;
- int displaysystemname; /*!< Add system name to manager responses and events */
- /* Queued events that we've not had the ability to send yet */
- struct eventqent *eventq;
- /* Timeout for ast_carefulwrite() */
- int writetimeout;
- int pending_event; /*!< Pending events indicator in case when waiting_thread is NULL */
- AST_LIST_ENTRY(mansession) list;
-};
-
-static AST_LIST_HEAD_STATIC(sessions, mansession);
-
-struct ast_manager_user {
- char username[80];
- char *secret;
- char *deny;
- char *permit;
- char *read;
- char *write;
- unsigned int displayconnects:1;
- int keep;
- AST_LIST_ENTRY(ast_manager_user) list;
-};
-
-static AST_LIST_HEAD_STATIC(users, ast_manager_user);
-
-static struct manager_action *first_action;
-AST_RWLOCK_DEFINE_STATIC(actionlock);
-
-/*! \brief Convert authority code to string with serveral options */
-static char *authority_to_str(int authority, char *res, int reslen)
-{
- int running_total = 0, i;
-
- memset(res, 0, reslen);
- for (i = 0; i < (sizeof(perms) / sizeof(perms[0])) - 1; i++) {
- if (authority & perms[i].num) {
- if (*res) {
- strncat(res, ",", (reslen > running_total) ? reslen - running_total - 1 : 0);
- running_total++;
- }
- strncat(res, perms[i].label, (reslen > running_total) ? reslen - running_total - 1 : 0);
- running_total += strlen(perms[i].label);
- }
- }
-
- if (ast_strlen_zero(res))
- ast_copy_string(res, "<none>", reslen);
-
- return res;
-}
-
-static char *complete_show_mancmd(const char *line, const char *word, int pos, int state)
-{
- struct manager_action *cur;
- int which = 0;
- char *ret = NULL;
-
- ast_rwlock_rdlock(&actionlock);
- for (cur = first_action; cur; cur = cur->next) { /* Walk the list of actions */
- if (!strncasecmp(word, cur->action, strlen(word)) && ++which > state) {
- ret = ast_strdup(cur->action);
- break; /* make sure we exit even if ast_strdup() returns NULL */
- }
- }
- ast_rwlock_unlock(&actionlock);
-
- return ret;
-}
-
-static void xml_copy_escape(char **dst, size_t *maxlen, const char *src, int lower)
-{
- while (*src && (*maxlen > 6)) {
- switch (*src) {
- case '<':
- strcpy(*dst, "&lt;");
- (*dst) += 4;
- *maxlen -= 4;
- break;
- case '>':
- strcpy(*dst, "&gt;");
- (*dst) += 4;
- *maxlen -= 4;
- break;
- case '\"':
- strcpy(*dst, "&quot;");
- (*dst) += 6;
- *maxlen -= 6;
- break;
- case '\'':
- strcpy(*dst, "&apos;");
- (*dst) += 6;
- *maxlen -= 6;
- break;
- case '&':
- strcpy(*dst, "&amp;");
- (*dst) += 5;
- *maxlen -= 5;
- break;
- default:
- *(*dst)++ = lower ? tolower(*src) : *src;
- (*maxlen)--;
- }
- src++;
- }
-}
-
-struct variable_count {
- char *varname;
- int count;
-};
-
-static int compress_char(char c)
-{
- c &= 0x7f;
- if (c < 32)
- return 0;
- else if (c >= 'a' && c <= 'z')
- return c - 64;
- else if (c > 'z')
- return '_';
- else
- return c - 32;
-}
-
-static int variable_count_hash_fn(const void *vvc, const int flags)
-{
- const struct variable_count *vc = vvc;
- int res = 0, i;
- for (i = 0; i < 5; i++) {
- if (vc->varname[i] == '\0')
- break;
- res += compress_char(vc->varname[i]) << (i * 6);
- }
- return res;
-}
-
-static int variable_count_cmp_fn(void *obj, void *vstr, int flags)
-{
- /* Due to the simplicity of struct variable_count, it makes no difference
- * if you pass in objects or strings, the same operation applies. This is
- * due to the fact that the hash occurs on the first element, which means
- * the address of both the struct and the string are exactly the same. */
- struct variable_count *vc = obj;
- char *str = vstr;
- return !strcmp(vc->varname, str) ? CMP_MATCH | CMP_STOP : 0;
-}
-
-static char *xml_translate(char *in, struct ast_variable *vars)
-{
- struct ast_variable *v;
- char *dest = NULL;
- char *out, *tmp, *var, *val;
- char *objtype = NULL;
- int colons = 0;
- int breaks = 0;
- size_t len;
- int count = 1;
- int escaped = 0;
- int inobj = 0;
- int x;
- struct variable_count *vc = NULL;
- struct ao2_container *vco = NULL;
-
- for (v = vars; v; v = v->next) {
- if (!dest && !strcasecmp(v->name, "ajaxdest"))
- dest = v->value;
- else if (!objtype && !strcasecmp(v->name, "ajaxobjtype"))
- objtype = v->value;
- }
- if (!dest)
- dest = "unknown";
- if (!objtype)
- objtype = "generic";
- for (x = 0; in[x]; x++) {
- if (in[x] == ':')
- colons++;
- else if (in[x] == '\n')
- breaks++;
- else if (strchr("&\"<>\'", in[x]))
- escaped++;
- }
- len = (size_t) (strlen(in) + colons * 5 + breaks * (40 + strlen(dest) + strlen(objtype)) + escaped * 10); /* foo="bar", "<response type=\"object\" id=\"dest\"", "&amp;" */
- out = ast_malloc(len);
- if (!out)
- return 0;
- tmp = out;
- while (*in) {
- var = in;
- while (*in && (*in >= 32))
- in++;
- if (*in) {
- if ((count > 3) && inobj) {
- ast_build_string(&tmp, &len, " /></response>\n");
- inobj = 0;
-
- /* Entity is closed, so close out the name cache */
- ao2_ref(vco, -1);
- vco = NULL;
- }
- count = 0;
- while (*in && (*in < 32)) {
- *in = '\0';
- in++;
- count++;
- }
- val = strchr(var, ':');
- if (val) {
- *val = '\0';
- val++;
- if (*val == ' ')
- val++;
- if (!inobj) {
- vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
- ast_build_string(&tmp, &len, "<response type='object' id='%s'><%s", dest, objtype);
- inobj = 1;
- }
-
- /* Check if the var has been used already */
- if ((vc = ao2_find(vco, var, 0)))
- vc->count++;
- else {
- /* Create a new entry for this one */
- vc = ao2_alloc(sizeof(*vc), NULL);
- vc->varname = var;
- vc->count = 1;
- ao2_link(vco, vc);
- }
-
- ast_build_string(&tmp, &len, " ");
- xml_copy_escape(&tmp, &len, var, 1);
- if (vc->count > 1)
- ast_build_string(&tmp, &len, "-%d", vc->count);
- ast_build_string(&tmp, &len, "='");
- xml_copy_escape(&tmp, &len, val, 0);
- ast_build_string(&tmp, &len, "'");
- ao2_ref(vc, -1);
- }
- }
- }
- if (inobj)
- ast_build_string(&tmp, &len, " /></response>\n");
- if (vco)
- ao2_ref(vco, -1);
- return out;
-}
-
-static char *html_translate(char *in)
-{
- int x;
- int colons = 0;
- int breaks = 0;
- size_t len;
- int count = 1;
- char *tmp, *var, *val, *out;
-
- for (x=0; in[x]; x++) {
- if (in[x] == ':')
- colons++;
- if (in[x] == '\n')
- breaks++;
- }
- len = strlen(in) + colons * 40 + breaks * 40; /* <tr><td></td><td></td></tr>, "<tr><td colspan=\"2\"><hr></td></tr> */
- out = ast_malloc(len);
- if (!out)
- return 0;
- tmp = out;
- while (*in) {
- var = in;
- while (*in && (*in >= 32))
- in++;
- if (*in) {
- if ((count % 4) == 0){
- ast_build_string(&tmp, &len, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
- }
- count = 0;
- while (*in && (*in < 32)) {
- *in = '\0';
- in++;
- count++;
- }
- val = strchr(var, ':');
- if (val) {
- *val = '\0';
- val++;
- if (*val == ' ')
- val++;
- ast_build_string(&tmp, &len, "<tr><td>%s</td><td>%s</td></tr>\r\n", var, val);
- }
- }
- }
- return out;
-}
-
-
-
-static struct ast_manager_user *ast_get_manager_by_name_locked(const char *name)
-{
- struct ast_manager_user *user = NULL;
-
- AST_LIST_TRAVERSE(&users, user, list)
- if (!strcasecmp(user->username, name))
- break;
- return user;
-}
-
-void astman_append(struct mansession *s, const char *fmt, ...)
-{
- va_list ap;
- struct ast_dynamic_str *buf;
-
- ast_mutex_lock(&s->__lock);
-
- if (!(buf = ast_dynamic_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
- ast_mutex_unlock(&s->__lock);
- return;
- }
-
- va_start(ap, fmt);
- ast_dynamic_str_thread_set_va(&buf, 0, &astman_append_buf, fmt, ap);
- va_end(ap);
-
- if (s->fd > -1)
- ast_carefulwrite(s->fd, buf->str, strlen(buf->str), s->writetimeout);
- else {
- if (!s->outputstr && !(s->outputstr = ast_calloc(1, sizeof(*s->outputstr)))) {
- ast_mutex_unlock(&s->__lock);
- return;
- }
-
- ast_dynamic_str_append(&s->outputstr, 0, "%s", buf->str);
- }
-
- ast_mutex_unlock(&s->__lock);
-}
-
-static int handle_showmancmd(int fd, int argc, char *argv[])
-{
- struct manager_action *cur;
- char authority[80];
- int num;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- ast_rwlock_rdlock(&actionlock);
- for (cur = first_action; cur; cur = cur->next) { /* Walk the list of actions */
- for (num = 3; num < argc; num++) {
- if (!strcasecmp(cur->action, argv[num])) {
- ast_cli(fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n", cur->action, cur->synopsis, authority_to_str(cur->authority, authority, sizeof(authority) -1), cur->description ? cur->description : "");
- }
- }
- }
- ast_rwlock_unlock(&actionlock);
-
- return RESULT_SUCCESS;
-}
-
-static int handle_showmanager(int fd, int argc, char *argv[])
-{
- struct ast_manager_user *user = NULL;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- AST_LIST_LOCK(&users);
-
- if (!(user = ast_get_manager_by_name_locked(argv[3]))) {
- ast_cli(fd, "There is no manager called %s\n", argv[3]);
- AST_LIST_UNLOCK(&users);
- return -1;
- }
-
- ast_cli(fd,"\n");
- ast_cli(fd,
- " username: %s\n"
- " secret: %s\n"
- " deny: %s\n"
- " permit: %s\n"
- " read: %s\n"
- " write: %s\n"
- "displayconnects: %s\n",
- (user->username ? user->username : "(N/A)"),
- (user->secret ? "<Set>" : "(N/A)"),
- (user->deny ? user->deny : "(N/A)"),
- (user->permit ? user->permit : "(N/A)"),
- (user->read ? user->read : "(N/A)"),
- (user->write ? user->write : "(N/A)"),
- (user->displayconnects ? "yes" : "no"));
-
- AST_LIST_UNLOCK(&users);
-
- return RESULT_SUCCESS;
-}
-
-
-static int handle_showmanagers(int fd, int argc, char *argv[])
-{
- struct ast_manager_user *user = NULL;
- int count_amu = 0;
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
-
- AST_LIST_LOCK(&users);
-
- /* If there are no users, print out something along those lines */
- if (AST_LIST_EMPTY(&users)) {
- ast_cli(fd, "There are no manager users.\n");
- AST_LIST_UNLOCK(&users);
- return RESULT_SUCCESS;
- }
-
- ast_cli(fd, "\nusername\n--------\n");
-
- AST_LIST_TRAVERSE(&users, user, list) {
- ast_cli(fd, "%s\n", user->username);
- count_amu++;
- }
-
- AST_LIST_UNLOCK(&users);
-
- ast_cli(fd,"-------------------\n");
- ast_cli(fd,"%d manager users configured.\n", count_amu);
-
- return RESULT_SUCCESS;
-}
-
-
-/*! \brief CLI command
- Should change to "manager show commands" */
-static int handle_showmancmds(int fd, int argc, char *argv[])
-{
- struct manager_action *cur;
- char authority[80];
- char *format = " %-15.15s %-15.15s %-55.55s\n";
-
- ast_cli(fd, format, "Action", "Privilege", "Synopsis");
- ast_cli(fd, format, "------", "---------", "--------");
-
- ast_rwlock_rdlock(&actionlock);
- for (cur = first_action; cur; cur = cur->next) /* Walk the list of actions */
- ast_cli(fd, format, cur->action, authority_to_str(cur->authority, authority, sizeof(authority) -1), cur->synopsis);
- ast_rwlock_unlock(&actionlock);
-
- return RESULT_SUCCESS;
-}
-
-/*! \brief CLI command show manager connected */
-/* Should change to "manager show connected" */
-static int handle_showmanconn(int fd, int argc, char *argv[])
-{
- struct mansession *s;
- char *format = " %-15.15s %-15.15s\n";
-
- ast_cli(fd, format, "Username", "IP Address");
-
- AST_LIST_LOCK(&sessions);
- AST_LIST_TRAVERSE(&sessions, s, list)
- ast_cli(fd, format,s->username, ast_inet_ntoa(s->sin.sin_addr));
- AST_LIST_UNLOCK(&sessions);
-
- return RESULT_SUCCESS;
-}
-
-/*! \brief CLI command show manager connected */
-/* Should change to "manager show connected" */
-static int handle_showmaneventq(int fd, int argc, char *argv[])
-{
- struct eventqent *s;
-
- AST_LIST_LOCK(&sessions);
- for (s = master_eventq; s; s = s->next) {
- ast_cli(fd, "Usecount: %d\n",s->usecount);
- ast_cli(fd, "Category: %d\n", s->category);
- ast_cli(fd, "Event:\n%s", s->eventdata);
- }
- AST_LIST_UNLOCK(&sessions);
-
- return RESULT_SUCCESS;
-}
-
-static char showmancmd_help[] =
-"Usage: manager show command <actionname>\n"
-" Shows the detailed description for a specific Asterisk manager interface command.\n";
-
-static char showmancmds_help[] =
-"Usage: manager show commands\n"
-" Prints a listing of all the available Asterisk manager interface commands.\n";
-
-static char showmanconn_help[] =
-"Usage: manager show connected\n"
-" Prints a listing of the users that are currently connected to the\n"
-"Asterisk manager interface.\n";
-
-static char showmaneventq_help[] =
-"Usage: manager show eventq\n"
-" Prints a listing of all events pending in the Asterisk manger\n"
-"event queue.\n";
-
-static char showmanagers_help[] =
-"Usage: manager show users\n"
-" Prints a listing of all managers that are currently configured on that\n"
-" system.\n";
-
-static char showmanager_help[] =
-" Usage: manager show user <user>\n"
-" Display all information related to the manager user specified.\n";
-
-static struct ast_cli_entry cli_show_manager_command_deprecated = {
- { "show", "manager", "command", NULL },
- handle_showmancmd, NULL,
- NULL, complete_show_mancmd };
-
-static struct ast_cli_entry cli_show_manager_commands_deprecated = {
- { "show", "manager", "commands", NULL },
- handle_showmancmds, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_manager_connected_deprecated = {
- { "show", "manager", "connected", NULL },
- handle_showmanconn, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_manager_eventq_deprecated = {
- { "show", "manager", "eventq", NULL },
- handle_showmaneventq, NULL,
- NULL };
-
-static struct ast_cli_entry cli_manager[] = {
- { { "manager", "show", "command", NULL },
- handle_showmancmd, "Show a manager interface command",
- showmancmd_help, complete_show_mancmd, &cli_show_manager_command_deprecated },
-
- { { "manager", "show", "commands", NULL },
- handle_showmancmds, "List manager interface commands",
- showmancmds_help, NULL, &cli_show_manager_commands_deprecated },
-
- { { "manager", "show", "connected", NULL },
- handle_showmanconn, "List connected manager interface users",
- showmanconn_help, NULL, &cli_show_manager_connected_deprecated },
-
- { { "manager", "show", "eventq", NULL },
- handle_showmaneventq, "List manager interface queued events",
- showmaneventq_help, NULL, &cli_show_manager_eventq_deprecated },
-
- { { "manager", "show", "users", NULL },
- handle_showmanagers, "List configured manager users",
- showmanagers_help, NULL, NULL },
-
- { { "manager", "show", "user", NULL },
- handle_showmanager, "Display information on a specific manager user",
- showmanager_help, NULL, NULL },
-};
-
-static void unuse_eventqent(struct eventqent *e)
-{
- if (ast_atomic_dec_and_test(&e->usecount) && e->next)
- pthread_kill(t, SIGURG);
-}
-
-static void free_session(struct mansession *s)
-{
- struct eventqent *eqe;
- if (s->fd > -1)
- close(s->fd);
- if (s->outputstr)
- free(s->outputstr);
- ast_mutex_destroy(&s->__lock);
- while (s->eventq) {
- eqe = s->eventq;
- s->eventq = s->eventq->next;
- unuse_eventqent(eqe);
- }
- free(s);
-}
-
-static void destroy_session(struct mansession *s)
-{
- AST_LIST_LOCK(&sessions);
- AST_LIST_REMOVE(&sessions, s, list);
- num_sessions--;
- free_session(s);
- AST_LIST_UNLOCK(&sessions);
-}
-
-const char *astman_get_header(const struct message *m, char *var)
-{
- char cmp[80];
- int x;
-
- snprintf(cmp, sizeof(cmp), "%s: ", var);
-
- for (x = 0; x < m->hdrcount; x++) {
- if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
- return m->headers[x] + strlen(cmp);
- }
-
- return "";
-}
-
-struct ast_variable *astman_get_variables(const struct message *m)
-{
- int varlen, x, y;
- struct ast_variable *head = NULL, *cur;
- char *var, *val;
-
- char *parse;
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(vars)[32];
- );
-
- varlen = strlen("Variable: ");
-
- for (x = 0; x < m->hdrcount; x++) {
- if (strncasecmp("Variable: ", m->headers[x], varlen))
- continue;
-
- parse = ast_strdupa(m->headers[x] + varlen);
-
- AST_STANDARD_APP_ARGS(args, parse);
- if (args.argc) {
- for (y = 0; y < args.argc; y++) {
- if (!args.vars[y])
- continue;
- var = val = ast_strdupa(args.vars[y]);
- strsep(&val, "=");
- if (!val || ast_strlen_zero(var))
- continue;
- cur = ast_variable_new(var, val);
- if (head) {
- cur->next = head;
- head = cur;
- } else
- head = cur;
- }
- }
- }
-
- return head;
-}
-
-/*! \note NOTE:
- Callers of astman_send_error(), astman_send_response() or astman_send_ack() must EITHER
- hold the session lock _or_ be running in an action callback (in which case s->busy will
- be non-zero). In either of these cases, there is no need to lock-protect the session's
- fd, since no other output will be sent (events will be queued), and no input will
- be read until either the current action finishes or get_input() obtains the session
- lock.
- */
-void astman_send_error(struct mansession *s, const struct message *m, char *error)
-{
- const char *id = astman_get_header(m,"ActionID");
-
- astman_append(s, "Response: Error\r\n");
- if (!ast_strlen_zero(id))
- astman_append(s, "ActionID: %s\r\n", id);
- astman_append(s, "Message: %s\r\n\r\n", error);
-}
-
-void astman_send_response(struct mansession *s, const struct message *m, char *resp, char *msg)
-{
- const char *id = astman_get_header(m,"ActionID");
-
- astman_append(s, "Response: %s\r\n", resp);
- if (!ast_strlen_zero(id))
- astman_append(s, "ActionID: %s\r\n", id);
- if (msg)
- astman_append(s, "Message: %s\r\n\r\n", msg);
- else
- astman_append(s, "\r\n");
-}
-
-void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
-{
- astman_send_response(s, m, "Success", msg);
-}
-
-/*! Tells you if smallstr exists inside bigstr
- which is delim by delim and uses no buf or stringsep
- ast_instring("this|that|more","this",',') == 1;
-
- feel free to move this to app.c -anthm */
-static int ast_instring(const char *bigstr, const char *smallstr, char delim)
-{
- const char *val = bigstr, *next;
-
- do {
- if ((next = strchr(val, delim))) {
- if (!strncmp(val, smallstr, (next - val)))
- return 1;
- else
- continue;
- } else
- return !strcmp(smallstr, val);
-
- } while (*(val = (next + 1)));
-
- return 0;
-}
-
-static int get_perm(const char *instr)
-{
- int x = 0, ret = 0;
-
- if (!instr)
- return 0;
-
- for (x = 0; x < (sizeof(perms) / sizeof(perms[0])); x++) {
- if (ast_instring(instr, perms[x].label, ','))
- ret |= perms[x].num;
- }
-
- return ret;
-}
-
-static int ast_is_number(const char *string)
-{
- int ret = 1, x = 0;
-
- if (!string)
- return 0;
-
- for (x = 0; x < strlen(string); x++) {
- if (!(string[x] >= 48 && string[x] <= 57)) {
- ret = 0;
- break;
- }
- }
-
- return ret ? atoi(string) : 0;
-}
-
-static int strings_to_mask(const char *string)
-{
- int x, ret = -1;
-
- x = ast_is_number(string);
-
- if (x)
- ret = x;
- else if (ast_strlen_zero(string))
- ret = -1;
- else if (ast_false(string))
- ret = 0;
- else if (ast_true(string)) {
- ret = 0;
- for (x=0; x<sizeof(perms) / sizeof(perms[0]); x++)
- ret |= perms[x].num;
- } else {
- ret = 0;
- for (x=0; x<sizeof(perms) / sizeof(perms[0]); x++) {
- if (ast_instring(string, perms[x].label, ','))
- ret |= perms[x].num;
- }
- }
-
- return ret;
-}
-
-/*! \brief
- Rather than braindead on,off this now can also accept a specific int mask value
- or a ',' delim list of mask strings (the same as manager.conf) -anthm
-*/
-static int set_eventmask(struct mansession *s, const char *eventmask)
-{
- int maskint = strings_to_mask(eventmask);
-
- ast_mutex_lock(&s->__lock);
- if (maskint >= 0)
- s->send_events = maskint;
- ast_mutex_unlock(&s->__lock);
-
- return maskint;
-}
-
-static int authenticate(struct mansession *s, const struct message *m)
-{
- struct ast_config *cfg;
- char *cat;
- const char *user = astman_get_header(m, "Username");
- const char *pass = astman_get_header(m, "Secret");
- const char *authtype = astman_get_header(m, "AuthType");
- const char *key = astman_get_header(m, "Key");
- const char *events = astman_get_header(m, "Events");
-
- cfg = ast_config_load("manager.conf");
- if (!cfg)
- return -1;
- cat = ast_category_browse(cfg, NULL);
- while (cat) {
- if (strcasecmp(cat, "general")) {
- /* This is a user */
- if (!strcasecmp(cat, user)) {
- struct ast_variable *v;
- struct ast_ha *ha = NULL;
- char *password = NULL;
-
- for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
- if (!strcasecmp(v->name, "secret")) {
- password = v->value;
- } else if (!strcasecmp(v->name, "displaysystemname")) {
- if (ast_true(v->value)) {
- if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
- s->displaysystemname = 1;
- } else {
- ast_log(LOG_ERROR, "Can't enable displaysystemname in manager.conf - no system name configured in asterisk.conf\n");
- }
- }
- } else if (!strcasecmp(v->name, "permit") ||
- !strcasecmp(v->name, "deny")) {
- ha = ast_append_ha(v->name, v->value, ha);
- } else if (!strcasecmp(v->name, "writetimeout")) {
- int val = atoi(v->value);
-
- if (val < 100)
- ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", v->value, v->lineno);
- else
- s->writetimeout = val;
- }
-
- }
- if (ha && !ast_apply_ha(ha, &(s->sin))) {
- ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user);
- ast_free_ha(ha);
- ast_config_destroy(cfg);
- return -1;
- } else if (ha)
- ast_free_ha(ha);
- if (!strcasecmp(authtype, "MD5")) {
- if (!ast_strlen_zero(key) &&
- !ast_strlen_zero(s->challenge) && !ast_strlen_zero(password)) {
- int x;
- int len = 0;
- char md5key[256] = "";
- struct MD5Context md5;
- unsigned char digest[16];
- MD5Init(&md5);
- MD5Update(&md5, (unsigned char *) s->challenge, strlen(s->challenge));
- MD5Update(&md5, (unsigned char *) password, strlen(password));
- MD5Final(digest, &md5);
- for (x=0; x<16; x++)
- len += sprintf(md5key + len, "%2.2x", digest[x]);
- if (!strcmp(md5key, key))
- break;
- else {
- ast_config_destroy(cfg);
- return -1;
- }
- } else {
- ast_log(LOG_DEBUG, "MD5 authentication is not possible. challenge: '%s'\n",
- S_OR(s->challenge, ""));
- ast_config_destroy(cfg);
- return -1;
- }
- } else if (password && !strcmp(password, pass)) {
- break;
- } else {
- ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user);
- ast_config_destroy(cfg);
- return -1;
- }
- }
- }
- cat = ast_category_browse(cfg, cat);
- }
- if (cat) {
- ast_copy_string(s->username, cat, sizeof(s->username));
- s->readperm = get_perm(ast_variable_retrieve(cfg, cat, "read"));
- s->writeperm = get_perm(ast_variable_retrieve(cfg, cat, "write"));
- ast_config_destroy(cfg);
- if (events)
- set_eventmask(s, events);
- return 0;
- }
- ast_config_destroy(cfg);
- cfg = ast_config_load("users.conf");
- if (!cfg)
- return -1;
- cat = ast_category_browse(cfg, NULL);
- while (cat) {
- struct ast_variable *v;
- const char *password = NULL;
- int hasmanager = 0;
- const char *readperms = NULL;
- const char *writeperms = NULL;
-
- if (strcasecmp(cat, user) || !strcasecmp(cat, "general")) {
- cat = ast_category_browse(cfg, cat);
- continue;
- }
- for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
- if (!strcasecmp(v->name, "secret"))
- password = v->value;
- else if (!strcasecmp(v->name, "hasmanager"))
- hasmanager = ast_true(v->value);
- else if (!strcasecmp(v->name, "managerread"))
- readperms = v->value;
- else if (!strcasecmp(v->name, "managerwrite"))
- writeperms = v->value;
- }
- if (!hasmanager)
- break;
- if (!password || strcmp(password, pass)) {
- ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user);
- ast_config_destroy(cfg);
- return -1;
- }
- ast_copy_string(s->username, cat, sizeof(s->username));
- s->readperm = readperms ? get_perm(readperms) : -1;
- s->writeperm = writeperms ? get_perm(writeperms) : -1;
- ast_config_destroy(cfg);
- if (events)
- set_eventmask(s, events);
- return 0;
- }
- ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user);
- ast_config_destroy(cfg);
- return -1;
-}
-
-/*! \brief Manager PING */
-static char mandescr_ping[] =
-"Description: A 'Ping' action will ellicit a 'Pong' response. Used to keep the\n"
-" manager connection open.\n"
-"Variables: NONE\n";
-
-static int action_ping(struct mansession *s, const struct message *m)
-{
- astman_send_response(s, m, "Pong", NULL);
- return 0;
-}
-
-static char mandescr_getconfig[] =
-"Description: A 'GetConfig' action will dump the contents of a configuration\n"
-"file by category and contents.\n"
-"Variables:\n"
-" Filename: Configuration filename (e.g. foo.conf)\n";
-
-static int action_getconfig(struct mansession *s, const struct message *m)
-{
- struct ast_config *cfg;
- const char *fn = astman_get_header(m, "Filename");
- int catcount = 0;
- int lineno = 0;
- char *category=NULL;
- struct ast_variable *v;
- char idText[256] = "";
- const char *id = astman_get_header(m, "ActionID");
-
- if (!ast_strlen_zero(id))
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
-
- if (ast_strlen_zero(fn)) {
- astman_send_error(s, m, "Filename not specified");
- return 0;
- }
- if (!(cfg = ast_config_load_with_comments(fn))) {
- astman_send_error(s, m, "Config file not found");
- return 0;
- }
- astman_append(s, "Response: Success\r\n%s", idText);
- while ((category = ast_category_browse(cfg, category))) {
- lineno = 0;
- astman_append(s, "Category-%06d: %s\r\n", catcount, category);
- for (v = ast_variable_browse(cfg, category); v; v = v->next)
- astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
- catcount++;
- }
- ast_config_destroy(cfg);
- astman_append(s, "\r\n");
-
- return 0;
-}
-
-
-static void handle_updates(struct mansession *s, const struct message *m, struct ast_config *cfg)
-{
- int x;
- char hdr[40];
- const char *action, *cat, *var, *value, *match;
- struct ast_category *category;
- struct ast_variable *v;
-
- for (x=0;x<100000;x++) {
- unsigned int object = 0;
-
- snprintf(hdr, sizeof(hdr), "Action-%06d", x);
- action = astman_get_header(m, hdr);
- if (ast_strlen_zero(action))
- break;
- snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
- cat = astman_get_header(m, hdr);
- snprintf(hdr, sizeof(hdr), "Var-%06d", x);
- var = astman_get_header(m, hdr);
- snprintf(hdr, sizeof(hdr), "Value-%06d", x);
- value = astman_get_header(m, hdr);
- if (!ast_strlen_zero(value) && *value == '>') {
- object = 1;
- value++;
- }
- snprintf(hdr, sizeof(hdr), "Match-%06d", x);
- match = astman_get_header(m, hdr);
- if (!strcasecmp(action, "newcat")) {
- if (!ast_strlen_zero(cat)) {
- category = ast_category_new(cat);
- if (category) {
- ast_category_append(cfg, category);
- }
- }
- } else if (!strcasecmp(action, "renamecat")) {
- if (!ast_strlen_zero(cat) && !ast_strlen_zero(value)) {
- category = ast_category_get(cfg, cat);
- if (category)
- ast_category_rename(category, value);
- }
- } else if (!strcasecmp(action, "delcat")) {
- if (!ast_strlen_zero(cat))
- ast_category_delete(cfg, (char *) cat);
- } else if (!strcasecmp(action, "update")) {
- if (!ast_strlen_zero(cat) && !ast_strlen_zero(var) && (category = ast_category_get(cfg, cat)))
- ast_variable_update(category, var, value, match, object);
- } else if (!strcasecmp(action, "delete")) {
- if (!ast_strlen_zero(cat) && !ast_strlen_zero(var) && (category = ast_category_get(cfg, cat)))
- ast_variable_delete(category, (char *) var, (char *) match);
- } else if (!strcasecmp(action, "append")) {
- if (!ast_strlen_zero(cat) && !ast_strlen_zero(var) &&
- (category = ast_category_get(cfg, cat)) &&
- (v = ast_variable_new(var, value))){
- if (object || (match && !strcasecmp(match, "object")))
- v->object = 1;
- ast_variable_append(category, v);
- }
- }
- }
-}
-
-static char mandescr_updateconfig[] =
-"Description: A 'UpdateConfig' action will modify, create, or delete\n"
-"configuration elements in Asterisk configuration files.\n"
-"Variables (X's represent 6 digit number beginning with 000000):\n"
-" SrcFilename: Configuration filename to read(e.g. foo.conf)\n"
-" DstFilename: Configuration filename to write(e.g. foo.conf)\n"
-" Reload: Whether or not a reload should take place (or name of specific module)\n"
-" Action-XXXXXX: Action to Take (NewCat,RenameCat,DelCat,Update,Delete,Append)\n"
-" Cat-XXXXXX: Category to operate on\n"
-" Var-XXXXXX: Variable to work on\n"
-" Value-XXXXXX: Value to work on\n"
-" Match-XXXXXX: Extra match required to match line\n";
-
-static int action_updateconfig(struct mansession *s, const struct message *m)
-{
- struct ast_config *cfg;
- const char *sfn = astman_get_header(m, "SrcFilename");
- const char *dfn = astman_get_header(m, "DstFilename");
- int res;
- char idText[256] = "";
- const char *id = astman_get_header(m, "ActionID");
- const char *rld = astman_get_header(m, "Reload");
-
- if (!ast_strlen_zero(id))
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
-
- if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
- astman_send_error(s, m, "Filename not specified");
- return 0;
- }
- if (!(cfg = ast_config_load_with_comments(sfn))) {
- astman_send_error(s, m, "Config file not found");
- return 0;
- }
- handle_updates(s, m, cfg);
- res = config_text_file_save(dfn, cfg, "Manager");
- ast_config_destroy(cfg);
- if (res) {
- astman_send_error(s, m, "Save of config failed");
- return 0;
- }
- astman_append(s, "Response: Success\r\n%s\r\n", idText);
- if (!ast_strlen_zero(rld)) {
- if (ast_true(rld))
- rld = NULL;
- ast_module_reload(rld);
- }
- return 0;
-}
-
-/*! \brief Manager WAITEVENT */
-static char mandescr_waitevent[] =
-"Description: A 'WaitEvent' action will ellicit a 'Success' response. Whenever\n"
-"a manager event is queued. Once WaitEvent has been called on an HTTP manager\n"
-"session, events will be generated and queued.\n"
-"Variables: \n"
-" Timeout: Maximum time to wait for events\n";
-
-static int action_waitevent(struct mansession *s, const struct message *m)
-{
- const char *timeouts = astman_get_header(m, "Timeout");
- int timeout = -1, max;
- int x;
- int needexit = 0;
- time_t now;
- struct eventqent *eqe;
- const char *id = astman_get_header(m,"ActionID");
- char idText[256] = "";
-
- if (!ast_strlen_zero(id))
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
-
- if (!ast_strlen_zero(timeouts)) {
- sscanf(timeouts, "%i", &timeout);
- }
-
- ast_mutex_lock(&s->__lock);
- if (s->waiting_thread != AST_PTHREADT_NULL) {
- pthread_kill(s->waiting_thread, SIGURG);
- }
- if (s->sessiontimeout) {
- time(&now);
- max = s->sessiontimeout - now - 10;
- if (max < 0)
- max = 0;
- if ((timeout < 0) || (timeout > max))
- timeout = max;
- if (!s->send_events)
- s->send_events = -1;
- /* Once waitevent is called, always queue events from now on */
- }
- ast_mutex_unlock(&s->__lock);
- s->waiting_thread = pthread_self();
- if (option_debug)
- ast_log(LOG_DEBUG, "Starting waiting for an event!\n");
- for (x=0; ((x < timeout) || (timeout < 0)); x++) {
- ast_mutex_lock(&s->__lock);
- if (s->eventq && s->eventq->next)
- needexit = 1;
- if (s->waiting_thread != pthread_self())
- needexit = 1;
- if (s->needdestroy)
- needexit = 1;
- ast_mutex_unlock(&s->__lock);
- if (needexit)
- break;
- if (s->fd > 0) {
- if (ast_wait_for_input(s->fd, 1000))
- break;
- } else {
- sleep(1);
- }
- }
- if (option_debug)
- ast_log(LOG_DEBUG, "Finished waiting for an event!\n");
- ast_mutex_lock(&s->__lock);
- if (s->waiting_thread == pthread_self()) {
- astman_send_response(s, m, "Success", "Waiting for Event...");
- /* Only show events if we're the most recent waiter */
- while(s->eventq->next) {
- eqe = s->eventq->next;
- if (((s->readperm & eqe->category) == eqe->category) &&
- ((s->send_events & eqe->category) == eqe->category)) {
- astman_append(s, "%s", eqe->eventdata);
- }
- unuse_eventqent(s->eventq);
- s->eventq = eqe;
- }
- astman_append(s,
- "Event: WaitEventComplete\r\n"
- "%s"
- "\r\n", idText);
- s->waiting_thread = AST_PTHREADT_NULL;
- } else {
- ast_log(LOG_DEBUG, "Abandoning event request!\n");
- }
- ast_mutex_unlock(&s->__lock);
- return 0;
-}
-
-static char mandescr_listcommands[] =
-"Description: Returns the action name and synopsis for every\n"
-" action that is available to the user\n"
-"Variables: NONE\n";
-
-/*! \note The actionlock is read-locked by the caller of this function */
-static int action_listcommands(struct mansession *s, const struct message *m)
-{
- struct manager_action *cur;
- char idText[256] = "";
- char temp[BUFSIZ];
- const char *id = astman_get_header(m,"ActionID");
-
- if (!ast_strlen_zero(id))
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
- astman_append(s, "Response: Success\r\n%s", idText);
- for (cur = first_action; cur; cur = cur->next) {
- if ((s->writeperm & cur->authority) == cur->authority)
- astman_append(s, "%s: %s (Priv: %s)\r\n", cur->action, cur->synopsis, authority_to_str(cur->authority, temp, sizeof(temp)));
- }
- astman_append(s, "\r\n");
-
- return 0;
-}
-
-static char mandescr_events[] =
-"Description: Enable/Disable sending of events to this manager\n"
-" client.\n"
-"Variables:\n"
-" EventMask: 'on' if all events should be sent,\n"
-" 'off' if no events should be sent,\n"
-" 'system,call,log' to select which flags events should have to be sent.\n";
-
-static int action_events(struct mansession *s, const struct message *m)
-{
- const char *mask = astman_get_header(m, "EventMask");
- int res;
-
- res = set_eventmask(s, mask);
- if (res > 0)
- astman_send_response(s, m, "Events On", NULL);
- else if (res == 0)
- astman_send_response(s, m, "Events Off", NULL);
-
- return 0;
-}
-
-static char mandescr_logoff[] =
-"Description: Logoff this manager session\n"
-"Variables: NONE\n";
-
-static int action_logoff(struct mansession *s, const struct message *m)
-{
- astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
- return -1;
-}
-
-static char mandescr_hangup[] =
-"Description: Hangup a channel\n"
-"Variables: \n"
-" Channel: The channel name to be hungup\n";
-
-static int action_hangup(struct mansession *s, const struct message *m)
-{
- struct ast_channel *c = NULL;
- const char *name = astman_get_header(m, "Channel");
- if (ast_strlen_zero(name)) {
- astman_send_error(s, m, "No channel specified");
- return 0;
- }
- c = ast_get_channel_by_name_locked(name);
- if (!c) {
- astman_send_error(s, m, "No such channel");
- return 0;
- }
- ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
- ast_channel_unlock(c);
- astman_send_ack(s, m, "Channel Hungup");
- return 0;
-}
-
-static char mandescr_setvar[] =
-"Description: Set a global or local channel variable.\n"
-"Variables: (Names marked with * are required)\n"
-" Channel: Channel to set variable for\n"
-" *Variable: Variable name\n"
-" *Value: Value\n";
-
-static int action_setvar(struct mansession *s, const struct message *m)
-{
- struct ast_channel *c = NULL;
- const char *name = astman_get_header(m, "Channel");
- const char *varname = astman_get_header(m, "Variable");
- const char *varval = astman_get_header(m, "Value");
-
- if (ast_strlen_zero(varname)) {
- astman_send_error(s, m, "No variable specified");
- return 0;
- }
-
- if (!ast_strlen_zero(name)) {
- c = ast_get_channel_by_name_locked(name);
- if (!c) {
- astman_send_error(s, m, "No such channel");
- return 0;
- }
- }
-
- pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
-
- if (c)
- ast_channel_unlock(c);
-
- astman_send_ack(s, m, "Variable Set");
-
- return 0;
-}
-
-static char mandescr_getvar[] =
-"Description: Get the value of a global or local channel variable.\n"
-"Variables: (Names marked with * are required)\n"
-" Channel: Channel to read variable from\n"
-" *Variable: Variable name\n"
-" ActionID: Optional Action id for message matching.\n";
-
-static int action_getvar(struct mansession *s, const struct message *m)
-{
- struct ast_channel *c = NULL;
- const char *name = astman_get_header(m, "Channel");
- const char *varname = astman_get_header(m, "Variable");
- const char *id = astman_get_header(m,"ActionID");
- char *varval;
- char workspace[1024] = "";
-
- if (ast_strlen_zero(varname)) {
- astman_send_error(s, m, "No variable specified");
- return 0;
- }
-
- if (!ast_strlen_zero(name)) {
- c = ast_get_channel_by_name_locked(name);
- if (!c) {
- astman_send_error(s, m, "No such channel");
- return 0;
- }
- }
-
- if (varname[strlen(varname) - 1] == ')') {
- char *copy = ast_strdupa(varname);
- if (!c) {
- c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/manager");
- if (c) {
- ast_func_read(c, copy, workspace, sizeof(workspace));
- ast_channel_free(c);
- } else
- ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
- } else
- ast_func_read(c, copy, workspace, sizeof(workspace));
- varval = workspace;
- } else {
- pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
- }
-
- if (c)
- ast_channel_unlock(c);
- astman_append(s, "Response: Success\r\n"
- "Variable: %s\r\nValue: %s\r\n", varname, varval);
- if (!ast_strlen_zero(id))
- astman_append(s, "ActionID: %s\r\n",id);
- astman_append(s, "\r\n");
-
- return 0;
-}
-
-
-/*! \brief Manager "status" command to show channels */
-/* Needs documentation... */
-static int action_status(struct mansession *s, const struct message *m)
-{
- const char *id = astman_get_header(m,"ActionID");
- const char *name = astman_get_header(m,"Channel");
- char idText[256] = "";
- struct ast_channel *c;
- char bridge[256];
- struct timeval now = ast_tvnow();
- long elapsed_seconds = 0;
- int all = ast_strlen_zero(name); /* set if we want all channels */
-
- if (!ast_strlen_zero(id))
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
- if (all)
- c = ast_channel_walk_locked(NULL);
- else {
- c = ast_get_channel_by_name_locked(name);
- if (!c) {
- astman_send_error(s, m, "No such channel");
- return 0;
- }
- }
- astman_send_ack(s, m, "Channel status will follow");
- /* if we look by name, we break after the first iteration */
- while (c) {
- if (c->_bridge)
- snprintf(bridge, sizeof(bridge), "Link: %s\r\n", c->_bridge->name);
- else
- bridge[0] = '\0';
- if (c->pbx) {
- if (c->cdr) {
- elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
- }
- astman_append(s,
- "Event: Status\r\n"
- "Privilege: Call\r\n"
- "Channel: %s\r\n"
- "CallerID: %s\r\n" /* This parameter is deprecated and will be removed post-1.4 */
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "Account: %s\r\n"
- "State: %s\r\n"
- "Context: %s\r\n"
- "Extension: %s\r\n"
- "Priority: %d\r\n"
- "Seconds: %ld\r\n"
- "%s"
- "Uniqueid: %s\r\n"
- "%s"
- "\r\n",
- c->name,
- S_OR(c->cid.cid_num, "<unknown>"),
- S_OR(c->cid.cid_num, "<unknown>"),
- S_OR(c->cid.cid_name, "<unknown>"),
- c->accountcode,
- ast_state2str(c->_state), c->context,
- c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, idText);
- } else {
- astman_append(s,
- "Event: Status\r\n"
- "Privilege: Call\r\n"
- "Channel: %s\r\n"
- "CallerID: %s\r\n" /* This parameter is deprecated and will be removed post-1.4 */
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "Account: %s\r\n"
- "State: %s\r\n"
- "%s"
- "Uniqueid: %s\r\n"
- "%s"
- "\r\n",
- c->name,
- S_OR(c->cid.cid_num, "<unknown>"),
- S_OR(c->cid.cid_num, "<unknown>"),
- S_OR(c->cid.cid_name, "<unknown>"),
- c->accountcode,
- ast_state2str(c->_state), bridge, c->uniqueid, idText);
- }
- ast_channel_unlock(c);
- if (!all)
- break;
- c = ast_channel_walk_locked(c);
- }
- astman_append(s,
- "Event: StatusComplete\r\n"
- "%s"
- "\r\n",idText);
- return 0;
-}
-
-static char mandescr_redirect[] =
-"Description: Redirect (transfer) a call.\n"
-"Variables: (Names marked with * are required)\n"
-" *Channel: Channel to redirect\n"
-" ExtraChannel: Second call leg to transfer (optional)\n"
-" *Exten: Extension to transfer to\n"
-" *Context: Context to transfer to\n"
-" *Priority: Priority to transfer to\n"
-" ActionID: Optional Action id for message matching.\n";
-
-/*! \brief action_redirect: The redirect manager command */
-static int action_redirect(struct mansession *s, const struct message *m)
-{
- const char *name = astman_get_header(m, "Channel");
- const char *name2 = astman_get_header(m, "ExtraChannel");
- const char *exten = astman_get_header(m, "Exten");
- const char *context = astman_get_header(m, "Context");
- const char *priority = astman_get_header(m, "Priority");
- struct ast_channel *chan, *chan2 = NULL;
- int pi = 0;
- int res;
-
- if (ast_strlen_zero(name)) {
- astman_send_error(s, m, "Channel not specified");
- return 0;
- }
- if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
- if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
- astman_send_error(s, m, "Invalid priority");
- return 0;
- }
- }
- /* XXX watch out, possible deadlock!!! */
- chan = ast_get_channel_by_name_locked(name);
- if (!chan) {
- char buf[BUFSIZ];
- snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
- astman_send_error(s, m, buf);
- return 0;
- }
- if (ast_check_hangup(chan)) {
- astman_send_error(s, m, "Redirect failed, channel not up.");
- ast_channel_unlock(chan);
- return 0;
- }
- if (!ast_strlen_zero(name2))
- chan2 = ast_get_channel_by_name_locked(name2);
- if (chan2 && ast_check_hangup(chan2)) {
- astman_send_error(s, m, "Redirect failed, extra channel not up.");
- ast_channel_unlock(chan);
- ast_channel_unlock(chan2);
- return 0;
- }
- res = ast_async_goto(chan, context, exten, pi);
- if (!res) {
- if (!ast_strlen_zero(name2)) {
- if (chan2)
- res = ast_async_goto(chan2, context, exten, pi);
- else
- res = -1;
- if (!res)
- astman_send_ack(s, m, "Dual Redirect successful");
- else
- astman_send_error(s, m, "Secondary redirect failed");
- } else
- astman_send_ack(s, m, "Redirect successful");
- } else
- astman_send_error(s, m, "Redirect failed");
- if (chan)
- ast_channel_unlock(chan);
- if (chan2)
- ast_channel_unlock(chan2);
- return 0;
-}
-
-static int check_blacklist(const char *cmd)
-{
- char *cmd_copy, *cur_cmd;
- char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, };
- int i;
-
- cmd_copy = ast_strdupa(cmd);
- for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
- cur_cmd = ast_strip(cur_cmd);
- if (ast_strlen_zero(cur_cmd)) {
- i--;
- continue;
- }
-
- cmd_words[i] = cur_cmd;
- }
-
- for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
- int j, match = 1;
-
- for (j = 0; command_blacklist[i].words[j]; j++) {
- if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
- match = 0;
- break;
- }
- }
-
- if (match) {
- return 1;
- }
- }
-
- return 0;
-}
-
-static char mandescr_command[] =
-"Description: Run a CLI command.\n"
-"Variables: (Names marked with * are required)\n"
-" *Command: Asterisk CLI command to run\n"
-" ActionID: Optional Action id for message matching.\n";
-
-/*! \brief action_command: Manager command "command" - execute CLI command */
-static int action_command(struct mansession *s, const struct message *m)
-{
- const char *cmd = astman_get_header(m, "Command");
- const char *id = astman_get_header(m, "ActionID");
- char *buf, *final_buf;
- char template[] = "/tmp/ast-ami-XXXXXX"; /* template for temporary file */
- int fd = mkstemp(template);
- off_t l;
-
- if (ast_strlen_zero(cmd)) {
- astman_send_error(s, m, "No command provided");
- return 0;
- }
-
- if (check_blacklist(cmd)) {
- astman_send_error(s, m, "Command blacklisted");
- return 0;
- }
-
- astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
- if (!ast_strlen_zero(id))
- astman_append(s, "ActionID: %s\r\n", id);
- /* FIXME: Wedge a ActionID response in here, waiting for later changes */
- ast_cli_command(fd, cmd); /* XXX need to change this to use a FILE * */
- l = lseek(fd, 0, SEEK_END); /* how many chars available */
-
- /* This has a potential to overflow the stack. Hence, use the heap. */
- buf = ast_calloc(1, l + 1);
- final_buf = ast_calloc(1, l + 1);
- if (buf) {
- lseek(fd, 0, SEEK_SET);
- if (read(fd, buf, l) < 0) {
- ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
- }
- buf[l] = '\0';
- if (final_buf) {
- term_strip(final_buf, buf, l);
- final_buf[l] = '\0';
- }
- astman_append(s, "%s", S_OR(final_buf, buf));
- ast_free(buf);
- }
- close(fd);
- unlink(template);
- astman_append(s, "--END COMMAND--\r\n\r\n");
- if (final_buf)
- ast_free(final_buf);
- return 0;
-}
-
-static void *fast_originate(void *data)
-{
- struct fast_originate_helper *in = data;
- int res;
- int reason = 0;
- struct ast_channel *chan = NULL;
- char requested_channel[AST_CHANNEL_NAME];
-
- if (!ast_strlen_zero(in->app)) {
- res = ast_pbx_outgoing_app(in->tech, in->format, in->data, in->timeout, in->app, in->appdata, &reason, 1,
- S_OR(in->cid_num, NULL),
- S_OR(in->cid_name, NULL),
- in->vars, in->account, &chan);
- } else {
- res = ast_pbx_outgoing_exten(in->tech, in->format, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
- S_OR(in->cid_num, NULL),
- S_OR(in->cid_name, NULL),
- in->vars, in->account, &chan);
- }
-
- if (!chan)
- snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
- /* Tell the manager what happened with the channel */
- manager_event(EVENT_FLAG_CALL, "OriginateResponse",
- "%s"
- "Response: %s\r\n"
- "Channel: %s\r\n"
- "Context: %s\r\n"
- "Exten: %s\r\n"
- "Reason: %d\r\n"
- "Uniqueid: %s\r\n"
- "CallerID: %s\r\n" /* This parameter is deprecated and will be removed post-1.4 */
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n",
- in->idtext, res ? "Failure" : "Success", chan ? chan->name : requested_channel, in->context, in->exten, reason,
- chan ? chan->uniqueid : "<null>",
- S_OR(in->cid_num, "<unknown>"),
- S_OR(in->cid_num, "<unknown>"),
- S_OR(in->cid_name, "<unknown>")
- );
-
- /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
- if (chan)
- ast_channel_unlock(chan);
- free(in);
- return NULL;
-}
-
-static char mandescr_originate[] =
-"Description: Generates an outgoing call to a Extension/Context/Priority or\n"
-" Application/Data\n"
-"Variables: (Names marked with * are required)\n"
-" *Channel: Channel name to call\n"
-" Exten: Extension to use (requires 'Context' and 'Priority')\n"
-" Context: Context to use (requires 'Exten' and 'Priority')\n"
-" Priority: Priority to use (requires 'Exten' and 'Context')\n"
-" Application: Application to use\n"
-" Data: Data to use (requires 'Application')\n"
-" Timeout: How long to wait for call to be answered (in ms)\n"
-" CallerID: Caller ID to be set on the outgoing channel\n"
-" Variable: Channel variable to set, multiple Variable: headers are allowed\n"
-" Account: Account code\n"
-" Async: Set to 'true' for fast origination\n";
-
-static int action_originate(struct mansession *s, const struct message *m)
-{
- const char *name = astman_get_header(m, "Channel");
- const char *exten = astman_get_header(m, "Exten");
- const char *context = astman_get_header(m, "Context");
- const char *priority = astman_get_header(m, "Priority");
- const char *timeout = astman_get_header(m, "Timeout");
- const char *callerid = astman_get_header(m, "CallerID");
- const char *account = astman_get_header(m, "Account");
- const char *app = astman_get_header(m, "Application");
- const char *appdata = astman_get_header(m, "Data");
- const char *async = astman_get_header(m, "Async");
- const char *id = astman_get_header(m, "ActionID");
- const char *codecs = astman_get_header(m, "Codecs");
- struct ast_variable *vars = astman_get_variables(m);
- char *tech, *data;
- char *l = NULL, *n = NULL;
- int pi = 0;
- int res;
- int to = 30000;
- int reason = 0;
- char tmp[256];
- char tmp2[256];
- int format = AST_FORMAT_SLINEAR;
-
- pthread_t th;
- pthread_attr_t attr;
- if (ast_strlen_zero(name)) {
- astman_send_error(s, m, "Channel not specified");
- return 0;
- }
- if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
- if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
- astman_send_error(s, m, "Invalid priority");
- return 0;
- }
- }
- if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%d", &to) != 1)) {
- astman_send_error(s, m, "Invalid timeout");
- return 0;
- }
- ast_copy_string(tmp, name, sizeof(tmp));
- tech = tmp;
- data = strchr(tmp, '/');
- if (!data) {
- astman_send_error(s, m, "Invalid channel");
- return 0;
- }
- *data++ = '\0';
- ast_copy_string(tmp2, callerid, sizeof(tmp2));
- ast_callerid_parse(tmp2, &n, &l);
- if (n) {
- if (ast_strlen_zero(n))
- n = NULL;
- }
- if (l) {
- ast_shrink_phone_number(l);
- if (ast_strlen_zero(l))
- l = NULL;
- }
- if (!ast_strlen_zero(codecs)) {
- format = 0;
- ast_parse_allow_disallow(NULL, &format, codecs, 1);
- }
- if (ast_true(async)) {
- struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
- if (!fast) {
- res = -1;
- } else {
- if (!ast_strlen_zero(id))
- snprintf(fast->idtext, sizeof(fast->idtext), "ActionID: %s\r\n", id);
- ast_copy_string(fast->tech, tech, sizeof(fast->tech));
- ast_copy_string(fast->data, data, sizeof(fast->data));
- ast_copy_string(fast->app, app, sizeof(fast->app));
- ast_copy_string(fast->appdata, appdata, sizeof(fast->appdata));
- if (l)
- ast_copy_string(fast->cid_num, l, sizeof(fast->cid_num));
- if (n)
- ast_copy_string(fast->cid_name, n, sizeof(fast->cid_name));
- fast->vars = vars;
- ast_copy_string(fast->context, context, sizeof(fast->context));
- ast_copy_string(fast->exten, exten, sizeof(fast->exten));
- ast_copy_string(fast->account, account, sizeof(fast->account));
- fast->format = format;
- fast->timeout = to;
- fast->priority = pi;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
- ast_free(fast);
- res = -1;
- } else {
- res = 0;
- }
- pthread_attr_destroy(&attr);
- }
- } else if (!ast_strlen_zero(app)) {
- res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
- } else {
- if (exten && context && pi)
- res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
- else {
- astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
- return 0;
- }
- }
- if (!res)
- astman_send_ack(s, m, "Originate successfully queued");
- else
- astman_send_error(s, m, "Originate failed");
- return 0;
-}
-
-/*! \brief Help text for manager command mailboxstatus
- */
-static char mandescr_mailboxstatus[] =
-"Description: Checks a voicemail account for status.\n"
-"Variables: (Names marked with * are required)\n"
-" *Mailbox: Full mailbox ID <mailbox>@<vm-context>\n"
-" ActionID: Optional ActionID for message matching.\n"
-"Returns number of messages.\n"
-" Message: Mailbox Status\n"
-" Mailbox: <mailboxid>\n"
-" Waiting: <count>\n"
-"\n";
-
-static int action_mailboxstatus(struct mansession *s, const struct message *m)
-{
- const char *mailbox = astman_get_header(m, "Mailbox");
- const char *id = astman_get_header(m,"ActionID");
- char idText[256] = "";
- int ret;
- if (ast_strlen_zero(mailbox)) {
- astman_send_error(s, m, "Mailbox not specified");
- return 0;
- }
- if (!ast_strlen_zero(id))
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
- ret = ast_app_has_voicemail(mailbox, NULL);
- astman_append(s, "Response: Success\r\n"
- "%s"
- "Message: Mailbox Status\r\n"
- "Mailbox: %s\r\n"
- "Waiting: %d\r\n\r\n", idText, mailbox, ret);
- return 0;
-}
-
-static char mandescr_mailboxcount[] =
-"Description: Checks a voicemail account for new messages.\n"
-"Variables: (Names marked with * are required)\n"
-" *Mailbox: Full mailbox ID <mailbox>@<vm-context>\n"
-" ActionID: Optional ActionID for message matching.\n"
-"Returns number of new and old messages.\n"
-" Message: Mailbox Message Count\n"
-" Mailbox: <mailboxid>\n"
-" NewMessages: <count>\n"
-" OldMessages: <count>\n"
-"\n";
-static int action_mailboxcount(struct mansession *s, const struct message *m)
-{
- const char *mailbox = astman_get_header(m, "Mailbox");
- const char *id = astman_get_header(m,"ActionID");
- char idText[256] = "";
- int newmsgs = 0, oldmsgs = 0;
- if (ast_strlen_zero(mailbox)) {
- astman_send_error(s, m, "Mailbox not specified");
- return 0;
- }
- ast_app_inboxcount(mailbox, &newmsgs, &oldmsgs);
- if (!ast_strlen_zero(id)) {
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n",id);
- }
- astman_append(s, "Response: Success\r\n"
- "%s"
- "Message: Mailbox Message Count\r\n"
- "Mailbox: %s\r\n"
- "NewMessages: %d\r\n"
- "OldMessages: %d\r\n"
- "\r\n",
- idText,mailbox, newmsgs, oldmsgs);
- return 0;
-}
-
-static char mandescr_extensionstate[] =
-"Description: Report the extension state for given extension.\n"
-" If the extension has a hint, will use devicestate to check\n"
-" the status of the device connected to the extension.\n"
-"Variables: (Names marked with * are required)\n"
-" *Exten: Extension to check state on\n"
-" *Context: Context for extension\n"
-" ActionId: Optional ID for this transaction\n"
-"Will return an \"Extension Status\" message.\n"
-"The response will include the hint for the extension and the status.\n";
-
-static int action_extensionstate(struct mansession *s, const struct message *m)
-{
- const char *exten = astman_get_header(m, "Exten");
- const char *context = astman_get_header(m, "Context");
- const char *id = astman_get_header(m,"ActionID");
- char idText[256] = "";
- char hint[256] = "";
- int status;
- if (ast_strlen_zero(exten)) {
- astman_send_error(s, m, "Extension not specified");
- return 0;
- }
- if (ast_strlen_zero(context))
- context = "default";
- status = ast_extension_state(NULL, context, exten);
- ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
- if (!ast_strlen_zero(id)) {
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
- }
- astman_append(s, "Response: Success\r\n"
- "%s"
- "Message: Extension Status\r\n"
- "Exten: %s\r\n"
- "Context: %s\r\n"
- "Hint: %s\r\n"
- "Status: %d\r\n\r\n",
- idText,exten, context, hint, status);
- return 0;
-}
-
-static char mandescr_timeout[] =
-"Description: Hangup a channel after a certain time.\n"
-"Variables: (Names marked with * are required)\n"
-" *Channel: Channel name to hangup\n"
-" *Timeout: Maximum duration of the call (sec)\n"
-"Acknowledges set time with 'Timeout Set' message\n";
-
-static int action_timeout(struct mansession *s, const struct message *m)
-{
- struct ast_channel *c = NULL;
- const char *name = astman_get_header(m, "Channel");
- int timeout = atoi(astman_get_header(m, "Timeout"));
- if (ast_strlen_zero(name)) {
- astman_send_error(s, m, "No channel specified");
- return 0;
- }
- if (!timeout) {
- astman_send_error(s, m, "No timeout specified");
- return 0;
- }
- c = ast_get_channel_by_name_locked(name);
- if (!c) {
- astman_send_error(s, m, "No such channel");
- return 0;
- }
- ast_channel_setwhentohangup(c, timeout);
- ast_channel_unlock(c);
- astman_send_ack(s, m, "Timeout Set");
- return 0;
-}
-
-static int process_events(struct mansession *s)
-{
- struct eventqent *eqe;
- int ret = 0;
- ast_mutex_lock(&s->__lock);
- if (!s->eventq)
- s->eventq = master_eventq;
- while(s->eventq->next) {
- eqe = s->eventq->next;
- if ((s->authenticated && (s->readperm & eqe->category) == eqe->category) &&
- ((s->send_events & eqe->category) == eqe->category)) {
- if (s->fd > -1) {
- if (!ret && ast_carefulwrite(s->fd, eqe->eventdata, strlen(eqe->eventdata), s->writetimeout) < 0)
- ret = -1;
- } else if (!s->outputstr && !(s->outputstr = ast_calloc(1, sizeof(*s->outputstr))))
- ret = -1;
- else
- ast_dynamic_str_append(&s->outputstr, 0, "%s", eqe->eventdata);
- }
- unuse_eventqent(s->eventq);
- s->eventq = eqe;
- }
- ast_mutex_unlock(&s->__lock);
- return ret;
-}
-
-static char mandescr_userevent[] =
-"Description: Send an event to manager sessions.\n"
-"Variables: (Names marked with * are required)\n"
-" *UserEvent: EventStringToSend\n"
-" Header1: Content1\n"
-" HeaderN: ContentN\n";
-
-static int action_userevent(struct mansession *s, const struct message *m)
-{
- const char *event = astman_get_header(m, "UserEvent");
- char body[2048] = "";
- int x, bodylen = 0, xlen;
- for (x = 0; x < m->hdrcount; x++) {
- if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
- if (sizeof(body) < bodylen + (xlen = strlen(m->headers[x])) + 3) {
- ast_log(LOG_WARNING, "UserEvent exceeds our buffer length. Truncating.\n");
- break;
- }
- ast_copy_string(body + bodylen, m->headers[x], sizeof(body) - bodylen - 3);
- bodylen += xlen;
- ast_copy_string(body + bodylen, "\r\n", 3);
- bodylen += 2;
- }
- }
-
- manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, body);
- return 0;
-}
-
-static int process_message(struct mansession *s, const struct message *m)
-{
- char action[80] = "";
- struct manager_action *tmp;
- const char *id = astman_get_header(m,"ActionID");
- char idText[256] = "";
- int ret = 0;
-
- ast_copy_string(action, astman_get_header(m, "Action"), sizeof(action));
- if (option_debug)
- ast_log( LOG_DEBUG, "Manager received command '%s'\n", action );
-
- if (ast_strlen_zero(action)) {
- astman_send_error(s, m, "Missing action in request");
- return 0;
- }
- if (!ast_strlen_zero(id)) {
- snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
- }
- if (!s->authenticated) {
- if (!strcasecmp(action, "Challenge")) {
- const char *authtype = astman_get_header(m, "AuthType");
-
- if (!strcasecmp(authtype, "MD5")) {
- if (ast_strlen_zero(s->challenge))
- snprintf(s->challenge, sizeof(s->challenge), "%ld", ast_random());
- astman_append(s, "Response: Success\r\n"
- "%s"
- "Challenge: %s\r\n\r\n",
- idText, s->challenge);
- return 0;
- } else {
- astman_send_error(s, m, "Must specify AuthType");
- return 0;
- }
- } else if (!strcasecmp(action, "Login")) {
- if (authenticate(s, m)) {
- sleep(1);
- astman_send_error(s, m, "Authentication failed");
- return -1;
- } else {
- s->authenticated = 1;
- if (option_verbose > 1) {
- if (displayconnects) {
- ast_verbose(VERBOSE_PREFIX_2 "%sManager '%s' logged on from %s\n",
- (s->sessiontimeout ? "HTTP " : ""), s->username, ast_inet_ntoa(s->sin.sin_addr));
- }
- }
- ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n",
- (s->sessiontimeout ? "HTTP " : ""), s->username, ast_inet_ntoa(s->sin.sin_addr));
- astman_send_ack(s, m, "Authentication accepted");
- }
- } else if (!strcasecmp(action, "Logoff")) {
- astman_send_ack(s, m, "See ya");
- return -1;
- } else
- astman_send_error(s, m, "Authentication Required");
- } else {
- if (!strcasecmp(action, "Login"))
- astman_send_ack(s, m, "Already logged in");
- else {
- ast_rwlock_rdlock(&actionlock);
- for (tmp = first_action; tmp; tmp = tmp->next) {
- if (strcasecmp(action, tmp->action))
- continue;
- if ((s->writeperm & tmp->authority) == tmp->authority) {
- if (tmp->func(s, m))
- ret = -1;
- } else
- astman_send_error(s, m, "Permission denied");
- break;
- }
- ast_rwlock_unlock(&actionlock);
- if (!tmp)
- astman_send_error(s, m, "Invalid/unknown command");
- }
- }
- if (ret)
- return ret;
- return process_events(s);
-}
-
-static int get_input(struct mansession *s, char *output)
-{
- /* output must have at least sizeof(s->inbuf) space */
- int res;
- int x;
- struct pollfd fds[1];
- for (x = 1; x < s->inlen; x++) {
- if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) {
- /* Copy output data up to and including \r\n */
- memcpy(output, s->inbuf, x + 1);
- /* Add trailing \0 */
- output[x+1] = '\0';
- /* Move remaining data back to the front */
- memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x);
- s->inlen -= (x + 1);
- return 1;
- }
- }
- if (s->inlen >= sizeof(s->inbuf) - 1) {
- ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->sin.sin_addr), s->inbuf);
- s->inlen = 0;
- }
- fds[0].fd = s->fd;
- fds[0].events = POLLIN;
- do {
- ast_mutex_lock(&s->__lock);
- if (s->pending_event) {
- s->pending_event = 0;
- ast_mutex_unlock(&s->__lock);
- return 0;
- }
- s->waiting_thread = pthread_self();
- ast_mutex_unlock(&s->__lock);
-
- res = poll(fds, 1, -1);
-
- ast_mutex_lock(&s->__lock);
- s->waiting_thread = AST_PTHREADT_NULL;
- ast_mutex_unlock(&s->__lock);
- if (res < 0) {
- if (errno == EINTR || errno == EAGAIN) {
- return 0;
- }
- ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
- return -1;
- } else if (res > 0) {
- ast_mutex_lock(&s->__lock);
- res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen);
- ast_mutex_unlock(&s->__lock);
- if (res < 1)
- return -1;
- break;
- }
- } while(1);
- s->inlen += res;
- s->inbuf[s->inlen] = '\0';
- return 0;
-}
-
-static int do_message(struct mansession *s)
-{
- struct message m = { 0 };
- char header_buf[sizeof(s->inbuf)] = { '\0' };
- int res;
-
- for (;;) {
- /* Check if any events are pending and do them if needed */
- if (s->eventq->next) {
- if (process_events(s))
- return -1;
- }
- res = get_input(s, header_buf);
- if (res == 0) {
- continue;
- } else if (res > 0) {
- /* Strip trailing \r\n */
- if (strlen(header_buf) < 2)
- continue;
- header_buf[strlen(header_buf) - 2] = '\0';
- if (ast_strlen_zero(header_buf))
- return process_message(s, &m) ? -1 : 0;
- else if (m.hdrcount < (AST_MAX_MANHEADERS - 1))
- m.headers[m.hdrcount++] = ast_strdupa(header_buf);
- } else {
- return res;
- }
- }
-}
-
-static void *session_do(void *data)
-{
- struct mansession *s = data;
- int res;
-
- astman_append(s, "Asterisk Call Manager/1.0\r\n");
- for (;;) {
- if ((res = do_message(s)) < 0)
- break;
- }
- if (s->authenticated) {
- if (option_verbose > 1) {
- if (displayconnects)
- ast_verbose(VERBOSE_PREFIX_2 "Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
- }
- ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
- } else {
- if (option_verbose > 1) {
- if (displayconnects)
- ast_verbose(VERBOSE_PREFIX_2 "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr));
- }
- ast_log(LOG_EVENT, "Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr));
- }
-
- /* It is possible under certain circumstances for this session thread
- to complete its work and exit *before* the thread that created it
- has finished executing the ast_pthread_create_background() function.
- If this occurs, some versions of glibc appear to act in a buggy
- fashion and attempt to write data into memory that it thinks belongs
- to the thread but is in fact not owned by the thread (or may have
- been freed completely).
-
- Causing this thread to yield to other threads at least one time
- appears to work around this bug.
- */
- usleep(1);
-
- destroy_session(s);
- return NULL;
-}
-
-static void *accept_thread(void *ignore)
-{
- int as;
- struct sockaddr_in sin;
- socklen_t sinlen;
- struct eventqent *eqe;
- struct mansession *s;
- struct protoent *p;
- int arg = 1;
- int flags;
- pthread_attr_t attr;
- time_t now;
- struct pollfd pfds[1];
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- for (;;) {
- time(&now);
- AST_LIST_LOCK(&sessions);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, s, list) {
- if (s->sessiontimeout && (now > s->sessiontimeout) && !s->inuse) {
- AST_LIST_REMOVE_CURRENT(&sessions, list);
- num_sessions--;
- if (s->authenticated && (option_verbose > 1) && displayconnects) {
- ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' timed out from %s\n",
- s->username, ast_inet_ntoa(s->sin.sin_addr));
- }
- free_session(s);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- /* Purge master event queue of old, unused events, but make sure we
- always keep at least one in the queue */
- eqe = master_eventq;
- while (master_eventq->next && !master_eventq->usecount) {
- eqe = master_eventq;
- master_eventq = master_eventq->next;
- free(eqe);
- }
- AST_LIST_UNLOCK(&sessions);
-
- sinlen = sizeof(sin);
- pfds[0].fd = asock;
- pfds[0].events = POLLIN;
- /* Wait for something to happen, but timeout every few seconds so
- we can ditch any old manager sessions */
- if (poll(pfds, 1, 5000) < 1)
- continue;
- as = accept(asock, (struct sockaddr *)&sin, &sinlen);
- if (as < 0) {
- ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
- continue;
- }
- p = getprotobyname("tcp");
- if (p) {
- if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
- ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
- }
- }
- if (!(s = ast_calloc(1, sizeof(*s))))
- continue;
-
- memcpy(&s->sin, &sin, sizeof(sin));
- s->writetimeout = 100;
- s->waiting_thread = AST_PTHREADT_NULL;
-
- if (!block_sockets) {
- /* For safety, make sure socket is non-blocking */
- flags = fcntl(as, F_GETFL);
- fcntl(as, F_SETFL, flags | O_NONBLOCK);
- } else {
- flags = fcntl(as, F_GETFL);
- fcntl(as, F_SETFL, flags & ~O_NONBLOCK);
- }
- ast_mutex_init(&s->__lock);
- s->fd = as;
- s->send_events = -1;
- AST_LIST_LOCK(&sessions);
- AST_LIST_INSERT_HEAD(&sessions, s, list);
- num_sessions++;
- /* Find the last place in the master event queue and hook ourselves
- in there */
- s->eventq = master_eventq;
- while(s->eventq->next)
- s->eventq = s->eventq->next;
- ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
- AST_LIST_UNLOCK(&sessions);
- if (ast_pthread_create_background(&s->t, &attr, session_do, s))
- destroy_session(s);
- }
- pthread_attr_destroy(&attr);
- return NULL;
-}
-
-static int append_event(const char *str, int category)
-{
- struct eventqent *tmp, *prev = NULL;
- tmp = ast_malloc(sizeof(*tmp) + strlen(str));
-
- if (!tmp)
- return -1;
-
- tmp->next = NULL;
- tmp->category = category;
- strcpy(tmp->eventdata, str);
-
- if (master_eventq) {
- prev = master_eventq;
- while (prev->next)
- prev = prev->next;
- prev->next = tmp;
- } else {
- master_eventq = tmp;
- }
-
- tmp->usecount = num_sessions;
-
- return 0;
-}
-
-/*! \brief manager_event: Send AMI event to client */
-int manager_event(int category, const char *event, const char *fmt, ...)
-{
- struct mansession *s;
- char auth[80];
- va_list ap;
- struct timeval now;
- struct ast_dynamic_str *buf;
-
- /* Abort if there aren't any manager sessions */
- if (!num_sessions)
- return 0;
-
- if (!(buf = ast_dynamic_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE)))
- return -1;
-
- ast_dynamic_str_thread_set(&buf, 0, &manager_event_buf,
- "Event: %s\r\nPrivilege: %s\r\n",
- event, authority_to_str(category, auth, sizeof(auth)));
-
- if (timestampevents) {
- now = ast_tvnow();
- ast_dynamic_str_thread_append(&buf, 0, &manager_event_buf,
- "Timestamp: %ld.%06lu\r\n",
- now.tv_sec, (unsigned long) now.tv_usec);
- }
-
- va_start(ap, fmt);
- ast_dynamic_str_thread_append_va(&buf, 0, &manager_event_buf, fmt, ap);
- va_end(ap);
-
- ast_dynamic_str_thread_append(&buf, 0, &manager_event_buf, "\r\n");
-
- /* Append event to master list and wake up any sleeping sessions */
- AST_LIST_LOCK(&sessions);
- append_event(buf->str, category);
- AST_LIST_TRAVERSE(&sessions, s, list) {
- ast_mutex_lock(&s->__lock);
- if (s->waiting_thread != AST_PTHREADT_NULL)
- pthread_kill(s->waiting_thread, SIGURG);
- else
- /* We have an event to process, but the mansession is
- * not waiting for it. We still need to indicate that there
- * is an event waiting so that get_input processes the pending
- * event instead of polling.
- */
- s->pending_event = 1;
- ast_mutex_unlock(&s->__lock);
- }
- AST_LIST_UNLOCK(&sessions);
-
- return 0;
-}
-
-int ast_manager_unregister(char *action)
-{
- struct manager_action *cur, *prev;
-
- ast_rwlock_wrlock(&actionlock);
- cur = prev = first_action;
- while (cur) {
- if (!strcasecmp(action, cur->action)) {
- prev->next = cur->next;
- free(cur);
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Manager unregistered action %s\n", action);
- ast_rwlock_unlock(&actionlock);
- return 0;
- }
- prev = cur;
- cur = cur->next;
- }
- ast_rwlock_unlock(&actionlock);
- return 0;
-}
-
-static int manager_state_cb(char *context, char *exten, int state, void *data)
-{
- /* Notify managers of change */
- manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
- return 0;
-}
-
-static int ast_manager_register_struct(struct manager_action *act)
-{
- struct manager_action *cur, *prev = NULL;
- int ret;
-
- ast_rwlock_wrlock(&actionlock);
- cur = first_action;
- while (cur) { /* Walk the list of actions */
- ret = strcasecmp(cur->action, act->action);
- if (ret == 0) {
- ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
- ast_rwlock_unlock(&actionlock);
- return -1;
- } else if (ret > 0) {
- /* Insert these alphabetically */
- if (prev) {
- act->next = prev->next;
- prev->next = act;
- } else {
- act->next = first_action;
- first_action = act;
- }
- break;
- }
- prev = cur;
- cur = cur->next;
- }
-
- if (!cur) {
- if (prev)
- prev->next = act;
- else
- first_action = act;
- act->next = NULL;
- }
-
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Manager registered action %s\n", act->action);
- ast_rwlock_unlock(&actionlock);
- return 0;
-}
-
-/*! \brief register a new command with manager, including online help. This is
- the preferred way to register a manager command */
-int ast_manager_register2(const char *action, int auth, int (*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description)
-{
- struct manager_action *cur;
-
- cur = ast_malloc(sizeof(*cur));
- if (!cur)
- return -1;
-
- cur->action = action;
- cur->authority = auth;
- cur->func = func;
- cur->synopsis = synopsis;
- cur->description = description;
- cur->next = NULL;
-
- ast_manager_register_struct(cur);
-
- return 0;
-}
-/*! @}
- END Doxygen group */
-
-static struct mansession *find_session(uint32_t ident)
-{
- struct mansession *s;
-
- AST_LIST_LOCK(&sessions);
- AST_LIST_TRAVERSE(&sessions, s, list) {
- ast_mutex_lock(&s->__lock);
- if (s->sessiontimeout && (s->managerid == ident) && !s->needdestroy) {
- s->inuse++;
- break;
- }
- ast_mutex_unlock(&s->__lock);
- }
- AST_LIST_UNLOCK(&sessions);
-
- return s;
-}
-
-int astman_verify_session_readpermissions(uint32_t ident, int perm)
-{
- int result = 0;
- struct mansession *s;
-
- AST_LIST_LOCK(&sessions);
- AST_LIST_TRAVERSE(&sessions, s, list) {
- ast_mutex_lock(&s->__lock);
- if ((s->managerid == ident) && (s->readperm & perm)) {
- result = 1;
- ast_mutex_unlock(&s->__lock);
- break;
- }
- ast_mutex_unlock(&s->__lock);
- }
- AST_LIST_UNLOCK(&sessions);
- return result;
-}
-
-int astman_verify_session_writepermissions(uint32_t ident, int perm)
-{
- int result = 0;
- struct mansession *s;
-
- AST_LIST_LOCK(&sessions);
- AST_LIST_TRAVERSE(&sessions, s, list) {
- ast_mutex_lock(&s->__lock);
- if ((s->managerid == ident) && (s->writeperm & perm)) {
- result = 1;
- ast_mutex_unlock(&s->__lock);
- break;
- }
- ast_mutex_unlock(&s->__lock);
- }
- AST_LIST_UNLOCK(&sessions);
- return result;
-}
-
-enum {
- FORMAT_RAW,
- FORMAT_HTML,
- FORMAT_XML,
-};
-static char *contenttype[] = { "plain", "html", "xml" };
-
-static char *generic_http_callback(int format, struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
-{
- struct mansession *s = NULL;
- uint32_t ident = 0;
- char workspace[512];
- char cookie[128];
- size_t len = sizeof(workspace);
- int blastaway = 0;
- char *c = workspace;
- char *retval = NULL;
- struct ast_variable *v;
-
- for (v = params; v; v = v->next) {
- if (!strcasecmp(v->name, "mansession_id")) {
- sscanf(v->value, "%x", &ident);
- break;
- }
- }
-
- if (!(s = find_session(ident))) {
- /* Create new session */
- if (!(s = ast_calloc(1, sizeof(*s)))) {
- *status = 500;
- goto generic_callback_out;
- }
- memcpy(&s->sin, requestor, sizeof(s->sin));
- s->fd = -1;
- s->waiting_thread = AST_PTHREADT_NULL;
- s->send_events = 0;
- ast_mutex_init(&s->__lock);
- ast_mutex_lock(&s->__lock);
- s->inuse = 1;
- /*!\note There is approximately a 1 in 1.8E19 chance that the following
- * calculation will produce 0, which is an invalid ID, but due to the
- * properties of the rand() function (and the constantcy of s), that
- * won't happen twice in a row.
- */
- while ((s->managerid = rand() ^ (unsigned long) s) == 0);
- AST_LIST_LOCK(&sessions);
- AST_LIST_INSERT_HEAD(&sessions, s, list);
- /* Hook into the last spot in the event queue */
- s->eventq = master_eventq;
- while (s->eventq->next)
- s->eventq = s->eventq->next;
- ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
- ast_atomic_fetchadd_int(&num_sessions, 1);
- AST_LIST_UNLOCK(&sessions);
- }
-
- /* Reset HTTP timeout. If we're not yet authenticated, keep it extremely short */
- time(&s->sessiontimeout);
- if (!s->authenticated && (httptimeout > 5))
- s->sessiontimeout += 5;
- else
- s->sessiontimeout += httptimeout;
- ast_mutex_unlock(&s->__lock);
-
- if (s) {
- struct message m = { 0 };
- char tmp[80];
- unsigned int x;
- size_t hdrlen;
-
- for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
- hdrlen = strlen(v->name) + strlen(v->value) + 3;
- m.headers[m.hdrcount] = alloca(hdrlen);
- snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
- m.hdrcount = x + 1;
- }
-
- if (process_message(s, &m)) {
- if (s->authenticated) {
- if (option_verbose > 1) {
- if (displayconnects)
- ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
- }
- ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
- } else {
- if (option_verbose > 1) {
- if (displayconnects)
- ast_verbose(VERBOSE_PREFIX_2 "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr));
- }
- ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr));
- }
- s->needdestroy = 1;
- }
- ast_build_string(&c, &len, "Content-type: text/%s\r\n", contenttype[format]);
- sprintf(tmp, "%08x", s->managerid);
- ast_build_string(&c, &len, "%s\r\n", ast_http_setcookie("mansession_id", tmp, httptimeout, cookie, sizeof(cookie)));
- if (format == FORMAT_HTML)
- ast_build_string(&c, &len, "<title>Asterisk&trade; Manager Interface</title>");
- if (format == FORMAT_XML) {
- ast_build_string(&c, &len, "<ajax-response>\n");
- } else if (format == FORMAT_HTML) {
- ast_build_string(&c, &len, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
- ast_build_string(&c, &len, "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\"><h1>&nbsp;&nbsp;Manager Tester</h1></td></tr>\r\n");
- }
- ast_mutex_lock(&s->__lock);
- if (s->outputstr) {
- char *tmp;
- if (format == FORMAT_XML)
- tmp = xml_translate(s->outputstr->str, params);
- else if (format == FORMAT_HTML)
- tmp = html_translate(s->outputstr->str);
- else
- tmp = s->outputstr->str;
- if (tmp) {
- retval = malloc(strlen(workspace) + strlen(tmp) + 128);
- if (retval) {
- strcpy(retval, workspace);
- strcpy(retval + strlen(retval), tmp);
- c = retval + strlen(retval);
- len = 120;
- }
- }
- if (tmp != s->outputstr->str)
- free(tmp);
- free(s->outputstr);
- s->outputstr = NULL;
- }
- ast_mutex_unlock(&s->__lock);
- /* Still okay because c would safely be pointing to workspace even
- if retval failed to allocate above */
- if (format == FORMAT_XML) {
- ast_build_string(&c, &len, "</ajax-response>\n");
- } else if (format == FORMAT_HTML)
- ast_build_string(&c, &len, "</table></body>\r\n");
- } else {
- *status = 500;
- *title = strdup("Server Error");
- }
- ast_mutex_lock(&s->__lock);
- if (s->needdestroy) {
- if (s->inuse == 1) {
- ast_log(LOG_DEBUG, "Need destroy, doing it now!\n");
- blastaway = 1;
- } else {
- ast_log(LOG_DEBUG, "Need destroy, but can't do it yet!\n");
- if (s->waiting_thread != AST_PTHREADT_NULL)
- pthread_kill(s->waiting_thread, SIGURG);
- s->inuse--;
- }
- } else
- s->inuse--;
- ast_mutex_unlock(&s->__lock);
-
- if (blastaway)
- destroy_session(s);
-generic_callback_out:
- if (*status != 200)
- return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n");
- return retval;
-}
-
-static char *manager_http_callback(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
-{
- return generic_http_callback(FORMAT_HTML, requestor, uri, params, status, title, contentlength);
-}
-
-static char *mxml_http_callback(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
-{
- return generic_http_callback(FORMAT_XML, requestor, uri, params, status, title, contentlength);
-}
-
-static char *rawman_http_callback(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
-{
- return generic_http_callback(FORMAT_RAW, requestor, uri, params, status, title, contentlength);
-}
-
-struct ast_http_uri rawmanuri = {
- .description = "Raw HTTP Manager Event Interface",
- .uri = "rawman",
- .has_subtree = 0,
- .callback = rawman_http_callback,
-};
-
-struct ast_http_uri manageruri = {
- .description = "HTML Manager Event Interface",
- .uri = "manager",
- .has_subtree = 0,
- .callback = manager_http_callback,
-};
-
-struct ast_http_uri managerxmluri = {
- .description = "XML Manager Event Interface",
- .uri = "mxml",
- .has_subtree = 0,
- .callback = mxml_http_callback,
-};
-
-static int registered = 0;
-static int webregged = 0;
-
-int init_manager(void)
-{
- struct ast_config *cfg = NULL, *ucfg = NULL;
- const char *val;
- char *cat = NULL;
- int oldportno = portno;
- static struct sockaddr_in ba;
- int x = 1;
- int flags;
- int webenabled = 0;
- int newhttptimeout = 60;
- struct ast_manager_user *user = NULL;
-
- if (!registered) {
- /* Register default actions */
- ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
- ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
- ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
- ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
- ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
- ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
- ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
- ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
- ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
- ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
- ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate);
- ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
- ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
- ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
- ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
- ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
- ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
- ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
- ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
-
- ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
- ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
- registered = 1;
- /* Append placeholder event so master_eventq never runs dry */
- append_event("Event: Placeholder\r\n\r\n", 0);
- }
- portno = DEFAULT_MANAGER_PORT;
- displayconnects = 1;
- cfg = ast_config_load("manager.conf");
- if (!cfg) {
- ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n");
- return 0;
- }
- val = ast_variable_retrieve(cfg, "general", "enabled");
- if (val)
- enabled = ast_true(val);
-
- val = ast_variable_retrieve(cfg, "general", "block-sockets");
- if (val)
- block_sockets = ast_true(val);
-
- val = ast_variable_retrieve(cfg, "general", "webenabled");
- if (val)
- webenabled = ast_true(val);
-
- if ((val = ast_variable_retrieve(cfg, "general", "port"))) {
- if (sscanf(val, "%d", &portno) != 1) {
- ast_log(LOG_WARNING, "Invalid port number '%s'\n", val);
- portno = DEFAULT_MANAGER_PORT;
- }
- }
-
- if ((val = ast_variable_retrieve(cfg, "general", "displayconnects")))
- displayconnects = ast_true(val);
-
- if ((val = ast_variable_retrieve(cfg, "general", "timestampevents")))
- timestampevents = ast_true(val);
-
- if ((val = ast_variable_retrieve(cfg, "general", "httptimeout")))
- newhttptimeout = atoi(val);
-
- memset(&ba, 0, sizeof(ba));
- ba.sin_family = AF_INET;
- ba.sin_port = htons(portno);
-
- if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) {
- if (!inet_aton(val, &ba.sin_addr)) {
- ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
- memset(&ba.sin_addr, 0, sizeof(ba.sin_addr));
- }
- }
-
-
- if ((asock > -1) && ((portno != oldportno) || !enabled)) {
-#if 0
- /* Can't be done yet */
- close(asock);
- asock = -1;
-#else
- ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
-#endif
- }
-
- AST_LIST_LOCK(&users);
-
- if ((ucfg = ast_config_load("users.conf"))) {
- while ((cat = ast_category_browse(ucfg, cat))) {
- int hasmanager = 0;
- struct ast_variable *var = NULL;
-
- if (!strcasecmp(cat, "general")) {
- continue;
- }
-
- if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) {
- continue;
- }
-
- /* Look for an existing entry, if none found - create one and add it to the list */
- if (!(user = ast_get_manager_by_name_locked(cat))) {
- if (!(user = ast_calloc(1, sizeof(*user)))) {
- break;
- }
- /* Copy name over */
- ast_copy_string(user->username, cat, sizeof(user->username));
- /* Insert into list */
- AST_LIST_INSERT_TAIL(&users, user, list);
- }
-
- /* Make sure we keep this user and don't destroy it during cleanup */
- user->keep = 1;
-
- for (var = ast_variable_browse(ucfg, cat); var; var = var->next) {
- if (!strcasecmp(var->name, "secret")) {
- if (user->secret) {
- free(user->secret);
- }
- user->secret = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "deny") ) {
- if (user->deny) {
- free(user->deny);
- }
- user->deny = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "permit") ) {
- if (user->permit) {
- free(user->permit);
- }
- user->permit = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "read") ) {
- if (user->read) {
- free(user->read);
- }
- user->read = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "write") ) {
- if (user->write) {
- free(user->write);
- }
- user->write = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "displayconnects") ) {
- user->displayconnects = ast_true(var->value);
- } else if (!strcasecmp(var->name, "hasmanager")) {
- /* already handled */
- } else {
- ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name);
- }
- }
- }
- ast_config_destroy(ucfg);
- }
-
- while ((cat = ast_category_browse(cfg, cat))) {
- struct ast_variable *var = NULL;
-
- if (!strcasecmp(cat, "general"))
- continue;
-
- /* Look for an existing entry, if none found - create one and add it to the list */
- if (!(user = ast_get_manager_by_name_locked(cat))) {
- if (!(user = ast_calloc(1, sizeof(*user))))
- break;
- /* Copy name over */
- ast_copy_string(user->username, cat, sizeof(user->username));
- /* Insert into list */
- AST_LIST_INSERT_TAIL(&users, user, list);
- }
-
- /* Make sure we keep this user and don't destroy it during cleanup */
- user->keep = 1;
-
- var = ast_variable_browse(cfg, cat);
- while (var) {
- if (!strcasecmp(var->name, "secret")) {
- if (user->secret)
- free(user->secret);
- user->secret = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "deny") ) {
- if (user->deny)
- free(user->deny);
- user->deny = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "permit") ) {
- if (user->permit)
- free(user->permit);
- user->permit = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "read") ) {
- if (user->read)
- free(user->read);
- user->read = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "write") ) {
- if (user->write)
- free(user->write);
- user->write = ast_strdup(var->value);
- } else if (!strcasecmp(var->name, "displayconnects") )
- user->displayconnects = ast_true(var->value);
- else
- ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name);
- var = var->next;
- }
- }
-
- /* Perform cleanup - essentially prune out old users that no longer exist */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
- if (user->keep) {
- user->keep = 0;
- continue;
- }
- /* We do not need to keep this user so take them out of the list */
- AST_LIST_REMOVE_CURRENT(&users, list);
- /* Free their memory now */
- if (user->secret)
- free(user->secret);
- if (user->deny)
- free(user->deny);
- if (user->permit)
- free(user->permit);
- if (user->read)
- free(user->read);
- if (user->write)
- free(user->write);
- free(user);
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- AST_LIST_UNLOCK(&users);
-
- ast_config_destroy(cfg);
-
- if (webenabled && enabled) {
- if (!webregged) {
- ast_http_uri_link(&rawmanuri);
- ast_http_uri_link(&manageruri);
- ast_http_uri_link(&managerxmluri);
- webregged = 1;
- }
- } else {
- if (webregged) {
- ast_http_uri_unlink(&rawmanuri);
- ast_http_uri_unlink(&manageruri);
- ast_http_uri_unlink(&managerxmluri);
- webregged = 0;
- }
- }
-
- if (newhttptimeout > 0)
- httptimeout = newhttptimeout;
-
- /* If not enabled, do nothing */
- if (!enabled)
- return 0;
-
- if (asock < 0) {
- asock = socket(AF_INET, SOCK_STREAM, 0);
- if (asock < 0) {
- ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
- return -1;
- }
- setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
- if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) {
- ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno));
- close(asock);
- asock = -1;
- return -1;
- }
- if (listen(asock, 2)) {
- ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno));
- close(asock);
- asock = -1;
- return -1;
- }
- flags = fcntl(asock, F_GETFL);
- fcntl(asock, F_SETFL, flags | O_NONBLOCK);
- if (option_verbose)
- ast_verbose("Asterisk Management interface listening on port %d\n", portno);
- ast_pthread_create_background(&t, NULL, accept_thread, NULL);
- }
- return 0;
-}
-
-int reload_manager(void)
-{
- manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n");
- return init_manager();
-}
diff --git a/main/md5.c b/main/md5.c
deleted file mode 100644
index 949c408e2..000000000
--- a/main/md5.c
+++ /dev/null
@@ -1,267 +0,0 @@
-
-/*!\file
-\brief MD5 checksum routines used for authentication. Not covered by GPL, but
- in the public domain as per the copyright below */
-
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <string.h> /* for memcpy() */
-
-#include "asterisk/endian.h"
-#include "asterisk/md5.h"
-
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define HIGHFIRST 1
-# endif
-#ifndef HIGHFIRST
-#define byteReverse(buf, len) /* Nothing */
-#else
-void byteReverse(unsigned char *buf, unsigned longs);
-
-#ifndef ASM_MD5
-/*
- * Note: this code is harmless on little-endian machines.
- */
-void byteReverse(unsigned char *buf, unsigned longs)
-{
- uint32_t t;
- do {
- t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
- ((unsigned) buf[1] << 8 | buf[0]);
- *(uint32_t *) buf = t;
- buf += 4;
- } while (--longs);
-}
-#endif
-#endif
-
-/*
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-void MD5Init(struct MD5Context *ctx)
-{
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
-
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
-{
- uint32_t t;
-
- /* Update bitcount */
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
-
- /* Handle any leading odd-sized chunks */
-
- if (t) {
- unsigned char *p = (unsigned char *) ctx->in + t;
-
- t = 64 - t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += t;
- len -= t;
- }
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
-{
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count - 8);
- }
- byteReverse(ctx->in, 14);
-
- /* Append length in bits and transform */
- ((uint32_t *) ctx->in)[14] = ctx->bits[0];
- ((uint32_t *) ctx->in)[15] = ctx->bits[1];
-
- MD5Transform(ctx->buf, (uint32_t *) ctx->in);
- byteReverse((unsigned char *) ctx->buf, 4);
- memcpy(digest, ctx->buf, 16);
- memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
-}
-
-#ifndef ASM_MD5
-
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-void MD5Transform(uint32_t buf[4], uint32_t const in[16])
-{
- register uint32_t a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-#endif
diff --git a/main/netsock.c b/main/netsock.c
deleted file mode 100644
index 9fa842ec3..000000000
--- a/main/netsock.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Kevin P. Fleming <kpfleming@digium.com>
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Network socket handling
- *
- * \author Kevin P. Fleming <kpfleming@digium.com>
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <net/if.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <sys/ioctl.h>
-
-#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
-#include <fcntl.h>
-#include <net/route.h>
-#endif
-
-#if defined (SOLARIS)
-#include <sys/sockio.h>
-#endif
-
-#include "asterisk/netsock.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/options.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-#include "asterisk/srv.h"
-
-struct ast_netsock {
- ASTOBJ_COMPONENTS(struct ast_netsock);
- struct sockaddr_in bindaddr;
- int sockfd;
- int *ioref;
- struct io_context *ioc;
- void *data;
-};
-
-struct ast_netsock_list {
- ASTOBJ_CONTAINER_COMPONENTS(struct ast_netsock);
- struct io_context *ioc;
-};
-
-static void ast_netsock_destroy(struct ast_netsock *netsock)
-{
- ast_io_remove(netsock->ioc, netsock->ioref);
- close(netsock->sockfd);
- free(netsock);
-}
-
-struct ast_netsock_list *ast_netsock_list_alloc(void)
-{
- return ast_calloc(1, sizeof(struct ast_netsock_list));
-}
-
-int ast_netsock_init(struct ast_netsock_list *list)
-{
- memset(list, 0, sizeof(*list));
- ASTOBJ_CONTAINER_INIT(list);
-
- return 0;
-}
-
-int ast_netsock_release(struct ast_netsock_list *list)
-{
- ASTOBJ_CONTAINER_DESTROYALL(list, ast_netsock_destroy);
- ASTOBJ_CONTAINER_DESTROY(list);
-
- return 0;
-}
-
-struct ast_netsock *ast_netsock_find(struct ast_netsock_list *list,
- struct sockaddr_in *sa)
-{
- struct ast_netsock *sock = NULL;
-
- ASTOBJ_CONTAINER_TRAVERSE(list, !sock, {
- ASTOBJ_RDLOCK(iterator);
- if (!inaddrcmp(&iterator->bindaddr, sa))
- sock = iterator;
- ASTOBJ_UNLOCK(iterator);
- });
-
- return sock;
-}
-
-struct ast_netsock *ast_netsock_bindaddr(struct ast_netsock_list *list, struct io_context *ioc, struct sockaddr_in *bindaddr, int tos, ast_io_cb callback, void *data)
-{
- int netsocket = -1;
- int *ioref;
-
- struct ast_netsock *ns;
- const int reuseFlag = 1;
-
- /* Make a UDP socket */
- netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
-
- if (netsocket < 0) {
- ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
- return NULL;
- }
- if (setsockopt(netsocket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseFlag, sizeof reuseFlag) < 0) {
- ast_log(LOG_WARNING, "Error setting SO_REUSEADDR on sockfd '%d'\n", netsocket);
- }
- if (bind(netsocket,(struct sockaddr *)bindaddr, sizeof(struct sockaddr_in))) {
- ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(bindaddr->sin_addr), ntohs(bindaddr->sin_port), strerror(errno));
- close(netsocket);
- return NULL;
- }
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
-
- if (setsockopt(netsocket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))
- ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
-
- ast_enable_packet_fragmentation(netsocket);
-
- if (!(ns = ast_calloc(1, sizeof(struct ast_netsock)))) {
- close(netsocket);
- return NULL;
- }
-
- /* Establish I/O callback for socket read */
- if (!(ioref = ast_io_add(ioc, netsocket, callback, AST_IO_IN, ns))) {
- close(netsocket);
- free(ns);
- return NULL;
- }
- ASTOBJ_INIT(ns);
- ns->ioref = ioref;
- ns->ioc = ioc;
- ns->sockfd = netsocket;
- ns->data = data;
- memcpy(&ns->bindaddr, bindaddr, sizeof(ns->bindaddr));
- ASTOBJ_CONTAINER_LINK(list, ns);
-
- return ns;
-}
-
-struct ast_netsock *ast_netsock_bind(struct ast_netsock_list *list, struct io_context *ioc, const char *bindinfo, int defaultport, int tos, ast_io_cb callback, void *data)
-{
- struct sockaddr_in sin;
- char *tmp;
- char *host;
- char *port;
- int portno;
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(defaultport);
- tmp = ast_strdupa(bindinfo);
-
- host = strsep(&tmp, ":");
- port = tmp;
-
- if (port && ((portno = atoi(port)) > 0))
- sin.sin_port = htons(portno);
-
- inet_aton(host, &sin.sin_addr);
-
- return ast_netsock_bindaddr(list, ioc, &sin, tos, callback, data);
-}
-
-int ast_netsock_sockfd(const struct ast_netsock *ns)
-{
- return ns ? ns-> sockfd : -1;
-}
-
-const struct sockaddr_in *ast_netsock_boundaddr(const struct ast_netsock *ns)
-{
- return &(ns->bindaddr);
-}
-
-void *ast_netsock_data(const struct ast_netsock *ns)
-{
- return ns->data;
-}
-
-void ast_netsock_unref(struct ast_netsock *ns)
-{
- ASTOBJ_UNREF(ns, ast_netsock_destroy);
-}
diff --git a/main/pbx.c b/main/pbx.c
deleted file mode 100644
index a1a815046..000000000
--- a/main/pbx.c
+++ /dev/null
@@ -1,6401 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Core PBX routines.
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/time.h>
-#include <limits.h>
-
-#include "asterisk/lock.h"
-#include "asterisk/cli.h"
-#include "asterisk/pbx.h"
-#include "asterisk/channel.h"
-#include "asterisk/options.h"
-#include "asterisk/logger.h"
-#include "asterisk/file.h"
-#include "asterisk/callerid.h"
-#include "asterisk/cdr.h"
-#include "asterisk/config.h"
-#include "asterisk/term.h"
-#include "asterisk/manager.h"
-#include "asterisk/ast_expr.h"
-#include "asterisk/linkedlists.h"
-#define SAY_STUBS /* generate declarations and stubs for say methods */
-#include "asterisk/say.h"
-#include "asterisk/utils.h"
-#include "asterisk/causes.h"
-#include "asterisk/musiconhold.h"
-#include "asterisk/app.h"
-#include "asterisk/devicestate.h"
-#include "asterisk/stringfields.h"
-#include "asterisk/threadstorage.h"
-
-/*!
- * \note I M P O R T A N T :
- *
- * The speed of extension handling will likely be among the most important
- * aspects of this PBX. The switching scheme as it exists right now isn't
- * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
- * of priorities, but a constant search time here would be great ;-)
- *
- */
-
-#ifdef LOW_MEMORY
-#define EXT_DATA_SIZE 256
-#else
-#define EXT_DATA_SIZE 8192
-#endif
-
-#define SWITCH_DATA_LENGTH 256
-
-#define VAR_BUF_SIZE 4096
-
-#define VAR_NORMAL 1
-#define VAR_SOFTTRAN 2
-#define VAR_HARDTRAN 3
-
-#define BACKGROUND_SKIP (1 << 0)
-#define BACKGROUND_NOANSWER (1 << 1)
-#define BACKGROUND_MATCHEXTEN (1 << 2)
-#define BACKGROUND_PLAYBACK (1 << 3)
-
-AST_APP_OPTIONS(background_opts, {
- AST_APP_OPTION('s', BACKGROUND_SKIP),
- AST_APP_OPTION('n', BACKGROUND_NOANSWER),
- AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
- AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
-});
-
-#define WAITEXTEN_MOH (1 << 0)
-
-AST_APP_OPTIONS(waitexten_opts, {
- AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),
-});
-
-struct ast_context;
-
-AST_THREADSTORAGE(switch_data, switch_data_init);
-
-/*!
- \brief ast_exten: An extension
- The dialplan is saved as a linked list with each context
- having it's own linked list of extensions - one item per
- priority.
-*/
-struct ast_exten {
- char *exten; /*!< Extension name */
- int matchcid; /*!< Match caller id ? */
- const char *cidmatch; /*!< Caller id to match for this extension */
- int priority; /*!< Priority */
- const char *label; /*!< Label */
- struct ast_context *parent; /*!< The context this extension belongs to */
- const char *app; /*!< Application to execute */
- void *data; /*!< Data to use (arguments) */
- void (*datad)(void *); /*!< Data destructor */
- struct ast_exten *peer; /*!< Next higher priority with our extension */
- const char *registrar; /*!< Registrar */
- struct ast_exten *next; /*!< Extension with a greater ID */
- char stuff[0];
-};
-
-/*! \brief ast_include: include= support in extensions.conf */
-struct ast_include {
- const char *name;
- const char *rname; /*!< Context to include */
- const char *registrar; /*!< Registrar */
- int hastime; /*!< If time construct exists */
- struct ast_timing timing; /*!< time construct */
- struct ast_include *next; /*!< Link them together */
- char stuff[0];
-};
-
-/*! \brief ast_sw: Switch statement in extensions.conf */
-struct ast_sw {
- char *name;
- const char *registrar; /*!< Registrar */
- char *data; /*!< Data load */
- int eval;
- AST_LIST_ENTRY(ast_sw) list;
- char stuff[0];
-};
-
-/*! \brief ast_ignorepat: Ignore patterns in dial plan */
-struct ast_ignorepat {
- const char *registrar;
- struct ast_ignorepat *next;
- const char pattern[0];
-};
-
-/*! \brief ast_context: An extension context */
-struct ast_context {
- ast_mutex_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
- struct ast_exten *root; /*!< The root of the list of extensions */
- struct ast_context *next; /*!< Link them together */
- struct ast_include *includes; /*!< Include other contexts */
- struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
- const char *registrar; /*!< Registrar */
- AST_LIST_HEAD_NOLOCK(, ast_sw) alts; /*!< Alternative switches */
- ast_mutex_t macrolock; /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
- char name[0]; /*!< Name of the context */
-};
-
-
-/*! \brief ast_app: A registered application */
-struct ast_app {
- int (*execute)(struct ast_channel *chan, void *data);
- const char *synopsis; /*!< Synopsis text for 'show applications' */
- const char *description; /*!< Description (help text) for 'show application &lt;name&gt;' */
- AST_LIST_ENTRY(ast_app) list; /*!< Next app in list */
- struct module *module; /*!< Module this app belongs to */
- char name[0]; /*!< Name of the application */
-};
-
-/*! \brief ast_state_cb: An extension state notify register item */
-struct ast_state_cb {
- int id;
- void *data;
- ast_state_cb_type callback;
- struct ast_state_cb *next;
-};
-
-/*! \brief Structure for dial plan hints
-
- \note Hints are pointers from an extension in the dialplan to one or
- more devices (tech/name) */
-struct ast_hint {
- struct ast_exten *exten; /*!< Extension */
- int laststate; /*!< Last known state */
- struct ast_state_cb *callbacks; /*!< Callback list for this extension */
- AST_LIST_ENTRY(ast_hint) list; /*!< Pointer to next hint in list */
-};
-
-static const struct cfextension_states {
- int extension_state;
- const char * const text;
-} extension_states[] = {
- { AST_EXTENSION_NOT_INUSE, "Idle" },
- { AST_EXTENSION_INUSE, "InUse" },
- { AST_EXTENSION_BUSY, "Busy" },
- { AST_EXTENSION_UNAVAILABLE, "Unavailable" },
- { AST_EXTENSION_RINGING, "Ringing" },
- { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
- { AST_EXTENSION_ONHOLD, "Hold" },
- { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD, "InUse&Hold" }
-};
-
-static int pbx_builtin_answer(struct ast_channel *, void *);
-static int pbx_builtin_goto(struct ast_channel *, void *);
-static int pbx_builtin_hangup(struct ast_channel *, void *);
-static int pbx_builtin_background(struct ast_channel *, void *);
-static int pbx_builtin_wait(struct ast_channel *, void *);
-static int pbx_builtin_waitexten(struct ast_channel *, void *);
-static int pbx_builtin_resetcdr(struct ast_channel *, void *);
-static int pbx_builtin_setamaflags(struct ast_channel *, void *);
-static int pbx_builtin_ringing(struct ast_channel *, void *);
-static int pbx_builtin_progress(struct ast_channel *, void *);
-static int pbx_builtin_congestion(struct ast_channel *, void *);
-static int pbx_builtin_busy(struct ast_channel *, void *);
-static int pbx_builtin_setglobalvar(struct ast_channel *, void *);
-static int pbx_builtin_noop(struct ast_channel *, void *);
-static int pbx_builtin_gotoif(struct ast_channel *, void *);
-static int pbx_builtin_gotoiftime(struct ast_channel *, void *);
-static int pbx_builtin_execiftime(struct ast_channel *, void *);
-static int pbx_builtin_saynumber(struct ast_channel *, void *);
-static int pbx_builtin_saydigits(struct ast_channel *, void *);
-static int pbx_builtin_saycharacters(struct ast_channel *, void *);
-static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
-int pbx_builtin_setvar(struct ast_channel *, void *);
-static int pbx_builtin_importvar(struct ast_channel *, void *);
-
-AST_MUTEX_DEFINE_STATIC(globalslock);
-static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
-
-static int autofallthrough = 1;
-
-AST_MUTEX_DEFINE_STATIC(maxcalllock);
-static int countcalls;
-
-static AST_LIST_HEAD_STATIC(acf_root, ast_custom_function);
-
-/*! \brief Declaration of builtin applications */
-static struct pbx_builtin {
- char name[AST_MAX_APP];
- int (*execute)(struct ast_channel *chan, void *data);
- char *synopsis;
- char *description;
-} builtins[] =
-{
- /* These applications are built into the PBX core and do not
- need separate modules */
-
- { "Answer", pbx_builtin_answer,
- "Answer a channel if ringing",
- " Answer([delay]): If the call has not been answered, this application will\n"
- "answer it. Otherwise, it has no effect on the call. If a delay is specified,\n"
- "Asterisk will wait this number of milliseconds before returning to\n"
- "the dialplan after answering the call.\n"
- },
-
- { "BackGround", pbx_builtin_background,
- "Play an audio file while waiting for digits of an extension to go to.",
- " Background(filename1[&filename2...][|options[|langoverride][|context]]):\n"
- "This application will play the given list of files (do not put extension)\n"
- "while waiting for an extension to be dialed by the calling channel. To\n"
- "continue waiting for digits after this application has finished playing\n"
- "files, the WaitExten application should be used. The 'langoverride' option\n"
- "explicitly specifies which language to attempt to use for the requested sound\n"
- "files. If a 'context' is specified, this is the dialplan context that this\n"
- "application will use when exiting to a dialed extension."
- " If one of the requested sound files does not exist, call processing will be\n"
- "terminated.\n"
- " Options:\n"
- " s - Causes the playback of the message to be skipped\n"
- " if the channel is not in the 'up' state (i.e. it\n"
- " hasn't been answered yet). If this happens, the\n"
- " application will return immediately.\n"
- " n - Don't answer the channel before playing the files.\n"
- " m - Only break if a digit hit matches a one digit\n"
- " extension in the destination context.\n"
- "See Also: Playback (application) -- Play sound file(s) to the channel,\n"
- " that cannot be interrupted\n"
- },
-
- { "Busy", pbx_builtin_busy,
- "Indicate the Busy condition",
- " Busy([timeout]): This application will indicate the busy condition to\n"
- "the calling channel. If the optional timeout is specified, the calling channel\n"
- "will be hung up after the specified number of seconds. Otherwise, this\n"
- "application will wait until the calling channel hangs up.\n"
- },
-
- { "Congestion", pbx_builtin_congestion,
- "Indicate the Congestion condition",
- " Congestion([timeout]): This application will indicate the congestion\n"
- "condition to the calling channel. If the optional timeout is specified, the\n"
- "calling channel will be hung up after the specified number of seconds.\n"
- "Otherwise, this application will wait until the calling channel hangs up.\n"
- },
-
- { "Goto", pbx_builtin_goto,
- "Jump to a particular priority, extension, or context",
- " Goto([[context|]extension|]priority): This application will set the current\n"
- "context, extension, and priority in the channel structure. After it completes, the\n"
- "pbx engine will continue dialplan execution at the specified location.\n"
- "If no specific extension, or extension and context, are specified, then this\n"
- "application will just set the specified priority of the current extension.\n"
- " At least a priority is required as an argument, or the goto will return a -1,\n"
- "and the channel and call will be terminated.\n"
- " If the location that is put into the channel information is bogus, and asterisk cannot\n"
- "find that location in the dialplan,\n"
- "then the execution engine will try to find and execute the code in the 'i' (invalid)\n"
- "extension in the current context. If that does not exist, it will try to execute the\n"
- "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
- "channel is hung up, and the execution of instructions on the channel is terminated.\n"
- "What this means is that, for example, you specify a context that does not exist, then\n"
- "it will not be possible to find the 'h' or 'i' extensions, and the call will terminate!\n"
- },
-
- { "GotoIf", pbx_builtin_gotoif,
- "Conditional goto",
- " GotoIf(condition?[labeliftrue]:[labeliffalse]): This application will set the current\n"
- "context, extension, and priority in the channel structure based on the evaluation of\n"
- "the given condition. After this application completes, the\n"
- "pbx engine will continue dialplan execution at the specified location in the dialplan.\n"
- "The channel will continue at\n"
- "'labeliftrue' if the condition is true, or 'labeliffalse' if the condition is\n"
- "false. The labels are specified with the same syntax as used within the Goto\n"
- "application. If the label chosen by the condition is omitted, no jump is\n"
- "performed, and the execution passes to the next instruction.\n"
- "If the target location is bogus, and does not exist, the execution engine will try \n"
- "to find and execute the code in the 'i' (invalid)\n"
- "extension in the current context. If that does not exist, it will try to execute the\n"
- "'h' extension. If either or neither the 'h' or 'i' extensions have been defined, the\n"
- "channel is hung up, and the execution of instructions on the channel is terminated.\n"
- "Remember that this command can set the current context, and if the context specified\n"
- "does not exist, then it will not be able to find any 'h' or 'i' extensions there, and\n"
- "the channel and call will both be terminated!\n"
- },
-
- { "GotoIfTime", pbx_builtin_gotoiftime,
- "Conditional Goto based on the current time",
- " GotoIfTime(<times>|<weekdays>|<mdays>|<months>?[[context|]exten|]priority):\n"
- "This application will set the context, extension, and priority in the channel structure\n"
- "if the current time matches the given time specification. Otherwise, nothing is done.\n"
- "Further information on the time specification can be found in examples\n"
- "illustrating how to do time-based context includes in the dialplan.\n"
- "If the target jump location is bogus, the same actions would be taken as for Goto.\n"
- },
-
- { "ExecIfTime", pbx_builtin_execiftime,
- "Conditional application execution based on the current time",
- " ExecIfTime(<times>|<weekdays>|<mdays>|<months>?appname[|appargs]):\n"
- "This application will execute the specified dialplan application, with optional\n"
- "arguments, if the current time matches the given time specification.\n"
- },
-
- { "Hangup", pbx_builtin_hangup,
- "Hang up the calling channel",
- " Hangup([causecode]): This application will hang up the calling channel.\n"
- "If a causecode is given the channel's hangup cause will be set to the given\n"
- "value.\n"
- },
-
- { "NoOp", pbx_builtin_noop,
- "Do Nothing",
- " NoOp(): This applicatiion does nothing. However, it is useful for debugging\n"
- "purposes. Any text that is provided as arguments to this application can be\n"
- "viewed at the Asterisk CLI. This method can be used to see the evaluations of\n"
- "variables or functions without having any effect."
- },
-
- { "Progress", pbx_builtin_progress,
- "Indicate progress",
- " Progress(): This application will request that in-band progress information\n"
- "be provided to the calling channel.\n"
- },
-
- { "ResetCDR", pbx_builtin_resetcdr,
- "Resets the Call Data Record",
- " ResetCDR([options]): This application causes the Call Data Record to be\n"
- "reset.\n"
- " Options:\n"
- " w -- Store the current CDR record before resetting it.\n"
- " a -- Store any stacked records.\n"
- " v -- Save CDR variables.\n"
- },
-
- { "Ringing", pbx_builtin_ringing,
- "Indicate ringing tone",
- " Ringing(): This application will request that the channel indicate a ringing\n"
- "tone to the user.\n"
- },
-
- { "SayNumber", pbx_builtin_saynumber,
- "Say Number",
- " SayNumber(digits[,gender]): This application will play the sounds that\n"
- "correspond to the given number. Optionally, a gender may be specified.\n"
- "This will use the language that is currently set for the channel. See the\n"
- "LANGUAGE function for more information on setting the language for the channel.\n"
- },
-
- { "SayDigits", pbx_builtin_saydigits,
- "Say Digits",
- " SayDigits(digits): This application will play the sounds that correspond\n"
- "to the digits of the given number. This will use the language that is currently\n"
- "set for the channel. See the LANGUAGE function for more information on setting\n"
- "the language for the channel.\n"
- },
-
- { "SayAlpha", pbx_builtin_saycharacters,
- "Say Alpha",
- " SayAlpha(string): This application will play the sounds that correspond to\n"
- "the letters of the given string.\n"
- },
-
- { "SayPhonetic", pbx_builtin_sayphonetic,
- "Say Phonetic",
- " SayPhonetic(string): This application will play the sounds from the phonetic\n"
- "alphabet that correspond to the letters in the given string.\n"
- },
-
- { "SetAMAFlags", pbx_builtin_setamaflags,
- "Set the AMA Flags",
- " SetAMAFlags([flag]): This application will set the channel's AMA Flags for\n"
- " billing purposes.\n"
- },
-
- { "SetGlobalVar", pbx_builtin_setglobalvar,
- "Set a global variable to a given value",
- " SetGlobalVar(variable=value): This application sets a given global variable to\n"
- "the specified value.\n"
- "\n\nThis application is deprecated in favor of Set(GLOBAL(var)=value)\n"
- },
-
- { "Set", pbx_builtin_setvar,
- "Set channel variable(s) or function value(s)",
- " Set(name1=value1|name2=value2|..[|options])\n"
- "This function can be used to set the value of channel variables or dialplan\n"
- "functions. It will accept up to 24 name/value pairs. When setting variables,\n"
- "if the variable name is prefixed with _, the variable will be inherited into\n"
- "channels created from the current channel. If the variable name is prefixed\n"
- "with __, the variable will be inherited into channels created from the current\n"
- "channel and all children channels.\n"
- " Options:\n"
- " g - Set variable globally instead of on the channel\n"
- " (applies only to variables, not functions)\n"
- "\n\nThe use of Set to set multiple variables at once and the g flag have both\n"
- "been deprecated. Please use multiple Set calls and the GLOBAL() dialplan\n"
- "function instead.\n"
- },
-
- { "ImportVar", pbx_builtin_importvar,
- "Import a variable from a channel into a new variable",
- " ImportVar(newvar=channelname|variable): This application imports a variable\n"
- "from the specified channel (as opposed to the current one) and stores it as\n"
- "a variable in the current channel (the channel that is calling this\n"
- "application). Variables created by this application have the same inheritance\n"
- "properties as those created with the Set application. See the documentation for\n"
- "Set for more information.\n"
- },
-
- { "Wait", pbx_builtin_wait,
- "Waits for some time",
- " Wait(seconds): This application waits for a specified number of seconds.\n"
- "Then, dialplan execution will continue at the next priority.\n"
- " Note that the seconds can be passed with fractions of a second. For example,\n"
- "'1.5' will ask the application to wait for 1.5 seconds.\n"
- },
-
- { "WaitExten", pbx_builtin_waitexten,
- "Waits for an extension to be entered",
- " WaitExten([seconds][|options]): This application waits for the user to enter\n"
- "a new extension for a specified number of seconds.\n"
- " Note that the seconds can be passed with fractions of a second. For example,\n"
- "'1.5' will ask the application to wait for 1.5 seconds.\n"
- " Options:\n"
- " m[(x)] - Provide music on hold to the caller while waiting for an extension.\n"
- " Optionally, specify the class for music on hold within parenthesis.\n"
- "See Also: Playback(application), Background(application).\n"
- },
-
-};
-
-static struct ast_context *contexts;
-AST_RWLOCK_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
-
-static AST_LIST_HEAD_STATIC(apps, ast_app);
-
-static AST_LIST_HEAD_STATIC(switches, ast_switch);
-
-static int stateid = 1;
-/* WARNING:
- When holding this list's lock, do _not_ do anything that will cause conlock
- to be taken, unless you _already_ hold it. The ast_merge_contexts_and_delete
- function will take the locks in conlock/hints order, so any other
- paths that require both locks must also take them in that order.
-*/
-static AST_LIST_HEAD_STATIC(hints, ast_hint);
-struct ast_state_cb *statecbs;
-
-/*
- \note This function is special. It saves the stack so that no matter
- how many times it is called, it returns to the same place */
-int pbx_exec(struct ast_channel *c, /*!< Channel */
- struct ast_app *app, /*!< Application */
- void *data) /*!< Data for execution */
-{
- int res;
-
- const char *saved_c_appl;
- const char *saved_c_data;
-
- if (c->cdr && !ast_check_hangup(c))
- ast_cdr_setapp(c->cdr, app->name, data);
-
- /* save channel values */
- saved_c_appl= c->appl;
- saved_c_data= c->data;
-
- c->appl = app->name;
- c->data = data;
- /* XXX remember what to to when we have linked apps to modules */
- if (app->module) {
- /* XXX LOCAL_USER_ADD(app->module) */
- }
- res = app->execute(c, S_OR(data, ""));
- if (app->module) {
- /* XXX LOCAL_USER_REMOVE(app->module) */
- }
- /* restore channel values */
- c->appl = saved_c_appl;
- c->data = saved_c_data;
- return res;
-}
-
-
-/*! Go no deeper than this through includes (not counting loops) */
-#define AST_PBX_MAX_STACK 128
-
-/*! \brief Find application handle in linked list
- */
-struct ast_app *pbx_findapp(const char *app)
-{
- struct ast_app *tmp;
-
- AST_LIST_LOCK(&apps);
- AST_LIST_TRAVERSE(&apps, tmp, list) {
- if (!strcasecmp(tmp->name, app))
- break;
- }
- AST_LIST_UNLOCK(&apps);
-
- return tmp;
-}
-
-static struct ast_switch *pbx_findswitch(const char *sw)
-{
- struct ast_switch *asw;
-
- AST_LIST_LOCK(&switches);
- AST_LIST_TRAVERSE(&switches, asw, list) {
- if (!strcasecmp(asw->name, sw))
- break;
- }
- AST_LIST_UNLOCK(&switches);
-
- return asw;
-}
-
-static inline int include_valid(struct ast_include *i)
-{
- if (!i->hastime)
- return 1;
-
- return ast_check_timing(&(i->timing));
-}
-
-static void pbx_destroy(struct ast_pbx *p)
-{
- free(p);
-}
-
-/*
- * Special characters used in patterns:
- * '_' underscore is the leading character of a pattern.
- * In other position it is treated as a regular char.
- * ' ' '-' space and '-' are separator and ignored. Why? so
- * patterns like NXX-XXX-XXXX or NXX XXX XXXX will work.
- * . one or more of any character. Only allowed at the end of
- * a pattern.
- * ! zero or more of anything. Also impacts the result of CANMATCH
- * and MATCHMORE. Only allowed at the end of a pattern.
- * In the core routine, ! causes a match with a return code of 2.
- * In turn, depending on the search mode: (XXX check if it is implemented)
- * - E_MATCH retuns 1 (does match)
- * - E_MATCHMORE returns 0 (no match)
- * - E_CANMATCH returns 1 (does match)
- *
- * / should not appear as it is considered the separator of the CID info.
- * XXX at the moment we may stop on this char.
- *
- * X Z N match ranges 0-9, 1-9, 2-9 respectively.
- * [ denotes the start of a set of character. Everything inside
- * is considered literally. We can have ranges a-d and individual
- * characters. A '[' and '-' can be considered literally if they
- * are just before ']'.
- * XXX currently there is no way to specify ']' in a range, nor \ is
- * considered specially.
- *
- * When we compare a pattern with a specific extension, all characters in the extension
- * itself are considered literally with the only exception of '-' which is considered
- * as a separator and thus ignored.
- * XXX do we want to consider space as a separator as well ?
- * XXX do we want to consider the separators in non-patterns as well ?
- */
-
-/*!
- * \brief helper functions to sort extensions and patterns in the desired way,
- * so that more specific patterns appear first.
- *
- * ext_cmp1 compares individual characters (or sets of), returning
- * an int where bits 0-7 are the ASCII code of the first char in the set,
- * while bit 8-15 are the cardinality of the set minus 1.
- * This way more specific patterns (smaller cardinality) appear first.
- * Wildcards have a special value, so that we can directly compare them to
- * sets by subtracting the two values. In particular:
- * 0x000xx one character, xx
- * 0x0yyxx yy character set starting with xx
- * 0x10000 '.' (one or more of anything)
- * 0x20000 '!' (zero or more of anything)
- * 0x30000 NUL (end of string)
- * 0x40000 error in set.
- * The pointer to the string is advanced according to needs.
- * NOTES:
- * 1. the empty set is equivalent to NUL.
- * 2. given that a full set has always 0 as the first element,
- * we could encode the special cases as 0xffXX where XX
- * is 1, 2, 3, 4 as used above.
- */
-static int ext_cmp1(const char **p)
-{
- uint32_t chars[8];
- int c, cmin = 0xff, count = 0;
- const char *end;
-
- /* load, sign extend and advance pointer until we find
- * a valid character.
- */
- while ( (c = *(*p)++) && (c == ' ' || c == '-') )
- ; /* ignore some characters */
-
- /* always return unless we have a set of chars */
- switch (c) {
- default: /* ordinary character */
- return 0x0000 | (c & 0xff);
-
- case 'N': /* 2..9 */
- return 0x0800 | '2' ;
-
- case 'X': /* 0..9 */
- return 0x0A00 | '0';
-
- case 'Z': /* 1..9 */
- return 0x0900 | '1';
-
- case '.': /* wildcard */
- return 0x10000;
-
- case '!': /* earlymatch */
- return 0x20000; /* less specific than NULL */
-
- case '\0': /* empty string */
- *p = NULL;
- return 0x30000;
-
- case '[': /* pattern */
- break;
- }
- /* locate end of set */
- end = strchr(*p, ']');
-
- if (end == NULL) {
- ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
- return 0x40000; /* XXX make this entry go last... */
- }
-
- bzero(chars, sizeof(chars)); /* clear all chars in the set */
- for (; *p < end ; (*p)++) {
- unsigned char c1, c2; /* first-last char in range */
- c1 = (unsigned char)((*p)[0]);
- if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
- c2 = (unsigned char)((*p)[2]);
- *p += 2; /* skip a total of 3 chars */
- } else /* individual character */
- c2 = c1;
- if (c1 < cmin)
- cmin = c1;
- for (; c1 <= c2; c1++) {
- uint32_t mask = 1 << (c1 % 32);
- if ( (chars[ c1 / 32 ] & mask) == 0)
- count += 0x100;
- chars[ c1 / 32 ] |= mask;
- }
- }
- (*p)++;
- return count == 0 ? 0x30000 : (count | cmin);
-}
-
-/*!
- * \brief the full routine to compare extensions in rules.
- */
-static int ext_cmp(const char *a, const char *b)
-{
- /* make sure non-patterns come first.
- * If a is not a pattern, it either comes first or
- * we use strcmp to compare the strings.
- */
- int ret = 0;
-
- if (a[0] != '_')
- return (b[0] == '_') ? -1 : strcmp(a, b);
-
- /* Now we know a is a pattern; if b is not, a comes first */
- if (b[0] != '_')
- return 1;
-#if 0 /* old mode for ext matching */
- return strcmp(a, b);
-#endif
- /* ok we need full pattern sorting routine */
- while (!ret && a && b)
- ret = ext_cmp1(&a) - ext_cmp1(&b);
- if (ret == 0)
- return 0;
- else
- return (ret > 0) ? 1 : -1;
-}
-
-/*!
- * When looking up extensions, we can have different requests
- * identified by the 'action' argument, as follows.
- * Note that the coding is such that the low 4 bits are the
- * third argument to extension_match_core.
- */
-enum ext_match_t {
- E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */
- E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */
- E_MATCH = 0x02, /* extension is an exact match */
- E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
- E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */
- E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */
-};
-
-/*
- * Internal function for ast_extension_{match|close}
- * return 0 on no-match, 1 on match, 2 on early match.
- * mode is as follows:
- * E_MATCH success only on exact match
- * E_MATCHMORE success only on partial match (i.e. leftover digits in pattern)
- * E_CANMATCH either of the above.
- */
-
-static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
-{
- mode &= E_MATCH_MASK; /* only consider the relevant bits */
-
- if ( (mode == E_MATCH) && (pattern[0] == '_') && (strcasecmp(pattern,data)==0) ) /* note: if this test is left out, then _x. will not match _x. !!! */
- return 1;
-
- if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
- int ld = strlen(data), lp = strlen(pattern);
-
- if (lp < ld) /* pattern too short, cannot match */
- return 0;
- /* depending on the mode, accept full or partial match or both */
- if (mode == E_MATCH)
- return !strcmp(pattern, data); /* 1 on match, 0 on fail */
- if (ld == 0 || !strncasecmp(pattern, data, ld)) /* partial or full match */
- return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
- else
- return 0;
- }
- pattern++; /* skip leading _ */
- /*
- * XXX below we stop at '/' which is a separator for the CID info. However we should
- * not store '/' in the pattern at all. When we insure it, we can remove the checks.
- */
- while (*data && *pattern && *pattern != '/') {
- const char *end;
-
- if (*data == '-') { /* skip '-' in data (just a separator) */
- data++;
- continue;
- }
- switch (toupper(*pattern)) {
- case '[': /* a range */
- end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
- if (end == NULL) {
- ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
- return 0; /* unconditional failure */
- }
- for (pattern++; pattern != end; pattern++) {
- if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
- if (*data >= pattern[0] && *data <= pattern[2])
- break; /* match found */
- else {
- pattern += 2; /* skip a total of 3 chars */
- continue;
- }
- } else if (*data == pattern[0])
- break; /* match found */
- }
- if (pattern == end)
- return 0;
- pattern = end; /* skip and continue */
- break;
- case 'N':
- if (*data < '2' || *data > '9')
- return 0;
- break;
- case 'X':
- if (*data < '0' || *data > '9')
- return 0;
- break;
- case 'Z':
- if (*data < '1' || *data > '9')
- return 0;
- break;
- case '.': /* Must match, even with more digits */
- return 1;
- case '!': /* Early match */
- return 2;
- case ' ':
- case '-': /* Ignore these in patterns */
- data--; /* compensate the final data++ */
- break;
- default:
- if (*data != *pattern)
- return 0;
- }
- data++;
- pattern++;
- }
- if (*data) /* data longer than pattern, no match */
- return 0;
- /*
- * match so far, but ran off the end of the data.
- * Depending on what is next, determine match or not.
- */
- if (*pattern == '\0' || *pattern == '/') /* exact match */
- return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */
- else if (*pattern == '!') /* early match */
- return 2;
- else /* partial match */
- return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */
-}
-
-/*
- * Wrapper around _extension_match_core() to do performance measurement
- * using the profiling code.
- */
-static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
-{
- int i;
- static int prof_id = -2; /* marker for 'unallocated' id */
- if (prof_id == -2)
- prof_id = ast_add_profile("ext_match", 0);
- ast_mark(prof_id, 1);
- i = _extension_match_core(pattern, data, mode);
- ast_mark(prof_id, 0);
- return i;
-}
-
-int ast_extension_match(const char *pattern, const char *data)
-{
- return extension_match_core(pattern, data, E_MATCH);
-}
-
-int ast_extension_close(const char *pattern, const char *data, int needmore)
-{
- if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
- ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
- return extension_match_core(pattern, data, needmore);
-}
-
-struct ast_context *ast_context_find(const char *name)
-{
- struct ast_context *tmp = NULL;
-
- ast_rdlock_contexts();
-
- while ( (tmp = ast_walk_contexts(tmp)) ) {
- if (!name || !strcasecmp(name, tmp->name))
- break;
- }
-
- ast_unlock_contexts();
-
- return tmp;
-}
-
-#define STATUS_NO_CONTEXT 1
-#define STATUS_NO_EXTENSION 2
-#define STATUS_NO_PRIORITY 3
-#define STATUS_NO_LABEL 4
-#define STATUS_SUCCESS 5
-
-static int matchcid(const char *cidpattern, const char *callerid)
-{
- /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
- failing to get a number should count as a match, otherwise not */
-
- if (ast_strlen_zero(callerid))
- return ast_strlen_zero(cidpattern) ? 1 : 0;
-
- return ast_extension_match(cidpattern, callerid);
-}
-
-/* request and result for pbx_find_extension */
-struct pbx_find_info {
-#if 0
- const char *context;
- const char *exten;
- int priority;
-#endif
-
- char *incstack[AST_PBX_MAX_STACK]; /* filled during the search */
- int stacklen; /* modified during the search */
- int status; /* set on return */
- struct ast_switch *swo; /* set on return */
- const char *data; /* set on return */
- const char *foundcontext; /* set on return */
-};
-
-static struct ast_exten *pbx_find_extension(struct ast_channel *chan,
- struct ast_context *bypass, struct pbx_find_info *q,
- const char *context, const char *exten, int priority,
- const char *label, const char *callerid, enum ext_match_t action)
-{
- int x, res;
- struct ast_context *tmp;
- struct ast_exten *e, *eroot;
- struct ast_include *i;
- struct ast_sw *sw;
- char *tmpdata = NULL;
-
- /* Initialize status if appropriate */
- if (q->stacklen == 0) {
- q->status = STATUS_NO_CONTEXT;
- q->swo = NULL;
- q->data = NULL;
- q->foundcontext = NULL;
- }
- /* Check for stack overflow */
- if (q->stacklen >= AST_PBX_MAX_STACK) {
- ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
- return NULL;
- }
- /* Check first to see if we've already been checked */
- for (x = 0; x < q->stacklen; x++) {
- if (!strcasecmp(q->incstack[x], context))
- return NULL;
- }
- if (bypass) /* bypass means we only look there */
- tmp = bypass;
- else { /* look in contexts */
- tmp = NULL;
- while ((tmp = ast_walk_contexts(tmp)) ) {
- if (!strcmp(tmp->name, context))
- break;
- }
- if (!tmp)
- return NULL;
- }
- if (q->status < STATUS_NO_EXTENSION)
- q->status = STATUS_NO_EXTENSION;
-
- /* scan the list trying to match extension and CID */
- eroot = NULL;
- while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
- int match = extension_match_core(eroot->exten, exten, action);
- /* 0 on fail, 1 on match, 2 on earlymatch */
-
- if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
- continue; /* keep trying */
- if (match == 2 && action == E_MATCHMORE) {
- /* We match an extension ending in '!'.
- * The decision in this case is final and is NULL (no match).
- */
- return NULL;
- }
- /* found entry, now look for the right priority */
- if (q->status < STATUS_NO_PRIORITY)
- q->status = STATUS_NO_PRIORITY;
- e = NULL;
- while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
- /* Match label or priority */
- if (action == E_FINDLABEL) {
- if (q->status < STATUS_NO_LABEL)
- q->status = STATUS_NO_LABEL;
- if (label && e->label && !strcmp(label, e->label))
- break; /* found it */
- } else if (e->priority == priority) {
- break; /* found it */
- } /* else keep searching */
- }
- if (e) { /* found a valid match */
- q->status = STATUS_SUCCESS;
- q->foundcontext = context;
- return e;
- }
- }
- /* Check alternative switches */
- AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
- struct ast_switch *asw = pbx_findswitch(sw->name);
- ast_switch_f *aswf = NULL;
- char *datap;
-
- if (!asw) {
- ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
- continue;
- }
- /* Substitute variables now */
- if (sw->eval) {
- if (!(tmpdata = ast_threadstorage_get(&switch_data, 512))) {
- ast_log(LOG_WARNING, "Can't evaluate switch?!");
- continue;
- }
- pbx_substitute_variables_helper(chan, sw->data, tmpdata, 512);
- }
-
- /* equivalent of extension_match_core() at the switch level */
- if (action == E_CANMATCH)
- aswf = asw->canmatch;
- else if (action == E_MATCHMORE)
- aswf = asw->matchmore;
- else /* action == E_MATCH */
- aswf = asw->exists;
- datap = sw->eval ? tmpdata : sw->data;
- if (!aswf)
- res = 0;
- else {
- if (chan)
- ast_autoservice_start(chan);
- res = aswf(chan, context, exten, priority, callerid, datap);
- if (chan)
- ast_autoservice_stop(chan);
- }
- if (res) { /* Got a match */
- q->swo = asw;
- q->data = datap;
- q->foundcontext = context;
- /* XXX keep status = STATUS_NO_CONTEXT ? */
- return NULL;
- }
- }
- q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
- /* Now try any includes we have in this context */
- for (i = tmp->includes; i; i = i->next) {
- if (include_valid(i)) {
- if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action)))
- return e;
- if (q->swo)
- return NULL;
- }
- }
- return NULL;
-}
-
-/*! \brief extract offset:length from variable name.
- * Returns 1 if there is a offset:length part, which is
- * trimmed off (values go into variables)
- */
-static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
-{
- int parens=0;
-
- *offset = 0;
- *length = INT_MAX;
- *isfunc = 0;
- for (; *var; var++) {
- if (*var == '(') {
- (*isfunc)++;
- parens++;
- } else if (*var == ')') {
- parens--;
- } else if (*var == ':' && parens == 0) {
- *var++ = '\0';
- sscanf(var, "%d:%d", offset, length);
- return 1; /* offset:length valid */
- }
- }
- return 0;
-}
-
-/*! \brief takes a substring. It is ok to call with value == workspace.
- *
- * offset < 0 means start from the end of the string and set the beginning
- * to be that many characters back.
- * length is the length of the substring. A value less than 0 means to leave
- * that many off the end.
- * Always return a copy in workspace.
- */
-static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
-{
- char *ret = workspace;
- int lr; /* length of the input string after the copy */
-
- ast_copy_string(workspace, value, workspace_len); /* always make a copy */
-
- lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
-
- /* Quick check if no need to do anything */
- if (offset == 0 && length >= lr) /* take the whole string */
- return ret;
-
- if (offset < 0) { /* translate negative offset into positive ones */
- offset = lr + offset;
- if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
- offset = 0;
- }
-
- /* too large offset result in empty string so we know what to return */
- if (offset >= lr)
- return ret + lr; /* the final '\0' */
-
- ret += offset; /* move to the start position */
- if (length >= 0 && length < lr - offset) /* truncate if necessary */
- ret[length] = '\0';
- else if (length < 0) {
- if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
- ret[lr + length - offset] = '\0';
- else
- ret[0] = '\0';
- }
-
- return ret;
-}
-
-/*! \brief pbx_retrieve_variable: Support for Asterisk built-in variables
- ---*/
-void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
-{
- const char not_found = '\0';
- char *tmpvar;
- const char *s; /* the result */
- int offset, length;
- int i, need_substring;
- struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
-
- if (c) {
- ast_channel_lock(c);
- places[0] = &c->varshead;
- }
- /*
- * Make a copy of var because parse_variable_name() modifies the string.
- * Then if called directly, we might need to run substring() on the result;
- * remember this for later in 'need_substring', 'offset' and 'length'
- */
- tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
- need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
-
- /*
- * Look first into predefined variables, then into variable lists.
- * Variable 's' points to the result, according to the following rules:
- * s == &not_found (set at the beginning) means that we did not find a
- * matching variable and need to look into more places.
- * If s != &not_found, s is a valid result string as follows:
- * s = NULL if the variable does not have a value;
- * you typically do this when looking for an unset predefined variable.
- * s = workspace if the result has been assembled there;
- * typically done when the result is built e.g. with an snprintf(),
- * so we don't need to do an additional copy.
- * s != workspace in case we have a string, that needs to be copied
- * (the ast_copy_string is done once for all at the end).
- * Typically done when the result is already available in some string.
- */
- s = &not_found; /* default value */
- if (c) { /* This group requires a valid channel */
- /* Names with common parts are looked up a piece at a time using strncmp. */
- if (!strncmp(var, "CALL", 4)) {
- if (!strncmp(var + 4, "ING", 3)) {
- if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */
- snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
- s = workspace;
- } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */
- snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
- s = workspace;
- } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */
- snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
- s = workspace;
- } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */
- snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
- s = workspace;
- }
- }
- } else if (!strcmp(var, "HINT")) {
- s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
- } else if (!strcmp(var, "HINTNAME")) {
- s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
- } else if (!strcmp(var, "EXTEN")) {
- s = c->exten;
- } else if (!strcmp(var, "CONTEXT")) {
- s = c->context;
- } else if (!strcmp(var, "PRIORITY")) {
- snprintf(workspace, workspacelen, "%d", c->priority);
- s = workspace;
- } else if (!strcmp(var, "CHANNEL")) {
- s = c->name;
- } else if (!strcmp(var, "UNIQUEID")) {
- s = c->uniqueid;
- } else if (!strcmp(var, "HANGUPCAUSE")) {
- snprintf(workspace, workspacelen, "%d", c->hangupcause);
- s = workspace;
- }
- }
- if (s == &not_found) { /* look for more */
- if (!strcmp(var, "EPOCH")) {
- snprintf(workspace, workspacelen, "%u",(int)time(NULL));
- s = workspace;
- } else if (!strcmp(var, "SYSTEMNAME")) {
- s = ast_config_AST_SYSTEM_NAME;
- }
- }
- /* if not found, look into chanvars or global vars */
- for (i = 0; s == &not_found && i < (sizeof(places) / sizeof(places[0])); i++) {
- struct ast_var_t *variables;
- if (!places[i])
- continue;
- if (places[i] == &globals)
- ast_mutex_lock(&globalslock);
- AST_LIST_TRAVERSE(places[i], variables, entries) {
- if (strcasecmp(ast_var_name(variables), var)==0) {
- s = ast_var_value(variables);
- break;
- }
- }
- if (places[i] == &globals)
- ast_mutex_unlock(&globalslock);
- }
- if (s == &not_found || s == NULL)
- *ret = NULL;
- else {
- if (s != workspace)
- ast_copy_string(workspace, s, workspacelen);
- *ret = workspace;
- if (need_substring)
- *ret = substring(*ret, offset, length, workspace, workspacelen);
- }
-
- if (c)
- ast_channel_unlock(c);
-}
-
-/*! \brief CLI function to show installed custom functions
- \addtogroup CLI_functions
- */
-static int handle_show_functions_deprecated(int fd, int argc, char *argv[])
-{
- struct ast_custom_function *acf;
- int count_acf = 0;
- int like = 0;
-
- if (argc == 4 && (!strcmp(argv[2], "like")) ) {
- like = 1;
- } else if (argc != 2) {
- return RESULT_SHOWUSAGE;
- }
-
- ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
-
- AST_LIST_LOCK(&acf_root);
- AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
- if (!like || strstr(acf->name, argv[3])) {
- count_acf++;
- ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis);
- }
- }
- AST_LIST_UNLOCK(&acf_root);
-
- ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
-
- return RESULT_SUCCESS;
-}
-static int handle_show_functions(int fd, int argc, char *argv[])
-{
- struct ast_custom_function *acf;
- int count_acf = 0;
- int like = 0;
-
- if (argc == 5 && (!strcmp(argv[3], "like")) ) {
- like = 1;
- } else if (argc != 3) {
- return RESULT_SHOWUSAGE;
- }
-
- ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
-
- AST_LIST_LOCK(&acf_root);
- AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
- if (!like || strstr(acf->name, argv[4])) {
- count_acf++;
- ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis);
- }
- }
- AST_LIST_UNLOCK(&acf_root);
-
- ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
-
- return RESULT_SUCCESS;
-}
-
-static int handle_show_function_deprecated(int fd, int argc, char *argv[])
-{
- struct ast_custom_function *acf;
- /* Maximum number of characters added by terminal coloring is 22 */
- char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
- char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
- char stxtitle[40], *syntax = NULL;
- int synopsis_size, description_size, syntax_size;
-
- if (argc < 3)
- return RESULT_SHOWUSAGE;
-
- if (!(acf = ast_custom_function_find(argv[2]))) {
- ast_cli(fd, "No function by that name registered.\n");
- return RESULT_FAILURE;
-
- }
-
- if (acf->synopsis)
- synopsis_size = strlen(acf->synopsis) + 23;
- else
- synopsis_size = strlen("Not available") + 23;
- synopsis = alloca(synopsis_size);
-
- if (acf->desc)
- description_size = strlen(acf->desc) + 23;
- else
- description_size = strlen("Not available") + 23;
- description = alloca(description_size);
-
- if (acf->syntax)
- syntax_size = strlen(acf->syntax) + 23;
- else
- syntax_size = strlen("Not available") + 23;
- syntax = alloca(syntax_size);
-
- snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name);
- term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
- term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
- term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
- term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
- term_color(syntax,
- acf->syntax ? acf->syntax : "Not available",
- COLOR_CYAN, 0, syntax_size);
- term_color(synopsis,
- acf->synopsis ? acf->synopsis : "Not available",
- COLOR_CYAN, 0, synopsis_size);
- term_color(description,
- acf->desc ? acf->desc : "Not available",
- COLOR_CYAN, 0, description_size);
-
- ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
-
- return RESULT_SUCCESS;
-}
-
-static int handle_show_function(int fd, int argc, char *argv[])
-{
- struct ast_custom_function *acf;
- /* Maximum number of characters added by terminal coloring is 22 */
- char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
- char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
- char stxtitle[40], *syntax = NULL;
- int synopsis_size, description_size, syntax_size;
-
- if (argc < 4)
- return RESULT_SHOWUSAGE;
-
- if (!(acf = ast_custom_function_find(argv[3]))) {
- ast_cli(fd, "No function by that name registered.\n");
- return RESULT_FAILURE;
-
- }
-
- if (acf->synopsis)
- synopsis_size = strlen(acf->synopsis) + 23;
- else
- synopsis_size = strlen("Not available") + 23;
- synopsis = alloca(synopsis_size);
-
- if (acf->desc)
- description_size = strlen(acf->desc) + 23;
- else
- description_size = strlen("Not available") + 23;
- description = alloca(description_size);
-
- if (acf->syntax)
- syntax_size = strlen(acf->syntax) + 23;
- else
- syntax_size = strlen("Not available") + 23;
- syntax = alloca(syntax_size);
-
- snprintf(info, 64 + AST_MAX_APP, "\n -= Info about function '%s' =- \n\n", acf->name);
- term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
- term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
- term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
- term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
- term_color(syntax,
- acf->syntax ? acf->syntax : "Not available",
- COLOR_CYAN, 0, syntax_size);
- term_color(synopsis,
- acf->synopsis ? acf->synopsis : "Not available",
- COLOR_CYAN, 0, synopsis_size);
- term_color(description,
- acf->desc ? acf->desc : "Not available",
- COLOR_CYAN, 0, description_size);
-
- ast_cli(fd,"%s%s%s\n\n%s%s\n\n%s%s\n", infotitle, stxtitle, syntax, syntitle, synopsis, destitle, description);
-
- return RESULT_SUCCESS;
-}
-
-static char *complete_show_function(const char *line, const char *word, int pos, int state)
-{
- struct ast_custom_function *acf;
- char *ret = NULL;
- int which = 0;
- int wordlen = strlen(word);
-
- /* case-insensitive for convenience in this 'complete' function */
- AST_LIST_LOCK(&acf_root);
- AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
- if (!strncasecmp(word, acf->name, wordlen) && ++which > state) {
- ret = strdup(acf->name);
- break;
- }
- }
- AST_LIST_UNLOCK(&acf_root);
-
- return ret;
-}
-
-struct ast_custom_function *ast_custom_function_find(const char *name)
-{
- struct ast_custom_function *acf = NULL;
-
- AST_LIST_LOCK(&acf_root);
- AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
- if (!strcmp(name, acf->name))
- break;
- }
- AST_LIST_UNLOCK(&acf_root);
-
- return acf;
-}
-
-int ast_custom_function_unregister(struct ast_custom_function *acf)
-{
- struct ast_custom_function *cur;
-
- if (!acf)
- return -1;
-
- AST_LIST_LOCK(&acf_root);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
- if (cur == acf) {
- AST_LIST_REMOVE_CURRENT(&acf_root, acflist);
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&acf_root);
-
- return acf ? 0 : -1;
-}
-
-int ast_custom_function_register(struct ast_custom_function *acf)
-{
- struct ast_custom_function *cur;
-
- if (!acf)
- return -1;
-
- AST_LIST_LOCK(&acf_root);
-
- if (ast_custom_function_find(acf->name)) {
- ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
- AST_LIST_UNLOCK(&acf_root);
- return -1;
- }
-
- /* Store in alphabetical order */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
- if (strcasecmp(acf->name, cur->name) < 0) {
- AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- if (!cur)
- AST_LIST_INSERT_TAIL(&acf_root, acf, acflist);
-
- AST_LIST_UNLOCK(&acf_root);
-
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
-
- return 0;
-}
-
-/*! \brief return a pointer to the arguments of the function,
- * and terminates the function name with '\\0'
- */
-static char *func_args(char *function)
-{
- char *args = strchr(function, '(');
-
- if (!args)
- ast_log(LOG_WARNING, "Function doesn't contain parentheses. Assuming null argument.\n");
- else {
- char *p;
- *args++ = '\0';
- if ((p = strrchr(args, ')')) )
- *p = '\0';
- else
- ast_log(LOG_WARNING, "Can't find trailing parenthesis?\n");
- }
- return args;
-}
-
-int ast_func_read(struct ast_channel *chan, char *function, char *workspace, size_t len)
-{
- char *args = func_args(function);
- struct ast_custom_function *acfptr = ast_custom_function_find(function);
-
- if (acfptr == NULL)
- ast_log(LOG_ERROR, "Function %s not registered\n", function);
- else if (!acfptr->read)
- ast_log(LOG_ERROR, "Function %s cannot be read\n", function);
- else
- return acfptr->read(chan, function, args, workspace, len);
- return -1;
-}
-
-int ast_func_write(struct ast_channel *chan, char *function, const char *value)
-{
- char *args = func_args(function);
- struct ast_custom_function *acfptr = ast_custom_function_find(function);
-
- if (acfptr == NULL)
- ast_log(LOG_ERROR, "Function %s not registered\n", function);
- else if (!acfptr->write)
- ast_log(LOG_ERROR, "Function %s cannot be written to\n", function);
- else
- return acfptr->write(chan, function, args, value);
-
- return -1;
-}
-
-static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count)
-{
- /* Substitutes variables into cp2, based on string cp1, and assuming cp2 to be
- zero-filled */
- char *cp4;
- const char *tmp, *whereweare;
- int length, offset, offset2, isfunction;
- char *workspace = NULL;
- char *ltmp = NULL, *var = NULL;
- char *nextvar, *nextexp, *nextthing;
- char *vars, *vare;
- int pos, brackets, needsub, len;
-
- whereweare=tmp=cp1;
- while (!ast_strlen_zero(whereweare) && count) {
- /* Assume we're copying the whole remaining string */
- pos = strlen(whereweare);
- nextvar = NULL;
- nextexp = NULL;
- nextthing = strchr(whereweare, '$');
- if (nextthing) {
- switch(nextthing[1]) {
- case '{':
- nextvar = nextthing;
- pos = nextvar - whereweare;
- break;
- case '[':
- nextexp = nextthing;
- pos = nextexp - whereweare;
- break;
- default:
- pos = 1;
- }
- }
-
- if (pos) {
- /* Can't copy more than 'count' bytes */
- if (pos > count)
- pos = count;
-
- /* Copy that many bytes */
- memcpy(cp2, whereweare, pos);
-
- count -= pos;
- cp2 += pos;
- whereweare += pos;
- }
-
- if (nextvar) {
- /* We have a variable. Find the start and end, and determine
- if we are going to have to recursively call ourselves on the
- contents */
- vars = vare = nextvar + 2;
- brackets = 1;
- needsub = 0;
-
- /* Find the end of it */
- while (brackets && *vare) {
- if ((vare[0] == '$') && (vare[1] == '{')) {
- needsub++;
- } else if (vare[0] == '{') {
- brackets++;
- } else if (vare[0] == '}') {
- brackets--;
- } else if ((vare[0] == '$') && (vare[1] == '['))
- needsub++;
- vare++;
- }
- if (brackets)
- ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
- len = vare - vars - 1;
-
- /* Skip totally over variable string */
- whereweare += (len + 3);
-
- if (!var)
- var = alloca(VAR_BUF_SIZE);
-
- /* Store variable name (and truncate) */
- ast_copy_string(var, vars, len + 1);
-
- /* Substitute if necessary */
- if (needsub) {
- if (!ltmp)
- ltmp = alloca(VAR_BUF_SIZE);
-
- memset(ltmp, 0, VAR_BUF_SIZE);
- pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
- vars = ltmp;
- } else {
- vars = var;
- }
-
- if (!workspace)
- workspace = alloca(VAR_BUF_SIZE);
-
- workspace[0] = '\0';
-
- parse_variable_name(vars, &offset, &offset2, &isfunction);
- if (isfunction) {
- /* Evaluate function */
- if (c || !headp)
- cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
- else {
- struct varshead old;
- struct ast_channel *c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
- if (c) {
- memcpy(&old, &c->varshead, sizeof(old));
- memcpy(&c->varshead, headp, sizeof(c->varshead));
- cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
- /* Don't deallocate the varshead that was passed in */
- memcpy(&c->varshead, &old, sizeof(c->varshead));
- ast_channel_free(c);
- } else
- ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
- }
-
- if (option_debug)
- ast_log(LOG_DEBUG, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
- } else {
- /* Retrieve variable value */
- pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
- }
- if (cp4) {
- cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
-
- length = strlen(cp4);
- if (length > count)
- length = count;
- memcpy(cp2, cp4, length);
- count -= length;
- cp2 += length;
- }
- } else if (nextexp) {
- /* We have an expression. Find the start and end, and determine
- if we are going to have to recursively call ourselves on the
- contents */
- vars = vare = nextexp + 2;
- brackets = 1;
- needsub = 0;
-
- /* Find the end of it */
- while(brackets && *vare) {
- if ((vare[0] == '$') && (vare[1] == '[')) {
- needsub++;
- brackets++;
- vare++;
- } else if (vare[0] == '[') {
- brackets++;
- } else if (vare[0] == ']') {
- brackets--;
- } else if ((vare[0] == '$') && (vare[1] == '{')) {
- needsub++;
- vare++;
- }
- vare++;
- }
- if (brackets)
- ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
- len = vare - vars - 1;
-
- /* Skip totally over expression */
- whereweare += (len + 3);
-
- if (!var)
- var = alloca(VAR_BUF_SIZE);
-
- /* Store variable name (and truncate) */
- ast_copy_string(var, vars, len + 1);
-
- /* Substitute if necessary */
- if (needsub) {
- if (!ltmp)
- ltmp = alloca(VAR_BUF_SIZE);
-
- memset(ltmp, 0, VAR_BUF_SIZE);
- pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1);
- vars = ltmp;
- } else {
- vars = var;
- }
-
- length = ast_expr(vars, cp2, count);
-
- if (length) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
- count -= length;
- cp2 += length;
- }
- }
- }
-}
-
-void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
-{
- pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count);
-}
-
-void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
-{
- pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count);
-}
-
-static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
-{
- memset(passdata, 0, datalen);
-
- /* No variables or expressions in e->data, so why scan it? */
- if (e->data && !strchr(e->data, '$') && !strstr(e->data,"${") && !strstr(e->data,"$[") && !strstr(e->data,"$(")) {
- ast_copy_string(passdata, e->data, datalen);
- return;
- }
-
- pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
-}
-
-/*!
- * \brief The return value depends on the action:
- *
- * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
- * and return 0 on failure, -1 on match;
- * E_FINDLABEL maps the label to a priority, and returns
- * the priority on success, ... XXX
- * E_SPAWN, spawn an application,
- * and return 0 on success, -1 on failure.
- *
- * \note The channel is auto-serviced in this function, because doing an extension
- * match may block for a long time. For example, if the lookup has to use a network
- * dialplan switch, such as DUNDi or IAX2, it may take a while. However, the channel
- * auto-service code will queue up any important signalling frames to be processed
- * after this is done.
- */
-static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
- const char *context, const char *exten, int priority,
- const char *label, const char *callerid, enum ext_match_t action)
-{
- struct ast_exten *e;
- struct ast_app *app;
- int res;
- struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
- char passdata[EXT_DATA_SIZE];
-
- int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
-
- ast_rdlock_contexts();
- e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
- if (e) {
- if (matching_action) {
- ast_unlock_contexts();
- return -1; /* success, we found it */
- } else if (action == E_FINDLABEL) { /* map the label to a priority */
- res = e->priority;
- ast_unlock_contexts();
- return res; /* the priority we were looking for */
- } else { /* spawn */
- app = pbx_findapp(e->app);
- ast_unlock_contexts();
- if (!app) {
- ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
- return -1;
- }
- if (c->context != context)
- ast_copy_string(c->context, context, sizeof(c->context));
- if (c->exten != exten)
- ast_copy_string(c->exten, exten, sizeof(c->exten));
- c->priority = priority;
- pbx_substitute_variables(passdata, sizeof(passdata), c, e);
- if (option_debug) {
- ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
- }
- if (option_verbose > 2) {
- char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
- ast_verbose( VERBOSE_PREFIX_3 "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
- exten, context, priority,
- term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
- term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
- term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
- "in new stack");
- }
- manager_event(EVENT_FLAG_CALL, "Newexten",
- "Channel: %s\r\n"
- "Context: %s\r\n"
- "Extension: %s\r\n"
- "Priority: %d\r\n"
- "Application: %s\r\n"
- "AppData: %s\r\n"
- "Uniqueid: %s\r\n",
- c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
- return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
- }
- } else if (q.swo) { /* not found here, but in another switch */
- ast_unlock_contexts();
- if (matching_action) {
- return -1;
- } else {
- if (!q.swo->exec) {
- ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
- res = -1;
- }
- return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
- }
- } else { /* not found anywhere, see what happened */
- ast_unlock_contexts();
- switch (q.status) {
- case STATUS_NO_CONTEXT:
- if (!matching_action)
- ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", context);
- break;
- case STATUS_NO_EXTENSION:
- if (!matching_action)
- ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, context);
- break;
- case STATUS_NO_PRIORITY:
- if (!matching_action)
- ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, context);
- break;
- case STATUS_NO_LABEL:
- if (context)
- ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, context);
- break;
- default:
- if (option_debug)
- ast_log(LOG_DEBUG, "Shouldn't happen!\n");
- }
-
- return (matching_action) ? 0 : -1;
- }
-}
-
-/*! \brief ast_hint_extension: Find hint for given extension in context */
-static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
-{
- struct ast_exten *e;
- struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
-
- ast_rdlock_contexts();
- e = pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
- ast_unlock_contexts();
-
- return e;
-}
-
-/*! \brief ast_extensions_state2: Check state of extension by using hints */
-static int ast_extension_state2(struct ast_exten *e)
-{
- char hint[AST_MAX_EXTENSION];
- char *cur, *rest;
- int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1;
- int busy = 0, inuse = 0, ring = 0;
-
- if (!e)
- return -1;
-
- ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint));
-
- rest = hint; /* One or more devices separated with a & character */
- while ( (cur = strsep(&rest, "&")) ) {
- int res = ast_device_state(cur);
- switch (res) {
- case AST_DEVICE_NOT_INUSE:
- allunavailable = 0;
- allbusy = 0;
- allonhold = 0;
- break;
- case AST_DEVICE_INUSE:
- inuse = 1;
- allunavailable = 0;
- allfree = 0;
- allonhold = 0;
- break;
- case AST_DEVICE_RINGING:
- ring = 1;
- allunavailable = 0;
- allfree = 0;
- allonhold = 0;
- break;
- case AST_DEVICE_RINGINUSE:
- inuse = 1;
- ring = 1;
- allunavailable = 0;
- allfree = 0;
- allonhold = 0;
- break;
- case AST_DEVICE_ONHOLD:
- allunavailable = 0;
- allfree = 0;
- break;
- case AST_DEVICE_BUSY:
- allunavailable = 0;
- allfree = 0;
- allonhold = 0;
- busy = 1;
- break;
- case AST_DEVICE_UNAVAILABLE:
- case AST_DEVICE_INVALID:
- allbusy = 0;
- allfree = 0;
- allonhold = 0;
- break;
- default:
- allunavailable = 0;
- allbusy = 0;
- allfree = 0;
- allonhold = 0;
- }
- }
-
- if (!inuse && ring)
- return AST_EXTENSION_RINGING;
- if (inuse && ring)
- return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
- if (inuse)
- return AST_EXTENSION_INUSE;
- if (allfree)
- return AST_EXTENSION_NOT_INUSE;
- if (allonhold)
- return AST_EXTENSION_ONHOLD;
- if (allbusy)
- return AST_EXTENSION_BUSY;
- if (allunavailable)
- return AST_EXTENSION_UNAVAILABLE;
- if (busy)
- return AST_EXTENSION_INUSE;
-
- return AST_EXTENSION_NOT_INUSE;
-}
-
-/*! \brief ast_extension_state2str: Return extension_state as string */
-const char *ast_extension_state2str(int extension_state)
-{
- int i;
-
- for (i = 0; (i < (sizeof(extension_states) / sizeof(extension_states[0]))); i++) {
- if (extension_states[i].extension_state == extension_state)
- return extension_states[i].text;
- }
- return "Unknown";
-}
-
-/*! \brief ast_extension_state: Check extension state for an extension by using hint */
-int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
-{
- struct ast_exten *e;
-
- e = ast_hint_extension(c, context, exten); /* Do we have a hint for this extension ? */
- if (!e)
- return -1; /* No hint, return -1 */
-
- return ast_extension_state2(e); /* Check all devices in the hint */
-}
-
-void ast_hint_state_changed(const char *device)
-{
- struct ast_hint *hint;
-
- AST_LIST_LOCK(&hints);
-
- AST_LIST_TRAVERSE(&hints, hint, list) {
- struct ast_state_cb *cblist;
- char buf[AST_MAX_EXTENSION];
- char *parse = buf;
- char *cur;
- int state;
-
- ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
- while ( (cur = strsep(&parse, "&")) ) {
- if (!strcasecmp(cur, device))
- break;
- }
- if (!cur)
- continue;
-
- /* Get device state for this hint */
- state = ast_extension_state2(hint->exten);
-
- if ((state == -1) || (state == hint->laststate))
- continue;
-
- /* Device state changed since last check - notify the watchers */
-
- /* For general callbacks */
- for (cblist = statecbs; cblist; cblist = cblist->next)
- cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
-
- /* For extension callbacks */
- for (cblist = hint->callbacks; cblist; cblist = cblist->next)
- cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
-
- hint->laststate = state; /* record we saw the change */
- }
-
- AST_LIST_UNLOCK(&hints);
-}
-
-/*! \brief ast_extension_state_add: Add watcher for extension states */
-int ast_extension_state_add(const char *context, const char *exten,
- ast_state_cb_type callback, void *data)
-{
- struct ast_hint *hint;
- struct ast_state_cb *cblist;
- struct ast_exten *e;
-
- /* If there's no context and extension: add callback to statecbs list */
- if (!context && !exten) {
- AST_LIST_LOCK(&hints);
-
- for (cblist = statecbs; cblist; cblist = cblist->next) {
- if (cblist->callback == callback) {
- cblist->data = data;
- AST_LIST_UNLOCK(&hints);
- return 0;
- }
- }
-
- /* Now insert the callback */
- if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
- AST_LIST_UNLOCK(&hints);
- return -1;
- }
- cblist->id = 0;
- cblist->callback = callback;
- cblist->data = data;
-
- cblist->next = statecbs;
- statecbs = cblist;
-
- AST_LIST_UNLOCK(&hints);
- return 0;
- }
-
- if (!context || !exten)
- return -1;
-
- /* This callback type is for only one hint, so get the hint */
- e = ast_hint_extension(NULL, context, exten);
- if (!e) {
- return -1;
- }
-
- /* Find the hint in the list of hints */
- AST_LIST_LOCK(&hints);
-
- AST_LIST_TRAVERSE(&hints, hint, list) {
- if (hint->exten == e)
- break;
- }
-
- if (!hint) {
- /* We have no hint, sorry */
- AST_LIST_UNLOCK(&hints);
- return -1;
- }
-
- /* Now insert the callback in the callback list */
- if (!(cblist = ast_calloc(1, sizeof(*cblist)))) {
- AST_LIST_UNLOCK(&hints);
- return -1;
- }
- cblist->id = stateid++; /* Unique ID for this callback */
- cblist->callback = callback; /* Pointer to callback routine */
- cblist->data = data; /* Data for the callback */
-
- cblist->next = hint->callbacks;
- hint->callbacks = cblist;
-
- AST_LIST_UNLOCK(&hints);
- return cblist->id;
-}
-
-/*! \brief ast_extension_state_del: Remove a watcher from the callback list */
-int ast_extension_state_del(int id, ast_state_cb_type callback)
-{
- struct ast_state_cb **p_cur = NULL; /* address of pointer to us */
- int ret = -1;
-
- if (!id && !callback)
- return -1;
-
- AST_LIST_LOCK(&hints);
-
- if (!id) { /* id == 0 is a callback without extension */
- for (p_cur = &statecbs; *p_cur; p_cur = &(*p_cur)->next) {
- if ((*p_cur)->callback == callback)
- break;
- }
- } else { /* callback with extension, find the callback based on ID */
- struct ast_hint *hint;
- AST_LIST_TRAVERSE(&hints, hint, list) {
- for (p_cur = &hint->callbacks; *p_cur; p_cur = &(*p_cur)->next) {
- if ((*p_cur)->id == id)
- break;
- }
- if (*p_cur) /* found in the inner loop */
- break;
- }
- }
- if (p_cur && *p_cur) {
- struct ast_state_cb *cur = *p_cur;
- *p_cur = cur->next;
- free(cur);
- ret = 0;
- }
- AST_LIST_UNLOCK(&hints);
- return ret;
-}
-
-/*! \brief ast_add_hint: Add hint to hint list, check initial extension state */
-static int ast_add_hint(struct ast_exten *e)
-{
- struct ast_hint *hint;
-
- if (!e)
- return -1;
-
- AST_LIST_LOCK(&hints);
-
- /* Search if hint exists, do nothing */
- AST_LIST_TRAVERSE(&hints, hint, list) {
- if (hint->exten == e) {
- AST_LIST_UNLOCK(&hints);
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
- return -1;
- }
- }
-
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "HINTS: Adding hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e));
-
- if (!(hint = ast_calloc(1, sizeof(*hint)))) {
- AST_LIST_UNLOCK(&hints);
- return -1;
- }
- /* Initialize and insert new item at the top */
- hint->exten = e;
- hint->laststate = ast_extension_state2(e);
- AST_LIST_INSERT_HEAD(&hints, hint, list);
-
- AST_LIST_UNLOCK(&hints);
- return 0;
-}
-
-/*! \brief ast_change_hint: Change hint for an extension */
-static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
-{
- struct ast_hint *hint;
- int res = -1;
-
- AST_LIST_LOCK(&hints);
- AST_LIST_TRAVERSE(&hints, hint, list) {
- if (hint->exten == oe) {
- hint->exten = ne;
- res = 0;
- break;
- }
- }
- AST_LIST_UNLOCK(&hints);
-
- return res;
-}
-
-/*! \brief ast_remove_hint: Remove hint from extension */
-static int ast_remove_hint(struct ast_exten *e)
-{
- /* Cleanup the Notifys if hint is removed */
- struct ast_hint *hint;
- struct ast_state_cb *cblist, *cbprev;
- int res = -1;
-
- if (!e)
- return -1;
-
- AST_LIST_LOCK(&hints);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&hints, hint, list) {
- if (hint->exten == e) {
- cbprev = NULL;
- cblist = hint->callbacks;
- while (cblist) {
- /* Notify with -1 and remove all callbacks */
- cbprev = cblist;
- cblist = cblist->next;
- cbprev->callback(hint->exten->parent->name, hint->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
- free(cbprev);
- }
- hint->callbacks = NULL;
- AST_LIST_REMOVE_CURRENT(&hints, list);
- free(hint);
- res = 0;
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&hints);
-
- return res;
-}
-
-
-/*! \brief ast_get_hint: Get hint for channel */
-int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
-{
- struct ast_exten *e = ast_hint_extension(c, context, exten);
-
- if (e) {
- if (hint)
- ast_copy_string(hint, ast_get_extension_app(e), hintsize);
- if (name) {
- const char *tmp = ast_get_extension_app_data(e);
- if (tmp)
- ast_copy_string(name, tmp, namesize);
- }
- return -1;
- }
- return 0;
-}
-
-int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
-{
- return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH);
-}
-
-int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
-{
- return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL);
-}
-
-int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
-{
- return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL);
-}
-
-int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
-{
- return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH);
-}
-
-int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
-{
- return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE);
-}
-
-int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
-{
- return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN);
-}
-
-/* helper function to set extension and priority */
-static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
-{
- ast_channel_lock(c);
- ast_copy_string(c->exten, exten, sizeof(c->exten));
- c->priority = pri;
- ast_channel_unlock(c);
-}
-
-/*!
- * \brief collect digits from the channel into the buffer,
- * return -1 on error, 0 on timeout or done.
- */
-static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
-{
- int digit;
-
- buf[pos] = '\0'; /* make sure it is properly terminated */
- while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
- /* As long as we're willing to wait, and as long as it's not defined,
- keep reading digits until we can't possibly get a right answer anymore. */
- digit = ast_waitfordigit(c, waittime * 1000);
- if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
- c->_softhangup = 0;
- } else {
- if (!digit) /* No entry */
- break;
- if (digit < 0) /* Error, maybe a hangup */
- return -1;
- if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
- buf[pos++] = digit;
- buf[pos] = '\0';
- }
- waittime = c->pbx->dtimeout;
- }
- }
- return 0;
-}
-
-static int __ast_pbx_run(struct ast_channel *c)
-{
- int found = 0; /* set if we find at least one match */
- int res = 0;
- int autoloopflag;
- int error = 0; /* set an error conditions */
-
- /* A little initial setup here */
- if (c->pbx) {
- ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
- /* XXX and now what ? */
- free(c->pbx);
- }
- if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
- return -1;
- /* Set reasonable defaults */
- c->pbx->rtimeout = 10;
- c->pbx->dtimeout = 5;
-
- autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
- ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
-
- /* Start by trying whatever the channel is set to */
- if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
- /* If not successful fall back to 's' */
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority);
- /* XXX the original code used the existing priority in the call to
- * ast_exists_extension(), and reset it to 1 afterwards.
- * I believe the correct thing is to set it to 1 immediately.
- */
- set_ext_pri(c, "s", 1);
- if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
- /* JK02: And finally back to default if everything else failed */
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority);
- ast_copy_string(c->context, "default", sizeof(c->context));
- }
- }
- for (;;) {
- char dst_exten[256]; /* buffer to accumulate digits */
- int pos = 0; /* XXX should check bounds */
- int digit = 0;
-
- /* loop on priorities in this context/exten */
- while (ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
- found = 1;
- if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
- /* Something bad happened, or a hangup has been requested. */
- if (strchr("0123456789ABCDEF*#", res)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
- pos = 0;
- dst_exten[pos++] = digit = res;
- dst_exten[pos] = '\0';
- break;
- }
- if (res == AST_PBX_KEEPALIVE) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE on '%s'\n", c->context, c->exten, c->priority, c->name);
- error = 1;
- break;
- }
- if (option_debug)
- ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
- if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
- c->_softhangup = 0;
- } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
- /* atimeout, nothing bad */
- } else {
- if (c->cdr)
- ast_cdr_update(c);
- error = 1;
- break;
- }
- }
- if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
- c->_softhangup = 0;
- } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c,c->context,"T",1,c->cid.cid_num)) {
- set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
- /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
- c->whentohangup = 0;
- c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
- } else if (c->_softhangup) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
- c->exten, c->priority);
- error = 1;
- break;
- }
- c->priority++;
- } /* end while - from here on we can use 'break' to go out */
- if (error)
- break;
-
- /* XXX we get here on non-existing extension or a keypress or hangup ? */
-
- if (!ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
- /* If there is no match at priority 1, it is not a valid extension anymore.
- * Try to continue at "i", 1 or exit if the latter does not exist.
- */
- if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
- pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
- set_ext_pri(c, "i", 1);
- } else {
- ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
- c->name, c->exten, c->context);
- error = 1; /* we know what to do with it */
- break;
- }
- } else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
- /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
- c->_softhangup = 0;
- } else { /* keypress received, get more digits for a full extension */
- int waittime = 0;
- if (digit)
- waittime = c->pbx->dtimeout;
- else if (!autofallthrough)
- waittime = c->pbx->rtimeout;
- if (!waittime) {
- const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
- if (!status)
- status = "UNKNOWN";
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_2 "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
- if (!strcasecmp(status, "CONGESTION"))
- res = pbx_builtin_congestion(c, "10");
- else if (!strcasecmp(status, "CHANUNAVAIL"))
- res = pbx_builtin_congestion(c, "10");
- else if (!strcasecmp(status, "BUSY"))
- res = pbx_builtin_busy(c, "10");
- error = 1; /* XXX disable message */
- break; /* exit from the 'for' loop */
- }
-
- if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
- break;
- if (ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
- set_ext_pri(c, dst_exten, 1);
- else {
- /* No such extension */
- if (!ast_strlen_zero(dst_exten)) {
- /* An invalid extension */
- if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
- pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
- set_ext_pri(c, "i", 1);
- } else {
- ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
- found = 1; /* XXX disable message */
- break;
- }
- } else {
- /* A simple timeout */
- if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "Timeout on %s\n", c->name);
- set_ext_pri(c, "t", 1);
- } else {
- ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
- found = 1; /* XXX disable message */
- break;
- }
- }
- }
- if (c->cdr) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_2 "CDR updated on %s\n",c->name);
- ast_cdr_update(c);
- }
- }
- }
- if (!found && !error)
- ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
- if (res != AST_PBX_KEEPALIVE)
- ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING);
- if ((res != AST_PBX_KEEPALIVE) && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
- set_ext_pri(c, "h", 1);
- while(ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
- if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num))) {
- /* Something bad happened, or a hangup has been requested. */
- if (option_debug)
- ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
- break;
- }
- c->priority++;
- }
- }
- ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
- ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
- pbx_destroy(c->pbx);
- c->pbx = NULL;
- if (res != AST_PBX_KEEPALIVE)
- ast_hangup(c);
- return 0;
-}
-
-/* Returns 0 on success, non-zero if call limit was reached */
-static int increase_call_count(const struct ast_channel *c)
-{
- int failed = 0;
- double curloadavg;
- ast_mutex_lock(&maxcalllock);
- if (option_maxcalls) {
- if (countcalls >= option_maxcalls) {
- ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
- failed = -1;
- }
- }
- if (option_maxload) {
- getloadavg(&curloadavg, 1);
- if (curloadavg >= option_maxload) {
- ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
- failed = -1;
- }
- }
- if (!failed)
- countcalls++;
- ast_mutex_unlock(&maxcalllock);
-
- return failed;
-}
-
-static void decrease_call_count(void)
-{
- ast_mutex_lock(&maxcalllock);
- if (countcalls > 0)
- countcalls--;
- ast_mutex_unlock(&maxcalllock);
-}
-
-static void destroy_exten(struct ast_exten *e)
-{
- if (e->priority == PRIORITY_HINT)
- ast_remove_hint(e);
-
- if (e->datad)
- e->datad(e->data);
- free(e);
-}
-
-static void *pbx_thread(void *data)
-{
- /* Oh joyeous kernel, we're a new thread, with nothing to do but
- answer this channel and get it going.
- */
- /* NOTE:
- The launcher of this function _MUST_ increment 'countcalls'
- before invoking the function; it will be decremented when the
- PBX has finished running on the channel
- */
- struct ast_channel *c = data;
-
- __ast_pbx_run(c);
- decrease_call_count();
-
- pthread_exit(NULL);
-
- return NULL;
-}
-
-enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
-{
- pthread_t t;
- pthread_attr_t attr;
-
- if (!c) {
- ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
- return AST_PBX_FAILED;
- }
-
- if (increase_call_count(c))
- return AST_PBX_CALL_LIMIT;
-
- /* Start a new thread, and get something handling this channel. */
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
- ast_log(LOG_WARNING, "Failed to create new channel thread\n");
- pthread_attr_destroy(&attr);
- decrease_call_count();
- return AST_PBX_FAILED;
- }
- pthread_attr_destroy(&attr);
-
- return AST_PBX_SUCCESS;
-}
-
-enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
-{
- enum ast_pbx_result res = AST_PBX_SUCCESS;
-
- if (increase_call_count(c))
- return AST_PBX_CALL_LIMIT;
-
- res = __ast_pbx_run(c);
- decrease_call_count();
-
- return res;
-}
-
-int ast_active_calls(void)
-{
- return countcalls;
-}
-
-int pbx_set_autofallthrough(int newval)
-{
- int oldval = autofallthrough;
- autofallthrough = newval;
- return oldval;
-}
-
-/* lookup for a context with a given name,
- * return with conlock held if found, NULL if not found
- */
-static struct ast_context *find_context_locked(const char *context)
-{
- struct ast_context *c = NULL;
-
- ast_rdlock_contexts();
- while ( (c = ast_walk_contexts(c)) ) {
- if (!strcmp(ast_get_context_name(c), context))
- return c;
- }
- ast_unlock_contexts();
-
- return NULL;
-}
-
-/*
- * This function locks contexts list by &conlist, search for the right context
- * structure, leave context list locked and call ast_context_remove_include2
- * which removes include, unlock contexts list and return ...
- */
-int ast_context_remove_include(const char *context, const char *include, const char *registrar)
-{
- int ret = -1;
- struct ast_context *c = find_context_locked(context);
-
- if (c) {
- /* found, remove include from this context ... */
- ret = ast_context_remove_include2(c, include, registrar);
- ast_unlock_contexts();
- }
- return ret;
-}
-
-/*
- * When we call this function, &conlock lock must be locked, because when
- * we giving *con argument, some process can remove/change this context
- * and after that there can be segfault.
- *
- * This function locks given context, removes include, unlock context and
- * return.
- */
-int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
-{
- struct ast_include *i, *pi = NULL;
- int ret = -1;
-
- ast_mutex_lock(&con->lock);
-
- /* find our include */
- for (i = con->includes; i; pi = i, i = i->next) {
- if (!strcmp(i->name, include) &&
- (!registrar || !strcmp(i->registrar, registrar))) {
- /* remove from list */
- if (pi)
- pi->next = i->next;
- else
- con->includes = i->next;
- /* free include and return */
- free(i);
- ret = 0;
- break;
- }
- }
-
- ast_mutex_unlock(&con->lock);
- return ret;
-}
-
-/*!
- * \note This function locks contexts list by &conlist, search for the rigt context
- * structure, leave context list locked and call ast_context_remove_switch2
- * which removes switch, unlock contexts list and return ...
- */
-int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
-{
- int ret = -1; /* default error return */
- struct ast_context *c = find_context_locked(context);
-
- if (c) {
- /* remove switch from this context ... */
- ret = ast_context_remove_switch2(c, sw, data, registrar);
- ast_unlock_contexts();
- }
- return ret;
-}
-
-/*!
- * \brief This function locks given context, removes switch, unlock context and
- * return.
- * \note When we call this function, &conlock lock must be locked, because when
- * we giving *con argument, some process can remove/change this context
- * and after that there can be segfault.
- *
- */
-int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
-{
- struct ast_sw *i;
- int ret = -1;
-
- ast_mutex_lock(&con->lock);
-
- /* walk switches */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
- if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
- (!registrar || !strcmp(i->registrar, registrar))) {
- /* found, remove from list */
- AST_LIST_REMOVE_CURRENT(&con->alts, list);
- free(i); /* free switch and return */
- ret = 0;
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
-
- ast_mutex_unlock(&con->lock);
-
- return ret;
-}
-
-/*
- * \note This functions lock contexts list, search for the right context,
- * call ast_context_remove_extension2, unlock contexts list and return.
- * In this function we are using
- */
-int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
-{
- return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
-}
-
-int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
-{
- int ret = -1; /* default error return */
- struct ast_context *c = find_context_locked(context);
-
- if (c) { /* ... remove extension ... */
- ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcid, registrar);
- ast_unlock_contexts();
- }
- return ret;
-}
-
-/*!
- * \brief This functionc locks given context, search for the right extension and
- * fires out all peer in this extensions with given priority. If priority
- * is set to 0, all peers are removed. After that, unlock context and
- * return.
- * \note When do you want to call this function, make sure that &conlock is locked,
- * because some process can handle with your *con context before you lock
- * it.
- *
- */
-int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar)
-{
- return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar);
-}
-
-int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
-{
- struct ast_exten *exten, *prev_exten = NULL;
- struct ast_exten *peer;
- struct ast_exten *previous_peer = NULL;
- struct ast_exten *next_peer = NULL;
- int found = 0;
-
- ast_mutex_lock(&con->lock);
-
- /* scan the extension list to find first matching extension-registrar */
- for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
- if (!strcmp(exten->exten, extension) &&
- (!registrar || !strcmp(exten->registrar, registrar)))
- break;
- }
- if (!exten) {
- /* we can't find right extension */
- ast_mutex_unlock(&con->lock);
- return -1;
- }
-
- /* scan the priority list to remove extension with exten->priority == priority */
- for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
- peer && !strcmp(peer->exten, extension);
- peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
- if ((priority == 0 || peer->priority == priority) &&
- (!callerid || !matchcid || (matchcid && !strcmp(peer->cidmatch, callerid))) &&
- (!registrar || !strcmp(peer->registrar, registrar) )) {
- found = 1;
-
- /* we are first priority extension? */
- if (!previous_peer) {
- /*
- * We are first in the priority chain, so must update the extension chain.
- * The next node is either the next priority or the next extension
- */
- struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
-
- if (!prev_exten) { /* change the root... */
- con->root = next_node;
- } else {
- prev_exten->next = next_node; /* unlink */
- }
- if (peer->peer) { /* update the new head of the pri list */
- peer->peer->next = peer->next;
- }
- } else { /* easy, we are not first priority in extension */
- previous_peer->peer = peer->peer;
- }
-
- /* now, free whole priority extension */
- destroy_exten(peer);
- } else {
- previous_peer = peer;
- }
- }
- ast_mutex_unlock(&con->lock);
- return found ? 0 : -1;
-}
-
-
-/*!
- * \note This function locks contexts list by &conlist, searches for the right context
- * structure, and locks the macrolock mutex in that context.
- * macrolock is used to limit a macro to be executed by one call at a time.
- */
-int ast_context_lockmacro(const char *context)
-{
- struct ast_context *c = NULL;
- int ret = -1;
-
- ast_rdlock_contexts();
-
- while ((c = ast_walk_contexts(c))) {
- if (!strcmp(ast_get_context_name(c), context)) {
- ret = 0;
- break;
- }
- }
-
- ast_unlock_contexts();
-
- /* if we found context, lock macrolock */
- if (ret == 0)
- ret = ast_mutex_lock(&c->macrolock);
-
- return ret;
-}
-
-/*!
- * \note This function locks contexts list by &conlist, searches for the right context
- * structure, and unlocks the macrolock mutex in that context.
- * macrolock is used to limit a macro to be executed by one call at a time.
- */
-int ast_context_unlockmacro(const char *context)
-{
- struct ast_context *c = NULL;
- int ret = -1;
-
- ast_rdlock_contexts();
-
- while ((c = ast_walk_contexts(c))) {
- if (!strcmp(ast_get_context_name(c), context)) {
- ret = 0;
- break;
- }
- }
-
- ast_unlock_contexts();
-
- /* if we found context, unlock macrolock */
- if (ret == 0)
- ret = ast_mutex_unlock(&c->macrolock);
-
- return ret;
-}
-
-/*! \brief Dynamically register a new dial plan application */
-int ast_register_application(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
-{
- struct ast_app *tmp, *cur = NULL;
- char tmps[80];
- int length;
-
- AST_LIST_LOCK(&apps);
- AST_LIST_TRAVERSE(&apps, tmp, list) {
- if (!strcasecmp(app, tmp->name)) {
- ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
- AST_LIST_UNLOCK(&apps);
- return -1;
- }
- }
-
- length = sizeof(*tmp) + strlen(app) + 1;
-
- if (!(tmp = ast_calloc(1, length))) {
- AST_LIST_UNLOCK(&apps);
- return -1;
- }
-
- strcpy(tmp->name, app);
- tmp->execute = execute;
- tmp->synopsis = synopsis;
- tmp->description = description;
-
- /* Store in alphabetical order */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
- if (strcasecmp(tmp->name, cur->name) < 0) {
- AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- if (!cur)
- AST_LIST_INSERT_TAIL(&apps, tmp, list);
-
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
-
- AST_LIST_UNLOCK(&apps);
-
- return 0;
-}
-
-/*
- * Append to the list. We don't have a tail pointer because we need
- * to scan the list anyways to check for duplicates during insertion.
- */
-int ast_register_switch(struct ast_switch *sw)
-{
- struct ast_switch *tmp;
-
- AST_LIST_LOCK(&switches);
- AST_LIST_TRAVERSE(&switches, tmp, list) {
- if (!strcasecmp(tmp->name, sw->name)) {
- AST_LIST_UNLOCK(&switches);
- ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
- return -1;
- }
- }
- AST_LIST_INSERT_TAIL(&switches, sw, list);
- AST_LIST_UNLOCK(&switches);
-
- return 0;
-}
-
-void ast_unregister_switch(struct ast_switch *sw)
-{
- AST_LIST_LOCK(&switches);
- AST_LIST_REMOVE(&switches, sw, list);
- AST_LIST_UNLOCK(&switches);
-}
-
-/*
- * Help for CLI commands ...
- */
-static char show_applications_help[] =
-"Usage: core show applications [{like|describing} <text>]\n"
-" List applications which are currently available.\n"
-" If 'like', <text> will be a substring of the app name\n"
-" If 'describing', <text> will be a substring of the description\n";
-
-static char show_functions_help[] =
-"Usage: core show functions [like <text>]\n"
-" List builtin functions, optionally only those matching a given string\n";
-
-static char show_switches_help[] =
-"Usage: core show switches\n"
-" List registered switches\n";
-
-static char show_hints_help[] =
-"Usage: core show hints\n"
-" List registered hints\n";
-
-static char show_globals_help[] =
-"Usage: core show globals\n"
-" List current global dialplan variables and their values\n";
-
-static char show_application_help[] =
-"Usage: core show application <application> [<application> [<application> [...]]]\n"
-" Describes a particular application.\n";
-
-static char show_function_help[] =
-"Usage: core show function <function>\n"
-" Describe a particular dialplan function.\n";
-
-static char show_dialplan_help[] =
-"Usage: dialplan show [exten@][context]\n"
-" Show dialplan\n";
-
-static char set_global_help[] =
-"Usage: core set global <name> <value>\n"
-" Set global dialplan variable <name> to <value>\n";
-
-
-/*
- * \brief 'show application' CLI command implementation functions ...
- */
-
-/*
- * There is a possibility to show informations about more than one
- * application at one time. You can type 'show application Dial Echo' and
- * you will see informations about these two applications ...
- */
-static char *complete_show_application(const char *line, const char *word, int pos, int state)
-{
- struct ast_app *a;
- char *ret = NULL;
- int which = 0;
- int wordlen = strlen(word);
-
- /* return the n-th [partial] matching entry */
- AST_LIST_LOCK(&apps);
- AST_LIST_TRAVERSE(&apps, a, list) {
- if (!strncasecmp(word, a->name, wordlen) && ++which > state) {
- ret = strdup(a->name);
- break;
- }
- }
- AST_LIST_UNLOCK(&apps);
-
- return ret;
-}
-
-static int handle_show_application_deprecated(int fd, int argc, char *argv[])
-{
- struct ast_app *a;
- int app, no_registered_app = 1;
-
- if (argc < 3)
- return RESULT_SHOWUSAGE;
-
- /* ... go through all applications ... */
- AST_LIST_LOCK(&apps);
- AST_LIST_TRAVERSE(&apps, a, list) {
- /* ... compare this application name with all arguments given
- * to 'show application' command ... */
- for (app = 2; app < argc; app++) {
- if (!strcasecmp(a->name, argv[app])) {
- /* Maximum number of characters added by terminal coloring is 22 */
- char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
- char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
- int synopsis_size, description_size;
-
- no_registered_app = 0;
-
- if (a->synopsis)
- synopsis_size = strlen(a->synopsis) + 23;
- else
- synopsis_size = strlen("Not available") + 23;
- synopsis = alloca(synopsis_size);
-
- if (a->description)
- description_size = strlen(a->description) + 23;
- else
- description_size = strlen("Not available") + 23;
- description = alloca(description_size);
-
- if (synopsis && description) {
- snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name);
- term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
- term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
- term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
- term_color(synopsis,
- a->synopsis ? a->synopsis : "Not available",
- COLOR_CYAN, 0, synopsis_size);
- term_color(description,
- a->description ? a->description : "Not available",
- COLOR_CYAN, 0, description_size);
-
- ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
- } else {
- /* ... one of our applications, show info ...*/
- ast_cli(fd,"\n -= Info about application '%s' =- \n\n"
- "[Synopsis]\n %s\n\n"
- "[Description]\n%s\n",
- a->name,
- a->synopsis ? a->synopsis : "Not available",
- a->description ? a->description : "Not available");
- }
- }
- }
- }
- AST_LIST_UNLOCK(&apps);
-
- /* we found at least one app? no? */
- if (no_registered_app) {
- ast_cli(fd, "Your application(s) is (are) not registered\n");
- return RESULT_FAILURE;
- }
-
- return RESULT_SUCCESS;
-}
-
-static int handle_show_application(int fd, int argc, char *argv[])
-{
- struct ast_app *a;
- int app, no_registered_app = 1;
-
- if (argc < 4)
- return RESULT_SHOWUSAGE;
-
- /* ... go through all applications ... */
- AST_LIST_LOCK(&apps);
- AST_LIST_TRAVERSE(&apps, a, list) {
- /* ... compare this application name with all arguments given
- * to 'show application' command ... */
- for (app = 3; app < argc; app++) {
- if (!strcasecmp(a->name, argv[app])) {
- /* Maximum number of characters added by terminal coloring is 22 */
- char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
- char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
- int synopsis_size, description_size;
-
- no_registered_app = 0;
-
- if (a->synopsis)
- synopsis_size = strlen(a->synopsis) + 23;
- else
- synopsis_size = strlen("Not available") + 23;
- synopsis = alloca(synopsis_size);
-
- if (a->description)
- description_size = strlen(a->description) + 23;
- else
- description_size = strlen("Not available") + 23;
- description = alloca(description_size);
-
- if (synopsis && description) {
- snprintf(info, 64 + AST_MAX_APP, "\n -= Info about application '%s' =- \n\n", a->name);
- term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
- term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
- term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
- term_color(synopsis,
- a->synopsis ? a->synopsis : "Not available",
- COLOR_CYAN, 0, synopsis_size);
- term_color(description,
- a->description ? a->description : "Not available",
- COLOR_CYAN, 0, description_size);
-
- ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
- } else {
- /* ... one of our applications, show info ...*/
- ast_cli(fd,"\n -= Info about application '%s' =- \n\n"
- "[Synopsis]\n %s\n\n"
- "[Description]\n%s\n",
- a->name,
- a->synopsis ? a->synopsis : "Not available",
- a->description ? a->description : "Not available");
- }
- }
- }
- }
- AST_LIST_UNLOCK(&apps);
-
- /* we found at least one app? no? */
- if (no_registered_app) {
- ast_cli(fd, "Your application(s) is (are) not registered\n");
- return RESULT_FAILURE;
- }
-
- return RESULT_SUCCESS;
-}
-
-/*! \brief handle_show_hints: CLI support for listing registred dial plan hints */
-static int handle_show_hints(int fd, int argc, char *argv[])
-{
- struct ast_hint *hint;
- int num = 0;
- int watchers;
- struct ast_state_cb *watcher;
-
- if (AST_LIST_EMPTY(&hints)) {
- ast_cli(fd, "There are no registered dialplan hints\n");
- return RESULT_SUCCESS;
- }
- /* ... we have hints ... */
- ast_cli(fd, "\n -= Registered Asterisk Dial Plan Hints =-\n");
- AST_LIST_LOCK(&hints);
- AST_LIST_TRAVERSE(&hints, hint, list) {
- watchers = 0;
- for (watcher = hint->callbacks; watcher; watcher = watcher->next)
- watchers++;
- ast_cli(fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n",
- ast_get_extension_name(hint->exten),
- ast_get_context_name(ast_get_extension_context(hint->exten)),
- ast_get_extension_app(hint->exten),
- ast_extension_state2str(hint->laststate), watchers);
- num++;
- }
- ast_cli(fd, "----------------\n");
- ast_cli(fd, "- %d hints registered\n", num);
- AST_LIST_UNLOCK(&hints);
- return RESULT_SUCCESS;
-}
-
-/*! \brief handle_show_switches: CLI support for listing registred dial plan switches */
-static int handle_show_switches(int fd, int argc, char *argv[])
-{
- struct ast_switch *sw;
-
- AST_LIST_LOCK(&switches);
-
- if (AST_LIST_EMPTY(&switches)) {
- AST_LIST_UNLOCK(&switches);
- ast_cli(fd, "There are no registered alternative switches\n");
- return RESULT_SUCCESS;
- }
-
- ast_cli(fd, "\n -= Registered Asterisk Alternative Switches =-\n");
- AST_LIST_TRAVERSE(&switches, sw, list)
- ast_cli(fd, "%s: %s\n", sw->name, sw->description);
-
- AST_LIST_UNLOCK(&switches);
-
- return RESULT_SUCCESS;
-}
-
-/*
- * 'show applications' CLI command implementation functions ...
- */
-static int handle_show_applications_deprecated(int fd, int argc, char *argv[])
-{
- struct ast_app *a;
- int like = 0, describing = 0;
- int total_match = 0; /* Number of matches in like clause */
- int total_apps = 0; /* Number of apps registered */
-
- AST_LIST_LOCK(&apps);
-
- if (AST_LIST_EMPTY(&apps)) {
- ast_cli(fd, "There are no registered applications\n");
- AST_LIST_UNLOCK(&apps);
- return -1;
- }
-
- /* show applications like <keyword> */
- if ((argc == 4) && (!strcmp(argv[2], "like"))) {
- like = 1;
- } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
- describing = 1;
- }
-
- /* show applications describing <keyword1> [<keyword2>] [...] */
- if ((!like) && (!describing)) {
- ast_cli(fd, " -= Registered Asterisk Applications =-\n");
- } else {
- ast_cli(fd, " -= Matching Asterisk Applications =-\n");
- }
-
- AST_LIST_TRAVERSE(&apps, a, list) {
- int printapp = 0;
- total_apps++;
- if (like) {
- if (strcasestr(a->name, argv[3])) {
- printapp = 1;
- total_match++;
- }
- } else if (describing) {
- if (a->description) {
- /* Match all words on command line */
- int i;
- printapp = 1;
- for (i = 3; i < argc; i++) {
- if (!strcasestr(a->description, argv[i])) {
- printapp = 0;
- } else {
- total_match++;
- }
- }
- }
- } else {
- printapp = 1;
- }
-
- if (printapp) {
- ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
- }
- }
- if ((!like) && (!describing)) {
- ast_cli(fd, " -= %d Applications Registered =-\n",total_apps);
- } else {
- ast_cli(fd, " -= %d Applications Matching =-\n",total_match);
- }
-
- AST_LIST_UNLOCK(&apps);
-
- return RESULT_SUCCESS;
-}
-static int handle_show_applications(int fd, int argc, char *argv[])
-{
- struct ast_app *a;
- int like = 0, describing = 0;
- int total_match = 0; /* Number of matches in like clause */
- int total_apps = 0; /* Number of apps registered */
-
- AST_LIST_LOCK(&apps);
-
- if (AST_LIST_EMPTY(&apps)) {
- ast_cli(fd, "There are no registered applications\n");
- AST_LIST_UNLOCK(&apps);
- return -1;
- }
-
- /* core list applications like <keyword> */
- if ((argc == 5) && (!strcmp(argv[3], "like"))) {
- like = 1;
- } else if ((argc > 4) && (!strcmp(argv[3], "describing"))) {
- describing = 1;
- }
-
- /* core list applications describing <keyword1> [<keyword2>] [...] */
- if ((!like) && (!describing)) {
- ast_cli(fd, " -= Registered Asterisk Applications =-\n");
- } else {
- ast_cli(fd, " -= Matching Asterisk Applications =-\n");
- }
-
- AST_LIST_TRAVERSE(&apps, a, list) {
- int printapp = 0;
- total_apps++;
- if (like) {
- if (strcasestr(a->name, argv[4])) {
- printapp = 1;
- total_match++;
- }
- } else if (describing) {
- if (a->description) {
- /* Match all words on command line */
- int i;
- printapp = 1;
- for (i = 4; i < argc; i++) {
- if (!strcasestr(a->description, argv[i])) {
- printapp = 0;
- } else {
- total_match++;
- }
- }
- }
- } else {
- printapp = 1;
- }
-
- if (printapp) {
- ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
- }
- }
- if ((!like) && (!describing)) {
- ast_cli(fd, " -= %d Applications Registered =-\n",total_apps);
- } else {
- ast_cli(fd, " -= %d Applications Matching =-\n",total_match);
- }
-
- AST_LIST_UNLOCK(&apps);
-
- return RESULT_SUCCESS;
-}
-
-static char *complete_show_applications_deprecated(const char *line, const char *word, int pos, int state)
-{
- static char* choices[] = { "like", "describing", NULL };
-
- return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
-}
-
-static char *complete_show_applications(const char *line, const char *word, int pos, int state)
-{
- static char* choices[] = { "like", "describing", NULL };
-
- return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
-}
-
-/*
- * 'show dialplan' CLI command implementation functions ...
- */
-static char *complete_show_dialplan_context(const char *line, const char *word, int pos,
- int state)
-{
- struct ast_context *c = NULL;
- char *ret = NULL;
- int which = 0;
- int wordlen;
-
- /* we are do completion of [exten@]context on second position only */
- if (pos != 2)
- return NULL;
-
- ast_rdlock_contexts();
-
- wordlen = strlen(word);
-
- /* walk through all contexts and return the n-th match */
- while ( (c = ast_walk_contexts(c)) ) {
- if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
- ret = ast_strdup(ast_get_context_name(c));
- break;
- }
- }
-
- ast_unlock_contexts();
-
- return ret;
-}
-
-struct dialplan_counters {
- int total_context;
- int total_exten;
- int total_prio;
- int context_existence;
- int extension_existence;
-};
-
-/*! \brief helper function to print an extension */
-static void print_ext(struct ast_exten *e, char * buf, int buflen)
-{
- int prio = ast_get_extension_priority(e);
- if (prio == PRIORITY_HINT) {
- snprintf(buf, buflen, "hint: %s",
- ast_get_extension_app(e));
- } else {
- snprintf(buf, buflen, "%d. %s(%s)",
- prio, ast_get_extension_app(e),
- (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
- }
-}
-
-/* XXX not verified */
-static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
-{
- struct ast_context *c = NULL;
- int res = 0, old_total_exten = dpc->total_exten;
-
- ast_rdlock_contexts();
-
- /* walk all contexts ... */
- while ( (c = ast_walk_contexts(c)) ) {
- struct ast_exten *e;
- struct ast_include *i;
- struct ast_ignorepat *ip;
- char buf[256], buf2[256];
- int context_info_printed = 0;
-
- if (context && strcmp(ast_get_context_name(c), context))
- continue; /* skip this one, name doesn't match */
-
- dpc->context_existence = 1;
-
- ast_lock_context(c);
-
- /* are we looking for exten too? if yes, we print context
- * only if we find our extension.
- * Otherwise print context even if empty ?
- * XXX i am not sure how the rinclude is handled.
- * I think it ought to go inside.
- */
- if (!exten) {
- dpc->total_context++;
- ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
- ast_get_context_name(c), ast_get_context_registrar(c));
- context_info_printed = 1;
- }
-
- /* walk extensions ... */
- e = NULL;
- while ( (e = ast_walk_context_extensions(c, e)) ) {
- struct ast_exten *p;
-
- if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
- continue; /* skip, extension match failed */
-
- dpc->extension_existence = 1;
-
- /* may we print context info? */
- if (!context_info_printed) {
- dpc->total_context++;
- if (rinclude) { /* TODO Print more info about rinclude */
- ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
- ast_get_context_name(c), ast_get_context_registrar(c));
- } else {
- ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
- ast_get_context_name(c), ast_get_context_registrar(c));
- }
- context_info_printed = 1;
- }
- dpc->total_prio++;
-
- /* write extension name and first peer */
- snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
-
- print_ext(e, buf2, sizeof(buf2));
-
- ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2,
- ast_get_extension_registrar(e));
-
- dpc->total_exten++;
- /* walk next extension peers */
- p = e; /* skip the first one, we already got it */
- while ( (p = ast_walk_extension_priorities(e, p)) ) {
- const char *el = ast_get_extension_label(p);
- dpc->total_prio++;
- if (el)
- snprintf(buf, sizeof(buf), " [%s]", el);
- else
- buf[0] = '\0';
- print_ext(p, buf2, sizeof(buf2));
-
- ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2,
- ast_get_extension_registrar(p));
- }
- }
-
- /* walk included and write info ... */
- i = NULL;
- while ( (i = ast_walk_context_includes(c, i)) ) {
- snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
- if (exten) {
- /* Check all includes for the requested extension */
- if (includecount >= AST_PBX_MAX_STACK) {
- ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n");
- } else {
- int dupe=0;
- int x;
- for (x=0;x<includecount;x++) {
- if (!strcasecmp(includes[x], ast_get_include_name(i))) {
- dupe++;
- break;
- }
- }
- if (!dupe) {
- includes[includecount] = ast_get_include_name(i);
- show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
- } else {
- ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
- }
- }
- } else {
- ast_cli(fd, " Include => %-45s [%s]\n",
- buf, ast_get_include_registrar(i));
- }
- }
-
- /* walk ignore patterns and write info ... */
- ip = NULL;
- while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
- const char *ipname = ast_get_ignorepat_name(ip);
- char ignorepat[AST_MAX_EXTENSION];
- snprintf(buf, sizeof(buf), "'%s'", ipname);
- snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
- if (!exten || ast_extension_match(ignorepat, exten)) {
- ast_cli(fd, " Ignore pattern => %-45s [%s]\n",
- buf, ast_get_ignorepat_registrar(ip));
- }
- }
- if (!rinclude) {
- struct ast_sw *sw = NULL;
- while ( (sw = ast_walk_context_switches(c, sw)) ) {
- snprintf(buf, sizeof(buf), "'%s/%s'",
- ast_get_switch_name(sw),
- ast_get_switch_data(sw));
- ast_cli(fd, " Alt. Switch => %-45s [%s]\n",
- buf, ast_get_switch_registrar(sw));
- }
- }
-
- ast_unlock_context(c);
-
- /* if we print something in context, make an empty line */
- if (context_info_printed)
- ast_cli(fd, "\r\n");
- }
- ast_unlock_contexts();
-
- return (dpc->total_exten == old_total_exten) ? -1 : res;
-}
-
-static int handle_show_dialplan(int fd, int argc, char *argv[])
-{
- char *exten = NULL, *context = NULL;
- /* Variables used for different counters */
- struct dialplan_counters counters;
-
- const char *incstack[AST_PBX_MAX_STACK];
- memset(&counters, 0, sizeof(counters));
-
- if (argc != 2 && argc != 3)
- return RESULT_SHOWUSAGE;
-
- /* we obtain [exten@]context? if yes, split them ... */
- if (argc == 3) {
- if (strchr(argv[2], '@')) { /* split into exten & context */
- context = ast_strdupa(argv[2]);
- exten = strsep(&context, "@");
- /* change empty strings to NULL */
- if (ast_strlen_zero(exten))
- exten = NULL;
- } else { /* no '@' char, only context given */
- context = argv[2];
- }
- if (ast_strlen_zero(context))
- context = NULL;
- }
- /* else Show complete dial plan, context and exten are NULL */
- show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
-
- /* check for input failure and throw some error messages */
- if (context && !counters.context_existence) {
- ast_cli(fd, "There is no existence of '%s' context\n", context);
- return RESULT_FAILURE;
- }
-
- if (exten && !counters.extension_existence) {
- if (context)
- ast_cli(fd, "There is no existence of %s@%s extension\n",
- exten, context);
- else
- ast_cli(fd,
- "There is no existence of '%s' extension in all contexts\n",
- exten);
- return RESULT_FAILURE;
- }
-
- ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n",
- counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
- counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
- counters.total_context, counters.total_context == 1 ? "context" : "contexts");
-
- /* everything ok */
- return RESULT_SUCCESS;
-}
-
-/*! \brief CLI support for listing global variables in a parseable way */
-static int handle_show_globals(int fd, int argc, char *argv[])
-{
- int i = 0;
- struct ast_var_t *newvariable;
-
- ast_mutex_lock(&globalslock);
- AST_LIST_TRAVERSE (&globals, newvariable, entries) {
- i++;
- ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
- }
- ast_mutex_unlock(&globalslock);
- ast_cli(fd, "\n -- %d variables\n", i);
-
- return RESULT_SUCCESS;
-}
-
-/*! \brief CLI support for setting global variables */
-static int handle_set_global_deprecated(int fd, int argc, char *argv[])
-{
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- pbx_builtin_setvar_helper(NULL, argv[2], argv[3]);
- ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[2], argv[3]);
-
- return RESULT_SUCCESS;
-}
-
-
-static int handle_set_global(int fd, int argc, char *argv[])
-{
- if (argc != 5)
- return RESULT_SHOWUSAGE;
-
- pbx_builtin_setvar_helper(NULL, argv[3], argv[4]);
- ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[3], argv[4]);
-
- return RESULT_SUCCESS;
-}
-
-
-
-/*
- * CLI entries for upper commands ...
- */
-static struct ast_cli_entry cli_show_applications_deprecated = {
- { "show", "applications", NULL },
- handle_show_applications_deprecated, NULL,
- NULL, complete_show_applications_deprecated };
-
-static struct ast_cli_entry cli_show_functions_deprecated = {
- { "show", "functions", NULL },
- handle_show_functions_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_switches_deprecated = {
- { "show", "switches", NULL },
- handle_show_switches, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_hints_deprecated = {
- { "show", "hints", NULL },
- handle_show_hints, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_globals_deprecated = {
- { "show", "globals", NULL },
- handle_show_globals, NULL,
- NULL };
-
-static struct ast_cli_entry cli_show_function_deprecated = {
- { "show" , "function", NULL },
- handle_show_function_deprecated, NULL,
- NULL, complete_show_function };
-
-static struct ast_cli_entry cli_show_application_deprecated = {
- { "show", "application", NULL },
- handle_show_application_deprecated, NULL,
- NULL, complete_show_application };
-
-static struct ast_cli_entry cli_show_dialplan_deprecated = {
- { "show", "dialplan", NULL },
- handle_show_dialplan, NULL,
- NULL, complete_show_dialplan_context };
-
-static struct ast_cli_entry cli_set_global_deprecated = {
- { "set", "global", NULL },
- handle_set_global_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry pbx_cli[] = {
- { { "core", "show", "applications", NULL },
- handle_show_applications, "Shows registered dialplan applications",
- show_applications_help, complete_show_applications, &cli_show_applications_deprecated },
-
- { { "core", "show", "functions", NULL },
- handle_show_functions, "Shows registered dialplan functions",
- show_functions_help, NULL, &cli_show_functions_deprecated },
-
- { { "core", "show", "switches", NULL },
- handle_show_switches, "Show alternative switches",
- show_switches_help, NULL, &cli_show_switches_deprecated },
-
- { { "core", "show", "hints", NULL },
- handle_show_hints, "Show dialplan hints",
- show_hints_help, NULL, &cli_show_hints_deprecated },
-
- { { "core", "show", "globals", NULL },
- handle_show_globals, "Show global dialplan variables",
- show_globals_help, NULL, &cli_show_globals_deprecated },
-
- { { "core", "show" , "function", NULL },
- handle_show_function, "Describe a specific dialplan function",
- show_function_help, complete_show_function, &cli_show_function_deprecated },
-
- { { "core", "show", "application", NULL },
- handle_show_application, "Describe a specific dialplan application",
- show_application_help, complete_show_application, &cli_show_application_deprecated },
-
- { { "core", "set", "global", NULL },
- handle_set_global, "Set global dialplan variable",
- set_global_help, NULL, &cli_set_global_deprecated },
-
- { { "dialplan", "show", NULL },
- handle_show_dialplan, "Show dialplan",
- show_dialplan_help, complete_show_dialplan_context, &cli_show_dialplan_deprecated },
-};
-
-int ast_unregister_application(const char *app)
-{
- struct ast_app *tmp;
-
- AST_LIST_LOCK(&apps);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
- if (!strcasecmp(app, tmp->name)) {
- AST_LIST_REMOVE_CURRENT(&apps, list);
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
- free(tmp);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&apps);
-
- return tmp ? 0 : -1;
-}
-
-static struct ast_context *__ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
-{
- struct ast_context *tmp, **local_contexts;
- int length = sizeof(struct ast_context) + strlen(name) + 1;
-
- if (!extcontexts) {
- ast_rdlock_contexts();
- local_contexts = &contexts;
- } else
- local_contexts = extcontexts;
-
- for (tmp = *local_contexts; tmp; tmp = tmp->next) {
- if (!strcasecmp(tmp->name, name)) {
- if (!existsokay) {
- ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
- tmp = NULL;
- }
- if (!extcontexts)
- ast_unlock_contexts();
- return tmp;
- }
- }
-
- if (!extcontexts)
- ast_unlock_contexts();
-
- if ((tmp = ast_calloc(1, length))) {
- ast_mutex_init(&tmp->lock);
- ast_mutex_init(&tmp->macrolock);
- strcpy(tmp->name, name);
- tmp->registrar = registrar;
- if (!extcontexts)
- ast_wrlock_contexts();
- tmp->next = *local_contexts;
- *local_contexts = tmp;
- if (!extcontexts)
- ast_unlock_contexts();
- if (option_debug)
- ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
- }
-
- return tmp;
-}
-
-struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
-{
- return __ast_context_create(extcontexts, name, registrar, 0);
-}
-
-struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar)
-{
- return __ast_context_create(extcontexts, name, registrar, 1);
-}
-void __ast_context_destroy(struct ast_context *con, const char *registrar);
-
-struct store_hint {
- char *context;
- char *exten;
- struct ast_state_cb *callbacks;
- int laststate;
- AST_LIST_ENTRY(store_hint) list;
- char data[1];
-};
-
-AST_LIST_HEAD(store_hints, store_hint);
-
-/* XXX this does not check that multiple contexts are merged */
-void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
-{
- struct ast_context *tmp, *lasttmp = NULL;
- struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
- struct store_hint *this;
- struct ast_hint *hint;
- struct ast_exten *exten;
- int length;
- struct ast_state_cb *thiscb, *prevcb;
-
- /* it is very important that this function hold the hint list lock _and_ the conlock
- during its operation; not only do we need to ensure that the list of contexts
- and extensions does not change, but also that no hint callbacks (watchers) are
- added or removed during the merge/delete process
-
- in addition, the locks _must_ be taken in this order, because there are already
- other code paths that use this order
- */
- ast_wrlock_contexts();
- AST_LIST_LOCK(&hints);
-
- /* preserve all watchers for hints associated with this registrar */
- AST_LIST_TRAVERSE(&hints, hint, list) {
- if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) {
- length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
- if (!(this = ast_calloc(1, length)))
- continue;
- this->callbacks = hint->callbacks;
- hint->callbacks = NULL;
- this->laststate = hint->laststate;
- this->context = this->data;
- strcpy(this->data, hint->exten->parent->name);
- this->exten = this->data + strlen(this->context) + 1;
- strcpy(this->exten, hint->exten->exten);
- AST_LIST_INSERT_HEAD(&store, this, list);
- }
- }
-
- tmp = *extcontexts;
- if (registrar) {
- /* XXX remove previous contexts from same registrar */
- if (option_debug)
- ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar);
- __ast_context_destroy(NULL,registrar);
- while (tmp) {
- lasttmp = tmp;
- tmp = tmp->next;
- }
- } else {
- /* XXX remove contexts with the same name */
- while (tmp) {
- ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar);
- __ast_context_destroy(tmp,tmp->registrar);
- lasttmp = tmp;
- tmp = tmp->next;
- }
- }
- if (lasttmp) {
- lasttmp->next = contexts;
- contexts = *extcontexts;
- *extcontexts = NULL;
- } else
- ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
-
- /* restore the watchers for hints that can be found; notify those that
- cannot be restored
- */
- while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
- struct pbx_find_info q = { .stacklen = 0 };
- exten = pbx_find_extension(NULL, NULL, &q, this->context, this->exten, PRIORITY_HINT, NULL, "", E_MATCH);
- /* Find the hint in the list of hints */
- AST_LIST_TRAVERSE(&hints, hint, list) {
- if (hint->exten == exten)
- break;
- }
- if (!exten || !hint) {
- /* this hint has been removed, notify the watchers */
- prevcb = NULL;
- thiscb = this->callbacks;
- while (thiscb) {
- prevcb = thiscb;
- thiscb = thiscb->next;
- prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
- free(prevcb);
- }
- } else {
- thiscb = this->callbacks;
- while (thiscb->next)
- thiscb = thiscb->next;
- thiscb->next = hint->callbacks;
- hint->callbacks = this->callbacks;
- hint->laststate = this->laststate;
- }
- free(this);
- }
-
- AST_LIST_UNLOCK(&hints);
- ast_unlock_contexts();
-
- return;
-}
-
-/*
- * errno values
- * EBUSY - can't lock
- * ENOENT - no existence of context
- */
-int ast_context_add_include(const char *context, const char *include, const char *registrar)
-{
- int ret = -1;
- struct ast_context *c = find_context_locked(context);
-
- if (c) {
- ret = ast_context_add_include2(c, include, registrar);
- ast_unlock_contexts();
- }
- return ret;
-}
-
-/*! \brief Helper for get_range.
- * return the index of the matching entry, starting from 1.
- * If names is not supplied, try numeric values.
- */
-static int lookup_name(const char *s, char *const names[], int max)
-{
- int i;
-
- if (names) {
- for (i = 0; names[i]; i++) {
- if (!strcasecmp(s, names[i]))
- return i+1;
- }
- } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
- return i;
- }
- return 0; /* error return */
-}
-
-/*! \brief helper function to return a range up to max (7, 12, 31 respectively).
- * names, if supplied, is an array of names that should be mapped to numbers.
- */
-static unsigned get_range(char *src, int max, char *const names[], const char *msg)
-{
- int s, e; /* start and ending position */
- unsigned int mask = 0;
-
- /* Check for whole range */
- if (ast_strlen_zero(src) || !strcmp(src, "*")) {
- s = 0;
- e = max - 1;
- } else {
- /* Get start and ending position */
- char *c = strchr(src, '-');
- if (c)
- *c++ = '\0';
- /* Find the start */
- s = lookup_name(src, names, max);
- if (!s) {
- ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
- return 0;
- }
- s--;
- if (c) { /* find end of range */
- e = lookup_name(c, names, max);
- if (!e) {
- ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
- return 0;
- }
- e--;
- } else
- e = s;
- }
- /* Fill the mask. Remember that ranges are cyclic */
- mask = 1 << e; /* initialize with last element */
- while (s != e) {
- if (s >= max) {
- s = 0;
- mask |= (1 << s);
- } else {
- mask |= (1 << s);
- s++;
- }
- }
- return mask;
-}
-
-/*! \brief store a bitmask of valid times, one bit each 2 minute */
-static void get_timerange(struct ast_timing *i, char *times)
-{
- char *e;
- int x;
- int s1, s2;
- int e1, e2;
- /* int cth, ctm; */
-
- /* start disabling all times, fill the fields with 0's, as they may contain garbage */
- memset(i->minmask, 0, sizeof(i->minmask));
-
- /* 2-minutes per bit, since the mask has only 32 bits :( */
- /* Star is all times */
- if (ast_strlen_zero(times) || !strcmp(times, "*")) {
- for (x=0; x<24; x++)
- i->minmask[x] = 0x3fffffff; /* 30 bits */
- return;
- }
- /* Otherwise expect a range */
- e = strchr(times, '-');
- if (!e) {
- ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
- return;
- }
- *e++ = '\0';
- /* XXX why skip non digits ? */
- while (*e && !isdigit(*e))
- e++;
- if (!*e) {
- ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n");
- return;
- }
- if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
- ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times);
- return;
- }
- if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
- ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e);
- return;
- }
- /* XXX this needs to be optimized */
-#if 1
- s1 = s1 * 30 + s2/2;
- if ((s1 < 0) || (s1 >= 24*30)) {
- ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
- return;
- }
- e1 = e1 * 30 + e2/2;
- if ((e1 < 0) || (e1 >= 24*30)) {
- ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
- return;
- }
- /* Go through the time and enable each appropriate bit */
- for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
- i->minmask[x/30] |= (1 << (x % 30));
- }
- /* Do the last one */
- i->minmask[x/30] |= (1 << (x % 30));
-#else
- for (cth=0; cth<24; cth++) {
- /* Initialize masks to blank */
- i->minmask[cth] = 0;
- for (ctm=0; ctm<30; ctm++) {
- if (
- /* First hour with more than one hour */
- (((cth == s1) && (ctm >= s2)) &&
- ((cth < e1)))
- /* Only one hour */
- || (((cth == s1) && (ctm >= s2)) &&
- ((cth == e1) && (ctm <= e2)))
- /* In between first and last hours (more than 2 hours) */
- || ((cth > s1) &&
- (cth < e1))
- /* Last hour with more than one hour */
- || ((cth > s1) &&
- ((cth == e1) && (ctm <= e2)))
- )
- i->minmask[cth] |= (1 << (ctm / 2));
- }
- }
-#endif
- /* All done */
- return;
-}
-
-static char *days[] =
-{
- "sun",
- "mon",
- "tue",
- "wed",
- "thu",
- "fri",
- "sat",
- NULL,
-};
-
-static char *months[] =
-{
- "jan",
- "feb",
- "mar",
- "apr",
- "may",
- "jun",
- "jul",
- "aug",
- "sep",
- "oct",
- "nov",
- "dec",
- NULL,
-};
-
-int ast_build_timing(struct ast_timing *i, const char *info_in)
-{
- char info_save[256];
- char *info;
-
- /* Check for empty just in case */
- if (ast_strlen_zero(info_in))
- return 0;
- /* make a copy just in case we were passed a static string */
- ast_copy_string(info_save, info_in, sizeof(info_save));
- info = info_save;
- /* Assume everything except time */
- i->monthmask = 0xfff; /* 12 bits */
- i->daymask = 0x7fffffffU; /* 31 bits */
- i->dowmask = 0x7f; /* 7 bits */
- /* on each call, use strsep() to move info to the next argument */
- get_timerange(i, strsep(&info, "|"));
- if (info)
- i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week");
- if (info)
- i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day");
- if (info)
- i->monthmask = get_range(strsep(&info, "|"), 12, months, "month");
- return 1;
-}
-
-int ast_check_timing(const struct ast_timing *i)
-{
- struct tm tm;
- time_t t = time(NULL);
-
- ast_localtime(&t, &tm, NULL);
-
- /* If it's not the right month, return */
- if (!(i->monthmask & (1 << tm.tm_mon)))
- return 0;
-
- /* If it's not that time of the month.... */
- /* Warning, tm_mday has range 1..31! */
- if (!(i->daymask & (1 << (tm.tm_mday-1))))
- return 0;
-
- /* If it's not the right day of the week */
- if (!(i->dowmask & (1 << tm.tm_wday)))
- return 0;
-
- /* Sanity check the hour just to be safe */
- if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
- ast_log(LOG_WARNING, "Insane time...\n");
- return 0;
- }
-
- /* Now the tough part, we calculate if it fits
- in the right time based on min/hour */
- if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
- return 0;
-
- /* If we got this far, then we're good */
- return 1;
-}
-
-/*
- * errno values
- * ENOMEM - out of memory
- * EBUSY - can't lock
- * EEXIST - already included
- * EINVAL - there is no existence of context for inclusion
- */
-int ast_context_add_include2(struct ast_context *con, const char *value,
- const char *registrar)
-{
- struct ast_include *new_include;
- char *c;
- struct ast_include *i, *il = NULL; /* include, include_last */
- int length;
- char *p;
-
- length = sizeof(struct ast_include);
- length += 2 * (strlen(value) + 1);
-
- /* allocate new include structure ... */
- if (!(new_include = ast_calloc(1, length)))
- return -1;
- /* Fill in this structure. Use 'p' for assignments, as the fields
- * in the structure are 'const char *'
- */
- p = new_include->stuff;
- new_include->name = p;
- strcpy(p, value);
- p += strlen(value) + 1;
- new_include->rname = p;
- strcpy(p, value);
- /* Strip off timing info, and process if it is there */
- if ( (c = strchr(p, '|')) ) {
- *c++ = '\0';
- new_include->hastime = ast_build_timing(&(new_include->timing), c);
- }
- new_include->next = NULL;
- new_include->registrar = registrar;
-
- ast_mutex_lock(&con->lock);
-
- /* ... go to last include and check if context is already included too... */
- for (i = con->includes; i; i = i->next) {
- if (!strcasecmp(i->name, new_include->name)) {
- free(new_include);
- ast_mutex_unlock(&con->lock);
- errno = EEXIST;
- return -1;
- }
- il = i;
- }
-
- /* ... include new context into context list, unlock, return */
- if (il)
- il->next = new_include;
- else
- con->includes = new_include;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
- ast_mutex_unlock(&con->lock);
-
- return 0;
-}
-
-/*
- * errno values
- * EBUSY - can't lock
- * ENOENT - no existence of context
- */
-int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
-{
- int ret = -1;
- struct ast_context *c = find_context_locked(context);
-
- if (c) { /* found, add switch to this context */
- ret = ast_context_add_switch2(c, sw, data, eval, registrar);
- ast_unlock_contexts();
- }
- return ret;
-}
-
-/*
- * errno values
- * ENOMEM - out of memory
- * EBUSY - can't lock
- * EEXIST - already included
- * EINVAL - there is no existence of context for inclusion
- */
-int ast_context_add_switch2(struct ast_context *con, const char *value,
- const char *data, int eval, const char *registrar)
-{
- struct ast_sw *new_sw;
- struct ast_sw *i;
- int length;
- char *p;
-
- length = sizeof(struct ast_sw);
- length += strlen(value) + 1;
- if (data)
- length += strlen(data);
- length++;
-
- /* allocate new sw structure ... */
- if (!(new_sw = ast_calloc(1, length)))
- return -1;
- /* ... fill in this structure ... */
- p = new_sw->stuff;
- new_sw->name = p;
- strcpy(new_sw->name, value);
- p += strlen(value) + 1;
- new_sw->data = p;
- if (data) {
- strcpy(new_sw->data, data);
- p += strlen(data) + 1;
- } else {
- strcpy(new_sw->data, "");
- p++;
- }
- new_sw->eval = eval;
- new_sw->registrar = registrar;
-
- /* ... try to lock this context ... */
- ast_mutex_lock(&con->lock);
-
- /* ... go to last sw and check if context is already swd too... */
- AST_LIST_TRAVERSE(&con->alts, i, list) {
- if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
- free(new_sw);
- ast_mutex_unlock(&con->lock);
- errno = EEXIST;
- return -1;
- }
- }
-
- /* ... sw new context into context list, unlock, return */
- AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
-
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
-
- ast_mutex_unlock(&con->lock);
-
- return 0;
-}
-
-/*
- * EBUSY - can't lock
- * ENOENT - there is not context existence
- */
-int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)
-{
- int ret = -1;
- struct ast_context *c = find_context_locked(context);
-
- if (c) {
- ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
- ast_unlock_contexts();
- }
- return ret;
-}
-
-int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
-{
- struct ast_ignorepat *ip, *ipl = NULL;
-
- ast_mutex_lock(&con->lock);
-
- for (ip = con->ignorepats; ip; ip = ip->next) {
- if (!strcmp(ip->pattern, ignorepat) &&
- (!registrar || (registrar == ip->registrar))) {
- if (ipl) {
- ipl->next = ip->next;
- free(ip);
- } else {
- con->ignorepats = ip->next;
- free(ip);
- }
- ast_mutex_unlock(&con->lock);
- return 0;
- }
- ipl = ip;
- }
-
- ast_mutex_unlock(&con->lock);
- errno = EINVAL;
- return -1;
-}
-
-/*
- * EBUSY - can't lock
- * ENOENT - there is no existence of context
- */
-int ast_context_add_ignorepat(const char *context, const char *value, const char *registrar)
-{
- int ret = -1;
- struct ast_context *c = find_context_locked(context);
-
- if (c) {
- ret = ast_context_add_ignorepat2(c, value, registrar);
- ast_unlock_contexts();
- }
- return ret;
-}
-
-int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
-{
- struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
- int length;
- char *pattern;
- length = sizeof(struct ast_ignorepat);
- length += strlen(value) + 1;
- if (!(ignorepat = ast_calloc(1, length)))
- return -1;
- /* The cast to char * is because we need to write the initial value.
- * The field is not supposed to be modified otherwise. Also, gcc 4.2
- * sees the cast as dereferencing a type-punned pointer and warns about
- * it. This is the workaround (we're telling gcc, yes, that's really
- * what we wanted to do).
- */
- pattern = (char *) ignorepat->pattern;
- strcpy(pattern, value);
- ignorepat->next = NULL;
- ignorepat->registrar = registrar;
- ast_mutex_lock(&con->lock);
- for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
- ignorepatl = ignorepatc;
- if (!strcasecmp(ignorepatc->pattern, value)) {
- /* Already there */
- ast_mutex_unlock(&con->lock);
- errno = EEXIST;
- return -1;
- }
- }
- if (ignorepatl)
- ignorepatl->next = ignorepat;
- else
- con->ignorepats = ignorepat;
- ast_mutex_unlock(&con->lock);
- return 0;
-
-}
-
-int ast_ignore_pattern(const char *context, const char *pattern)
-{
- struct ast_context *con = ast_context_find(context);
- if (con) {
- struct ast_ignorepat *pat;
- for (pat = con->ignorepats; pat; pat = pat->next) {
- if (ast_extension_match(pat->pattern, pattern))
- return 1;
- }
- }
-
- return 0;
-}
-
-/*
- * EBUSY - can't lock
- * ENOENT - no existence of context
- *
- */
-int ast_add_extension(const char *context, int replace, const char *extension,
- int priority, const char *label, const char *callerid,
- const char *application, void *data, void (*datad)(void *), const char *registrar)
-{
- int ret = -1;
- struct ast_context *c = find_context_locked(context);
-
- if (c) {
- ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
- application, data, datad, registrar);
- ast_unlock_contexts();
- }
- return ret;
-}
-
-int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
-{
- if (!chan)
- return -1;
-
- ast_channel_lock(chan);
-
- if (!ast_strlen_zero(context))
- ast_copy_string(chan->context, context, sizeof(chan->context));
- if (!ast_strlen_zero(exten))
- ast_copy_string(chan->exten, exten, sizeof(chan->exten));
- if (priority > -1) {
- chan->priority = priority;
- /* see flag description in channel.h for explanation */
- if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
- chan->priority--;
- }
-
- ast_channel_unlock(chan);
-
- return 0;
-}
-
-int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
-{
- int res = 0;
-
- ast_channel_lock(chan);
-
- if (chan->pbx) { /* This channel is currently in the PBX */
- ast_explicit_goto(chan, context, exten, priority);
- ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
- } else {
- /* In order to do it when the channel doesn't really exist within
- the PBX, we have to make a new channel, masquerade, and start the PBX
- at the new location */
- struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
- if (!tmpchan) {
- res = -1;
- } else {
- if (chan->cdr) {
- ast_cdr_discard(tmpchan->cdr);
- tmpchan->cdr = ast_cdr_dup(chan->cdr); /* share the love */
- }
- /* Make formats okay */
- tmpchan->readformat = chan->readformat;
- tmpchan->writeformat = chan->writeformat;
- /* Setup proper location */
- ast_explicit_goto(tmpchan,
- S_OR(context, chan->context), S_OR(exten, chan->exten), priority);
-
- /* Masquerade into temp channel */
- if (ast_channel_masquerade(tmpchan, chan)) {
- /* Failed to set up the masquerade. It's probably chan_local
- * in the middle of optimizing itself out. Sad. :( */
- ast_hangup(tmpchan);
- tmpchan = NULL;
- res = -1;
- } else {
- /* Grab the locks and get going */
- ast_channel_lock(tmpchan);
- ast_do_masquerade(tmpchan);
- ast_channel_unlock(tmpchan);
- /* Start the PBX going on our stolen channel */
- if (ast_pbx_start(tmpchan)) {
- ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
- ast_hangup(tmpchan);
- res = -1;
- }
- }
- }
- }
- ast_channel_unlock(chan);
- return res;
-}
-
-int ast_async_goto_by_name(const char *channame, const char *context, const char *exten, int priority)
-{
- struct ast_channel *chan;
- int res = -1;
-
- chan = ast_get_channel_by_name_locked(channame);
- if (chan) {
- res = ast_async_goto(chan, context, exten, priority);
- ast_channel_unlock(chan);
- }
- return res;
-}
-
-/*! \brief copy a string skipping whitespace */
-static int ext_strncpy(char *dst, const char *src, int len)
-{
- int count=0;
-
- while (*src && (count < len - 1)) {
- switch(*src) {
- case ' ':
- /* otherwise exten => [a-b],1,... doesn't work */
- /* case '-': */
- /* Ignore */
- break;
- default:
- *dst = *src;
- dst++;
- }
- src++;
- count++;
- }
- *dst = '\0';
-
- return count;
-}
-
-/*! \brief add the extension in the priority chain.
- * returns 0 on success, -1 on failure
- */
-static int add_pri(struct ast_context *con, struct ast_exten *tmp,
- struct ast_exten *el, struct ast_exten *e, int replace)
-{
- struct ast_exten *ep;
-
- for (ep = NULL; e ; ep = e, e = e->peer) {
- if (e->priority >= tmp->priority)
- break;
- }
- if (!e) { /* go at the end, and ep is surely set because the list is not empty */
- ep->peer = tmp;
- return 0; /* success */
- }
- if (e->priority == tmp->priority) {
- /* Can't have something exactly the same. Is this a
- replacement? If so, replace, otherwise, bonk. */
- if (!replace) {
- ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
- if (tmp->datad)
- tmp->datad(tmp->data);
- free(tmp);
- return -1;
- }
- /* we are replacing e, so copy the link fields and then update
- * whoever pointed to e to point to us
- */
- tmp->next = e->next; /* not meaningful if we are not first in the peer list */
- tmp->peer = e->peer; /* always meaningful */
- if (ep) /* We're in the peer list, just insert ourselves */
- ep->peer = tmp;
- else if (el) /* We're the first extension. Take over e's functions */
- el->next = tmp;
- else /* We're the very first extension. */
- con->root = tmp;
- if (tmp->priority == PRIORITY_HINT)
- ast_change_hint(e,tmp);
- /* Destroy the old one */
- if (e->datad)
- e->datad(e->data);
- free(e);
- } else { /* Slip ourselves in just before e */
- tmp->peer = e;
- tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
- if (ep) /* Easy enough, we're just in the peer list */
- ep->peer = tmp;
- else { /* we are the first in some peer list, so link in the ext list */
- if (el)
- el->next = tmp; /* in the middle... */
- else
- con->root = tmp; /* ... or at the head */
- e->next = NULL; /* e is no more at the head, so e->next must be reset */
- }
- /* And immediately return success. */
- if (tmp->priority == PRIORITY_HINT)
- ast_add_hint(tmp);
- }
- return 0;
-}
-
-/*! \brief
- * Main interface to add extensions to the list for out context.
- *
- * We sort extensions in order of matching preference, so that we can
- * stop the search as soon as we find a suitable match.
- * This ordering also takes care of wildcards such as '.' (meaning
- * "one or more of any character") and '!' (which is 'earlymatch',
- * meaning "zero or more of any character" but also impacts the
- * return value from CANMATCH and EARLYMATCH.
- *
- * The extension match rules defined in the devmeeting 2006.05.05 are
- * quite simple: WE SELECT THE LONGEST MATCH.
- * In detail, "longest" means the number of matched characters in
- * the extension. In case of ties (e.g. _XXX and 333) in the length
- * of a pattern, we give priority to entries with the smallest cardinality
- * (e.g, [5-9] comes before [2-8] before the former has only 5 elements,
- * while the latter has 7, etc.
- * In case of same cardinality, the first element in the range counts.
- * If we still have a tie, any final '!' will make this as a possibly
- * less specific pattern.
- *
- * EBUSY - can't lock
- * EEXIST - extension with the same priority exist and no replace is set
- *
- */
-int ast_add_extension2(struct ast_context *con,
- int replace, const char *extension, int priority, const char *label, const char *callerid,
- const char *application, void *data, void (*datad)(void *),
- const char *registrar)
-{
- /*
- * Sort extensions (or patterns) according to the rules indicated above.
- * These are implemented by the function ext_cmp()).
- * All priorities for the same ext/pattern/cid are kept in a list,
- * using the 'peer' field as a link field..
- */
- struct ast_exten *tmp, *e, *el = NULL;
- int res;
- int length;
- char *p;
- char expand_buf[VAR_BUF_SIZE] = { 0, };
-
- /* if we are adding a hint, and there are global variables, and the hint
- contains variable references, then expand them
- */
- ast_mutex_lock(&globalslock);
- if (priority == PRIORITY_HINT && AST_LIST_FIRST(&globals) && strstr(application, "${")) {
- pbx_substitute_variables_varshead(&globals, application, expand_buf, sizeof(expand_buf));
- application = expand_buf;
- }
- ast_mutex_unlock(&globalslock);
-
- length = sizeof(struct ast_exten);
- length += strlen(extension) + 1;
- length += strlen(application) + 1;
- if (label)
- length += strlen(label) + 1;
- if (callerid)
- length += strlen(callerid) + 1;
- else
- length ++; /* just the '\0' */
-
- /* Be optimistic: Build the extension structure first */
- if (!(tmp = ast_calloc(1, length)))
- return -1;
-
- /* use p as dst in assignments, as the fields are const char * */
- p = tmp->stuff;
- if (label) {
- tmp->label = p;
- strcpy(p, label);
- p += strlen(label) + 1;
- }
- tmp->exten = p;
- p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
- tmp->priority = priority;
- tmp->cidmatch = p; /* but use p for assignments below */
- if (callerid) {
- p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
- tmp->matchcid = 1;
- } else {
- *p++ = '\0';
- tmp->matchcid = 0;
- }
- tmp->app = p;
- strcpy(p, application);
- tmp->parent = con;
- tmp->data = data;
- tmp->datad = datad;
- tmp->registrar = registrar;
-
- ast_mutex_lock(&con->lock);
- res = 0; /* some compilers will think it is uninitialized otherwise */
- for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
- res = ext_cmp(e->exten, tmp->exten);
- if (res == 0) { /* extension match, now look at cidmatch */
- if (!e->matchcid && !tmp->matchcid)
- res = 0;
- else if (tmp->matchcid && !e->matchcid)
- res = 1;
- else if (e->matchcid && !tmp->matchcid)
- res = -1;
- else
- res = strcasecmp(e->cidmatch, tmp->cidmatch);
- }
- if (res >= 0)
- break;
- }
- if (e && res == 0) { /* exact match, insert in the pri chain */
- res = add_pri(con, tmp, el, e, replace);
- ast_mutex_unlock(&con->lock);
- if (res < 0) {
- errno = EEXIST; /* XXX do we care ? */
- return 0; /* XXX should we return -1 maybe ? */
- }
- } else {
- /*
- * not an exact match, this is the first entry with this pattern,
- * so insert in the main list right before 'e' (if any)
- */
- tmp->next = e;
- if (el)
- el->next = tmp;
- else
- con->root = tmp;
- ast_mutex_unlock(&con->lock);
- if (tmp->priority == PRIORITY_HINT)
- ast_add_hint(tmp);
- }
- if (option_debug) {
- if (tmp->matchcid) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s\n",
- tmp->exten, tmp->priority, tmp->cidmatch, con->name);
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s\n",
- tmp->exten, tmp->priority, con->name);
- }
- }
- if (option_verbose > 2) {
- if (tmp->matchcid) {
- ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d (CID match '%s')to %s\n",
- tmp->exten, tmp->priority, tmp->cidmatch, con->name);
- } else {
- ast_verbose( VERBOSE_PREFIX_3 "Added extension '%s' priority %d to %s\n",
- tmp->exten, tmp->priority, con->name);
- }
- }
- return 0;
-}
-
-struct async_stat {
- pthread_t p;
- struct ast_channel *chan;
- char context[AST_MAX_CONTEXT];
- char exten[AST_MAX_EXTENSION];
- int priority;
- int timeout;
- char app[AST_MAX_EXTENSION];
- char appdata[1024];
-};
-
-static void *async_wait(void *data)
-{
- struct async_stat *as = data;
- struct ast_channel *chan = as->chan;
- int timeout = as->timeout;
- int res;
- struct ast_frame *f;
- struct ast_app *app;
-
- while (timeout && (chan->_state != AST_STATE_UP)) {
- res = ast_waitfor(chan, timeout);
- if (res < 1)
- break;
- if (timeout > -1)
- timeout = res;
- f = ast_read(chan);
- if (!f)
- break;
- if (f->frametype == AST_FRAME_CONTROL) {
- if ((f->subclass == AST_CONTROL_BUSY) ||
- (f->subclass == AST_CONTROL_CONGESTION) ) {
- ast_frfree(f);
- break;
- }
- }
- ast_frfree(f);
- }
- if (chan->_state == AST_STATE_UP) {
- if (!ast_strlen_zero(as->app)) {
- app = pbx_findapp(as->app);
- if (app) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
- pbx_exec(chan, app, as->appdata);
- } else
- ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
- } else {
- if (!ast_strlen_zero(as->context))
- ast_copy_string(chan->context, as->context, sizeof(chan->context));
- if (!ast_strlen_zero(as->exten))
- ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
- if (as->priority > 0)
- chan->priority = as->priority;
- /* Run the PBX */
- if (ast_pbx_run(chan)) {
- ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
- } else {
- /* PBX will have taken care of this */
- chan = NULL;
- }
- }
- }
- free(as);
- if (chan)
- ast_hangup(chan);
- return NULL;
-}
-
-/*! Function to post an empty cdr after a spool call fails.
- *
- * This function posts an empty cdr for a failed spool call
- *
- */
-static int ast_pbx_outgoing_cdr_failed(void)
-{
- /* allocate a channel */
- struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", "");
-
- if (!chan)
- return -1; /* failure */
-
- if (!chan->cdr) {
- /* allocation of the cdr failed */
- ast_channel_free(chan); /* free the channel */
- return -1; /* return failure */
- }
-
- /* allocation of the cdr was successful */
- ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
- ast_cdr_start(chan->cdr); /* record the start and stop time */
- ast_cdr_end(chan->cdr);
- ast_cdr_failed(chan->cdr); /* set the status to failed */
- ast_cdr_detach(chan->cdr); /* post and free the record */
- chan->cdr = NULL;
- ast_channel_free(chan); /* free the channel */
-
- return 0; /* success */
-}
-
-int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
-{
- struct ast_channel *chan;
- struct async_stat *as;
- int res = -1, cdr_res = -1;
- struct outgoing_helper oh;
- pthread_attr_t attr;
-
- if (sync) {
- LOAD_OH(oh);
- chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
- if (channel) {
- *channel = chan;
- if (chan)
- ast_channel_lock(chan);
- }
- if (chan) {
- if (chan->_state == AST_STATE_UP) {
- res = 0;
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
-
- if (sync > 1) {
- if (channel)
- ast_channel_unlock(chan);
- if (ast_pbx_run(chan)) {
- ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
- if (channel)
- *channel = NULL;
- ast_hangup(chan);
- chan = NULL;
- res = -1;
- }
- } else {
- if (ast_pbx_start(chan)) {
- ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
- if (channel) {
- *channel = NULL;
- ast_channel_unlock(chan);
- }
- ast_hangup(chan);
- res = -1;
- }
- chan = NULL;
- }
- } else {
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
-
- if (chan->cdr) { /* update the cdr */
- /* here we update the status of the call, which sould be busy.
- * if that fails then we set the status to failed */
- if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
- ast_cdr_failed(chan->cdr);
- }
-
- if (channel) {
- *channel = NULL;
- ast_channel_unlock(chan);
- }
- ast_hangup(chan);
- chan = NULL;
- }
- }
-
- if (res < 0) { /* the call failed for some reason */
- if (*reason == 0) { /* if the call failed (not busy or no answer)
- * update the cdr with the failed message */
- cdr_res = ast_pbx_outgoing_cdr_failed();
- if (cdr_res != 0) {
- res = cdr_res;
- goto outgoing_exten_cleanup;
- }
- }
-
- /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
- /* check if "failed" exists */
- if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
- chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
- if (chan) {
- char failed_reason[4] = "";
- if (!ast_strlen_zero(context))
- ast_copy_string(chan->context, context, sizeof(chan->context));
- set_ext_pri(chan, "failed", 1);
- ast_set_variables(chan, vars);
- snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
- pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
- if (account)
- ast_cdr_setaccount(chan, account);
- if (ast_pbx_run(chan)) {
- ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
- ast_hangup(chan);
- }
- chan = NULL;
- }
- }
- }
- } else {
- if (!(as = ast_calloc(1, sizeof(*as)))) {
- res = -1;
- goto outgoing_exten_cleanup;
- }
- chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
- if (channel) {
- *channel = chan;
- if (chan)
- ast_channel_lock(chan);
- }
- if (!chan) {
- free(as);
- res = -1;
- goto outgoing_exten_cleanup;
- }
- as->chan = chan;
- ast_copy_string(as->context, context, sizeof(as->context));
- set_ext_pri(as->chan, exten, priority);
- as->timeout = timeout;
- ast_set_variables(chan, vars);
- if (account)
- ast_cdr_setaccount(chan, account);
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
- ast_log(LOG_WARNING, "Failed to start async wait\n");
- free(as);
- if (channel) {
- *channel = NULL;
- ast_channel_unlock(chan);
- }
- ast_hangup(chan);
- res = -1;
- pthread_attr_destroy(&attr);
- goto outgoing_exten_cleanup;
- }
- pthread_attr_destroy(&attr);
- res = 0;
- }
-outgoing_exten_cleanup:
- ast_variables_destroy(vars);
- return res;
-}
-
-struct app_tmp {
- char app[256];
- char data[256];
- struct ast_channel *chan;
- pthread_t t;
-};
-
-/*! \brief run the application and free the descriptor once done */
-static void *ast_pbx_run_app(void *data)
-{
- struct app_tmp *tmp = data;
- struct ast_app *app;
- app = pbx_findapp(tmp->app);
- if (app) {
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_4 "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
- pbx_exec(tmp->chan, app, tmp->data);
- } else
- ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
- ast_hangup(tmp->chan);
- free(tmp);
- return NULL;
-}
-
-int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
-{
- struct ast_channel *chan;
- struct app_tmp *tmp;
- int res = -1, cdr_res = -1;
- struct outgoing_helper oh;
- pthread_attr_t attr;
-
- memset(&oh, 0, sizeof(oh));
- oh.vars = vars;
- oh.account = account;
-
- if (locked_channel)
- *locked_channel = NULL;
- if (ast_strlen_zero(app)) {
- res = -1;
- goto outgoing_app_cleanup;
- }
- if (sync) {
- chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
- if (chan) {
- ast_set_variables(chan, vars);
- if (account)
- ast_cdr_setaccount(chan, account);
- if (chan->_state == AST_STATE_UP) {
- res = 0;
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", chan->name);
- tmp = ast_calloc(1, sizeof(*tmp));
- if (!tmp)
- res = -1;
- else {
- ast_copy_string(tmp->app, app, sizeof(tmp->app));
- if (appdata)
- ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
- tmp->chan = chan;
- if (sync > 1) {
- if (locked_channel)
- ast_channel_unlock(chan);
- ast_pbx_run_app(tmp);
- } else {
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (locked_channel)
- ast_channel_lock(chan);
- if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
- ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
- free(tmp);
- if (locked_channel)
- ast_channel_unlock(chan);
- ast_hangup(chan);
- res = -1;
- } else {
- if (locked_channel)
- *locked_channel = chan;
- }
- pthread_attr_destroy(&attr);
- }
- }
- } else {
- if (option_verbose > 3)
- ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
- if (chan->cdr) { /* update the cdr */
- /* here we update the status of the call, which sould be busy.
- * if that fails then we set the status to failed */
- if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
- ast_cdr_failed(chan->cdr);
- }
- ast_hangup(chan);
- }
- }
-
- if (res < 0) { /* the call failed for some reason */
- if (*reason == 0) { /* if the call failed (not busy or no answer)
- * update the cdr with the failed message */
- cdr_res = ast_pbx_outgoing_cdr_failed();
- if (cdr_res != 0) {
- res = cdr_res;
- goto outgoing_app_cleanup;
- }
- }
- }
-
- } else {
- struct async_stat *as;
- if (!(as = ast_calloc(1, sizeof(*as)))) {
- res = -1;
- goto outgoing_app_cleanup;
- }
- chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
- if (!chan) {
- free(as);
- res = -1;
- goto outgoing_app_cleanup;
- }
- as->chan = chan;
- ast_copy_string(as->app, app, sizeof(as->app));
- if (appdata)
- ast_copy_string(as->appdata, appdata, sizeof(as->appdata));
- as->timeout = timeout;
- ast_set_variables(chan, vars);
- if (account)
- ast_cdr_setaccount(chan, account);
- /* Start a new thread, and get something handling this channel. */
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (locked_channel)
- ast_channel_lock(chan);
- if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
- ast_log(LOG_WARNING, "Failed to start async wait\n");
- free(as);
- if (locked_channel)
- ast_channel_unlock(chan);
- ast_hangup(chan);
- res = -1;
- pthread_attr_destroy(&attr);
- goto outgoing_app_cleanup;
- } else {
- if (locked_channel)
- *locked_channel = chan;
- }
- pthread_attr_destroy(&attr);
- res = 0;
- }
-outgoing_app_cleanup:
- ast_variables_destroy(vars);
- return res;
-}
-
-void __ast_context_destroy(struct ast_context *con, const char *registrar)
-{
- struct ast_context *tmp, *tmpl=NULL;
- struct ast_include *tmpi;
- struct ast_sw *sw;
- struct ast_exten *e, *el, *en;
- struct ast_ignorepat *ipi;
-
- for (tmp = contexts; tmp; ) {
- struct ast_context *next; /* next starting point */
- for (; tmp; tmpl = tmp, tmp = tmp->next) {
- if (option_debug)
- ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar);
- if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
- (!con || !strcasecmp(tmp->name, con->name)) )
- break; /* found it */
- }
- if (!tmp) /* not found, we are done */
- break;
- ast_mutex_lock(&tmp->lock);
- if (option_debug)
- ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
- next = tmp->next;
- if (tmpl)
- tmpl->next = next;
- else
- contexts = next;
- /* Okay, now we're safe to let it go -- in a sense, we were
- ready to let it go as soon as we locked it. */
- ast_mutex_unlock(&tmp->lock);
- for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
- struct ast_include *tmpil = tmpi;
- tmpi = tmpi->next;
- free(tmpil);
- }
- for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
- struct ast_ignorepat *ipl = ipi;
- ipi = ipi->next;
- free(ipl);
- }
- while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
- free(sw);
- for (e = tmp->root; e;) {
- for (en = e->peer; en;) {
- el = en;
- en = en->peer;
- destroy_exten(el);
- }
- el = e;
- e = e->next;
- destroy_exten(el);
- }
- ast_mutex_destroy(&tmp->lock);
- free(tmp);
- /* if we have a specific match, we are done, otherwise continue */
- tmp = con ? NULL : next;
- }
-}
-
-void ast_context_destroy(struct ast_context *con, const char *registrar)
-{
- ast_wrlock_contexts();
- __ast_context_destroy(con,registrar);
- ast_unlock_contexts();
-}
-
-static void wait_for_hangup(struct ast_channel *chan, void *data)
-{
- int res;
- struct ast_frame *f;
- int waittime;
-
- if (ast_strlen_zero(data) || (sscanf(data, "%d", &waittime) != 1) || (waittime < 0))
- waittime = -1;
- if (waittime > -1) {
- ast_safe_sleep(chan, waittime * 1000);
- } else do {
- res = ast_waitfor(chan, -1);
- if (res < 0)
- return;
- f = ast_read(chan);
- if (f)
- ast_frfree(f);
- } while(f);
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_progress(struct ast_channel *chan, void *data)
-{
- ast_indicate(chan, AST_CONTROL_PROGRESS);
- return 0;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_ringing(struct ast_channel *chan, void *data)
-{
- ast_indicate(chan, AST_CONTROL_RINGING);
- return 0;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_busy(struct ast_channel *chan, void *data)
-{
- ast_indicate(chan, AST_CONTROL_BUSY);
- /* Don't change state of an UP channel, just indicate
- busy in audio */
- if (chan->_state != AST_STATE_UP)
- ast_setstate(chan, AST_STATE_BUSY);
- wait_for_hangup(chan, data);
- return -1;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_congestion(struct ast_channel *chan, void *data)
-{
- ast_indicate(chan, AST_CONTROL_CONGESTION);
- /* Don't change state of an UP channel, just indicate
- congestion in audio */
- if (chan->_state != AST_STATE_UP)
- ast_setstate(chan, AST_STATE_BUSY);
- wait_for_hangup(chan, data);
- return -1;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_answer(struct ast_channel *chan, void *data)
-{
- int delay = 0;
- int res;
-
- if (chan->_state == AST_STATE_UP)
- delay = 0;
- else if (!ast_strlen_zero(data))
- delay = atoi(data);
-
- res = ast_answer(chan);
- if (res)
- return res;
-
- if (delay)
- res = ast_safe_sleep(chan, delay);
-
- return res;
-}
-
-AST_APP_OPTIONS(resetcdr_opts, {
- AST_APP_OPTION('w', AST_CDR_FLAG_POSTED),
- AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED),
- AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),
-});
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_resetcdr(struct ast_channel *chan, void *data)
-{
- char *args;
- struct ast_flags flags = { 0 };
-
- if (!ast_strlen_zero(data)) {
- args = ast_strdupa(data);
- ast_app_parse_options(resetcdr_opts, &flags, NULL, args);
- }
-
- ast_cdr_reset(chan->cdr, &flags);
-
- return 0;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_setamaflags(struct ast_channel *chan, void *data)
-{
- /* Copy the AMA Flags as specified */
- ast_cdr_setamaflags(chan, data ? data : "");
- return 0;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
-{
- if (!ast_strlen_zero(data)) {
- int cause;
- char *endptr;
-
- if ((cause = ast_str2cause(data)) > -1) {
- chan->hangupcause = cause;
- return -1;
- }
-
- cause = strtol((const char *) data, &endptr, 10);
- if (cause != 0 || (data != endptr)) {
- chan->hangupcause = cause;
- return -1;
- }
-
- ast_log(LOG_NOTICE, "Invalid cause given to Hangup(): \"%s\"\n", (char *) data);
- }
-
- if (!chan->hangupcause) {
- chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
- }
-
- return -1;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_gotoiftime(struct ast_channel *chan, void *data)
-{
- int res=0;
- char *s, *ts;
- struct ast_timing timing;
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n <time range>|<days of week>|<days of month>|<months>?[[context|]extension|]priority\n");
- return -1;
- }
-
- ts = s = ast_strdupa(data);
-
- /* Separate the Goto path */
- strsep(&ts,"?");
-
- /* struct ast_include include contained garbage here, fixed by zeroing it on get_timerange */
- if (ast_build_timing(&timing, s) && ast_check_timing(&timing))
- res = pbx_builtin_goto(chan, ts);
-
- return res;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_execiftime(struct ast_channel *chan, void *data)
-{
- char *s, *appname;
- struct ast_timing timing;
- struct ast_app *app;
- static const char *usage = "ExecIfTime requires an argument:\n <time range>|<days of week>|<days of month>|<months>?<appname>[|<appargs>]";
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "%s\n", usage);
- return -1;
- }
-
- appname = ast_strdupa(data);
-
- s = strsep(&appname,"?"); /* Separate the timerange and application name/data */
- if (!appname) { /* missing application */
- ast_log(LOG_WARNING, "%s\n", usage);
- return -1;
- }
-
- if (!ast_build_timing(&timing, s)) {
- ast_log(LOG_WARNING, "Invalid Time Spec: %s\nCorrect usage: %s\n", s, usage);
- return -1;
- }
-
- if (!ast_check_timing(&timing)) /* outside the valid time window, just return */
- return 0;
-
- /* now split appname|appargs */
- if ((s = strchr(appname, '|')))
- *s++ = '\0';
-
- if ((app = pbx_findapp(appname))) {
- return pbx_exec(chan, app, S_OR(s, ""));
- } else {
- ast_log(LOG_WARNING, "Cannot locate application %s\n", appname);
- return -1;
- }
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_wait(struct ast_channel *chan, void *data)
-{
- double s;
- int ms;
-
- /* Wait for "n" seconds */
- if (data && (s = atof(data)) > 0) {
- ms = s * 1000.0;
- return ast_safe_sleep(chan, ms);
- }
- return 0;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_waitexten(struct ast_channel *chan, void *data)
-{
- int ms, res;
- double sec;
- struct ast_flags flags = {0};
- char *opts[1] = { NULL };
- char *parse;
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(timeout);
- AST_APP_ARG(options);
- );
-
- if (!ast_strlen_zero(data)) {
- parse = ast_strdupa(data);
- AST_STANDARD_APP_ARGS(args, parse);
- } else
- memset(&args, 0, sizeof(args));
-
- if (args.options)
- ast_app_parse_options(waitexten_opts, &flags, opts, args.options);
-
- if (ast_test_flag(&flags, WAITEXTEN_MOH) && !opts[0] ) {
- ast_log(LOG_WARNING, "The 'm' option has been specified for WaitExten without a class.\n");
- } else if (ast_test_flag(&flags, WAITEXTEN_MOH))
- ast_indicate_data(chan, AST_CONTROL_HOLD, opts[0], strlen(opts[0]));
-
- /* Wait for "n" seconds */
- if (args.timeout && (sec = atof(args.timeout)) > 0.0)
- ms = 1000 * sec;
- else if (chan->pbx)
- ms = chan->pbx->rtimeout * 1000;
- else
- ms = 10000;
- res = ast_waitfordigit(chan, ms);
- if (!res) {
- if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Timeout on %s, continuing...\n", chan->name);
- } else if (chan->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Call timeout on %s, checking for 'T'\n", chan->name);
- res = -1;
- } else if (ast_exists_extension(chan, chan->context, "t", 1, chan->cid.cid_num)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Timeout on %s, going to 't'\n", chan->name);
- set_ext_pri(chan, "t", 0); /* 0 will become 1, next time through the loop */
- } else {
- ast_log(LOG_WARNING, "Timeout but no rule 't' in context '%s'\n", chan->context);
- res = -1;
- }
- }
-
- if (ast_test_flag(&flags, WAITEXTEN_MOH))
- ast_indicate(chan, AST_CONTROL_UNHOLD);
-
- return res;
-}
-
-/*!
- * \ingroup applications
- */
-static int pbx_builtin_background(struct ast_channel *chan, void *data)
-{
- int res = 0;
- struct ast_flags flags = {0};
- char *parse;
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(filename);
- AST_APP_ARG(options);
- AST_APP_ARG(lang);
- AST_APP_ARG(context);
- );
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "Background requires an argument (filename)\n");
- return -1;
- }
-
- parse = ast_strdupa(data);
-
- AST_STANDARD_APP_ARGS(args, parse);
-
- if (ast_strlen_zero(args.lang))
- args.lang = (char *)chan->language; /* XXX this is const */
-
- if (ast_strlen_zero(args.context))
- args.context = chan->context;
-
- if (args.options) {
- if (!strcasecmp(args.options, "skip"))
- flags.flags = BACKGROUND_SKIP;
- else if (!strcasecmp(args.options, "noanswer"))
- flags.flags = BACKGROUND_NOANSWER;
- else
- ast_app_parse_options(background_opts, &flags, NULL, args.options);
- }
-
- /* Answer if need be */
- if (chan->_state != AST_STATE_UP) {
- if (ast_test_flag(&flags, BACKGROUND_SKIP)) {
- return 0;
- } else if (!ast_test_flag(&flags, BACKGROUND_NOANSWER)) {
- res = ast_answer(chan);
- }
- }
-
- if (!res) {
- char *back = args.filename;
- char *front;
- ast_stopstream(chan); /* Stop anything playing */
- /* Stream the list of files */
- while (!res && (front = strsep(&back, "&")) ) {
- if ( (res = ast_streamfile(chan, front, args.lang)) ) {
- ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char*)data);
- res = 0;
- break;
- }
- if (ast_test_flag(&flags, BACKGROUND_PLAYBACK)) {
- res = ast_waitstream(chan, "");
- } else if (ast_test_flag(&flags, BACKGROUND_MATCHEXTEN)) {
- res = ast_waitstream_exten(chan, args.context);
- } else {
- res = ast_waitstream(chan, AST_DIGIT_ANY);
- }
- ast_stopstream(chan);
- }
- }
- if (args.context != chan->context && res) {
- snprintf(chan->exten, sizeof(chan->exten), "%c", res);
- ast_copy_string(chan->context, args.context, sizeof(chan->context));
- chan->priority = 0;
- res = 0;
- }
- return res;
-}
-
-/*! Goto
- * \ingroup applications
- */
-static int pbx_builtin_goto(struct ast_channel *chan, void *data)
-{
- int res = ast_parseable_goto(chan, data);
- if (!res && (option_verbose > 2))
- ast_verbose( VERBOSE_PREFIX_3 "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1);
- return res;
-}
-
-
-int pbx_builtin_serialize_variables(struct ast_channel *chan, char *buf, size_t size)
-{
- struct ast_var_t *variables;
- const char *var, *val;
- int total = 0;
-
- if (!chan)
- return 0;
-
- memset(buf, 0, size);
-
- ast_channel_lock(chan);
-
- AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
- if ((var=ast_var_name(variables)) && (val=ast_var_value(variables))
- /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
- ) {
- if (ast_build_string(&buf, &size, "%s=%s\n", var, val)) {
- ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
- break;
- } else
- total++;
- } else
- break;
- }
-
- ast_channel_unlock(chan);
-
- return total;
-}
-
-const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
-{
- struct ast_var_t *variables;
- const char *ret = NULL;
- int i;
- struct varshead *places[2] = { NULL, &globals };
-
- if (!name)
- return NULL;
-
- if (chan) {
- ast_channel_lock(chan);
- places[0] = &chan->varshead;
- }
-
- for (i = 0; i < 2; i++) {
- if (!places[i])
- continue;
- if (places[i] == &globals)
- ast_mutex_lock(&globalslock);
- AST_LIST_TRAVERSE(places[i], variables, entries) {
- if (!strcmp(name, ast_var_name(variables))) {
- ret = ast_var_value(variables);
- break;
- }
- }
- if (places[i] == &globals)
- ast_mutex_unlock(&globalslock);
- if (ret)
- break;
- }
-
- if (chan)
- ast_channel_unlock(chan);
-
- return ret;
-}
-
-void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
-{
- struct ast_var_t *newvariable;
- struct varshead *headp;
-
- if (name[strlen(name)-1] == ')') {
- char *function = ast_strdupa(name);
-
- ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
- ast_func_write(chan, function, value);
- return;
- }
-
- if (chan) {
- ast_channel_lock(chan);
- headp = &chan->varshead;
- } else {
- ast_mutex_lock(&globalslock);
- headp = &globals;
- }
-
- if (value) {
- if ((option_verbose > 1) && (headp == &globals))
- ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
- newvariable = ast_var_assign(name, value);
- AST_LIST_INSERT_HEAD(headp, newvariable, entries);
- }
-
- if (chan)
- ast_channel_unlock(chan);
- else
- ast_mutex_unlock(&globalslock);
-}
-
-void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
-{
- struct ast_var_t *newvariable;
- struct varshead *headp;
- const char *nametail = name;
-
- if (name[strlen(name)-1] == ')') {
- char *function = ast_strdupa(name);
-
- ast_func_write(chan, function, value);
- return;
- }
-
- if (chan) {
- ast_channel_lock(chan);
- headp = &chan->varshead;
- } else {
- ast_mutex_lock(&globalslock);
- headp = &globals;
- }
-
- /* For comparison purposes, we have to strip leading underscores */
- if (*nametail == '_') {
- nametail++;
- if (*nametail == '_')
- nametail++;
- }
-
- AST_LIST_TRAVERSE (headp, newvariable, entries) {
- if (strcasecmp(ast_var_name(newvariable), nametail) == 0) {
- /* there is already such a variable, delete it */
- AST_LIST_REMOVE(headp, newvariable, entries);
- ast_var_delete(newvariable);
- break;
- }
- }
-
- if (value) {
- if ((option_verbose > 1) && (headp == &globals))
- ast_verbose(VERBOSE_PREFIX_2 "Setting global variable '%s' to '%s'\n", name, value);
- newvariable = ast_var_assign(name, value);
- AST_LIST_INSERT_HEAD(headp, newvariable, entries);
- }
-
- if (chan)
- ast_channel_unlock(chan);
- else
- ast_mutex_unlock(&globalslock);
-}
-
-int pbx_builtin_setvar(struct ast_channel *chan, void *data)
-{
- char *name, *value, *mydata;
- int argc;
- char *argv[24]; /* this will only support a maximum of 24 variables being set in a single operation */
- int global = 0;
- int x;
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "Set requires at least one variable name/value pair.\n");
- return 0;
- }
-
- mydata = ast_strdupa(data);
- argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
-
- /* check for a trailing flags argument */
- if ((argc > 1) && !strchr(argv[argc-1], '=')) {
- argc--;
- if (strchr(argv[argc], 'g')) {
- ast_log(LOG_WARNING, "The use of the 'g' flag is deprecated. Please use Set(GLOBAL(foo)=bar) instead\n");
- global = 1;
- }
- }
-
- if (argc > 1)
- ast_log(LOG_WARNING, "Setting multiple variables at once within Set is deprecated. Please separate each name/value pair into its own line.\n");
-
- for (x = 0; x < argc; x++) {
- name = argv[x];
- if ((value = strchr(name, '='))) {
- *value++ = '\0';
- pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
- } else
- ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
- }
-
- return(0);
-}
-
-int pbx_builtin_importvar(struct ast_channel *chan, void *data)
-{
- char *name;
- char *value;
- char *channel;
- char tmp[VAR_BUF_SIZE]="";
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
- return 0;
- }
-
- value = ast_strdupa(data);
- name = strsep(&value,"=");
- channel = strsep(&value,"|");
- if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
- struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
- if (chan2) {
- char *s = alloca(strlen(value) + 4);
- if (s) {
- sprintf(s, "${%s}", value);
- pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
- }
- ast_channel_unlock(chan2);
- }
- pbx_builtin_setvar_helper(chan, name, tmp);
- }
-
- return(0);
-}
-
-/*! \todo XXX overwrites data ? */
-static int pbx_builtin_setglobalvar(struct ast_channel *chan, void *data)
-{
- char *name;
- char *stringp = data;
- static int dep_warning = 0;
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
- return 0;
- }
-
- name = strsep(&stringp, "=");
-
- if (!dep_warning) {
- dep_warning = 1;
- ast_log(LOG_WARNING, "SetGlobalVar is deprecated. Please use Set(GLOBAL(%s)=%s) instead.\n", name, stringp);
- }
-
- /*! \todo XXX watch out, leading whitespace ? */
- pbx_builtin_setvar_helper(NULL, name, stringp);
-
- return(0);
-}
-
-static int pbx_builtin_noop(struct ast_channel *chan, void *data)
-{
- return 0;
-}
-
-void pbx_builtin_clear_globals(void)
-{
- struct ast_var_t *vardata;
-
- ast_mutex_lock(&globalslock);
- while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
- ast_var_delete(vardata);
- ast_mutex_unlock(&globalslock);
-}
-
-int pbx_checkcondition(const char *condition)
-{
- if (ast_strlen_zero(condition)) /* NULL or empty strings are false */
- return 0;
- else if (*condition >= '0' && *condition <= '9') /* Numbers are evaluated for truth */
- return atoi(condition);
- else /* Strings are true */
- return 1;
-}
-
-static int pbx_builtin_gotoif(struct ast_channel *chan, void *data)
-{
- char *condition, *branch1, *branch2, *branch;
- int rc;
- char *stringp;
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
- return 0;
- }
-
- stringp = ast_strdupa(data);
- condition = strsep(&stringp,"?");
- branch1 = strsep(&stringp,":");
- branch2 = strsep(&stringp,"");
- branch = pbx_checkcondition(condition) ? branch1 : branch2;
-
- if (ast_strlen_zero(branch)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Not taking any branch\n");
- return 0;
- }
-
- rc = pbx_builtin_goto(chan, branch);
-
- return rc;
-}
-
-static int pbx_builtin_saynumber(struct ast_channel *chan, void *data)
-{
- char tmp[256];
- char *number = tmp;
- char *options;
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
- return -1;
- }
- ast_copy_string(tmp, data, sizeof(tmp));
- strsep(&number, "|");
- options = strsep(&number, "|");
- if (options) {
- if ( strcasecmp(options, "f") && strcasecmp(options,"m") &&
- strcasecmp(options, "c") && strcasecmp(options, "n") ) {
- ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
- return -1;
- }
- }
-
- if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
- ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
- }
-
- return 0;
-}
-
-static int pbx_builtin_saydigits(struct ast_channel *chan, void *data)
-{
- int res = 0;
-
- if (data)
- res = ast_say_digit_str(chan, data, "", chan->language);
- return res;
-}
-
-static int pbx_builtin_saycharacters(struct ast_channel *chan, void *data)
-{
- int res = 0;
-
- if (data)
- res = ast_say_character_str(chan, data, "", chan->language);
- return res;
-}
-
-static int pbx_builtin_sayphonetic(struct ast_channel *chan, void *data)
-{
- int res = 0;
-
- if (data)
- res = ast_say_phonetic_str(chan, data, "", chan->language);
- return res;
-}
-
-int load_pbx(void)
-{
- int x;
-
- /* Initialize the PBX */
- if (option_verbose) {
- ast_verbose( "Asterisk PBX Core Initializing\n");
- ast_verbose( "Registering builtin applications:\n");
- }
- ast_cli_register_multiple(pbx_cli, sizeof(pbx_cli) / sizeof(struct ast_cli_entry));
-
- /* Register builtin applications */
- for (x=0; x<sizeof(builtins) / sizeof(struct pbx_builtin); x++) {
- if (option_verbose)
- ast_verbose( VERBOSE_PREFIX_1 "[%s]\n", builtins[x].name);
- if (ast_register_application(builtins[x].name, builtins[x].execute, builtins[x].synopsis, builtins[x].description)) {
- ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
- return -1;
- }
- }
- return 0;
-}
-
-/*
- * Lock context list functions ...
- */
-int ast_lock_contexts()
-{
- return ast_rwlock_wrlock(&conlock);
-}
-
-int ast_rdlock_contexts(void)
-{
- return ast_rwlock_rdlock(&conlock);
-}
-
-int ast_wrlock_contexts(void)
-{
- return ast_rwlock_wrlock(&conlock);
-}
-
-int ast_unlock_contexts()
-{
- return ast_rwlock_unlock(&conlock);
-}
-
-/*
- * Lock context ...
- */
-int ast_lock_context(struct ast_context *con)
-{
- return ast_mutex_lock(&con->lock);
-}
-
-int ast_unlock_context(struct ast_context *con)
-{
- return ast_mutex_unlock(&con->lock);
-}
-
-/*
- * Name functions ...
- */
-const char *ast_get_context_name(struct ast_context *con)
-{
- return con ? con->name : NULL;
-}
-
-struct ast_context *ast_get_extension_context(struct ast_exten *exten)
-{
- return exten ? exten->parent : NULL;
-}
-
-const char *ast_get_extension_name(struct ast_exten *exten)
-{
- return exten ? exten->exten : NULL;
-}
-
-const char *ast_get_extension_label(struct ast_exten *exten)
-{
- return exten ? exten->label : NULL;
-}
-
-const char *ast_get_include_name(struct ast_include *inc)
-{
- return inc ? inc->name : NULL;
-}
-
-const char *ast_get_ignorepat_name(struct ast_ignorepat *ip)
-{
- return ip ? ip->pattern : NULL;
-}
-
-int ast_get_extension_priority(struct ast_exten *exten)
-{
- return exten ? exten->priority : -1;
-}
-
-/*
- * Registrar info functions ...
- */
-const char *ast_get_context_registrar(struct ast_context *c)
-{
- return c ? c->registrar : NULL;
-}
-
-const char *ast_get_extension_registrar(struct ast_exten *e)
-{
- return e ? e->registrar : NULL;
-}
-
-const char *ast_get_include_registrar(struct ast_include *i)
-{
- return i ? i->registrar : NULL;
-}
-
-const char *ast_get_ignorepat_registrar(struct ast_ignorepat *ip)
-{
- return ip ? ip->registrar : NULL;
-}
-
-int ast_get_extension_matchcid(struct ast_exten *e)
-{
- return e ? e->matchcid : 0;
-}
-
-const char *ast_get_extension_cidmatch(struct ast_exten *e)
-{
- return e ? e->cidmatch : NULL;
-}
-
-const char *ast_get_extension_app(struct ast_exten *e)
-{
- return e ? e->app : NULL;
-}
-
-void *ast_get_extension_app_data(struct ast_exten *e)
-{
- return e ? e->data : NULL;
-}
-
-const char *ast_get_switch_name(struct ast_sw *sw)
-{
- return sw ? sw->name : NULL;
-}
-
-const char *ast_get_switch_data(struct ast_sw *sw)
-{
- return sw ? sw->data : NULL;
-}
-
-const char *ast_get_switch_registrar(struct ast_sw *sw)
-{
- return sw ? sw->registrar : NULL;
-}
-
-/*
- * Walking functions ...
- */
-struct ast_context *ast_walk_contexts(struct ast_context *con)
-{
- return con ? con->next : contexts;
-}
-
-struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
- struct ast_exten *exten)
-{
- if (!exten)
- return con ? con->root : NULL;
- else
- return exten->next;
-}
-
-struct ast_sw *ast_walk_context_switches(struct ast_context *con,
- struct ast_sw *sw)
-{
- if (!sw)
- return con ? AST_LIST_FIRST(&con->alts) : NULL;
- else
- return AST_LIST_NEXT(sw, list);
-}
-
-struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
- struct ast_exten *priority)
-{
- return priority ? priority->peer : exten;
-}
-
-struct ast_include *ast_walk_context_includes(struct ast_context *con,
- struct ast_include *inc)
-{
- if (!inc)
- return con ? con->includes : NULL;
- else
- return inc->next;
-}
-
-struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
- struct ast_ignorepat *ip)
-{
- if (!ip)
- return con ? con->ignorepats : NULL;
- else
- return ip->next;
-}
-
-int ast_context_verify_includes(struct ast_context *con)
-{
- struct ast_include *inc = NULL;
- int res = 0;
-
- while ( (inc = ast_walk_context_includes(con, inc)) ) {
- if (ast_context_find(inc->rname))
- continue;
-
- res = -1;
- ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
- ast_get_context_name(con), inc->rname);
- break;
- }
-
- return res;
-}
-
-
-static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
-{
- int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
-
- if (!chan)
- return -2;
-
- if (context == NULL)
- context = chan->context;
- if (exten == NULL)
- exten = chan->exten;
-
- goto_func = (async) ? ast_async_goto : ast_explicit_goto;
- if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
- return goto_func(chan, context, exten, priority);
- else
- return -3;
-}
-
-int ast_goto_if_exists(struct ast_channel *chan, const char* context, const char *exten, int priority)
-{
- return __ast_goto_if_exists(chan, context, exten, priority, 0);
-}
-
-int ast_async_goto_if_exists(struct ast_channel *chan, const char * context, const char *exten, int priority)
-{
- return __ast_goto_if_exists(chan, context, exten, priority, 1);
-}
-
-int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
-{
- char *exten, *pri, *context;
- char *stringp;
- int ipri;
- int mode = 0;
-
- if (ast_strlen_zero(goto_string)) {
- ast_log(LOG_WARNING, "Goto requires an argument (optional context|optional extension|priority)\n");
- return -1;
- }
- stringp = ast_strdupa(goto_string);
- context = strsep(&stringp, "|"); /* guaranteed non-null */
- exten = strsep(&stringp, "|");
- pri = strsep(&stringp, "|");
- if (!exten) { /* Only a priority in this one */
- pri = context;
- exten = NULL;
- context = NULL;
- } else if (!pri) { /* Only an extension and priority in this one */
- pri = exten;
- exten = context;
- context = NULL;
- }
- if (*pri == '+') {
- mode = 1;
- pri++;
- } else if (*pri == '-') {
- mode = -1;
- pri++;
- }
- if (sscanf(pri, "%d", &ipri) != 1) {
- if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
- pri, chan->cid.cid_num)) < 1) {
- ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
- return -1;
- } else
- mode = 0;
- }
- /* At this point we have a priority and maybe an extension and a context */
-
- if (mode)
- ipri = chan->priority + (ipri * mode);
-
- ast_explicit_goto(chan, context, exten, ipri);
- return 0;
-
-}
diff --git a/main/plc.c b/main/plc.c
deleted file mode 100644
index 336a99030..000000000
--- a/main/plc.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *
- * Copyright (C) 2004 Steve Underwood
- *
- * All rights reserved.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- *
- * This version may be optionally licenced under the GNU LGPL licence.
- *
- * A license has been granted to Digium (via disclaimer) for the use of
- * this code.
- */
-
-/*! \file
- *
- * \brief SpanDSP - a series of DSP components for telephony
- *
- * \author Steve Underwood <steveu@coppice.org>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "asterisk/plc.h"
-
-#if !defined(FALSE)
-#define FALSE 0
-#endif
-#if !defined(TRUE)
-#define TRUE (!FALSE)
-#endif
-
-#if !defined(INT16_MAX)
-#define INT16_MAX (32767)
-#define INT16_MIN (-32767-1)
-#endif
-
-/* We do a straight line fade to zero volume in 50ms when we are filling in for missing data. */
-#define ATTENUATION_INCREMENT 0.0025 /* Attenuation per sample */
-
-#define ms_to_samples(t) (((t)*DEFAULT_SAMPLE_RATE)/1000)
-
-static inline int16_t fsaturate(double damp)
-{
- if (damp > 32767.0)
- return INT16_MAX;
- if (damp < -32768.0)
- return INT16_MIN;
- return (int16_t) rint(damp);
-}
-
-static void save_history(plc_state_t *s, int16_t *buf, int len)
-{
- if (len >= PLC_HISTORY_LEN) {
- /* Just keep the last part of the new data, starting at the beginning of the buffer */
- memcpy(s->history, buf + len - PLC_HISTORY_LEN, sizeof(int16_t) * PLC_HISTORY_LEN);
- s->buf_ptr = 0;
- return;
- }
- if (s->buf_ptr + len > PLC_HISTORY_LEN) {
- /* Wraps around - must break into two sections */
- memcpy(s->history + s->buf_ptr, buf, sizeof(int16_t) * (PLC_HISTORY_LEN - s->buf_ptr));
- len -= (PLC_HISTORY_LEN - s->buf_ptr);
- memcpy(s->history, buf + (PLC_HISTORY_LEN - s->buf_ptr), sizeof(int16_t)*len);
- s->buf_ptr = len;
- return;
- }
- /* Can use just one section */
- memcpy(s->history + s->buf_ptr, buf, sizeof(int16_t)*len);
- s->buf_ptr += len;
-}
-
-/*- End of function --------------------------------------------------------*/
-
-static void normalise_history(plc_state_t *s)
-{
- int16_t tmp[PLC_HISTORY_LEN];
-
- if (s->buf_ptr == 0)
- return;
- memcpy(tmp, s->history, sizeof(int16_t)*s->buf_ptr);
- memcpy(s->history, s->history + s->buf_ptr, sizeof(int16_t) * (PLC_HISTORY_LEN - s->buf_ptr));
- memcpy(s->history + PLC_HISTORY_LEN - s->buf_ptr, tmp, sizeof(int16_t) * s->buf_ptr);
- s->buf_ptr = 0;
-}
-
-/*- End of function --------------------------------------------------------*/
-
-static int __inline__ amdf_pitch(int min_pitch, int max_pitch, int16_t amp[], int len)
-{
- int i;
- int j;
- int acc;
- int min_acc;
- int pitch;
-
- pitch = min_pitch;
- min_acc = INT_MAX;
- for (i = max_pitch; i <= min_pitch; i++) {
- acc = 0;
- for (j = 0; j < len; j++)
- acc += abs(amp[i + j] - amp[j]);
- if (acc < min_acc) {
- min_acc = acc;
- pitch = i;
- }
- }
- return pitch;
-}
-
-/*- End of function --------------------------------------------------------*/
-
-int plc_rx(plc_state_t *s, int16_t amp[], int len)
-{
- int i;
- int pitch_overlap;
- float old_step;
- float new_step;
- float old_weight;
- float new_weight;
- float gain;
-
- if (s->missing_samples) {
- /* Although we have a real signal, we need to smooth it to fit well
- with the synthetic signal we used for the previous block */
-
- /* The start of the real data is overlapped with the next 1/4 cycle
- of the synthetic data. */
- pitch_overlap = s->pitch >> 2;
- if (pitch_overlap > len)
- pitch_overlap = len;
- gain = 1.0 - s->missing_samples*ATTENUATION_INCREMENT;
- if (gain < 0.0)
- gain = 0.0;
- new_step = 1.0/pitch_overlap;
- old_step = new_step*gain;
- new_weight = new_step;
- old_weight = (1.0 - new_step)*gain;
- for (i = 0; i < pitch_overlap; i++) {
- amp[i] = fsaturate(old_weight * s->pitchbuf[s->pitch_offset] + new_weight * amp[i]);
- if (++s->pitch_offset >= s->pitch)
- s->pitch_offset = 0;
- new_weight += new_step;
- old_weight -= old_step;
- if (old_weight < 0.0)
- old_weight = 0.0;
- }
- s->missing_samples = 0;
- }
- save_history(s, amp, len);
- return len;
-}
-
-/*- End of function --------------------------------------------------------*/
-
-int plc_fillin(plc_state_t *s, int16_t amp[], int len)
-{
- int i;
- int pitch_overlap;
- float old_step;
- float new_step;
- float old_weight;
- float new_weight;
- float gain;
- int16_t *orig_amp;
- int orig_len;
-
- orig_amp = amp;
- orig_len = len;
- if (s->missing_samples == 0) {
- /* As the gap in real speech starts we need to assess the last known pitch,
- and prepare the synthetic data we will use for fill-in */
- normalise_history(s);
- s->pitch = amdf_pitch(PLC_PITCH_MIN, PLC_PITCH_MAX, s->history + PLC_HISTORY_LEN - CORRELATION_SPAN - PLC_PITCH_MIN, CORRELATION_SPAN);
- /* We overlap a 1/4 wavelength */
- pitch_overlap = s->pitch >> 2;
- /* Cook up a single cycle of pitch, using a single of the real signal with 1/4
- cycle OLA'ed to make the ends join up nicely */
- /* The first 3/4 of the cycle is a simple copy */
- for (i = 0; i < s->pitch - pitch_overlap; i++)
- s->pitchbuf[i] = s->history[PLC_HISTORY_LEN - s->pitch + i];
- /* The last 1/4 of the cycle is overlapped with the end of the previous cycle */
- new_step = 1.0/pitch_overlap;
- new_weight = new_step;
- for ( ; i < s->pitch; i++) {
- s->pitchbuf[i] = s->history[PLC_HISTORY_LEN - s->pitch + i] * (1.0 - new_weight) + s->history[PLC_HISTORY_LEN - 2 * s->pitch + i]*new_weight;
- new_weight += new_step;
- }
- /* We should now be ready to fill in the gap with repeated, decaying cycles
- of what is in pitchbuf */
-
- /* We need to OLA the first 1/4 wavelength of the synthetic data, to smooth
- it into the previous real data. To avoid the need to introduce a delay
- in the stream, reverse the last 1/4 wavelength, and OLA with that. */
- gain = 1.0;
- new_step = 1.0 / pitch_overlap;
- old_step = new_step;
- new_weight = new_step;
- old_weight = 1.0 - new_step;
- for (i = 0; i < pitch_overlap; i++) {
- amp[i] = fsaturate(old_weight * s->history[PLC_HISTORY_LEN - 1 - i] + new_weight * s->pitchbuf[i]);
- new_weight += new_step;
- old_weight -= old_step;
- if (old_weight < 0.0)
- old_weight = 0.0;
- }
- s->pitch_offset = i;
- } else {
- gain = 1.0 - s->missing_samples*ATTENUATION_INCREMENT;
- i = 0;
- }
- for ( ; gain > 0.0 && i < len; i++) {
- amp[i] = s->pitchbuf[s->pitch_offset] * gain;
- gain -= ATTENUATION_INCREMENT;
- if (++s->pitch_offset >= s->pitch)
- s->pitch_offset = 0;
- }
- for ( ; i < len; i++)
- amp[i] = 0;
- s->missing_samples += orig_len;
- save_history(s, amp, len);
- return len;
-}
-
-/*- End of function --------------------------------------------------------*/
-
-plc_state_t *plc_init(plc_state_t *s)
-{
- memset(s, 0, sizeof(*s));
- return s;
-}
-/*- End of function --------------------------------------------------------*/
-/*- End of file ------------------------------------------------------------*/
diff --git a/main/poll.c b/main/poll.c
deleted file mode 100644
index c053ba015..000000000
--- a/main/poll.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*---------------------------------------------------------------------------*\
- $Id$
-
- NAME
-
- poll - select(2)-based poll() emulation function for BSD systems.
-
- SYNOPSIS
- #include "poll.h"
-
- struct pollfd
- {
- int fd;
- short events;
- short revents;
- }
-
- int poll (struct pollfd *pArray, unsigned long n_fds, int timeout)
-
- DESCRIPTION
-
- This file, and the accompanying "poll.h", implement the System V
- poll(2) system call for BSD systems (which typically do not provide
- poll()). Poll() provides a method for multiplexing input and output
- on multiple open file descriptors; in traditional BSD systems, that
- capability is provided by select(). While the semantics of select()
- differ from those of poll(), poll() can be readily emulated in terms
- of select() -- which is how this function is implemented.
-
- REFERENCES
- Stevens, W. Richard. Unix Network Programming. Prentice-Hall, 1990.
-
- NOTES
- 1. This software requires an ANSI C compiler.
-
- LICENSE
-
- This software is released under the following license:
-
- Copyright (c) 1995-2002 Brian M. Clapper
- All rights reserved.
-
- Redistribution and use in source and binary forms are
- permitted provided that: (1) source distributions retain
- this entire copyright notice and comment; (2) modifications
- made to the software are prominently mentioned, and a copy
- of the original software (or a pointer to its location) are
- included; and (3) distributions including binaries display
- the following acknowledgement: "This product includes
- software developed by Brian M. Clapper <bmc@clapper.org>"
- in the documentation or other materials provided with the
- distribution. The name of the author may not be used to
- endorse or promote products derived from this software
- without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- PARTICULAR PURPOSE.
-
- Effectively, this means you can do what you want with the software
- except remove this notice or take advantage of the author's name.
- If you modify the software and redistribute your modified version,
- you must indicate that your version is a modification of the
- original, and you must provide either a pointer to or a copy of the
- original.
-\*---------------------------------------------------------------------------*/
-
-
-/*---------------------------------------------------------------------------*\
- Includes
-\*---------------------------------------------------------------------------*/
-
-#include <unistd.h> /* standard Unix definitions */
-#include <sys/types.h> /* system types */
-#include <sys/time.h> /* time definitions */
-#include <assert.h> /* assertion macros */
-#include <string.h> /* string functions */
-
-#include "asterisk/poll-compat.h" /* this package */
-
-/*---------------------------------------------------------------------------*\
- Macros
-\*---------------------------------------------------------------------------*/
-
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-
-/*---------------------------------------------------------------------------*\
- Private Functions
-\*---------------------------------------------------------------------------*/
-
-static int map_poll_spec
-#if __STDC__ > 0
- (struct pollfd *pArray,
- unsigned long n_fds,
- fd_set *pReadSet,
- fd_set *pWriteSet,
- fd_set *pExceptSet)
-#else
- (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
- struct pollfd *pArray;
- unsigned long n_fds;
- fd_set *pReadSet;
- fd_set *pWriteSet;
- fd_set *pExceptSet;
-#endif
-{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
- register int max_fd = -1; /* return value */
-
- /*
- Map the poll() structures into the file descriptor sets required
- by select().
- */
- for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
- {
- /* Skip any bad FDs in the array. */
-
- if (pCur->fd < 0)
- continue;
-
- if (pCur->events & POLLIN)
- {
- /* "Input Ready" notification desired. */
- FD_SET (pCur->fd, pReadSet);
- }
-
- if (pCur->events & POLLOUT)
- {
- /* "Output Possible" notification desired. */
- FD_SET (pCur->fd, pWriteSet);
- }
-
- if (pCur->events & POLLPRI)
- {
- /*
- "Exception Occurred" notification desired. (Exceptions
- include out of band data.
- */
- FD_SET (pCur->fd, pExceptSet);
- }
-
- max_fd = MAX (max_fd, pCur->fd);
- }
-
- return max_fd;
-}
-
-static struct timeval *map_timeout
-#if __STDC__ > 0
- (int poll_timeout, struct timeval *pSelTimeout)
-#else
- (poll_timeout, pSelTimeout)
- int poll_timeout;
- struct timeval *pSelTimeout;
-#endif
-{
- struct timeval *pResult;
-
- /*
- Map the poll() timeout value into a select() timeout. The possible
- values of the poll() timeout value, and their meanings, are:
-
- VALUE MEANING
-
- -1 wait indefinitely (until signal occurs)
- 0 return immediately, don't block
- >0 wait specified number of milliseconds
-
- select() uses a "struct timeval", which specifies the timeout in
- seconds and microseconds, so the milliseconds value has to be mapped
- accordingly.
- */
-
- assert (pSelTimeout != (struct timeval *) NULL);
-
- switch (poll_timeout)
- {
- case -1:
- /*
- A NULL timeout structure tells select() to wait indefinitely.
- */
- pResult = (struct timeval *) NULL;
- break;
-
- case 0:
- /*
- "Return immediately" (test) is specified by all zeros in
- a timeval structure.
- */
- pSelTimeout->tv_sec = 0;
- pSelTimeout->tv_usec = 0;
- pResult = pSelTimeout;
- break;
-
- default:
- /* Wait the specified number of milliseconds. */
- pSelTimeout->tv_sec = poll_timeout / 1000; /* get seconds */
- poll_timeout %= 1000; /* remove seconds */
- pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
- pResult = pSelTimeout;
- break;
- }
-
-
- return pResult;
-}
-
-static void map_select_results
-#if __STDC__ > 0
- (struct pollfd *pArray,
- unsigned long n_fds,
- fd_set *pReadSet,
- fd_set *pWriteSet,
- fd_set *pExceptSet)
-#else
- (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
- struct pollfd *pArray;
- unsigned long n_fds;
- fd_set *pReadSet;
- fd_set *pWriteSet;
- fd_set *pExceptSet;
-#endif
-{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
-
- for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
- {
- /* Skip any bad FDs in the array. */
-
- if (pCur->fd < 0)
- continue;
-
- /* Exception events take priority over input events. */
-
- pCur->revents = 0;
- if (FD_ISSET (pCur->fd, pExceptSet))
- pCur->revents |= POLLPRI;
-
- else if (FD_ISSET (pCur->fd, pReadSet))
- pCur->revents |= POLLIN;
-
- if (FD_ISSET (pCur->fd, pWriteSet))
- pCur->revents |= POLLOUT;
- }
-
- return;
-}
-
-/*---------------------------------------------------------------------------*\
- Public Functions
-\*---------------------------------------------------------------------------*/
-
-int poll
-
-#if __STDC__ > 0
- (struct pollfd *pArray, unsigned long n_fds, int timeout)
-#else
- (pArray, n_fds, timeout)
- struct pollfd *pArray;
- unsigned long n_fds;
- int timeout;
-#endif
-
-{
- fd_set read_descs; /* input file descs */
- fd_set write_descs; /* output file descs */
- fd_set except_descs; /* exception descs */
- struct timeval stime; /* select() timeout value */
- int ready_descriptors; /* function result */
- int max_fd = 0; /* maximum fd value */
- struct timeval *pTimeout; /* actually passed */
-
- FD_ZERO (&read_descs);
- FD_ZERO (&write_descs);
- FD_ZERO (&except_descs);
-
- /* Map the poll() file descriptor list in the select() data structures. */
-
- if (pArray) {
- max_fd = map_poll_spec (pArray, n_fds,
- &read_descs, &write_descs, &except_descs);
- }
-
- /* Map the poll() timeout value in the select() timeout structure. */
-
- pTimeout = map_timeout (timeout, &stime);
-
- /* Make the select() call. */
-
- ready_descriptors = select (max_fd + 1, &read_descs, &write_descs,
- &except_descs, pTimeout);
-
- if (ready_descriptors >= 0)
- {
- map_select_results (pArray, n_fds,
- &read_descs, &write_descs, &except_descs);
- }
-
- return ready_descriptors;
-}
diff --git a/main/privacy.c b/main/privacy.c
deleted file mode 100644
index b27bb5046..000000000
--- a/main/privacy.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Privacy Routines
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <dirent.h>
-
-#include "asterisk/channel.h"
-#include "asterisk/file.h"
-#include "asterisk/app.h"
-#include "asterisk/dsp.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/astdb.h"
-#include "asterisk/callerid.h"
-#include "asterisk/privacy.h"
-#include "asterisk/utils.h"
-#include "asterisk/lock.h"
-
-int ast_privacy_check(char *dest, char *cid)
-{
- char tmp[256] = "";
- char *trimcid = "";
- char *n, *l;
- int res;
- char key[256], result[256];
- if (cid)
- ast_copy_string(tmp, cid, sizeof(tmp));
- ast_callerid_parse(tmp, &n, &l);
- if (l) {
- ast_shrink_phone_number(l);
- trimcid = l;
- }
- snprintf(key, sizeof(key), "%s/%s", dest, trimcid);
- res = ast_db_get("privacy", key, result, sizeof(result));
- if (!res) {
- if (!strcasecmp(result, "allow"))
- return AST_PRIVACY_ALLOW;
- if (!strcasecmp(result, "deny"))
- return AST_PRIVACY_DENY;
- if (!strcasecmp(result, "kill"))
- return AST_PRIVACY_KILL;
- if (!strcasecmp(result, "torture"))
- return AST_PRIVACY_TORTURE;
- }
- return AST_PRIVACY_UNKNOWN;
-}
-
-int ast_privacy_reset(char *dest)
-{
- if (!dest)
- return -1;
- return ast_db_deltree("privacy", dest);
-}
-
-int ast_privacy_set(char *dest, char *cid, int status)
-{
- char tmp[256] = "";
- char *trimcid = "";
- char *n, *l;
- int res;
- char key[256];
- if (cid)
- ast_copy_string(tmp, cid, sizeof(tmp));
- ast_callerid_parse(tmp, &n, &l);
- if (l) {
- ast_shrink_phone_number(l);
- trimcid = l;
- }
- if (ast_strlen_zero(trimcid)) {
- /* Don't store anything for empty Caller*ID */
- return 0;
- }
- snprintf(key, sizeof(key), "%s/%s", dest, trimcid);
- if (status == AST_PRIVACY_UNKNOWN)
- res = ast_db_del("privacy", key);
- else if (status == AST_PRIVACY_ALLOW)
- res = ast_db_put("privacy", key, "allow");
- else if (status == AST_PRIVACY_DENY)
- res = ast_db_put("privacy", key, "deny");
- else if (status == AST_PRIVACY_KILL)
- res = ast_db_put("privacy", key, "kill");
- else if (status == AST_PRIVACY_TORTURE)
- res = ast_db_put("privacy", key, "torture");
- else
- res = -1;
- return res;
-}
diff --git a/main/rtp.c b/main/rtp.c
deleted file mode 100644
index 28fcad75f..000000000
--- a/main/rtp.c
+++ /dev/null
@@ -1,3833 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*!
- * \file
- *
- * \brief Supports RTP and RTCP with Symmetric RTP support for NAT traversal.
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * \note RTP is defined in RFC 3550.
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <netinet/in.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-
-#include "asterisk/rtp.h"
-#include "asterisk/frame.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/channel.h"
-#include "asterisk/acl.h"
-#include "asterisk/channel.h"
-#include "asterisk/config.h"
-#include "asterisk/lock.h"
-#include "asterisk/utils.h"
-#include "asterisk/cli.h"
-#include "asterisk/unaligned.h"
-#include "asterisk/utils.h"
-
-#define MAX_TIMESTAMP_SKEW 640
-
-#define RTP_SEQ_MOD (1<<16) /*!< A sequence number can't be more than 16 bits */
-#define RTCP_DEFAULT_INTERVALMS 5000 /*!< Default milli-seconds between RTCP reports we send */
-#define RTCP_MIN_INTERVALMS 500 /*!< Min milli-seconds between RTCP reports we send */
-#define RTCP_MAX_INTERVALMS 60000 /*!< Max milli-seconds between RTCP reports we send */
-
-#define RTCP_PT_FUR 192
-#define RTCP_PT_SR 200
-#define RTCP_PT_RR 201
-#define RTCP_PT_SDES 202
-#define RTCP_PT_BYE 203
-#define RTCP_PT_APP 204
-
-#define RTP_MTU 1200
-
-#define DEFAULT_DTMF_TIMEOUT 3000 /*!< samples */
-
-static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
-
-static int rtpstart; /*!< First port for RTP sessions (set in rtp.conf) */
-static int rtpend; /*!< Last port for RTP sessions (set in rtp.conf) */
-static int rtpdebug; /*!< Are we debugging? */
-static int rtcpdebug; /*!< Are we debugging RTCP? */
-static int rtcpstats; /*!< Are we debugging RTCP? */
-static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
-static int stundebug; /*!< Are we debugging stun? */
-static struct sockaddr_in rtpdebugaddr; /*!< Debug packets to/from this host */
-static struct sockaddr_in rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
-#ifdef SO_NO_CHECK
-static int nochecksums;
-#endif
-
-/* Uncomment this to enable more intense native bridging, but note: this is currently buggy */
-/* #define P2P_INTENSE */
-
-/*!
- * \brief Structure representing a RTP session.
- *
- * RTP session is defined on page 9 of RFC 3550: "An association among a set of participants communicating with RTP. A participant may be involved in multiple RTP sessions at the same time [...]"
- *
- */
-/*! \brief The value of each payload format mapping: */
-struct rtpPayloadType {
- int isAstFormat; /*!< whether the following code is an AST_FORMAT */
- int code;
-};
-
-
-/*! \brief RTP session description */
-struct ast_rtp {
- int s;
- struct ast_frame f;
- unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
- unsigned int ssrc; /*!< Synchronization source, RFC 3550, page 10. */
- unsigned int themssrc; /*!< Their SSRC */
- unsigned int rxssrc;
- unsigned int lastts;
- unsigned int lastrxts;
- unsigned int lastividtimestamp;
- unsigned int lastovidtimestamp;
- unsigned int lasteventseqn;
- int lastrxseqno; /*!< Last received sequence number */
- unsigned short seedrxseqno; /*!< What sequence number did they start with?*/
- unsigned int seedrxts; /*!< What RTP timestamp did they start with? */
- unsigned int rxcount; /*!< How many packets have we received? */
- unsigned int rxoctetcount; /*!< How many octets have we received? should be rxcount *160*/
- unsigned int txcount; /*!< How many packets have we sent? */
- unsigned int txoctetcount; /*!< How many octets have we sent? (txcount*160)*/
- unsigned int cycles; /*!< Shifted count of sequence number cycles */
- double rxjitter; /*!< Interarrival jitter at the moment */
- double rxtransit; /*!< Relative transit time for previous packet */
- int lasttxformat;
- int lastrxformat;
-
- int rtptimeout; /*!< RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
- int rtpholdtimeout; /*!< RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
- int rtpkeepalive; /*!< Send RTP comfort noice packets for keepalive */
-
- /* DTMF Reception Variables */
- char resp;
- unsigned int lastevent;
- int dtmfcount;
- unsigned int dtmfsamples;
- /* DTMF Transmission Variables */
- unsigned int lastdigitts;
- char sending_digit; /*!< boolean - are we sending digits */
- char send_digit; /*!< digit we are sending */
- int send_payload;
- int send_duration;
- int nat;
- unsigned int flags;
- struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
- struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
- struct timeval rxcore;
- struct timeval txcore;
- double drxcore; /*!< The double representation of the first received packet */
- struct timeval lastrx; /*!< timeval when we last received a packet */
- struct timeval dtmfmute;
- struct ast_smoother *smoother;
- int *ioid;
- unsigned short seqno; /*!< Sequence number, RFC 3550, page 13. */
- unsigned short rxseqno;
- struct sched_context *sched;
- struct io_context *io;
- void *data;
- ast_rtp_callback callback;
- ast_mutex_t bridge_lock;
- struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
- int rtp_lookup_code_cache_isAstFormat; /*!< a cache for the result of rtp_lookup_code(): */
- int rtp_lookup_code_cache_code;
- int rtp_lookup_code_cache_result;
- struct ast_rtcp *rtcp;
- struct ast_codec_pref pref;
- struct ast_rtp *bridged; /*!< Who we are Packet bridged to */
- int set_marker_bit:1; /*!< Whether to set the marker bit or not */
-};
-
-/* Forward declarations */
-static int ast_rtcp_write(const void *data);
-static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw);
-static int ast_rtcp_write_sr(const void *data);
-static int ast_rtcp_write_rr(const void *data);
-static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp);
-static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp);
-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
-
-#define FLAG_3389_WARNING (1 << 0)
-#define FLAG_NAT_ACTIVE (3 << 1)
-#define FLAG_NAT_INACTIVE (0 << 1)
-#define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
-#define FLAG_HAS_DTMF (1 << 3)
-#define FLAG_P2P_SENT_MARK (1 << 4)
-#define FLAG_P2P_NEED_DTMF (1 << 5)
-#define FLAG_CALLBACK_MODE (1 << 6)
-#define FLAG_DTMF_COMPENSATE (1 << 7)
-#define FLAG_HAS_STUN (1 << 8)
-
-/*!
- * \brief Structure defining an RTCP session.
- *
- * The concept "RTCP session" is not defined in RFC 3550, but since
- * this structure is analogous to ast_rtp, which tracks a RTP session,
- * it is logical to think of this as a RTCP session.
- *
- * RTCP packet is defined on page 9 of RFC 3550.
- *
- */
-struct ast_rtcp {
- int s; /*!< Socket */
- struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
- struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
- unsigned int soc; /*!< What they told us */
- unsigned int spc; /*!< What they told us */
- unsigned int themrxlsr; /*!< The middle 32 bits of the NTP timestamp in the last received SR*/
- struct timeval rxlsr; /*!< Time when we got their last SR */
- struct timeval txlsr; /*!< Time when we sent or last SR*/
- unsigned int expected_prior; /*!< no. packets in previous interval */
- unsigned int received_prior; /*!< no. packets received in previous interval */
- int schedid; /*!< Schedid returned from ast_sched_add() to schedule RTCP-transmissions*/
- unsigned int rr_count; /*!< number of RRs we've sent, not including report blocks in SR's */
- unsigned int sr_count; /*!< number of SRs we've sent */
- unsigned int lastsrtxcount; /*!< Transmit packet count when last SR sent */
- double accumulated_transit; /*!< accumulated a-dlsr-lsr */
- double rtt; /*!< Last reported rtt */
- unsigned int reported_jitter; /*!< The contents of their last jitter entry in the RR */
- unsigned int reported_lost; /*!< Reported lost packets in their RR */
- char quality[AST_MAX_USER_FIELD];
- double maxrxjitter;
- double minrxjitter;
- double maxrtt;
- double minrtt;
- int sendfur;
-};
-
-
-typedef struct { unsigned int id[4]; } __attribute__((packed)) stun_trans_id;
-
-/* XXX Maybe stun belongs in another file if it ever has use outside of RTP */
-struct stun_header {
- unsigned short msgtype;
- unsigned short msglen;
- stun_trans_id id;
- unsigned char ies[0];
-} __attribute__((packed));
-
-struct stun_attr {
- unsigned short attr;
- unsigned short len;
- unsigned char value[0];
-} __attribute__((packed));
-
-struct stun_addr {
- unsigned char unused;
- unsigned char family;
- unsigned short port;
- unsigned int addr;
-} __attribute__((packed));
-
-#define STUN_IGNORE (0)
-#define STUN_ACCEPT (1)
-
-#define STUN_BINDREQ 0x0001
-#define STUN_BINDRESP 0x0101
-#define STUN_BINDERR 0x0111
-#define STUN_SECREQ 0x0002
-#define STUN_SECRESP 0x0102
-#define STUN_SECERR 0x0112
-
-#define STUN_MAPPED_ADDRESS 0x0001
-#define STUN_RESPONSE_ADDRESS 0x0002
-#define STUN_CHANGE_REQUEST 0x0003
-#define STUN_SOURCE_ADDRESS 0x0004
-#define STUN_CHANGED_ADDRESS 0x0005
-#define STUN_USERNAME 0x0006
-#define STUN_PASSWORD 0x0007
-#define STUN_MESSAGE_INTEGRITY 0x0008
-#define STUN_ERROR_CODE 0x0009
-#define STUN_UNKNOWN_ATTRIBUTES 0x000a
-#define STUN_REFLECTED_FROM 0x000b
-
-static const char *stun_msg2str(int msg)
-{
- switch(msg) {
- case STUN_BINDREQ:
- return "Binding Request";
- case STUN_BINDRESP:
- return "Binding Response";
- case STUN_BINDERR:
- return "Binding Error Response";
- case STUN_SECREQ:
- return "Shared Secret Request";
- case STUN_SECRESP:
- return "Shared Secret Response";
- case STUN_SECERR:
- return "Shared Secret Error Response";
- }
- return "Non-RFC3489 Message";
-}
-
-static const char *stun_attr2str(int msg)
-{
- switch(msg) {
- case STUN_MAPPED_ADDRESS:
- return "Mapped Address";
- case STUN_RESPONSE_ADDRESS:
- return "Response Address";
- case STUN_CHANGE_REQUEST:
- return "Change Request";
- case STUN_SOURCE_ADDRESS:
- return "Source Address";
- case STUN_CHANGED_ADDRESS:
- return "Changed Address";
- case STUN_USERNAME:
- return "Username";
- case STUN_PASSWORD:
- return "Password";
- case STUN_MESSAGE_INTEGRITY:
- return "Message Integrity";
- case STUN_ERROR_CODE:
- return "Error Code";
- case STUN_UNKNOWN_ATTRIBUTES:
- return "Unknown Attributes";
- case STUN_REFLECTED_FROM:
- return "Reflected From";
- }
- return "Non-RFC3489 Attribute";
-}
-
-struct stun_state {
- const char *username;
- const char *password;
-};
-
-static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
-{
- if (stundebug)
- ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
- stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
- switch(ntohs(attr->attr)) {
- case STUN_USERNAME:
- state->username = (const char *) (attr->value);
- break;
- case STUN_PASSWORD:
- state->password = (const char *) (attr->value);
- break;
- default:
- if (stundebug)
- ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
- stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
- }
- return 0;
-}
-
-static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
-{
- int size = sizeof(**attr) + strlen(s);
- if (*left > size) {
- (*attr)->attr = htons(attrval);
- (*attr)->len = htons(strlen(s));
- memcpy((*attr)->value, s, strlen(s));
- (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
- *len += size;
- *left -= size;
- }
-}
-
-static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
-{
- int size = sizeof(**attr) + 8;
- struct stun_addr *addr;
- if (*left > size) {
- (*attr)->attr = htons(attrval);
- (*attr)->len = htons(8);
- addr = (struct stun_addr *)((*attr)->value);
- addr->unused = 0;
- addr->family = 0x01;
- addr->port = sin->sin_port;
- addr->addr = sin->sin_addr.s_addr;
- (*attr) = (struct stun_attr *)((*attr)->value + 8);
- *len += size;
- *left -= size;
- }
-}
-
-static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
-{
- return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
- (struct sockaddr *)dst, sizeof(*dst));
-}
-
-static void stun_req_id(struct stun_header *req)
-{
- int x;
- for (x=0;x<4;x++)
- req->id.id[x] = ast_random();
-}
-
-size_t ast_rtp_alloc_size(void)
-{
- return sizeof(struct ast_rtp);
-}
-
-void ast_rtp_stun_request(struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
-{
- struct stun_header *req;
- unsigned char reqdata[1024];
- int reqlen, reqleft;
- struct stun_attr *attr;
-
- req = (struct stun_header *)reqdata;
- stun_req_id(req);
- reqlen = 0;
- reqleft = sizeof(reqdata) - sizeof(struct stun_header);
- req->msgtype = 0;
- req->msglen = 0;
- attr = (struct stun_attr *)req->ies;
- if (username)
- append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
- req->msglen = htons(reqlen);
- req->msgtype = htons(STUN_BINDREQ);
- stun_send(rtp->s, suggestion, req);
-}
-
-static int stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len)
-{
- struct stun_header *resp, *hdr = (struct stun_header *)data;
- struct stun_attr *attr;
- struct stun_state st;
- int ret = STUN_IGNORE;
- unsigned char respdata[1024];
- int resplen, respleft;
-
- if (len < sizeof(struct stun_header)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Runt STUN packet (only %zd, wanting at least %zd)\n", len, sizeof(struct stun_header));
- return -1;
- }
- if (stundebug)
- ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), ntohs(hdr->msglen));
- if (ntohs(hdr->msglen) > len - sizeof(struct stun_header)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Scrambled STUN packet length (got %d, expecting %zd)\n", ntohs(hdr->msglen), len - sizeof(struct stun_header));
- } else
- len = ntohs(hdr->msglen);
- data += sizeof(struct stun_header);
- memset(&st, 0, sizeof(st));
- while(len) {
- if (len < sizeof(struct stun_attr)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Runt Attribute (got %zd, expecting %zd)\n", len, sizeof(struct stun_attr));
- break;
- }
- attr = (struct stun_attr *)data;
- if ((ntohs(attr->len) + sizeof(struct stun_attr)) > len) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", (int) (ntohs(attr->len) + sizeof(struct stun_attr)), (int) len);
- break;
- }
- if (stun_process_attr(&st, attr)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
- break;
- }
- /* Clear attribute in case previous entry was a string */
- attr->attr = 0;
- data += ntohs(attr->len) + sizeof(struct stun_attr);
- len -= ntohs(attr->len) + sizeof(struct stun_attr);
- }
- /* Null terminate any string */
- *data = '\0';
- resp = (struct stun_header *)respdata;
- resplen = 0;
- respleft = sizeof(respdata) - sizeof(struct stun_header);
- resp->id = hdr->id;
- resp->msgtype = 0;
- resp->msglen = 0;
- attr = (struct stun_attr *)resp->ies;
- if (!len) {
- switch(ntohs(hdr->msgtype)) {
- case STUN_BINDREQ:
- if (stundebug)
- ast_verbose("STUN Bind Request, username: %s\n",
- st.username ? st.username : "<none>");
- if (st.username)
- append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
- append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
- resp->msglen = htons(resplen);
- resp->msgtype = htons(STUN_BINDRESP);
- stun_send(s, src, resp);
- ret = STUN_ACCEPT;
- break;
- default:
- if (stundebug)
- ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
- }
- }
- return ret;
-}
-
-/*! \brief List of current sessions */
-static AST_LIST_HEAD_STATIC(protos, ast_rtp_protocol);
-
-static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
-{
- unsigned int sec, usec, frac;
- sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
- usec = tv.tv_usec;
- frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
- *msw = sec;
- *lsw = frac;
-}
-
-int ast_rtp_fd(struct ast_rtp *rtp)
-{
- return rtp->s;
-}
-
-int ast_rtcp_fd(struct ast_rtp *rtp)
-{
- if (rtp->rtcp)
- return rtp->rtcp->s;
- return -1;
-}
-
-unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
-{
- unsigned int interval;
- /*! \todo XXX Do a more reasonable calculation on this one
- * Look in RFC 3550 Section A.7 for an example*/
- interval = rtcpinterval;
- return interval;
-}
-
-/* \brief Put RTP timeout timers on hold during another transaction, like T.38 */
-void ast_rtp_set_rtptimers_onhold(struct ast_rtp *rtp)
-{
- rtp->rtptimeout = (-1) * rtp->rtptimeout;
- rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
-}
-
-/*! \brief Set rtp timeout */
-void ast_rtp_set_rtptimeout(struct ast_rtp *rtp, int timeout)
-{
- rtp->rtptimeout = timeout;
-}
-
-/*! \brief Set rtp hold timeout */
-void ast_rtp_set_rtpholdtimeout(struct ast_rtp *rtp, int timeout)
-{
- rtp->rtpholdtimeout = timeout;
-}
-
-/*! \brief set RTP keepalive interval */
-void ast_rtp_set_rtpkeepalive(struct ast_rtp *rtp, int period)
-{
- rtp->rtpkeepalive = period;
-}
-
-/*! \brief Get rtp timeout */
-int ast_rtp_get_rtptimeout(struct ast_rtp *rtp)
-{
- if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */
- return 0;
- return rtp->rtptimeout;
-}
-
-/*! \brief Get rtp hold timeout */
-int ast_rtp_get_rtpholdtimeout(struct ast_rtp *rtp)
-{
- if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */
- return 0;
- return rtp->rtpholdtimeout;
-}
-
-/*! \brief Get RTP keepalive interval */
-int ast_rtp_get_rtpkeepalive(struct ast_rtp *rtp)
-{
- return rtp->rtpkeepalive;
-}
-
-void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
-{
- rtp->data = data;
-}
-
-void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
-{
- rtp->callback = callback;
-}
-
-void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
-{
- rtp->nat = nat;
-}
-
-int ast_rtp_getnat(struct ast_rtp *rtp)
-{
- return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
-}
-
-void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf)
-{
- ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
-}
-
-void ast_rtp_setdtmfcompensate(struct ast_rtp *rtp, int compensate)
-{
- ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
-}
-
-void ast_rtp_setstun(struct ast_rtp *rtp, int stun_enable)
-{
- ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
-}
-
-static struct ast_frame *send_dtmf(struct ast_rtp *rtp, enum ast_frame_type type)
-{
- if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
- (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
- rtp->resp = 0;
- rtp->dtmfsamples = 0;
- return &ast_null_frame;
- }
- if (option_debug)
- ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
- if (rtp->resp == 'X') {
- rtp->f.frametype = AST_FRAME_CONTROL;
- rtp->f.subclass = AST_CONTROL_FLASH;
- } else {
- rtp->f.frametype = type;
- rtp->f.subclass = rtp->resp;
- }
- rtp->f.datalen = 0;
- rtp->f.samples = 0;
- rtp->f.mallocd = 0;
- rtp->f.src = "RTP";
- return &rtp->f;
-
-}
-
-static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
-{
- if (rtpdebug == 0)
- return 0;
- if (rtpdebugaddr.sin_addr.s_addr) {
- if (((ntohs(rtpdebugaddr.sin_port) != 0)
- && (rtpdebugaddr.sin_port != addr->sin_port))
- || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
- return 0;
- }
- return 1;
-}
-
-static inline int rtcp_debug_test_addr(struct sockaddr_in *addr)
-{
- if (rtcpdebug == 0)
- return 0;
- if (rtcpdebugaddr.sin_addr.s_addr) {
- if (((ntohs(rtcpdebugaddr.sin_port) != 0)
- && (rtcpdebugaddr.sin_port != addr->sin_port))
- || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
- return 0;
- }
- return 1;
-}
-
-
-static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *data, int len)
-{
- unsigned int event;
- char resp = 0;
- struct ast_frame *f = NULL;
- event = ntohl(*((unsigned int *)(data)));
- event &= 0x001F;
- if (option_debug > 2 || rtpdebug)
- ast_log(LOG_DEBUG, "Cisco DTMF Digit: %08x (len = %d)\n", event, len);
- if (event < 10) {
- resp = '0' + event;
- } else if (event < 11) {
- resp = '*';
- } else if (event < 12) {
- resp = '#';
- } else if (event < 16) {
- resp = 'A' + (event - 12);
- } else if (event < 17) {
- resp = 'X';
- }
- if (rtp->resp && (rtp->resp != resp)) {
- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
- }
- rtp->resp = resp;
- rtp->dtmfcount = dtmftimeout;
- return f;
-}
-
-/*!
- * \brief Process RTP DTMF and events according to RFC 2833.
- *
- * RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".
- *
- * \param rtp
- * \param data
- * \param len
- * \param seqno
- * \returns
- */
-static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp)
-{
- unsigned int event;
- unsigned int event_end;
- unsigned int samples;
- char resp = 0;
- struct ast_frame *f = NULL;
-
- /* Figure out event, event end, and samples */
- event = ntohl(*((unsigned int *)(data)));
- event >>= 24;
- event_end = ntohl(*((unsigned int *)(data)));
- event_end <<= 8;
- event_end >>= 24;
- samples = ntohl(*((unsigned int *)(data)));
- samples &= 0xFFFF;
-
- /* Print out debug if turned on */
- if (rtpdebug || option_debug > 2)
- ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
-
- /* Figure out what digit was pressed */
- if (event < 10) {
- resp = '0' + event;
- } else if (event < 11) {
- resp = '*';
- } else if (event < 12) {
- resp = '#';
- } else if (event < 16) {
- resp = 'A' + (event - 12);
- } else if (event < 17) { /* Event 16: Hook flash */
- resp = 'X';
- } else {
- /* Not a supported event */
- ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
- return &ast_null_frame;
- }
-
- if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
- if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
- rtp->resp = resp;
- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
- f->len = 0;
- rtp->lastevent = timestamp;
- }
- } else {
- if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) {
- rtp->resp = resp;
- f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
- } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) {
- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
- f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
- rtp->resp = 0;
- rtp->lastevent = seqno;
- }
- }
-
- rtp->dtmfcount = dtmftimeout;
- rtp->dtmfsamples = samples;
-
- return f;
-}
-
-/*!
- * \brief Process Comfort Noise RTP.
- *
- * This is incomplete at the moment.
- *
-*/
-static struct ast_frame *process_rfc3389(struct ast_rtp *rtp, unsigned char *data, int len)
-{
- struct ast_frame *f = NULL;
- /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
- totally help us out becuase we don't have an engine to keep it going and we are not
- guaranteed to have it every 20ms or anything */
- if (rtpdebug)
- ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
-
- if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
- ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
- ast_inet_ntoa(rtp->them.sin_addr));
- ast_set_flag(rtp, FLAG_3389_WARNING);
- }
-
- /* Must have at least one byte */
- if (!len)
- return NULL;
- if (len < 24) {
- rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
- rtp->f.datalen = len - 1;
- rtp->f.offset = AST_FRIENDLY_OFFSET;
- memcpy(rtp->f.data, data + 1, len - 1);
- } else {
- rtp->f.data = NULL;
- rtp->f.offset = 0;
- rtp->f.datalen = 0;
- }
- rtp->f.frametype = AST_FRAME_CNG;
- rtp->f.subclass = data[0] & 0x7f;
- rtp->f.datalen = len - 1;
- rtp->f.samples = 0;
- rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
- f = &rtp->f;
- return f;
-}
-
-static int rtpread(int *id, int fd, short events, void *cbdata)
-{
- struct ast_rtp *rtp = cbdata;
- struct ast_frame *f;
- f = ast_rtp_read(rtp);
- if (f) {
- if (rtp->callback)
- rtp->callback(rtp, f, rtp->data);
- }
- return 1;
-}
-
-struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
-{
- socklen_t len;
- int position, i, packetwords;
- int res;
- struct sockaddr_in sin;
- unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
- unsigned int *rtcpheader;
- int pt;
- struct timeval now;
- unsigned int length;
- int rc;
- double rttsec;
- uint64_t rtt = 0;
- unsigned int dlsr;
- unsigned int lsr;
- unsigned int msw;
- unsigned int lsw;
- unsigned int comp;
- struct ast_frame *f = &ast_null_frame;
-
- if (!rtp || !rtp->rtcp)
- return &ast_null_frame;
-
- len = sizeof(sin);
-
- res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
- 0, (struct sockaddr *)&sin, &len);
- rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
-
- if (res < 0) {
- ast_assert(errno != EBADF);
- if (errno != EAGAIN) {
- ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno));
- return NULL;
- }
- return &ast_null_frame;
- }
-
- packetwords = res / 4;
-
- if (rtp->nat) {
- /* Send to whoever sent to us */
- if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
- (rtp->rtcp->them.sin_port != sin.sin_port)) {
- memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
- if (option_debug || rtpdebug)
- ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
- }
- }
-
- if (option_debug)
- ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
-
- /* Process a compound packet */
- position = 0;
- while (position < packetwords) {
- i = position;
- length = ntohl(rtcpheader[i]);
- pt = (length & 0xff0000) >> 16;
- rc = (length & 0x1f000000) >> 24;
- length &= 0xffff;
-
- if ((i + length) > packetwords) {
- ast_log(LOG_WARNING, "RTCP Read too short\n");
- return &ast_null_frame;
- }
-
- if (rtcp_debug_test_addr(&sin)) {
- ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
- ast_verbose("Reception reports: %d\n", rc);
- ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
- }
-
- i += 2; /* Advance past header and ssrc */
-
- switch (pt) {
- case RTCP_PT_SR:
- gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
- rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
- rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
- rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
-
- if (rtcp_debug_test_addr(&sin)) {
- ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
- ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
- ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
- }
- i += 5;
- if (rc < 1)
- break;
- /* Intentional fall through */
- case RTCP_PT_RR:
- /* Don't handle multiple reception reports (rc > 1) yet */
- /* Calculate RTT per RFC */
- gettimeofday(&now, NULL);
- timeval2ntp(now, &msw, &lsw);
- if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
- comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
- lsr = ntohl(rtcpheader[i + 4]);
- dlsr = ntohl(rtcpheader[i + 5]);
- rtt = comp - lsr - dlsr;
-
- /* Convert end to end delay to usec (keeping the calculation in 64bit space)
- sess->ee_delay = (eedelay * 1000) / 65536; */
- if (rtt < 4294) {
- rtt = (rtt * 1000000) >> 16;
- } else {
- rtt = (rtt * 1000) >> 16;
- rtt *= 1000;
- }
- rtt = rtt / 1000.;
- rttsec = rtt / 1000.;
-
- if (comp - dlsr >= lsr) {
- rtp->rtcp->accumulated_transit += rttsec;
- rtp->rtcp->rtt = rttsec;
- if (rtp->rtcp->maxrtt<rttsec)
- rtp->rtcp->maxrtt = rttsec;
- if (rtp->rtcp->minrtt>rttsec)
- rtp->rtcp->minrtt = rttsec;
- } else if (rtcp_debug_test_addr(&sin)) {
- ast_verbose("Internal RTCP NTP clock skew detected: "
- "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
- "diff=%d\n",
- lsr, comp, dlsr, dlsr / 65536,
- (dlsr % 65536) * 1000 / 65536,
- dlsr - (comp - lsr));
- }
- }
-
- rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
- rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
- if (rtcp_debug_test_addr(&sin)) {
- ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
- ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost);
- ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
- ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
- ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
- ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
- ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
- if (rtt)
- ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt);
- }
- break;
- case RTCP_PT_FUR:
- if (rtcp_debug_test_addr(&sin))
- ast_verbose("Received an RTCP Fast Update Request\n");
- rtp->f.frametype = AST_FRAME_CONTROL;
- rtp->f.subclass = AST_CONTROL_VIDUPDATE;
- rtp->f.datalen = 0;
- rtp->f.samples = 0;
- rtp->f.mallocd = 0;
- rtp->f.src = "RTP";
- f = &rtp->f;
- break;
- case RTCP_PT_SDES:
- if (rtcp_debug_test_addr(&sin))
- ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
- break;
- case RTCP_PT_BYE:
- if (rtcp_debug_test_addr(&sin))
- ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
- break;
- default:
- if (option_debug)
- ast_log(LOG_DEBUG, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
- break;
- }
- position += (length + 1);
- }
-
- return f;
-}
-
-static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
-{
- struct timeval now;
- double transit;
- double current_time;
- double d;
- double dtv;
- double prog;
-
- if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
- gettimeofday(&rtp->rxcore, NULL);
- rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
- /* map timestamp to a real time */
- rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
- rtp->rxcore.tv_sec -= timestamp / 8000;
- rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
- /* Round to 0.1ms for nice, pretty timestamps */
- rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
- if (rtp->rxcore.tv_usec < 0) {
- /* Adjust appropriately if necessary */
- rtp->rxcore.tv_usec += 1000000;
- rtp->rxcore.tv_sec -= 1;
- }
- }
-
- gettimeofday(&now,NULL);
- /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
- tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
- tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
- if (tv->tv_usec >= 1000000) {
- tv->tv_usec -= 1000000;
- tv->tv_sec += 1;
- }
- prog = (double)((timestamp-rtp->seedrxts)/8000.);
- dtv = (double)rtp->drxcore + (double)(prog);
- current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
- transit = current_time - dtv;
- d = transit - rtp->rxtransit;
- rtp->rxtransit = transit;
- if (d<0)
- d=-d;
- rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
- if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
- rtp->rtcp->maxrxjitter = rtp->rxjitter;
- if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
- rtp->rtcp->minrxjitter = rtp->rxjitter;
-}
-
-/*! \brief Perform a Packet2Packet RTP write */
-static int bridge_p2p_rtp_write(struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen)
-{
- int res = 0, payload = 0, bridged_payload = 0, mark;
- struct rtpPayloadType rtpPT;
- int reconstruct = ntohl(rtpheader[0]);
-
- /* Get fields from packet */
- payload = (reconstruct & 0x7f0000) >> 16;
- mark = (((reconstruct & 0x800000) >> 23) != 0);
-
- /* Check what the payload value should be */
- rtpPT = ast_rtp_lookup_pt(rtp, payload);
-
- /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
- if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
- return -1;
-
- /* Otherwise adjust bridged payload to match */
- bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
-
- /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
- if (!bridged->current_RTP_PT[bridged_payload].code)
- return -1;
-
-
- /* If the mark bit has not been sent yet... do it now */
- if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
- mark = 1;
- ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
- }
-
- /* Reconstruct part of the packet */
- reconstruct &= 0xFF80FFFF;
- reconstruct |= (bridged_payload << 16);
- reconstruct |= (mark << 23);
- rtpheader[0] = htonl(reconstruct);
-
- /* Send the packet back out */
- res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
- if (res < 0) {
- if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
- ast_log(LOG_DEBUG, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno));
- } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
- if (option_debug || rtpdebug)
- ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port));
- ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
- }
- return 0;
- } else if (rtp_debug_test_addr(&bridged->them))
- ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), bridged_payload, len - hdrlen);
-
- return 0;
-}
-
-struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
-{
- int res;
- struct sockaddr_in sin;
- socklen_t len;
- unsigned int seqno;
- int version;
- int payloadtype;
- int hdrlen = 12;
- int padding;
- int mark;
- int ext;
- int cc;
- unsigned int ssrc;
- unsigned int timestamp;
- unsigned int *rtpheader;
- struct rtpPayloadType rtpPT;
- struct ast_rtp *bridged = NULL;
-
- /* If time is up, kill it */
- if (rtp->sending_digit)
- ast_rtp_senddigit_continuation(rtp);
-
- len = sizeof(sin);
-
- /* Cache where the header will go */
- res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
- 0, (struct sockaddr *)&sin, &len);
-
- rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
- if (res < 0) {
- ast_assert(errno != EBADF);
- if (errno != EAGAIN) {
- ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
- return NULL;
- }
- return &ast_null_frame;
- }
-
- if (res < hdrlen) {
- ast_log(LOG_WARNING, "RTP Read too short\n");
- return &ast_null_frame;
- }
-
- /* Get fields */
- seqno = ntohl(rtpheader[0]);
-
- /* Check RTP version */
- version = (seqno & 0xC0000000) >> 30;
- if (!version) {
- if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) &&
- (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
- memcpy(&rtp->them, &sin, sizeof(rtp->them));
- }
- return &ast_null_frame;
- }
-
-#if 0 /* Allow to receive RTP stream with closed transmission path */
- /* If we don't have the other side's address, then ignore this */
- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
- return &ast_null_frame;
-#endif
-
- /* Send to whoever send to us if NAT is turned on */
- if (rtp->nat) {
- if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
- (rtp->them.sin_port != sin.sin_port)) {
- rtp->them = sin;
- if (rtp->rtcp) {
- memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
- rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1);
- }
- rtp->rxseqno = 0;
- ast_set_flag(rtp, FLAG_NAT_ACTIVE);
- if (option_debug || rtpdebug)
- ast_log(LOG_DEBUG, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
- }
- }
-
- /* If we are bridged to another RTP stream, send direct */
- if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
- return &ast_null_frame;
-
- if (version != 2)
- return &ast_null_frame;
-
- payloadtype = (seqno & 0x7f0000) >> 16;
- padding = seqno & (1 << 29);
- mark = seqno & (1 << 23);
- ext = seqno & (1 << 28);
- cc = (seqno & 0xF000000) >> 24;
- seqno &= 0xffff;
- timestamp = ntohl(rtpheader[1]);
- ssrc = ntohl(rtpheader[2]);
-
- if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
- if (option_debug || rtpdebug)
- ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n");
- mark = 1;
- }
-
- rtp->rxssrc = ssrc;
-
- if (padding) {
- /* Remove padding bytes */
- res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
- }
-
- if (cc) {
- /* CSRC fields present */
- hdrlen += cc*4;
- }
-
- if (ext) {
- /* RTP Extension present */
- hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
- hdrlen += 4;
- }
-
- if (res < hdrlen) {
- ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
- return &ast_null_frame;
- }
-
- rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
-
- if (rtp->rxcount==1) {
- /* This is the first RTP packet successfully received from source */
- rtp->seedrxseqno = seqno;
- }
-
- /* Do not schedule RR if RTCP isn't run */
- if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
- /* Schedule transmission of Receiver Report */
- rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
- }
- if ( (int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
- rtp->cycles += RTP_SEQ_MOD;
-
- rtp->lastrxseqno = seqno;
-
- if (rtp->themssrc==0)
- rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
-
- if (rtp_debug_test_addr(&sin))
- ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
-
- rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
- if (!rtpPT.isAstFormat) {
- struct ast_frame *f = NULL;
-
- /* This is special in-band data that's not one of our codecs */
- if (rtpPT.code == AST_RTP_DTMF) {
- /* It's special -- rfc2833 process it */
- if (rtp_debug_test_addr(&sin)) {
- unsigned char *data;
- unsigned int event;
- unsigned int event_end;
- unsigned int duration;
- data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
- event = ntohl(*((unsigned int *)(data)));
- event >>= 24;
- event_end = ntohl(*((unsigned int *)(data)));
- event_end <<= 8;
- event_end >>= 24;
- duration = ntohl(*((unsigned int *)(data)));
- duration &= 0xFFFF;
- ast_verbose("Got RTP RFC2833 from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
- }
- f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
- } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
- /* It's really special -- process it the Cisco way */
- if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
- f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
- rtp->lastevent = seqno;
- }
- } else if (rtpPT.code == AST_RTP_CN) {
- /* Comfort Noise */
- f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
- } else {
- ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
- }
- return f ? f : &ast_null_frame;
- }
- rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
- rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO;
-
- if (!rtp->lastrxts)
- rtp->lastrxts = timestamp;
-
- rtp->rxseqno = seqno;
-
- /* Record received timestamp as last received now */
- rtp->lastrxts = timestamp;
-
- rtp->f.mallocd = 0;
- rtp->f.datalen = res - hdrlen;
- rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
- rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
- rtp->f.seqno = seqno;
- if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
- rtp->f.samples = ast_codec_get_samples(&rtp->f);
- if (rtp->f.subclass == AST_FORMAT_SLINEAR)
- ast_frame_byteswap_be(&rtp->f);
- calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
- /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
- ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
- rtp->f.ts = timestamp / 8;
- rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000);
- } else {
- /* Video -- samples is # of samples vs. 90000 */
- if (!rtp->lastividtimestamp)
- rtp->lastividtimestamp = timestamp;
- rtp->f.samples = timestamp - rtp->lastividtimestamp;
- rtp->lastividtimestamp = timestamp;
- rtp->f.delivery.tv_sec = 0;
- rtp->f.delivery.tv_usec = 0;
- if (mark)
- rtp->f.subclass |= 0x1;
-
- }
- rtp->f.src = "RTP";
- return &rtp->f;
-}
-
-/* The following array defines the MIME Media type (and subtype) for each
- of our codecs, or RTP-specific data type. */
-static struct {
- struct rtpPayloadType payloadType;
- char* type;
- char* subtype;
-} mimeTypes[] = {
- {{1, AST_FORMAT_G723_1}, "audio", "G723"},
- {{1, AST_FORMAT_GSM}, "audio", "GSM"},
- {{1, AST_FORMAT_ULAW}, "audio", "PCMU"},
- {{1, AST_FORMAT_ULAW}, "audio", "G711U"},
- {{1, AST_FORMAT_ALAW}, "audio", "PCMA"},
- {{1, AST_FORMAT_ALAW}, "audio", "G711A"},
- {{1, AST_FORMAT_G726}, "audio", "G726-32"},
- {{1, AST_FORMAT_ADPCM}, "audio", "DVI4"},
- {{1, AST_FORMAT_SLINEAR}, "audio", "L16"},
- {{1, AST_FORMAT_LPC10}, "audio", "LPC"},
- {{1, AST_FORMAT_G729A}, "audio", "G729"},
- {{1, AST_FORMAT_G729A}, "audio", "G729A"},
- {{1, AST_FORMAT_G729A}, "audio", "G.729"},
- {{1, AST_FORMAT_SPEEX}, "audio", "speex"},
- {{1, AST_FORMAT_ILBC}, "audio", "iLBC"},
- {{1, AST_FORMAT_G722}, "audio", "G722"},
- {{1, AST_FORMAT_G726_AAL2}, "audio", "AAL2-G726-32"},
- {{0, AST_RTP_DTMF}, "audio", "telephone-event"},
- {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event"},
- {{0, AST_RTP_CN}, "audio", "CN"},
- {{1, AST_FORMAT_JPEG}, "video", "JPEG"},
- {{1, AST_FORMAT_PNG}, "video", "PNG"},
- {{1, AST_FORMAT_H261}, "video", "H261"},
- {{1, AST_FORMAT_H263}, "video", "H263"},
- {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998"},
- {{1, AST_FORMAT_H264}, "video", "H264"},
-};
-
-/* Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
- also, our own choices for dynamic payload types. This is our master
- table for transmission */
-static struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] = {
- [0] = {1, AST_FORMAT_ULAW},
-#ifdef USE_DEPRECATED_G726
- [2] = {1, AST_FORMAT_G726}, /* Technically this is G.721, but if Cisco can do it, so can we... */
-#endif
- [3] = {1, AST_FORMAT_GSM},
- [4] = {1, AST_FORMAT_G723_1},
- [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */
- [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */
- [7] = {1, AST_FORMAT_LPC10},
- [8] = {1, AST_FORMAT_ALAW},
- [9] = {1, AST_FORMAT_G722},
- [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */
- [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */
- [13] = {0, AST_RTP_CN},
- [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */
- [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */
- [18] = {1, AST_FORMAT_G729A},
- [19] = {0, AST_RTP_CN}, /* Also used for CN */
- [26] = {1, AST_FORMAT_JPEG},
- [31] = {1, AST_FORMAT_H261},
- [34] = {1, AST_FORMAT_H263},
- [103] = {1, AST_FORMAT_H263_PLUS},
- [97] = {1, AST_FORMAT_ILBC},
- [99] = {1, AST_FORMAT_H264},
- [101] = {0, AST_RTP_DTMF},
- [110] = {1, AST_FORMAT_SPEEX},
- [111] = {1, AST_FORMAT_G726},
- [112] = {1, AST_FORMAT_G726_AAL2},
- [121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
-};
-
-void ast_rtp_pt_clear(struct ast_rtp* rtp)
-{
- int i;
-
- if (!rtp)
- return;
-
- ast_mutex_lock(&rtp->bridge_lock);
-
- for (i = 0; i < MAX_RTP_PT; ++i) {
- rtp->current_RTP_PT[i].isAstFormat = 0;
- rtp->current_RTP_PT[i].code = 0;
- }
-
- rtp->rtp_lookup_code_cache_isAstFormat = 0;
- rtp->rtp_lookup_code_cache_code = 0;
- rtp->rtp_lookup_code_cache_result = 0;
-
- ast_mutex_unlock(&rtp->bridge_lock);
-}
-
-void ast_rtp_pt_default(struct ast_rtp* rtp)
-{
- int i;
-
- ast_mutex_lock(&rtp->bridge_lock);
-
- /* Initialize to default payload types */
- for (i = 0; i < MAX_RTP_PT; ++i) {
- rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
- rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
- }
-
- rtp->rtp_lookup_code_cache_isAstFormat = 0;
- rtp->rtp_lookup_code_cache_code = 0;
- rtp->rtp_lookup_code_cache_result = 0;
-
- ast_mutex_unlock(&rtp->bridge_lock);
-}
-
-void ast_rtp_pt_copy(struct ast_rtp *dest, struct ast_rtp *src)
-{
- unsigned int i;
-
- ast_mutex_lock(&dest->bridge_lock);
- ast_mutex_lock(&src->bridge_lock);
-
- for (i=0; i < MAX_RTP_PT; ++i) {
- dest->current_RTP_PT[i].isAstFormat =
- src->current_RTP_PT[i].isAstFormat;
- dest->current_RTP_PT[i].code =
- src->current_RTP_PT[i].code;
- }
- dest->rtp_lookup_code_cache_isAstFormat = 0;
- dest->rtp_lookup_code_cache_code = 0;
- dest->rtp_lookup_code_cache_result = 0;
-
- ast_mutex_unlock(&src->bridge_lock);
- ast_mutex_unlock(&dest->bridge_lock);
-}
-
-/*! \brief Get channel driver interface structure */
-static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
-{
- struct ast_rtp_protocol *cur = NULL;
-
- AST_LIST_LOCK(&protos);
- AST_LIST_TRAVERSE(&protos, cur, list) {
- if (cur->type == chan->tech->type)
- break;
- }
- AST_LIST_UNLOCK(&protos);
-
- return cur;
-}
-
-int ast_rtp_early_bridge(struct ast_channel *dest, struct ast_channel *src)
-{
- struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */
- struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */
- struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
- enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
- enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
- int srccodec, destcodec, nat_active = 0;
-
- /* Lock channels */
- ast_channel_lock(dest);
- if (src) {
- while(ast_channel_trylock(src)) {
- ast_channel_unlock(dest);
- usleep(1);
- ast_channel_lock(dest);
- }
- }
-
- /* Find channel driver interfaces */
- destpr = get_proto(dest);
- if (src)
- srcpr = get_proto(src);
- if (!destpr) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
- ast_channel_unlock(dest);
- if (src)
- ast_channel_unlock(src);
- return 0;
- }
- if (!srcpr) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>");
- ast_channel_unlock(dest);
- if (src)
- ast_channel_unlock(src);
- return 0;
- }
-
- /* Get audio and video interface (if native bridge is possible) */
- audio_dest_res = destpr->get_rtp_info(dest, &destp);
- video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
- if (srcpr) {
- audio_src_res = srcpr->get_rtp_info(src, &srcp);
- video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
- }
-
- /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
- if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
- /* Somebody doesn't want to play... */
- ast_channel_unlock(dest);
- if (src)
- ast_channel_unlock(src);
- return 0;
- }
- if (audio_src_res == AST_RTP_TRY_NATIVE && (video_src_res == AST_RTP_GET_FAILED || video_src_res == AST_RTP_TRY_NATIVE) && srcpr->get_codec)
- srccodec = srcpr->get_codec(src);
- else
- srccodec = 0;
- if (audio_dest_res == AST_RTP_TRY_NATIVE && (video_dest_res == AST_RTP_GET_FAILED || video_dest_res == AST_RTP_TRY_NATIVE) && destpr->get_codec)
- destcodec = destpr->get_codec(dest);
- else
- destcodec = 0;
- /* Ensure we have at least one matching codec */
- if (srcp && !(srccodec & destcodec)) {
- ast_channel_unlock(dest);
- ast_channel_unlock(src);
- return 0;
- }
- /* Consider empty media as non-existant */
- if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
- srcp = NULL;
- /* If the client has NAT stuff turned on then just safe NAT is active */
- if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
- nat_active = 1;
- /* Bridge media early */
- if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active))
- ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>");
- ast_channel_unlock(dest);
- if (src)
- ast_channel_unlock(src);
- if (option_debug)
- ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>");
- return 1;
-}
-
-int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, int media)
-{
- struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */
- struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */
- struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
- enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
- enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
- int srccodec, destcodec;
-
- /* Lock channels */
- ast_channel_lock(dest);
- while(ast_channel_trylock(src)) {
- ast_channel_unlock(dest);
- usleep(1);
- ast_channel_lock(dest);
- }
-
- /* Find channel driver interfaces */
- if (!(destpr = get_proto(dest))) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
- ast_channel_unlock(dest);
- ast_channel_unlock(src);
- return 0;
- }
- if (!(srcpr = get_proto(src))) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name);
- ast_channel_unlock(dest);
- ast_channel_unlock(src);
- return 0;
- }
-
- /* Get audio and video interface (if native bridge is possible) */
- audio_dest_res = destpr->get_rtp_info(dest, &destp);
- video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
- audio_src_res = srcpr->get_rtp_info(src, &srcp);
- video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
-
- /* Ensure we have at least one matching codec */
- if (srcpr->get_codec)
- srccodec = srcpr->get_codec(src);
- else
- srccodec = 0;
- if (destpr->get_codec)
- destcodec = destpr->get_codec(dest);
- else
- destcodec = 0;
-
- /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
- if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE) || audio_src_res != AST_RTP_TRY_NATIVE || (video_src_res != AST_RTP_GET_FAILED && video_src_res != AST_RTP_TRY_NATIVE) || !(srccodec & destcodec)) {
- /* Somebody doesn't want to play... */
- ast_channel_unlock(dest);
- ast_channel_unlock(src);
- return 0;
- }
- ast_rtp_pt_copy(destp, srcp);
- if (vdestp && vsrcp)
- ast_rtp_pt_copy(vdestp, vsrcp);
- if (media) {
- /* Bridge early */
- if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
- ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
- }
- ast_channel_unlock(dest);
- ast_channel_unlock(src);
- if (option_debug)
- ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
- return 1;
-}
-
-/*! \brief Make a note of a RTP payload type that was seen in a SDP "m=" line.
- * By default, use the well-known value for this type (although it may
- * still be set to a different value by a subsequent "a=rtpmap:" line)
- */
-void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt)
-{
- if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0)
- return; /* bogus payload type */
-
- ast_mutex_lock(&rtp->bridge_lock);
- rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
- ast_mutex_unlock(&rtp->bridge_lock);
-}
-
-/*! \brief remove setting from payload type list if the rtpmap header indicates
- an unknown media type */
-void ast_rtp_unset_m_type(struct ast_rtp* rtp, int pt)
-{
- if (pt < 0 || pt > MAX_RTP_PT)
- return; /* bogus payload type */
-
- ast_mutex_lock(&rtp->bridge_lock);
- rtp->current_RTP_PT[pt].isAstFormat = 0;
- rtp->current_RTP_PT[pt].code = 0;
- ast_mutex_unlock(&rtp->bridge_lock);
-}
-
-/*! \brief Make a note of a RTP payload type (with MIME type) that was seen in
- * an SDP "a=rtpmap:" line.
- * \return 0 if the MIME type was found and set, -1 if it wasn't found
- */
-int ast_rtp_set_rtpmap_type(struct ast_rtp *rtp, int pt,
- char *mimeType, char *mimeSubtype,
- enum ast_rtp_options options)
-{
- unsigned int i;
- int found = 0;
-
- if (pt < 0 || pt > MAX_RTP_PT)
- return -1; /* bogus payload type */
-
- ast_mutex_lock(&rtp->bridge_lock);
-
- for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
- if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
- strcasecmp(mimeType, mimeTypes[i].type) == 0) {
- found = 1;
- rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
- if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
- mimeTypes[i].payloadType.isAstFormat &&
- (options & AST_RTP_OPT_G726_NONSTANDARD))
- rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
- break;
- }
- }
-
- ast_mutex_unlock(&rtp->bridge_lock);
-
- return (found ? 0 : -1);
-}
-
-/*! \brief Return the union of all of the codecs that were set by rtp_set...() calls
- * They're returned as two distinct sets: AST_FORMATs, and AST_RTPs */
-void ast_rtp_get_current_formats(struct ast_rtp* rtp,
- int* astFormats, int* nonAstFormats)
-{
- int pt;
-
- ast_mutex_lock(&rtp->bridge_lock);
-
- *astFormats = *nonAstFormats = 0;
- for (pt = 0; pt < MAX_RTP_PT; ++pt) {
- if (rtp->current_RTP_PT[pt].isAstFormat) {
- *astFormats |= rtp->current_RTP_PT[pt].code;
- } else {
- *nonAstFormats |= rtp->current_RTP_PT[pt].code;
- }
- }
-
- ast_mutex_unlock(&rtp->bridge_lock);
-
- return;
-}
-
-struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt)
-{
- struct rtpPayloadType result;
-
- result.isAstFormat = result.code = 0;
-
- if (pt < 0 || pt > MAX_RTP_PT)
- return result; /* bogus payload type */
-
- /* Start with negotiated codecs */
- ast_mutex_lock(&rtp->bridge_lock);
- result = rtp->current_RTP_PT[pt];
- ast_mutex_unlock(&rtp->bridge_lock);
-
- /* If it doesn't exist, check our static RTP type list, just in case */
- if (!result.code)
- result = static_RTP_PT[pt];
-
- return result;
-}
-
-/*! \brief Looks up an RTP code out of our *static* outbound list */
-int ast_rtp_lookup_code(struct ast_rtp* rtp, const int isAstFormat, const int code)
-{
- int pt = 0;
-
- ast_mutex_lock(&rtp->bridge_lock);
-
- if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
- code == rtp->rtp_lookup_code_cache_code) {
- /* Use our cached mapping, to avoid the overhead of the loop below */
- pt = rtp->rtp_lookup_code_cache_result;
- ast_mutex_unlock(&rtp->bridge_lock);
- return pt;
- }
-
- /* Check the dynamic list first */
- for (pt = 0; pt < MAX_RTP_PT; ++pt) {
- if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
- rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
- rtp->rtp_lookup_code_cache_code = code;
- rtp->rtp_lookup_code_cache_result = pt;
- ast_mutex_unlock(&rtp->bridge_lock);
- return pt;
- }
- }
-
- /* Then the static list */
- for (pt = 0; pt < MAX_RTP_PT; ++pt) {
- if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
- rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
- rtp->rtp_lookup_code_cache_code = code;
- rtp->rtp_lookup_code_cache_result = pt;
- ast_mutex_unlock(&rtp->bridge_lock);
- return pt;
- }
- }
-
- ast_mutex_unlock(&rtp->bridge_lock);
-
- return -1;
-}
-
-const char *ast_rtp_lookup_mime_subtype(const int isAstFormat, const int code,
- enum ast_rtp_options options)
-{
- unsigned int i;
-
- for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
- if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
- if (isAstFormat &&
- (code == AST_FORMAT_G726_AAL2) &&
- (options & AST_RTP_OPT_G726_NONSTANDARD))
- return "G726-32";
- else
- return mimeTypes[i].subtype;
- }
- }
-
- return "";
-}
-
-char *ast_rtp_lookup_mime_multiple(char *buf, size_t size, const int capability,
- const int isAstFormat, enum ast_rtp_options options)
-{
- int format;
- unsigned len;
- char *end = buf;
- char *start = buf;
-
- if (!buf || !size)
- return NULL;
-
- snprintf(end, size, "0x%x (", capability);
-
- len = strlen(end);
- end += len;
- size -= len;
- start = end;
-
- for (format = 1; format < AST_RTP_MAX; format <<= 1) {
- if (capability & format) {
- const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
-
- snprintf(end, size, "%s|", name);
- len = strlen(end);
- end += len;
- size -= len;
- }
- }
-
- if (start == end)
- snprintf(start, size, "nothing)");
- else if (size > 1)
- *(end -1) = ')';
-
- return buf;
-}
-
-static int rtp_socket(void)
-{
- int s;
- long flags;
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s > -1) {
- flags = fcntl(s, F_GETFL);
- fcntl(s, F_SETFL, flags | O_NONBLOCK);
-#ifdef SO_NO_CHECK
- if (nochecksums)
- setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
-#endif
- }
- return s;
-}
-
-/*!
- * \brief Initialize a new RTCP session.
- *
- * \returns The newly initialized RTCP session.
- */
-static struct ast_rtcp *ast_rtcp_new(void)
-{
- struct ast_rtcp *rtcp;
-
- if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
- return NULL;
- rtcp->s = rtp_socket();
- rtcp->us.sin_family = AF_INET;
- rtcp->them.sin_family = AF_INET;
- rtcp->schedid = -1;
-
- if (rtcp->s < 0) {
- free(rtcp);
- ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno));
- return NULL;
- }
-
- return rtcp;
-}
-
-/*!
- * \brief Initialize a new RTP structure.
- *
- */
-void ast_rtp_new_init(struct ast_rtp *rtp)
-{
- ast_mutex_init(&rtp->bridge_lock);
-
- rtp->them.sin_family = AF_INET;
- rtp->us.sin_family = AF_INET;
- rtp->ssrc = ast_random();
- rtp->seqno = ast_random() & 0xffff;
- ast_set_flag(rtp, FLAG_HAS_DTMF);
-
- return;
-}
-
-struct ast_rtp *ast_rtp_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
-{
- struct ast_rtp *rtp;
- int x;
- int first;
- int startplace;
-
- if (!(rtp = ast_calloc(1, sizeof(*rtp))))
- return NULL;
-
- ast_rtp_new_init(rtp);
-
- rtp->s = rtp_socket();
- if (rtp->s < 0) {
- free(rtp);
- ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
- return NULL;
- }
- if (sched && rtcpenable) {
- rtp->sched = sched;
- rtp->rtcp = ast_rtcp_new();
- }
-
- /* Select a random port number in the range of possible RTP */
- x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
- x = x & ~1;
- /* Save it for future references. */
- startplace = x;
- /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
- for (;;) {
- /* Must be an even port number by RTP spec */
- rtp->us.sin_port = htons(x);
- rtp->us.sin_addr = addr;
- /* If there's rtcp, initialize it as well. */
- if (rtp->rtcp) {
- rtp->rtcp->us.sin_port = htons(x + 1);
- rtp->rtcp->us.sin_addr = addr;
- }
- /* Try to bind it/them. */
- if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
- (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
- break;
- if (!first) {
- /* Primary bind succeeded! Gotta recreate it */
- close(rtp->s);
- rtp->s = rtp_socket();
- }
- if (errno != EADDRINUSE) {
- /* We got an error that wasn't expected, abort! */
- ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
- close(rtp->s);
- if (rtp->rtcp) {
- close(rtp->rtcp->s);
- free(rtp->rtcp);
- }
- free(rtp);
- return NULL;
- }
- /* The port was used, increment it (by two). */
- x += 2;
- /* Did we go over the limit ? */
- if (x > rtpend)
- /* then, start from the begingig. */
- x = (rtpstart + 1) & ~1;
- /* Check if we reached the place were we started. */
- if (x == startplace) {
- /* If so, there's no ports available. */
- ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
- close(rtp->s);
- if (rtp->rtcp) {
- close(rtp->rtcp->s);
- free(rtp->rtcp);
- }
- free(rtp);
- return NULL;
- }
- }
- rtp->sched = sched;
- rtp->io = io;
- if (callbackmode) {
- rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
- ast_set_flag(rtp, FLAG_CALLBACK_MODE);
- }
- ast_rtp_pt_default(rtp);
- return rtp;
-}
-
-struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
-{
- struct in_addr ia;
-
- memset(&ia, 0, sizeof(ia));
- return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
-}
-
-int ast_rtp_settos(struct ast_rtp *rtp, int tos)
-{
- int res;
-
- if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))))
- ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
- return res;
-}
-
-void ast_rtp_new_source(struct ast_rtp *rtp)
-{
- if (rtp) {
- rtp->set_marker_bit = 1;
- }
- return;
-}
-
-void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
-{
- rtp->them.sin_port = them->sin_port;
- rtp->them.sin_addr = them->sin_addr;
- if (rtp->rtcp) {
- rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
- rtp->rtcp->them.sin_addr = them->sin_addr;
- }
- rtp->rxseqno = 0;
-}
-
-int ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
-{
- if ((them->sin_family != AF_INET) ||
- (them->sin_port != rtp->them.sin_port) ||
- (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
- them->sin_family = AF_INET;
- them->sin_port = rtp->them.sin_port;
- them->sin_addr = rtp->them.sin_addr;
- return 1;
- }
- return 0;
-}
-
-void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us)
-{
- *us = rtp->us;
-}
-
-struct ast_rtp *ast_rtp_get_bridged(struct ast_rtp *rtp)
-{
- struct ast_rtp *bridged = NULL;
-
- ast_mutex_lock(&rtp->bridge_lock);
- bridged = rtp->bridged;
- ast_mutex_unlock(&rtp->bridge_lock);
-
- return bridged;
-}
-
-void ast_rtp_stop(struct ast_rtp *rtp)
-{
- if (rtp->rtcp) {
- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
- }
-
- memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
- memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
- if (rtp->rtcp) {
- memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
- memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
- }
-
- ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
-}
-
-void ast_rtp_reset(struct ast_rtp *rtp)
-{
- memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
- memset(&rtp->txcore, 0, sizeof(rtp->txcore));
- memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
- rtp->lastts = 0;
- rtp->lastdigitts = 0;
- rtp->lastrxts = 0;
- rtp->lastividtimestamp = 0;
- rtp->lastovidtimestamp = 0;
- rtp->lasteventseqn = 0;
- rtp->lastevent = 0;
- rtp->lasttxformat = 0;
- rtp->lastrxformat = 0;
- rtp->dtmfcount = 0;
- rtp->dtmfsamples = 0;
- rtp->seqno = 0;
- rtp->rxseqno = 0;
-}
-
-char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual)
-{
- /*
- *ssrc our ssrc
- *themssrc their ssrc
- *lp lost packets
- *rxjitter our calculated jitter(rx)
- *rxcount no. received packets
- *txjitter reported jitter of the other end
- *txcount transmitted packets
- *rlp remote lost packets
- *rtt round trip time
- */
-
- if (qual && rtp) {
- qual->local_ssrc = rtp->ssrc;
- qual->local_jitter = rtp->rxjitter;
- qual->local_count = rtp->rxcount;
- qual->remote_ssrc = rtp->themssrc;
- qual->remote_count = rtp->txcount;
- if (rtp->rtcp) {
- qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
- qual->remote_lostpackets = rtp->rtcp->reported_lost;
- qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
- qual->rtt = rtp->rtcp->rtt;
- }
- }
- if (rtp->rtcp) {
- snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
- "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
- rtp->ssrc,
- rtp->themssrc,
- rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
- rtp->rxjitter,
- rtp->rxcount,
- (double)rtp->rtcp->reported_jitter / 65536.0,
- rtp->txcount,
- rtp->rtcp->reported_lost,
- rtp->rtcp->rtt);
- return rtp->rtcp->quality;
- } else
- return "<Unknown> - RTP/RTCP has already been destroyed";
-}
-
-void ast_rtp_destroy(struct ast_rtp *rtp)
-{
- if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
- /*Print some info on the call here */
- ast_verbose(" RTP-stats\n");
- ast_verbose("* Our Receiver:\n");
- ast_verbose(" SSRC: %u\n", rtp->themssrc);
- ast_verbose(" Received packets: %u\n", rtp->rxcount);
- ast_verbose(" Lost packets: %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
- ast_verbose(" Jitter: %.4f\n", rtp->rxjitter);
- ast_verbose(" Transit: %.4f\n", rtp->rxtransit);
- ast_verbose(" RR-count: %u\n", rtp->rtcp->rr_count);
- ast_verbose("* Our Sender:\n");
- ast_verbose(" SSRC: %u\n", rtp->ssrc);
- ast_verbose(" Sent packets: %u\n", rtp->txcount);
- ast_verbose(" Lost packets: %u\n", rtp->rtcp->reported_lost);
- ast_verbose(" Jitter: %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0);
- ast_verbose(" SR-count: %u\n", rtp->rtcp->sr_count);
- ast_verbose(" RTT: %f\n", rtp->rtcp->rtt);
- }
-
- if (rtp->smoother)
- ast_smoother_free(rtp->smoother);
- if (rtp->ioid)
- ast_io_remove(rtp->io, rtp->ioid);
- if (rtp->s > -1)
- close(rtp->s);
- if (rtp->rtcp) {
- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
- close(rtp->rtcp->s);
- free(rtp->rtcp);
- rtp->rtcp=NULL;
- }
-
- ast_mutex_destroy(&rtp->bridge_lock);
-
- free(rtp);
-}
-
-static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
-{
- struct timeval t;
- long ms;
- if (ast_tvzero(rtp->txcore)) {
- rtp->txcore = ast_tvnow();
- /* Round to 20ms for nice, pretty timestamps */
- rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
- }
- /* Use previous txcore if available */
- t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
- ms = ast_tvdiff_ms(t, rtp->txcore);
- if (ms < 0)
- ms = 0;
- /* Use what we just got for next time */
- rtp->txcore = t;
- return (unsigned int) ms;
-}
-
-/*! \brief Send begin frames for DTMF */
-int ast_rtp_senddigit_begin(struct ast_rtp *rtp, char digit)
-{
- unsigned int *rtpheader;
- int hdrlen = 12, res = 0, i = 0, payload = 0;
- char data[256];
-
- if ((digit <= '9') && (digit >= '0'))
- digit -= '0';
- else if (digit == '*')
- digit = 10;
- else if (digit == '#')
- digit = 11;
- else if ((digit >= 'A') && (digit <= 'D'))
- digit = digit - 'A' + 12;
- else if ((digit >= 'a') && (digit <= 'd'))
- digit = digit - 'a' + 12;
- else {
- ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
- return 0;
- }
-
- /* If we have no peer, return immediately */
- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
- return 0;
-
- payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
-
- rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
- rtp->send_duration = 160;
- rtp->lastdigitts = rtp->lastts + rtp->send_duration;
-
- /* Get a pointer to the header */
- rtpheader = (unsigned int *)data;
- rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
- rtpheader[1] = htonl(rtp->lastdigitts);
- rtpheader[2] = htonl(rtp->ssrc);
-
- for (i = 0; i < 2; i++) {
- rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
- res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
- if (res < 0)
- ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
- ast_inet_ntoa(rtp->them.sin_addr),
- ntohs(rtp->them.sin_port), strerror(errno));
- if (rtp_debug_test_addr(&rtp->them))
- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(rtp->them.sin_addr),
- ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
- /* Increment sequence number */
- rtp->seqno++;
- /* Increment duration */
- rtp->send_duration += 160;
- /* Clear marker bit and set seqno */
- rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
- }
-
- /* Since we received a begin, we can safely store the digit and disable any compensation */
- rtp->sending_digit = 1;
- rtp->send_digit = digit;
- rtp->send_payload = payload;
-
- return 0;
-}
-
-/*! \brief Send continuation frame for DTMF */
-static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp)
-{
- unsigned int *rtpheader;
- int hdrlen = 12, res = 0;
- char data[256];
-
- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
- return 0;
-
- /* Setup packet to send */
- rtpheader = (unsigned int *)data;
- rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
- rtpheader[1] = htonl(rtp->lastdigitts);
- rtpheader[2] = htonl(rtp->ssrc);
- rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
- rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
-
- /* Transmit */
- res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
- if (res < 0)
- ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
- ast_inet_ntoa(rtp->them.sin_addr),
- ntohs(rtp->them.sin_port), strerror(errno));
- if (rtp_debug_test_addr(&rtp->them))
- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(rtp->them.sin_addr),
- ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
-
- /* Increment sequence number */
- rtp->seqno++;
- /* Increment duration */
- rtp->send_duration += 160;
-
- return 0;
-}
-
-/*! \brief Send end packets for DTMF */
-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit)
-{
- unsigned int *rtpheader;
- int hdrlen = 12, res = 0, i = 0;
- char data[256];
-
- /* If no address, then bail out */
- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
- return 0;
-
- if ((digit <= '9') && (digit >= '0'))
- digit -= '0';
- else if (digit == '*')
- digit = 10;
- else if (digit == '#')
- digit = 11;
- else if ((digit >= 'A') && (digit <= 'D'))
- digit = digit - 'A' + 12;
- else if ((digit >= 'a') && (digit <= 'd'))
- digit = digit - 'a' + 12;
- else {
- ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
- return 0;
- }
-
- rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
-
- rtpheader = (unsigned int *)data;
- rtpheader[1] = htonl(rtp->lastdigitts);
- rtpheader[2] = htonl(rtp->ssrc);
- rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
- /* Set end bit */
- rtpheader[3] |= htonl((1 << 23));
-
- /* Send 3 termination packets */
- for (i = 0; i < 3; i++) {
- rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
- res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
- rtp->seqno++;
- if (res < 0)
- ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
- ast_inet_ntoa(rtp->them.sin_addr),
- ntohs(rtp->them.sin_port), strerror(errno));
- if (rtp_debug_test_addr(&rtp->them))
- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(rtp->them.sin_addr),
- ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
- }
- rtp->lastts += rtp->send_duration;
- rtp->sending_digit = 0;
- rtp->send_digit = 0;
-
- return res;
-}
-
-/*! \brief Public function: Send an H.261 fast update request, some devices need this rather than SIP XML */
-int ast_rtcp_send_h261fur(void *data)
-{
- struct ast_rtp *rtp = data;
- int res;
-
- rtp->rtcp->sendfur = 1;
- res = ast_rtcp_write(data);
-
- return res;
-}
-
-/*! \brief Send RTCP sender's report */
-static int ast_rtcp_write_sr(const void *data)
-{
- struct ast_rtp *rtp = (struct ast_rtp *)data;
- int res;
- int len = 0;
- struct timeval now;
- unsigned int now_lsw;
- unsigned int now_msw;
- unsigned int *rtcpheader;
- unsigned int lost;
- unsigned int extended;
- unsigned int expected;
- unsigned int expected_interval;
- unsigned int received_interval;
- int lost_interval;
- int fraction;
- struct timeval dlsr;
- char bdata[512];
-
- /* Commented condition is always not NULL if rtp->rtcp is not NULL */
- if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
- return 0;
-
- if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */
- ast_verbose("RTCP SR transmission error, rtcp halted\n");
- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
- return 0;
- }
-
- gettimeofday(&now, NULL);
- timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
- rtcpheader = (unsigned int *)bdata;
- rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */
- rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
- rtcpheader[3] = htonl(now_lsw); /* now, LSW */
- rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */
- rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */
- rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */
- len += 28;
-
- extended = rtp->cycles + rtp->lastrxseqno;
- expected = extended - rtp->seedrxseqno + 1;
- if (rtp->rxcount > expected)
- expected += rtp->rxcount - expected;
- lost = expected - rtp->rxcount;
- expected_interval = expected - rtp->rtcp->expected_prior;
- rtp->rtcp->expected_prior = expected;
- received_interval = rtp->rxcount - rtp->rtcp->received_prior;
- rtp->rtcp->received_prior = rtp->rxcount;
- lost_interval = expected_interval - received_interval;
- if (expected_interval == 0 || lost_interval <= 0)
- fraction = 0;
- else
- fraction = (lost_interval << 8) / expected_interval;
- timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
- rtcpheader[7] = htonl(rtp->themssrc);
- rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
- rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
- rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
- rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
- rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
- len += 24;
-
- rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
-
- if (rtp->rtcp->sendfur) {
- rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
- rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */
- len += 8;
- rtp->rtcp->sendfur = 0;
- }
-
- /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
- /* it can change mid call, and SDES can't) */
- rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
- rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
- rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
- len += 12;
-
- res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
- if (res < 0) {
- ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
- return 0;
- }
-
- /* FIXME Don't need to get a new one */
- gettimeofday(&rtp->rtcp->txlsr, NULL);
- rtp->rtcp->sr_count++;
-
- rtp->rtcp->lastsrtxcount = rtp->txcount;
-
- if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
- ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
- ast_verbose(" Our SSRC: %u\n", rtp->ssrc);
- ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
- ast_verbose(" Sent(RTP): %u\n", rtp->lastts);
- ast_verbose(" Sent packets: %u\n", rtp->txcount);
- ast_verbose(" Sent octets: %u\n", rtp->txoctetcount);
- ast_verbose(" Report block:\n");
- ast_verbose(" Fraction lost: %u\n", fraction);
- ast_verbose(" Cumulative loss: %u\n", lost);
- ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter);
- ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr);
- ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
- }
- return res;
-}
-
-/*! \brief Send RTCP recepient's report */
-static int ast_rtcp_write_rr(const void *data)
-{
- struct ast_rtp *rtp = (struct ast_rtp *)data;
- int res;
- int len = 32;
- unsigned int lost;
- unsigned int extended;
- unsigned int expected;
- unsigned int expected_interval;
- unsigned int received_interval;
- int lost_interval;
- struct timeval now;
- unsigned int *rtcpheader;
- char bdata[1024];
- struct timeval dlsr;
- int fraction;
-
- if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
- return 0;
-
- if (!rtp->rtcp->them.sin_addr.s_addr) {
- ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
- return 0;
- }
-
- extended = rtp->cycles + rtp->lastrxseqno;
- expected = extended - rtp->seedrxseqno + 1;
- lost = expected - rtp->rxcount;
- expected_interval = expected - rtp->rtcp->expected_prior;
- rtp->rtcp->expected_prior = expected;
- received_interval = rtp->rxcount - rtp->rtcp->received_prior;
- rtp->rtcp->received_prior = rtp->rxcount;
- lost_interval = expected_interval - received_interval;
- if (expected_interval == 0 || lost_interval <= 0)
- fraction = 0;
- else
- fraction = (lost_interval << 8) / expected_interval;
- gettimeofday(&now, NULL);
- timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
- rtcpheader = (unsigned int *)bdata;
- rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
- rtcpheader[1] = htonl(rtp->ssrc);
- rtcpheader[2] = htonl(rtp->themssrc);
- rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
- rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
- rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
- rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
- rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
-
- if (rtp->rtcp->sendfur) {
- rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
- rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */
- len += 8;
- rtp->rtcp->sendfur = 0;
- }
-
- /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
- it can change mid call, and SDES can't) */
- rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
- rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
- rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
- len += 12;
-
- res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
-
- if (res < 0) {
- ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
- /* Remove the scheduler */
- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
- return 0;
- }
-
- rtp->rtcp->rr_count++;
-
- if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
- ast_verbose("\n* Sending RTCP RR to %s:%d\n"
- " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
- " IA jitter: %.4f\n"
- " Their last SR: %u\n"
- " DLSR: %4.4f (sec)\n\n",
- ast_inet_ntoa(rtp->rtcp->them.sin_addr),
- ntohs(rtp->rtcp->them.sin_port),
- rtp->ssrc, rtp->themssrc, fraction, lost,
- rtp->rxjitter,
- rtp->rtcp->themrxlsr,
- (double)(ntohl(rtcpheader[7])/65536.0));
- }
-
- return res;
-}
-
-/*! \brief Write and RTCP packet to the far end
- * \note Decide if we are going to send an SR (with Reception Block) or RR
- * RR is sent if we have not sent any rtp packets in the previous interval */
-static int ast_rtcp_write(const void *data)
-{
- struct ast_rtp *rtp = (struct ast_rtp *)data;
- int res;
-
- if (!rtp || !rtp->rtcp)
- return 0;
-
- if (rtp->txcount > rtp->rtcp->lastsrtxcount)
- res = ast_rtcp_write_sr(data);
- else
- res = ast_rtcp_write_rr(data);
-
- return res;
-}
-
-/*! \brief generate comfort noice (CNG) */
-int ast_rtp_sendcng(struct ast_rtp *rtp, int level)
-{
- unsigned int *rtpheader;
- int hdrlen = 12;
- int res;
- int payload;
- char data[256];
- level = 127 - (level & 0x7f);
- payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
-
- /* If we have no peer, return immediately */
- if (!rtp->them.sin_addr.s_addr)
- return 0;
-
- rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
-
- /* Get a pointer to the header */
- rtpheader = (unsigned int *)data;
- rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
- rtpheader[1] = htonl(rtp->lastts);
- rtpheader[2] = htonl(rtp->ssrc);
- data[12] = level;
- if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
- res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
- if (res <0)
- ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
- if (rtp_debug_test_addr(&rtp->them))
- ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
- , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);
-
- }
- return 0;
-}
-
-static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec)
-{
- unsigned char *rtpheader;
- int hdrlen = 12;
- int res;
- unsigned int ms;
- int pred;
- int mark = 0;
-
- if (rtp->sending_digit) {
- return 0;
- }
-
- ms = calc_txstamp(rtp, &f->delivery);
- /* Default prediction */
- if (f->frametype == AST_FRAME_VOICE) {
- pred = rtp->lastts + f->samples;
-
- /* Re-calculate last TS */
- rtp->lastts = rtp->lastts + ms * 8;
- if (ast_tvzero(f->delivery)) {
- /* If this isn't an absolute delivery time, Check if it is close to our prediction,
- and if so, go with our prediction */
- if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
- rtp->lastts = pred;
- else {
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
- mark = 1;
- }
- }
- } else if (f->frametype == AST_FRAME_VIDEO) {
- mark = f->subclass & 0x1;
- pred = rtp->lastovidtimestamp + f->samples;
- /* Re-calculate last TS */
- rtp->lastts = rtp->lastts + ms * 90;
- /* If it's close to our prediction, go for it */
- if (ast_tvzero(f->delivery)) {
- if (abs(rtp->lastts - pred) < 7200) {
- rtp->lastts = pred;
- rtp->lastovidtimestamp += f->samples;
- } else {
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples);
- rtp->lastovidtimestamp = rtp->lastts;
- }
- }
- }
-
- /* If we have been explicitly told to set the marker bit do so */
- if (rtp->set_marker_bit) {
- mark = 1;
- rtp->set_marker_bit = 0;
- }
-
- /* If the timestamp for non-digit packets has moved beyond the timestamp
- for digits, update the digit timestamp.
- */
- if (rtp->lastts > rtp->lastdigitts)
- rtp->lastdigitts = rtp->lastts;
-
- if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
- rtp->lastts = f->ts * 8;
-
- /* Get a pointer to the header */
- rtpheader = (unsigned char *)(f->data - hdrlen);
-
- put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
- put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
- put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
-
- if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
- res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
- if (res <0) {
- if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
- ast_log(LOG_DEBUG, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
- } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
- /* Only give this error message once if we are not RTP debugging */
- if (option_debug || rtpdebug)
- ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
- ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
- }
- } else {
- rtp->txcount++;
- rtp->txoctetcount +=(res - hdrlen);
-
- /* Do not schedule RR if RTCP isn't run */
- if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
- rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
- }
- }
-
- if (rtp_debug_test_addr(&rtp->them))
- ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
- ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
- }
-
- rtp->seqno++;
-
- return 0;
-}
-
-int ast_rtp_codec_setpref(struct ast_rtp *rtp, struct ast_codec_pref *prefs)
-{
- int x;
- for (x = 0; x < 32; x++) { /* Ugly way */
- rtp->pref.order[x] = prefs->order[x];
- rtp->pref.framing[x] = prefs->framing[x];
- }
- if (rtp->smoother)
- ast_smoother_free(rtp->smoother);
- rtp->smoother = NULL;
- return 0;
-}
-
-struct ast_codec_pref *ast_rtp_codec_getpref(struct ast_rtp *rtp)
-{
- return &rtp->pref;
-}
-
-int ast_rtp_codec_getformat(int pt)
-{
- if (pt < 0 || pt > MAX_RTP_PT)
- return 0; /* bogus payload type */
-
- if (static_RTP_PT[pt].isAstFormat)
- return static_RTP_PT[pt].code;
- else
- return 0;
-}
-
-int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
-{
- struct ast_frame *f;
- int codec;
- int hdrlen = 12;
- int subclass;
-
-
- /* If we have no peer, return immediately */
- if (!rtp->them.sin_addr.s_addr)
- return 0;
-
- /* If there is no data length, return immediately */
- if (!_f->datalen)
- return 0;
-
- /* Make sure we have enough space for RTP header */
- if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
- ast_log(LOG_WARNING, "RTP can only send voice and video\n");
- return -1;
- }
-
- subclass = _f->subclass;
- if (_f->frametype == AST_FRAME_VIDEO)
- subclass &= ~0x1;
-
- codec = ast_rtp_lookup_code(rtp, 1, subclass);
- if (codec < 0) {
- ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
- return -1;
- }
-
- if (rtp->lasttxformat != subclass) {
- /* New format, reset the smoother */
- if (option_debug)
- ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
- rtp->lasttxformat = subclass;
- if (rtp->smoother)
- ast_smoother_free(rtp->smoother);
- rtp->smoother = NULL;
- }
-
- if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
- struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
- if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
- if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
- ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
- return -1;
- }
- if (fmt.flags)
- ast_smoother_set_flags(rtp->smoother, fmt.flags);
- if (option_debug)
- ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
- }
- }
- if (rtp->smoother) {
- if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
- ast_smoother_feed_be(rtp->smoother, _f);
- } else {
- ast_smoother_feed(rtp->smoother, _f);
- }
-
- while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
- if (f->subclass == AST_FORMAT_G722) {
- /* G.722 is silllllllllllllly */
- f->samples /= 2;
- }
-
- ast_rtp_raw_write(rtp, f, codec);
- }
- } else {
- /* Don't buffer outgoing frames; send them one-per-packet: */
- if (_f->offset < hdrlen) {
- f = ast_frdup(_f);
- } else {
- f = _f;
- }
- if (f->data) {
- if (f->subclass == AST_FORMAT_G722) {
- /* G.722 is silllllllllllllly */
- f->samples /= 2;
- }
- ast_rtp_raw_write(rtp, f, codec);
- }
- if (f != _f)
- ast_frfree(f);
- }
-
- return 0;
-}
-
-/*! \brief Unregister interface to channel driver */
-void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto)
-{
- AST_LIST_LOCK(&protos);
- AST_LIST_REMOVE(&protos, proto, list);
- AST_LIST_UNLOCK(&protos);
-}
-
-/*! \brief Register interface to channel driver */
-int ast_rtp_proto_register(struct ast_rtp_protocol *proto)
-{
- struct ast_rtp_protocol *cur;
-
- AST_LIST_LOCK(&protos);
- AST_LIST_TRAVERSE(&protos, cur, list) {
- if (!strcmp(cur->type, proto->type)) {
- ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
- AST_LIST_UNLOCK(&protos);
- return -1;
- }
- }
- AST_LIST_INSERT_HEAD(&protos, proto, list);
- AST_LIST_UNLOCK(&protos);
-
- return 0;
-}
-
-/*! \brief Bridge loop for true native bridge (reinvite) */
-static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
-{
- struct ast_frame *fr = NULL;
- struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
- int oldcodec0 = codec0, oldcodec1 = codec1;
- struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,};
- struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,};
-
- /* Set it up so audio goes directly between the two endpoints */
-
- /* Test the first channel */
- if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
- ast_rtp_get_peer(p1, &ac1);
- if (vp1)
- ast_rtp_get_peer(vp1, &vac1);
- } else
- ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
-
- /* Test the second channel */
- if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
- ast_rtp_get_peer(p0, &ac0);
- if (vp0)
- ast_rtp_get_peer(vp0, &vac0);
- } else
- ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
-
- /* Now we can unlock and move into our loop */
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
-
- /* Throw our channels into the structure and enter the loop */
- cs[0] = c0;
- cs[1] = c1;
- cs[2] = NULL;
- for (;;) {
- /* Check if anything changed */
- if ((c0->tech_pvt != pvt0) ||
- (c1->tech_pvt != pvt1) ||
- (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
- (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
- ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
- if (c0->tech_pvt == pvt0)
- if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
- if (c1->tech_pvt == pvt1)
- if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
- return AST_BRIDGE_RETRY;
- }
-
- /* Check if they have changed their address */
- ast_rtp_get_peer(p1, &t1);
- if (vp1)
- ast_rtp_get_peer(vp1, &vt1);
- if (pr1->get_codec)
- codec1 = pr1->get_codec(c1);
- ast_rtp_get_peer(p0, &t0);
- if (vp0)
- ast_rtp_get_peer(vp0, &vt0);
- if (pr0->get_codec)
- codec0 = pr0->get_codec(c0);
- if ((inaddrcmp(&t1, &ac1)) ||
- (vp1 && inaddrcmp(&vt1, &vac1)) ||
- (codec1 != oldcodec1)) {
- if (option_debug > 1) {
- ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
- c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
- ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
- c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
- ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
- c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
- ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
- c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
- }
- if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
- ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
- memcpy(&ac1, &t1, sizeof(ac1));
- memcpy(&vac1, &vt1, sizeof(vac1));
- oldcodec1 = codec1;
- }
- if ((inaddrcmp(&t0, &ac0)) ||
- (vp0 && inaddrcmp(&vt0, &vac0))) {
- if (option_debug > 1) {
- ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
- c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
- ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
- c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
- }
- if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
- ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
- memcpy(&ac0, &t0, sizeof(ac0));
- memcpy(&vac0, &vt0, sizeof(vac0));
- oldcodec0 = codec0;
- }
-
- /* Wait for frame to come in on the channels */
- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
- if (!timeoutms) {
- if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
- if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
- return AST_BRIDGE_RETRY;
- }
- if (option_debug)
- ast_log(LOG_DEBUG, "Ooh, empty read...\n");
- if (ast_check_hangup(c0) || ast_check_hangup(c1))
- break;
- continue;
- }
- fr = ast_read(who);
- other = (who == c0) ? c1 : c0;
- if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
- (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
- ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
- /* Break out of bridge */
- *fo = fr;
- *rc = who;
- if (option_debug)
- ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
- if (c0->tech_pvt == pvt0)
- if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
- if (c1->tech_pvt == pvt1)
- if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
- return AST_BRIDGE_COMPLETE;
- } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
- if ((fr->subclass == AST_CONTROL_HOLD) ||
- (fr->subclass == AST_CONTROL_UNHOLD) ||
- (fr->subclass == AST_CONTROL_VIDUPDATE) ||
- (fr->subclass == AST_CONTROL_SRCUPDATE)) {
- if (fr->subclass == AST_CONTROL_HOLD) {
- /* If we someone went on hold we want the other side to reinvite back to us */
- if (who == c0)
- pr1->set_rtp_peer(c1, NULL, NULL, 0, 0);
- else
- pr0->set_rtp_peer(c0, NULL, NULL, 0, 0);
- } else if (fr->subclass == AST_CONTROL_UNHOLD) {
- /* If they went off hold they should go back to being direct */
- if (who == c0)
- pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
- else
- pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
- }
- /* Update local address information */
- ast_rtp_get_peer(p0, &t0);
- memcpy(&ac0, &t0, sizeof(ac0));
- ast_rtp_get_peer(p1, &t1);
- memcpy(&ac1, &t1, sizeof(ac1));
- /* Update codec information */
- if (pr0->get_codec && c0->tech_pvt)
- oldcodec0 = codec0 = pr0->get_codec(c0);
- if (pr1->get_codec && c1->tech_pvt)
- oldcodec1 = codec1 = pr1->get_codec(c1);
- ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
- ast_frfree(fr);
- } else {
- *fo = fr;
- *rc = who;
- ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
- return AST_BRIDGE_COMPLETE;
- }
- } else {
- if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
- (fr->frametype == AST_FRAME_DTMF_END) ||
- (fr->frametype == AST_FRAME_VOICE) ||
- (fr->frametype == AST_FRAME_VIDEO) ||
- (fr->frametype == AST_FRAME_IMAGE) ||
- (fr->frametype == AST_FRAME_HTML) ||
- (fr->frametype == AST_FRAME_MODEM) ||
- (fr->frametype == AST_FRAME_TEXT)) {
- ast_write(other, fr);
- }
- ast_frfree(fr);
- }
- /* Swap priority */
- cs[2] = cs[0];
- cs[0] = cs[1];
- cs[1] = cs[2];
- }
-
- if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
- if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
-
- return AST_BRIDGE_FAILED;
-}
-
-/*! \brief P2P RTP Callback */
-#ifdef P2P_INTENSE
-static int p2p_rtp_callback(int *id, int fd, short events, void *cbdata)
-{
- int res = 0, hdrlen = 12;
- struct sockaddr_in sin;
- socklen_t len;
- unsigned int *header;
- struct ast_rtp *rtp = cbdata, *bridged = NULL;
-
- if (!rtp)
- return 1;
-
- len = sizeof(sin);
- if ((res = recvfrom(fd, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0)
- return 1;
-
- header = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
-
- /* If NAT support is turned on, then see if we need to change their address */
- if ((rtp->nat) &&
- ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
- (rtp->them.sin_port != sin.sin_port))) {
- rtp->them = sin;
- rtp->rxseqno = 0;
- ast_set_flag(rtp, FLAG_NAT_ACTIVE);
- if (option_debug || rtpdebug)
- ast_log(LOG_DEBUG, "P2P RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
- }
-
- /* Write directly out to other RTP stream if bridged */
- if ((bridged = ast_rtp_get_bridged(rtp)))
- bridge_p2p_rtp_write(rtp, bridged, header, res, hdrlen);
-
- return 1;
-}
-
-/*! \brief Helper function to switch a channel and RTP stream into callback mode */
-static int p2p_callback_enable(struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
-{
- /* If we need DTMF, are looking for STUN, or we have no IO structure then we can't do direct callback */
- if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) || ast_test_flag(rtp, FLAG_HAS_STUN) || !rtp->io)
- return 0;
-
- /* If the RTP structure is already in callback mode, remove it temporarily */
- if (rtp->ioid) {
- ast_io_remove(rtp->io, rtp->ioid);
- rtp->ioid = NULL;
- }
-
- /* Steal the file descriptors from the channel and stash them away */
- fds[0] = chan->fds[0];
- chan->fds[0] = -1;
-
- /* Now, fire up callback mode */
- iod[0] = ast_io_add(rtp->io, fds[0], p2p_rtp_callback, AST_IO_IN, rtp);
-
- return 1;
-}
-#else
-static int p2p_callback_enable(struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
-{
- return 0;
-}
-#endif
-
-/*! \brief Helper function to switch a channel and RTP stream out of callback mode */
-static int p2p_callback_disable(struct ast_channel *chan, struct ast_rtp *rtp, int *fds, int **iod)
-{
- ast_channel_lock(chan);
-
- /* Remove the callback from the IO context */
- ast_io_remove(rtp->io, iod[0]);
-
- /* Restore file descriptors */
- chan->fds[0] = fds[0];
- ast_channel_unlock(chan);
-
- /* Restore callback mode if previously used */
- if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
- rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
-
- return 0;
-}
-
-/*! \brief Helper function that sets what an RTP structure is bridged to */
-static void p2p_set_bridge(struct ast_rtp *rtp0, struct ast_rtp *rtp1)
-{
- ast_mutex_lock(&rtp0->bridge_lock);
- rtp0->bridged = rtp1;
- ast_mutex_unlock(&rtp0->bridge_lock);
-
- return;
-}
-
-/*! \brief Bridge loop for partial native bridge (packet2packet) */
-static enum ast_bridge_result bridge_p2p_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
-{
- struct ast_frame *fr = NULL;
- struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
- int p0_fds[2] = {-1, -1}, p1_fds[2] = {-1, -1};
- int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
- int p0_callback = 0, p1_callback = 0;
- enum ast_bridge_result res = AST_BRIDGE_FAILED;
-
- /* Okay, setup each RTP structure to do P2P forwarding */
- ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
- p2p_set_bridge(p0, p1);
- ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
- p2p_set_bridge(p1, p0);
-
- /* Activate callback modes if possible */
- p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
- p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
-
- /* Now let go of the channel locks and be on our way */
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
-
- /* Go into a loop forwarding frames until we don't need to anymore */
- cs[0] = c0;
- cs[1] = c1;
- cs[2] = NULL;
- for (;;) {
- /* If the underlying formats have changed force this bridge to break */
- if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
- ast_log(LOG_DEBUG, "Oooh, formats changed, backing out\n");
- res = AST_BRIDGE_FAILED_NOWARN;
- break;
- }
- /* Check if anything changed */
- if ((c0->tech_pvt != pvt0) ||
- (c1->tech_pvt != pvt1) ||
- (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
- (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
- ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
- if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
- ast_frfree(fr);
- if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
- ast_frfree(fr);
- res = AST_BRIDGE_RETRY;
- break;
- }
- /* Wait on a channel to feed us a frame */
- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
- if (!timeoutms) {
- res = AST_BRIDGE_RETRY;
- break;
- }
- if (option_debug)
- ast_log(LOG_NOTICE, "Ooh, empty read...\n");
- if (ast_check_hangup(c0) || ast_check_hangup(c1))
- break;
- continue;
- }
- /* Read in frame from channel */
- fr = ast_read(who);
- other = (who == c0) ? c1 : c0;
- /* Dependong on the frame we may need to break out of our bridge */
- if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
- ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
- ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
- /* Record received frame and who */
- *fo = fr;
- *rc = who;
- if (option_debug)
- ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
- res = AST_BRIDGE_COMPLETE;
- break;
- } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
- if ((fr->subclass == AST_CONTROL_HOLD) ||
- (fr->subclass == AST_CONTROL_UNHOLD) ||
- (fr->subclass == AST_CONTROL_VIDUPDATE) ||
- (fr->subclass == AST_CONTROL_SRCUPDATE)) {
- /* If we are going on hold, then break callback mode and P2P bridging */
- if (fr->subclass == AST_CONTROL_HOLD) {
- if (p0_callback)
- p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
- if (p1_callback)
- p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
- p2p_set_bridge(p0, NULL);
- p2p_set_bridge(p1, NULL);
- } else if (fr->subclass == AST_CONTROL_UNHOLD) {
- /* If we are off hold, then go back to callback mode and P2P bridging */
- ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
- p2p_set_bridge(p0, p1);
- ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
- p2p_set_bridge(p1, p0);
- p0_callback = p2p_callback_enable(c0, p0, &p0_fds[0], &p0_iod[0]);
- p1_callback = p2p_callback_enable(c1, p1, &p1_fds[0], &p1_iod[0]);
- }
- ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
- ast_frfree(fr);
- } else {
- *fo = fr;
- *rc = who;
- ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
- res = AST_BRIDGE_COMPLETE;
- break;
- }
- } else {
- if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
- (fr->frametype == AST_FRAME_DTMF_END) ||
- (fr->frametype == AST_FRAME_VOICE) ||
- (fr->frametype == AST_FRAME_VIDEO) ||
- (fr->frametype == AST_FRAME_IMAGE) ||
- (fr->frametype == AST_FRAME_HTML) ||
- (fr->frametype == AST_FRAME_MODEM) ||
- (fr->frametype == AST_FRAME_TEXT)) {
- ast_write(other, fr);
- }
-
- ast_frfree(fr);
- }
- /* Swap priority */
- cs[2] = cs[0];
- cs[0] = cs[1];
- cs[1] = cs[2];
- }
-
- /* If we are totally avoiding the core, then restore our link to it */
- if (p0_callback)
- p0_callback = p2p_callback_disable(c0, p0, &p0_fds[0], &p0_iod[0]);
- if (p1_callback)
- p1_callback = p2p_callback_disable(c1, p1, &p1_fds[0], &p1_iod[0]);
-
- /* Break out of the direct bridge */
- p2p_set_bridge(p0, NULL);
- p2p_set_bridge(p1, NULL);
-
- return res;
-}
-
-/*! \brief Bridge calls. If possible and allowed, initiate
- re-invite so the peers exchange media directly outside
- of Asterisk. */
-enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
-{
- struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */
- struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */
- struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
- enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
- enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
- enum ast_bridge_result res = AST_BRIDGE_FAILED;
- int codec0 = 0, codec1 = 0;
- void *pvt0 = NULL, *pvt1 = NULL;
-
- /* Lock channels */
- ast_channel_lock(c0);
- while(ast_channel_trylock(c1)) {
- ast_channel_unlock(c0);
- usleep(1);
- ast_channel_lock(c0);
- }
-
- /* Ensure neither channel got hungup during lock avoidance */
- if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
- ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return AST_BRIDGE_FAILED;
- }
-
- /* Find channel driver interfaces */
- if (!(pr0 = get_proto(c0))) {
- ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return AST_BRIDGE_FAILED;
- }
- if (!(pr1 = get_proto(c1))) {
- ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return AST_BRIDGE_FAILED;
- }
-
- /* Get channel specific interface structures */
- pvt0 = c0->tech_pvt;
- pvt1 = c1->tech_pvt;
-
- /* Get audio and video interface (if native bridge is possible) */
- audio_p0_res = pr0->get_rtp_info(c0, &p0);
- video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
- audio_p1_res = pr1->get_rtp_info(c1, &p1);
- video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
-
- /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
- if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
- audio_p0_res = AST_RTP_GET_FAILED;
- if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
- audio_p1_res = AST_RTP_GET_FAILED;
-
- /* Check if a bridge is possible (partial/native) */
- if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
- /* Somebody doesn't want to play... */
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return AST_BRIDGE_FAILED_NOWARN;
- }
-
- /* If we need to feed DTMF frames into the core then only do a partial native bridge */
- if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
- ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
- audio_p0_res = AST_RTP_TRY_PARTIAL;
- }
-
- if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
- ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
- audio_p1_res = AST_RTP_TRY_PARTIAL;
- }
-
- /* If both sides are not using the same method of DTMF transmission
- * (ie: one is RFC2833, other is INFO... then we can not do direct media.
- * --------------------------------------------------
- * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
- * |-----------|------------|-----------------------|
- * | Inband | False | True |
- * | RFC2833 | True | True |
- * | SIP INFO | False | False |
- * --------------------------------------------------
- * However, if DTMF from both channels is being monitored by the core, then
- * we can still do packet-to-packet bridging, because passing through the
- * core will handle DTMF mode translation.
- */
- if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
- (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
- if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return AST_BRIDGE_FAILED_NOWARN;
- }
- audio_p0_res = AST_RTP_TRY_PARTIAL;
- audio_p1_res = AST_RTP_TRY_PARTIAL;
- }
-
- /* If we need to feed frames into the core don't do a P2P bridge */
- if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
- (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return AST_BRIDGE_FAILED_NOWARN;
- }
-
- /* Get codecs from both sides */
- codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
- codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
- if (codec0 && codec1 && !(codec0 & codec1)) {
- /* Hey, we can't do native bridging if both parties speak different codecs */
- if (option_debug)
- ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return AST_BRIDGE_FAILED_NOWARN;
- }
-
- /* If either side can only do a partial bridge, then don't try for a true native bridge */
- if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
- struct ast_format_list fmt0, fmt1;
-
- /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
- if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return AST_BRIDGE_FAILED_NOWARN;
- }
- /* They must also be using the same packetization */
- fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
- fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
- if (fmt0.cur_ms != fmt1.cur_ms) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n");
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return AST_BRIDGE_FAILED_NOWARN;
- }
-
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
- res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
- } else {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
- res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
- }
-
- return res;
-}
-
-static int rtp_do_debug_ip(int fd, int argc, char *argv[])
-{
- struct hostent *hp;
- struct ast_hostent ahp;
- int port = 0;
- char *p, *arg;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- arg = argv[3];
- p = strstr(arg, ":");
- if (p) {
- *p = '\0';
- p++;
- port = atoi(p);
- }
- hp = ast_gethostbyname(arg, &ahp);
- if (hp == NULL)
- return RESULT_SHOWUSAGE;
- rtpdebugaddr.sin_family = AF_INET;
- memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
- rtpdebugaddr.sin_port = htons(port);
- if (port == 0)
- ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
- else
- ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
- rtpdebug = 1;
- return RESULT_SUCCESS;
-}
-
-static int rtcp_do_debug_ip_deprecated(int fd, int argc, char *argv[])
-{
- struct hostent *hp;
- struct ast_hostent ahp;
- int port = 0;
- char *p, *arg;
- if (argc != 5)
- return RESULT_SHOWUSAGE;
-
- arg = argv[4];
- p = strstr(arg, ":");
- if (p) {
- *p = '\0';
- p++;
- port = atoi(p);
- }
- hp = ast_gethostbyname(arg, &ahp);
- if (hp == NULL)
- return RESULT_SHOWUSAGE;
- rtcpdebugaddr.sin_family = AF_INET;
- memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
- rtcpdebugaddr.sin_port = htons(port);
- if (port == 0)
- ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
- else
- ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
- rtcpdebug = 1;
- return RESULT_SUCCESS;
-}
-
-static int rtcp_do_debug_ip(int fd, int argc, char *argv[])
-{
- struct hostent *hp;
- struct ast_hostent ahp;
- int port = 0;
- char *p, *arg;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
-
- arg = argv[3];
- p = strstr(arg, ":");
- if (p) {
- *p = '\0';
- p++;
- port = atoi(p);
- }
- hp = ast_gethostbyname(arg, &ahp);
- if (hp == NULL)
- return RESULT_SHOWUSAGE;
- rtcpdebugaddr.sin_family = AF_INET;
- memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
- rtcpdebugaddr.sin_port = htons(port);
- if (port == 0)
- ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
- else
- ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
- rtcpdebug = 1;
- return RESULT_SUCCESS;
-}
-
-static int rtp_do_debug(int fd, int argc, char *argv[])
-{
- if (argc != 2) {
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- return rtp_do_debug_ip(fd, argc, argv);
- }
- rtpdebug = 1;
- memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
- ast_cli(fd, "RTP Debugging Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int rtcp_do_debug_deprecated(int fd, int argc, char *argv[]) {
- if (argc != 3) {
- if (argc != 5)
- return RESULT_SHOWUSAGE;
- return rtcp_do_debug_ip_deprecated(fd, argc, argv);
- }
- rtcpdebug = 1;
- memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
- ast_cli(fd, "RTCP Debugging Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int rtcp_do_debug(int fd, int argc, char *argv[]) {
- if (argc != 2) {
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- return rtcp_do_debug_ip(fd, argc, argv);
- }
- rtcpdebug = 1;
- memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
- ast_cli(fd, "RTCP Debugging Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int rtcp_do_stats_deprecated(int fd, int argc, char *argv[]) {
- if (argc != 3) {
- return RESULT_SHOWUSAGE;
- }
- rtcpstats = 1;
- ast_cli(fd, "RTCP Stats Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int rtcp_do_stats(int fd, int argc, char *argv[]) {
- if (argc != 2) {
- return RESULT_SHOWUSAGE;
- }
- rtcpstats = 1;
- ast_cli(fd, "RTCP Stats Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int rtp_no_debug(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- rtpdebug = 0;
- ast_cli(fd,"RTP Debugging Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static int rtcp_no_debug_deprecated(int fd, int argc, char *argv[])
-{
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- rtcpdebug = 0;
- ast_cli(fd,"RTCP Debugging Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static int rtcp_no_debug(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- rtcpdebug = 0;
- ast_cli(fd,"RTCP Debugging Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static int rtcp_no_stats_deprecated(int fd, int argc, char *argv[])
-{
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- rtcpstats = 0;
- ast_cli(fd,"RTCP Stats Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static int rtcp_no_stats(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- rtcpstats = 0;
- ast_cli(fd,"RTCP Stats Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static int stun_do_debug(int fd, int argc, char *argv[])
-{
- if (argc != 2) {
- return RESULT_SHOWUSAGE;
- }
- stundebug = 1;
- ast_cli(fd, "STUN Debugging Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int stun_no_debug(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- stundebug = 0;
- ast_cli(fd, "STUN Debugging Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static char debug_usage[] =
- "Usage: rtp debug [ip host[:port]]\n"
- " Enable dumping of all RTP packets to and from host.\n";
-
-static char no_debug_usage[] =
- "Usage: rtp debug off\n"
- " Disable all RTP debugging\n";
-
-static char stun_debug_usage[] =
- "Usage: stun debug\n"
- " Enable STUN (Simple Traversal of UDP through NATs) debugging\n";
-
-static char stun_no_debug_usage[] =
- "Usage: stun debug off\n"
- " Disable STUN debugging\n";
-
-static char rtcp_debug_usage[] =
- "Usage: rtcp debug [ip host[:port]]\n"
- " Enable dumping of all RTCP packets to and from host.\n";
-
-static char rtcp_no_debug_usage[] =
- "Usage: rtcp debug off\n"
- " Disable all RTCP debugging\n";
-
-static char rtcp_stats_usage[] =
- "Usage: rtcp stats\n"
- " Enable dumping of RTCP stats.\n";
-
-static char rtcp_no_stats_usage[] =
- "Usage: rtcp stats off\n"
- " Disable all RTCP stats\n";
-
-static struct ast_cli_entry cli_rtp_no_debug_deprecated = {
- { "rtp", "no", "debug", NULL },
- rtp_no_debug, NULL,
- NULL };
-
-static struct ast_cli_entry cli_rtp_rtcp_debug_ip_deprecated = {
- { "rtp", "rtcp", "debug", "ip", NULL },
- rtcp_do_debug_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_rtp_rtcp_debug_deprecated = {
- { "rtp", "rtcp", "debug", NULL },
- rtcp_do_debug_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_rtp_rtcp_no_debug_deprecated = {
- { "rtp", "rtcp", "no", "debug", NULL },
- rtcp_no_debug_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_rtp_rtcp_stats_deprecated = {
- { "rtp", "rtcp", "stats", NULL },
- rtcp_do_stats_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_rtp_rtcp_no_stats_deprecated = {
- { "rtp", "rtcp", "no", "stats", NULL },
- rtcp_no_stats_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_stun_no_debug_deprecated = {
- { "stun", "no", "debug", NULL },
- stun_no_debug, NULL,
- NULL };
-
-static struct ast_cli_entry cli_rtp[] = {
- { { "rtp", "debug", "ip", NULL },
- rtp_do_debug, "Enable RTP debugging on IP",
- debug_usage },
-
- { { "rtp", "debug", NULL },
- rtp_do_debug, "Enable RTP debugging",
- debug_usage },
-
- { { "rtp", "debug", "off", NULL },
- rtp_no_debug, "Disable RTP debugging",
- no_debug_usage, NULL, &cli_rtp_no_debug_deprecated },
-
- { { "rtcp", "debug", "ip", NULL },
- rtcp_do_debug, "Enable RTCP debugging on IP",
- rtcp_debug_usage, NULL, &cli_rtp_rtcp_debug_ip_deprecated },
-
- { { "rtcp", "debug", NULL },
- rtcp_do_debug, "Enable RTCP debugging",
- rtcp_debug_usage, NULL, &cli_rtp_rtcp_debug_deprecated },
-
- { { "rtcp", "debug", "off", NULL },
- rtcp_no_debug, "Disable RTCP debugging",
- rtcp_no_debug_usage, NULL, &cli_rtp_rtcp_no_debug_deprecated },
-
- { { "rtcp", "stats", NULL },
- rtcp_do_stats, "Enable RTCP stats",
- rtcp_stats_usage, NULL, &cli_rtp_rtcp_stats_deprecated },
-
- { { "rtcp", "stats", "off", NULL },
- rtcp_no_stats, "Disable RTCP stats",
- rtcp_no_stats_usage, NULL, &cli_rtp_rtcp_no_stats_deprecated },
-
- { { "stun", "debug", NULL },
- stun_do_debug, "Enable STUN debugging",
- stun_debug_usage },
-
- { { "stun", "debug", "off", NULL },
- stun_no_debug, "Disable STUN debugging",
- stun_no_debug_usage, NULL, &cli_stun_no_debug_deprecated },
-};
-
-int ast_rtp_reload(void)
-{
- struct ast_config *cfg;
- const char *s;
-
- rtpstart = 5000;
- rtpend = 31000;
- dtmftimeout = DEFAULT_DTMF_TIMEOUT;
- cfg = ast_config_load("rtp.conf");
- if (cfg) {
- if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
- rtpstart = atoi(s);
- if (rtpstart < 1024)
- rtpstart = 1024;
- if (rtpstart > 65535)
- rtpstart = 65535;
- }
- if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
- rtpend = atoi(s);
- if (rtpend < 1024)
- rtpend = 1024;
- if (rtpend > 65535)
- rtpend = 65535;
- }
- if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
- rtcpinterval = atoi(s);
- if (rtcpinterval == 0)
- rtcpinterval = 0; /* Just so we're clear... it's zero */
- if (rtcpinterval < RTCP_MIN_INTERVALMS)
- rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
- if (rtcpinterval > RTCP_MAX_INTERVALMS)
- rtcpinterval = RTCP_MAX_INTERVALMS;
- }
- if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
-#ifdef SO_NO_CHECK
- if (ast_false(s))
- nochecksums = 1;
- else
- nochecksums = 0;
-#else
- if (ast_false(s))
- ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
-#endif
- }
- if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
- dtmftimeout = atoi(s);
- if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
- ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
- dtmftimeout, DEFAULT_DTMF_TIMEOUT);
- dtmftimeout = DEFAULT_DTMF_TIMEOUT;
- };
- }
- ast_config_destroy(cfg);
- }
- if (rtpstart >= rtpend) {
- ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
- rtpstart = 5000;
- rtpend = 31000;
- }
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
- return 0;
-}
-
-/*! \brief Initialize the RTP system in Asterisk */
-void ast_rtp_init(void)
-{
- ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
- ast_rtp_reload();
-}
-
diff --git a/main/say.c b/main/say.c
deleted file mode 100644
index b6b973ccd..000000000
--- a/main/say.c
+++ /dev/null
@@ -1,7394 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- * George Konstantoulakis <gkon@inaccessnetworks.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Say numbers and dates (maybe words one day too)
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * \note 12-16-2004 : Support for Greek added by InAccess Networks (work funded by HOL, www.hol.gr) George Konstantoulakis <gkon@inaccessnetworks.com>
- *
- * \note 2007-02-08 : Support for Georgian added by Alexander Shaduri <ashaduri@gmail.com>,
- * Next Generation Networks (NGN).
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <string.h>
-#include <stdlib.h>
-#include <netinet/in.h>
-#include <time.h>
-#include <ctype.h>
-#include <math.h>
-#include <stdio.h>
-
-#ifdef SOLARIS
-#include <iso/limits_iso.h>
-#endif
-
-#include "asterisk/file.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/say.h"
-#include "asterisk/lock.h"
-#include "asterisk/localtime.h"
-#include "asterisk/utils.h"
-#include "asterisk/app.h"
-
-/* Forward declaration */
-static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang);
-
-
-static int say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
-{
- const char *fn;
- char fnbuf[256];
- char ltr;
- int num = 0;
- int res = 0;
-
- while (str[num] && !res) {
- fn = NULL;
- switch (str[num]) {
- case ('*'):
- fn = "digits/star";
- break;
- case ('#'):
- fn = "digits/pound";
- break;
- case ('!'):
- fn = "letters/exclaimation-point";
- break;
- case ('@'):
- fn = "letters/at";
- break;
- case ('$'):
- fn = "letters/dollar";
- break;
- case ('-'):
- fn = "letters/dash";
- break;
- case ('.'):
- fn = "letters/dot";
- break;
- case ('='):
- fn = "letters/equals";
- break;
- case ('+'):
- fn = "letters/plus";
- break;
- case ('/'):
- fn = "letters/slash";
- break;
- case (' '):
- fn = "letters/space";
- break;
- case ('0'):
- case ('1'):
- case ('2'):
- case ('3'):
- case ('4'):
- case ('5'):
- case ('6'):
- case ('7'):
- case ('8'):
- case ('9'):
- strcpy(fnbuf, "digits/X");
- fnbuf[7] = str[num];
- fn = fnbuf;
- break;
- default:
- ltr = str[num];
- if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A'; /* file names are all lower-case */
- strcpy(fnbuf, "letters/X");
- fnbuf[8] = ltr;
- fn = fnbuf;
- }
- if (fn && ast_fileexists(fn, NULL, lang) > 0) {
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- num++;
- }
-
- return res;
-}
-
-static int say_phonetic_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
-{
- const char *fn;
- char fnbuf[256];
- char ltr;
- int num = 0;
- int res = 0;
-
- while (str[num] && !res) {
- fn = NULL;
- switch (str[num]) {
- case ('*'):
- fn = "digits/star";
- break;
- case ('#'):
- fn = "digits/pound";
- break;
- case ('!'):
- fn = "letters/exclaimation-point";
- break;
- case ('@'):
- fn = "letters/at";
- break;
- case ('$'):
- fn = "letters/dollar";
- break;
- case ('-'):
- fn = "letters/dash";
- break;
- case ('.'):
- fn = "letters/dot";
- break;
- case ('='):
- fn = "letters/equals";
- break;
- case ('+'):
- fn = "letters/plus";
- break;
- case ('/'):
- fn = "letters/slash";
- break;
- case (' '):
- fn = "letters/space";
- break;
- case ('0'):
- case ('1'):
- case ('2'):
- case ('3'):
- case ('4'):
- case ('5'):
- case ('6'):
- case ('7'):
- case ('8'):
- strcpy(fnbuf, "digits/X");
- fnbuf[7] = str[num];
- fn = fnbuf;
- break;
- default: /* '9' falls here... */
- ltr = str[num];
- if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A'; /* file names are all lower-case */
- strcpy(fnbuf, "phonetic/X_p");
- fnbuf[9] = ltr;
- fn = fnbuf;
- }
- if (fn && ast_fileexists(fn, NULL, lang) > 0) {
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- num++;
- }
-
- return res;
-}
-
-static int say_digit_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
-{
- const char *fn;
- char fnbuf[256];
- int num = 0;
- int res = 0;
-
- while (str[num] && !res) {
- fn = NULL;
- switch (str[num]) {
- case ('*'):
- fn = "digits/star";
- break;
- case ('#'):
- fn = "digits/pound";
- break;
- case ('-'):
- fn = "digits/minus";
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- strcpy(fnbuf, "digits/X");
- fnbuf[7] = str[num];
- fn = fnbuf;
- break;
- }
- if (fn && ast_fileexists(fn, NULL, lang) > 0) {
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- num++;
- }
-
- return res;
-}
-
-/* Forward declarations */
-/*! \page Def_syntaxlang Asterisk Language Syntaxes supported
- \note Not really language codes.
- For these language codes, Asterisk will change the syntax when
- saying numbers (and in some cases dates and voicemail messages
- as well)
- \arg \b da - Danish
- \arg \b de - German
- \arg \b en - English (US)
- \arg \b en_GB - English (British)
- \arg \b es - Spanish, Mexican
- \arg \b fr - French
- \arg \b he - Hebrew
- \arg \b it - Italian
- \arg \b nl - Dutch
- \arg \b no - Norwegian
- \arg \b pl - Polish
- \arg \b pt - Portuguese
- \arg \b pt_BR - Portuguese (Brazil)
- \arg \b se - Swedish
- \arg \b tw - Taiwanese / Chinese
- \arg \b ru - Russian
- \arg \b ge - Georgian
-
- \par Gender:
- For Some languages the numbers differ for gender and plural.
- \arg Use the option argument 'f' for female, 'm' for male and 'n' for neuter in languages like Portuguese, French, Spanish and German.
- \arg use the option argument 'c' is for commune and 'n' for neuter gender in nordic languages like Danish, Swedish and Norwegian.
- use the option argument 'p' for plural enumerations like in German
-
- Date/Time functions currently have less languages supported than saynumber().
-
- \todo Note that in future, we need to move to a model where we can differentiate further - e.g. between en_US & en_UK
-
- See contrib/i18n.testsuite.conf for some examples of the different syntaxes
-
- \par Portuguese
- Portuguese sound files needed for Time/Date functions:
- pt-ah
- pt-ao
- pt-de
- pt-e
- pt-ora
- pt-meianoite
- pt-meiodia
- pt-sss
-
- \par Spanish
- Spanish sound files needed for Time/Date functions:
- es-de
- es-el
-
- \par Italian
- Italian sound files needed for Time/Date functions:
- ore-una
- ore-mezzanotte
-
-*/
-
-/* Forward declarations of language specific variants of ast_say_number_full */
-static int ast_say_number_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
-static int ast_say_number_full_cz(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_en_GB(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
-static int ast_say_number_full_es(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_it(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
-static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
-static int ast_say_number_full_no(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_pl(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_pt(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_se(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_tw(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
-static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
-static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_number_full_ge(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-
-/* Forward declarations of language specific variants of ast_say_enumeration_full */
-static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
-static int ast_say_enumeration_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_enumeration_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-static int ast_say_enumeration_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
-
-/* Forward declarations of ast_say_date, ast_say_datetime and ast_say_time functions */
-static int ast_say_date_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_date_da(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_date_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_date_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_date_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_date_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_date_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_date_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_date_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-
-static int ast_say_date_with_format_en(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_da(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_de(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_es(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_he(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_fr(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_it(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_nl(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_pl(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_tw(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
-
-static int ast_say_time_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_time_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_time_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_time_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_time_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_time_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_time_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_time_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_time_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_time_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-
-static int ast_say_datetime_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-
-static int ast_say_datetime_from_now_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_from_now_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_from_now_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-static int ast_say_datetime_from_now_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
-
-static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang)
-{
- int res;
- if ((res = ast_streamfile(chan, file, lang)))
- ast_log(LOG_WARNING, "Unable to play message %s\n", file);
- if (!res)
- res = ast_waitstream(chan, ints);
- return res;
-}
-
-/*! \brief ast_say_number_full: call language-specific functions */
-/* Called from AGI */
-static int say_number_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- if (!strcasecmp(language,"en") ) { /* English syntax */
- return(ast_say_number_full_en(chan, num, ints, language, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "cz") ) { /* Czech syntax */
- return(ast_say_number_full_cz(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "da") ) { /* Danish syntax */
- return(ast_say_number_full_da(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "de") ) { /* German syntax */
- return(ast_say_number_full_de(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "en_GB") ) { /* British syntax */
- return(ast_say_number_full_en_GB(chan, num, ints, language, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "no") ) { /* Norwegian syntax */
- return(ast_say_number_full_no(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "es") || !strcasecmp(language, "mx")) { /* Spanish syntax */
- return(ast_say_number_full_es(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "fr") ) { /* French syntax */
- return(ast_say_number_full_fr(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "he") ) { /* Hebrew syntax */
- return(ast_say_number_full_he(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "it") ) { /* Italian syntax */
- return(ast_say_number_full_it(chan, num, ints, language, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "nl") ) { /* Dutch syntax */
- return(ast_say_number_full_nl(chan, num, ints, language, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "pl") ) { /* Polish syntax */
- return(ast_say_number_full_pl(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "pt") || !strcasecmp(language, "pt_BR")) { /* Portuguese syntax */
- return(ast_say_number_full_pt(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "se") ) { /* Swedish syntax */
- return(ast_say_number_full_se(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "tw") || !strcasecmp(language, "zh") ) { /* Taiwanese / Chinese syntax */
- return(ast_say_number_full_tw(chan, num, ints, language, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "gr") ) { /* Greek syntax */
- return(ast_say_number_full_gr(chan, num, ints, language, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "ru") ) { /* Russian syntax */
- return(ast_say_number_full_ru(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "ge") ) { /* Georgian syntax */
- return(ast_say_number_full_ge(chan, num, ints, language, options, audiofd, ctrlfd));
- }
-
- /* Default to english */
- return(ast_say_number_full_en(chan, num, ints, language, audiofd, ctrlfd));
-}
-
-/*! \brief ast_say_number_full_en: English syntax */
-/* This is the default syntax, if no other syntax defined in this file is used */
-static int ast_say_number_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- char fn[256] = "";
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- while (!res && (num || playh)) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playh) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- playh = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
- num -= ((num / 10) * 10);
- } else {
- if (num < 1000){
- snprintf(fn, sizeof(fn), "digits/%d", (num/100));
- playh++;
- num -= ((num / 100) * 100);
- } else {
- if (num < 1000000) { /* 1,000,000 */
- res = ast_say_number_full_en(chan, num / 1000, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- num = num % 1000;
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else {
- if (num < 1000000000) { /* 1,000,000,000 */
- res = ast_say_number_full_en(chan, num / 1000000, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- num = num % 1000000;
- snprintf(fn, sizeof(fn), "digits/million");
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- }
- }
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-static int exp10_int(int power)
-{
- int x, res= 1;
- for (x=0;x<power;x++)
- res *= 10;
- return res;
-}
-
-/*! \brief ast_say_number_full_cz: Czech syntax */
-/* files needed:
- * 1m,2m - gender male
- * 1w,2w - gender female
- * 3,4,...,20
- * 30,40,...,90
- *
- * hundereds - 100 - sto, 200 - 2ste, 300,400 3,4sta, 500,600,...,900 5,6,...9set
- *
- * for each number 10^(3n + 3) exist 3 files represented as:
- * 1 tousand = jeden tisic = 1_E3
- * 2,3,4 tousands = dva,tri,ctyri tisice = 2-3_E3
- * 5,6,... tousands = pet,sest,... tisic = 5_E3
- *
- * million = _E6
- * miliard = _E9
- * etc...
- *
- * tousand, milion are gender male, so 1 and 2 is 1m 2m
- * miliard is gender female, so 1 and 2 is 1w 2w
- */
-static int ast_say_number_full_cz(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- char fn[256] = "";
-
- int hundered = 0;
- int left = 0;
- int length = 0;
-
- /* options - w = woman, m = man, n = neutral. Defaultl is woman */
- if (!options)
- options = "w";
-
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- while (!res && (num || playh)) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (num < 3 ) {
- snprintf(fn, sizeof(fn), "digits/%d%c",num,options[0]);
- playh = 0;
- num = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/%d",num);
- playh = 0;
- num = 0;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
- num -= ((num / 10) * 10);
- } else if (num < 1000) {
- hundered = num / 100;
- if ( hundered == 1 ) {
- snprintf(fn, sizeof(fn), "digits/1sto");
- } else if ( hundered == 2 ) {
- snprintf(fn, sizeof(fn), "digits/2ste");
- } else {
- res = ast_say_number_full_cz(chan,hundered,ints,language,options,audiofd,ctrlfd);
- if (res)
- return res;
- if (hundered == 3 || hundered == 4) {
- snprintf(fn, sizeof(fn), "digits/sta");
- } else if ( hundered > 4 ) {
- snprintf(fn, sizeof(fn), "digits/set");
- }
- }
- num -= (hundered * 100);
- } else { /* num > 1000 */
- length = (int)log10(num)+1;
- while ( (length % 3 ) != 1 ) {
- length--;
- }
- left = num / (exp10_int(length-1));
- if ( left == 2 ) {
- switch (length-1) {
- case 9: options = "w"; /* 1,000,000,000 gender female */
- break;
- default : options = "m"; /* others are male */
- }
- }
- if ( left > 1 ) { /* we dont say "one thousand" but only thousand */
- res = ast_say_number_full_cz(chan,left,ints,language,options,audiofd,ctrlfd);
- if (res)
- return res;
- }
- if ( left >= 5 ) { /* >= 5 have the same declesion */
- snprintf(fn, sizeof(fn), "digits/5_E%d",length-1);
- } else if ( left >= 2 && left <= 4 ) {
- snprintf(fn, sizeof(fn), "digits/2-4_E%d",length-1);
- } else { /* left == 1 */
- snprintf(fn, sizeof(fn), "digits/1_E%d",length-1);
- }
- num -= left * (exp10_int(length-1));
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1)) {
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- } else {
- res = ast_waitstream(chan, ints);
- }
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_da: Danish syntax */
-/* New files:
- In addition to English, the following sounds are required: "1N", "millions", "and" and "1-and" through "9-and"
- */
-static int ast_say_number_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- int playa = 0;
- int cn = 1; /* +1 = commune; -1 = neuter */
- char fn[256] = "";
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- if (options && !strncasecmp(options, "n",1)) cn = -1;
-
- while (!res && (num || playh || playa )) {
- /* The grammar for Danish numbers is the same as for English except
- * for the following:
- * - 1 exists in both commune ("en", file "1N") and neuter ("et", file "1")
- * - numbers 20 through 99 are said in reverse order, i.e. 21 is
- * "one-and twenty" and 68 is "eight-and sixty".
- * - "million" is different in singular and plural form
- * - numbers > 1000 with zero as the third digit from last have an
- * "and" before the last two digits, i.e. 2034 is "two thousand and
- * four-and thirty" and 1000012 is "one million and twelve".
- */
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playh) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- playh = 0;
- } else if (playa) {
- snprintf(fn, sizeof(fn), "digits/and");
- playa = 0;
- } else if (num == 1 && cn == -1) {
- snprintf(fn, sizeof(fn), "digits/1N");
- num = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- int ones = num % 10;
- if (ones) {
- snprintf(fn, sizeof(fn), "digits/%d-and", ones);
- num -= ones;
- } else {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- }
- } else {
- if (num < 1000) {
- int hundreds = num / 100;
- if (hundreds == 1)
- snprintf(fn, sizeof(fn), "digits/1N");
- else
- snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
-
- playh++;
- num -= 100 * hundreds;
- if (num)
- playa++;
-
- } else {
- if (num < 1000000) {
- res = ast_say_number_full_da(chan, num / 1000, ints, language, "n", audiofd, ctrlfd);
- if (res)
- return res;
- num = num % 1000;
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else {
- if (num < 1000000000) {
- int millions = num / 1000000;
- res = ast_say_number_full_da(chan, millions, ints, language, "c", audiofd, ctrlfd);
- if (res)
- return res;
- if (millions == 1)
- snprintf(fn, sizeof(fn), "digits/million");
- else
- snprintf(fn, sizeof(fn), "digits/millions");
- num = num % 1000000;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- }
- if (num && num < 100)
- playa++;
- }
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_de: German syntax */
-/* New files:
- In addition to English, the following sounds are required:
- "millions"
- "1-and" through "9-and"
- "1F" (eine)
- "1N" (ein)
- NB "1" is recorded as 'eins'
- */
-static int ast_say_number_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0, t = 0;
- int mf = 1; /* +1 = male and neuter; -1 = female */
- char fn[256] = "";
- char fna[256] = "";
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- if (options && (!strncasecmp(options, "f",1)))
- mf = -1;
-
- while (!res && num) {
- /* The grammar for German numbers is the same as for English except
- * for the following:
- * - numbers 20 through 99 are said in reverse order, i.e. 21 is
- * "one-and twenty" and 68 is "eight-and sixty".
- * - "one" varies according to gender
- * - 100 is 'hundert', however all other instances are 'ein hundert'
- * - 1000 is 'tausend', however all other instances are 'ein tausend'
- * - 1000000 is always 'eine million'
- * - "million" is different in singular and plural form
- */
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (num < 100 && t) {
- snprintf(fn, sizeof(fn), "digits/and");
- t = 0;
- } else if (num == 1 && mf == -1) {
- snprintf(fn, sizeof(fn), "digits/%dF", num);
- num = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- int ones = num % 10;
- if (ones) {
- snprintf(fn, sizeof(fn), "digits/%d-and", ones);
- num -= ones;
- } else {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- }
- } else if (num == 100 && t == 0) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- num = 0;
- } else if (num < 1000) {
- int hundreds = num / 100;
- num = num % 100;
- if (hundreds == 1) {
- snprintf(fn, sizeof(fn), "digits/1N");
- } else {
- snprintf(fn, sizeof(fn), "digits/%d", hundreds);
- }
- snprintf(fna, sizeof(fna), "digits/hundred");
- t = 1;
- } else if (num == 1000 && t == 0) {
- snprintf(fn, sizeof(fn), "digits/thousand");
- num = 0;
- } else if (num < 1000000) {
- int thousands = num / 1000;
- num = num % 1000;
- t = 1;
- if (thousands == 1) {
- snprintf(fn, sizeof(fn), "digits/1N");
- snprintf(fna, sizeof(fna), "digits/thousand");
- } else {
- res = ast_say_number_full_de(chan, thousands, ints, language, options, audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/thousand");
- }
- } else if (num < 1000000000) {
- int millions = num / 1000000;
- num = num % 1000000;
- t = 1;
- if (millions == 1) {
- snprintf(fn, sizeof(fn), "digits/1F");
- snprintf(fna, sizeof(fna), "digits/million");
- } else {
- res = ast_say_number_full_de(chan, millions, ints, language, options, audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/millions");
- }
- } else if (num <= INT_MAX) {
- int billions = num / 1000000000;
- num = num % 1000000000;
- t = 1;
- if (billions == 1) {
- snprintf(fn, sizeof(fn), "digits/1F");
- snprintf(fna, sizeof(fna), "digits/milliard");
- } else {
- res = ast_say_number_full_de(chan, billions, ints, language, options, audiofd, ctrlfd);
- if (res) {
- return res;
- }
- snprintf(fn, sizeof(fn), "digits/milliards");
- }
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- if (!res) {
- if (strlen(fna) != 0 && !ast_streamfile(chan, fna, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- strcpy(fna, "");
- }
- }
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_en_GB: British and Norwegian syntax */
-/* New files:
- In addition to American English, the following sounds are required: "and"
- */
-static int ast_say_number_full_en_GB(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- int playa = 0;
- char fn[256] = "";
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- while (!res && (num || playh || playa )) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playh) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- playh = 0;
- } else if (playa) {
- snprintf(fn, sizeof(fn), "digits/and");
- playa = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
- num -= ((num / 10) * 10);
- } else if (num < 1000) {
- int hundreds = num / 100;
- snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
-
- playh++;
- num -= 100 * hundreds;
- if (num)
- playa++;
- } else if (num < 1000000) {
- res = ast_say_number_full_en_GB(chan, num / 1000, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/thousand");
- num = num % 1000;
- if (num && num < 100)
- playa++;
- } else if (num < 1000000000) {
- int millions = num / 1000000;
- res = ast_say_number_full_en_GB(chan, millions, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/million");
- num = num % 1000000;
- if (num && num < 100)
- playa++;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
-
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_es: Spanish syntax */
-/* New files:
- Requires a few new audios:
- 1F.gsm: feminine 'una'
- 21.gsm thru 29.gsm, cien.gsm, mil.gsm, millon.gsm, millones.gsm, 100.gsm, 200.gsm, 300.gsm, 400.gsm, 500.gsm, 600.gsm, 700.gsm, 800.gsm, 900.gsm, y.gsm
- */
-static int ast_say_number_full_es(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playa = 0;
- int mf = 0; /* +1 = male; -1 = female */
- char fn[256] = "";
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- if (options) {
- if (!strncasecmp(options, "f",1))
- mf = -1;
- else if (!strncasecmp(options, "m", 1))
- mf = 1;
- }
-
- while (!res && num) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playa) {
- snprintf(fn, sizeof(fn), "digits/and");
- playa = 0;
- } else if (num == 1) {
- if (mf < 0)
- snprintf(fn, sizeof(fn), "digits/%dF", num);
- else if (mf > 0)
- snprintf(fn, sizeof(fn), "digits/%dM", num);
- else
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 31) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10);
- num -= ((num/10)*10);
- if (num)
- playa++;
- } else if (num == 100) {
- snprintf(fn, sizeof(fn), "digits/100");
- num = 0;
- } else if (num < 200) {
- snprintf(fn, sizeof(fn), "digits/100-and");
- num -= 100;
- } else {
- if (num < 1000) {
- snprintf(fn, sizeof(fn), "digits/%d", (num/100)*100);
- num -= ((num/100)*100);
- } else if (num < 2000) {
- num = num % 1000;
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else {
- if (num < 1000000) {
- res = ast_say_number_full_es(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
- if (res)
- return res;
- num = num % 1000;
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else {
- if (num < 2147483640) {
- if ((num/1000000) == 1) {
- res = ast_say_number_full_es(chan, num / 1000000, ints, language, "M", audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/million");
- } else {
- res = ast_say_number_full_es(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/millions");
- }
- num = num % 1000000;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- }
- }
- }
-
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
-
- }
-
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_fr: French syntax */
-/* Extra sounds needed:
- 1F: feminin 'une'
- et: 'and' */
-static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- int playa = 0;
- int mf = 1; /* +1 = male; -1 = female */
- char fn[256] = "";
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- if (options && !strncasecmp(options, "f",1))
- mf = -1;
-
- while (!res && (num || playh || playa)) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playh) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- playh = 0;
- } else if (playa) {
- snprintf(fn, sizeof(fn), "digits/et");
- playa = 0;
- } else if (num == 1) {
- if (mf < 0)
- snprintf(fn, sizeof(fn), "digits/%dF", num);
- else
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 21) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 70) {
- snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10);
- if ((num % 10) == 1) playa++;
- num = num % 10;
- } else if (num < 80) {
- snprintf(fn, sizeof(fn), "digits/60");
- if ((num % 10) == 1) playa++;
- num = num - 60;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/80");
- num = num - 80;
- } else if (num < 200) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- num = num - 100;
- } else if (num < 1000) {
- snprintf(fn, sizeof(fn), "digits/%d", (num/100));
- playh++;
- num = num % 100;
- } else if (num < 2000) {
- snprintf(fn, sizeof(fn), "digits/thousand");
- num = num - 1000;
- } else if (num < 1000000) {
- res = ast_say_number_full_fr(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/thousand");
- num = num % 1000;
- } else if (num < 1000000000) {
- res = ast_say_number_full_fr(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/million");
- num = num % 1000000;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-
-
-/* Hebrew syntax */
-/* Check doc/lang/hebrew-digits.txt for information about the various
- * recordings required to make this translation work properly */
-#define SAY_NUM_BUF_SIZE 256
-static int ast_say_number_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- int state = 0; /* no need to save anything */
- int mf = -1; /* +1 = Masculin; -1 = Feminin */
- int tmpnum = 0;
-
- char fn[SAY_NUM_BUF_SIZE] = "";
-
- ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: started. num: %d, options=\"%s\"\n", num, options);
-
- if (!num) {
- return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
- }
- if (options && !strncasecmp(options, "m", 1)) {
- mf = 1;
- }
- ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d\n", num, state, options, mf);
-
- /* Do we have work to do? */
- while (!res && (num || (state > 0))) {
- /* first type of work: play a second sound. In this loop
- * we can only play one sound file at a time. Thus playing
- * a second one requires repeating the loop just for the
- * second file. The variable 'state' remembers where we were.
- * state==0 is the normal mode and it means that we continue
- * to check if the number num has yet anything left.
- */
- ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d, tmpnum=%d\n", num, state, options, mf, tmpnum);
-
- if (state == 1) {
- state = 0;
- } else if (state == 2) {
- if ((num >= 11) && (num < 21)) {
- if (mf < 0) {
- snprintf(fn, sizeof(fn), "digits/ve");
- } else {
- snprintf(fn, sizeof(fn), "digits/uu");
- }
- } else {
- switch (num) {
- case 1:
- snprintf(fn, sizeof(fn), "digits/ve");
- break;
- case 2:
- snprintf(fn, sizeof(fn), "digits/uu");
- break;
- case 3:
- if (mf < 0) {
- snprintf(fn, sizeof(fn), "digits/ve");
- } else {
- snprintf(fn, sizeof(fn), "digits/uu");
- }
- break;
- case 4:
- snprintf(fn, sizeof(fn), "digits/ve");
- break;
- case 5:
- snprintf(fn, sizeof(fn), "digits/ve");
- break;
- case 6:
- snprintf(fn, sizeof(fn), "digits/ve");
- break;
- case 7:
- snprintf(fn, sizeof(fn), "digits/ve");
- break;
- case 8:
- snprintf(fn, sizeof(fn), "digits/uu");
- break;
- case 9:
- snprintf(fn, sizeof(fn), "digits/ve");
- break;
- case 10:
- snprintf(fn, sizeof(fn), "digits/ve");
- break;
- }
- }
- state = 0;
- } else if (state == 3) {
- snprintf(fn, sizeof(fn), "digits/1k");
- state = 0;
- } else if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- num = (-1) * num;
- } else if (num < 20) {
- if (mf < 0) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- } else {
- snprintf(fn, sizeof(fn), "digits/%dm", num);
- }
- num = 0;
- } else if ((num < 100) && (num >= 20)) {
- snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
- num = num % 10;
- if (num > 0) {
- state = 2;
- }
- } else if ((num >= 100) && (num < 1000)) {
- tmpnum = num / 100;
- snprintf(fn, sizeof(fn), "digits/%d00", tmpnum);
- num = num - (tmpnum * 100);
- if ((num > 0) && (num < 11)) {
- state = 2;
- }
- } else if ((num >= 1000) && (num < 10000)) {
- tmpnum = num / 1000;
- snprintf(fn, sizeof(fn), "digits/%dk", tmpnum);
- num = num - (tmpnum * 1000);
- if ((num > 0) && (num < 11)) {
- state = 2;
- }
- } else if (num < 20000) {
- snprintf(fn, sizeof(fn), "digits/%dm", (num / 1000));
- num = num % 1000;
- state = 3;
- } else if (num < 1000000) {
- res = ast_say_number_full_he(chan, num / 1000, ints, language, "m", audiofd, ctrlfd);
- if (res) {
- return res;
- }
- snprintf(fn, sizeof(fn), "digits/1k");
- num = num % 1000;
- if ((num > 0) && (num < 11)) {
- state = 2;
- }
- } else if (num < 2000000) {
- snprintf(fn, sizeof(fn), "digits/million");
- num = num % 1000000;
- if ((num > 0) && (num < 11)) {
- state = 2;
- }
- } else if (num < 3000000) {
- snprintf(fn, sizeof(fn), "digits/twomillion");
- num = num - 2000000;
- if ((num > 0) && (num < 11)) {
- state = 2;
- }
- } else if (num < 1000000000) {
- res = ast_say_number_full_he(chan, num / 1000000, ints, language, "m", audiofd, ctrlfd);
- if (res) {
- return res;
- }
- snprintf(fn, sizeof(fn), "digits/million");
- num = num % 1000000;
- if ((num > 0) && (num < 11)) {
- state = 2;
- }
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- tmpnum = 0;
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1)) {
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- } else {
- res = ast_waitstream(chan, ints);
- }
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_it: Italian */
-static int ast_say_number_full_it(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- int tempnum = 0;
- char fn[256] = "";
-
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- /*
- Italian support
-
- Like english, numbers up to 20 are a single 'word', and others
- compound, but with exceptions.
- For example 21 is not twenty-one, but there is a single word in 'it'.
- Idem for 28 (ie when a the 2nd part of a compund number
- starts with a vowel)
-
- There are exceptions also for hundred, thousand and million.
- In english 100 = one hundred, 200 is two hundred.
- In italian 100 = cento , like to say hundred (without one),
- 200 and more are like english.
-
- Same applies for thousand:
- 1000 is one thousand in en, 2000 is two thousand.
- In it we have 1000 = mille , 2000 = 2 mila
-
- For million(s) we use the plural, if more than one
- Also, one million is abbreviated in it, like on-million,
- or 'un milione', not 'uno milione'.
- So the right file is provided.
- */
-
- while (!res && (num || playh)) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playh) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- playh = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 21) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 28) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 31) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 38) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 41) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 48) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 51) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 58) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 61) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 68) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 71) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 78) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 81) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 88) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 91) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num == 98) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
- num -= ((num / 10) * 10);
- } else {
- if (num < 1000) {
- if ((num / 100) > 1) {
- snprintf(fn, sizeof(fn), "digits/%d", (num/100));
- playh++;
- } else {
- snprintf(fn, sizeof(fn), "digits/hundred");
- }
- num -= ((num / 100) * 100);
- } else {
- if (num < 1000000) { /* 1,000,000 */
- if ((num/1000) > 1)
- res = ast_say_number_full_it(chan, num / 1000, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- tempnum = num;
- num = num % 1000;
- if ((tempnum / 1000) < 2)
- snprintf(fn, sizeof(fn), "digits/thousand");
- else /* for 1000 it says mille, for >1000 (eg 2000) says mila */
- snprintf(fn, sizeof(fn), "digits/thousands");
- } else {
- if (num < 1000000000) { /* 1,000,000,000 */
- if ((num / 1000000) > 1)
- res = ast_say_number_full_it(chan, num / 1000000, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- tempnum = num;
- num = num % 1000000;
- if ((tempnum / 1000000) < 2)
- snprintf(fn, sizeof(fn), "digits/million");
- else
- snprintf(fn, sizeof(fn), "digits/millions");
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- }
- }
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_nl: dutch syntax */
-/* New files: digits/nl-en
- */
-static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- int units = 0;
- char fn[256] = "";
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
- while (!res && (num || playh )) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playh) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- playh = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- units = num % 10;
- if (units > 0) {
- res = ast_say_number_full_nl(chan, units, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- num = num - units;
- snprintf(fn, sizeof(fn), "digits/nl-en");
- } else {
- snprintf(fn, sizeof(fn), "digits/%d", num - units);
- num = 0;
- }
- } else if (num < 200) {
- /* hundred, not one-hundred */
- ast_copy_string(fn, "digits/hundred", sizeof(fn));
- num -= ((num / 100) * 100);
- } else if (num < 1000) {
- snprintf(fn, sizeof(fn), "digits/%d", num / 100);
- playh++;
- num -= ((num / 100) * 100);
- } else {
- if (num < 1100) {
- /* thousand, not one-thousand */
- num = num % 1000;
- ast_copy_string(fn, "digits/thousand", sizeof(fn));
- } else if (num < 10000) { /* 1,100 to 9,9999 */
- res = ast_say_number_full_nl(chan, num / 100, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- num = num % 100;
- ast_copy_string(fn, "digits/hundred", sizeof(fn));
- } else {
- if (num < 1000000) { /* 1,000,000 */
- res = ast_say_number_full_nl(chan, num / 1000, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- num = num % 1000;
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else {
- if (num < 1000000000) { /* 1,000,000,000 */
- res = ast_say_number_full_nl(chan, num / 1000000, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- num = num % 1000000;
- snprintf(fn, sizeof(fn), "digits/million");
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- }
- }
- }
-
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_no: Norwegian syntax */
-/* New files:
- In addition to American English, the following sounds are required: "and", "1N"
- */
-static int ast_say_number_full_no(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- int playa = 0;
- int cn = 1; /* +1 = commune; -1 = neuter */
- char fn[256] = "";
-
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- if (options && !strncasecmp(options, "n",1)) cn = -1;
-
- while (!res && (num || playh || playa )) {
- /* The grammar for Norwegian numbers is the same as for English except
- * for the following:
- * - 1 exists in both commune ("en", file "1") and neuter ("ett", file "1N")
- * "and" before the last two digits, i.e. 2034 is "two thousand and
- * thirty-four" and 1000012 is "one million and twelve".
- */
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playh) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- playh = 0;
- } else if (playa) {
- snprintf(fn, sizeof(fn), "digits/and");
- playa = 0;
- } else if (num == 1 && cn == -1) {
- snprintf(fn, sizeof(fn), "digits/1N");
- num = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
- num -= ((num / 10) * 10);
- } else if (num < 1000) {
- int hundreds = num / 100;
- if (hundreds == 1)
- snprintf(fn, sizeof(fn), "digits/1N");
- else
- snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
-
- playh++;
- num -= 100 * hundreds;
- if (num)
- playa++;
- } else if (num < 1000000) {
- res = ast_say_number_full_no(chan, num / 1000, ints, language, "n", audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/thousand");
- num = num % 1000;
- if (num && num < 100)
- playa++;
- } else if (num < 1000000000) {
- int millions = num / 1000000;
- res = ast_say_number_full_no(chan, millions, ints, language, "c", audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(fn, sizeof(fn), "digits/million");
- num = num % 1000000;
- if (num && num < 100)
- playa++;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
-
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-typedef struct {
- char *separator_dziesiatek;
- char *cyfry[10];
- char *cyfry2[10];
- char *setki[10];
- char *dziesiatki[10];
- char *nastki[10];
- char *rzedy[3][3];
-} odmiana;
-
-static char *pl_rzad_na_tekst(odmiana *odm, int i, int rzad)
-{
- if (rzad==0)
- return "";
-
- if (i==1)
- return odm->rzedy[rzad - 1][0];
- if ((i > 21 || i < 11) && i%10 > 1 && i%10 < 5)
- return odm->rzedy[rzad - 1][1];
- else
- return odm->rzedy[rzad - 1][2];
-}
-
-static char* pl_append(char* buffer, char* str)
-{
- strcpy(buffer, str);
- buffer += strlen(str);
- return buffer;
-}
-
-static void pl_odtworz_plik(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, char *fn)
-{
- char file_name[255] = "digits/";
- strcat(file_name, fn);
- ast_log(LOG_DEBUG, "Trying to play: %s\n", file_name);
- if (!ast_streamfile(chan, file_name, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
-}
-
-static void powiedz(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, odmiana *odm, int rzad, int i)
-{
- /* Initialise variables to allow compilation on Debian-stable, etc */
- int m1000E6 = 0;
- int i1000E6 = 0;
- int m1000E3 = 0;
- int i1000E3 = 0;
- int m1000 = 0;
- int i1000 = 0;
- int m100 = 0;
- int i100 = 0;
-
- if (i == 0 && rzad > 0) {
- return;
- }
- if (i == 0) {
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[0]);
- return;
- }
-
- m1000E6 = i % 1000000000;
- i1000E6 = i / 1000000000;
-
- powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+3, i1000E6);
-
- m1000E3 = m1000E6 % 1000000;
- i1000E3 = m1000E6 / 1000000;
-
- powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+2, i1000E3);
-
- m1000 = m1000E3 % 1000;
- i1000 = m1000E3 / 1000;
-
- powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+1, i1000);
-
- m100 = m1000 % 100;
- i100 = m1000 / 100;
-
- if (i100>0)
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->setki[i100]);
-
- if ( m100 > 0 && m100 <=9 ) {
- if (m1000>0)
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100]);
- else
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[m100]);
- } else if (m100 % 10 == 0) {
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
- } else if (m100 <= 19 ) {
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->nastki[m100 % 10]);
- } else if (m100 != 0) {
- if (odm->separator_dziesiatek[0]==' ') {
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100 % 10]);
- } else {
- char buf[10];
- char *b = buf;
- b = pl_append(b, odm->dziesiatki[m100 / 10]);
- b = pl_append(b, odm->separator_dziesiatek);
- b = pl_append(b, odm->cyfry2[m100 % 10]);
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, buf);
- }
- }
-
- if (rzad > 0) {
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, pl_rzad_na_tekst(odm, i, rzad));
- }
-}
-
-/* ast_say_number_full_pl: Polish syntax */
-static int ast_say_number_full_pl(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-/*
-Sounds needed:
-0 zero
-1 jeden
-10 dziesiec
-100 sto
-1000 tysiac
-1000000 milion
-1000000000 miliard
-1000000000.2 miliardy
-1000000000.5 miliardow
-1000000.2 miliony
-1000000.5 milionow
-1000.2 tysiace
-1000.5 tysiecy
-100m stu
-10m dziesieciu
-11 jedenascie
-11m jedenastu
-12 dwanascie
-12m dwunastu
-13 trzynascie
-13m trzynastu
-14 czternascie
-14m czternastu
-15 pietnascie
-15m pietnastu
-16 szesnascie
-16m szesnastu
-17 siedemnascie
-17m siedemnastu
-18 osiemnascie
-18m osiemnastu
-19 dziewietnascie
-19m dziewietnastu
-1z jedna
-2 dwa
-20 dwadziescia
-200 dwiescie
-200m dwustu
-20m dwudziestu
-2-1m dwaj
-2-2m dwoch
-2z dwie
-3 trzy
-30 trzydziesci
-300 trzysta
-300m trzystu
-30m trzydziestu
-3-1m trzej
-3-2m trzech
-4 cztery
-40 czterdziesci
-400 czterysta
-400m czterystu
-40m czterdziestu
-4-1m czterej
-4-2m czterech
-5 piec
-50 piecdziesiat
-500 piecset
-500m pieciuset
-50m piedziesieciu
-5m pieciu
-6 szesc
-60 szescdziesiat
-600 szescset
-600m szesciuset
-60m szescdziesieciu
-6m szesciu
-7 siedem
-70 siedemdziesiat
-700 siedemset
-700m siedmiuset
-70m siedemdziesieciu
-7m siedmiu
-8 osiem
-80 osiemdziesiat
-800 osiemset
-800m osmiuset
-80m osiemdziesieciu
-8m osmiu
-9 dziewiec
-90 dziewiecdziesiat
-900 dziewiecset
-900m dziewieciuset
-90m dziewiedziesieciu
-9m dziewieciu
-and combinations of eg.: 20_1, 30m_3m, etc...
-
-*/
-{
- char *zenski_cyfry[] = {"0","1z", "2z", "3", "4", "5", "6", "7", "8", "9"};
-
- char *zenski_cyfry2[] = {"0","1", "2z", "3", "4", "5", "6", "7", "8", "9"};
-
- char *meski_cyfry[] = {"0","1", "2-1m", "3-1m", "4-1m", "5m", /*"2-1mdwaj"*/ "6m", "7m", "8m", "9m"};
-
- char *meski_cyfry2[] = {"0","1", "2-2m", "3-2m", "4-2m", "5m", "6m", "7m", "8m", "9m"};
-
- char *meski_setki[] = {"", "100m", "200m", "300m", "400m", "500m", "600m", "700m", "800m", "900m"};
-
- char *meski_dziesiatki[] = {"", "10m", "20m", "30m", "40m", "50m", "60m", "70m", "80m", "90m"};
-
- char *meski_nastki[] = {"", "11m", "12m", "13m", "14m", "15m", "16m", "17m", "18m", "19m"};
-
- char *nijaki_cyfry[] = {"0","1", "2", "3", "4", "5", "6", "7", "8", "9"};
-
- char *nijaki_cyfry2[] = {"0","1", "2", "3", "4", "5", "6", "7", "8", "9"};
-
- char *nijaki_setki[] = {"", "100", "200", "300", "400", "500", "600", "700", "800", "900"};
-
- char *nijaki_dziesiatki[] = {"", "10", "20", "30", "40", "50", "60", "70", "80", "90"};
-
- char *nijaki_nastki[] = {"", "11", "12", "13", "14", "15", "16", "17", "18", "19"};
-
- char *rzedy[][3] = { {"1000", "1000.2", "1000.5"}, {"1000000", "1000000.2", "1000000.5"}, {"1000000000", "1000000000.2", "1000000000.5"}};
-
- /* Initialise variables to allow compilation on Debian-stable, etc */
- odmiana *o;
-
- static odmiana *odmiana_nieosobowa = NULL;
- static odmiana *odmiana_meska = NULL;
- static odmiana *odmiana_zenska = NULL;
-
- if (odmiana_nieosobowa == NULL) {
- odmiana_nieosobowa = (odmiana *) malloc(sizeof(odmiana));
-
- odmiana_nieosobowa->separator_dziesiatek = " ";
-
- memcpy(odmiana_nieosobowa->cyfry, nijaki_cyfry, sizeof(odmiana_nieosobowa->cyfry));
- memcpy(odmiana_nieosobowa->cyfry2, nijaki_cyfry2, sizeof(odmiana_nieosobowa->cyfry));
- memcpy(odmiana_nieosobowa->setki, nijaki_setki, sizeof(odmiana_nieosobowa->setki));
- memcpy(odmiana_nieosobowa->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_nieosobowa->dziesiatki));
- memcpy(odmiana_nieosobowa->nastki, nijaki_nastki, sizeof(odmiana_nieosobowa->nastki));
- memcpy(odmiana_nieosobowa->rzedy, rzedy, sizeof(odmiana_nieosobowa->rzedy));
- }
-
- if (odmiana_zenska == NULL) {
- odmiana_zenska = (odmiana *) malloc(sizeof(odmiana));
-
- odmiana_zenska->separator_dziesiatek = " ";
-
- memcpy(odmiana_zenska->cyfry, zenski_cyfry, sizeof(odmiana_zenska->cyfry));
- memcpy(odmiana_zenska->cyfry2, zenski_cyfry2, sizeof(odmiana_zenska->cyfry));
- memcpy(odmiana_zenska->setki, nijaki_setki, sizeof(odmiana_zenska->setki));
- memcpy(odmiana_zenska->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_zenska->dziesiatki));
- memcpy(odmiana_zenska->nastki, nijaki_nastki, sizeof(odmiana_zenska->nastki));
- memcpy(odmiana_zenska->rzedy, rzedy, sizeof(odmiana_zenska->rzedy));
- }
-
- if (odmiana_meska == NULL) {
- odmiana_meska = (odmiana *) malloc(sizeof(odmiana));
-
- odmiana_meska->separator_dziesiatek = " ";
-
- memcpy(odmiana_meska->cyfry, meski_cyfry, sizeof(odmiana_meska->cyfry));
- memcpy(odmiana_meska->cyfry2, meski_cyfry2, sizeof(odmiana_meska->cyfry));
- memcpy(odmiana_meska->setki, meski_setki, sizeof(odmiana_meska->setki));
- memcpy(odmiana_meska->dziesiatki, meski_dziesiatki, sizeof(odmiana_meska->dziesiatki));
- memcpy(odmiana_meska->nastki, meski_nastki, sizeof(odmiana_meska->nastki));
- memcpy(odmiana_meska->rzedy, rzedy, sizeof(odmiana_meska->rzedy));
- }
-
- if (options) {
- if (strncasecmp(options, "f", 1) == 0)
- o = odmiana_zenska;
- else if (strncasecmp(options, "m", 1) == 0)
- o = odmiana_meska;
- else
- o = odmiana_nieosobowa;
- } else
- o = odmiana_nieosobowa;
-
- powiedz(chan, language, audiofd, ctrlfd, ints, o, 0, num);
- return 0;
-}
-
-/* ast_say_number_full_pt: Portuguese syntax */
-/* Extra sounds needed: */
-/* For feminin all sound files end with F */
-/* 100E for 100+ something */
-/* 1000000S for plural */
-/* pt-e for 'and' */
-static int ast_say_number_full_pt(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- int mf = 1; /* +1 = male; -1 = female */
- char fn[256] = "";
-
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- if (options && !strncasecmp(options, "f",1))
- mf = -1;
-
- while (!res && num ) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (num < 20) {
- if ((num == 1 || num == 2) && (mf < 0))
- snprintf(fn, sizeof(fn), "digits/%dF", num);
- else
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
- if (num % 10)
- playh = 1;
- num = num % 10;
- } else if (num < 1000) {
- if (num == 100)
- snprintf(fn, sizeof(fn), "digits/100");
- else if (num < 200)
- snprintf(fn, sizeof(fn), "digits/100E");
- else {
- if (mf < 0 && num > 199)
- snprintf(fn, sizeof(fn), "digits/%dF", (num / 100) * 100);
- else
- snprintf(fn, sizeof(fn), "digits/%d", (num / 100) * 100);
- if (num % 100)
- playh = 1;
- }
- num = num % 100;
- } else if (num < 1000000) {
- if (num > 1999) {
- res = ast_say_number_full_pt(chan, (num / 1000) * mf, ints, language, options, audiofd, ctrlfd);
- if (res)
- return res;
- }
- snprintf(fn, sizeof(fn), "digits/1000");
- if ((num % 1000) && ((num % 1000) < 100 || !(num % 100)))
- playh = 1;
- num = num % 1000;
- } else if (num < 1000000000) {
- res = ast_say_number_full_pt(chan, (num / 1000000), ints, language, options, audiofd, ctrlfd );
- if (res)
- return res;
- if (num < 2000000)
- snprintf(fn, sizeof(fn), "digits/1000000");
- else
- snprintf(fn, sizeof(fn), "digits/1000000S");
-
- if ((num % 1000000) &&
- /* no thousands */
- ((!((num / 1000) % 1000) && ((num % 1000) < 100 || !(num % 100))) ||
- /* no hundreds and below */
- (!(num % 1000) && (((num / 1000) % 1000) < 100 || !((num / 1000) % 100))) ) )
- playh = 1;
- num = num % 1000000;
- } else {
- /* number is too big */
- ast_log(LOG_WARNING, "Number '%d' is too big to say.", num);
- res = -1;
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- if (!res && playh) {
- res = wait_file(chan, ints, "digits/pt-e", language);
- ast_stopstream(chan);
- playh = 0;
- }
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_se: Swedish syntax */
-static int ast_say_number_full_se(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- char fn[256] = "";
- int cn = 1; /* +1 = commune; -1 = neuter */
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
- if (options && !strncasecmp(options, "n",1)) cn = -1;
-
- while (!res && (num || playh)) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playh) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- playh = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
- num -= ((num / 10) * 10);
- } else if (num == 1 && cn == -1) { /* En eller ett? */
- snprintf(fn, sizeof(fn), "digits/1N");
- num = 0;
- } else {
- if (num < 1000){
- snprintf(fn, sizeof(fn), "digits/%d", (num/100));
- playh++;
- num -= ((num / 100) * 100);
- } else {
- if (num < 1000000) { /* 1,000,000 */
- res = ast_say_number_full_se(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
- if (res) {
- return res;
- }
- num = num % 1000;
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else {
- if (num < 1000000000) { /* 1,000,000,000 */
- res = ast_say_number_full_se(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
- if (res) {
- return res;
- }
- num = num % 1000000;
- snprintf(fn, sizeof(fn), "digits/million");
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- }
- }
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- ast_stopstream(chan);
- }
- }
- }
- return res;
-}
-
-/*! \brief ast_say_number_full_tw: Taiwanese / Chinese syntax */
-static int ast_say_number_full_tw(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
-{
- int res = 0;
- int playh = 0;
- int playt = 0;
- int playz = 0;
- int last_length = 0;
- char buf[20] = "";
- char fn[256] = "";
- if (!num)
- return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
-
- while (!res && (num || playh || playt || playz)) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (playz) {
- snprintf(fn, sizeof(fn), "digits/0");
- last_length = 0;
- playz = 0;
- } else if (playh) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- playh = 0;
- } else if (playt) {
- snprintf(fn, sizeof(fn), "digits/thousand");
- playt = 0;
- } else if (num < 10) {
- snprintf(buf, 10, "%d", num);
- if (last_length - strlen(buf) > 1 && last_length != 0) {
- last_length = strlen(buf);
- playz++;
- continue;
- }
- if (strcasecmp(language,"twz") == 0)
- snprintf(fn, sizeof(fn), "digits/%d", num);
- else
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num < 100) {
- snprintf(buf, 10, "%d", num);
- if (last_length - strlen(buf) > 1 && last_length != 0) {
- last_length = strlen(buf);
- playz++;
- continue;
- }
- last_length = strlen(buf);
- snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
- num -= ((num / 10) * 10);
- } else {
- if (num < 1000){
- snprintf(buf, 10, "%d", num);
- if (last_length - strlen(buf) > 1 && last_length != 0) {
- last_length = strlen(buf);
- playz++;
- continue;
- }
- snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
- playh++;
- snprintf(buf, 10, "%d", num);
- ast_log(LOG_DEBUG, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
- last_length = strlen(buf);
- num -= ((num / 100) * 100);
- } else if (num < 10000){
- snprintf(buf, 10, "%d", num);
- if (last_length - strlen(buf) > 1 && last_length != 0 && last_length % strlen(buf) > 0) {
- last_length = strlen(buf);
- playz++;
- continue;
- }
- snprintf(fn, sizeof(fn), "digits/%d", (num / 1000));
- playt++;
- snprintf(buf, 10, "%d", num);
- ast_log(LOG_DEBUG, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
- last_length = strlen(buf);
- num -= ((num / 1000) * 1000);
- } else if (num < 100000000) { /* 100,000,000 */
- res = ast_say_number_full_tw(chan, num / 10000, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- if (((num / 10000) % (num/100000)) == 0)
- playz++;
-
- snprintf(buf, 10, "%d", num);
- ast_log(LOG_DEBUG, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
- num -= ((num / 10000) * 10000);
- last_length = strlen(buf);
- snprintf(fn, sizeof(fn), "digits/wan");
- } else {
- if (num < 1000000000) { /* 1000,000,000 */
- res = ast_say_number_full_tw(chan, num / 100000000, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- snprintf(buf, 10, "%d", num);
- ast_log(LOG_DEBUG, "Number '%d' %d %d\n", num, (int)strlen(buf), last_length);
- last_length = strlen(buf);
- num -= ((num / 100000000) * 100000000);
- snprintf(fn, sizeof(fn), "digits/yi");
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- }
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-
-/*! \brief determine last digits for thousands/millions (ru) */
-static int get_lastdigits_ru(int num) {
- if (num < 20) {
- return num;
- } else if (num < 100) {
- return get_lastdigits_ru(num % 10);
- } else if (num < 1000) {
- return get_lastdigits_ru(num % 100);
- }
- return 0; /* number too big */
-}
-
-
-/*! \brief ast_say_number_full_ru: Russian syntax */
-/*! \brief additional files:
- n00.gsm (one hundred, two hundred, ...)
- thousand.gsm
- million.gsm
- thousands-i.gsm (tisyachi)
- million-a.gsm (milliona)
- thousands.gsm
- millions.gsm
- 1f.gsm (odna)
- 2f.gsm (dve)
-
- where 'n' from 1 to 9
-*/
-static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- int lastdigits = 0;
- char fn[256] = "";
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- while (!res && (num)) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus");
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (num < 20) {
- if (options && strlen(options) == 1 && num < 3) {
- snprintf(fn, sizeof(fn), "digits/%d%s", num, options);
- } else {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- }
- num = 0;
- } else if (num < 100) {
- snprintf(fn, sizeof(fn), "digits/%d", num - (num % 10));
- num %= 10;
- } else if (num < 1000){
- snprintf(fn, sizeof(fn), "digits/%d", num - (num % 100));
- num %= 100;
- } else if (num < 1000000) { /* 1,000,000 */
- lastdigits = get_lastdigits_ru(num / 1000);
- /* say thousands */
- if (lastdigits < 3) {
- res = ast_say_number_full_ru(chan, num / 1000, ints, language, "f", audiofd, ctrlfd);
- } else {
- res = ast_say_number_full_ru(chan, num / 1000, ints, language, NULL, audiofd, ctrlfd);
- }
- if (res)
- return res;
- if (lastdigits == 1) {
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else if (lastdigits > 1 && lastdigits < 5) {
- snprintf(fn, sizeof(fn), "digits/thousands-i");
- } else {
- snprintf(fn, sizeof(fn), "digits/thousands");
- }
- num %= 1000;
- } else if (num < 1000000000) { /* 1,000,000,000 */
- lastdigits = get_lastdigits_ru(num / 1000000);
- /* say millions */
- res = ast_say_number_full_ru(chan, num / 1000000, ints, language, NULL, audiofd, ctrlfd);
- if (res)
- return res;
- if (lastdigits == 1) {
- snprintf(fn, sizeof(fn), "digits/million");
- } else if (lastdigits > 1 && lastdigits < 5) {
- snprintf(fn, sizeof(fn), "digits/million-a");
- } else {
- snprintf(fn, sizeof(fn), "digits/millions");
- }
- num %= 1000000;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-
-/*! \brief ast_say_enumeration_full: call language-specific functions */
-/* Called from AGI */
-static int say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- if (!strcasecmp(language,"en") ) { /* English syntax */
- return(ast_say_enumeration_full_en(chan, num, ints, language, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "da") ) { /* Danish syntax */
- return(ast_say_enumeration_full_da(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "de") ) { /* German syntax */
- return(ast_say_enumeration_full_de(chan, num, ints, language, options, audiofd, ctrlfd));
- } else if (!strcasecmp(language, "he")) { /* Hebrew syntax */
- return (ast_say_enumeration_full_he(chan, num, ints, language, options, audiofd, ctrlfd));
- }
-
- /* Default to english */
- return(ast_say_enumeration_full_en(chan, num, ints, language, audiofd, ctrlfd));
-}
-
-/*! \brief ast_say_enumeration_full_en: English syntax */
-/* This is the default syntax, if no other syntax defined in this file is used */
-static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
-{
- int res = 0, t = 0;
- char fn[256] = "";
-
- while (!res && num) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus"); /* kind of senseless for enumerations, but our best effort for error checking */
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/h-%d", num);
- num = 0;
- } else if (num < 100) {
- int tens = num / 10;
- num = num % 10;
- if (num == 0) {
- snprintf(fn, sizeof(fn), "digits/h-%d", (tens * 10));
- } else {
- snprintf(fn, sizeof(fn), "digits/%d", (tens * 10));
- }
- } else if (num < 1000) {
- int hundreds = num / 100;
- num = num % 100;
- if (hundreds > 1 || t == 1) {
- res = ast_say_number_full_en(chan, hundreds, ints, language, audiofd, ctrlfd);
- }
- if (res)
- return res;
- if (num) {
- snprintf(fn, sizeof(fn), "digits/hundred");
- } else {
- snprintf(fn, sizeof(fn), "digits/h-hundred");
- }
- } else if (num < 1000000) {
- int thousands = num / 1000;
- num = num % 1000;
- if (thousands > 1 || t == 1) {
- res = ast_say_number_full_en(chan, thousands, ints, language, audiofd, ctrlfd);
- }
- if (res)
- return res;
- if (num) {
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else {
- snprintf(fn, sizeof(fn), "digits/h-thousand");
- }
- t = 1;
- } else if (num < 1000000000) {
- int millions = num / 1000000;
- num = num % 1000000;
- t = 1;
- res = ast_say_number_full_en(chan, millions, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- if (num) {
- snprintf(fn, sizeof(fn), "digits/million");
- } else {
- snprintf(fn, sizeof(fn), "digits/h-million");
- }
- } else if (num < INT_MAX) {
- int billions = num / 1000000000;
- num = num % 1000000000;
- t = 1;
- res = ast_say_number_full_en(chan, billions, ints, language, audiofd, ctrlfd);
- if (res)
- return res;
- if (num) {
- snprintf(fn, sizeof(fn), "digits/billion");
- } else {
- snprintf(fn, sizeof(fn), "digits/h-billion");
- }
- } else if (num == INT_MAX) {
- snprintf(fn, sizeof(fn), "digits/h-last");
- num = 0;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
-
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1)) {
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- } else {
- res = ast_waitstream(chan, ints);
- }
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-/*! \brief ast_say_enumeration_full_da: Danish syntax */
-static int ast_say_enumeration_full_da(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- /* options can be: '' or 'm' male gender; 'f' female gender; 'n' neuter gender; 'p' plural */
- int res = 0, t = 0;
- char fn[256] = "", fna[256] = "";
- char *gender;
-
- if (options && !strncasecmp(options, "f",1)) {
- gender = "F";
- } else if (options && !strncasecmp(options, "n",1)) {
- gender = "N";
- } else {
- gender = "";
- }
-
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- while (!res && num) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus"); /* kind of senseless for enumerations, but our best effort for error checking */
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (num < 100 && t) {
- snprintf(fn, sizeof(fn), "digits/and");
- t = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
- num = 0;
- } else if (num < 100) {
- int ones = num % 10;
- if (ones) {
- snprintf(fn, sizeof(fn), "digits/%d-and", ones);
- num -= ones;
- } else {
- snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
- num = 0;
- }
- } else if (num == 100 && t == 0) {
- snprintf(fn, sizeof(fn), "digits/h-hundred%s", gender);
- num = 0;
- } else if (num < 1000) {
- int hundreds = num / 100;
- num = num % 100;
- if (hundreds == 1) {
- snprintf(fn, sizeof(fn), "digits/1N");
- } else {
- snprintf(fn, sizeof(fn), "digits/%d", hundreds);
- }
- if (num) {
- snprintf(fna, sizeof(fna), "digits/hundred");
- } else {
- snprintf(fna, sizeof(fna), "digits/h-hundred%s", gender);
- }
- t = 1;
- } else if (num < 1000000) {
- int thousands = num / 1000;
- num = num % 1000;
- if (thousands == 1) {
- if (num) {
- snprintf(fn, sizeof(fn), "digits/1N");
- snprintf(fna, sizeof(fna), "digits/thousand");
- } else {
- if (t) {
- snprintf(fn, sizeof(fn), "digits/1N");
- snprintf(fna, sizeof(fna), "digits/h-thousand%s", gender);
- } else {
- snprintf(fn, sizeof(fn), "digits/h-thousand%s", gender);
- }
- }
- } else {
- res = ast_say_number_full_de(chan, thousands, ints, language, options, audiofd, ctrlfd);
- if (res) {
- return res;
- }
- if (num) {
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else {
- snprintf(fn, sizeof(fn), "digits/h-thousand%s", gender);
- }
- }
- t = 1;
- } else if (num < 1000000000) {
- int millions = num / 1000000;
- num = num % 1000000;
- if (millions == 1) {
- if (num) {
- snprintf(fn, sizeof(fn), "digits/1F");
- snprintf(fna, sizeof(fna), "digits/million");
- } else {
- snprintf(fn, sizeof(fn), "digits/1N");
- snprintf(fna, sizeof(fna), "digits/h-million%s", gender);
- }
- } else {
- res = ast_say_number_full_de(chan, millions, ints, language, options, audiofd, ctrlfd);
- if (res) {
- return res;
- }
- if (num) {
- snprintf(fn, sizeof(fn), "digits/millions");
- } else {
- snprintf(fn, sizeof(fn), "digits/h-million%s", gender);
- }
- }
- t = 1;
- } else if (num < INT_MAX) {
- int billions = num / 1000000000;
- num = num % 1000000000;
- if (billions == 1) {
- if (num) {
- snprintf(fn, sizeof(fn), "digits/1F");
- snprintf(fna, sizeof(fna), "digits/milliard");
- } else {
- snprintf(fn, sizeof(fn), "digits/1N");
- snprintf(fna, sizeof(fna), "digits/h-milliard%s", gender);
- }
- } else {
- res = ast_say_number_full_de(chan, billions, ints, language, options, audiofd, ctrlfd);
- if (res)
- return res;
- if (num) {
- snprintf(fn, sizeof(fna), "digits/milliards");
- } else {
- snprintf(fn, sizeof(fna), "digits/h-milliard%s", gender);
- }
- }
- t = 1;
- } else if (num == INT_MAX) {
- snprintf(fn, sizeof(fn), "digits/h-last%s", gender);
- num = 0;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
-
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- if (!res) {
- if (strlen(fna) != 0 && !ast_streamfile(chan, fna, language)) {
- if ((audiofd > -1) && (ctrlfd > -1)) {
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- } else {
- res = ast_waitstream(chan, ints);
- }
- }
- ast_stopstream(chan);
- strcpy(fna, "");
- }
- }
- }
- return res;
-}
-
-/*! \brief ast_say_enumeration_full_de: German syntax */
-static int ast_say_enumeration_full_de(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- /* options can be: '' or 'm' male gender; 'f' female gender; 'n' neuter gender; 'p' plural */
- int res = 0, t = 0;
- char fn[256] = "", fna[256] = "";
- char *gender;
-
- if (options && !strncasecmp(options, "f",1)) {
- gender = "F";
- } else if (options && !strncasecmp(options, "n",1)) {
- gender = "N";
- } else {
- gender = "";
- }
-
- if (!num)
- return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
-
- while (!res && num) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus"); /* kind of senseless for enumerations, but our best effort for error checking */
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (num < 100 && t) {
- snprintf(fn, sizeof(fn), "digits/and");
- t = 0;
- } else if (num < 20) {
- snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
- num = 0;
- } else if (num < 100) {
- int ones = num % 10;
- if (ones) {
- snprintf(fn, sizeof(fn), "digits/%d-and", ones);
- num -= ones;
- } else {
- snprintf(fn, sizeof(fn), "digits/h-%d%s", num, gender);
- num = 0;
- }
- } else if (num == 100 && t == 0) {
- snprintf(fn, sizeof(fn), "digits/h-hundred%s", gender);
- num = 0;
- } else if (num < 1000) {
- int hundreds = num / 100;
- num = num % 100;
- if (hundreds == 1) {
- snprintf(fn, sizeof(fn), "digits/1N");
- } else {
- snprintf(fn, sizeof(fn), "digits/%d", hundreds);
- }
- if (num) {
- snprintf(fna, sizeof(fna), "digits/hundred");
- } else {
- snprintf(fna, sizeof(fna), "digits/h-hundred%s", gender);
- }
- t = 1;
- } else if (num < 1000000) {
- int thousands = num / 1000;
- num = num % 1000;
- if (thousands == 1) {
- if (num) {
- snprintf(fn, sizeof(fn), "digits/1N");
- snprintf(fna, sizeof(fna), "digits/thousand");
- } else {
- if (t) {
- snprintf(fn, sizeof(fn), "digits/1N");
- snprintf(fna, sizeof(fna), "digits/h-thousand%s", gender);
- } else {
- snprintf(fn, sizeof(fn), "digits/h-thousand%s", gender);
- }
- }
- } else {
- res = ast_say_number_full_de(chan, thousands, ints, language, options, audiofd, ctrlfd);
- if (res) {
- return res;
- }
- if (num) {
- snprintf(fn, sizeof(fn), "digits/thousand");
- } else {
- snprintf(fn, sizeof(fn), "digits/h-thousand%s", gender);
- }
- }
- t = 1;
- } else if (num < 1000000000) {
- int millions = num / 1000000;
- num = num % 1000000;
- if (millions == 1) {
- if (num) {
- snprintf(fn, sizeof(fn), "digits/1F");
- snprintf(fna, sizeof(fna), "digits/million");
- } else {
- snprintf(fn, sizeof(fn), "digits/1N");
- snprintf(fna, sizeof(fna), "digits/h-million%s", gender);
- }
- } else {
- res = ast_say_number_full_de(chan, millions, ints, language, options, audiofd, ctrlfd);
- if (res) {
- return res;
- }
- if (num) {
- snprintf(fn, sizeof(fn), "digits/millions");
- } else {
- snprintf(fn, sizeof(fn), "digits/h-million%s", gender);
- }
- }
- t = 1;
- } else if (num < INT_MAX) {
- int billions = num / 1000000000;
- num = num % 1000000000;
- if (billions == 1) {
- if (num) {
- snprintf(fn, sizeof(fn), "digits/1F");
- snprintf(fna, sizeof(fna), "digits/milliard");
- } else {
- snprintf(fn, sizeof(fn), "digits/1N");
- snprintf(fna, sizeof(fna), "digits/h-milliard%s", gender);
- }
- } else {
- res = ast_say_number_full_de(chan, billions, ints, language, options, audiofd, ctrlfd);
- if (res)
- return res;
- if (num) {
- snprintf(fn, sizeof(fna), "digits/milliards");
- } else {
- snprintf(fn, sizeof(fna), "digits/h-milliard%s", gender);
- }
- }
- t = 1;
- } else if (num == INT_MAX) {
- snprintf(fn, sizeof(fn), "digits/h-last%s", gender);
- num = 0;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
-
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- if (!res) {
- if (strlen(fna) != 0 && !ast_streamfile(chan, fna, language)) {
- if ((audiofd > -1) && (ctrlfd > -1)) {
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- } else {
- res = ast_waitstream(chan, ints);
- }
- }
- ast_stopstream(chan);
- strcpy(fna, "");
- }
- }
- }
- return res;
-}
-
-static int ast_say_enumeration_full_he(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- char fn[256] = "";
- int mf = -1; /* +1 = Masculin; -1 = Feminin */
- ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: started. num: %d, options=\"%s\"\n", num, options);
-
- if (options && !strncasecmp(options, "m", 1)) {
- mf = -1;
- }
-
- ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, options=\"%s\", mf=%d\n", num, options, mf);
-
- while (!res && num) {
- if (num < 0) {
- snprintf(fn, sizeof(fn), "digits/minus"); /* kind of senseless for enumerations, but our best effort for error checking */
- if (num > INT_MIN) {
- num = -num;
- } else {
- num = 0;
- }
- } else if (num < 21) {
- if (mf < 0) {
- if (num < 10) {
- snprintf(fn, sizeof(fn), "digits/f-0%d", num);
- } else {
- snprintf(fn, sizeof(fn), "digits/f-%d", num);
- }
- } else {
- if (num < 10) {
- snprintf(fn, sizeof(fn), "digits/m-0%d", num);
- } else {
- snprintf(fn, sizeof(fn), "digits/m-%d", num);
- }
- }
- num = 0;
- } else if ((num < 100) && num >= 20) {
- snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10);
- num = num % 10;
- } else if ((num >= 100) && (num < 1000)) {
- int tmpnum = num / 100;
- snprintf(fn, sizeof(fn), "digits/%d00", tmpnum);
- num = num - (tmpnum * 100);
- } else if ((num >= 1000) && (num < 10000)) {
- int tmpnum = num / 1000;
- snprintf(fn, sizeof(fn), "digits/%dk", tmpnum);
- num = num - (tmpnum * 1000);
- } else if (num < 20000) {
- snprintf(fn, sizeof(fn), "digits/m-%d", (num / 1000));
- num = num % 1000;
- } else if (num < 1000000) {
- res = ast_say_number_full_he(chan, num / 1000, ints, language, "m", audiofd, ctrlfd);
- if (res) {
- return res;
- }
- snprintf(fn, sizeof(fn), "digits/1k");
- num = num % 1000;
- } else if (num < 2000000) {
- snprintf(fn, sizeof(fn), "digits/1m");
- num = num % 1000000;
- } else if (num < 3000000) {
- snprintf(fn, sizeof(fn), "digits/2m");
- num = num - 2000000;
- } else if (num < 1000000000) {
- res = ast_say_number_full_he(chan, num / 1000000, ints, language, "m", audiofd, ctrlfd);
- if (res) {
- return res;
- }
- snprintf(fn, sizeof(fn), "digits/1m");
- num = num % 1000000;
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1)) {
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- } else {
- res = ast_waitstream(chan, ints);
- }
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-static int say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- if (!strcasecmp(lang, "en") ) { /* English syntax */
- return(ast_say_date_en(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "da") ) { /* Danish syntax */
- return(ast_say_date_da(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "de") ) { /* German syntax */
- return(ast_say_date_de(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "fr") ) { /* French syntax */
- return(ast_say_date_fr(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "nl") ) { /* Dutch syntax */
- return(ast_say_date_nl(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) { /* Portuguese syntax */
- return(ast_say_date_pt(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "gr") ) { /* Greek syntax */
- return(ast_say_date_gr(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "ge") ) { /* Georgian syntax */
- return(ast_say_date_ge(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "he")) { /* Hebrew syntax */
- return (ast_say_date_he(chan, t, ints, lang));
- }
-
- /* Default to English */
- return(ast_say_date_en(chan, t, ints, lang));
-}
-
-/* English syntax */
-int ast_say_date_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- ast_localtime(&t,&tm,NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- return res;
-}
-
-/* Danish syntax */
-int ast_say_date_da(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- ast_localtime(&t,&tm,NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, (char * ) NULL);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- /* Year */
- int year = tm.tm_year + 1900;
- if (year > 1999) { /* year 2000 and later */
- res = ast_say_number(chan, year, ints, lang, (char *) NULL);
- } else {
- if (year < 1100) {
- /* I'm not going to handle 1100 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- } else {
- /* year 1100 to 1999. will anybody need this?!? */
- snprintf(fn,sizeof(fn), "digits/%d", (year / 100) );
- res = wait_file(chan, ints, fn, lang);
- if (!res) {
- res = wait_file(chan,ints, "digits/hundred", lang);
- if (!res && year % 100 != 0) {
- res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
- }
- }
- }
- }
- }
- return res;
-}
-
-/* German syntax */
-int ast_say_date_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- ast_localtime(&t,&tm,NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, (char * ) NULL);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- /* Year */
- int year = tm.tm_year + 1900;
- if (year > 1999) { /* year 2000 and later */
- res = ast_say_number(chan, year, ints, lang, (char *) NULL);
- } else {
- if (year < 1100) {
- /* I'm not going to handle 1100 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- } else {
- /* year 1100 to 1999. will anybody need this?!? */
- /* say 1967 as 'neunzehn hundert sieben und sechzig' */
- snprintf(fn,sizeof(fn), "digits/%d", (year / 100) );
- res = wait_file(chan, ints, fn, lang);
- if (!res) {
- res = wait_file(chan,ints, "digits/hundred", lang);
- if (!res && year % 100 != 0) {
- res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
- }
- }
- }
- }
- }
- return res;
-}
-
-/* French syntax */
-int ast_say_date_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- ast_localtime(&t,&tm,NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- return res;
-}
-
-/* Dutch syntax */
-int ast_say_date_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- ast_localtime(&t,&tm,NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- return res;
-}
-
-/* Portuguese syntax */
-int ast_say_date_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- if (!res)
- res = wait_file(chan, ints, fn, lang);
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
- if (!res)
- res = wait_file(chan, ints, "digits/pt-de", lang);
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- if (!res)
- res = wait_file(chan, ints, fn, lang);
- if (!res)
- res = wait_file(chan, ints, "digits/pt-de", lang);
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
-
- return res;
-}
-
-/* Hebrew syntax */
-int ast_say_date_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- ast_localtime(&t, &tm, NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- res = ast_waitstream(chan, ints);
- }
- }
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- res = ast_waitstream(chan, ints);
- }
- }
- if (!res) {
- res = ast_say_number(chan, tm.tm_mday, ints, lang, "m");
- }
- if (!res) {
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, "m");
- }
- return res;
-}
-
-static int say_date_with_format(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- if (!strcasecmp(lang, "en") ) { /* English syntax */
- return(ast_say_date_with_format_en(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "da") ) { /* Danish syntax */
- return(ast_say_date_with_format_da(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "de") ) { /* German syntax */
- return(ast_say_date_with_format_de(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "es") || !strcasecmp(lang, "mx")) { /* Spanish syntax */
- return (ast_say_date_with_format_es(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "he")) { /* Hebrew syntax */
- return (ast_say_date_with_format_he(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "fr")) { /* French syntax */
- return (ast_say_date_with_format_fr(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "it")) { /* Italian syntax */
- return (ast_say_date_with_format_it(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "nl")) { /* Dutch syntax */
- return (ast_say_date_with_format_nl(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "pl")) { /* Polish syntax */
- return (ast_say_date_with_format_pl(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) { /* Portuguese syntax */
- return(ast_say_date_with_format_pt(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "tw") || !strcasecmp(lang, "zh") ) { /* Taiwanese / Chinese syntax */
- return(ast_say_date_with_format_tw(chan, time, ints, lang, format, timezone));
- } else if (!strcasecmp(lang, "gr") ) { /* Greek syntax */
- return(ast_say_date_with_format_gr(chan, time, ints, lang, format, timezone));
- }
-
- /* Default to English */
- return(ast_say_date_with_format_en(chan, time, ints, lang, format, timezone));
-}
-
-/* English syntax */
-int ast_say_date_with_format_en(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (format == NULL)
- format = "ABdY 'digits/at' IMp";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan,ints,sndfile,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'm':
- /* Month enumerated */
- res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, (char *) NULL);
- break;
- case 'd':
- case 'e':
- /* First - Thirtyfirst */
- res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, (char *) NULL);
- break;
- case 'Y':
- /* Year */
- if (tm.tm_year > 99) {
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- } else if (tm.tm_year < 1) {
- /* I'm not going to handle 1900 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- } else {
- res = wait_file(chan, ints, "digits/19", lang);
- if (!res) {
- if (tm.tm_year <= 9) {
- /* 1901 - 1909 */
- res = wait_file(chan,ints, "digits/oh", lang);
- }
-
- res |= ast_say_number(chan, tm.tm_year, ints, lang, (char *) NULL);
- }
- }
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (tm.tm_hour == 0)
- snprintf(nextmsg,sizeof(nextmsg), "digits/12");
- else if (tm.tm_hour > 12)
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'H':
- case 'k':
- /* 24-Hour */
- if (format[offset] == 'H') {
- /* e.g. oh-eight */
- if (tm.tm_hour < 10) {
- res = wait_file(chan,ints, "digits/oh",lang);
- }
- } else {
- /* e.g. eight */
- if (tm.tm_hour == 0) {
- res = wait_file(chan,ints, "digits/oh",lang);
- }
- }
- if (!res) {
- if (tm.tm_hour != 0) {
- int remainder = tm.tm_hour;
- if (tm.tm_hour > 20) {
- res = wait_file(chan,ints, "digits/20",lang);
- remainder -= 20;
- }
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", remainder);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- }
- break;
- case 'M':
- case 'N':
- /* Minute */
- if (tm.tm_min == 0) {
- if (format[offset] == 'M') {
- res = wait_file(chan, ints, "digits/oclock", lang);
- } else {
- res = wait_file(chan, ints, "digits/hundred", lang);
- }
- } else if (tm.tm_min < 10) {
- res = wait_file(chan,ints, "digits/oh",lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_min);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- } else {
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- }
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 11)
- snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_en(chan, time, ints, lang, "A", timezone);
- } else if (beg_today - 2628000 < time) {
- /* Less than a month ago - "Sunday, October third" */
- res = ast_say_date_with_format_en(chan, time, ints, lang, "ABd", timezone);
- } else if (beg_today - 15768000 < time) {
- /* Less than 6 months ago - "August seventh" */
- res = ast_say_date_with_format_en(chan, time, ints, lang, "Bd", timezone);
- } else {
- /* More than 6 months ago - "April nineteenth two thousand three" */
- res = ast_say_date_with_format_en(chan, time, ints, lang, "BdY", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_en(chan, time, ints, lang, "A", timezone);
- } else if (beg_today - 2628000 < time) {
- /* Less than a month ago - "Sunday, October third" */
- res = ast_say_date_with_format_en(chan, time, ints, lang, "ABd", timezone);
- } else if (beg_today - 15768000 < time) {
- /* Less than 6 months ago - "August seventh" */
- res = ast_say_date_with_format_en(chan, time, ints, lang, "Bd", timezone);
- } else {
- /* More than 6 months ago - "April nineteenth two thousand three" */
- res = ast_say_date_with_format_en(chan, time, ints, lang, "BdY", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_en(chan, time, ints, lang, "HM", timezone);
- break;
- case 'S':
- /* Seconds */
- if (tm.tm_sec == 0) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- } else if (tm.tm_sec < 10) {
- res = wait_file(chan,ints, "digits/oh",lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- } else {
- res = ast_say_number(chan, tm.tm_sec, ints, lang, (char *) NULL);
- }
- break;
- case 'T':
- res = ast_say_date_with_format_en(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-/* Danish syntax */
-int ast_say_date_with_format_da(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (!format)
- format = "A dBY HMS";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan,ints,sndfile,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'm':
- /* Month enumerated */
- res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, "m");
- break;
- case 'd':
- case 'e':
- /* First - Thirtyfirst */
- res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, "m");
- break;
- case 'Y':
- /* Year */
- {
- int year = tm.tm_year + 1900;
- if (year > 1999) { /* year 2000 and later */
- res = ast_say_number(chan, year, ints, lang, (char *) NULL);
- } else {
- if (year < 1100) {
- /* I'm not going to handle 1100 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- } else {
- /* year 1100 to 1999. will anybody need this?!? */
- /* say 1967 as 'nineteen hundred seven and sixty' */
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", (year / 100) );
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- res = wait_file(chan,ints, "digits/hundred",lang);
- if (!res && year % 100 != 0) {
- res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
- }
- }
- }
- }
- }
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- res = wait_file(chan,ints,"digits/oclock",lang);
- if (tm.tm_hour == 0)
- snprintf(nextmsg,sizeof(nextmsg), "digits/12");
- else if (tm.tm_hour > 12)
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
- if (!res) {
- res = wait_file(chan,ints,nextmsg,lang);
- }
- break;
- case 'H':
- /* 24-Hour, single digit hours preceeded by "oh" (0) */
- if (tm.tm_hour < 10 && tm.tm_hour > 0) {
- res = wait_file(chan,ints, "digits/0",lang);
- }
- /* FALLTRHU */
- case 'k':
- /* 24-Hour */
- res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
- break;
- case 'M':
- /* Minute */
- if (tm.tm_min > 0 || format[offset+ 1 ] == 'S' ) { /* zero 'digits/0' only if seconds follow (kind of a hack) */
- res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
- }
- if ( !res && format[offset + 1] == 'S' ) { /* minutes only if seconds follow (kind of a hack) */
- if (tm.tm_min == 1) {
- res = wait_file(chan,ints,"digits/minute",lang);
- } else {
- res = wait_file(chan,ints,"digits/minutes",lang);
- }
- }
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 11)
- snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or AdBY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else {
- res = ast_say_date_with_format_da(chan, time, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_da(chan, time, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format_da(chan, time, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_da(chan, time, ints, lang, "HM", timezone);
- break;
- case 'S':
- /* Seconds */
- res = wait_file(chan,ints, "digits/and",lang);
- if (!res) {
- res = ast_say_number(chan, tm.tm_sec, ints, lang, "f");
- if (!res) {
- res = wait_file(chan,ints, "digits/seconds",lang);
- }
- }
- break;
- case 'T':
- res = ast_say_date_with_format_da(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-/* German syntax */
-int ast_say_date_with_format_de(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (!format)
- format = "A dBY HMS";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan,ints,sndfile,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'm':
- /* Month enumerated */
- res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, "m");
- break;
- case 'd':
- case 'e':
- /* First - Thirtyfirst */
- res = ast_say_enumeration(chan, tm.tm_mday, ints, lang, "m");
- break;
- case 'Y':
- /* Year */
- {
- int year = tm.tm_year + 1900;
- if (year > 1999) { /* year 2000 and later */
- res = ast_say_number(chan, year, ints, lang, (char *) NULL);
- } else {
- if (year < 1100) {
- /* I'm not going to handle 1100 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- } else {
- /* year 1100 to 1999. will anybody need this?!? */
- /* say 1967 as 'neunzehn hundert sieben und sechzig' */
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", (year / 100) );
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- res = wait_file(chan,ints, "digits/hundred",lang);
- if (!res && year % 100 != 0) {
- res = ast_say_number(chan, (year % 100), ints, lang, (char *) NULL);
- }
- }
- }
- }
- }
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (tm.tm_hour == 0)
- snprintf(nextmsg,sizeof(nextmsg), "digits/12");
- else if (tm.tm_hour > 12)
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- res = wait_file(chan,ints,"digits/oclock",lang);
- }
- break;
- case 'H':
- case 'k':
- /* 24-Hour */
- res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
- if (!res) {
- res = wait_file(chan,ints,"digits/oclock",lang);
- }
- break;
- case 'M':
- /* Minute */
- if (tm.tm_min > 0 || format[offset+ 1 ] == 'S' ) { /* zero 'digits/0' only if seconds follow (kind of a hack) */
- res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
- }
- if ( !res && format[offset + 1] == 'S' ) { /* minutes only if seconds follow (kind of a hack) */
- if (tm.tm_min == 1) {
- res = wait_file(chan,ints,"digits/minute",lang);
- } else {
- res = wait_file(chan,ints,"digits/minutes",lang);
- }
- }
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 11)
- snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or AdBY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else {
- res = ast_say_date_with_format_de(chan, time, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_de(chan, time, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format_de(chan, time, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_de(chan, time, ints, lang, "HM", timezone);
- break;
- case 'S':
- /* Seconds */
- res = wait_file(chan,ints, "digits/and",lang);
- if (!res) {
- res = ast_say_number(chan, tm.tm_sec, ints, lang, "f");
- if (!res) {
- res = wait_file(chan,ints, "digits/seconds",lang);
- }
- }
- break;
- case 'T':
- res = ast_say_date_with_format_de(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-/* TODO: this probably is not the correct format for doxygen remarks */
-
-/** ast_say_date_with_format_he Say formmated date in Hebrew
- *
- * \ref ast_say_date_with_format_en for the details of the options
- *
- * Changes from the English version:
- *
- * * don't replicate in here the logic of ast_say_number_full_he
- *
- * * year is always 4-digit (because it's simpler)
- *
- * * added c, x, and X. Mainly for my tests
- *
- * * The standard "long" format used in Hebrew is AdBY, rather than ABdY
- *
- * TODO:
- * * A "ha" is missing in the standard date format, before the 'd'.
- * * The numbers of 3000--19000 are not handled well
- **/
-#define IL_DATE_STR "AdBY"
-#define IL_TIME_STR "HM" /* NOTE: In Hebrew we do not support 12 hours, only 24. No AM or PM exists in the Hebrew language */
-#define IL_DATE_STR_FULL IL_DATE_STR " 'digits/at' " IL_TIME_STR
-int ast_say_date_with_format_he(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- /* TODO: This whole function is cut&paste from
- * ast_say_date_with_format_en . Is that considered acceptable?
- **/
- struct tm tm;
- int res = 0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (!format) {
- format = IL_DATE_STR_FULL;
- }
-
- ast_localtime(&time, &tm, timezone);
-
- for (offset = 0; format[offset] != '\0'; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan,ints,sndfile,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'd':
- case 'e': /* Day of the month */
- /* I'm not sure exactly what the parameters
- * audiofd and ctrlfd to
- * ast_say_number_full_he mean, but it seems
- * safe to pass -1 there.
- *
- * At least in one of the pathes :-(
- */
- res = ast_say_number_full_he(chan, tm.tm_mday, ints, lang, "m", -1, -1);
- break;
- case 'Y': /* Year */
- res = ast_say_number_full_he(chan, tm.tm_year+1900,
- ints, lang, "f", -1, -1
- );
- break;
- case 'I':
- case 'l': /* 12-Hour -> we do not support 12 hour based langauges in Hebrew */
- case 'H':
- case 'k': /* 24-Hour */
- res = ast_say_number_full_he(chan, tm.tm_hour, ints, lang, "f", -1, -1);
- break;
- case 'M': /* Minute */
- if (tm.tm_min >= 0 && tm.tm_min <= 9) /* say a leading zero if needed */
- res = ast_say_number_full_he(chan, 0, ints, lang, "f", -1, -1);
- res = ast_say_number_full_he(chan, tm.tm_min, ints, lang, "f", -1, -1);
- break;
- case 'P':
- case 'p':
- /* AM/PM - There is no AM/PM in Hebrew... */
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or "date" */
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A
- * (weekday), or "date" */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
- char todo = format[offset]; /* The letter to format*/
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- if (todo == 'Q') {
- res = wait_file(chan,
- ints,
- "digits/today",
- lang);
- }
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if ((todo != 'Q') &&
- (beg_today - 86400 * 6 < time))
- {
- /* Within the last week */
- res = ast_say_date_with_format_he(chan,
- time, ints, lang,
- "A", timezone);
- } else {
- res = ast_say_date_with_format_he(chan,
- time, ints, lang,
- IL_DATE_STR, timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_he(chan, time, ints, lang, "HM", timezone);
- break;
- case 'S': /* Seconds */
- res = ast_say_number_full_he(chan, tm.tm_sec,
- ints, lang, "f", -1, -1
- );
- break;
- case 'T':
- res = ast_say_date_with_format_he(chan, time, ints, lang, "HMS", timezone);
- break;
- /* c, x, and X seem useful for testing. Not sure
- * if thiey're good for the general public */
- case 'c':
- res = ast_say_date_with_format_he(chan, time,
- ints, lang, IL_DATE_STR_FULL, timezone);
- break;
- case 'x':
- res = ast_say_date_with_format_he(chan, time,
- ints, lang, IL_DATE_STR, timezone);
- break;
- case 'X': /* Currently not locale-dependent...*/
- res = ast_say_date_with_format_he(chan, time,
- ints, lang, IL_TIME_STR, timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-
-/* Spanish syntax */
-int ast_say_date_with_format_es(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (format == NULL)
- format = "'digits/es-el' Ad 'digits/es-de' B 'digits/es-de' Y 'digits/at' IMp";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- snprintf(nextmsg,sizeof(nextmsg), "%s", sndfile);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'm':
- /* First - Twelfth */
- snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'd':
- case 'e':
- /* First - Thirtyfirst */
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
- break;
- case 'Y':
- /* Year */
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (tm.tm_hour == 0)
- snprintf(nextmsg,sizeof(nextmsg), "digits/12");
- else if (tm.tm_hour > 12)
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'H':
- case 'k':
- /* 24-Hour */
- res = ast_say_number(chan, tm.tm_hour, ints, lang, NULL);
- break;
- case 'M':
- /* Minute */
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 18)
- res = wait_file(chan, ints, "digits/p-m", lang);
- else if (tm.tm_hour > 12)
- res = wait_file(chan, ints, "digits/afternoon", lang);
- else if (tm.tm_hour)
- res = wait_file(chan, ints, "digits/a-m", lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else {
- res = ast_say_date_with_format_es(chan, time, ints, lang, "'digits/es-el' Ad 'digits/es-de' B 'digits/es-de' Y", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_es(chan, time, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format_es(chan, time, ints, lang, "'digits/es-el' Ad 'digits/es-de' B 'digits/es-de' Y", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_es(chan, time, ints, lang, "H 'digits/y' M", timezone);
- break;
- case 'S':
- /* Seconds */
- if (tm.tm_sec == 0) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- } else if (tm.tm_sec < 10) {
- res = wait_file(chan,ints, "digits/oh",lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- int ten, one;
- ten = (tm.tm_sec / 10) * 10;
- one = (tm.tm_sec % 10);
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- /* Fifty, not fifty-zero */
- if (one != 0) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- }
- break;
- case 'T':
- res = ast_say_date_with_format_es(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-/* French syntax
-oclock = heure
-*/
-int ast_say_date_with_format_fr(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (format == NULL)
- format = "AdBY 'digits/at' IMp";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan,ints,sndfile,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'm':
- /* First - Twelfth */
- snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'd':
- case 'e':
- /* First */
- if (tm.tm_mday == 1) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mday);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
- }
- break;
- case 'Y':
- /* Year */
- if (tm.tm_year > 99) {
- res = wait_file(chan,ints, "digits/2",lang);
- if (!res) {
- res = wait_file(chan,ints, "digits/thousand",lang);
- }
- if (tm.tm_year > 100) {
- if (!res) {
- res = ast_say_number(chan, tm.tm_year - 100, ints, lang, (char * ) NULL);
- }
- }
- } else {
- if (tm.tm_year < 1) {
- /* I'm not going to handle 1900 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- } else {
- res = wait_file(chan,ints, "digits/thousand",lang);
- if (!res) {
- wait_file(chan,ints, "digits/9",lang);
- wait_file(chan,ints, "digits/hundred",lang);
- res = ast_say_number(chan, tm.tm_year, ints, lang, (char * ) NULL);
- }
- }
- }
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (tm.tm_hour == 0)
- snprintf(nextmsg,sizeof(nextmsg), "digits/12");
- else if (tm.tm_hour > 12)
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res)
- res = wait_file(chan,ints, "digits/oclock",lang);
- break;
- case 'H':
- case 'k':
- /* 24-Hour */
- res = ast_say_number(chan, tm.tm_hour, ints, lang, (char * ) NULL);
- if (!res)
- res = wait_file(chan,ints, "digits/oclock",lang);
- break;
- case 'M':
- /* Minute */
- if (tm.tm_min == 0) {
- break;
- }
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char * ) NULL);
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 11)
- snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or AdBY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else {
- res = ast_say_date_with_format_fr(chan, time, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_fr(chan, time, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format_fr(chan, time, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_fr(chan, time, ints, lang, "HM", timezone);
- break;
- case 'S':
- /* Seconds */
- res = ast_say_number(chan, tm.tm_sec, ints, lang, (char * ) NULL);
- if (!res) {
- res = wait_file(chan,ints, "digits/second",lang);
- }
- break;
- case 'T':
- res = ast_say_date_with_format_fr(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-int ast_say_date_with_format_it(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (format == NULL)
- format = "AdB 'digits/at' IMp";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan,ints,sndfile,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'm':
- /* First - Twelfth */
- snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'd':
- case 'e':
- /* First day of the month is spelled as ordinal */
- if (tm.tm_mday == 1) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mday);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- if (!res) {
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
- }
- }
- break;
- case 'Y':
- /* Year */
- if (tm.tm_year > 99) {
- res = wait_file(chan,ints, "digits/ore-2000",lang);
- if (tm.tm_year > 100) {
- if (!res) {
- /* This works until the end of 2021 */
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year - 100);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- } else {
- if (tm.tm_year < 1) {
- /* I'm not going to handle 1900 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- } else {
- res = wait_file(chan,ints, "digits/ore-1900",lang);
- if ((!res) && (tm.tm_year != 0)) {
- if (tm.tm_year <= 21) {
- /* 1910 - 1921 */
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- /* 1922 - 1999, but sounds badly in 1928, 1931, 1938, etc... */
- int ten, one;
- ten = tm.tm_year / 10;
- one = tm.tm_year % 10;
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten * 10);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- if (one != 0) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- }
- }
- }
- }
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (tm.tm_hour == 0)
- snprintf(nextmsg,sizeof(nextmsg), "digits/12");
- else if (tm.tm_hour > 12)
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'H':
- case 'k':
- /* 24-Hour */
- if (tm.tm_hour == 0) {
- res = wait_file(chan,ints, "digits/ore-mezzanotte",lang);
- } else if (tm.tm_hour == 1) {
- res = wait_file(chan,ints, "digits/ore-una",lang);
- } else {
- res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
- }
- break;
- case 'M':
- /* Minute */
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 11)
- snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else {
- res = ast_say_date_with_format_it(chan, time, ints, lang, "AdB", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_it(chan, time, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format_it(chan, time, ints, lang, "AdB", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_it(chan, time, ints, lang, "HM", timezone);
- break;
- case 'S':
- /* Seconds */
- if (tm.tm_sec == 0) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- } else if (tm.tm_sec < 10) {
- res = wait_file(chan,ints, "digits/oh",lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- int ten, one;
- ten = (tm.tm_sec / 10) * 10;
- one = (tm.tm_sec % 10);
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- /* Fifty, not fifty-zero */
- if (one != 0) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- }
- break;
- case 'T':
- res = ast_say_date_with_format_it(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-/* Dutch syntax */
-int ast_say_date_with_format_nl(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (format == NULL)
- format = "ABdY 'digits/at' IMp";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan,ints,sndfile,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'm':
- /* First - Twelfth */
- snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'd':
- case 'e':
- /* First - Thirtyfirst */
- res = ast_say_number(chan, tm.tm_mday, ints, lang, NULL);
- break;
- case 'Y':
- /* Year */
- if (tm.tm_year > 99) {
- res = wait_file(chan,ints, "digits/2",lang);
- if (!res) {
- res = wait_file(chan,ints, "digits/thousand",lang);
- }
- if (tm.tm_year > 100) {
- if (!res) {
- /* This works until the end of 2020 */
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year - 100);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- } else {
- if (tm.tm_year < 1) {
- /* I'm not going to handle 1900 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- } else {
- res = wait_file(chan,ints, "digits/19",lang);
- if (!res) {
- if (tm.tm_year <= 9) {
- /* 1901 - 1909 */
- res = wait_file(chan,ints, "digits/oh",lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- } else if (tm.tm_year <= 20) {
- /* 1910 - 1920 */
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- /* 1921 - 1999 */
- int ten, one;
- ten = tm.tm_year / 10;
- one = tm.tm_year % 10;
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten * 10);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- if (one != 0) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- }
- }
- }
- }
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (tm.tm_hour == 0)
- snprintf(nextmsg,sizeof(nextmsg), "digits/12");
- else if (tm.tm_hour > 12)
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'H':
- case 'k':
- /* 24-Hour */
- res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
- if (!res) {
- res = wait_file(chan,ints, "digits/nl-uur",lang);
- }
- break;
- case 'M':
- /* Minute */
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 11)
- snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else {
- res = ast_say_date_with_format_nl(chan, time, ints, lang, "ABdY", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_nl(chan, time, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format_nl(chan, time, ints, lang, "ABdY", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_nl(chan, time, ints, lang, "HM", timezone);
- break;
- case 'S':
- /* Seconds */
- res = ast_say_number(chan, tm.tm_sec, ints, lang, (char *) NULL);
- break;
- case 'T':
- res = ast_say_date_with_format_nl(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-/* Polish syntax */
-int ast_say_date_with_format_pl(struct ast_channel *chan, time_t thetime, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- ast_localtime(&thetime, &tm, timezone);
-
- for (offset = 0 ; format[offset] != '\0' ; offset++) {
- int remainder;
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset = 0;
- for (sndoffset = 0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan, ints, sndfile, lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg, sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan, ints, nextmsg, lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg, sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan, ints, nextmsg, lang);
- break;
- case 'm':
- /* Month enumerated */
- res = ast_say_enumeration(chan, (tm.tm_mon + 1), ints, lang, NULL);
- break;
- case 'd':
- case 'e':
- /* First - Thirtyfirst */
- remainder = tm.tm_mday;
- if (tm.tm_mday > 30) {
- res = wait_file(chan, ints, "digits/h-30", lang);
- remainder -= 30;
- }
- if (tm.tm_mday > 20 && tm.tm_mday < 30) {
- res = wait_file(chan, ints, "digits/h-20", lang);
- remainder -= 20;
- }
- if (!res) {
- snprintf(nextmsg, sizeof(nextmsg), "digits/h-%d", remainder);
- res = wait_file(chan, ints, nextmsg, lang);
- }
- break;
- case 'Y':
- /* Year */
- if (tm.tm_year > 100) {
- res = wait_file(chan, ints, "digits/2", lang);
- if (!res)
- res = wait_file(chan, ints, "digits/1000.2",lang);
- if (tm.tm_year > 100) {
- if (!res)
- res = ast_say_enumeration(chan, tm.tm_year - 100, ints, lang, NULL);
- }
- } else if (tm.tm_year == 100) {
- res = wait_file(chan, ints, "digits/h-2000", lang);
- } else {
- if (tm.tm_year < 1) {
- /* I'm not going to handle 1900 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- break;
- } else {
- res = wait_file(chan, ints, "digits/1000", lang);
- if (!res) {
- wait_file(chan, ints, "digits/900", lang);
- res = ast_say_enumeration(chan, tm.tm_year, ints, lang, NULL);
- }
- }
- }
- if (!res)
- wait_file(chan, ints, "digits/year", lang);
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (tm.tm_hour == 0)
- snprintf(nextmsg, sizeof(nextmsg), "digits/t-12");
- else if (tm.tm_hour > 12)
- snprintf(nextmsg, sizeof(nextmsg), "digits/t-%d", tm.tm_hour - 12);
- else
- snprintf(nextmsg, sizeof(nextmsg), "digits/t-%d", tm.tm_hour);
-
- res = wait_file(chan, ints, nextmsg, lang);
- break;
- case 'H':
- case 'k':
- /* 24-Hour */
- if (tm.tm_hour != 0) {
- snprintf(nextmsg, sizeof(nextmsg), "digits/t-%d", tm.tm_hour);
- res = wait_file(chan, ints, nextmsg, lang);
- } else
- res = wait_file(chan, ints, "digits/t-24", lang);
- break;
- case 'M':
- case 'N':
- /* Minute */
- if (tm.tm_min == 0) {
- if (format[offset] == 'M') {
- res = wait_file(chan, ints, "digits/oclock", lang);
- } else {
- res = wait_file(chan, ints, "digits/100", lang);
- }
- } else
- res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 11)
- snprintf(nextmsg, sizeof(nextmsg), "digits/p-m");
- else
- snprintf(nextmsg, sizeof(nextmsg), "digits/a-m");
- res = wait_file(chan, ints, nextmsg, lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or AdBY */
- {
- time_t tv_sec = time(NULL);
- struct tm tmnow;
- time_t beg_today;
-
- ast_localtime(&tv_sec,&tmnow, timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < thetime) {
- /* Today */
- res = wait_file(chan, ints, "digits/today", lang);
- } else if (beg_today - 86400 < thetime) {
- /* Yesterday */
- res = wait_file(chan, ints, "digits/yesterday", lang);
- } else {
- res = ast_say_date_with_format(chan, thetime, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or AdBY */
- {
- time_t tv_sec = time(NULL);
- struct tm tmnow;
- time_t beg_today;
-
- ast_localtime(&tv_sec, &tmnow, timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < thetime) {
- /* Today */
- } else if ((beg_today - 86400) < thetime) {
- /* Yesterday */
- res = wait_file(chan, ints, "digits/yesterday", lang);
- } else if (beg_today - 86400 * 6 < thetime) {
- /* Within the last week */
- res = ast_say_date_with_format(chan, thetime, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format(chan, thetime, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format(chan, thetime, ints, lang, "HM", timezone);
- break;
- case 'S':
- /* Seconds */
- res = wait_file(chan, ints, "digits/and", lang);
- if (!res) {
- if (tm.tm_sec == 1) {
- res = wait_file(chan, ints, "digits/1z", lang);
- if (!res)
- res = wait_file(chan, ints, "digits/second-a", lang);
- } else {
- res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
- if (!res) {
- int ten, one;
- ten = tm.tm_sec / 10;
- one = tm.tm_sec % 10;
-
- if (one > 1 && one < 5 && ten != 1)
- res = wait_file(chan,ints, "digits/seconds",lang);
- else
- res = wait_file(chan,ints, "digits/second",lang);
- }
- }
- }
- break;
- case 'T':
- res = ast_say_date_with_format(chan, thetime, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res)
- break;
- }
- return res;
-}
-
-/* Portuguese syntax */
-int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (format == NULL)
- format = "Ad 'digits/pt-de' B 'digits/pt-de' Y I 'digits/pt-e' Mp";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- snprintf(nextmsg,sizeof(nextmsg), "%s", sndfile);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'm':
- /* First - Twelfth */
- if (!strcasecmp(lang, "pt_BR")) {
- res = ast_say_number(chan, tm.tm_mon+1, ints, lang, (char *) NULL);
- } else {
- snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d", tm.tm_mon +1);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- break;
- case 'd':
- case 'e':
- /* First - Thirtyfirst */
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
- break;
- case 'Y':
- /* Year */
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (!strcasecmp(lang, "pt_BR")) {
- if (tm.tm_hour == 0) {
- if (format[offset] == 'I')
- res = wait_file(chan, ints, "digits/pt-a", lang);
- if (!res)
- res = wait_file(chan, ints, "digits/pt-meianoite", lang);
- } else if (tm.tm_hour == 12) {
- if (format[offset] == 'I')
- res = wait_file(chan, ints, "digits/pt-ao", lang);
- if (!res)
- res = wait_file(chan, ints, "digits/pt-meiodia", lang);
- } else {
- if (format[offset] == 'I') {
- if ((tm.tm_hour % 12) != 1)
- res = wait_file(chan, ints, "digits/pt-as", lang);
- else
- res = wait_file(chan, ints, "digits/pt-a", lang);
- }
- if (!res)
- res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
- }
- } else {
- if (tm.tm_hour == 0) {
- if (format[offset] == 'I')
- res = wait_file(chan, ints, "digits/pt-ah", lang);
- if (!res)
- res = wait_file(chan, ints, "digits/pt-meianoite", lang);
- }
- else if (tm.tm_hour == 12) {
- if (format[offset] == 'I')
- res = wait_file(chan, ints, "digits/pt-ao", lang);
- if (!res)
- res = wait_file(chan, ints, "digits/pt-meiodia", lang);
- }
- else {
- if (format[offset] == 'I') {
- res = wait_file(chan, ints, "digits/pt-ah", lang);
- if ((tm.tm_hour % 12) != 1)
- if (!res)
- res = wait_file(chan, ints, "digits/pt-sss", lang);
- }
- if (!res)
- res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f");
- }
- }
- break;
- case 'H':
- case 'k':
- /* 24-Hour */
- if (!strcasecmp(lang, "pt_BR")) {
- res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
- if ((!res) && (format[offset] == 'H')) {
- if (tm.tm_hour > 1) {
- res = wait_file(chan,ints,"digits/hours",lang);
- } else {
- res = wait_file(chan,ints,"digits/hour",lang);
- }
- }
- } else {
- res = ast_say_number(chan, -tm.tm_hour, ints, lang, NULL);
- if (!res) {
- if (tm.tm_hour != 0) {
- int remainder = tm.tm_hour;
- if (tm.tm_hour > 20) {
- res = wait_file(chan,ints, "digits/20",lang);
- remainder -= 20;
- }
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", remainder);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- }
- }
- break;
- case 'M':
- /* Minute */
- if (!strcasecmp(lang, "pt_BR")) {
- res = ast_say_number(chan, tm.tm_min, ints, lang, NULL);
- if (!res) {
- if (tm.tm_min > 1) {
- res = wait_file(chan,ints,"digits/minutes",lang);
- } else {
- res = wait_file(chan,ints,"digits/minute",lang);
- }
- }
- } else {
- if (tm.tm_min == 0) {
- res = wait_file(chan, ints, "digits/pt-hora", lang);
- if (tm.tm_hour != 1)
- if (!res)
- res = wait_file(chan, ints, "digits/pt-sss", lang);
- } else {
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- }
- }
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (!strcasecmp(lang, "pt_BR")) {
- if ((tm.tm_hour != 0) && (tm.tm_hour != 12)) {
- res = wait_file(chan, ints, "digits/pt-da", lang);
- if (!res) {
- if ((tm.tm_hour >= 0) && (tm.tm_hour < 12))
- res = wait_file(chan, ints, "digits/morning", lang);
- else if ((tm.tm_hour >= 12) && (tm.tm_hour < 18))
- res = wait_file(chan, ints, "digits/afternoon", lang);
- else res = wait_file(chan, ints, "digits/night", lang);
- }
- }
- } else {
- if (tm.tm_hour > 12)
- res = wait_file(chan, ints, "digits/p-m", lang);
- else if (tm.tm_hour && tm.tm_hour < 12)
- res = wait_file(chan, ints, "digits/a-m", lang);
- }
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else {
- res = ast_say_date_with_format_pt(chan, time, ints, lang, "Ad 'digits/pt-de' B 'digits/pt-de' Y", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_pt(chan, time, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format_pt(chan, time, ints, lang, "Ad 'digits/pt-de' B 'digits/pt-de' Y", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_pt(chan, time, ints, lang, "H 'digits/pt-e' M", timezone);
- break;
- case 'S':
- /* Seconds */
- if (!strcasecmp(lang, "pt_BR")) {
- res = ast_say_number(chan, tm.tm_sec, ints, lang, NULL);
- if (!res) {
- if (tm.tm_sec > 1) {
- res = wait_file(chan,ints,"digits/seconds",lang);
- } else {
- res = wait_file(chan,ints,"digits/second",lang);
- }
- } else if (tm.tm_sec < 10) {
- res = wait_file(chan,ints, "digits/oh",lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- int ten, one;
- ten = (tm.tm_sec / 10) * 10;
- one = (tm.tm_sec % 10);
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- /* Fifty, not fifty-zero */
- if (one != 0) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- }
- }
- break;
- case 'T':
- res = ast_say_date_with_format_pt(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-/* Taiwanese / Chinese syntax */
-int ast_say_date_with_format_tw(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (format == NULL)
- format = "YBdAkM";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan,ints,sndfile,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- case 'm':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'd':
- case 'e':
- /* First - Thirtyfirst */
- if (!(tm.tm_mday % 10) || (tm.tm_mday < 10)) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_mday);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_mday - (tm.tm_mday % 10));
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_mday % 10);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- if (!res) res = wait_file(chan,ints,"digits/day",lang);
- break;
- case 'Y':
- /* Year */
- if (tm.tm_year > 99) {
- res = wait_file(chan,ints, "digits/2",lang);
- if (!res) {
- res = wait_file(chan,ints, "digits/thousand",lang);
- }
- if (tm.tm_year > 100) {
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", (tm.tm_year - 100) / 10);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", (tm.tm_year - 100) % 10);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- }
- if (!res) {
- res = wait_file(chan,ints, "digits/year",lang);
- }
- } else {
- if (tm.tm_year < 1) {
- /* I'm not going to handle 1900 and prior */
- /* We'll just be silent on the year, instead of bombing out. */
- } else {
- res = wait_file(chan,ints, "digits/1",lang);
- if (!res) {
- res = wait_file(chan,ints, "digits/9",lang);
- }
- if (!res) {
- if (tm.tm_year <= 9) {
- /* 1901 - 1909 */
- res = wait_file(chan,ints, "digits/0",lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- } else {
- /* 1910 - 1999 */
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year / 10);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year % 10);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- }
- }
- if (!res) {
- res = wait_file(chan,ints, "digits/year",lang);
- }
- }
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (tm.tm_hour == 0)
- snprintf(nextmsg,sizeof(nextmsg), "digits/12");
- else if (tm.tm_hour > 12)
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- res = wait_file(chan,ints, "digits/oclock",lang);
- }
- break;
- case 'H':
- if (tm.tm_hour < 10) {
- res = wait_file(chan, ints, "digits/0", lang);
- }
- case 'k':
- /* 24-Hour */
- if (!(tm.tm_hour % 10) || tm.tm_hour < 10) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - (tm.tm_hour % 10));
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour % 10);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- if (!res) {
- res = wait_file(chan,ints, "digits/oclock",lang);
- }
- break;
- case 'M':
- /* Minute */
- if (!(tm.tm_min % 10) || tm.tm_min < 10) {
- if (tm.tm_min < 10) {
- res = wait_file(chan, ints, "digits/0", lang);
- }
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_min);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_min - (tm.tm_min % 10));
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_min % 10);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- if (!res) {
- res = wait_file(chan,ints, "digits/minute",lang);
- }
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 11)
- snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else {
- res = ast_say_date_with_format_tw(chan, time, ints, lang, "YBdA", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_tw(chan, time, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format_tw(chan, time, ints, lang, "YBdA", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_tw(chan, time, ints, lang, "kM", timezone);
- break;
- case 'S':
- /* Seconds */
- if (!(tm.tm_sec % 10) || tm.tm_sec < 10) {
- if (tm.tm_sec < 10) {
- res = wait_file(chan, ints, "digits/0", lang);
- }
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
- res = wait_file(chan,ints,nextmsg,lang);
- } else {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec - (tm.tm_sec % 10));
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res) {
- snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec % 10);
- res = wait_file(chan,ints,nextmsg,lang);
- }
- }
- if (!res) {
- res = wait_file(chan,ints, "digits/second",lang);
- }
- break;
- case 'T':
- res = ast_say_date_with_format_tw(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-static int say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- if (!strcasecmp(lang, "en") ) { /* English syntax */
- return(ast_say_time_en(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "de") ) { /* German syntax */
- return(ast_say_time_de(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "fr") ) { /* French syntax */
- return(ast_say_time_fr(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "nl") ) { /* Dutch syntax */
- return(ast_say_time_nl(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "pt") ) { /* Portuguese syntax */
- return(ast_say_time_pt(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "pt_BR") ) { /* Brazilian Portuguese syntax */
- return(ast_say_time_pt_BR(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "tw") || !strcasecmp(lang, "zh") ) { /* Taiwanese / Chinese syntax */
- return(ast_say_time_tw(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "gr") ) { /* Greek syntax */
- return(ast_say_time_gr(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "ge") ) { /* Georgian syntax */
- return(ast_say_time_ge(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "he")) { /* Hebrew syntax */
- return (ast_say_time_he(chan, t, ints, lang));
- }
-
- /* Default to English */
- return(ast_say_time_en(chan, t, ints, lang));
-}
-
-/* English syntax */
-int ast_say_time_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
- int hour, pm=0;
-
- ast_localtime(&t, &tm, NULL);
- hour = tm.tm_hour;
- if (!hour)
- hour = 12;
- else if (hour == 12)
- pm = 1;
- else if (hour > 12) {
- hour -= 12;
- pm = 1;
- }
- if (!res)
- res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
-
- if (tm.tm_min > 9) {
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- } else if (tm.tm_min) {
- if (!res)
- res = ast_streamfile(chan, "digits/oh", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/oclock", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (pm) {
- if (!res)
- res = ast_streamfile(chan, "digits/p-m", lang);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/a-m", lang);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- return res;
-}
-
-/* German syntax */
-int ast_say_time_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
- if (!res)
- res = ast_say_number(chan, tm.tm_hour, ints, lang, "n");
- if (!res)
- res = ast_streamfile(chan, "digits/oclock", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- if (tm.tm_min > 0)
- res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
- return res;
-}
-
-/* French syntax */
-int ast_say_time_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
-
- res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
- if (!res)
- res = ast_streamfile(chan, "digits/oclock", lang);
- if (tm.tm_min) {
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- }
- return res;
-}
-
-/* Dutch syntax */
-int ast_say_time_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
- if (!res)
- res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL);
- if (!res)
- res = ast_streamfile(chan, "digits/nl-uur", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- if (tm.tm_min > 0)
- res = ast_say_number(chan, tm.tm_min, ints, lang, NULL);
- return res;
-}
-
-/* Portuguese syntax */
-int ast_say_time_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
- int hour;
-
- ast_localtime(&t, &tm, NULL);
- hour = tm.tm_hour;
- if (!res)
- res = ast_say_number(chan, hour, ints, lang, "f");
- if (tm.tm_min) {
- if (!res)
- res = wait_file(chan, ints, "digits/pt-e", lang);
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- } else {
- if (!res)
- res = wait_file(chan, ints, "digits/pt-hora", lang);
- if (tm.tm_hour != 1)
- if (!res)
- res = wait_file(chan, ints, "digits/pt-sss", lang);
- }
- if (!res)
- res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
- return res;
-}
-
-/* Brazilian Portuguese syntax */
-int ast_say_time_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
-
- res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
- if (!res) {
- if (tm.tm_hour > 1)
- res = wait_file(chan, ints, "digits/hours", lang);
- else
- res = wait_file(chan, ints, "digits/hour", lang);
- }
- if ((!res) && (tm.tm_min)) {
- res = wait_file(chan, ints, "digits/pt-e", lang);
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- if (!res) {
- if (tm.tm_min > 1)
- res = wait_file(chan, ints, "digits/minutes", lang);
- else
- res = wait_file(chan, ints, "digits/minute", lang);
- }
- }
- return res;
-}
-
-/* Taiwanese / Chinese syntax */
-int ast_say_time_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
- int hour, pm=0;
-
- ast_localtime(&t, &tm, NULL);
- hour = tm.tm_hour;
- if (!hour)
- hour = 12;
- else if (hour == 12)
- pm = 1;
- else if (hour > 12) {
- hour -= 12;
- pm = 1;
- }
- if (pm) {
- if (!res)
- res = ast_streamfile(chan, "digits/p-m", lang);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/a-m", lang);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
- if (!res)
- res = ast_streamfile(chan, "digits/oclock", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- if (!res)
- res = ast_streamfile(chan, "digits/minute", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- return res;
-}
-
-/* Hebrew syntax */
-int ast_say_time_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
- int hour;
-
- ast_localtime(&t, &tm, NULL);
- hour = tm.tm_hour;
- if (!hour)
- hour = 12;
-
- if (!res)
- res = ast_say_number_full_he(chan, hour, ints, lang, "f", -1, -1);
-
- if (tm.tm_min > 9) {
- if (!res)
- res = ast_say_number_full_he(chan, tm.tm_min, ints, lang, "f", -1, -1);
- } else if (tm.tm_min) {
- if (!res) { /* say a leading zero if needed */
- res = ast_say_number_full_he(chan, 0, ints, lang, "f", -1, -1);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number_full_he(chan, tm.tm_min, ints, lang, "f", -1, -1);
- } else {
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- return res;
-}
-static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- if (!strcasecmp(lang, "en") ) { /* English syntax */
- return(ast_say_datetime_en(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "de") ) { /* German syntax */
- return(ast_say_datetime_de(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "fr") ) { /* French syntax */
- return(ast_say_datetime_fr(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "nl") ) { /* Dutch syntax */
- return(ast_say_datetime_nl(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "pt") ) { /* Portuguese syntax */
- return(ast_say_datetime_pt(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "pt_BR") ) { /* Brazilian Portuguese syntax */
- return(ast_say_datetime_pt_BR(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "tw") || !strcasecmp(lang, "zh") ) { /* Taiwanese / Chinese syntax */
- return(ast_say_datetime_tw(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "gr") ) { /* Greek syntax */
- return(ast_say_datetime_gr(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "ge") ) { /* Georgian syntax */
- return(ast_say_datetime_ge(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "he")) { /* Hebrew syntax */
- return (ast_say_datetime_he(chan, t, ints, lang));
- }
-
- /* Default to English */
- return(ast_say_datetime_en(chan, t, ints, lang));
-}
-
-/* English syntax */
-int ast_say_datetime_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- int hour, pm=0;
-
- ast_localtime(&t, &tm, NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
-
- hour = tm.tm_hour;
- if (!hour)
- hour = 12;
- else if (hour == 12)
- pm = 1;
- else if (hour > 12) {
- hour -= 12;
- pm = 1;
- }
- if (!res)
- res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
-
- if (tm.tm_min > 9) {
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- } else if (tm.tm_min) {
- if (!res)
- res = ast_streamfile(chan, "digits/oh", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/oclock", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (pm) {
- if (!res)
- res = ast_streamfile(chan, "digits/p-m", lang);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/a-m", lang);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- return res;
-}
-
-/* German syntax */
-int ast_say_datetime_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
- res = ast_say_date(chan, t, ints, lang);
- if (!res)
- ast_say_time(chan, t, ints, lang);
- return res;
-
-}
-
-/* French syntax */
-int ast_say_datetime_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
-
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
-
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
-
- if (!res)
- res = ast_say_number(chan, tm.tm_hour, ints, lang, "f");
- if (!res)
- res = ast_streamfile(chan, "digits/oclock", lang);
- if (tm.tm_min > 0) {
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- return res;
-}
-
-/* Dutch syntax */
-int ast_say_datetime_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
- res = ast_say_date(chan, t, ints, lang);
- if (!res) {
- res = ast_streamfile(chan, "digits/nl-om", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- ast_say_time(chan, t, ints, lang);
- return res;
-}
-
-/* Portuguese syntax */
-int ast_say_datetime_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- int hour, pm=0;
-
- ast_localtime(&t, &tm, NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
-
- hour = tm.tm_hour;
- if (!hour)
- hour = 12;
- else if (hour == 12)
- pm = 1;
- else if (hour > 12) {
- hour -= 12;
- pm = 1;
- }
- if (!res)
- res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
-
- if (tm.tm_min > 9) {
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- } else if (tm.tm_min) {
- if (!res)
- res = ast_streamfile(chan, "digits/oh", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/oclock", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (pm) {
- if (!res)
- res = ast_streamfile(chan, "digits/p-m", lang);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/a-m", lang);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- return res;
-}
-
-/* Brazilian Portuguese syntax */
-int ast_say_datetime_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
- res = ast_say_date(chan, t, ints, lang);
- if (!res)
- res = ast_say_time(chan, t, ints, lang);
- return res;
-}
-
-/* Taiwanese / Chinese syntax */
-int ast_say_datetime_tw(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- int hour, pm=0;
-
- ast_localtime(&t, &tm, NULL);
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
-
- hour = tm.tm_hour;
- if (!hour)
- hour = 12;
- else if (hour == 12)
- pm = 1;
- else if (hour > 12) {
- hour -= 12;
- pm = 1;
- }
- if (pm) {
- if (!res)
- res = ast_streamfile(chan, "digits/p-m", lang);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/a-m", lang);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
- if (!res)
- res = ast_streamfile(chan, "digits/oclock", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- if (!res)
- res = ast_streamfile(chan, "digits/minute", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- return res;
-}
-
-/* Hebrew syntax */
-int ast_say_datetime_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- int hour;
-
- ast_localtime(&t, &tm, NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- res = ast_waitstream(chan, ints);
- }
- }
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- res = ast_waitstream(chan, ints);
- }
- }
- if (!res) {
- res = ast_say_number(chan, tm.tm_mday, ints, lang, "f");
- }
-
- hour = tm.tm_hour;
- if (!hour) {
- hour = 12;
- }
-
- if (!res) {
- res = ast_say_number(chan, hour, ints, lang, "f");
- }
-
- if (tm.tm_min > 9) {
- if (!res) {
- res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
- }
- } else if (tm.tm_min) {
- if (!res) {
- /* say a leading zero if needed */
- res = ast_say_number(chan, 0, ints, lang, "f");
- }
- if (!res) {
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- res = ast_say_number(chan, tm.tm_min, ints, lang, "f");
- }
- } else {
- if (!res) {
- res = ast_waitstream(chan, ints);
- }
- }
- if (!res) {
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, "f");
- }
- return res;
-}
-static int say_datetime_from_now(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- if (!strcasecmp(lang, "en") ) { /* English syntax */
- return(ast_say_datetime_from_now_en(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "fr") ) { /* French syntax */
- return(ast_say_datetime_from_now_fr(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) { /* Portuguese syntax */
- return(ast_say_datetime_from_now_pt(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "ge") ) { /* Georgian syntax */
- return(ast_say_datetime_from_now_ge(chan, t, ints, lang));
- } else if (!strcasecmp(lang, "he")) { /* Georgian syntax */
- return (ast_say_datetime_from_now_he(chan, t, ints, lang));
- }
-
- /* Default to English */
- return(ast_say_datetime_from_now_en(chan, t, ints, lang));
-}
-
-/* English syntax */
-int ast_say_datetime_from_now_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- int res=0;
- time_t nowt;
- int daydiff;
- struct tm tm;
- struct tm now;
- char fn[256];
-
- time(&nowt);
-
- ast_localtime(&t, &tm, NULL);
- ast_localtime(&nowt,&now, NULL);
- daydiff = now.tm_yday - tm.tm_yday;
- if ((daydiff < 0) || (daydiff > 6)) {
- /* Day of month and month */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
-
- } else if (daydiff) {
- /* Just what day of the week */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- } /* Otherwise, it was today */
- if (!res)
- res = ast_say_time(chan, t, ints, lang);
- return res;
-}
-
-/* French syntax */
-int ast_say_datetime_from_now_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- int res=0;
- time_t nowt;
- int daydiff;
- struct tm tm;
- struct tm now;
- char fn[256];
-
- time(&nowt);
-
- ast_localtime(&t, &tm, NULL);
- ast_localtime(&nowt, &now, NULL);
- daydiff = now.tm_yday - tm.tm_yday;
- if ((daydiff < 0) || (daydiff > 6)) {
- /* Day of month and month */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
-
- } else if (daydiff) {
- /* Just what day of the week */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- } /* Otherwise, it was today */
- if (!res)
- res = ast_say_time(chan, t, ints, lang);
- return res;
-}
-
-/* Portuguese syntax */
-int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- int res=0;
- time_t nowt;
- int daydiff;
- struct tm tm;
- struct tm now;
- char fn[256];
-
- time(&nowt);
-
- ast_localtime(&t, &tm, NULL);
- ast_localtime(&nowt, &now, NULL);
- daydiff = now.tm_yday - tm.tm_yday;
- if ((daydiff < 0) || (daydiff > 6)) {
- /* Day of month and month */
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
- if (!res)
- res = wait_file(chan, ints, "digits/pt-de", lang);
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- if (!res)
- res = wait_file(chan, ints, fn, lang);
-
- } else if (daydiff) {
- /* Just what day of the week */
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- if (!res)
- res = wait_file(chan, ints, fn, lang);
- } /* Otherwise, it was today */
- if (!strcasecmp(lang, "pt_BR")) {
- if (tm.tm_hour > 1) {
- snprintf(fn, sizeof(fn), "digits/pt-as");
- } else {
- snprintf(fn, sizeof(fn), "digits/pt-a");
- }
- if (!res)
- res = wait_file(chan, ints, fn, lang);
- } else {
- snprintf(fn, sizeof(fn), "digits/pt-ah");
- if (!res)
- res = wait_file(chan, ints, fn, lang);
- if (tm.tm_hour != 1)
- if (!res)
- res = wait_file(chan, ints, "digits/pt-sss", lang);
- if (!res)
- res = ast_say_time(chan, t, ints, lang);
- }
- return res;
-}
-
-/* Hebrew syntax */
-int ast_say_datetime_from_now_he(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- int res = 0;
- time_t nowt;
- int daydiff;
- struct tm tm;
- struct tm now;
- char fn[256];
-
- time(&nowt);
-
- ast_localtime(&t, &tm, NULL);
- ast_localtime(&nowt, &now, NULL);
- daydiff = now.tm_yday - tm.tm_yday;
- if ((daydiff < 0) || (daydiff > 6)) {
- /* Day of month and month */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (!res) {
- res = ast_say_number(chan, tm.tm_mday, ints, lang, "f");
- }
- } else if (daydiff) {
- /* Just what day of the week */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- res = ast_waitstream(chan, ints);
- }
- }
- } /* Otherwise, it was today */
- if (!res) {
- res = ast_say_time(chan, t, ints, lang);
- }
- return res;
-}
-
-/*********************************** GREEK SUPPORT ***************************************/
-
-
-/*
- * digits/female-[1..4] : "Mia, dyo , treis, tessereis"
- */
-static int gr_say_number_female(int num, struct ast_channel *chan, const char *ints, const char *lang){
- int tmp;
- int left;
- int res;
- char fn[256] = "";
-
- /* ast_log(LOG_DEBUG, "\n\n Saying number female %s %d \n\n",lang, num); */
- if (num < 5) {
- snprintf(fn, sizeof(fn), "digits/female-%d", num);
- res = wait_file(chan, ints, fn, lang);
- } else if (num < 13) {
- res = ast_say_number(chan, num, ints, lang, (char *) NULL);
- } else if (num <100 ) {
- tmp = (num/10) * 10;
- left = num - tmp;
- snprintf(fn, sizeof(fn), "digits/%d", tmp);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (left)
- gr_say_number_female(left, chan, ints, lang);
-
- } else {
- return -1;
- }
- return res;
-}
-
-
-
-/*
- * A list of the files that you need to create
- -> digits/xilia = "xilia"
- -> digits/myrio = "ekatomyrio"
- -> digits/thousands = "xiliades"
- -> digits/millions = "ektatomyria"
- -> digits/[1..12] :: A pronunciation of th digits form 1 to 12 e.g. "tria"
- -> digits/[10..100] :: A pronunciation of the tens from 10 to 90
- e,g 80 = "ogdonta"
- Here we must note that we use digits/tens/100 to utter "ekato"
- and digits/hundred-100 to utter "ekaton"
- -> digits/hundred-[100...1000] :: A pronunciation of hundreds from 100 to 1000 e.g 400 =
- "terakosia". Here again we use hundreds/1000 for "xilia"
- and digits/thousnds for "xiliades"
-*/
-
-static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char *ints, const char *language,int audiofd, int ctrlfd)
-{
- int res = 0;
- char fn[256] = "";
- int i=0;
-
-
- if (!num) {
- snprintf(fn, sizeof(fn), "digits/0");
- res = ast_streamfile(chan, fn, chan->language);
- if (!res)
- return ast_waitstream(chan, ints);
- }
-
- while (!res && num ) {
- i++;
- if (num < 13) {
- snprintf(fn, sizeof(fn), "digits/%d", num);
- num = 0;
- } else if (num <= 100) {
- /* 13 < num <= 100 */
- snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
- num -= ((num / 10) * 10);
- } else if (num < 200) {
- /* 100 < num < 200 */
- snprintf(fn, sizeof(fn), "digits/hundred-100");
- num -= ((num / 100) * 100);
- } else if (num < 1000) {
- /* 200 < num < 1000 */
- snprintf(fn, sizeof(fn), "digits/hundred-%d", (num/100)*100);
- num -= ((num / 100) * 100);
- } else if (num < 2000){
- snprintf(fn, sizeof(fn), "digits/xilia");
- num -= ((num / 1000) * 1000);
- } else {
- /* num > 1000 */
- if (num < 1000000) {
- res = ast_say_number_full_gr(chan, (num / 1000), ints, chan->language, audiofd, ctrlfd);
- if (res)
- return res;
- num = num % 1000;
- snprintf(fn, sizeof(fn), "digits/thousands");
- } else {
- if (num < 1000000000) { /* 1,000,000,000 */
- res = ast_say_number_full_gr(chan, (num / 1000000), ints, chan->language ,audiofd, ctrlfd);
- if (res)
- return res;
- num = num % 1000000;
- snprintf(fn, sizeof(fn), "digits/millions");
- } else {
- ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
- res = -1;
- }
- }
- }
- if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
- }
- }
- return res;
-}
-
-
-/*
- * The format is weekday - day - month -year
- *
- * A list of the files that you need to create
- * digits/day-[1..7] : "Deytera .. Paraskeyh"
- * digits/months/1..12 : "Ianouariou .. Dekembriou"
- Attention the months are in
- "gekinh klhsh"
- */
-
-
-static int ast_say_date_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
-
- char fn[256];
- int res = 0;
-
-
- ast_localtime(&t,&tm,NULL);
- /* W E E K - D A Y */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- /* D A Y */
- if (!res) {
- gr_say_number_female(tm.tm_mday, chan, ints, lang);
- }
- /* M O N T H */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- /* Y E A R */
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
- return res;
-}
-
-
-
-/* A list of the files that you need to create
- * digits/female/1..4 : "Mia, dyo , treis, tesseris "
- * digits/kai : "KAI"
- * didgits : "h wra"
- * digits/p-m : "meta meshmbrias"
- * digits/a-m : "pro meshmbrias"
- */
-
-static int ast_say_time_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
-
- struct tm tm;
- int res = 0;
- int hour, pm=0;
-
- ast_localtime(&t, &tm, NULL);
- hour = tm.tm_hour;
-
- if (!hour)
- hour = 12;
- else if (hour == 12)
- pm = 1;
- else if (hour > 12) {
- hour -= 12;
- pm = 1;
- }
-
- res = gr_say_number_female(hour, chan, ints, lang);
- if (tm.tm_min) {
- if (!res)
- res = ast_streamfile(chan, "digits/kai", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/hwra", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- if (pm) {
- if (!res)
- res = ast_streamfile(chan, "digits/p-m", lang);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/a-m", lang);
- }
- if (!res)
- res = ast_waitstream(chan, ints);
- return res;
-}
-
-
-
-static int ast_say_datetime_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
-
-
- /* W E E K - D A Y */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- /* D A Y */
- if (!res) {
- gr_say_number_female(tm.tm_mday, chan, ints, lang);
- }
- /* M O N T H */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
-
- res = ast_say_time_gr(chan, t, ints, lang);
- return res;
-}
-
-static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
-{
-
- struct tm tm;
- int res=0, offset, sndoffset;
- char sndfile[256], nextmsg[256];
-
- if (!format)
- format = "AdBY 'digits/at' IMp";
-
- ast_localtime(&time,&tm,timezone);
-
- for (offset=0 ; format[offset] != '\0' ; offset++) {
- ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
- switch (format[offset]) {
- /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
- case '\'':
- /* Literal name of a sound file */
- sndoffset=0;
- for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
- sndfile[sndoffset] = format[offset];
- sndfile[sndoffset] = '\0';
- res = wait_file(chan,ints,sndfile,lang);
- break;
- case 'A':
- case 'a':
- /* Sunday - Saturday */
- snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'B':
- case 'b':
- case 'h':
- /* January - December */
- snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'd':
- case 'e':
- /* first - thirtyfirst */
- gr_say_number_female(tm.tm_mday, chan, ints, lang);
- break;
- case 'Y':
- /* Year */
-
- ast_say_number_full_gr(chan, 1900+tm.tm_year, ints, chan->language, -1, -1);
- break;
- case 'I':
- case 'l':
- /* 12-Hour */
- if (tm.tm_hour == 0)
- gr_say_number_female(12, chan, ints, lang);
- else if (tm.tm_hour > 12)
- gr_say_number_female(tm.tm_hour - 12, chan, ints, lang);
- else
- gr_say_number_female(tm.tm_hour, chan, ints, lang);
- break;
- case 'H':
- case 'k':
- /* 24-Hour */
- gr_say_number_female(tm.tm_hour, chan, ints, lang);
- break;
- case 'M':
- /* Minute */
- if (tm.tm_min) {
- if (!res)
- res = ast_streamfile(chan, "digits/kai", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- if (!res)
- res = ast_say_number_full_gr(chan, tm.tm_min, ints, lang, -1, -1);
- } else {
- if (!res)
- res = ast_streamfile(chan, "digits/oclock", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- break;
- case 'P':
- case 'p':
- /* AM/PM */
- if (tm.tm_hour > 11)
- snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
- else
- snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'Q':
- /* Shorthand for "Today", "Yesterday", or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- res = wait_file(chan,ints, "digits/today",lang);
- } else if (beg_today - 86400 < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else {
- res = ast_say_date_with_format_gr(chan, time, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'q':
- /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
- /* XXX As emphasized elsewhere, this should the native way in your
- * language to say the date, with changes in what you say, depending
- * upon how recent the date is. XXX */
- {
- struct timeval now;
- struct tm tmnow;
- time_t beg_today, tt;
-
- gettimeofday(&now,NULL);
- tt = now.tv_sec;
- ast_localtime(&tt,&tmnow,timezone);
- /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
- /* In any case, it saves not having to do ast_mktime() */
- beg_today = tt - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
- if (beg_today < time) {
- /* Today */
- } else if ((beg_today - 86400) < time) {
- /* Yesterday */
- res = wait_file(chan,ints, "digits/yesterday",lang);
- } else if (beg_today - 86400 * 6 < time) {
- /* Within the last week */
- res = ast_say_date_with_format_gr(chan, time, ints, lang, "A", timezone);
- } else {
- res = ast_say_date_with_format_gr(chan, time, ints, lang, "AdBY", timezone);
- }
- }
- break;
- case 'R':
- res = ast_say_date_with_format_gr(chan, time, ints, lang, "HM", timezone);
- break;
- case 'S':
- /* Seconds */
- snprintf(nextmsg,sizeof(nextmsg), "digits/kai");
- res = wait_file(chan,ints,nextmsg,lang);
- if (!res)
- res = ast_say_number_full_gr(chan, tm.tm_sec, ints, lang, -1, -1);
- if (!res)
- snprintf(nextmsg,sizeof(nextmsg), "digits/seconds");
- res = wait_file(chan,ints,nextmsg,lang);
- break;
- case 'T':
- res = ast_say_date_with_format_gr(chan, time, ints, lang, "HMS", timezone);
- break;
- case ' ':
- case ' ':
- /* Just ignore spaces and tabs */
- break;
- default:
- /* Unknown character */
- ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
- }
- /* Jump out on DTMF */
- if (res) {
- break;
- }
- }
- return res;
-}
-
-
-
-
-/*********************************** Georgian Support ***************************************/
-
-
-/*
- Convert a number into a semi-localized string. Only for Georgian.
- res must be of at least 256 bytes, preallocated.
- The output corresponds to Georgian spoken numbers, so
- it may be either converted to real words by applying a direct conversion
- table, or played just by substituting the entities with played files.
-
- Output may consist of the following tokens (separated by spaces):
- 0, minus.
- 1-9, 1_-9_. (erti, ori, sami, otxi, ... . erti, or, sam, otx, ...).
- 10-19.
- 20, 40, 60, 80, 20_, 40_, 60_, 80_. (oci, ormoci, ..., ocda, ormocda, ...).
- 100, 100_, 200, 200_, ..., 900, 900_. (asi, as, orasi, oras, ...).
- 1000, 1000_. (atasi, atas).
- 1000000, 1000000_. (milioni, milion).
- 1000000000, 1000000000_. (miliardi, miliard).
-
- To be able to play the sounds, each of the above tokens needs
- a corresponding sound file. (e.g. 200_.gsm).
-*/
-static char* ast_translate_number_ge(int num, char* res, int res_len)
-{
- char buf[256];
- int digit = 0;
- int remainder = 0;
-
-
- if (num < 0) {
- strncat(res, "minus ", res_len - strlen(res) - 1);
- if ( num > INT_MIN ) {
- num = -num;
- } else {
- num = 0;
- }
- }
-
-
- /* directly read the numbers */
- if (num <= 20 || num == 40 || num == 60 || num == 80 || num == 100) {
- snprintf(buf, sizeof(buf), "%d", num);
- strncat(res, buf, res_len - strlen(res) - 1);
- return res;
- }
-
-
- if (num < 40) { /* ocda... */
- strncat(res, "20_ ", res_len - strlen(res) - 1);
- return ast_translate_number_ge(num - 20, res, res_len);
- }
-
- if (num < 60) { /* ormocda... */
- strncat(res, "40_ ", res_len - strlen(res) - 1);
- return ast_translate_number_ge(num - 40, res, res_len);
- }
-
- if (num < 80) { /* samocda... */
- strncat(res, "60_ ", res_len - strlen(res) - 1);
- return ast_translate_number_ge(num - 60, res, res_len);
- }
-
- if (num < 100) { /* otxmocda... */
- strncat(res, "80_ ", res_len - strlen(res) - 1);
- return ast_translate_number_ge(num - 80, res, res_len);
- }
-
-
- if (num < 1000) { /* as, oras, samas, ..., cxraas. asi, orasi, ..., cxraasi. */
- remainder = num % 100;
- digit = (num - remainder) / 100;
-
- if (remainder == 0) {
- snprintf(buf, sizeof(buf), "%d", num);
- strncat(res, buf, res_len - strlen(res) - 1);
- return res;
- } else {
- snprintf(buf, sizeof(buf), "%d_ ", digit*100);
- strncat(res, buf, res_len - strlen(res) - 1);
- return ast_translate_number_ge(remainder, res, res_len);
- }
- }
-
-
- if (num == 1000) {
- strncat(res, "1000", res_len - strlen(res) - 1);
- return res;
- }
-
-
- if (num < 1000000) {
- remainder = num % 1000;
- digit = (num - remainder) / 1000;
-
- if (remainder == 0) {
- ast_translate_number_ge(digit, res, res_len);
- strncat(res, " 1000", res_len - strlen(res) - 1);
- return res;
- }
-
- if (digit == 1) {
- strncat(res, "1000_ ", res_len - strlen(res) - 1);
- return ast_translate_number_ge(remainder, res, res_len);
- }
-
- ast_translate_number_ge(digit, res, res_len);
- strncat(res, " 1000_ ", res_len - strlen(res) - 1);
- return ast_translate_number_ge(remainder, res, res_len);
-
- }
-
-
- if (num == 1000000) {
- strncat(res, "1 1000000", res_len - strlen(res) - 1);
- return res;
- }
-
-
- if (num < 1000000000) {
- remainder = num % 1000000;
- digit = (num - remainder) / 1000000;
-
- if (remainder == 0) {
- ast_translate_number_ge(digit, res, res_len);
- strncat(res, " 1000000", res_len - strlen(res) - 1);
- return res;
- }
-
- ast_translate_number_ge(digit, res, res_len);
- strncat(res, " 1000000_ ", res_len - strlen(res) - 1);
- return ast_translate_number_ge(remainder, res, res_len);
-
- }
-
-
- if (num == 1000000000) {
- strncat(res, "1 1000000000", res_len - strlen(res) - 1);
- return res;
- }
-
-
- if (num > 1000000000) {
- remainder = num % 1000000000;
- digit = (num - remainder) / 1000000000;
-
- if (remainder == 0) {
- ast_translate_number_ge(digit, res, res_len);
- strncat(res, " 1000000000", res_len - strlen(res) - 1);
- return res;
- }
-
- ast_translate_number_ge(digit, res, res_len);
- strncat(res, " 1000000000_ ", res_len - strlen(res) - 1);
- return ast_translate_number_ge(remainder, res, res_len);
-
- }
-
- return res;
-
-}
-
-
-
-/*! \brief ast_say_number_full_ge: Georgian syntax */
-static int ast_say_number_full_ge(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
-{
- int res = 0;
- char fn[512] = "";
- char* s = 0;
- const char* remainder = fn;
-
- if (!num)
- return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
-
-
- ast_translate_number_ge(num, fn, 512);
-
-
-
- while (res == 0 && (s = strstr(remainder, " "))) {
- size_t len = s - remainder;
- char* new_string = malloc(len + 1 + strlen("digits/"));
-
- sprintf(new_string, "digits/");
- strncat(new_string, remainder, len); /* we can't sprintf() it, it's not null-terminated. */
-/* new_string[len + strlen("digits/")] = '\0'; */
-
- if (!ast_streamfile(chan, new_string, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
-
- free(new_string);
-
- remainder = s + 1; /* position just after the found space char. */
- while (*remainder == ' ') /* skip multiple spaces */
- remainder++;
- }
-
-
- /* the last chunk. */
- if (res == 0 && *remainder) {
-
- char* new_string = malloc(strlen(remainder) + 1 + strlen("digits/"));
- sprintf(new_string, "digits/%s", remainder);
-
- if (!ast_streamfile(chan, new_string, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
-
- free(new_string);
-
- }
-
-
- return res;
-
-}
-
-
-
-/*
-Georgian support for date/time requires the following files (*.gsm):
-
-mon-1, mon-2, ... (ianvari, tebervali, ...)
-day-1, day-2, ... (orshabati, samshabati, ...)
-saati_da
-tsuti
-tslis
-*/
-
-
-
-/* Georgian syntax. e.g. "oriatas xuti tslis 5 noemberi". */
-static int ast_say_date_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- char fn[256];
- int res = 0;
- ast_localtime(&t,&tm,NULL);
-
- if (!res)
- res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
-
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/tslis %d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
-
- if (!res) {
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
-/* if (!res)
- res = ast_waitstream(chan, ints);
-*/
- }
-
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- return res;
-
-}
-
-
-
-
-
-/* Georgian syntax. e.g. "otxi saati da eqvsi tsuti" */
-static int ast_say_time_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
-
- res = ast_say_number(chan, tm.tm_hour, ints, lang, (char*)NULL);
- if (!res) {
- res = ast_streamfile(chan, "digits/saati_da", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
-
- if (tm.tm_min) {
- if (!res) {
- res = ast_say_number(chan, tm.tm_min, ints, lang, (char*)NULL);
-
- if (!res) {
- res = ast_streamfile(chan, "digits/tsuti", lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- }
- }
- return res;
-}
-
-
-
-/* Georgian syntax. Say date, then say time. */
-static int ast_say_datetime_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- struct tm tm;
- int res = 0;
-
- ast_localtime(&t, &tm, NULL);
- res = ast_say_date(chan, t, ints, lang);
- if (!res)
- ast_say_time(chan, t, ints, lang);
- return res;
-
-}
-
-
-
-
-/* Georgian syntax */
-static int ast_say_datetime_from_now_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
-{
- int res=0;
- time_t nowt;
- int daydiff;
- struct tm tm;
- struct tm now;
- char fn[256];
-
- time(&nowt);
-
- ast_localtime(&t, &tm, NULL);
- ast_localtime(&nowt, &now, NULL);
- daydiff = now.tm_yday - tm.tm_yday;
- if ((daydiff < 0) || (daydiff > 6)) {
- /* Day of month and month */
- if (!res)
- res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
-
- } else if (daydiff) {
- /* Just what day of the week */
- if (!res) {
- snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
- res = ast_streamfile(chan, fn, lang);
- if (!res)
- res = ast_waitstream(chan, ints);
- }
- } /* Otherwise, it was today */
- if (!res)
- res = ast_say_time(chan, t, ints, lang);
-
- return res;
-}
-
-/* In English, we use the plural for everything but one. For example:
- * 1 degree
- * 2 degrees
- * 5 degrees
- * The filename for the plural form is generated by appending "s". Note that
- * purpose is to generate a unique filename, not to implement irregular
- * declensions. Thus:
- * 1 man
- * 2 mans (the "mans" soundfile will of course say "men")
- */
-static const char *counted_noun_ending_en(int num)
-{
- if (num == 1 || num == -1) {
- return "";
- } else {
- return "s";
- }
-}
-
-/* Counting of objects in slavic languages such as Russian and Ukrainian the
- * rules are more complicated. There are two plural forms used in counting.
- * They are the genative singular which we represent with the suffix "x1" and
- * the genative plural which we represent with the suffix "x2". The base names
- * of the soundfiles remain in English. For example:
- * 1 degree (soudfile says "gradus")
- * 2 degreex1 (soundfile says "gradusa")
- * 5 degreex2 (soundfile says "gradusov")
- */
-static const char *counted_noun_ending_slavic(int num)
-{
- if (num < 0) {
- num *= -1;
- }
- num %= 100; /* never pay attention to more than two digits */
- if (num >= 20) { /* for numbers 20 and above, pay attention to only last digit */
- num %= 10;
- }
- if (num == 1) { /* singular */
- return "";
- }
- if (num > 0 && num < 5) { /* 2--5 get genative singular */
- return "x1";
- } else { /* 5--19 get genative plural */
- return "x2";
- }
-}
-
-int ast_say_counted_noun(struct ast_channel *chan, int num, const char noun[])
-{
- char *temp;
- int temp_len;
- const char *ending;
- if (!strcasecmp(chan->language, "ru")) { /* Russian */
- ending = counted_noun_ending_slavic(num);
- } else if(!strcasecmp(chan->language, "ua")) { /* Ukrainian */
- ending = counted_noun_ending_slavic(num);
- } else if(!strcasecmp(chan->language, "ua")) { /* Polish */
- ending = counted_noun_ending_slavic(num);
- } else { /* English and default */
- ending = counted_noun_ending_en(num);
- }
- temp = alloca((temp_len = (strlen(noun) + strlen(ending) + 1)));
- snprintf(temp, temp_len, "%s%s", noun, ending);
- return ast_play_and_wait(chan, temp);
-}
-
-/*
- * In slavic languages such as Russian and Ukrainian the rules for declining
- * adjectives are simpler than those for nouns. When counting we use only
- * the singular (to which we give no suffix) and the genative plural (which
- * we represent by adding an "x"). Oh, an in the singular gender matters
- * so we append the supplied gender suffix ("m", "f", "n").
- */
-static const char *counted_adjective_ending_ru(int num, const char gender[])
-{
- if (num < 0) {
- num *= -1;
- }
- num %= 100; /* never pay attention to more than two digits */
- if (num >= 20) { /* at 20 and beyond only the last digit matters */
- num %= 10;
- }
- if (num == 1) {
- return gender ? gender : "";
- } else { /* all other numbers get the genative plural */
- return "x";
- }
-}
-
-int ast_say_counted_adjective(struct ast_channel *chan, int num, const char adjective[], const char gender[])
-{
- char *temp;
- int temp_len;
- const char *ending;
- if (!strcasecmp(chan->language, "ru")) { /* Russian */
- ending = counted_adjective_ending_ru(num, gender);
- } else if (!strcasecmp(chan->language, "ua")) { /* Ukrainian */
- ending = counted_adjective_ending_ru(num, gender);
- } else if (!strcasecmp(chan->language, "pl")) { /* Polish */
- ending = counted_adjective_ending_ru(num, gender);
- } else { /* English and default */
- ending = "";
- }
- temp = alloca((temp_len = (strlen(adjective) + strlen(ending) + 1)));
- snprintf(temp, temp_len, "%s%s", adjective, ending);
- return ast_play_and_wait(chan, temp);
-}
-
-
-
-/*
- * remap the 'say' functions to use those in this file
- */
-static void __attribute__((constructor)) __say_init(void)
-{
- ast_say_number_full = say_number_full;
- ast_say_enumeration_full = say_enumeration_full;
- ast_say_digit_str_full = say_digit_str_full;
- ast_say_character_str_full = say_character_str_full;
- ast_say_phonetic_str_full = say_phonetic_str_full;
- ast_say_datetime = say_datetime;
- ast_say_time = say_time;
- ast_say_date = say_date;
- ast_say_datetime_from_now = say_datetime_from_now;
- ast_say_date_with_format = say_date_with_format;
-}
diff --git a/main/sched.c b/main/sched.c
deleted file mode 100644
index cb6098635..000000000
--- a/main/sched.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Scheduler Routines (from cheops-NG)
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#ifdef DEBUG_SCHEDULER
-#define DEBUG(a) do { \
- if (option_debug) \
- DEBUG_M(a) \
- } while (0)
-#else
-#define DEBUG(a)
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "asterisk/sched.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/lock.h"
-#include "asterisk/utils.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/options.h"
-
-struct sched {
- AST_LIST_ENTRY(sched) list;
- int id; /*!< ID number of event */
- struct timeval when; /*!< Absolute time event should take place */
- int resched; /*!< When to reschedule */
- int variable; /*!< Use return value from callback to reschedule */
- const void *data; /*!< Data */
- ast_sched_cb callback; /*!< Callback */
-};
-
-struct sched_context {
- ast_mutex_t lock;
- unsigned int eventcnt; /*!< Number of events processed */
- unsigned int schedcnt; /*!< Number of outstanding schedule events */
- AST_LIST_HEAD_NOLOCK(, sched) schedq; /*!< Schedule entry and main queue */
-
-#ifdef SCHED_MAX_CACHE
- AST_LIST_HEAD_NOLOCK(, sched) schedc; /*!< Cache of unused schedule structures and how many */
- unsigned int schedccnt;
-#endif
-};
-
-struct sched_context *sched_context_create(void)
-{
- struct sched_context *tmp;
-
- if (!(tmp = ast_calloc(1, sizeof(*tmp))))
- return NULL;
-
- ast_mutex_init(&tmp->lock);
- tmp->eventcnt = 1;
-
- return tmp;
-}
-
-void sched_context_destroy(struct sched_context *con)
-{
- struct sched *s;
-
- ast_mutex_lock(&con->lock);
-
-#ifdef SCHED_MAX_CACHE
- /* Eliminate the cache */
- while ((s = AST_LIST_REMOVE_HEAD(&con->schedc, list)))
- free(s);
-#endif
-
- /* And the queue */
- while ((s = AST_LIST_REMOVE_HEAD(&con->schedq, list)))
- free(s);
-
- /* And the context */
- ast_mutex_unlock(&con->lock);
- ast_mutex_destroy(&con->lock);
- free(con);
-}
-
-static struct sched *sched_alloc(struct sched_context *con)
-{
- struct sched *tmp;
-
- /*
- * We keep a small cache of schedule entries
- * to minimize the number of necessary malloc()'s
- */
-#ifdef SCHED_MAX_CACHE
- if ((tmp = AST_LIST_REMOVE_HEAD(&con->schedc, list)))
- con->schedccnt--;
- else
-#endif
- tmp = ast_calloc(1, sizeof(*tmp));
-
- return tmp;
-}
-
-static void sched_release(struct sched_context *con, struct sched *tmp)
-{
- /*
- * Add to the cache, or just free() if we
- * already have too many cache entries
- */
-
-#ifdef SCHED_MAX_CACHE
- if (con->schedccnt < SCHED_MAX_CACHE) {
- AST_LIST_INSERT_HEAD(&con->schedc, tmp, list);
- con->schedccnt++;
- } else
-#endif
- free(tmp);
-}
-
-/*! \brief
- * Return the number of milliseconds
- * until the next scheduled event
- */
-int ast_sched_wait(struct sched_context *con)
-{
- int ms;
-
- DEBUG(ast_log(LOG_DEBUG, "ast_sched_wait()\n"));
-
- ast_mutex_lock(&con->lock);
- if (AST_LIST_EMPTY(&con->schedq)) {
- ms = -1;
- } else {
- ms = ast_tvdiff_ms(AST_LIST_FIRST(&con->schedq)->when, ast_tvnow());
- if (ms < 0)
- ms = 0;
- }
- ast_mutex_unlock(&con->lock);
-
- return ms;
-}
-
-
-/*! \brief
- * Take a sched structure and put it in the
- * queue, such that the soonest event is
- * first in the list.
- */
-static void schedule(struct sched_context *con, struct sched *s)
-{
-
- struct sched *cur = NULL;
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&con->schedq, cur, list) {
- if (ast_tvcmp(s->when, cur->when) == -1) {
- AST_LIST_INSERT_BEFORE_CURRENT(&con->schedq, s, list);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
- if (!cur)
- AST_LIST_INSERT_TAIL(&con->schedq, s, list);
-
- con->schedcnt++;
-}
-
-/*! \brief
- * given the last event *tv and the offset in milliseconds 'when',
- * computes the next value,
- */
-static int sched_settime(struct timeval *tv, int when)
-{
- struct timeval now = ast_tvnow();
-
- /*ast_log(LOG_DEBUG, "TV -> %lu,%lu\n", tv->tv_sec, tv->tv_usec);*/
- if (ast_tvzero(*tv)) /* not supplied, default to now */
- *tv = now;
- *tv = ast_tvadd(*tv, ast_samp2tv(when, 1000));
- if (ast_tvcmp(*tv, now) < 0) {
- *tv = now;
- }
- return 0;
-}
-
-
-/*! \brief
- * Schedule callback(data) to happen when ms into the future
- */
-int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable)
-{
- struct sched *tmp;
- int res = -1;
-
- DEBUG(ast_log(LOG_DEBUG, "ast_sched_add()\n"));
-
- ast_mutex_lock(&con->lock);
- if ((tmp = sched_alloc(con))) {
- tmp->id = con->eventcnt++;
- tmp->callback = callback;
- tmp->data = data;
- tmp->resched = when;
- tmp->variable = variable;
- tmp->when = ast_tv(0, 0);
- if (sched_settime(&tmp->when, when)) {
- sched_release(con, tmp);
- } else {
- schedule(con, tmp);
- res = tmp->id;
- }
- }
-#ifdef DUMP_SCHEDULER
- /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */
- if (option_debug)
- ast_sched_dump(con);
-#endif
- ast_mutex_unlock(&con->lock);
-
- return res;
-}
-
-int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data)
-{
- return ast_sched_add_variable(con, when, callback, data, 0);
-}
-
-/*! \brief
- * Delete the schedule entry with number
- * "id". It's nearly impossible that there
- * would be two or more in the list with that
- * id.
- */
-#ifndef AST_DEVMODE
-int ast_sched_del(struct sched_context *con, int id)
-#else
-int _ast_sched_del(struct sched_context *con, int id, const char *file, int line, const char *function)
-#endif
-{
- struct sched *s;
-
- DEBUG(ast_log(LOG_DEBUG, "ast_sched_del()\n"));
-
- ast_mutex_lock(&con->lock);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&con->schedq, s, list) {
- if (s->id == id) {
- AST_LIST_REMOVE_CURRENT(&con->schedq, list);
- con->schedcnt--;
- sched_release(con, s);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END
-
-#ifdef DUMP_SCHEDULER
- /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */
- if (option_debug)
- ast_sched_dump(con);
-#endif
- ast_mutex_unlock(&con->lock);
-
- if (!s) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Attempted to delete nonexistent schedule entry %d!\n", id);
-#ifndef AST_DEVMODE
- ast_assert(s != NULL);
-#else
- _ast_assert(0, "s != NULL", file, line, function);
-#endif
- return -1;
- }
-
- return 0;
-}
-
-/*! \brief Dump the contents of the scheduler to LOG_DEBUG */
-void ast_sched_dump(const struct sched_context *con)
-{
- struct sched *q;
- struct timeval tv = ast_tvnow();
-#ifdef SCHED_MAX_CACHE
- ast_log(LOG_DEBUG, "Asterisk Schedule Dump (%d in Q, %d Total, %d Cache)\n", con->schedcnt, con->eventcnt - 1, con->schedccnt);
-#else
- ast_log(LOG_DEBUG, "Asterisk Schedule Dump (%d in Q, %d Total)\n", con->schedcnt, con->eventcnt - 1);
-#endif
-
- ast_log(LOG_DEBUG, "=============================================================\n");
- ast_log(LOG_DEBUG, "|ID Callback Data Time (sec:ms) |\n");
- ast_log(LOG_DEBUG, "+-----+-----------------+-----------------+-----------------+\n");
- AST_LIST_TRAVERSE(&con->schedq, q, list) {
- struct timeval delta = ast_tvsub(q->when, tv);
-
- ast_log(LOG_DEBUG, "|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n",
- q->id,
- q->callback,
- q->data,
- delta.tv_sec,
- (long int)delta.tv_usec);
- }
- ast_log(LOG_DEBUG, "=============================================================\n");
-
-}
-
-/*! \brief
- * Launch all events which need to be run at this time.
- */
-int ast_sched_runq(struct sched_context *con)
-{
- struct sched *current;
- struct timeval tv;
- int numevents;
- int res;
-
- DEBUG(ast_log(LOG_DEBUG, "ast_sched_runq()\n"));
-
- ast_mutex_lock(&con->lock);
-
- for (numevents = 0; !AST_LIST_EMPTY(&con->schedq); numevents++) {
- /* schedule all events which are going to expire within 1ms.
- * We only care about millisecond accuracy anyway, so this will
- * help us get more than one event at one time if they are very
- * close together.
- */
- tv = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
- if (ast_tvcmp(AST_LIST_FIRST(&con->schedq)->when, tv) != -1)
- break;
-
- current = AST_LIST_REMOVE_HEAD(&con->schedq, list);
- con->schedcnt--;
-
- /*
- * At this point, the schedule queue is still intact. We
- * have removed the first event and the rest is still there,
- * so it's permissible for the callback to add new events, but
- * trying to delete itself won't work because it isn't in
- * the schedule queue. If that's what it wants to do, it
- * should return 0.
- */
-
- ast_mutex_unlock(&con->lock);
- res = current->callback(current->data);
- ast_mutex_lock(&con->lock);
-
- if (res) {
- /*
- * If they return non-zero, we should schedule them to be
- * run again.
- */
- if (sched_settime(&current->when, current->variable? res : current->resched)) {
- sched_release(con, current);
- } else
- schedule(con, current);
- } else {
- /* No longer needed, so release it */
- sched_release(con, current);
- }
- }
-
- ast_mutex_unlock(&con->lock);
-
- return numevents;
-}
-
-long ast_sched_when(struct sched_context *con,int id)
-{
- struct sched *s;
- long secs = -1;
- DEBUG(ast_log(LOG_DEBUG, "ast_sched_when()\n"));
-
- ast_mutex_lock(&con->lock);
- AST_LIST_TRAVERSE(&con->schedq, s, list) {
- if (s->id == id)
- break;
- }
- if (s) {
- struct timeval now = ast_tvnow();
- secs = s->when.tv_sec - now.tv_sec;
- }
- ast_mutex_unlock(&con->lock);
-
- return secs;
-}
diff --git a/main/sha1.c b/main/sha1.c
deleted file mode 100644
index 16ddd6aa3..000000000
--- a/main/sha1.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- *
- * Based on the RFC 3174
- *
- * Full Copyright Statement
- *
- * Copyright (C) The Internet Society (2001). All Rights Reserved.
- *
- * This document and translations of it may be copied and furnished to
- * others, and derivative works that comment on or otherwise explain it
- * or assist in its implementation may be prepared, copied, published
- * and distributed, in whole or in part, without restriction of any
- * kind, provided that the above copyright notice and this paragraph are
- * included on all such copies and derivative works. However, this
- * document itself may not be modified in any way, such as by removing
- * the copyright notice or references to the Internet Society or other
- * Internet organizations, except as needed for the purpose of
- * developing Internet standards in which case the procedures for
- * copyrights defined in the Internet Standards process must be
- * followed, or as required to translate it into languages other than
- * English.
- *
- * The limited permissions granted above are perpetual and will not be
- * revoked by the Internet Society or its successors or assigns.
-
- * This document and the information contained herein is provided on an
- * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
- * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- *
- *
- * Description:
- * This file implements the Secure Hashing Algorithm 1 as
- * defined in FIPS PUB 180-1 published April 17, 1995.
- *
- * The SHA-1, produces a 160-bit message digest for a given
- * data stream. It should take about 2**n steps to find a
- * message with the same digest as a given message and
- * 2**(n/2) to find any two messages with the same digest,
- * when n is the digest size in bits. Therefore, this
- * algorithm can serve as a means of providing a
- * "fingerprint" for a message.
- *
- * Portability Issues:
- * SHA-1 is defined in terms of 32-bit "words". This code
- * uses <stdint.h> (included via "sha1.h" to define 32 and 8
- * bit unsigned integer types. If your C compiler does not
- * support 32 bit unsigned integers, this code is not
- * appropriate.
- *
- * Caveats:
- * SHA-1 is designed to work with messages less than 2^64 bits
- * long. Although SHA-1 allows a message digest to be generated
- * for messages of any number of bits less than 2^64, this
- * implementation only works with messages with a length that is
- * a multiple of the size of an 8-bit character.
- *
- */
-
-
-#include "asterisk/sha1.h"
-
-/*
- * Define the SHA1 circular left shift macro
- */
-#define SHA1CircularShift(bits,word) \
- (((word) << (bits)) | ((word) >> (32-(bits))))
-
-/* Local Function Prototyptes */
-void SHA1PadMessage(SHA1Context *);
-void SHA1ProcessMessageBlock(SHA1Context *);
-
-/*
- * SHA1Reset
- *
- * Description:
- * This function will initialize the SHA1Context in preparation
- * for computing a new SHA1 message digest.
- *
- * Parameters:
- * context: [in/out]
- * The context to reset.
- *
- * Returns:
- * sha Error Code.
- *
- */
-int SHA1Reset(SHA1Context *context)
-{
- if (!context) {
- return shaNull;
- }
-
- context->Length_Low = 0;
- context->Length_High = 0;
- context->Message_Block_Index = 0;
-
- context->Intermediate_Hash[0] = 0x67452301;
- context->Intermediate_Hash[1] = 0xEFCDAB89;
- context->Intermediate_Hash[2] = 0x98BADCFE;
- context->Intermediate_Hash[3] = 0x10325476;
- context->Intermediate_Hash[4] = 0xC3D2E1F0;
-
- context->Computed = 0;
- context->Corrupted = 0;
-
- return shaSuccess;
-}
-
-/*
- * SHA1Result
- *
- * Description:
- * This function will return the 160-bit message digest into the
- * Message_Digest array provided by the caller.
- * NOTE: The first octet of hash is stored in the 0th element,
- * the last octet of hash in the 19th element.
- *
- * Parameters:
- * context: [in/out]
- * The context to use to calculate the SHA-1 hash.
- * Message_Digest: [out]
- * Where the digest is returned.
- *
- * Returns:
- * sha Error Code.
- *
- */
-int SHA1Result( SHA1Context *context,
- uint8_t Message_Digest[SHA1HashSize])
-{
- int i;
-
- if (!context || !Message_Digest) {
- return shaNull;
- }
-
- if (context->Corrupted) {
- return context->Corrupted;
- }
-
- if (!context->Computed) {
- SHA1PadMessage(context);
- for (i = 0; i < 64; ++i) {
- /* message may be sensitive, clear it out */
- context->Message_Block[i] = 0;
- }
- context->Length_Low = 0; /* and clear length */
- context->Length_High = 0;
- context->Computed = 1;
- }
-
- for (i = 0; i < SHA1HashSize; ++i) {
- Message_Digest[i] = context->Intermediate_Hash[i >> 2] >> 8 * ( 3 - ( i & 0x03 ) );
- }
-
- return shaSuccess;
-}
-
-/*
- * SHA1Input
- *
- * Description:
- * This function accepts an array of octets as the next portion
- * of the message.
- *
- * Parameters:
- * context: [in/out]
- * The SHA context to update
- * message_array: [in]
- * An array of characters representing the next portion of
- * the message.
- * length: [in]
- * The length of the message in message_array
- *
- * Returns:
- * sha Error Code.
- *
- */
-int SHA1Input(SHA1Context *context, const uint8_t *message_array, unsigned length)
-{
- if (!length) {
- return shaSuccess;
- }
-
- if (!context || !message_array) {
- return shaNull;
- }
-
- if (context->Computed) {
- context->Corrupted = shaStateError;
- return shaStateError;
- }
-
- if (context->Corrupted) {
- return context->Corrupted;
- }
-
- while (length-- && !context->Corrupted) {
- context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);
-
- context->Length_Low += 8;
- if (context->Length_Low == 0) {
- context->Length_High++;
- if (context->Length_High == 0) {
- /* Message is too long */
- context->Corrupted = 1;
- }
- }
-
- if (context->Message_Block_Index == 64) {
- SHA1ProcessMessageBlock(context);
- }
-
- message_array++;
- }
-
- return shaSuccess;
-}
-
-/*
- * SHA1ProcessMessageBlock
- *
- * Description:
- * This function will process the next 512 bits of the message
- * stored in the Message_Block array.
- *
- * Parameters:
- * None.
- *
- * Returns:
- * Nothing.
- *
- * Comments:
- * Many of the variable names in this code, especially the
- * single character names, were used because those were the
- * names used in the publication.
- *
- *
- */
-void SHA1ProcessMessageBlock(SHA1Context *context)
-{
- const uint32_t K[] = { /* Constants defined in SHA-1 */
- 0x5A827999,
- 0x6ED9EBA1,
- 0x8F1BBCDC,
- 0xCA62C1D6
- };
- int t; /* Loop counter */
- uint32_t temp; /* Temporary word value */
- uint32_t W[80]; /* Word sequence */
- uint32_t A, B, C, D, E; /* Word buffers */
-
- /*
- * Initialize the first 16 words in the array W
- */
- for (t = 0; t < 16; t++) {
- W[t] = context->Message_Block[t * 4] << 24;
- W[t] |= context->Message_Block[t * 4 + 1] << 16;
- W[t] |= context->Message_Block[t * 4 + 2] << 8;
- W[t] |= context->Message_Block[t * 4 + 3];
- }
-
- for (t = 16; t < 80; t++) {
- W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
- }
-
- A = context->Intermediate_Hash[0];
- B = context->Intermediate_Hash[1];
- C = context->Intermediate_Hash[2];
- D = context->Intermediate_Hash[3];
- E = context->Intermediate_Hash[4];
-
- for (t = 0; t < 20; t++) {
- temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
- E = D;
- D = C;
- C = SHA1CircularShift(30,B);
- B = A;
- A = temp;
- }
-
- for (t = 20; t < 40; t++) {
- temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
- E = D;
- D = C;
- C = SHA1CircularShift(30,B);
- B = A;
- A = temp;
- }
-
- for (t = 40; t < 60; t++) {
- temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
- E = D;
- D = C;
- C = SHA1CircularShift(30,B);
- B = A;
- A = temp;
- }
-
- for (t = 60; t < 80; t++) {
- temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
- E = D;
- D = C;
- C = SHA1CircularShift(30,B);
- B = A;
- A = temp;
- }
-
- context->Intermediate_Hash[0] += A;
- context->Intermediate_Hash[1] += B;
- context->Intermediate_Hash[2] += C;
- context->Intermediate_Hash[3] += D;
- context->Intermediate_Hash[4] += E;
-
- context->Message_Block_Index = 0;
-}
-
-
-/*
- * SHA1PadMessage
- *
- * Description:
- * According to the standard, the message must be padded to an even
- * 512 bits. The first padding bit must be a '1'. The last 64
- * bits represent the length of the original message. All bits in
- * between should be 0. This function will pad the message
- * according to those rules by filling the Message_Block array
- * accordingly. It will also call the ProcessMessageBlock function
- * provided appropriately. When it returns, it can be assumed that
- * the message digest has been computed.
- *
- * Parameters:
- * context: [in/out]
- * The context to pad
- * ProcessMessageBlock: [in]
- * The appropriate SHA*ProcessMessageBlock function
- * Returns:
- * Nothing.
- *
- */
-
-void SHA1PadMessage(SHA1Context *context)
-{
- /*
- * Check to see if the current message block is too small to hold
- * the initial padding bits and length. If so, we will pad the
- * block, process it, and then continue padding into a second
- * block.
- */
- if (context->Message_Block_Index > 55) {
- context->Message_Block[context->Message_Block_Index++] = 0x80;
- while (context->Message_Block_Index < 64) {
- context->Message_Block[context->Message_Block_Index++] = 0;
- }
-
- SHA1ProcessMessageBlock(context);
-
- while (context->Message_Block_Index < 56) {
- context->Message_Block[context->Message_Block_Index++] = 0;
- }
- } else {
- context->Message_Block[context->Message_Block_Index++] = 0x80;
- while (context->Message_Block_Index < 56) {
- context->Message_Block[context->Message_Block_Index++] = 0;
- }
- }
-
- /*
- * Store the message length as the last 8 octets
- */
- context->Message_Block[56] = context->Length_High >> 24;
- context->Message_Block[57] = context->Length_High >> 16;
- context->Message_Block[58] = context->Length_High >> 8;
- context->Message_Block[59] = context->Length_High;
- context->Message_Block[60] = context->Length_Low >> 24;
- context->Message_Block[61] = context->Length_Low >> 16;
- context->Message_Block[62] = context->Length_Low >> 8;
- context->Message_Block[63] = context->Length_Low;
-
- SHA1ProcessMessageBlock(context);
-}
diff --git a/main/slinfactory.c b/main/slinfactory.c
deleted file mode 100644
index bd5b8de4f..000000000
--- a/main/slinfactory.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2005, Anthony Minessale II.
- *
- * Anthony Minessale <anthmct@yahoo.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief A machine to gather up arbitrary frames and convert them
- * to raw slinear on demand.
- *
- * \author Anthony Minessale <anthmct@yahoo.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <string.h>
-
-#include "asterisk/frame.h"
-#include "asterisk/slinfactory.h"
-#include "asterisk/logger.h"
-#include "asterisk/translate.h"
-
-void ast_slinfactory_init(struct ast_slinfactory *sf)
-{
- memset(sf, 0, sizeof(*sf));
- sf->offset = sf->hold;
-}
-
-void ast_slinfactory_destroy(struct ast_slinfactory *sf)
-{
- struct ast_frame *f;
-
- if (sf->trans) {
- ast_translator_free_path(sf->trans);
- sf->trans = NULL;
- }
-
- while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
- ast_frfree(f);
-}
-
-int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
-{
- struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
- unsigned int x;
-
- if (f->subclass != AST_FORMAT_SLINEAR) {
- if (sf->trans && f->subclass != sf->format) {
- ast_translator_free_path(sf->trans);
- sf->trans = NULL;
- }
-
- if (!sf->trans) {
- if ((sf->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, f->subclass)) == NULL) {
- ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f->subclass));
- return 0;
- } else {
- sf->format = f->subclass;
- }
- }
-
- if (!(begin_frame = ast_translate(sf->trans, f, 0)))
- return 0;
-
- duped_frame = ast_frdup(begin_frame);
-
- ast_frfree(begin_frame);
-
- if (!duped_frame)
- return 0;
- } else {
- if (!(duped_frame = ast_frdup(f)))
- return 0;
- }
-
- x = 0;
- AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list)
- x++;
-
- AST_LIST_INSERT_TAIL(&sf->queue, duped_frame, frame_list);
-
- sf->size += duped_frame->samples;
-
- return x;
-}
-
-int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
-{
- struct ast_frame *frame_ptr;
- unsigned int sofar = 0, ineed, remain;
- short *frame_data, *offset = buf;
-
- while (sofar < samples) {
- ineed = samples - sofar;
-
- if (sf->holdlen) {
- if (sf->holdlen <= ineed) {
- memcpy(offset, sf->hold, sf->holdlen * sizeof(*offset));
- sofar += sf->holdlen;
- offset += sf->holdlen;
- sf->holdlen = 0;
- sf->offset = sf->hold;
- } else {
- remain = sf->holdlen - ineed;
- memcpy(offset, sf->offset, ineed * sizeof(*offset));
- sofar += ineed;
- sf->offset += ineed;
- sf->holdlen = remain;
- }
- continue;
- }
-
- if ((frame_ptr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
- frame_data = frame_ptr->data;
-
- if (frame_ptr->samples <= ineed) {
- memcpy(offset, frame_data, frame_ptr->samples * sizeof(*offset));
- sofar += frame_ptr->samples;
- offset += frame_ptr->samples;
- } else {
- remain = frame_ptr->samples - ineed;
- memcpy(offset, frame_data, ineed * sizeof(*offset));
- sofar += ineed;
- frame_data += ineed;
- if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
- remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
- }
- memcpy(sf->hold, frame_data, remain * sizeof(*offset));
- sf->holdlen = remain;
- }
- ast_frfree(frame_ptr);
- } else {
- break;
- }
- }
-
- sf->size -= sofar;
- return sofar;
-}
-
-unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
-{
- return sf->size;
-}
-
-void ast_slinfactory_flush(struct ast_slinfactory *sf)
-{
- struct ast_frame *fr = NULL;
-
- if (sf->trans) {
- ast_translator_free_path(sf->trans);
- sf->trans = NULL;
- }
-
- while ((fr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
- ast_frfree(fr);
-
- sf->size = sf->holdlen = 0;
- sf->offset = sf->hold;
-
- return;
-}
diff --git a/main/srv.c b/main/srv.c
deleted file mode 100644
index cf99ef3ec..000000000
--- a/main/srv.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * Funding provided by nic.at
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief DNS SRV Record Lookup Support for Asterisk
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * \arg See also \ref AstENUM
- *
- * \note Funding provided by nic.at
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#if __APPLE_CC__ >= 1495
-#include <arpa/nameser_compat.h>
-#endif
-#include <resolv.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/srv.h"
-#include "asterisk/dns.h"
-#include "asterisk/options.h"
-#include "asterisk/utils.h"
-#include "asterisk/linkedlists.h"
-
-#ifdef __APPLE__
-#undef T_SRV
-#define T_SRV 33
-#endif
-
-struct srv_entry {
- unsigned short priority;
- unsigned short weight;
- unsigned short port;
- unsigned int weight_sum;
- AST_LIST_ENTRY(srv_entry) list;
- char host[1];
-};
-
-struct srv_context {
- unsigned int have_weights:1;
- AST_LIST_HEAD_NOLOCK(srv_entries, srv_entry) entries;
-};
-
-static int parse_srv(unsigned char *answer, int len, unsigned char *msg, struct srv_entry **result)
-{
- struct srv {
- unsigned short priority;
- unsigned short weight;
- unsigned short port;
- } __attribute__((__packed__)) *srv = (struct srv *) answer;
-
- int res = 0;
- char repl[256] = "";
- struct srv_entry *entry;
-
- if (len < sizeof(*srv))
- return -1;
-
- answer += sizeof(*srv);
- len -= sizeof(*srv);
-
- if ((res = dn_expand(msg, answer + len, answer, repl, sizeof(repl) - 1)) <= 0) {
- ast_log(LOG_WARNING, "Failed to expand hostname\n");
- return -1;
- }
-
- /* the magic value "." for the target domain means that this service
- is *NOT* available at the domain we searched */
- if (!strcmp(repl, "."))
- return -1;
-
- if (!(entry = ast_calloc(1, sizeof(*entry) + strlen(repl))))
- return -1;
-
- entry->priority = ntohs(srv->priority);
- entry->weight = ntohs(srv->weight);
- entry->port = ntohs(srv->port);
- strcpy(entry->host, repl);
-
- *result = entry;
-
- return 0;
-}
-
-static int srv_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
-{
- struct srv_context *c = (struct srv_context *) context;
- struct srv_entry *entry = NULL;
- struct srv_entry *current;
-
- if (parse_srv(answer, len, fullanswer, &entry))
- return -1;
-
- if (entry->weight)
- c->have_weights = 1;
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&c->entries, current, list) {
- /* insert this entry just before the first existing
- entry with a higher priority */
- if (current->priority <= entry->priority)
- continue;
-
- AST_LIST_INSERT_BEFORE_CURRENT(&c->entries, entry, list);
- entry = NULL;
- break;
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- /* if we didn't find a place to insert the entry before an existing
- entry, then just add it to the end */
- if (entry)
- AST_LIST_INSERT_TAIL(&c->entries, entry, list);
-
- return 1;
-}
-
-/* Do the bizarre SRV record weight-handling algorithm
- involving sorting and random number generation...
-
- See RFC 2782 if you want know why this code does this
-*/
-static void process_weights(struct srv_context *context)
-{
- struct srv_entry *current;
- struct srv_entries newlist = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
-
- while (AST_LIST_FIRST(&context->entries)) {
- unsigned int random_weight;
- unsigned int weight_sum;
- unsigned short cur_priority = AST_LIST_FIRST(&context->entries)->priority;
- struct srv_entries temp_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
- weight_sum = 0;
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&context->entries, current, list) {
- if (current->priority != cur_priority)
- break;
-
- AST_LIST_REMOVE_CURRENT(&context->entries, list);
- AST_LIST_INSERT_TAIL(&temp_list, current, list);
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- while (AST_LIST_FIRST(&temp_list)) {
- weight_sum = 0;
- AST_LIST_TRAVERSE(&temp_list, current, list)
- current->weight_sum = weight_sum += current->weight;
-
- /* if all the remaining entries have weight == 0,
- then just append them to the result list and quit */
- if (weight_sum == 0) {
- AST_LIST_APPEND_LIST(&newlist, &temp_list, list);
- break;
- }
-
- random_weight = 1 + (unsigned int) ((float) weight_sum * (ast_random() / ((float) RAND_MAX + 1.0)));
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(&temp_list, current, list) {
- if (current->weight < random_weight)
- continue;
-
- AST_LIST_REMOVE_CURRENT(&temp_list, list);
- AST_LIST_INSERT_TAIL(&newlist, current, list);
- break;
- }
- AST_LIST_TRAVERSE_SAFE_END;
- }
-
- }
-
- /* now that the new list has been ordered,
- put it in place */
-
- AST_LIST_APPEND_LIST(&context->entries, &newlist, list);
-}
-
-int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
-{
- struct srv_context context = { .entries = AST_LIST_HEAD_NOLOCK_INIT_VALUE };
- struct srv_entry *current;
- int ret;
-
- if (chan && ast_autoservice_start(chan) < 0)
- return -1;
-
- ret = ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
-
- if (context.have_weights)
- process_weights(&context);
-
- if (chan)
- ret |= ast_autoservice_stop(chan);
-
- /* TODO: there could be a "." entry in the returned list of
- answers... if so, this requires special handling */
-
- /* the list of entries will be sorted in the proper selection order
- already, so we just need the first one (if any) */
-
- if ((ret > 0) && (current = AST_LIST_REMOVE_HEAD(&context.entries, list))) {
- ast_copy_string(host, current->host, hostlen);
- *port = current->port;
- ast_free(current);
- if (option_verbose > 3) {
- ast_verbose(VERBOSE_PREFIX_3 "ast_get_srv: SRV lookup for '%s' mapped to host %s, port %d\n",
- service, host, *port);
- }
- } else {
- host[0] = '\0';
- *port = -1;
- }
-
- while ((current = AST_LIST_REMOVE_HEAD(&context.entries, list)))
- ast_free(current);
-
- return ret;
-}
diff --git a/main/stdtime/Makefile b/main/stdtime/Makefile
deleted file mode 100644
index d4b7f0093..000000000
--- a/main/stdtime/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-OBJS=localtime.o
-
-all: libtime.a
-
-libtime.a: $(OBJS)
- ar rv $@ $(OBJS)
- ranlib $@
-
-install:
-
-uninstall:
-
-clean-depend:
- rm -f .depend
-
-clean: clean-depend
- rm -f libtime.a *.o test *.i
-
-depend: .depend
-
-.depend:
- ../build_tools/mkdep $(CFLAGS) *.c
-
-test: test.c
- ${CC} ${CFLAGS} -o test test.c
-
-ifneq ($(wildcard .depend),)
-include .depend
-endif
diff --git a/main/stdtime/localtime.c b/main/stdtime/localtime.c
deleted file mode 100644
index 75968f787..000000000
--- a/main/stdtime/localtime.c
+++ /dev/null
@@ -1,1651 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * Most of this code is in the public domain, so clarified as of
- * June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
- *
- * All modifications to this code to abstract timezones away from
- * the environment are by Tilghman Lesher, <tlesher@vcch.com>, with
- * the copyright assigned to Digium.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * Multi-timezone Localtime code
- *
- * The original source from this file may be obtained from ftp://elsie.nci.nih.gov/pub/
- */
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-
-/*
-** Leap second handling from Bradley White.
-** POSIX-style TZ environment variable handling from Guy Harris.
-*/
-
-/* #define DEBUG */
-
-/*LINTLIBRARY*/
-
-#include "asterisk.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#ifdef DEBUG
-#include <stdio.h>
-#endif
-#include <float.h>
-
-
-#include "private.h"
-#include "tzfile.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/lock.h"
-#include "asterisk/localtime.h"
-#include "asterisk/strings.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/utils.h"
-
-#ifndef lint
-#ifndef NOID
-static char __attribute__((unused)) elsieid[] = "@(#)localtime.c 8.5";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-#ifndef TZ_ABBR_MAX_LEN
-#define TZ_ABBR_MAX_LEN 16
-#endif /* !defined TZ_ABBR_MAX_LEN */
-
-#ifndef TZ_ABBR_CHAR_SET
-#define TZ_ABBR_CHAR_SET \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
-#endif /* !defined TZ_ABBR_CHAR_SET */
-
-#ifndef TZ_ABBR_ERR_CHAR
-#define TZ_ABBR_ERR_CHAR '_'
-#endif /* !defined TZ_ABBR_ERR_CHAR */
-
-/*
-** SunOS 4.1.1 headers lack O_BINARY.
-*/
-
-#ifdef O_BINARY
-#define OPEN_MODE (O_RDONLY | O_BINARY)
-#endif /* defined O_BINARY */
-#ifndef O_BINARY
-#define OPEN_MODE O_RDONLY
-#endif /* !defined O_BINARY */
-
-static const char gmt[] = "GMT";
-
-/*! \note
- * The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
- * We default to US rules as of 1999-08-17.
- * POSIX 1003.1 section 8.1.1 says that the default DST rules are
- * implementation dependent; for historical reasons, US rules are a
- * common default.
- */
-#ifndef TZDEFRULESTRING
-#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
-#endif /* !defined TZDEFDST */
-
-#ifndef WRONG
-#define WRONG (-1)
-#endif /* !defined WRONG */
-
-/*!< \brief time type information */
-struct ttinfo { /* time type information */
- long tt_gmtoff; /* UTC offset in seconds */
- int tt_isdst; /* used to set tm_isdst */
- int tt_abbrind; /* abbreviation list index */
- int tt_ttisstd; /* TRUE if transition is std time */
- int tt_ttisgmt; /* TRUE if transition is UTC */
-};
-
-/*! \brief leap second information */
-struct lsinfo { /* leap second information */
- time_t ls_trans; /* transition time */
- long ls_corr; /* correction to apply */
-};
-
-#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
-
-#ifdef TZNAME_MAX
-#define MY_TZNAME_MAX TZNAME_MAX
-#endif /* defined TZNAME_MAX */
-#ifndef TZNAME_MAX
-#define MY_TZNAME_MAX 255
-#endif /* !defined TZNAME_MAX */
-#ifndef TZ_STRLEN_MAX
-#define TZ_STRLEN_MAX 255
-#endif /* !defined TZ_STRLEN_MAX */
-
-struct state {
- /*! Name of the file that this references */
- char name[TZ_STRLEN_MAX + 1];
- int leapcnt;
- int timecnt;
- int typecnt;
- int charcnt;
- int goback;
- int goahead;
- time_t ats[TZ_MAX_TIMES];
- unsigned char types[TZ_MAX_TIMES];
- struct ttinfo ttis[TZ_MAX_TYPES];
- char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
- (2 * (MY_TZNAME_MAX + 1)))];
- struct lsinfo lsis[TZ_MAX_LEAPS];
- AST_LIST_ENTRY(state) list;
-};
-
-struct rule {
- int r_type; /* type of rule--see below */
- int r_day; /* day number of rule */
- int r_week; /* week number of rule */
- int r_mon; /* month number of rule */
- long r_time; /* transition time of rule */
-};
-
-#define JULIAN_DAY 0 /* Jn - Julian day */
-#define DAY_OF_YEAR 1 /* n - day of year */
-#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
-
-/*
-** Prototypes for static functions.
-*/
-
-static long detzcode P((const char * codep));
-static time_t detzcode64 P((const char * codep));
-static int differ_by_repeat P((time_t t1, time_t t0));
-static const char * getzname P((const char * strp));
-static const char * getqzname P((const char * strp, const int delim));
-static const char * getnum P((const char * strp, int * nump, int min,
- int max));
-static const char * getsecs P((const char * strp, long * secsp));
-static const char * getoffset P((const char * strp, long * offsetp));
-static const char * getrule P((const char * strp, struct rule * rulep));
-static int gmtload P((struct state * sp));
-static struct tm * gmtsub P((const time_t * timep, long offset,
- struct tm * tmp));
-static struct tm * localsub P((const time_t * timep, long offset,
- struct tm * tmp, const struct state *sp));
-static int increment_overflow P((int * number, int delta));
-static int leaps_thru_end_of P((int y));
-static int long_increment_overflow P((long * number, int delta));
-static int long_normalize_overflow P((long * tensptr,
- int * unitsptr, const int base));
-static int normalize_overflow P((int * tensptr, int * unitsptr,
- const int base));
-static time_t time1 P((struct tm * tmp,
- struct tm * (*funcp) P((const time_t *,
- long, struct tm *, const struct state *sp)),
- long offset, const struct state *sp));
-static time_t time2 P((struct tm *tmp,
- struct tm * (*funcp) P((const time_t *,
- long, struct tm*, const struct state *sp)),
- long offset, int * okayp, const struct state *sp));
-static time_t time2sub P((struct tm *tmp,
- struct tm * (*funcp) (const time_t *,
- long, struct tm*, const struct state *sp),
- long offset, int * okayp, int do_norm_secs, const struct state *sp));
-static struct tm * timesub P((const time_t * timep, long offset,
- const struct state * sp, struct tm * tmp));
-static int tmcomp P((const struct tm * atmp,
- const struct tm * btmp));
-static time_t transtime P((time_t janfirst, int year,
- const struct rule * rulep, long offset));
-static int tzload P((const char * name, struct state * sp,
- int doextend));
-static int tzparse P((const char * name, struct state * sp,
- int lastditch));
-
-static AST_LIST_HEAD_STATIC(zonelist, state);
-
-#ifndef TZ_STRLEN_MAX
-#define TZ_STRLEN_MAX 255
-#endif /* !defined TZ_STRLEN_MAX */
-
-/*! \note
-** Section 4.12.3 of X3.159-1989 requires that
-** Except for the strftime function, these functions [asctime,
-** ctime, gmtime, localtime] return values in one of two static
-** objects: a broken-down time structure and an array of char.
-** Thanks to Paul Eggert for noting this.
-*/
-
-static long detzcode(const char * const codep)
-{
- long result;
- int i;
-
- result = (codep[0] & 0x80) ? ~0L : 0;
- for (i = 0; i < 4; ++i)
- result = (result << 8) | (codep[i] & 0xff);
- return result;
-}
-
-static time_t detzcode64(const char * const codep)
-{
- time_t result;
- int i;
-
- result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
- for (i = 0; i < 8; ++i)
- result = result * 256 + (codep[i] & 0xff);
- return result;
-}
-
-static int differ_by_repeat(const time_t t1, const time_t t0)
-{
- const long long at1 = t1, at0 = t0;
- if (TYPE_INTEGRAL(time_t) &&
- TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
- return 0;
- return at1 - at0 == SECSPERREPEAT;
-}
-
-static int tzload(const char *name, struct state * const sp, const int doextend)
-{
- const char * p;
- int i;
- int fid;
- int stored;
- int nread;
- union {
- struct tzhead tzhead;
- char buf[2 * sizeof(struct tzhead) +
- 2 * sizeof *sp +
- 4 * TZ_MAX_TIMES];
- } u;
-
- if (name == NULL && (name = TZDEFAULT) == NULL)
- return WRONG;
- {
- int doaccess;
- /*
- ** Section 4.9.1 of the C standard says that
- ** "FILENAME_MAX expands to an integral constant expression
- ** that is the size needed for an array of char large enough
- ** to hold the longest file name string that the implementation
- ** guarantees can be opened."
- */
- char fullname[FILENAME_MAX + 1];
-
- if (name[0] == ':')
- ++name;
- doaccess = name[0] == '/';
- if (!doaccess) {
- if ((p = TZDIR) == NULL)
- return WRONG;
- if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
- return WRONG;
- (void) strcpy(fullname, p);
- (void) strcat(fullname, "/");
- (void) strcat(fullname, name);
- /*
- ** Set doaccess if '.' (as in "../") shows up in name.
- */
- if (strchr(name, '.') != NULL)
- doaccess = TRUE;
- name = fullname;
- }
- if (doaccess && access(name, R_OK) != 0)
- return WRONG;
- if ((fid = open(name, OPEN_MODE)) == -1)
- return WRONG;
- }
- nread = read(fid, u.buf, sizeof u.buf);
- if (close(fid) < 0 || nread <= 0)
- return WRONG;
- for (stored = 4; stored <= 8; stored *= 2) {
- int ttisstdcnt;
- int ttisgmtcnt;
-
- ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
- ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
- sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
- sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
- sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
- sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
- p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
- if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
- sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
- sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
- sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
- (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
- (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
- return WRONG;
- if (nread - (p - u.buf) <
- sp->timecnt * stored + /* ats */
- sp->timecnt + /* types */
- sp->typecnt * 6 + /* ttinfos */
- sp->charcnt + /* chars */
- sp->leapcnt * (stored + 4) + /* lsinfos */
- ttisstdcnt + /* ttisstds */
- ttisgmtcnt) /* ttisgmts */
- return WRONG;
- for (i = 0; i < sp->timecnt; ++i) {
- sp->ats[i] = (stored == 4) ?
- detzcode(p) : detzcode64(p);
- p += stored;
- }
- for (i = 0; i < sp->timecnt; ++i) {
- sp->types[i] = (unsigned char) *p++;
- if (sp->types[i] >= sp->typecnt)
- return WRONG;
- }
- for (i = 0; i < sp->typecnt; ++i) {
- struct ttinfo * ttisp;
-
- ttisp = &sp->ttis[i];
- ttisp->tt_gmtoff = detzcode(p);
- p += 4;
- ttisp->tt_isdst = (unsigned char) *p++;
- if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
- return WRONG;
- ttisp->tt_abbrind = (unsigned char) *p++;
- if (ttisp->tt_abbrind < 0 ||
- ttisp->tt_abbrind > sp->charcnt)
- return WRONG;
- }
- for (i = 0; i < sp->charcnt; ++i)
- sp->chars[i] = *p++;
- sp->chars[i] = '\0'; /* ensure '\0' at end */
- for (i = 0; i < sp->leapcnt; ++i) {
- struct lsinfo * lsisp;
-
- lsisp = &sp->lsis[i];
- lsisp->ls_trans = (stored == 4) ?
- detzcode(p) : detzcode64(p);
- p += stored;
- lsisp->ls_corr = detzcode(p);
- p += 4;
- }
- for (i = 0; i < sp->typecnt; ++i) {
- struct ttinfo * ttisp;
-
- ttisp = &sp->ttis[i];
- if (ttisstdcnt == 0)
- ttisp->tt_ttisstd = FALSE;
- else {
- ttisp->tt_ttisstd = *p++;
- if (ttisp->tt_ttisstd != TRUE &&
- ttisp->tt_ttisstd != FALSE)
- return WRONG;
- }
- }
- for (i = 0; i < sp->typecnt; ++i) {
- struct ttinfo * ttisp;
-
- ttisp = &sp->ttis[i];
- if (ttisgmtcnt == 0)
- ttisp->tt_ttisgmt = FALSE;
- else {
- ttisp->tt_ttisgmt = *p++;
- if (ttisp->tt_ttisgmt != TRUE &&
- ttisp->tt_ttisgmt != FALSE)
- return WRONG;
- }
- }
- /*
- ** Out-of-sort ats should mean we're running on a
- ** signed time_t system but using a data file with
- ** unsigned values (or vice versa).
- */
- for (i = 0; i < sp->timecnt - 2; ++i)
- if (sp->ats[i] > sp->ats[i + 1]) {
- ++i;
- if (TYPE_SIGNED(time_t)) {
- /*
- ** Ignore the end (easy).
- */
- sp->timecnt = i;
- } else {
- /*
- ** Ignore the beginning (harder).
- */
- int j;
-
- for (j = 0; j + i < sp->timecnt; ++j) {
- sp->ats[j] = sp->ats[j + i];
- sp->types[j] = sp->types[j + i];
- }
- sp->timecnt = j;
- }
- break;
- }
- /*
- ** If this is an old file, we're done.
- */
- if (u.tzhead.tzh_version[0] == '\0')
- break;
- nread -= p - u.buf;
- for (i = 0; i < nread; ++i)
- u.buf[i] = p[i];
- /*
- ** If this is a narrow integer time_t system, we're done.
- */
- if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
- break;
- }
- if (doextend && nread > 2 &&
- u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
- sp->typecnt + 2 <= TZ_MAX_TYPES) {
- struct state ts;
- int result;
-
- u.buf[nread - 1] = '\0';
- result = tzparse(&u.buf[1], &ts, FALSE);
- if (result == 0 && ts.typecnt == 2 &&
- sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
- for (i = 0; i < 2; ++i)
- ts.ttis[i].tt_abbrind +=
- sp->charcnt;
- for (i = 0; i < ts.charcnt; ++i)
- sp->chars[sp->charcnt++] =
- ts.chars[i];
- i = 0;
- while (i < ts.timecnt &&
- ts.ats[i] <=
- sp->ats[sp->timecnt - 1])
- ++i;
- while (i < ts.timecnt &&
- sp->timecnt < TZ_MAX_TIMES) {
- sp->ats[sp->timecnt] =
- ts.ats[i];
- sp->types[sp->timecnt] =
- sp->typecnt +
- ts.types[i];
- ++sp->timecnt;
- ++i;
- }
- sp->ttis[sp->typecnt++] = ts.ttis[0];
- sp->ttis[sp->typecnt++] = ts.ttis[1];
- }
- }
- i = 2 * YEARSPERREPEAT;
- sp->goback = sp->goahead = sp->timecnt > i;
- sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
- differ_by_repeat(sp->ats[i], sp->ats[0]);
- sp->goahead = sp->goahead &&
- sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
- differ_by_repeat(sp->ats[sp->timecnt - 1],
- sp->ats[sp->timecnt - 1 - i]);
- return 0;
-}
-
-static const int mon_lengths[2][MONSPERYEAR] = {
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
-};
-
-static const int year_lengths[2] = {
- DAYSPERNYEAR, DAYSPERLYEAR
-};
-
-/*! \brief
-** Given a pointer into a time zone string, scan until a character that is not
-** a valid character in a zone name is found. Return a pointer to that
-** character.
-*/
-
-static const char * getzname(const char *strp)
-{
- char c;
-
- while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
- c != '+')
- ++strp;
- return strp;
-}
-
-/*! \brief
-** Given a pointer into an extended time zone string, scan until the ending
-** delimiter of the zone name is located. Return a pointer to the delimiter.
-**
-** As with getzname above, the legal character set is actually quite
-** restricted, with other characters producing undefined results.
-** We don't do any checking here; checking is done later in common-case code.
-*/
-
-static const char * getqzname(const char *strp, const int delim)
-{
- int c;
-
- while ((c = *strp) != '\0' && c != delim)
- ++strp;
- return strp;
-}
-
-/*! \brief
-** Given a pointer into a time zone string, extract a number from that string.
-** Check that the number is within a specified range; if it is not, return
-** NULL.
-** Otherwise, return a pointer to the first character not part of the number.
-*/
-
-static const char *getnum(const char *strp, int *nump, const int min, const int max)
-{
- char c;
- int num;
-
- if (strp == NULL || !is_digit(c = *strp))
- return NULL;
- num = 0;
- do {
- num = num * 10 + (c - '0');
- if (num > max)
- return NULL; /* illegal value */
- c = *++strp;
- } while (is_digit(c));
- if (num < min)
- return NULL; /* illegal value */
- *nump = num;
- return strp;
-}
-
-/*! \brief
-** Given a pointer into a time zone string, extract a number of seconds,
-** in hh[:mm[:ss]] form, from the string.
-** If any error occurs, return NULL.
-** Otherwise, return a pointer to the first character not part of the number
-** of seconds.
-*/
-
-static const char *getsecs(const char *strp, long * const secsp)
-{
- int num;
-
- /*
- ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
- ** "M10.4.6/26", which does not conform to Posix,
- ** but which specifies the equivalent of
- ** ``02:00 on the first Sunday on or after 23 Oct''.
- */
- strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
- if (strp == NULL)
- return NULL;
- *secsp = num * (long) SECSPERHOUR;
- if (*strp == ':') {
- ++strp;
- strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
- if (strp == NULL)
- return NULL;
- *secsp += num * SECSPERMIN;
- if (*strp == ':') {
- ++strp;
- /* `SECSPERMIN' allows for leap seconds. */
- strp = getnum(strp, &num, 0, SECSPERMIN);
- if (strp == NULL)
- return NULL;
- *secsp += num;
- }
- }
- return strp;
-}
-
-/*! \brief
-** Given a pointer into a time zone string, extract an offset, in
-** [+-]hh[:mm[:ss]] form, from the string.
-** If any error occurs, return NULL.
-** Otherwise, return a pointer to the first character not part of the time.
-*/
-
-static const char *getoffset(const char *strp, long *offsetp)
-{
- int neg = 0;
-
- if (*strp == '-') {
- neg = 1;
- ++strp;
- } else if (*strp == '+')
- ++strp;
- strp = getsecs(strp, offsetp);
- if (strp == NULL)
- return NULL; /* illegal time */
- if (neg)
- *offsetp = -*offsetp;
- return strp;
-}
-
-/*! \brief
-** Given a pointer into a time zone string, extract a rule in the form
-** date[/time]. See POSIX section 8 for the format of "date" and "time".
-** If a valid rule is not found, return NULL.
-** Otherwise, return a pointer to the first character not part of the rule.
-*/
-
-static const char *getrule(const char *strp, struct rule *rulep)
-{
- if (*strp == 'J') {
- /*
- ** Julian day.
- */
- rulep->r_type = JULIAN_DAY;
- ++strp;
- strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
- } else if (*strp == 'M') {
- /*
- ** Month, week, day.
- */
- rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
- ++strp;
- strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
- if (strp == NULL)
- return NULL;
- if (*strp++ != '.')
- return NULL;
- strp = getnum(strp, &rulep->r_week, 1, 5);
- if (strp == NULL)
- return NULL;
- if (*strp++ != '.')
- return NULL;
- strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
- } else if (is_digit(*strp)) {
- /*
- ** Day of year.
- */
- rulep->r_type = DAY_OF_YEAR;
- strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
- } else return NULL; /* invalid format */
- if (strp == NULL)
- return NULL;
- if (*strp == '/') {
- /*
- ** Time specified.
- */
- ++strp;
- strp = getsecs(strp, &rulep->r_time);
- } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
- return strp;
-}
-
-/*! \brief
-** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
-** year, a rule, and the offset from UTC at the time that rule takes effect,
-** calculate the Epoch-relative time that rule takes effect.
-*/
-
-static time_t transtime(const time_t janfirst, const int year, const struct rule *rulep, const long offset)
-{
- int leapyear;
- time_t value;
- int i;
- int d, m1, yy0, yy1, yy2, dow;
-
- INITIALIZE(value);
- leapyear = isleap(year);
- switch (rulep->r_type) {
-
- case JULIAN_DAY:
- /*
- ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
- ** years.
- ** In non-leap years, or if the day number is 59 or less, just
- ** add SECSPERDAY times the day number-1 to the time of
- ** January 1, midnight, to get the day.
- */
- value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
- if (leapyear && rulep->r_day >= 60)
- value += SECSPERDAY;
- break;
-
- case DAY_OF_YEAR:
- /*
- ** n - day of year.
- ** Just add SECSPERDAY times the day number to the time of
- ** January 1, midnight, to get the day.
- */
- value = janfirst + rulep->r_day * SECSPERDAY;
- break;
-
- case MONTH_NTH_DAY_OF_WEEK:
- /*
- ** Mm.n.d - nth "dth day" of month m.
- */
- value = janfirst;
- for (i = 0; i < rulep->r_mon - 1; ++i)
- value += mon_lengths[leapyear][i] * SECSPERDAY;
-
- /*
- ** Use Zeller's Congruence to get day-of-week of first day of
- ** month.
- */
- m1 = (rulep->r_mon + 9) % 12 + 1;
- yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
- yy1 = yy0 / 100;
- yy2 = yy0 % 100;
- dow = ((26 * m1 - 2) / 10 +
- 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
- if (dow < 0)
- dow += DAYSPERWEEK;
-
- /*
- ** "dow" is the day-of-week of the first day of the month. Get
- ** the day-of-month (zero-origin) of the first "dow" day of the
- ** month.
- */
- d = rulep->r_day - dow;
- if (d < 0)
- d += DAYSPERWEEK;
- for (i = 1; i < rulep->r_week; ++i) {
- if (d + DAYSPERWEEK >=
- mon_lengths[leapyear][rulep->r_mon - 1])
- break;
- d += DAYSPERWEEK;
- }
-
- /*
- ** "d" is the day-of-month (zero-origin) of the day we want.
- */
- value += d * SECSPERDAY;
- break;
- }
-
- /*
- ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
- ** question. To get the Epoch-relative time of the specified local
- ** time on that day, add the transition time and the current offset
- ** from UTC.
- */
- return value + rulep->r_time + offset;
-}
-
-/*! \note
-** Given a POSIX section 8-style TZ string, fill in the rule tables as
-** appropriate.
-*/
-
-static int tzparse(const char *name, struct state *sp, const int lastditch)
-{
- const char * stdname;
- const char * dstname;
- size_t stdlen;
- size_t dstlen;
- long stdoffset;
- long dstoffset;
- time_t * atp;
- unsigned char * typep;
- char * cp;
- int load_result;
-
- INITIALIZE(dstname);
- stdname = name;
- if (lastditch) {
- stdlen = strlen(name); /* length of standard zone name */
- name += stdlen;
- if (stdlen >= sizeof sp->chars)
- stdlen = (sizeof sp->chars) - 1;
- stdoffset = 0;
- } else {
- if (*name == '<') {
- name++;
- stdname = name;
- name = getqzname(name, '>');
- if (*name != '>')
- return WRONG;
- stdlen = name - stdname;
- name++;
- } else {
- name = getzname(name);
- stdlen = name - stdname;
- }
- if (*name == '\0')
- return WRONG;
- name = getoffset(name, &stdoffset);
- if (name == NULL)
- return WRONG;
- }
- load_result = tzload(TZDEFRULES, sp, FALSE);
- if (load_result != 0)
- sp->leapcnt = 0; /* so, we're off a little */
- if (*name != '\0') {
- if (*name == '<') {
- dstname = ++name;
- name = getqzname(name, '>');
- if (*name != '>')
- return WRONG;
- dstlen = name - dstname;
- name++;
- } else {
- dstname = name;
- name = getzname(name);
- dstlen = name - dstname; /* length of DST zone name */
- }
- if (*name != '\0' && *name != ',' && *name != ';') {
- name = getoffset(name, &dstoffset);
- if (name == NULL)
- return WRONG;
- } else dstoffset = stdoffset - SECSPERHOUR;
- if (*name == '\0' && load_result != 0)
- name = TZDEFRULESTRING;
- if (*name == ',' || *name == ';') {
- struct rule start;
- struct rule end;
- int year;
- time_t janfirst;
- time_t starttime;
- time_t endtime;
-
- ++name;
- if ((name = getrule(name, &start)) == NULL)
- return WRONG;
- if (*name++ != ',')
- return WRONG;
- if ((name = getrule(name, &end)) == NULL)
- return WRONG;
- if (*name != '\0')
- return WRONG;
- sp->typecnt = 2; /* standard time and DST */
- /*
- ** Two transitions per year, from EPOCH_YEAR forward.
- */
- sp->ttis[0].tt_gmtoff = -dstoffset;
- sp->ttis[0].tt_isdst = 1;
- sp->ttis[0].tt_abbrind = stdlen + 1;
- sp->ttis[1].tt_gmtoff = -stdoffset;
- sp->ttis[1].tt_isdst = 0;
- sp->ttis[1].tt_abbrind = 0;
- atp = sp->ats;
- typep = sp->types;
- janfirst = 0;
- sp->timecnt = 0;
- for (year = EPOCH_YEAR;
- sp->timecnt + 2 <= TZ_MAX_TIMES;
- ++year) {
- time_t newfirst;
-
- starttime = transtime(janfirst, year, &start,
- stdoffset);
- endtime = transtime(janfirst, year, &end,
- dstoffset);
- if (starttime > endtime) {
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- } else {
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
- }
- sp->timecnt += 2;
- newfirst = janfirst;
- newfirst += year_lengths[isleap(year)] *
- SECSPERDAY;
- if (newfirst <= janfirst)
- break;
- janfirst = newfirst;
- }
- } else {
- long theirstdoffset;
- long theirdstoffset;
- long theiroffset;
- int isdst;
- int i;
- int j;
-
- if (*name != '\0')
- return WRONG;
- /*
- ** Initial values of theirstdoffset and theirdstoffset.
- */
- theirstdoffset = 0;
- for (i = 0; i < sp->timecnt; ++i) {
- j = sp->types[i];
- if (!sp->ttis[j].tt_isdst) {
- theirstdoffset =
- -sp->ttis[j].tt_gmtoff;
- break;
- }
- }
- theirdstoffset = 0;
- for (i = 0; i < sp->timecnt; ++i) {
- j = sp->types[i];
- if (sp->ttis[j].tt_isdst) {
- theirdstoffset =
- -sp->ttis[j].tt_gmtoff;
- break;
- }
- }
- /*
- ** Initially we're assumed to be in standard time.
- */
- isdst = FALSE;
- theiroffset = theirstdoffset;
- /*
- ** Now juggle transition times and types
- ** tracking offsets as you do.
- */
- for (i = 0; i < sp->timecnt; ++i) {
- j = sp->types[i];
- sp->types[i] = sp->ttis[j].tt_isdst;
- if (sp->ttis[j].tt_ttisgmt) {
- /* No adjustment to transition time */
- } else {
- /*
- ** If summer time is in effect, and the
- ** transition time was not specified as
- ** standard time, add the summer time
- ** offset to the transition time;
- ** otherwise, add the standard time
- ** offset to the transition time.
- */
- /*
- ** Transitions from DST to DDST
- ** will effectively disappear since
- ** POSIX provides for only one DST
- ** offset.
- */
- if (isdst && !sp->ttis[j].tt_ttisstd) {
- sp->ats[i] += dstoffset -
- theirdstoffset;
- } else {
- sp->ats[i] += stdoffset -
- theirstdoffset;
- }
- }
- theiroffset = -sp->ttis[j].tt_gmtoff;
- if (sp->ttis[j].tt_isdst)
- theirdstoffset = theiroffset;
- else theirstdoffset = theiroffset;
- }
- /*
- ** Finally, fill in ttis.
- ** ttisstd and ttisgmt need not be handled.
- */
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = FALSE;
- sp->ttis[0].tt_abbrind = 0;
- sp->ttis[1].tt_gmtoff = -dstoffset;
- sp->ttis[1].tt_isdst = TRUE;
- sp->ttis[1].tt_abbrind = stdlen + 1;
- sp->typecnt = 2;
- }
- } else {
- dstlen = 0;
- sp->typecnt = 1; /* only standard time */
- sp->timecnt = 0;
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = 0;
- sp->ttis[0].tt_abbrind = 0;
- }
- sp->charcnt = stdlen + 1;
- if (dstlen != 0)
- sp->charcnt += dstlen + 1;
- if ((size_t) sp->charcnt > sizeof sp->chars)
- return WRONG;
- cp = sp->chars;
- (void) strncpy(cp, stdname, stdlen);
- cp += stdlen;
- *cp++ = '\0';
- if (dstlen != 0) {
- (void) strncpy(cp, dstname, dstlen);
- *(cp + dstlen) = '\0';
- }
- return 0;
-}
-
-static int gmtload(struct state *sp)
-{
- if (tzload(gmt, sp, TRUE) != 0)
- return tzparse(gmt, sp, TRUE);
- else
- return WRONG;
-}
-
-static const struct state *ast_tzset(const char *zone)
-{
- struct state *sp;
-
- if (ast_strlen_zero(zone))
- zone = "/etc/localtime";
-
- AST_LIST_LOCK(&zonelist);
- AST_LIST_TRAVERSE(&zonelist, sp, list) {
- if (!strcmp(sp->name, zone)) {
- AST_LIST_UNLOCK(&zonelist);
- return sp;
- }
- }
- AST_LIST_UNLOCK(&zonelist);
-
- if (!(sp = ast_calloc(1, sizeof *sp)))
- return NULL;
-
- if (tzload(zone, sp, TRUE) != 0) {
- if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
- (void) gmtload(sp);
- }
- ast_copy_string(sp->name, zone, sizeof(sp->name));
- AST_LIST_LOCK(&zonelist);
- AST_LIST_INSERT_TAIL(&zonelist, sp, list);
- AST_LIST_UNLOCK(&zonelist);
- return sp;
-}
-
-/*! \note
-** The easy way to behave "as if no library function calls" localtime
-** is to not call it--so we drop its guts into "localsub", which can be
-** freely called. (And no, the PANS doesn't require the above behavior--
-** but it *is* desirable.)
-**
-** The unused offset argument is for the benefit of mktime variants.
-*/
-
-static struct tm *localsub(const time_t *timep, const long offset, struct tm *tmp, const struct state *sp)
-{
- const struct ttinfo * ttisp;
- int i;
- struct tm * result;
- const time_t t = *timep;
-
- if (sp == NULL)
- return gmtsub(timep, offset, tmp);
- if ((sp->goback && t < sp->ats[0]) ||
- (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
- time_t newt = t;
- time_t seconds;
- time_t tcycles;
- int_fast64_t icycles;
-
- if (t < sp->ats[0])
- seconds = sp->ats[0] - t;
- else seconds = t - sp->ats[sp->timecnt - 1];
- --seconds;
- tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
- ++tcycles;
- icycles = tcycles;
- if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
- return NULL;
- seconds = icycles;
- seconds *= YEARSPERREPEAT;
- seconds *= AVGSECSPERYEAR;
- if (t < sp->ats[0])
- newt += seconds;
- else newt -= seconds;
- if (newt < sp->ats[0] ||
- newt > sp->ats[sp->timecnt - 1])
- return NULL; /* "cannot happen" */
- result = localsub(&newt, offset, tmp, sp);
- if (result == tmp) {
- time_t newy;
-
- newy = tmp->tm_year;
- if (t < sp->ats[0])
- newy -= icycles * YEARSPERREPEAT;
- else
- newy += icycles * YEARSPERREPEAT;
- tmp->tm_year = newy;
- if (tmp->tm_year != newy)
- return NULL;
- }
- return result;
- }
- if (sp->timecnt == 0 || t < sp->ats[0]) {
- i = 0;
- while (sp->ttis[i].tt_isdst) {
- if (++i >= sp->typecnt) {
- i = 0;
- break;
- }
- }
- } else {
- int lo = 1;
- int hi = sp->timecnt;
-
- while (lo < hi) {
- int mid = (lo + hi) >> 1;
-
- if (t < sp->ats[mid])
- hi = mid;
- else
- lo = mid + 1;
- }
- i = (int) sp->types[lo - 1];
- }
- ttisp = &sp->ttis[i];
- /*
- ** To get (wrong) behavior that's compatible with System V Release 2.0
- ** you'd replace the statement below with
- ** t += ttisp->tt_gmtoff;
- ** timesub(&t, 0L, sp, tmp);
- */
- result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
- tmp->tm_isdst = ttisp->tt_isdst;
-#ifndef SOLARIS /* Solaris doesn't have this element */
- tmp->tm_gmtoff = ttisp->tt_gmtoff;
-#endif
-#ifdef TM_ZONE
- tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
-#endif /* defined TM_ZONE */
- return result;
-}
-
-struct tm *ast_localtime(const time_t *timep, struct tm *tmp, const char *zone)
-{
- const struct state *sp = ast_tzset(zone);
- memset(tmp, 0, sizeof(*tmp));
- return sp ? localsub(timep, 0L, tmp, sp) : NULL;
-}
-
-/*
-** gmtsub is to gmtime as localsub is to localtime.
-*/
-
-static struct tm *gmtsub(const time_t *timep, const long offset, struct tm *tmp)
-{
- struct tm * result;
- struct state *sp;
-
- AST_LIST_LOCK(&zonelist);
- AST_LIST_TRAVERSE(&zonelist, sp, list) {
- if (!strcmp(sp->name, "UTC"))
- break;
- }
-
- if (!sp) {
- if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
- return NULL;
- gmtload(sp);
- AST_LIST_INSERT_TAIL(&zonelist, sp, list);
- }
- AST_LIST_UNLOCK(&zonelist);
-
- result = timesub(timep, offset, sp, tmp);
-#ifdef TM_ZONE
- /*
- ** Could get fancy here and deliver something such as
- ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
- ** but this is no time for a treasure hunt.
- */
- if (offset != 0)
- tmp->TM_ZONE = " ";
- else
- tmp->TM_ZONE = sp->chars;
-#endif /* defined TM_ZONE */
- return result;
-}
-
-/*! \brief
-** Return the number of leap years through the end of the given year
-** where, to make the math easy, the answer for year zero is defined as zero.
-*/
-
-static int leaps_thru_end_of(const int y)
-{
- return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
- -(leaps_thru_end_of(-(y + 1)) + 1);
-}
-
-static struct tm *timesub(const time_t *timep, const long offset, const struct state *sp, struct tm *tmp)
-{
- const struct lsinfo * lp;
- time_t tdays;
- int idays; /* unsigned would be so 2003 */
- long rem;
- int y;
- const int * ip;
- long corr;
- int hit;
- int i;
- long seconds;
-
-
- corr = 0;
- hit = 0;
- i = (sp == NULL) ? 0 : sp->leapcnt;
- while (--i >= 0) {
- lp = &sp->lsis[i];
- if (*timep >= lp->ls_trans) {
- if (*timep == lp->ls_trans) {
- hit = ((i == 0 && lp->ls_corr > 0) ||
- lp->ls_corr > sp->lsis[i - 1].ls_corr);
- if (hit)
- while (i > 0 &&
- sp->lsis[i].ls_trans ==
- sp->lsis[i - 1].ls_trans + 1 &&
- sp->lsis[i].ls_corr ==
- sp->lsis[i - 1].ls_corr + 1) {
- ++hit;
- --i;
- }
- }
- corr = lp->ls_corr;
- break;
- }
- }
- y = EPOCH_YEAR;
- tdays = *timep / SECSPERDAY;
- rem = *timep - tdays * SECSPERDAY;
- while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
- int newy;
- time_t tdelta;
- int idelta;
- int leapdays;
-
- tdelta = tdays / DAYSPERLYEAR;
- idelta = tdelta;
- if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
- return NULL;
- if (idelta == 0)
- idelta = (tdays < 0) ? -1 : 1;
- newy = y;
- if (increment_overflow(&newy, idelta))
- return NULL;
- leapdays = leaps_thru_end_of(newy - 1) -
- leaps_thru_end_of(y - 1);
- tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
- tdays -= leapdays;
- y = newy;
- }
-
- seconds = tdays * SECSPERDAY + 0.5;
- tdays = seconds / SECSPERDAY;
- rem += seconds - tdays * SECSPERDAY;
-
- /*
- ** Given the range, we can now fearlessly cast...
- */
- idays = tdays;
- rem += offset - corr;
- while (rem < 0) {
- rem += SECSPERDAY;
- --idays;
- }
- while (rem >= SECSPERDAY) {
- rem -= SECSPERDAY;
- ++idays;
- }
- while (idays < 0) {
- if (increment_overflow(&y, -1))
- return NULL;
- idays += year_lengths[isleap(y)];
- }
- while (idays >= year_lengths[isleap(y)]) {
- idays -= year_lengths[isleap(y)];
- if (increment_overflow(&y, 1))
- return NULL;
- }
- tmp->tm_year = y;
- if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
- return NULL;
- tmp->tm_yday = idays;
- /*
- ** The "extra" mods below avoid overflow problems.
- */
- tmp->tm_wday = EPOCH_WDAY +
- ((y - EPOCH_YEAR) % DAYSPERWEEK) *
- (DAYSPERNYEAR % DAYSPERWEEK) +
- leaps_thru_end_of(y - 1) -
- leaps_thru_end_of(EPOCH_YEAR - 1) +
- idays;
- tmp->tm_wday %= DAYSPERWEEK;
- if (tmp->tm_wday < 0)
- tmp->tm_wday += DAYSPERWEEK;
- tmp->tm_hour = (int) (rem / SECSPERHOUR);
- rem %= SECSPERHOUR;
- tmp->tm_min = (int) (rem / SECSPERMIN);
- /*
- ** A positive leap second requires a special
- ** representation. This uses "... ??:59:60" et seq.
- */
- tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
- ip = mon_lengths[isleap(y)];
- for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
- idays -= ip[tmp->tm_mon];
- tmp->tm_mday = (int) (idays + 1);
- tmp->tm_isdst = 0;
-#ifdef TM_GMTOFF
- tmp->TM_GMTOFF = offset;
-#endif /* defined TM_GMTOFF */
- return tmp;
-}
-
-/*! \note
-** Adapted from code provided by Robert Elz, who writes:
-** The "best" way to do mktime I think is based on an idea of Bob
-** Kridle's (so its said...) from a long time ago.
-** It does a binary search of the time_t space. Since time_t's are
-** just 32 bits, its a max of 32 iterations (even at 64 bits it
-** would still be very reasonable).
-*/
-
-/*! \brief
-** Simplified normalize logic courtesy Paul Eggert.
-*/
-
-static int increment_overflow(int *number, int delta)
-{
- int number0;
-
- number0 = *number;
- *number += delta;
- return (*number < number0) != (delta < 0);
-}
-
-static int long_increment_overflow(long *number, int delta)
-{
- long number0;
-
- number0 = *number;
- *number += delta;
- return (*number < number0) != (delta < 0);
-}
-
-static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
-{
- int tensdelta;
-
- tensdelta = (*unitsptr >= 0) ?
- (*unitsptr / base) :
- (-1 - (-1 - *unitsptr) / base);
- *unitsptr -= tensdelta * base;
- return increment_overflow(tensptr, tensdelta);
-}
-
-static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
-{
- int tensdelta;
-
- tensdelta = (*unitsptr >= 0) ?
- (*unitsptr / base) :
- (-1 - (-1 - *unitsptr) / base);
- *unitsptr -= tensdelta * base;
- return long_increment_overflow(tensptr, tensdelta);
-}
-
-static int tmcomp(const struct tm *atmp, const struct tm *btmp)
-{
- int result;
-
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
- (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
- (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
- (result = (atmp->tm_min - btmp->tm_min)) == 0)
- result = atmp->tm_sec - btmp->tm_sec;
- return result;
-}
-
-static time_t time2sub(struct tm *tmp, struct tm * (* const funcp) (const time_t *, long, struct tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp)
-{
- int dir;
- int i, j;
- int saved_seconds;
- long li;
- time_t lo;
- time_t hi;
- long y;
- time_t newt;
- time_t t;
- struct tm yourtm, mytm;
-
- *okayp = FALSE;
- yourtm = *tmp;
- if (do_norm_secs) {
- if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
- SECSPERMIN))
- return WRONG;
- }
- if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
- return WRONG;
- if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
- return WRONG;
- y = yourtm.tm_year;
- if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
- return WRONG;
- /*
- ** Turn y into an actual year number for now.
- ** It is converted back to an offset from TM_YEAR_BASE later.
- */
- if (long_increment_overflow(&y, TM_YEAR_BASE))
- return WRONG;
- while (yourtm.tm_mday <= 0) {
- if (long_increment_overflow(&y, -1))
- return WRONG;
- li = y + (1 < yourtm.tm_mon);
- yourtm.tm_mday += year_lengths[isleap(li)];
- }
- while (yourtm.tm_mday > DAYSPERLYEAR) {
- li = y + (1 < yourtm.tm_mon);
- yourtm.tm_mday -= year_lengths[isleap(li)];
- if (long_increment_overflow(&y, 1))
- return WRONG;
- }
- for ( ; ; ) {
- i = mon_lengths[isleap(y)][yourtm.tm_mon];
- if (yourtm.tm_mday <= i)
- break;
- yourtm.tm_mday -= i;
- if (++yourtm.tm_mon >= MONSPERYEAR) {
- yourtm.tm_mon = 0;
- if (long_increment_overflow(&y, 1))
- return WRONG;
- }
- }
- if (long_increment_overflow(&y, -TM_YEAR_BASE))
- return WRONG;
- yourtm.tm_year = y;
- if (yourtm.tm_year != y)
- return WRONG;
- if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
- saved_seconds = 0;
- else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
- /*
- ** We can't set tm_sec to 0, because that might push the
- ** time below the minimum representable time.
- ** Set tm_sec to 59 instead.
- ** This assumes that the minimum representable time is
- ** not in the same minute that a leap second was deleted from,
- ** which is a safer assumption than using 58 would be.
- */
- if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
- return WRONG;
- saved_seconds = yourtm.tm_sec;
- yourtm.tm_sec = SECSPERMIN - 1;
- } else {
- saved_seconds = yourtm.tm_sec;
- yourtm.tm_sec = 0;
- }
- /*
- ** Do a binary search (this works whatever time_t's type is).
- */
- if (!TYPE_SIGNED(time_t)) {
- lo = 0;
- hi = lo - 1;
- } else if (!TYPE_INTEGRAL(time_t)) {
- if (sizeof(time_t) > sizeof(float))
- hi = (time_t) DBL_MAX;
- else hi = (time_t) FLT_MAX;
- lo = -hi;
- } else {
- lo = 1;
- for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
- lo *= 2;
- hi = -(lo + 1);
- }
- for ( ; ; ) {
- t = lo / 2 + hi / 2;
- if (t < lo)
- t = lo;
- else if (t > hi)
- t = hi;
- if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
- /*
- ** Assume that t is too extreme to be represented in
- ** a struct tm; arrange things so that it is less
- ** extreme on the next pass.
- */
- dir = (t > 0) ? 1 : -1;
- } else dir = tmcomp(&mytm, &yourtm);
- if (dir != 0) {
- if (t == lo) {
- ++t;
- if (t <= lo)
- return WRONG;
- ++lo;
- } else if (t == hi) {
- --t;
- if (t >= hi)
- return WRONG;
- --hi;
- }
- if (lo > hi)
- return WRONG;
- if (dir > 0)
- hi = t;
- else lo = t;
- continue;
- }
- if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
- break;
- /*
- ** Right time, wrong type.
- ** Hunt for right time, right type.
- ** It's okay to guess wrong since the guess
- ** gets checked.
- */
- /*
- ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
- */
- for (i = sp->typecnt - 1; i >= 0; --i) {
- if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
- continue;
- for (j = sp->typecnt - 1; j >= 0; --j) {
- if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
- continue;
- newt = t + sp->ttis[j].tt_gmtoff -
- sp->ttis[i].tt_gmtoff;
- if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
- continue;
- if (tmcomp(&mytm, &yourtm) != 0)
- continue;
- if (mytm.tm_isdst != yourtm.tm_isdst)
- continue;
- /*
- ** We have a match.
- */
- t = newt;
- goto label;
- }
- }
- return WRONG;
- }
-label:
- newt = t + saved_seconds;
- if ((newt < t) != (saved_seconds < 0))
- return WRONG;
- t = newt;
- if ((*funcp)(&t, offset, tmp, sp))
- *okayp = TRUE;
- return t;
-}
-
-static time_t time2(struct tm *tmp, struct tm * (* const funcp) (const time_t*, long, struct tm*, const struct state *sp), const long offset, int *okayp, const struct state *sp)
-{
- time_t t;
-
- /*! \note
- ** First try without normalization of seconds
- ** (in case tm_sec contains a value associated with a leap second).
- ** If that fails, try with normalization of seconds.
- */
- t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
- return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
-}
-
-static time_t time1(struct tm *tmp, struct tm * (* const funcp) (const time_t *, long, struct tm *, const struct state *), const long offset, const struct state *sp)
-{
- time_t t;
- int samei, otheri;
- int sameind, otherind;
- int i;
- int nseen;
- int seen[TZ_MAX_TYPES];
- int types[TZ_MAX_TYPES];
- int okay;
-
- if (tmp->tm_isdst > 1)
- tmp->tm_isdst = 1;
- t = time2(tmp, funcp, offset, &okay, sp);
-#ifdef PCTS
- /*
- ** PCTS code courtesy Grant Sullivan.
- */
- if (okay)
- return t;
- if (tmp->tm_isdst < 0)
- tmp->tm_isdst = 0; /* reset to std and try again */
-#endif /* defined PCTS */
-#ifndef PCTS
- if (okay || tmp->tm_isdst < 0)
- return t;
-#endif /* !defined PCTS */
- /*
- ** We're supposed to assume that somebody took a time of one type
- ** and did some math on it that yielded a "struct tm" that's bad.
- ** We try to divine the type they started from and adjust to the
- ** type they need.
- */
- if (sp == NULL)
- return WRONG;
- for (i = 0; i < sp->typecnt; ++i)
- seen[i] = FALSE;
- nseen = 0;
- for (i = sp->timecnt - 1; i >= 0; --i)
- if (!seen[sp->types[i]]) {
- seen[sp->types[i]] = TRUE;
- types[nseen++] = sp->types[i];
- }
- for (sameind = 0; sameind < nseen; ++sameind) {
- samei = types[sameind];
- if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
- continue;
- for (otherind = 0; otherind < nseen; ++otherind) {
- otheri = types[otherind];
- if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
- continue;
- tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
- tmp->tm_isdst = !tmp->tm_isdst;
- t = time2(tmp, funcp, offset, &okay, sp);
- if (okay)
- return t;
- tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
- tmp->tm_isdst = !tmp->tm_isdst;
- }
- }
- return WRONG;
-}
-
-time_t ast_mktime(struct tm *tmp, const char *zone)
-{
- const struct state *sp;
- if (!(sp = ast_tzset(zone)))
- return 0;
- return time1(tmp, localsub, 0L, sp);
-}
-
diff --git a/main/stdtime/private.h b/main/stdtime/private.h
deleted file mode 100644
index 11793088d..000000000
--- a/main/stdtime/private.h
+++ /dev/null
@@ -1,358 +0,0 @@
-#ifndef PRIVATE_H
-
-#define PRIVATE_H
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-
-/*
-** This header is for use ONLY with the time conversion code.
-** There is no guarantee that it will remain unchanged,
-** or that it will remain at all.
-** Do NOT copy it to any system include directory.
-** Thank you!
-*/
-
-/*
-** ID
-*/
-
-#ifndef lint
-#ifndef NOID
-static char __attribute__((unused)) privatehid[] = "@(#)private.h 8.3";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-#define GRANDPARENTED "Local time zone must be set--see zic manual page"
-
-/*
-** Defaults for preprocessor symbols.
-** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
-*/
-
-#ifndef HAVE_ADJTIME
-#define HAVE_ADJTIME 1
-#endif /* !defined HAVE_ADJTIME */
-
-#ifndef HAVE_GETTEXT
-#define HAVE_GETTEXT 0
-#endif /* !defined HAVE_GETTEXT */
-
-#ifndef HAVE_INCOMPATIBLE_CTIME_R
-#define HAVE_INCOMPATIBLE_CTIME_R 0
-#endif /* !defined INCOMPATIBLE_CTIME_R */
-
-#ifndef HAVE_SETTIMEOFDAY
-#define HAVE_SETTIMEOFDAY 3
-#endif /* !defined HAVE_SETTIMEOFDAY */
-
-#ifndef HAVE_STRERROR
-#define HAVE_STRERROR 1
-#endif /* !defined HAVE_STRERROR */
-
-#ifndef HAVE_SYMLINK
-#define HAVE_SYMLINK 1
-#endif /* !defined HAVE_SYMLINK */
-
-#ifndef HAVE_SYS_STAT_H
-#define HAVE_SYS_STAT_H 1
-#endif /* !defined HAVE_SYS_STAT_H */
-
-#ifndef HAVE_SYS_WAIT_H
-#define HAVE_SYS_WAIT_H 1
-#endif /* !defined HAVE_SYS_WAIT_H */
-
-#ifndef HAVE_UNISTD_H
-#define HAVE_UNISTD_H 1
-#endif /* !defined HAVE_UNISTD_H */
-
-#ifndef HAVE_UTMPX_H
-#define HAVE_UTMPX_H 0
-#endif /* !defined HAVE_UTMPX_H */
-
-#ifndef LOCALE_HOME
-#define LOCALE_HOME "/usr/lib/locale"
-#endif /* !defined LOCALE_HOME */
-
-#if HAVE_INCOMPATIBLE_CTIME_R
-#define asctime_r _incompatible_asctime_r
-#define ctime_r _incompatible_ctime_r
-#endif /* HAVE_INCOMPATIBLE_CTIME_R */
-
-/*
-** Nested includes
-*/
-
-#include "sys/types.h" /* for time_t */
-#include "stdio.h"
-#include "errno.h"
-#include "string.h"
-#include "limits.h" /* for CHAR_BIT et al. */
-#include "time.h"
-#include "stdlib.h"
-
-#if HAVE_GETTEXT
-#include "libintl.h"
-#endif /* HAVE_GETTEXT */
-
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
-#endif /* HAVE_SYS_WAIT_H */
-
-#ifndef WIFEXITED
-#define WIFEXITED(status) (((status) & 0xff) == 0)
-#endif /* !defined WIFEXITED */
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
-#endif /* !defined WEXITSTATUS */
-
-#if HAVE_UNISTD_H
-#include "unistd.h" /* for F_OK and R_OK */
-#endif /* HAVE_UNISTD_H */
-
-#if !HAVE_UNISTD_H
-#ifndef F_OK
-#define F_OK 0
-#endif /* !defined F_OK */
-#ifndef R_OK
-#define R_OK 4
-#endif /* !defined R_OK */
-#endif /* !HAVE_UNISTD_H */
-
-/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
-#define is_digit(c) ((unsigned)(c) - '0' <= 9)
-
-/*
-** Define HAVE_STDINT_H's default value here, rather than at the
-** start, since __GLIBC__'s value depends on previously-included
-** files.
-** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
-*/
-#ifndef HAVE_STDINT_H
-#define HAVE_STDINT_H \
- (199901 <= __STDC_VERSION__ || \
- 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
-#endif /* !defined HAVE_STDINT_H */
-
-#if HAVE_STDINT_H
-#include "stdint.h"
-#endif /* !HAVE_STDINT_H */
-
-#ifndef INT_FAST64_MAX
-/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
-#if defined LLONG_MAX || defined __LONG_LONG_MAX__
-typedef long long int_fast64_t;
-#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
-#if (LONG_MAX >> 31) < 0xffffffff
-Please use a compiler that supports a 64-bit integer type (or wider);
-you may need to compile with "-DHAVE_STDINT_H".
-#endif /* (LONG_MAX >> 31) < 0xffffffff */
-typedef long int_fast64_t;
-#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
-#endif /* !defined INT_FAST64_MAX */
-
-#ifndef INT32_MAX
-#define INT32_MAX 0x7fffffff
-#endif /* !defined INT32_MAX */
-#ifndef INT32_MIN
-#define INT32_MIN (-1 - INT32_MAX)
-#endif /* !defined INT32_MIN */
-
-/*
-** Workarounds for compilers/systems.
-*/
-
-/*
-** If your compiler lacks prototypes, "#define P(x) ()".
-*/
-
-#ifndef P
-#define P(x) x
-#endif /* !defined P */
-
-/*
-** SunOS 4.1.1 headers lack EXIT_SUCCESS.
-*/
-
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif /* !defined EXIT_SUCCESS */
-
-/*
-** SunOS 4.1.1 headers lack EXIT_FAILURE.
-*/
-
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif /* !defined EXIT_FAILURE */
-
-/*
-** SunOS 4.1.1 headers lack FILENAME_MAX.
-*/
-
-#ifndef FILENAME_MAX
-
-#ifndef MAXPATHLEN
-#ifdef unix
-#include "sys/param.h"
-#endif /* defined unix */
-#endif /* !defined MAXPATHLEN */
-
-#ifdef MAXPATHLEN
-#define FILENAME_MAX MAXPATHLEN
-#endif /* defined MAXPATHLEN */
-#ifndef MAXPATHLEN
-#define FILENAME_MAX 1024 /* Pure guesswork */
-#endif /* !defined MAXPATHLEN */
-
-#endif /* !defined FILENAME_MAX */
-
-/*
-** SunOS 4.1.1 libraries lack remove.
-*/
-
-#ifndef remove
-extern int unlink P((const char * filename));
-#define remove unlink
-#endif /* !defined remove */
-
-/*
-** Some ancient errno.h implementations don't declare errno.
-** But some newer errno.h implementations define it as a macro.
-** Fix the former without affecting the latter.
-*/
-
-#ifndef errno
-extern int errno;
-#endif /* !defined errno */
-
-/*
-** Private function declarations.
-*/
-
-char * icalloc P((int nelem, int elsize));
-char * icatalloc P((char * old, const char * new));
-char * icpyalloc P((const char * string));
-char * imalloc P((int n));
-void * irealloc P((void * pointer, int size));
-void icfree P((char * pointer));
-void ifree P((char * pointer));
-const char * scheck P((const char * string, const char * format));
-
-/*
-** Finally, some convenience items.
-*/
-
-#ifndef TRUE
-#define TRUE 1
-#endif /* !defined TRUE */
-
-#ifndef FALSE
-#define FALSE 0
-#endif /* !defined FALSE */
-
-#ifndef TYPE_BIT
-#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
-#endif /* !defined TYPE_BIT */
-
-#ifndef TYPE_SIGNED
-#define TYPE_SIGNED(type) (((type) -1) < 0)
-#endif /* !defined TYPE_SIGNED */
-
-/*
-** Since the definition of TYPE_INTEGRAL contains floating point numbers,
-** it cannot be used in preprocessor directives.
-*/
-
-#ifndef TYPE_INTEGRAL
-#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
-#endif /* !defined TYPE_INTEGRAL */
-
-#ifndef INT_STRLEN_MAXIMUM
-/*
-** 302 / 1000 is log10(2.0) rounded up.
-** Subtract one for the sign bit if the type is signed;
-** add one for integer division truncation;
-** add one more for a minus sign if the type is signed.
-*/
-#define INT_STRLEN_MAXIMUM(type) \
- ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
- 1 + TYPE_SIGNED(type))
-#endif /* !defined INT_STRLEN_MAXIMUM */
-
-/*
-** INITIALIZE(x)
-*/
-
-#ifndef GNUC_or_lint
-#ifdef lint
-#define GNUC_or_lint
-#endif /* defined lint */
-#ifndef lint
-#ifdef __GNUC__
-#define GNUC_or_lint
-#endif /* defined __GNUC__ */
-#endif /* !defined lint */
-#endif /* !defined GNUC_or_lint */
-
-#ifndef INITIALIZE
-#ifdef GNUC_or_lint
-#define INITIALIZE(x) ((x) = 0)
-#endif /* defined GNUC_or_lint */
-#ifndef GNUC_or_lint
-#define INITIALIZE(x)
-#endif /* !defined GNUC_or_lint */
-#endif /* !defined INITIALIZE */
-
-/*
-** For the benefit of GNU folk...
-** `_(MSGID)' uses the current locale's message library string for MSGID.
-** The default is to use gettext if available, and use MSGID otherwise.
-*/
-
-#ifndef _
-#if HAVE_GETTEXT
-#define _(msgid) gettext(msgid)
-#else /* !HAVE_GETTEXT */
-#define _(msgid) msgid
-#endif /* !HAVE_GETTEXT */
-#endif /* !defined _ */
-
-#ifndef TZ_DOMAIN
-#define TZ_DOMAIN "tz"
-#endif /* !defined TZ_DOMAIN */
-
-#if HAVE_INCOMPATIBLE_CTIME_R
-#undef asctime_r
-#undef ctime_r
-char *asctime_r P((struct tm const *, char *));
-char *ctime_r P((time_t const *, char *));
-#endif /* HAVE_INCOMPATIBLE_CTIME_R */
-
-#ifndef YEARSPERREPEAT
-#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
-#endif /* !defined YEARSPERREPEAT */
-
-/*
-** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
-*/
-
-#ifndef AVGSECSPERYEAR
-#define AVGSECSPERYEAR 31556952L
-#endif /* !defined AVGSECSPERYEAR */
-
-#ifndef SECSPERREPEAT
-#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
-#endif /* !defined SECSPERREPEAT */
-
-#ifndef SECSPERREPEAT_BITS
-#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
-#endif /* !defined SECSPERREPEAT_BITS */
-
-/*
-** UNIX was a registered trademark of The Open Group in 2003.
-*/
-
-#endif /* !defined PRIVATE_H */
diff --git a/main/stdtime/test.c b/main/stdtime/test.c
deleted file mode 100644
index 9e8ce45da..000000000
--- a/main/stdtime/test.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*! \file
- \brief Testing localtime functionality */
-
-#include "localtime.c"
-#include <sys/time.h>
-#include <stdio.h>
-
-int main(int argc, char **argv) {
- struct timeval tv;
- struct tm tm;
- char *zone[4] = { "America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles" };
- int i;
-
- gettimeofday(&tv,NULL);
-
- for (i=0;i<4;i++) {
- ast_localtime(&tv.tv_sec,&tm,zone[i]);
- printf("Localtime at %s is %04d/%02d/%02d %02d:%02d:%02d\n",zone[i],tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
- }
- return 0;
-}
diff --git a/main/stdtime/tzfile.h b/main/stdtime/tzfile.h
deleted file mode 100644
index 9201b967f..000000000
--- a/main/stdtime/tzfile.h
+++ /dev/null
@@ -1,184 +0,0 @@
-#ifndef TZFILE_H
-
-#define TZFILE_H
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-
-/*
-** This header is for use ONLY with the time conversion code.
-** There is no guarantee that it will remain unchanged,
-** or that it will remain at all.
-** Do NOT copy it to any system include directory.
-** Thank you!
-*/
-
-/*
-** ID
-*/
-
-#ifndef lint
-#ifndef NOID
-static char __attribute__((unused)) tzfilehid[] = "@(#)tzfile.h 8.1";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** Information about time zone files.
-*/
-
-#ifndef TZDIR
-#ifdef SOLARIS
-#define TZDIR "/usr/share/lib/zoneinfo"
-#else
-#define TZDIR "/usr/share/zoneinfo"
-#endif /* defined SOLARIS */
-#endif /* !defined TZDIR */
-
-#ifndef TZDEFAULT
-#define TZDEFAULT "localtime"
-#endif /* !defined TZDEFAULT */
-
-#ifndef TZDEFRULES
-#define TZDEFRULES "posixrules"
-#endif /* !defined TZDEFRULES */
-
-/*
-** Each file begins with. . .
-*/
-
-#define TZ_MAGIC "TZif"
-
-struct tzhead {
- char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_version[1]; /* '\0' or '2' as of 2005 */
- char tzh_reserved[15]; /* reserved--must be zero */
- char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
- char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
- char tzh_leapcnt[4]; /* coded number of leap seconds */
- char tzh_timecnt[4]; /* coded number of transition times */
- char tzh_typecnt[4]; /* coded number of local time types */
- char tzh_charcnt[4]; /* coded number of abbr. chars */
-};
-
-/*
-** . . .followed by. . .
-**
-** tzh_timecnt (char [4])s coded transition times a la time(2)
-** tzh_timecnt (unsigned char)s types of local time starting at above
-** tzh_typecnt repetitions of
-** one (char [4]) coded UTC offset in seconds
-** one (unsigned char) used to set tm_isdst
-** one (unsigned char) that's an abbreviation list index
-** tzh_charcnt (char)s '\0'-terminated zone abbreviations
-** tzh_leapcnt repetitions of
-** one (char [4]) coded leap second transition times
-** one (char [4]) total correction after above
-** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
-** time is standard time, if FALSE,
-** transition time is wall clock time
-** if absent, transition times are
-** assumed to be wall clock time
-** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
-** time is UTC, if FALSE,
-** transition time is local time
-** if absent, transition times are
-** assumed to be local time
-*/
-
-/*
-** If tzh_version is '2' or greater, the above is followed by a second instance
-** of tzhead and a second instance of the data in which each coded transition
-** time uses 8 rather than 4 chars,
-** then a POSIX-TZ-environment-variable-style string for use in handling
-** instants after the last transition time stored in the file
-** (with nothing between the newlines if there is no POSIX representation for
-** such instants).
-*/
-
-/*
-** In the current implementation, "tzset()" refuses to deal with files that
-** exceed any of the limits below.
-*/
-
-#ifndef TZ_MAX_TIMES
-#define TZ_MAX_TIMES 1200
-#endif /* !defined TZ_MAX_TIMES */
-
-#ifndef TZ_MAX_TYPES
-#ifndef NOSOLAR
-#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
-#endif /* !defined NOSOLAR */
-#ifdef NOSOLAR
-/*
-** Must be at least 14 for Europe/Riga as of Jan 12 1995,
-** as noted by Earl Chew.
-*/
-#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
-#endif /* !defined NOSOLAR */
-#endif /* !defined TZ_MAX_TYPES */
-
-#ifndef TZ_MAX_CHARS
-#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
- /* (limited by what unsigned chars can hold) */
-#endif /* !defined TZ_MAX_CHARS */
-
-#ifndef TZ_MAX_LEAPS
-#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
-#endif /* !defined TZ_MAX_LEAPS */
-
-#define SECSPERMIN 60
-#define MINSPERHOUR 60
-#define HOURSPERDAY 24
-#define DAYSPERWEEK 7
-#define DAYSPERNYEAR 365
-#define DAYSPERLYEAR 366
-#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
-#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
-#define MONSPERYEAR 12
-
-#define TM_SUNDAY 0
-#define TM_MONDAY 1
-#define TM_TUESDAY 2
-#define TM_WEDNESDAY 3
-#define TM_THURSDAY 4
-#define TM_FRIDAY 5
-#define TM_SATURDAY 6
-
-#define TM_JANUARY 0
-#define TM_FEBRUARY 1
-#define TM_MARCH 2
-#define TM_APRIL 3
-#define TM_MAY 4
-#define TM_JUNE 5
-#define TM_JULY 6
-#define TM_AUGUST 7
-#define TM_SEPTEMBER 8
-#define TM_OCTOBER 9
-#define TM_NOVEMBER 10
-#define TM_DECEMBER 11
-
-#define TM_YEAR_BASE 1900
-
-#define EPOCH_YEAR 1970
-#define EPOCH_WDAY TM_THURSDAY
-
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
-
-/*
-** Since everything in isleap is modulo 400 (or a factor of 400), we know that
-** isleap(y) == isleap(y % 400)
-** and so
-** isleap(a + b) == isleap((a + b) % 400)
-** or
-** isleap(a + b) == isleap(a % 400 + b % 400)
-** This is true even if % means modulo rather than Fortran remainder
-** (which is allowed by C89 but not C99).
-** We use this to avoid addition overflow problems.
-*/
-
-#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
-
-#endif /* !defined TZFILE_H */
diff --git a/main/strcompat.c b/main/strcompat.c
deleted file mode 100644
index 243ef76cb..000000000
--- a/main/strcompat.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Compatibility functions for strsep and strtoq missing on Solaris
- */
-
-#include "asterisk.h"
-
-#include <sys/types.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-
-#ifndef HAVE_STRSEP
-char *strsep(char **str, const char *delims)
-{
- char *token;
-
- if (!*str) {
- /* No more tokens */
- return NULL;
- }
-
- token = *str;
- while (**str != '\0') {
- if (strchr(delims, **str)) {
- **str = '\0';
- (*str)++;
- return token;
- }
- (*str)++;
- }
-
- /* There is no other token */
- *str = NULL;
-
- return token;
-}
-#endif
-
-#ifndef HAVE_SETENV
-int setenv(const char *name, const char *value, int overwrite)
-{
- unsigned char *buf;
- int buflen;
-
- buflen = strlen(name) + strlen(value) + 2;
- buf = alloca(buflen);
-
- if (!overwrite && getenv(name))
- return 0;
-
- snprintf(buf, buflen, "%s=%s", name, value);
-
- return putenv(buf);
-}
-#endif
-
-#ifndef HAVE_UNSETENV
-int unsetenv(const char *name)
-{
- return setenv(name, "", 0);
-}
-#endif
-
-#ifndef HAVE_STRCASESTR
-static char *upper(const char *orig, char *buf, int bufsize)
-{
- int i = 0;
-
- while (i < (bufsize - 1) && orig[i]) {
- buf[i] = toupper(orig[i]);
- i++;
- }
-
- buf[i] = '\0';
-
- return buf;
-}
-
-char *strcasestr(const char *haystack, const char *needle)
-{
- char *u1, *u2;
- int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
-
- u1 = alloca(u1len);
- u2 = alloca(u2len);
- if (u1 && u2) {
- char *offset;
- if (u2len > u1len) {
- /* Needle bigger than haystack */
- return NULL;
- }
- offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
- if (offset) {
- /* Return the offset into the original string */
- return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
- } else {
- return NULL;
- }
- } else {
- return NULL;
- }
-}
-#endif /* !HAVE_STRCASESTR */
-
-#ifndef HAVE_STRNLEN
-size_t strnlen(const char *s, size_t n)
-{
- size_t len;
-
- for (len = 0; len < n; len++)
- if (s[len] == '\0')
- break;
-
- return len;
-}
-#endif /* !HAVE_STRNLEN */
-
-#if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
-char *strndup(const char *s, size_t n)
-{
- size_t len = strnlen(s, n);
- char *new = malloc(len + 1);
-
- if (!new)
- return NULL;
-
- new[len] = '\0';
- return memcpy(new, s, len);
-}
-#endif /* !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC) */
-
-#if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
-int vasprintf(char **strp, const char *fmt, va_list ap)
-{
- int size;
- va_list ap2;
- char s;
-
- *strp = NULL;
- va_copy(ap2, ap);
- size = vsnprintf(&s, 1, fmt, ap2);
- va_end(ap2);
- *strp = malloc(size + 1);
- if (!*strp)
- return -1;
- vsnprintf(*strp, size + 1, fmt, ap);
-
- return size;
-}
-#endif /* !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
-
-/*
- * Based on Code from bsd-asprintf from OpenSSH
- * Copyright (c) 2004 Darren Tucker.
- *
- * Based originally on asprintf.c from OpenBSD:
- * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#if !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC)
-int asprintf(char **str, const char *fmt, ...)
-{
- va_list ap;
- int ret;
-
- *str = NULL;
- va_start(ap, fmt);
- ret = vasprintf(str, fmt, ap);
- va_end(ap);
-
- return ret;
-}
-#endif /* !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) */
-
-#ifndef HAVE_STRTOQ
-#ifndef LONG_MIN
-#define LONG_MIN (-9223372036854775807L-1L)
- /* min value of a "long int" */
-#endif
-#ifndef LONG_MAX
-#define LONG_MAX 9223372036854775807L
- /* max value of a "long int" */
-#endif
-
-/*! \brief
- * Convert a string to a quad integer.
- *
- * \note Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-uint64_t strtoq(const char *nptr, char **endptr, int base)
-{
- const char *s;
- uint64_t acc;
- unsigned char c;
- uint64_t qbase, cutoff;
- int neg, any, cutlim;
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- s = nptr;
- do {
- c = *s++;
- } while (isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else {
- neg = 0;
- if (c == '+')
- c = *s++;
- }
- if ((base == 0 || base == 16) &&
- c == '\0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '\0' ? 8 : 10;
-
- /*
- * Compute the cutoff value between legal numbers and illegal
- * numbers. That is the largest legal value, divided by the
- * base. An input number that is greater than this value, if
- * followed by a legal input character, is too big. One that
- * is equal to this value may be valid or not; the limit
- * between valid and invalid numbers is then based on the last
- * digit. For instance, if the range for quads is
- * [-9223372036854775808..9223372036854775807] and the input base
- * is 10, cutoff will be set to 922337203685477580 and cutlim to
- * either 7 (neg==0) or 8 (neg==1), meaning that if we have
- * accumulated a value > 922337203685477580, or equal but the
- * next digit is > 7 (or 8), the number is too big, and we will
- * return a range error.
- *
- * Set any if any `digits' consumed; make it negative to indicate
- * overflow.
- */
- qbase = (unsigned)base;
- cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
- cutlim = cutoff % qbase;
- cutoff /= qbase;
- for (acc = 0, any = 0;; c = *s++) {
- if (!isascii(c))
- break;
- if (isdigit(c))
- c -= '\0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= qbase;
- acc += c;
- }
- }
- if (any < 0) {
- acc = neg ? LONG_MIN : LONG_MAX;
- } else if (neg)
- acc = -acc;
- if (endptr != 0)
- *((const char **)endptr) = any ? s - 1 : nptr;
- return acc;
-}
-#endif /* !HAVE_STRTOQ */
-
-#ifndef HAVE_GETLOADAVG
-#ifdef linux
-/*! \brief Alternative method of getting load avg on Linux only */
-int getloadavg(double *list, int nelem)
-{
- FILE *LOADAVG;
- double avg[3] = { 0.0, 0.0, 0.0 };
- int i, res = -1;
-
- if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
- fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]);
- res = 0;
- fclose(LOADAVG);
- }
-
- for (i = 0; (i < nelem) && (i < 3); i++) {
- list[i] = avg[i];
- }
-
- return res;
-}
-#else /* !linux */
-/*! \brief Return something that won't cancel the call, but still return -1, in case
- * we correct the implementation to check return value */
-int getloadavg(double *list, int nelem)
-{
- int i;
-
- for (i = 0; i < nelem; i++) {
- list[i] = 0.1;
- }
- return -1;
-}
-#endif /* linux */
-#endif /* !HAVE_GETLOADAVG */
-
-
-/*
- * For strlcat()
- *
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Appends src to string dst of size siz (unlike strncat, siz is the
- * full size of dst, not space left). At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
- * Returns strlen(src) + MIN(siz, strlen(initial dst)).
- * If retval >= siz, truncation occurred.
- */
-#ifndef HAVE_STRLCAT
-size_t strlcat(char *dst, const char *src, size_t siz)
-{
- register char *d = dst;
- register const char *s = src;
- register size_t n = siz;
- size_t dlen;
-
- /* Find the end of dst and adjust bytes left but don't go past end */
- while (n-- != 0 && *d != '\0')
- d++;
- dlen = d - dst;
- n = siz - dlen;
-
- if (n == 0)
- return dlen + strlen(s);
-
- while (*s != '\0') {
- if (n != 1) {
- *d++ = *s;
- n--;
- }
- s++;
- }
- *d = '\0';
-
- return dlen + (s - src); /* count does not include NUL */
-}
-#endif /* HAVE_STRLCAT */
-
-/*
- * For strlcpy()
- *
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Copy src to string dst of size siz. At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- */
-#ifndef HAVE_STRLCPY
-size_t strlcpy(char *dst, const char *src, size_t siz)
-{
- register char *d = dst;
- register const char *s = src;
- register size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0 && --n != 0) {
- do {
- if ((*d++ = *s++) == 0)
- break;
- } while (--n != 0);
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0) {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
- }
-
- return s - src - 1; /* count does not include NUL */
-}
-#endif /* HAVE_STRLCPY */
diff --git a/main/tdd.c b/main/tdd.c
deleted file mode 100644
index f1d7cf471..000000000
--- a/main/tdd.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * Includes code and algorithms from the Zapata library.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief TTY/TDD Generation support
- *
- * \author Mark Spencer <markster@digium.com>
- *
- * \note Includes code and algorithms from the Zapata library.
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <time.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <math.h>
-#include <ctype.h>
-
-#include "asterisk/ulaw.h"
-#include "asterisk/tdd.h"
-#include "asterisk/logger.h"
-#include "asterisk/fskmodem.h"
-#include "ecdisa.h"
-
-struct tdd_state {
- fsk_data fskd;
- char rawdata[256];
- short oldstuff[4096];
- int oldlen;
- int pos;
- int modo;
- int mode;
- int charnum;
-};
-
-static float dr[4], di[4];
-static float tddsb = 176.0; /* 45.5 baud */
-
-#define TDD_SPACE 1800.0 /* 1800 hz for "0" */
-#define TDD_MARK 1400.0 /* 1400 hz for "1" */
-
-static int tdd_decode_baudot(struct tdd_state *tdd,unsigned char data) /* covert baudot into ASCII */
-{
- static char ltrs[32] = { '<','E','\n','A',' ','S','I','U',
- '\n','D','R','J','N','F','C','K',
- 'T','Z','L','W','H','Y','P','Q',
- 'O','B','G','^','M','X','V','^' };
- static char figs[32] = { '<','3','\n','-',' ','\'','8','7',
- '\n','$','4','\'',',','!',':','(',
- '5','\"',')','2','=','6','0','1',
- '9','?','+','^','.','/',';','^' };
- int d = 0; /* return 0 if not decodeable */
- switch (data) {
- case 0x1f:
- tdd->modo = 0;
- break;
- case 0x1b:
- tdd->modo = 1;
- break;
- default:
- if (tdd->modo == 0)
- d = ltrs[data];
- else
- d = figs[data];
- break;
- }
- return d;
-}
-
-void tdd_init(void)
-{
- /* Initialize stuff for inverse FFT */
- dr[0] = cos(TDD_SPACE * 2.0 * M_PI / 8000.0);
- di[0] = sin(TDD_SPACE * 2.0 * M_PI / 8000.0);
- dr[1] = cos(TDD_MARK * 2.0 * M_PI / 8000.0);
- di[1] = sin(TDD_MARK * 2.0 * M_PI / 8000.0);
-}
-
-struct tdd_state *tdd_new(void)
-{
- struct tdd_state *tdd;
- tdd = calloc(1, sizeof(*tdd));
- if (tdd) {
- tdd->fskd.spb = 176; /* 45.5 baud */
- tdd->fskd.hdlc = 0; /* Async */
- tdd->fskd.nbit = 5; /* 5 bits */
- tdd->fskd.nstop = 1.5; /* 1.5 stop bits */
- tdd->fskd.paridad = 0; /* No parity */
- tdd->fskd.bw=0; /* Filter 75 Hz */
- tdd->fskd.f_mark_idx = 0; /* 1400 Hz */
- tdd->fskd.f_space_idx = 1; /* 1800 Hz */
- tdd->fskd.pcola = 0; /* No clue */
- tdd->fskd.cont = 0; /* Digital PLL reset */
- tdd->fskd.x0 = 0.0;
- tdd->fskd.state = 0;
- tdd->pos = 0;
- tdd->mode = 0;
- tdd->charnum = 0;
- } else
- ast_log(LOG_WARNING, "Out of memory\n");
- return tdd;
-}
-
-int ast_tdd_gen_ecdisa(unsigned char *outbuf, int len)
-{
- int pos = 0;
- int cnt;
- while (len) {
- cnt = len > sizeof(ecdisa) ? sizeof(ecdisa) : len;
- memcpy(outbuf + pos, ecdisa, cnt);
- pos += cnt;
- len -= cnt;
- }
- return 0;
-}
-
-int tdd_feed(struct tdd_state *tdd, unsigned char *ubuf, int len)
-{
- int mylen = len;
- int olen;
- int b = 'X';
- int res;
- int c,x;
- short *buf = calloc(1, 2 * len + tdd->oldlen);
- short *obuf = buf;
- if (!buf) {
- ast_log(LOG_WARNING, "Out of memory\n");
- return -1;
- }
- memcpy(buf, tdd->oldstuff, tdd->oldlen);
- mylen += tdd->oldlen/2;
- for (x = 0; x < len; x++)
- buf[x + tdd->oldlen / 2] = AST_MULAW(ubuf[x]);
- c = res = 0;
- while (mylen >= 1320) { /* has to have enough to work on */
- olen = mylen;
- res = fsk_serie(&tdd->fskd, buf, &mylen, &b);
- if (mylen < 0) {
- ast_log(LOG_ERROR, "fsk_serial made mylen < 0 (%d) (olen was %d)\n", mylen, olen);
- free(obuf);
- return -1;
- }
- buf += (olen - mylen);
- if (res < 0) {
- ast_log(LOG_NOTICE, "fsk_serial failed\n");
- free(obuf);
- return -1;
- }
- if (res == 1) {
- /* Ignore invalid bytes */
- if (b > 0x7f)
- continue;
- c = tdd_decode_baudot(tdd,b);
- if ((c < 1) || (c > 126))
- continue; /* if not valid */
- break;
- }
- }
- if (mylen) {
- memcpy(tdd->oldstuff, buf, mylen * 2);
- tdd->oldlen = mylen * 2;
- } else
- tdd->oldlen = 0;
- free(obuf);
- if (res) {
- tdd->mode = 2;
-/* put it in mode where it
- reliably puts teleprinter in correct shift mode */
- return(c);
- }
- return 0;
-}
-
-void tdd_free(struct tdd_state *tdd)
-{
- free(tdd);
-}
-
-static inline float tdd_getcarrier(float *cr, float *ci, int bit)
-{
- /* Move along. There's nothing to see here... */
- float t;
- t = *cr * dr[bit] - *ci * di[bit];
- *ci = *cr * di[bit] + *ci * dr[bit];
- *cr = t;
-
- t = 2.0 - (*cr * *cr + *ci * *ci);
- *cr *= t;
- *ci *= t;
- return *cr;
-}
-
-#define PUT_BYTE(a) do { \
- *(buf++) = (a); \
- bytes++; \
-} while(0)
-
-#define PUT_AUDIO_SAMPLE(y) do { \
- int index = (short)(rint(8192.0 * (y))); \
- *(buf++) = AST_LIN2MU(index); \
- bytes++; \
-} while(0)
-
-#define PUT_TDD_MARKMS do { \
- int x; \
- for (x=0;x<8;x++) \
- PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1)); \
-} while(0)
-
-#define PUT_TDD_BAUD(bit) do { \
- while (scont < tddsb) { \
- PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, bit)); \
- scont += 1.0; \
- } \
- scont -= tddsb; \
-} while(0)
-
-#define PUT_TDD_STOP do { \
- while (scont < (tddsb * 1.5)) { \
- PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1)); \
- scont += 1.0; \
- } \
- scont -= (tddsb * 1.5); \
-} while(0)
-
-
-#define PUT_TDD(byte) do { \
- int z; \
- unsigned char b = (byte); \
- PUT_TDD_BAUD(0); /* Start bit */ \
- for (z = 0; z < 5; z++) { \
- PUT_TDD_BAUD(b & 1); \
- b >>= 1; \
- } \
- PUT_TDD_STOP; /* Stop bit */ \
-} while(0);
-
-int tdd_generate(struct tdd_state *tdd, unsigned char *buf, const char *str)
-{
- int bytes=0;
- int i,x;
- char c;
- /*! Baudot letters */
- static unsigned char lstr[31] = "\000E\nA SIU\rDRJNFCKTZLWHYPQOBG\000MXV";
- /*! Baudot figures */
- static unsigned char fstr[31] = "\0003\n- \00787\r$4',!:(5\")2\0006019?+\000./;";
- /* Initial carriers (real/imaginary) */
- float cr = 1.0;
- float ci = 0.0;
- float scont = 0.0;
-
- for(x = 0; str[x]; x++) {
- /* Do synch for each 72th character */
- if ( (tdd->charnum++) % 72 == 0)
- PUT_TDD(tdd->mode ? 27 /* FIGS */ : 31 /* LTRS */);
-
- c = toupper(str[x]);
-#if 0
- printf("%c",c); fflush(stdout);
-#endif
- if (c == 0) { /* send null */
- PUT_TDD(0);
- continue;
- }
- if (c == '\r') { /* send c/r */
- PUT_TDD(8);
- continue;
- }
- if (c == '\n') { /* send c/r and l/f */
- PUT_TDD(8);
- PUT_TDD(2);
- continue;
- }
- if (c == ' ') { /* send space */
- PUT_TDD(4);
- continue;
- }
- for (i = 0; i < 31; i++) {
- if (lstr[i] == c)
- break;
- }
- if (i < 31) { /* if we found it */
- if (tdd->mode) { /* if in figs mode, change it */
- PUT_TDD(31); /* Send LTRS */
- tdd->mode = 0;
- }
- PUT_TDD(i);
- continue;
- }
- for (i = 0; i < 31; i++) {
- if (fstr[i] == c)
- break;
- }
- if (i < 31) { /* if we found it */
- if (tdd->mode != 1) { /* if in ltrs mode, change it */
- PUT_TDD(27); /* send FIGS */
- tdd->mode = 1;
- }
- PUT_TDD(i); /* send byte */
- continue;
- }
- }
- return bytes;
-}
-
diff --git a/main/term.c b/main/term.c
deleted file mode 100644
index d051338d8..000000000
--- a/main/term.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Terminal Routines
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "asterisk/term.h"
-#include "asterisk/options.h"
-#include "asterisk/lock.h"
-#include "asterisk/utils.h"
-
-static int vt100compat;
-
-static char prepdata[80] = "";
-static char enddata[80] = "";
-static char quitdata[80] = "";
-
-static const char *termpath[] = {
- "/usr/share/terminfo",
- "/usr/local/share/misc/terminfo",
- "/usr/lib/terminfo",
- NULL
- };
-
-/* Ripped off from Ross Ridge, but it's public domain code (libmytinfo) */
-static short convshort(char *s)
-{
- register int a,b;
-
- a = (int) s[0] & 0377;
- b = (int) s[1] & 0377;
-
- if (a == 0377 && b == 0377)
- return -1;
- if (a == 0376 && b == 0377)
- return -2;
-
- return a + b * 256;
-}
-
-int ast_term_init(void)
-{
- char *term = getenv("TERM");
- char termfile[256] = "";
- char buffer[512] = "";
- int termfd = -1, parseokay = 0, i;
-
- if (!term)
- return 0;
- if (!ast_opt_console || ast_opt_no_color || !ast_opt_no_fork)
- return 0;
-
- for (i=0 ;; i++) {
- if (termpath[i] == NULL) {
- break;
- }
- snprintf(termfile, sizeof(termfile), "%s/%c/%s", termpath[i], *term, term);
- termfd = open(termfile, O_RDONLY);
- if (termfd > -1) {
- break;
- }
- }
- if (termfd > -1) {
- int actsize = read(termfd, buffer, sizeof(buffer) - 1);
- short sz_names = convshort(buffer + 2);
- short sz_bools = convshort(buffer + 4);
- short n_nums = convshort(buffer + 6);
-
- /* if ((sz_names + sz_bools) & 1)
- sz_bools++; */
-
- if (sz_names + sz_bools + n_nums < actsize) {
- /* Offset 13 is defined in /usr/include/term.h, though we do not
- * include it here, as it conflicts with include/asterisk/term.h */
- short max_colors = convshort(buffer + 12 + sz_names + sz_bools + 13 * 2);
- if (max_colors > 0) {
- vt100compat = 1;
- }
- parseokay = 1;
- }
- close(termfd);
- }
-
- if (!parseokay) {
- /* These comparisons should not be substrings nor case-insensitive, as
- * terminal types are very particular about how they treat suffixes and
- * capitalization. For example, terminal type 'linux-m' does NOT
- * support color, while 'linux' does. Not even all vt100* terminals
- * support color, either (e.g. 'vt100+fnkeys'). */
- if (!strcmp(term, "linux")) {
- vt100compat = 1;
- } else if (!strcmp(term, "xterm")) {
- vt100compat = 1;
- } else if (!strcmp(term, "xterm-color")) {
- vt100compat = 1;
- } else if (!strncmp(term, "Eterm", 5)) {
- /* Both entries which start with Eterm support color */
- vt100compat = 1;
- } else if (!strcmp(term, "vt100")) {
- vt100compat = 1;
- } else if (!strncmp(term, "crt", 3)) {
- /* Both crt terminals support color */
- vt100compat = 1;
- }
- }
-
- if (vt100compat) {
- /* Make commands show up in nice colors */
- snprintf(prepdata, sizeof(prepdata), "%c[%d;%d;%dm", ESC, ATTR_BRIGHT, COLOR_BROWN, COLOR_BLACK + 10);
- snprintf(enddata, sizeof(enddata), "%c[%d;%d;%dm", ESC, ATTR_RESET, COLOR_WHITE, COLOR_BLACK + 10);
- snprintf(quitdata, sizeof(quitdata), "%c[0m", ESC);
- }
- return 0;
-}
-
-char *term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
-{
- int attr=0;
- char tmp[40];
- if (!vt100compat) {
- ast_copy_string(outbuf, inbuf, maxout);
- return outbuf;
- }
- if (!fgcolor && !bgcolor) {
- ast_copy_string(outbuf, inbuf, maxout);
- return outbuf;
- }
- if ((fgcolor & 128) && (bgcolor & 128)) {
- /* Can't both be highlighted */
- ast_copy_string(outbuf, inbuf, maxout);
- return outbuf;
- }
- if (!bgcolor)
- bgcolor = COLOR_BLACK;
-
- if (bgcolor) {
- bgcolor &= ~128;
- bgcolor += 10;
- }
- if (fgcolor & 128) {
- attr = ATTR_BRIGHT;
- fgcolor &= ~128;
- }
- if (fgcolor && bgcolor) {
- snprintf(tmp, sizeof(tmp), "%d;%d", fgcolor, bgcolor);
- } else if (bgcolor) {
- snprintf(tmp, sizeof(tmp), "%d", bgcolor);
- } else if (fgcolor) {
- snprintf(tmp, sizeof(tmp), "%d", fgcolor);
- }
- if (attr) {
- snprintf(outbuf, maxout, "%c[%d;%sm%s%c[0;%d;%dm", ESC, attr, tmp, inbuf, ESC, COLOR_WHITE, COLOR_BLACK + 10);
- } else {
- snprintf(outbuf, maxout, "%c[%sm%s%c[0;%d;%dm", ESC, tmp, inbuf, ESC, COLOR_WHITE, COLOR_BLACK + 10);
- }
- return outbuf;
-}
-
-char *term_color_code(char *outbuf, int fgcolor, int bgcolor, int maxout)
-{
- int attr=0;
- char tmp[40];
- if ((!vt100compat) || (!fgcolor && !bgcolor)) {
- *outbuf = '\0';
- return outbuf;
- }
- if ((fgcolor & 128) && (bgcolor & 128)) {
- /* Can't both be highlighted */
- *outbuf = '\0';
- return outbuf;
- }
- if (!bgcolor)
- bgcolor = COLOR_BLACK;
-
- if (bgcolor) {
- bgcolor &= ~128;
- bgcolor += 10;
- }
- if (fgcolor & 128) {
- attr = ATTR_BRIGHT;
- fgcolor &= ~128;
- }
- if (fgcolor && bgcolor) {
- snprintf(tmp, sizeof(tmp), "%d;%d", fgcolor, bgcolor);
- } else if (bgcolor) {
- snprintf(tmp, sizeof(tmp), "%d", bgcolor);
- } else if (fgcolor) {
- snprintf(tmp, sizeof(tmp), "%d", fgcolor);
- }
- if (attr) {
- snprintf(outbuf, maxout, "%c[%d;%sm", ESC, attr, tmp);
- } else {
- snprintf(outbuf, maxout, "%c[%sm", ESC, tmp);
- }
- return outbuf;
-}
-
-char *term_strip(char *outbuf, char *inbuf, int maxout)
-{
- char *outbuf_ptr = outbuf, *inbuf_ptr = inbuf;
-
- while (outbuf_ptr < outbuf + maxout) {
- switch (*inbuf_ptr) {
- case ESC:
- while (*inbuf_ptr && (*inbuf_ptr != 'm'))
- inbuf_ptr++;
- break;
- default:
- *outbuf_ptr = *inbuf_ptr;
- outbuf_ptr++;
- }
- if (! *inbuf_ptr)
- break;
- inbuf_ptr++;
- }
- return outbuf;
-}
-
-char *term_prompt(char *outbuf, const char *inbuf, int maxout)
-{
- if (!vt100compat) {
- ast_copy_string(outbuf, inbuf, maxout);
- return outbuf;
- }
- snprintf(outbuf, maxout, "%c[%d;%d;%dm%c%c[%d;%d;%dm%s",
- ESC, ATTR_BRIGHT, COLOR_BLUE, COLOR_BLACK + 10,
- inbuf[0],
- ESC, 0, COLOR_WHITE, COLOR_BLACK + 10,
- inbuf + 1);
- return outbuf;
-}
-
-/* filter escape sequences */
-void term_filter_escapes(char *line)
-{
- int i;
- int len = strlen(line);
-
- for (i = 0; i < len; i++) {
- if (line[i] != ESC)
- continue;
- if ((i < (len - 2)) &&
- (line[i + 1] == 0x5B)) {
- switch (line[i + 2]) {
- case 0x30:
- case 0x31:
- case 0x33:
- continue;
- }
- }
- /* replace ESC with a space */
- line[i] = ' ';
- }
-}
-
-char *term_prep(void)
-{
- return prepdata;
-}
-
-char *term_end(void)
-{
- return enddata;
-}
-
-char *term_quit(void)
-{
- return quitdata;
-}
diff --git a/main/threadstorage.c b/main/threadstorage.c
deleted file mode 100644
index 0bad38981..000000000
--- a/main/threadstorage.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Kevin P. Fleming <kpfleming@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Debugging support for thread-local-storage objects
- *
- * \author Kevin P. Fleming <kpfleming@digium.com>
- */
-
-#include "asterisk.h"
-
-#if defined(DEBUG_THREADLOCALS)
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "asterisk/logger.h"
-#include "asterisk/strings.h"
-#include "asterisk/utils.h"
-#include "asterisk/threadstorage.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/cli.h"
-
-struct tls_object {
- void *key;
- size_t size;
- const char *file;
- const char *function;
- unsigned int line;
- pthread_t thread;
- AST_LIST_ENTRY(tls_object) entry;
-};
-
-static AST_LIST_HEAD_NOLOCK_STATIC(tls_objects, tls_object);
-
-/* Allow direct use of pthread_mutex_t and friends */
-#undef pthread_mutex_t
-#undef pthread_mutex_lock
-#undef pthread_mutex_unlock
-#undef pthread_mutex_init
-#undef pthread_mutex_destroy
-
-/*!
- * \brief lock for the tls_objects list
- *
- * \note We can not use an ast_mutex_t for this. The reason is that this
- * lock is used within the context of thread-local data destructors,
- * and the ast_mutex_* API uses thread-local data. Allocating more
- * thread-local data at that point just causes a memory leak.
- */
-static pthread_mutex_t threadstoragelock;
-
-void __ast_threadstorage_object_add(void *key, size_t len, const char *file, const char *function, unsigned int line)
-{
- struct tls_object *to;
-
- if (!(to = ast_calloc(1, sizeof(*to))))
- return;
-
- to->key = key;
- to->size = len;
- to->file = file;
- to->function = function;
- to->line = line;
- to->thread = pthread_self();
-
- pthread_mutex_lock(&threadstoragelock);
- AST_LIST_INSERT_TAIL(&tls_objects, to, entry);
- pthread_mutex_unlock(&threadstoragelock);
-}
-
-void __ast_threadstorage_object_remove(void *key)
-{
- struct tls_object *to;
-
- pthread_mutex_lock(&threadstoragelock);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&tls_objects, to, entry) {
- if (to->key == key) {
- AST_LIST_REMOVE_CURRENT(&tls_objects, entry);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- pthread_mutex_unlock(&threadstoragelock);
- if (to)
- free(to);
-}
-
-void __ast_threadstorage_object_replace(void *key_old, void *key_new, size_t len)
-{
- struct tls_object *to;
-
- pthread_mutex_lock(&threadstoragelock);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&tls_objects, to, entry) {
- if (to->key == key_old) {
- to->key = key_new;
- to->size = len;
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- pthread_mutex_unlock(&threadstoragelock);
-}
-
-static int handle_show_allocations(int fd, int argc, char *argv[])
-{
- char *fn = NULL;
- size_t len = 0;
- unsigned int count = 0;
- struct tls_object *to;
-
- if (argc > 3)
- fn = argv[3];
-
- pthread_mutex_lock(&threadstoragelock);
-
- AST_LIST_TRAVERSE(&tls_objects, to, entry) {
- if (fn && strcasecmp(to->file, fn))
- continue;
-
- ast_cli(fd, "%10d bytes allocated in %20s at line %5d of %25s (thread %p)\n",
- (int) to->size, to->function, to->line, to->file, (void *) to->thread);
- len += to->size;
- count++;
- }
-
- pthread_mutex_unlock(&threadstoragelock);
-
- ast_cli(fd, "%10d bytes allocated in %d allocation%s\n", (int) len, count, count > 1 ? "s" : "");
-
- return RESULT_SUCCESS;
-}
-
-static int handle_show_summary(int fd, int argc, char *argv[])
-{
- char *fn = NULL;
- size_t len = 0;
- unsigned int count = 0;
- struct tls_object *to;
- struct file {
- const char *name;
- size_t len;
- unsigned int count;
- AST_LIST_ENTRY(file) entry;
- } *file;
- AST_LIST_HEAD_NOLOCK_STATIC(file_summary, file);
-
- if (argc > 3)
- fn = argv[3];
-
- pthread_mutex_lock(&threadstoragelock);
-
- AST_LIST_TRAVERSE(&tls_objects, to, entry) {
- if (fn && strcasecmp(to->file, fn))
- continue;
-
- AST_LIST_TRAVERSE(&file_summary, file, entry) {
- if ((!fn && (file->name == to->file)) || (fn && (file->name == to->function)))
- break;
- }
-
- if (!file) {
- file = alloca(sizeof(*file));
- memset(file, 0, sizeof(*file));
- file->name = fn ? to->function : to->file;
- AST_LIST_INSERT_TAIL(&file_summary, file, entry);
- }
-
- file->len += to->size;
- file->count++;
- }
-
- pthread_mutex_unlock(&threadstoragelock);
-
- AST_LIST_TRAVERSE(&file_summary, file, entry) {
- len += file->len;
- count += file->count;
- if (fn) {
- ast_cli(fd, "%10d bytes in %d allocation%ss in function %s\n",
- (int) file->len, file->count, file->count > 1 ? "s" : "", file->name);
- } else {
- ast_cli(fd, "%10d bytes in %d allocation%s in file %s\n",
- (int) file->len, file->count, file->count > 1 ? "s" : "", file->name);
- }
- }
-
- ast_cli(fd, "%10d bytes allocated in %d allocation%s\n", (int) len, count, count > 1 ? "s" : "");
-
- return RESULT_SUCCESS;
-}
-
-static struct ast_cli_entry cli[] = {
- {
- .cmda = { "threadstorage", "show", "allocations", NULL },
- .handler = handle_show_allocations,
- .summary = "Display outstanding thread local storage allocations",
- .usage =
- "Usage: threadstorage show allocations [<file>]\n"
- " Dumps a list of all thread-specific memory allocations,\n"
- "optionally limited to those from a specific file\n",
- },
- {
- .cmda = { "threadstorage", "show", "summary", NULL },
- .handler = handle_show_summary,
- .summary = "Summarize outstanding memory allocations",
- .usage =
- "Usage: threadstorage show summary [<file>]\n"
- " Summarizes thread-specific memory allocations by file, or optionally\n"
- "by function, if a file is specified\n",
- },
-};
-
-void threadstorage_init(void)
-{
- pthread_mutex_init(&threadstoragelock, NULL);
- ast_cli_register_multiple(cli, sizeof(cli) / sizeof(cli[0]));
-}
-
-#else /* !defined(DEBUG_THREADLOCALS) */
-
-void threadstorage_init(void)
-{
-}
-
-#endif /* !defined(DEBUG_THREADLOCALS) */
-
diff --git a/main/translate.c b/main/translate.c
deleted file mode 100644
index 598520c07..000000000
--- a/main/translate.c
+++ /dev/null
@@ -1,986 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Translate via the use of pseudo channels
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "asterisk/lock.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/translate.h"
-#include "asterisk/module.h"
-#include "asterisk/options.h"
-#include "asterisk/frame.h"
-#include "asterisk/sched.h"
-#include "asterisk/cli.h"
-#include "asterisk/term.h"
-
-#define MAX_RECALC 200 /* max sample recalc */
-
-/*! \brief the list of translators */
-static AST_LIST_HEAD_STATIC(translators, ast_translator);
-
-struct translator_path {
- struct ast_translator *step; /*!< Next step translator */
- unsigned int cost; /*!< Complete cost to destination */
- unsigned int multistep; /*!< Multiple conversions required for this translation */
-};
-
-/*! \brief a matrix that, for any pair of supported formats,
- * indicates the total cost of translation and the first step.
- * The full path can be reconstricted iterating on the matrix
- * until step->dstfmt == desired_format.
- *
- * Array indexes are 'src' and 'dest', in that order.
- *
- * Note: the lock in the 'translators' list is also used to protect
- * this structure.
- */
-static struct translator_path tr_matrix[MAX_FORMAT][MAX_FORMAT];
-
-/*! \todo
- * TODO: sample frames for each supported input format.
- * We build this on the fly, by taking an SLIN frame and using
- * the existing converter to play with it.
- */
-
-/*! \brief returns the index of the lowest bit set */
-static force_inline int powerof(unsigned int d)
-{
- int x = ffs(d);
-
- if (x)
- return x - 1;
-
- ast_log(LOG_WARNING, "No bits set? %d\n", d);
-
- return -1;
-}
-
-/*
- * wrappers around the translator routines.
- */
-
-/*!
- * \brief Allocate the descriptor, required outbuf space,
- * and possibly also plc and desc.
- */
-static void *newpvt(struct ast_translator *t)
-{
- struct ast_trans_pvt *pvt;
- int len;
- int useplc = t->plc_samples > 0 && t->useplc; /* cache, because it can change on the fly */
- char *ofs;
-
- /*
- * compute the required size adding private descriptor,
- * plc, buffer, AST_FRIENDLY_OFFSET.
- */
- len = sizeof(*pvt) + t->desc_size;
- if (useplc)
- len += sizeof(plc_state_t);
- if (t->buf_size)
- len += AST_FRIENDLY_OFFSET + t->buf_size;
- pvt = ast_calloc(1, len);
- if (!pvt)
- return NULL;
- pvt->t = t;
- ofs = (char *)(pvt + 1); /* pointer to data space */
- if (t->desc_size) { /* first comes the descriptor */
- pvt->pvt = ofs;
- ofs += t->desc_size;
- }
- if (useplc) { /* then plc state */
- pvt->plc = (plc_state_t *)ofs;
- ofs += sizeof(plc_state_t);
- }
- if (t->buf_size) /* finally buffer and header */
- pvt->outbuf = ofs + AST_FRIENDLY_OFFSET;
- /* call local init routine, if present */
- if (t->newpvt && t->newpvt(pvt)) {
- free(pvt);
- return NULL;
- }
- ast_module_ref(t->module);
- return pvt;
-}
-
-static void destroy(struct ast_trans_pvt *pvt)
-{
- struct ast_translator *t = pvt->t;
-
- if (ast_test_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR)) {
- /* If this flag is still set, that means that the translation path has
- * been torn down, while we still have a frame out there being used.
- * When ast_frfree() gets called on that frame, this ast_trans_pvt
- * will get destroyed, too. */
-
- /* Set the magic hint that this has been requested to be destroyed. */
- pvt->datalen = -1;
-
- return;
- }
-
- if (t->destroy)
- t->destroy(pvt);
- free(pvt);
- ast_module_unref(t->module);
-}
-
-/*! \brief framein wrapper, deals with plc and bound checks. */
-static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
-{
- int16_t *dst = (int16_t *)pvt->outbuf;
- int ret;
- int samples = pvt->samples; /* initial value */
-
- /* Copy the last in jb timing info to the pvt */
- ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO);
- pvt->f.ts = f->ts;
- pvt->f.len = f->len;
- pvt->f.seqno = f->seqno;
-
- if (f->samples == 0) {
- ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
- }
- if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
- if (f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
- if (pvt->plc) {
- int l = pvt->t->plc_samples;
- if (pvt->samples + l > pvt->t->buffer_samples) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- l = plc_fillin(pvt->plc, dst + pvt->samples, l);
- pvt->samples += l;
- pvt->datalen = pvt->samples * 2; /* SLIN has 2bytes for 1sample */
- }
- /* We don't want generic PLC. If the codec has native PLC, then do that */
- if (!pvt->t->native_plc)
- return 0;
- }
- if (pvt->samples + f->samples > pvt->t->buffer_samples) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- }
- /* we require a framein routine, wouldn't know how to do
- * it otherwise.
- */
- ret = pvt->t->framein(pvt, f);
- /* possibly store data for plc */
- if (!ret && pvt->plc) {
- int l = pvt->t->plc_samples;
- if (pvt->samples < l)
- l = pvt->samples;
- plc_rx(pvt->plc, dst + pvt->samples - l, l);
- }
- /* diagnostic ... */
- if (pvt->samples == samples)
- ast_log(LOG_WARNING, "%s did not update samples %d\n",
- pvt->t->name, pvt->samples);
- return ret;
-}
-
-/*! \brief generic frameout routine.
- * If samples and datalen are 0, take whatever is in pvt
- * and reset them, otherwise take the values in the caller and
- * leave alone the pvt values.
- */
-struct ast_frame *ast_trans_frameout(struct ast_trans_pvt *pvt,
- int datalen, int samples)
-{
- struct ast_frame *f = &pvt->f;
-
- if (samples)
- f->samples = samples;
- else {
- if (pvt->samples == 0)
- return NULL;
- f->samples = pvt->samples;
- pvt->samples = 0;
- }
- if (datalen)
- f->datalen = datalen;
- else {
- f->datalen = pvt->datalen;
- pvt->datalen = 0;
- }
-
- f->frametype = AST_FRAME_VOICE;
- f->subclass = 1 << (pvt->t->dstfmt);
- f->mallocd = 0;
- f->offset = AST_FRIENDLY_OFFSET;
- f->src = pvt->t->name;
- f->data = pvt->outbuf;
-
- ast_set_flag(f, AST_FRFLAG_FROM_TRANSLATOR);
-
- return f;
-}
-
-static struct ast_frame *default_frameout(struct ast_trans_pvt *pvt)
-{
- return ast_trans_frameout(pvt, 0, 0);
-}
-
-/* end of callback wrappers and helpers */
-
-void ast_translator_free_path(struct ast_trans_pvt *p)
-{
- struct ast_trans_pvt *pn = p;
- while ( (p = pn) ) {
- pn = p->next;
- destroy(p);
- }
-}
-
-/*! \brief Build a chain of translators based upon the given source and dest formats */
-struct ast_trans_pvt *ast_translator_build_path(int dest, int source)
-{
- struct ast_trans_pvt *head = NULL, *tail = NULL;
-
- source = powerof(source);
- dest = powerof(dest);
-
- if (source == -1 || dest == -1) {
- ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending");
- return NULL;
- }
-
- AST_LIST_LOCK(&translators);
-
- while (source != dest) {
- struct ast_trans_pvt *cur;
- struct ast_translator *t = tr_matrix[source][dest].step;
- if (!t) {
- ast_log(LOG_WARNING, "No translator path from %s to %s\n",
- ast_getformatname(source), ast_getformatname(dest));
- AST_LIST_UNLOCK(&translators);
- return NULL;
- }
- if (!(cur = newpvt(t))) {
- ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
- if (head)
- ast_translator_free_path(head);
- AST_LIST_UNLOCK(&translators);
- return NULL;
- }
- if (!head)
- head = cur;
- else
- tail->next = cur;
- tail = cur;
- cur->nextin = cur->nextout = ast_tv(0, 0);
- /* Keep going if this isn't the final destination */
- source = cur->t->dstfmt;
- }
-
- AST_LIST_UNLOCK(&translators);
- return head;
-}
-
-/*! \brief do the actual translation */
-struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
-{
- struct ast_trans_pvt *p = path;
- struct ast_frame *out = f;
- struct timeval delivery;
- int has_timing_info;
- long ts;
- long len;
- int seqno;
-
- has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO);
- ts = f->ts;
- len = f->len;
- seqno = f->seqno;
-
- /* XXX hmmm... check this below */
- if (!ast_tvzero(f->delivery)) {
- if (!ast_tvzero(path->nextin)) {
- /* Make sure this is in line with what we were expecting */
- if (!ast_tveq(path->nextin, f->delivery)) {
- /* The time has changed between what we expected and this
- most recent time on the new packet. If we have a
- valid prediction adjust our output time appropriately */
- if (!ast_tvzero(path->nextout)) {
- path->nextout = ast_tvadd(path->nextout,
- ast_tvsub(f->delivery, path->nextin));
- }
- path->nextin = f->delivery;
- }
- } else {
- /* This is our first pass. Make sure the timing looks good */
- path->nextin = f->delivery;
- path->nextout = f->delivery;
- }
- /* Predict next incoming sample */
- path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass)));
- }
- delivery = f->delivery;
- for ( ; out && p ; p = p->next) {
- framein(p, out);
- if (out != f)
- ast_frfree(out);
- out = p->t->frameout(p);
- }
- if (consume)
- ast_frfree(f);
- if (out == NULL)
- return NULL;
- /* we have a frame, play with times */
- if (!ast_tvzero(delivery)) {
- /* Regenerate prediction after a discontinuity */
- if (ast_tvzero(path->nextout))
- path->nextout = ast_tvnow();
-
- /* Use next predicted outgoing timestamp */
- out->delivery = path->nextout;
-
- /* Predict next outgoing timestamp from samples in this
- frame. */
- path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass)));
- } else {
- out->delivery = ast_tv(0, 0);
- ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO);
- if (has_timing_info) {
- out->ts = ts;
- out->len = len;
- out->seqno = seqno;
- }
- }
- /* Invalidate prediction if we're entering a silence period */
- if (out->frametype == AST_FRAME_CNG)
- path->nextout = ast_tv(0, 0);
- return out;
-}
-
-/*! \brief compute the cost of a single translation step */
-static void calc_cost(struct ast_translator *t, int seconds)
-{
- int num_samples = 0;
- struct ast_trans_pvt *pvt;
- struct timeval start;
- int cost;
- int out_rate = ast_format_rate(t->dstfmt);
-
- if (!seconds)
- seconds = 1;
-
- /* If they don't make samples, give them a terrible score */
- if (!t->sample) {
- ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
- t->cost = 99999;
- return;
- }
-
- pvt = newpvt(t);
- if (!pvt) {
- ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
- t->cost = 99999;
- return;
- }
-
- start = ast_tvnow();
-
- /* Call the encoder until we've processed the required number of samples */
- while (num_samples < seconds * out_rate) {
- struct ast_frame *f = t->sample();
- if (!f) {
- ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
- destroy(pvt);
- t->cost = 99999;
- return;
- }
- framein(pvt, f);
- ast_frfree(f);
- while ((f = t->frameout(pvt))) {
- num_samples += f->samples;
- ast_frfree(f);
- }
- }
-
- cost = ast_tvdiff_ms(ast_tvnow(), start);
-
- destroy(pvt);
-
- t->cost = cost / seconds;
-
- if (!t->cost)
- t->cost = 1;
-}
-
-/*!
- * \brief rebuild a translation matrix.
- * \note This function expects the list of translators to be locked
-*/
-static void rebuild_matrix(int samples)
-{
- struct ast_translator *t;
- int x; /* source format index */
- int y; /* intermediate format index */
- int z; /* destination format index */
-
- if (option_debug)
- ast_log(LOG_DEBUG, "Resetting translation matrix\n");
-
- bzero(tr_matrix, sizeof(tr_matrix));
-
- /* first, compute all direct costs */
- AST_LIST_TRAVERSE(&translators, t, list) {
- if (!t->active)
- continue;
-
- x = t->srcfmt;
- z = t->dstfmt;
-
- if (samples)
- calc_cost(t, samples);
-
- if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) {
- tr_matrix[x][z].step = t;
- tr_matrix[x][z].cost = t->cost;
- }
- }
-
- /*
- * For each triple x, y, z of distinct formats, check if there is
- * a path from x to z through y which is cheaper than what is
- * currently known, and in case, update the matrix.
- * Repeat until the matrix is stable.
- */
- for (;;) {
- int changed = 0;
- for (x = 0; x < MAX_FORMAT; x++) { /* source format */
- for (y=0; y < MAX_FORMAT; y++) { /* intermediate format */
- if (x == y) /* skip ourselves */
- continue;
-
- for (z=0; z<MAX_FORMAT; z++) { /* dst format */
- int newcost;
-
- if (z == x || z == y) /* skip null conversions */
- continue;
- if (!tr_matrix[x][y].step) /* no path from x to y */
- continue;
- if (!tr_matrix[y][z].step) /* no path from y to z */
- continue;
- newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost;
- if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost)
- continue; /* x->y->z is more expensive than
- * the existing path */
- /* ok, we can get from x to z via y with a cost that
- is the sum of the transition from x to y and
- from y to z */
-
- tr_matrix[x][z].step = tr_matrix[x][y].step;
- tr_matrix[x][z].cost = newcost;
- tr_matrix[x][z].multistep = 1;
- if (option_debug)
- ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost,
- ast_getformatname(1 << x), ast_getformatname(1 << z), ast_getformatname(1 << y));
- changed++;
- }
- }
- }
- if (!changed)
- break;
- }
-}
-
-/*! \brief CLI "show translation" command handler */
-static int show_translation_deprecated(int fd, int argc, char *argv[])
-{
-#define SHOW_TRANS 13
- int x, y, z;
- int curlen = 0, longest = 0;
-
- if (argc > 4)
- return RESULT_SHOWUSAGE;
-
- AST_LIST_LOCK(&translators);
-
- if (argv[2] && !strcasecmp(argv[2], "recalc")) {
- z = argv[3] ? atoi(argv[3]) : 1;
-
- if (z <= 0) {
- ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n");
- z = 1;
- }
-
- if (z > MAX_RECALC) {
- ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
- z = MAX_RECALC;
- }
- ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
- rebuild_matrix(z);
- }
-
- ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n");
- ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n");
- /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
- for (x = 0; x < SHOW_TRANS; x++) {
- curlen = strlen(ast_getformatname(1 << (x)));
- if (curlen > longest)
- longest = curlen;
- }
- for (x = -1; x < SHOW_TRANS; x++) {
- char line[120];
- char *buf = line;
- size_t left = sizeof(line) - 1; /* one initial space */
- /* next 2 lines run faster than using ast_build_string() */
- *buf++ = ' ';
- *buf = '\0';
- for (y = -1; y < SHOW_TRANS; y++) {
- if (y >= 0)
- curlen = strlen(ast_getformatname(1 << (y)));
-
- if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
- /* XXX 999 is a little hackish
- We don't want this number being larger than the shortest (or current) codec
- For now, that is "gsm" */
- ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
- } else if (x == -1 && y >= 0) {
- /* Top row - use a dynamic size */
- ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) );
- } else if (y == -1 && x >= 0) {
- /* Left column - use a static size. */
- ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) );
- } else if (x >= 0 && y >= 0) {
- ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
- } else {
- ast_build_string(&buf, &left, "%*s", longest, "");
- }
- }
- ast_build_string(&buf, &left, "\n");
- ast_cli(fd, "%s", line);
- }
- AST_LIST_UNLOCK(&translators);
- return RESULT_SUCCESS;
-}
-
-static int show_translation(int fd, int argc, char *argv[])
-{
- int x, y, z;
- int curlen = 0, longest = 0;
-
- if (argc > 5)
- return RESULT_SHOWUSAGE;
-
- AST_LIST_LOCK(&translators);
-
- if (argv[3] && !strcasecmp(argv[3], "recalc")) {
- z = argv[4] ? atoi(argv[4]) : 1;
-
- if (z <= 0) {
- ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n");
- z = 1;
- }
-
- if (z > MAX_RECALC) {
- ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
- z = MAX_RECALC;
- }
- ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
- rebuild_matrix(z);
- }
-
- ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n");
- ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n");
- /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
- for (x = 0; x < SHOW_TRANS; x++) {
- curlen = strlen(ast_getformatname(1 << (x)));
- if (curlen > longest)
- longest = curlen;
- }
- for (x = -1; x < SHOW_TRANS; x++) {
- char line[120];
- char *buf = line;
- size_t left = sizeof(line) - 1; /* one initial space */
- /* next 2 lines run faster than using ast_build_string() */
- *buf++ = ' ';
- *buf = '\0';
- for (y = -1; y < SHOW_TRANS; y++) {
- if (y >= 0)
- curlen = strlen(ast_getformatname(1 << (y)));
-
- if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
- /* XXX 999 is a little hackish
- We don't want this number being larger than the shortest (or current) codec
- For now, that is "gsm" */
- ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
- } else if (x == -1 && y >= 0) {
- /* Top row - use a dynamic size */
- ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) );
- } else if (y == -1 && x >= 0) {
- /* Left column - use a static size. */
- ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) );
- } else if (x >= 0 && y >= 0) {
- ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
- } else {
- ast_build_string(&buf, &left, "%*s", longest, "");
- }
- }
- ast_build_string(&buf, &left, "\n");
- ast_cli(fd, "%s", line);
- }
- AST_LIST_UNLOCK(&translators);
- return RESULT_SUCCESS;
-}
-
-static char show_trans_usage[] =
-"Usage: core show translation [recalc] [<recalc seconds>]\n"
-" Displays known codec translators and the cost associated\n"
-"with each conversion. If the argument 'recalc' is supplied along\n"
-"with optional number of seconds to test a new test will be performed\n"
-"as the chart is being displayed.\n";
-
-static struct ast_cli_entry cli_show_translation_deprecated = {
- { "show", "translation", NULL },
- show_translation_deprecated, NULL,
- NULL };
-
-static struct ast_cli_entry cli_translate[] = {
- { { "core", "show", "translation", NULL },
- show_translation, "Display translation matrix",
- show_trans_usage, NULL, &cli_show_translation_deprecated },
-};
-
-/*! \brief register codec translator */
-int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
-{
- static int added_cli = 0;
- struct ast_translator *u;
-
- if (!mod) {
- ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
- return -1;
- }
-
- if (!t->buf_size) {
- ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
- return -1;
- }
-
- t->module = mod;
-
- t->srcfmt = powerof(t->srcfmt);
- t->dstfmt = powerof(t->dstfmt);
- t->active = 1;
-
- if (t->srcfmt == -1 || t->dstfmt == -1) {
- ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending");
- return -1;
- }
- if (t->plc_samples) {
- if (t->buffer_samples < t->plc_samples) {
- ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n",
- t->plc_samples, t->buffer_samples);
- return -1;
- }
- if (t->dstfmt != powerof(AST_FORMAT_SLINEAR))
- ast_log(LOG_WARNING, "plc_samples %d format %x\n",
- t->plc_samples, t->dstfmt);
- }
- if (t->srcfmt >= MAX_FORMAT) {
- ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
- return -1;
- }
-
- if (t->dstfmt >= MAX_FORMAT) {
- ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
- return -1;
- }
-
- if (t->buf_size) {
- /*
- * Align buf_size properly, rounding up to the machine-specific
- * alignment for pointers.
- */
- struct _test_align { void *a, *b; } p;
- int align = (char *)&p.b - (char *)&p.a;
-
- t->buf_size = ((t->buf_size + align - 1) / align) * align;
- }
-
- if (t->frameout == NULL)
- t->frameout = default_frameout;
-
- calc_cost(t, 1);
-
- if (option_verbose > 1) {
- char tmp[80];
-
- ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n",
- term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
- ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
- }
-
- if (!added_cli) {
- ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
- added_cli++;
- }
-
- AST_LIST_LOCK(&translators);
-
- /* find any existing translators that provide this same srcfmt/dstfmt,
- and put this one in order based on cost */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
- if ((u->srcfmt == t->srcfmt) &&
- (u->dstfmt == t->dstfmt) &&
- (u->cost > t->cost)) {
- AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list);
- t = NULL;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- /* if no existing translator was found for this format combination,
- add it to the beginning of the list */
- if (t)
- AST_LIST_INSERT_HEAD(&translators, t, list);
-
- rebuild_matrix(0);
-
- AST_LIST_UNLOCK(&translators);
-
- return 0;
-}
-
-/*! \brief unregister codec translator */
-int ast_unregister_translator(struct ast_translator *t)
-{
- char tmp[80];
- struct ast_translator *u;
- int found = 0;
-
- AST_LIST_LOCK(&translators);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
- if (u == t) {
- AST_LIST_REMOVE_CURRENT(&translators, list);
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt));
- found = 1;
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- if (found)
- rebuild_matrix(0);
-
- AST_LIST_UNLOCK(&translators);
-
- return (u ? 0 : -1);
-}
-
-void ast_translator_activate(struct ast_translator *t)
-{
- AST_LIST_LOCK(&translators);
- t->active = 1;
- rebuild_matrix(0);
- AST_LIST_UNLOCK(&translators);
-}
-
-void ast_translator_deactivate(struct ast_translator *t)
-{
- AST_LIST_LOCK(&translators);
- t->active = 0;
- rebuild_matrix(0);
- AST_LIST_UNLOCK(&translators);
-}
-
-/*! \brief Calculate our best translator source format, given costs, and a desired destination */
-int ast_translator_best_choice(int *dst, int *srcs)
-{
- int x,y;
- int best = -1;
- int bestdst = 0;
- int cur, cursrc;
- int besttime = INT_MAX;
- int beststeps = INT_MAX;
- int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */
-
- if (common) { /* yes, pick one and return */
- for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
- if (cur & common) /* guaranteed to find one */
- break;
- }
- /* We are done, this is a common format to both. */
- *srcs = *dst = cur;
- return 0;
- } else { /* No, we will need to translate */
- AST_LIST_LOCK(&translators);
- for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
- if (! (cur & *dst))
- continue;
- for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) {
- if (!(*srcs & cursrc) || !tr_matrix[x][y].step ||
- tr_matrix[x][y].cost > besttime)
- continue; /* not existing or no better */
- if (tr_matrix[x][y].cost < besttime ||
- tr_matrix[x][y].multistep < beststeps) {
- /* better than what we have so far */
- best = cursrc;
- bestdst = cur;
- besttime = tr_matrix[x][y].cost;
- beststeps = tr_matrix[x][y].multistep;
- }
- }
- }
- AST_LIST_UNLOCK(&translators);
- if (best > -1) {
- *srcs = best;
- *dst = bestdst;
- best = 0;
- }
- return best;
- }
-}
-
-unsigned int ast_translate_path_steps(unsigned int dest, unsigned int src)
-{
- unsigned int res = -1;
-
- /* convert bitwise format numbers into array indices */
- src = powerof(src);
- dest = powerof(dest);
-
- if (src == -1 || dest == -1) {
- ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending");
- return -1;
- }
- AST_LIST_LOCK(&translators);
-
- if (tr_matrix[src][dest].step)
- res = tr_matrix[src][dest].multistep + 1;
-
- AST_LIST_UNLOCK(&translators);
-
- return res;
-}
-
-unsigned int ast_translate_available_formats(unsigned int dest, unsigned int src)
-{
- unsigned int res = dest;
- unsigned int x;
- unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK;
- unsigned int src_video = src & AST_FORMAT_VIDEO_MASK;
-
- /* if we don't have a source format, we just have to try all
- possible destination formats */
- if (!src)
- return dest;
-
- /* If we have a source audio format, get its format index */
- if (src_audio)
- src_audio = powerof(src_audio);
-
- /* If we have a source video format, get its format index */
- if (src_video)
- src_video = powerof(src_video);
-
- AST_LIST_LOCK(&translators);
-
- /* For a given source audio format, traverse the list of
- known audio formats to determine whether there exists
- a translation path from the source format to the
- destination format. */
- for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) {
- /* if this is not a desired format, nothing to do */
- if (!dest & x)
- continue;
-
- /* if the source is supplying this format, then
- we can leave it in the result */
- if (src & x)
- continue;
-
- /* if we don't have a translation path from the src
- to this format, remove it from the result */
- if (!tr_matrix[src_audio][powerof(x)].step) {
- res &= ~x;
- continue;
- }
-
- /* now check the opposite direction */
- if (!tr_matrix[powerof(x)][src_audio].step)
- res &= ~x;
- }
-
- /* For a given source video format, traverse the list of
- known video formats to determine whether there exists
- a translation path from the source format to the
- destination format. */
- for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) {
- /* if this is not a desired format, nothing to do */
- if (!dest & x)
- continue;
-
- /* if the source is supplying this format, then
- we can leave it in the result */
- if (src & x)
- continue;
-
- /* if we don't have a translation path from the src
- to this format, remove it from the result */
- if (!tr_matrix[src_video][powerof(x)].step) {
- res &= ~x;
- continue;
- }
-
- /* now check the opposite direction */
- if (!tr_matrix[powerof(x)][src_video].step)
- res &= ~x;
- }
-
- AST_LIST_UNLOCK(&translators);
-
- return res;
-}
-
-void ast_translate_frame_freed(struct ast_frame *fr)
-{
- struct ast_trans_pvt *pvt;
-
- ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
-
- pvt = (struct ast_trans_pvt *) (((char *) fr) - offsetof(struct ast_trans_pvt, f));
-
- if (pvt->datalen != -1)
- return;
-
- destroy(pvt);
-}
diff --git a/main/udptl.c b/main/udptl.c
deleted file mode 100644
index 679282731..000000000
--- a/main/udptl.c
+++ /dev/null
@@ -1,1247 +0,0 @@
-/*
- * Asterisk -- A telephony toolkit for Linux.
- *
- * UDPTL support for T.38
- *
- * Copyright (C) 2005, Steve Underwood, partly based on RTP code which is
- * Copyright (C) 1999-2006, Digium, Inc.
- *
- * Steve Underwood <steveu@coppice.org>
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License
- *
- * A license has been granted to Digium (via disclaimer) for the use of
- * this code.
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <netinet/in.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-
-#include "asterisk/udptl.h"
-#include "asterisk/frame.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/channel.h"
-#include "asterisk/acl.h"
-#include "asterisk/channel.h"
-#include "asterisk/config.h"
-#include "asterisk/lock.h"
-#include "asterisk/utils.h"
-#include "asterisk/cli.h"
-#include "asterisk/unaligned.h"
-#include "asterisk/utils.h"
-
-#define UDPTL_MTU 1200
-
-#if !defined(FALSE)
-#define FALSE 0
-#endif
-#if !defined(TRUE)
-#define TRUE (!FALSE)
-#endif
-
-static int udptlstart;
-static int udptlend;
-static int udptldebug; /* Are we debugging? */
-static struct sockaddr_in udptldebugaddr; /* Debug packets to/from this host */
-#ifdef SO_NO_CHECK
-static int nochecksums;
-#endif
-static int udptlfectype;
-static int udptlfecentries;
-static int udptlfecspan;
-static int udptlmaxdatagram;
-
-#define LOCAL_FAX_MAX_DATAGRAM 400
-#define MAX_FEC_ENTRIES 5
-#define MAX_FEC_SPAN 5
-
-#define UDPTL_BUF_MASK 15
-
-typedef struct {
- int buf_len;
- uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
-} udptl_fec_tx_buffer_t;
-
-typedef struct {
- int buf_len;
- uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
- int fec_len[MAX_FEC_ENTRIES];
- uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM];
- int fec_span;
- int fec_entries;
-} udptl_fec_rx_buffer_t;
-
-struct ast_udptl {
- int fd;
- char resp;
- struct ast_frame f[16];
- unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
- unsigned int lasteventseqn;
- int nat;
- int flags;
- struct sockaddr_in us;
- struct sockaddr_in them;
- int *ioid;
- struct sched_context *sched;
- struct io_context *io;
- void *data;
- ast_udptl_callback callback;
- int udptl_offered_from_local;
-
- /*! This option indicates the error correction scheme used in transmitted UDPTL
- packets. */
- int error_correction_scheme;
-
- /*! This option indicates the number of error correction entries transmitted in
- UDPTL packets. */
- int error_correction_entries;
-
- /*! This option indicates the span of the error correction entries in transmitted
- UDPTL packets (FEC only). */
- int error_correction_span;
-
- /*! This option indicates the maximum size of a UDPTL packet that can be accepted by
- the remote device. */
- int far_max_datagram_size;
-
- /*! This option indicates the maximum size of a UDPTL packet that we are prepared to
- accept. */
- int local_max_datagram_size;
-
- int verbose;
-
- struct sockaddr_in far;
-
- int tx_seq_no;
- int rx_seq_no;
- int rx_expected_seq_no;
-
- udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1];
- udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1];
-};
-
-static struct ast_udptl_protocol *protos;
-
-static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len);
-static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, int ifp_len);
-
-static inline int udptl_debug_test_addr(struct sockaddr_in *addr)
-{
- if (udptldebug == 0)
- return 0;
- if (udptldebugaddr.sin_addr.s_addr) {
- if (((ntohs(udptldebugaddr.sin_port) != 0)
- && (udptldebugaddr.sin_port != addr->sin_port))
- || (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
- return 0;
- }
- return 1;
-}
-
-static int decode_length(uint8_t *buf, int limit, int *len, int *pvalue)
-{
- if (*len >= limit)
- return -1;
- if ((buf[*len] & 0x80) == 0) {
- *pvalue = buf[*len];
- (*len)++;
- return 0;
- }
- if ((buf[*len] & 0x40) == 0) {
- if (*len == limit - 1)
- return -1;
- *pvalue = (buf[*len] & 0x3F) << 8;
- (*len)++;
- *pvalue |= buf[*len];
- (*len)++;
- return 0;
- }
- *pvalue = (buf[*len] & 0x3F) << 14;
- (*len)++;
- /* Indicate we have a fragment */
- return 1;
-}
-/*- End of function --------------------------------------------------------*/
-
-static int decode_open_type(uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets)
-{
- int octet_cnt;
- int octet_idx;
- int stat;
- int i;
- const uint8_t **pbuf;
-
- for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) {
- if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0)
- return -1;
- if (octet_cnt > 0) {
- *p_num_octets += octet_cnt;
-
- pbuf = &p_object[octet_idx];
- i = 0;
- /* Make sure the buffer contains at least the number of bits requested */
- if ((*len + octet_cnt) > limit)
- return -1;
-
- *pbuf = &buf[*len];
- *len += octet_cnt;
- }
- if (stat == 0)
- break;
- }
- return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-static int encode_length(uint8_t *buf, int *len, int value)
-{
- int multiplier;
-
- if (value < 0x80) {
- /* 1 octet */
- buf[*len] = value;
- (*len)++;
- return value;
- }
- if (value < 0x4000) {
- /* 2 octets */
- /* Set the first bit of the first octet */
- buf[*len] = ((0x8000 | value) >> 8) & 0xFF;
- (*len)++;
- buf[*len] = value & 0xFF;
- (*len)++;
- return value;
- }
- /* Fragmentation */
- multiplier = (value < 0x10000) ? (value >> 14) : 4;
- /* Set the first 2 bits of the octet */
- buf[*len] = 0xC0 | multiplier;
- (*len)++;
- return multiplier << 14;
-}
-/*- End of function --------------------------------------------------------*/
-
-static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num_octets)
-{
- int enclen;
- int octet_idx;
- uint8_t zero_byte;
-
- /* If open type is of zero length, add a single zero byte (10.1) */
- if (num_octets == 0) {
- zero_byte = 0;
- data = &zero_byte;
- num_octets = 1;
- }
- /* Encode the open type */
- for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
- if ((enclen = encode_length(buf, len, num_octets)) < 0)
- return -1;
- if (enclen > 0) {
- memcpy(&buf[*len], &data[octet_idx], enclen);
- *len += enclen;
- }
- if (enclen >= num_octets)
- break;
- }
-
- return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
-{
- int stat;
- int stat2;
- int i;
- int j;
- int k;
- int l;
- int m;
- int x;
- int limit;
- int which;
- int ptr;
- int count;
- int total_count;
- int seq_no;
- const uint8_t *ifp;
- const uint8_t *data;
- int ifp_len;
- int repaired[16];
- const uint8_t *bufs[16];
- int lengths[16];
- int span;
- int entries;
- int ifp_no;
-
- ptr = 0;
- ifp_no = 0;
- memset(&s->f[0], 0, sizeof(s->f[0]));
-
- /* Decode seq_number */
- if (ptr + 2 > len)
- return -1;
- seq_no = (buf[0] << 8) | buf[1];
- ptr += 2;
-
- /* Break out the primary packet */
- if ((stat = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0)
- return -1;
- /* Decode error_recovery */
- if (ptr + 1 > len)
- return -1;
- if ((buf[ptr++] & 0x80) == 0) {
- /* Secondary packet mode for error recovery */
- if (seq_no > s->rx_seq_no) {
- /* We received a later packet than we expected, so we need to check if we can fill in the gap from the
- secondary packets. */
- total_count = 0;
- do {
- if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
- return -1;
- for (i = 0; i < count; i++) {
- if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0)
- return -1;
- }
- total_count += count;
- }
- while (stat2 > 0);
- /* Step through in reverse order, so we go oldest to newest */
- for (i = total_count; i > 0; i--) {
- if (seq_no - i >= s->rx_seq_no) {
- /* This one wasn't seen before */
- /* Decode the secondary IFP packet */
- //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]);
- s->f[ifp_no].frametype = AST_FRAME_MODEM;
- s->f[ifp_no].subclass = AST_MODEM_T38;
-
- s->f[ifp_no].mallocd = 0;
- s->f[ifp_no].seqno = seq_no - i;
- s->f[ifp_no].datalen = lengths[i - 1];
- s->f[ifp_no].data = (uint8_t *) bufs[i - 1];
- s->f[ifp_no].offset = 0;
- s->f[ifp_no].src = "UDPTL";
- if (ifp_no > 0)
- AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
- AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
- ifp_no++;
- }
- }
- }
- }
- else
- {
- /* FEC mode for error recovery */
- /* Our buffers cannot tolerate overlength IFP packets in FEC mode */
- if (ifp_len > LOCAL_FAX_MAX_DATAGRAM)
- return -1;
- /* Update any missed slots in the buffer */
- for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) {
- x = s->rx_seq_no & UDPTL_BUF_MASK;
- s->rx[x].buf_len = -1;
- s->rx[x].fec_len[0] = 0;
- s->rx[x].fec_span = 0;
- s->rx[x].fec_entries = 0;
- }
-
- x = seq_no & UDPTL_BUF_MASK;
-
- memset(repaired, 0, sizeof(repaired));
-
- /* Save the new IFP packet */
- memcpy(s->rx[x].buf, ifp, ifp_len);
- s->rx[x].buf_len = ifp_len;
- repaired[x] = TRUE;
-
- /* Decode the FEC packets */
- /* The span is defined as an unconstrained integer, but will never be more
- than a small value. */
- if (ptr + 2 > len)
- return -1;
- if (buf[ptr++] != 1)
- return -1;
- span = buf[ptr++];
- s->rx[x].fec_span = span;
-
- /* The number of entries is defined as a length, but will only ever be a small
- value. Treat it as such. */
- if (ptr + 1 > len)
- return -1;
- entries = buf[ptr++];
- s->rx[x].fec_entries = entries;
-
- /* Decode the elements */
- for (i = 0; i < entries; i++) {
- if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0)
- return -1;
- if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM)
- return -1;
-
- /* Save the new FEC data */
- memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]);
-#if 0
- fprintf(stderr, "FEC: ");
- for (j = 0; j < s->rx[x].fec_len[i]; j++)
- fprintf(stderr, "%02X ", data[j]);
- fprintf(stderr, "\n");
-#endif
- }
-
- /* See if we can reconstruct anything which is missing */
- /* TODO: this does not comprehensively hunt back and repair everything that is possible */
- for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) {
- if (s->rx[l].fec_len[0] <= 0)
- continue;
- for (m = 0; m < s->rx[l].fec_entries; m++) {
- limit = (l + m) & UDPTL_BUF_MASK;
- for (which = -1, k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) {
- if (s->rx[k].buf_len <= 0)
- which = (which == -1) ? k : -2;
- }
- if (which >= 0) {
- /* Repairable */
- for (j = 0; j < s->rx[l].fec_len[m]; j++) {
- s->rx[which].buf[j] = s->rx[l].fec[m][j];
- for (k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
- s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
- }
- s->rx[which].buf_len = s->rx[l].fec_len[m];
- repaired[which] = TRUE;
- }
- }
- }
- /* Now play any new packets forwards in time */
- for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) {
- if (repaired[l]) {
- //fprintf(stderr, "Fixed packet %d, len %d\n", j, l);
- s->f[ifp_no].frametype = AST_FRAME_MODEM;
- s->f[ifp_no].subclass = AST_MODEM_T38;
-
- s->f[ifp_no].mallocd = 0;
- s->f[ifp_no].seqno = j;
- s->f[ifp_no].datalen = s->rx[l].buf_len;
- s->f[ifp_no].data = s->rx[l].buf;
- s->f[ifp_no].offset = 0;
- s->f[ifp_no].src = "UDPTL";
- if (ifp_no > 0)
- AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
- AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
- ifp_no++;
- }
- }
- }
-
- /* If packets are received out of sequence, we may have already processed this packet from the error
- recovery information in a packet already received. */
- if (seq_no >= s->rx_seq_no) {
- /* Decode the primary IFP packet */
- s->f[ifp_no].frametype = AST_FRAME_MODEM;
- s->f[ifp_no].subclass = AST_MODEM_T38;
-
- s->f[ifp_no].mallocd = 0;
- s->f[ifp_no].seqno = seq_no;
- s->f[ifp_no].datalen = ifp_len;
- s->f[ifp_no].data = (uint8_t *) ifp;
- s->f[ifp_no].offset = 0;
- s->f[ifp_no].src = "UDPTL";
- if (ifp_no > 0)
- AST_LIST_NEXT(&s->f[ifp_no - 1], frame_list) = &s->f[ifp_no];
- AST_LIST_NEXT(&s->f[ifp_no], frame_list) = NULL;
-
- ifp_no++;
- }
-
- s->rx_seq_no = seq_no + 1;
- return ifp_no;
-}
-/*- End of function --------------------------------------------------------*/
-
-static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, int ifp_len)
-{
- uint8_t fec[LOCAL_FAX_MAX_DATAGRAM];
- int i;
- int j;
- int seq;
- int entry;
- int entries;
- int span;
- int m;
- int len;
- int limit;
- int high_tide;
-
- seq = s->tx_seq_no & 0xFFFF;
-
- /* Map the sequence number to an entry in the circular buffer */
- entry = seq & UDPTL_BUF_MASK;
-
- /* We save the message in a circular buffer, for generating FEC or
- redundancy sets later on. */
- s->tx[entry].buf_len = ifp_len;
- memcpy(s->tx[entry].buf, ifp, ifp_len);
-
- /* Build the UDPTLPacket */
-
- len = 0;
- /* Encode the sequence number */
- buf[len++] = (seq >> 8) & 0xFF;
- buf[len++] = seq & 0xFF;
-
- /* Encode the primary IFP packet */
- if (encode_open_type(buf, &len, ifp, ifp_len) < 0)
- return -1;
-
- /* Encode the appropriate type of error recovery information */
- switch (s->error_correction_scheme)
- {
- case UDPTL_ERROR_CORRECTION_NONE:
- /* Encode the error recovery type */
- buf[len++] = 0x00;
- /* The number of entries will always be zero, so it is pointless allowing
- for the fragmented case here. */
- if (encode_length(buf, &len, 0) < 0)
- return -1;
- break;
- case UDPTL_ERROR_CORRECTION_REDUNDANCY:
- /* Encode the error recovery type */
- buf[len++] = 0x00;
- if (s->tx_seq_no > s->error_correction_entries)
- entries = s->error_correction_entries;
- else
- entries = s->tx_seq_no;
- /* The number of entries will always be small, so it is pointless allowing
- for the fragmented case here. */
- if (encode_length(buf, &len, entries) < 0)
- return -1;
- /* Encode the elements */
- for (i = 0; i < entries; i++) {
- j = (entry - i - 1) & UDPTL_BUF_MASK;
- if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0)
- return -1;
- }
- break;
- case UDPTL_ERROR_CORRECTION_FEC:
- span = s->error_correction_span;
- entries = s->error_correction_entries;
- if (seq < s->error_correction_span*s->error_correction_entries) {
- /* In the initial stages, wind up the FEC smoothly */
- entries = seq/s->error_correction_span;
- if (seq < s->error_correction_span)
- span = 0;
- }
- /* Encode the error recovery type */
- buf[len++] = 0x80;
- /* Span is defined as an inconstrained integer, which it dumb. It will only
- ever be a small value. Treat it as such. */
- buf[len++] = 1;
- buf[len++] = span;
- /* The number of entries is defined as a length, but will only ever be a small
- value. Treat it as such. */
- buf[len++] = entries;
- for (m = 0; m < entries; m++) {
- /* Make an XOR'ed entry the maximum length */
- limit = (entry + m) & UDPTL_BUF_MASK;
- high_tide = 0;
- for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) {
- if (high_tide < s->tx[i].buf_len) {
- for (j = 0; j < high_tide; j++)
- fec[j] ^= s->tx[i].buf[j];
- for ( ; j < s->tx[i].buf_len; j++)
- fec[j] = s->tx[i].buf[j];
- high_tide = s->tx[i].buf_len;
- } else {
- for (j = 0; j < s->tx[i].buf_len; j++)
- fec[j] ^= s->tx[i].buf[j];
- }
- }
- if (encode_open_type(buf, &len, fec, high_tide) < 0)
- return -1;
- }
- break;
- }
-
- if (s->verbose)
- fprintf(stderr, "\n");
-
- s->tx_seq_no++;
- return len;
-}
-
-int ast_udptl_fd(struct ast_udptl *udptl)
-{
- return udptl->fd;
-}
-
-void ast_udptl_set_data(struct ast_udptl *udptl, void *data)
-{
- udptl->data = data;
-}
-
-void ast_udptl_set_callback(struct ast_udptl *udptl, ast_udptl_callback callback)
-{
- udptl->callback = callback;
-}
-
-void ast_udptl_setnat(struct ast_udptl *udptl, int nat)
-{
- udptl->nat = nat;
-}
-
-static int udptlread(int *id, int fd, short events, void *cbdata)
-{
- struct ast_udptl *udptl = cbdata;
- struct ast_frame *f;
-
- if ((f = ast_udptl_read(udptl))) {
- if (udptl->callback)
- udptl->callback(udptl, f, udptl->data);
- }
- return 1;
-}
-
-struct ast_frame *ast_udptl_read(struct ast_udptl *udptl)
-{
- int res;
- struct sockaddr_in sin;
- socklen_t len;
- uint16_t seqno = 0;
- uint16_t *udptlheader;
-
- len = sizeof(sin);
-
- /* Cache where the header will go */
- res = recvfrom(udptl->fd,
- udptl->rawdata + AST_FRIENDLY_OFFSET,
- sizeof(udptl->rawdata) - AST_FRIENDLY_OFFSET,
- 0,
- (struct sockaddr *) &sin,
- &len);
- udptlheader = (uint16_t *)(udptl->rawdata + AST_FRIENDLY_OFFSET);
- if (res < 0) {
- if (errno != EAGAIN)
- ast_log(LOG_WARNING, "UDPTL read error: %s\n", strerror(errno));
- ast_assert(errno != EBADF);
- return &ast_null_frame;
- }
-
- /* Ignore if the other side hasn't been given an address yet. */
- if (!udptl->them.sin_addr.s_addr || !udptl->them.sin_port)
- return &ast_null_frame;
-
- if (udptl->nat) {
- /* Send to whoever sent to us */
- if ((udptl->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
- (udptl->them.sin_port != sin.sin_port)) {
- memcpy(&udptl->them, &sin, sizeof(udptl->them));
- ast_log(LOG_DEBUG, "UDPTL NAT: Using address %s:%d\n", ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
- }
- }
-
- if (udptl_debug_test_addr(&sin)) {
- ast_verbose("Got UDPTL packet from %s:%d (type %d, seq %d, len %d)\n",
- ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), 0, seqno, res);
- }
-#if 0
- printf("Got UDPTL packet from %s:%d (seq %d, len = %d)\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), seqno, res);
-#endif
- if (udptl_rx_packet(udptl, udptl->rawdata + AST_FRIENDLY_OFFSET, res) < 1)
- return &ast_null_frame;
-
- return &udptl->f[0];
-}
-
-void ast_udptl_offered_from_local(struct ast_udptl* udptl, int local)
-{
- if (udptl)
- udptl->udptl_offered_from_local = local;
- else
- ast_log(LOG_WARNING, "udptl structure is null\n");
-}
-
-int ast_udptl_get_error_correction_scheme(struct ast_udptl* udptl)
-{
- if (udptl)
- return udptl->error_correction_scheme;
- else {
- ast_log(LOG_WARNING, "udptl structure is null\n");
- return -1;
- }
-}
-
-void ast_udptl_set_error_correction_scheme(struct ast_udptl* udptl, int ec)
-{
- if (udptl) {
- switch (ec) {
- case UDPTL_ERROR_CORRECTION_FEC:
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC;
- break;
- case UDPTL_ERROR_CORRECTION_REDUNDANCY:
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY;
- break;
- case UDPTL_ERROR_CORRECTION_NONE:
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE;
- break;
- default:
- ast_log(LOG_WARNING, "error correction parameter invalid\n");
- };
- } else
- ast_log(LOG_WARNING, "udptl structure is null\n");
-}
-
-int ast_udptl_get_local_max_datagram(struct ast_udptl* udptl)
-{
- if (udptl)
- return udptl->local_max_datagram_size;
- else {
- ast_log(LOG_WARNING, "udptl structure is null\n");
- return -1;
- }
-}
-
-int ast_udptl_get_far_max_datagram(struct ast_udptl* udptl)
-{
- if (udptl)
- return udptl->far_max_datagram_size;
- else {
- ast_log(LOG_WARNING, "udptl structure is null\n");
- return -1;
- }
-}
-
-void ast_udptl_set_local_max_datagram(struct ast_udptl* udptl, int max_datagram)
-{
- if (udptl)
- udptl->local_max_datagram_size = max_datagram;
- else
- ast_log(LOG_WARNING, "udptl structure is null\n");
-}
-
-void ast_udptl_set_far_max_datagram(struct ast_udptl* udptl, int max_datagram)
-{
- if (udptl)
- udptl->far_max_datagram_size = max_datagram;
- else
- ast_log(LOG_WARNING, "udptl structure is null\n");
-}
-
-struct ast_udptl *ast_udptl_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int callbackmode, struct in_addr addr)
-{
- struct ast_udptl *udptl;
- int x;
- int startplace;
- int i;
- long int flags;
-
- if (!(udptl = ast_calloc(1, sizeof(*udptl))))
- return NULL;
-
- if (udptlfectype == 2)
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_FEC;
- else if (udptlfectype == 1)
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_REDUNDANCY;
- else
- udptl->error_correction_scheme = UDPTL_ERROR_CORRECTION_NONE;
- udptl->error_correction_span = udptlfecspan;
- udptl->error_correction_entries = udptlfecentries;
-
- udptl->far_max_datagram_size = udptlmaxdatagram;
- udptl->local_max_datagram_size = udptlmaxdatagram;
-
- memset(&udptl->rx, 0, sizeof(udptl->rx));
- memset(&udptl->tx, 0, sizeof(udptl->tx));
- for (i = 0; i <= UDPTL_BUF_MASK; i++) {
- udptl->rx[i].buf_len = -1;
- udptl->tx[i].buf_len = -1;
- }
-
- udptl->them.sin_family = AF_INET;
- udptl->us.sin_family = AF_INET;
-
- if ((udptl->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- free(udptl);
- ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
- return NULL;
- }
- flags = fcntl(udptl->fd, F_GETFL);
- fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK);
-#ifdef SO_NO_CHECK
- if (nochecksums)
- setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
-#endif
- /* Find us a place */
- x = (ast_random() % (udptlend - udptlstart)) + udptlstart;
- startplace = x;
- for (;;) {
- udptl->us.sin_port = htons(x);
- udptl->us.sin_addr = addr;
- if (bind(udptl->fd, (struct sockaddr *) &udptl->us, sizeof(udptl->us)) == 0)
- break;
- if (errno != EADDRINUSE) {
- ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
- close(udptl->fd);
- free(udptl);
- return NULL;
- }
- if (++x > udptlend)
- x = udptlstart;
- if (x == startplace) {
- ast_log(LOG_WARNING, "No UDPTL ports remaining\n");
- close(udptl->fd);
- free(udptl);
- return NULL;
- }
- }
- if (io && sched && callbackmode) {
- /* Operate this one in a callback mode */
- udptl->sched = sched;
- udptl->io = io;
- udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl);
- }
- return udptl;
-}
-
-struct ast_udptl *ast_udptl_new(struct sched_context *sched, struct io_context *io, int callbackmode)
-{
- struct in_addr ia;
- memset(&ia, 0, sizeof(ia));
- return ast_udptl_new_with_bindaddr(sched, io, callbackmode, ia);
-}
-
-int ast_udptl_settos(struct ast_udptl *udptl, int tos)
-{
- int res;
-
- if ((res = setsockopt(udptl->fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))))
- ast_log(LOG_WARNING, "UDPTL unable to set TOS to %d\n", tos);
- return res;
-}
-
-void ast_udptl_set_peer(struct ast_udptl *udptl, struct sockaddr_in *them)
-{
- udptl->them.sin_port = them->sin_port;
- udptl->them.sin_addr = them->sin_addr;
-}
-
-void ast_udptl_get_peer(struct ast_udptl *udptl, struct sockaddr_in *them)
-{
- memset(them, 0, sizeof(*them));
- them->sin_family = AF_INET;
- them->sin_port = udptl->them.sin_port;
- them->sin_addr = udptl->them.sin_addr;
-}
-
-void ast_udptl_get_us(struct ast_udptl *udptl, struct sockaddr_in *us)
-{
- memcpy(us, &udptl->us, sizeof(udptl->us));
-}
-
-void ast_udptl_stop(struct ast_udptl *udptl)
-{
- memset(&udptl->them.sin_addr, 0, sizeof(udptl->them.sin_addr));
- memset(&udptl->them.sin_port, 0, sizeof(udptl->them.sin_port));
-}
-
-void ast_udptl_destroy(struct ast_udptl *udptl)
-{
- if (udptl->ioid)
- ast_io_remove(udptl->io, udptl->ioid);
- if (udptl->fd > -1)
- close(udptl->fd);
- free(udptl);
-}
-
-int ast_udptl_write(struct ast_udptl *s, struct ast_frame *f)
-{
- int seq;
- int len;
- int res;
- uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
-
- /* If we have no peer, return immediately */
- if (s->them.sin_addr.s_addr == INADDR_ANY)
- return 0;
-
- /* If there is no data length, return immediately */
- if (f->datalen == 0)
- return 0;
-
- if (f->frametype != AST_FRAME_MODEM) {
- ast_log(LOG_WARNING, "UDPTL can only send T.38 data\n");
- return -1;
- }
-
- /* Save seq_no for debug output because udptl_build_packet increments it */
- seq = s->tx_seq_no & 0xFFFF;
-
- /* Cook up the UDPTL packet, with the relevant EC info. */
- len = udptl_build_packet(s, buf, f->data, f->datalen);
-
- if (len > 0 && s->them.sin_port && s->them.sin_addr.s_addr) {
- if ((res = sendto(s->fd, buf, len, 0, (struct sockaddr *) &s->them, sizeof(s->them))) < 0)
- ast_log(LOG_NOTICE, "UDPTL Transmission error to %s:%d: %s\n", ast_inet_ntoa(s->them.sin_addr), ntohs(s->them.sin_port), strerror(errno));
-#if 0
- printf("Sent %d bytes of UDPTL data to %s:%d\n", res, ast_inet_ntoa(udptl->them.sin_addr), ntohs(udptl->them.sin_port));
-#endif
- if (udptl_debug_test_addr(&s->them))
- ast_verbose("Sent UDPTL packet to %s:%d (type %d, seq %d, len %d)\n",
- ast_inet_ntoa(s->them.sin_addr),
- ntohs(s->them.sin_port), 0, seq, len);
- }
-
- return 0;
-}
-
-void ast_udptl_proto_unregister(struct ast_udptl_protocol *proto)
-{
- struct ast_udptl_protocol *cur;
- struct ast_udptl_protocol *prev;
-
- cur = protos;
- prev = NULL;
- while (cur) {
- if (cur == proto) {
- if (prev)
- prev->next = proto->next;
- else
- protos = proto->next;
- return;
- }
- prev = cur;
- cur = cur->next;
- }
-}
-
-int ast_udptl_proto_register(struct ast_udptl_protocol *proto)
-{
- struct ast_udptl_protocol *cur;
-
- cur = protos;
- while (cur) {
- if (cur->type == proto->type) {
- ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
- return -1;
- }
- cur = cur->next;
- }
- proto->next = protos;
- protos = proto;
- return 0;
-}
-
-static struct ast_udptl_protocol *get_proto(struct ast_channel *chan)
-{
- struct ast_udptl_protocol *cur;
-
- cur = protos;
- while (cur) {
- if (cur->type == chan->tech->type)
- return cur;
- cur = cur->next;
- }
- return NULL;
-}
-
-int ast_udptl_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
-{
- struct ast_frame *f;
- struct ast_channel *who;
- struct ast_channel *cs[3];
- struct ast_udptl *p0;
- struct ast_udptl *p1;
- struct ast_udptl_protocol *pr0;
- struct ast_udptl_protocol *pr1;
- struct sockaddr_in ac0;
- struct sockaddr_in ac1;
- struct sockaddr_in t0;
- struct sockaddr_in t1;
- void *pvt0;
- void *pvt1;
- int to;
-
- ast_channel_lock(c0);
- while (ast_channel_trylock(c1)) {
- ast_channel_unlock(c0);
- usleep(1);
- ast_channel_lock(c0);
- }
- pr0 = get_proto(c0);
- pr1 = get_proto(c1);
- if (!pr0) {
- ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return -1;
- }
- if (!pr1) {
- ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return -1;
- }
- pvt0 = c0->tech_pvt;
- pvt1 = c1->tech_pvt;
- p0 = pr0->get_udptl_info(c0);
- p1 = pr1->get_udptl_info(c1);
- if (!p0 || !p1) {
- /* Somebody doesn't want to play... */
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- return -2;
- }
- if (pr0->set_udptl_peer(c0, p1)) {
- ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
- memset(&ac1, 0, sizeof(ac1));
- } else {
- /* Store UDPTL peer */
- ast_udptl_get_peer(p1, &ac1);
- }
- if (pr1->set_udptl_peer(c1, p0)) {
- ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
- memset(&ac0, 0, sizeof(ac0));
- } else {
- /* Store UDPTL peer */
- ast_udptl_get_peer(p0, &ac0);
- }
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- cs[0] = c0;
- cs[1] = c1;
- cs[2] = NULL;
- for (;;) {
- if ((c0->tech_pvt != pvt0) ||
- (c1->tech_pvt != pvt1) ||
- (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
- ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
- /* Tell it to try again later */
- return -3;
- }
- to = -1;
- ast_udptl_get_peer(p1, &t1);
- ast_udptl_get_peer(p0, &t0);
- if (inaddrcmp(&t1, &ac1)) {
- ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n",
- c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port));
- ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n",
- c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port));
- memcpy(&ac1, &t1, sizeof(ac1));
- }
- if (inaddrcmp(&t0, &ac0)) {
- ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d\n",
- c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port));
- ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d\n",
- c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port));
- memcpy(&ac0, &t0, sizeof(ac0));
- }
- who = ast_waitfor_n(cs, 2, &to);
- if (!who) {
- ast_log(LOG_DEBUG, "Ooh, empty read...\n");
- /* check for hangup / whentohangup */
- if (ast_check_hangup(c0) || ast_check_hangup(c1))
- break;
- continue;
- }
- f = ast_read(who);
- if (!f) {
- *fo = f;
- *rc = who;
- ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
- /* That's all we needed */
- return 0;
- } else {
- if (f->frametype == AST_FRAME_MODEM) {
- /* Forward T.38 frames if they happen upon us */
- if (who == c0) {
- ast_write(c1, f);
- } else if (who == c1) {
- ast_write(c0, f);
- }
- }
- ast_frfree(f);
- }
- /* Swap priority. Not that it's a big deal at this point */
- cs[2] = cs[0];
- cs[0] = cs[1];
- cs[1] = cs[2];
- }
- return -1;
-}
-
-static int udptl_do_debug_ip(int fd, int argc, char *argv[])
-{
- struct hostent *hp;
- struct ast_hostent ahp;
- int port;
- char *p;
- char *arg;
-
- port = 0;
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- arg = argv[3];
- p = strstr(arg, ":");
- if (p) {
- *p = '\0';
- p++;
- port = atoi(p);
- }
- hp = ast_gethostbyname(arg, &ahp);
- if (hp == NULL)
- return RESULT_SHOWUSAGE;
- udptldebugaddr.sin_family = AF_INET;
- memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
- udptldebugaddr.sin_port = htons(port);
- if (port == 0)
- ast_cli(fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
- else
- ast_cli(fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
- udptldebug = 1;
- return RESULT_SUCCESS;
-}
-
-static int udptl_do_debug(int fd, int argc, char *argv[])
-{
- if (argc != 2) {
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- return udptl_do_debug_ip(fd, argc, argv);
- }
- udptldebug = 1;
- memset(&udptldebugaddr,0,sizeof(udptldebugaddr));
- ast_cli(fd, "UDPTL Debugging Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int udptl_nodebug(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- udptldebug = 0;
- ast_cli(fd,"UDPTL Debugging Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static char debug_usage[] =
- "Usage: udptl debug [ip host[:port]]\n"
- " Enable dumping of all UDPTL packets to and from host.\n";
-
-static char nodebug_usage[] =
- "Usage: udptl debug off\n"
- " Disable all UDPTL debugging\n";
-
-static struct ast_cli_entry cli_udptl_no_debug = {
- { "udptl", "no", "debug", NULL },
- udptl_nodebug, NULL,
- NULL };
-
-static struct ast_cli_entry cli_udptl[] = {
- { { "udptl", "debug", NULL },
- udptl_do_debug, "Enable UDPTL debugging",
- debug_usage },
-
- { { "udptl", "debug", "ip", NULL },
- udptl_do_debug, "Enable UDPTL debugging on IP",
- debug_usage },
-
- { { "udptl", "debug", "off", NULL },
- udptl_nodebug, "Disable UDPTL debugging",
- nodebug_usage, NULL, &cli_udptl_no_debug },
-};
-
-void ast_udptl_reload(void)
-{
- struct ast_config *cfg;
- const char *s;
-
- udptlstart = 4500;
- udptlend = 4999;
- udptlfectype = 0;
- udptlfecentries = 0;
- udptlfecspan = 0;
- udptlmaxdatagram = 0;
-
- if ((cfg = ast_config_load("udptl.conf"))) {
- if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) {
- udptlstart = atoi(s);
- if (udptlstart < 1024)
- udptlstart = 1024;
- if (udptlstart > 65535)
- udptlstart = 65535;
- }
- if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) {
- udptlend = atoi(s);
- if (udptlend < 1024)
- udptlend = 1024;
- if (udptlend > 65535)
- udptlend = 65535;
- }
- if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) {
-#ifdef SO_NO_CHECK
- if (ast_false(s))
- nochecksums = 1;
- else
- nochecksums = 0;
-#else
- if (ast_false(s))
- ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n");
-#endif
- }
- if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) {
- if (strcmp(s, "t38UDPFEC") == 0)
- udptlfectype = 2;
- else if (strcmp(s, "t38UDPRedundancy") == 0)
- udptlfectype = 1;
- }
- if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) {
- udptlmaxdatagram = atoi(s);
- if (udptlmaxdatagram < 0)
- udptlmaxdatagram = 0;
- if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM)
- udptlmaxdatagram = LOCAL_FAX_MAX_DATAGRAM;
- }
- if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) {
- udptlfecentries = atoi(s);
- if (udptlfecentries < 0)
- udptlfecentries = 0;
- if (udptlfecentries > MAX_FEC_ENTRIES)
- udptlfecentries = MAX_FEC_ENTRIES;
- }
- if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) {
- udptlfecspan = atoi(s);
- if (udptlfecspan < 0)
- udptlfecspan = 0;
- if (udptlfecspan > MAX_FEC_SPAN)
- udptlfecspan = MAX_FEC_SPAN;
- }
- ast_config_destroy(cfg);
- }
- if (udptlstart >= udptlend) {
- ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end\n");
- udptlstart = 4500;
- udptlend = 4999;
- }
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend);
-}
-
-void ast_udptl_init(void)
-{
- ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry));
- ast_udptl_reload();
-}
diff --git a/main/ulaw.c b/main/ulaw.c
deleted file mode 100644
index 2735f6cce..000000000
--- a/main/ulaw.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief u-Law to Signed linear conversion
- *
- * \author Mark Spencer <markster@digium.com>
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/ulaw.h"
-
-#define ZEROTRAP /*!< turn on the trap as per the MIL-STD */
-#define BIAS 0x84 /*!< define the add-in bias for 16 bit samples */
-#define CLIP 32635
-
-unsigned char __ast_lin2mu[16384];
-short __ast_mulaw[256];
-
-
-static unsigned char linear2ulaw(short sample)
-{
- static int exp_lut[256] = {
- 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
- 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 };
- int sign, exponent, mantissa;
- unsigned char ulawbyte;
-
- /* Get the sample into sign-magnitude. */
- sign = (sample >> 8) & 0x80; /* set aside the sign */
- if (sign != 0)
- sample = -sample; /* get magnitude */
- if (sample > CLIP)
- sample = CLIP; /* clip the magnitude */
-
- /* Convert from 16 bit linear to ulaw. */
- sample = sample + BIAS;
- exponent = exp_lut[(sample >> 7) & 0xFF];
- mantissa = (sample >> (exponent + 3)) & 0x0F;
- ulawbyte = ~(sign | (exponent << 4) | mantissa);
-#ifdef ZEROTRAP
- if (ulawbyte == 0)
- ulawbyte = 0x02; /* optional CCITT trap */
-#endif
-
- return ulawbyte;
-}
-
-/*!
- * \brief Set up mu-law conversion table
- */
-void ast_ulaw_init(void)
-{
- int i;
- for (i = 0; i < 256; i++) {
- short mu, e, f, y;
- static short etab[] = {0,132,396,924,1980,4092,8316,16764};
-
- mu = 255 - i;
- e = (mu & 0x70) / 16;
- f = mu & 0x0f;
- y = f * (1 << (e + 3));
- y += etab[e];
- if (mu & 0x80)
- y = -y;
- __ast_mulaw[i] = y;
- }
- /* set up the reverse (mu-law) conversion table */
- for (i = -32768; i < 32768; i++) {
- __ast_lin2mu[((unsigned short)i) >> 2] = linear2ulaw(i);
- }
-}
-
diff --git a/main/utils.c b/main/utils.c
deleted file mode 100644
index d7863198b..000000000
--- a/main/utils.c
+++ /dev/null
@@ -1,1414 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2006, Digium, Inc.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Utility functions
- *
- * \note These are important for portability and security,
- * so please use them in favour of other routines.
- * Please consult the CODING GUIDELINES for more information.
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <ctype.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#define AST_API_MODULE /* ensure that inlinable API functions will be built in lock.h if required */
-#include "asterisk/lock.h"
-#include "asterisk/io.h"
-#include "asterisk/logger.h"
-#include "asterisk/md5.h"
-#include "asterisk/sha1.h"
-#include "asterisk/options.h"
-#include "asterisk/cli.h"
-#include "asterisk/linkedlists.h"
-
-#define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
-#include "asterisk/strings.h"
-
-#define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
-#include "asterisk/time.h"
-
-#define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
-#include "asterisk/stringfields.h"
-
-#define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
-#include "asterisk/utils.h"
-
-#define AST_API_MODULE
-#include "asterisk/threadstorage.h"
-
-static char base64[64];
-static char b2a[256];
-
-AST_THREADSTORAGE(inet_ntoa_buf, inet_ntoa_buf_init);
-
-#if !defined(HAVE_GETHOSTBYNAME_R_5) && !defined(HAVE_GETHOSTBYNAME_R_6)
-
-#define ERANGE 34 /*!< duh? ERANGE value copied from web... */
-#undef gethostbyname
-
-AST_MUTEX_DEFINE_STATIC(__mutex);
-
-/*! \brief Reentrant replacement for gethostbyname for BSD-based systems.
-\note This
-routine is derived from code originally written and placed in the public
-domain by Enzo Michelangeli <em@em.no-ip.com> */
-
-static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
- size_t buflen, struct hostent **result,
- int *h_errnop)
-{
- int hsave;
- struct hostent *ph;
- ast_mutex_lock(&__mutex); /* begin critical area */
- hsave = h_errno;
-
- ph = gethostbyname(name);
- *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
- if (ph == NULL) {
- *result = NULL;
- } else {
- char **p, **q;
- char *pbuf;
- int nbytes=0;
- int naddr=0, naliases=0;
- /* determine if we have enough space in buf */
-
- /* count how many addresses */
- for (p = ph->h_addr_list; *p != 0; p++) {
- nbytes += ph->h_length; /* addresses */
- nbytes += sizeof(*p); /* pointers */
- naddr++;
- }
- nbytes += sizeof(*p); /* one more for the terminating NULL */
-
- /* count how many aliases, and total length of strings */
- for (p = ph->h_aliases; *p != 0; p++) {
- nbytes += (strlen(*p)+1); /* aliases */
- nbytes += sizeof(*p); /* pointers */
- naliases++;
- }
- nbytes += sizeof(*p); /* one more for the terminating NULL */
-
- /* here nbytes is the number of bytes required in buffer */
- /* as a terminator must be there, the minimum value is ph->h_length */
- if (nbytes > buflen) {
- *result = NULL;
- ast_mutex_unlock(&__mutex); /* end critical area */
- return ERANGE; /* not enough space in buf!! */
- }
-
- /* There is enough space. Now we need to do a deep copy! */
- /* Allocation in buffer:
- from [0] to [(naddr-1) * sizeof(*p)]:
- pointers to addresses
- at [naddr * sizeof(*p)]:
- NULL
- from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
- pointers to aliases
- at [(naddr+naliases+1) * sizeof(*p)]:
- NULL
- then naddr addresses (fixed length), and naliases aliases (asciiz).
- */
-
- *ret = *ph; /* copy whole structure (not its address!) */
-
- /* copy addresses */
- q = (char **)buf; /* pointer to pointers area (type: char **) */
- ret->h_addr_list = q; /* update pointer to address list */
- pbuf = buf + ((naddr + naliases + 2) * sizeof(*p)); /* skip that area */
- for (p = ph->h_addr_list; *p != 0; p++) {
- memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
- *q++ = pbuf; /* the pointer is the one inside buf... */
- pbuf += ph->h_length; /* advance pbuf */
- }
- *q++ = NULL; /* address list terminator */
-
- /* copy aliases */
- ret->h_aliases = q; /* update pointer to aliases list */
- for (p = ph->h_aliases; *p != 0; p++) {
- strcpy(pbuf, *p); /* copy alias strings */
- *q++ = pbuf; /* the pointer is the one inside buf... */
- pbuf += strlen(*p); /* advance pbuf */
- *pbuf++ = 0; /* string terminator */
- }
- *q++ = NULL; /* terminator */
-
- strcpy(pbuf, ph->h_name); /* copy alias strings */
- ret->h_name = pbuf;
- pbuf += strlen(ph->h_name); /* advance pbuf */
- *pbuf++ = 0; /* string terminator */
-
- *result = ret; /* and let *result point to structure */
-
- }
- h_errno = hsave; /* restore h_errno */
- ast_mutex_unlock(&__mutex); /* end critical area */
-
- return (*result == NULL); /* return 0 on success, non-zero on error */
-}
-
-
-#endif
-
-/*! \brief Re-entrant (thread safe) version of gethostbyname that replaces the
- standard gethostbyname (which is not thread safe)
-*/
-struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
-{
- int res;
- int herrno;
- int dots=0;
- const char *s;
- struct hostent *result = NULL;
- /* Although it is perfectly legitimate to lookup a pure integer, for
- the sake of the sanity of people who like to name their peers as
- integers, we break with tradition and refuse to look up a
- pure integer */
- s = host;
- res = 0;
- while(s && *s) {
- if (*s == '.')
- dots++;
- else if (!isdigit(*s))
- break;
- s++;
- }
- if (!s || !*s) {
- /* Forge a reply for IP's to avoid octal IP's being interpreted as octal */
- if (dots != 3)
- return NULL;
- memset(hp, 0, sizeof(struct ast_hostent));
- hp->hp.h_addrtype = AF_INET;
- hp->hp.h_addr_list = (void *) hp->buf;
- hp->hp.h_addr = hp->buf + sizeof(void *);
- if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0)
- return &hp->hp;
- return NULL;
-
- }
-#ifdef HAVE_GETHOSTBYNAME_R_5
- result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
-
- if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
- return NULL;
-#else
- res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
-
- if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
- return NULL;
-#endif
- return &hp->hp;
-}
-
-/*! \brief Produce 32 char MD5 hash of value. */
-void ast_md5_hash(char *output, char *input)
-{
- struct MD5Context md5;
- unsigned char digest[16];
- char *ptr;
- int x;
-
- MD5Init(&md5);
- MD5Update(&md5, (unsigned char *)input, strlen(input));
- MD5Final(digest, &md5);
- ptr = output;
- for (x = 0; x < 16; x++)
- ptr += sprintf(ptr, "%2.2x", digest[x]);
-}
-
-/*! \brief Produce 40 char SHA1 hash of value. */
-void ast_sha1_hash(char *output, char *input)
-{
- struct SHA1Context sha;
- char *ptr;
- int x;
- uint8_t Message_Digest[20];
-
- SHA1Reset(&sha);
-
- SHA1Input(&sha, (const unsigned char *) input, strlen(input));
-
- SHA1Result(&sha, Message_Digest);
- ptr = output;
- for (x = 0; x < 20; x++)
- ptr += sprintf(ptr, "%2.2x", Message_Digest[x]);
-}
-
-/*! \brief decode BASE64 encoded text */
-int ast_base64decode(unsigned char *dst, const char *src, int max)
-{
- int cnt = 0;
- unsigned int byte = 0;
- unsigned int bits = 0;
- int incnt = 0;
- while(*src && (cnt < max)) {
- /* Shift in 6 bits of input */
- byte <<= 6;
- byte |= (b2a[(int)(*src)]) & 0x3f;
- bits += 6;
- src++;
- incnt++;
- /* If we have at least 8 bits left over, take that character
- off the top */
- if (bits >= 8) {
- bits -= 8;
- *dst = (byte >> bits) & 0xff;
- dst++;
- cnt++;
- }
- }
- /* Dont worry about left over bits, they're extra anyway */
- return cnt;
-}
-
-/*! \brief encode text to BASE64 coding */
-int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
-{
- int cnt = 0;
- int col = 0;
- unsigned int byte = 0;
- int bits = 0;
- int cntin = 0;
- /* Reserve space for null byte at end of string */
- max--;
- while ((cntin < srclen) && (cnt < max)) {
- byte <<= 8;
- byte |= *(src++);
- bits += 8;
- cntin++;
- if ((bits == 24) && (cnt + 4 <= max)) {
- *dst++ = base64[(byte >> 18) & 0x3f];
- *dst++ = base64[(byte >> 12) & 0x3f];
- *dst++ = base64[(byte >> 6) & 0x3f];
- *dst++ = base64[byte & 0x3f];
- cnt += 4;
- col += 4;
- bits = 0;
- byte = 0;
- }
- if (linebreaks && (cnt < max) && (col == 64)) {
- *dst++ = '\n';
- cnt++;
- col = 0;
- }
- }
- if (bits && (cnt + 4 <= max)) {
- /* Add one last character for the remaining bits,
- padding the rest with 0 */
- byte <<= 24 - bits;
- *dst++ = base64[(byte >> 18) & 0x3f];
- *dst++ = base64[(byte >> 12) & 0x3f];
- if (bits == 16)
- *dst++ = base64[(byte >> 6) & 0x3f];
- else
- *dst++ = '=';
- *dst++ = '=';
- cnt += 4;
- }
- if (linebreaks && (cnt < max)) {
- *dst++ = '\n';
- cnt++;
- }
- *dst = '\0';
- return cnt;
-}
-
-int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
-{
- return ast_base64encode_full(dst, src, srclen, max, 0);
-}
-
-static void base64_init(void)
-{
- int x;
- memset(b2a, -1, sizeof(b2a));
- /* Initialize base-64 Conversion table */
- for (x = 0; x < 26; x++) {
- /* A-Z */
- base64[x] = 'A' + x;
- b2a['A' + x] = x;
- /* a-z */
- base64[x + 26] = 'a' + x;
- b2a['a' + x] = x + 26;
- /* 0-9 */
- if (x < 10) {
- base64[x + 52] = '0' + x;
- b2a['0' + x] = x + 52;
- }
- }
- base64[62] = '+';
- base64[63] = '/';
- b2a[(int)'+'] = 62;
- b2a[(int)'/'] = 63;
-}
-
-/*! \brief ast_uri_encode: Turn text string to URI-encoded %XX version
-\note At this point, we're converting from ISO-8859-x (8-bit), not UTF8
- as in the SIP protocol spec
- If doreserved == 1 we will convert reserved characters also.
- RFC 2396, section 2.4
- outbuf needs to have more memory allocated than the instring
- to have room for the expansion. Every char that is converted
- is replaced by three ASCII characters.
-
- Note: The doreserved option is needed for replaces header in
- SIP transfers.
-*/
-char *ast_uri_encode(const char *string, char *outbuf, int buflen, int doreserved)
-{
- char *reserved = ";/?:@&=+$,# "; /* Reserved chars */
-
- const char *ptr = string; /* Start with the string */
- char *out = NULL;
- char *buf = NULL;
-
- ast_copy_string(outbuf, string, buflen);
-
- /* If there's no characters to convert, just go through and don't do anything */
- while (*ptr) {
- if (((unsigned char) *ptr) > 127 || (doreserved && strchr(reserved, *ptr)) ) {
- /* Oops, we need to start working here */
- if (!buf) {
- buf = outbuf;
- out = buf + (ptr - string) ; /* Set output ptr */
- }
- out += sprintf(out, "%%%02x", (unsigned char) *ptr);
- } else if (buf) {
- *out = *ptr; /* Continue copying the string */
- out++;
- }
- ptr++;
- }
- if (buf)
- *out = '\0';
- return outbuf;
-}
-
-/*! \brief ast_uri_decode: Decode SIP URI, URN, URL (overwrite the string) */
-void ast_uri_decode(char *s)
-{
- char *o;
- unsigned int tmp;
-
- for (o = s; *s; s++, o++) {
- if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
- /* have '%', two chars and correct parsing */
- *o = tmp;
- s += 2; /* Will be incremented once more when we break out */
- } else /* all other cases, just copy */
- *o = *s;
- }
- *o = '\0';
-}
-
-/*! \brief ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
-const char *ast_inet_ntoa(struct in_addr ia)
-{
- char *buf;
-
- if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN)))
- return "";
-
- return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
-}
-
-#ifndef __linux__
-#undef pthread_create /* For ast_pthread_create function only */
-#endif /* !__linux__ */
-
-#if !defined(LOW_MEMORY)
-
-#ifdef DEBUG_THREADS
-
-/*! \brief A reasonable maximum number of locks a thread would be holding ... */
-#define AST_MAX_LOCKS 64
-
-/* Allow direct use of pthread_mutex_t and friends */
-#undef pthread_mutex_t
-#undef pthread_mutex_lock
-#undef pthread_mutex_unlock
-#undef pthread_mutex_init
-#undef pthread_mutex_destroy
-
-/*!
- * \brief Keep track of which locks a thread holds
- *
- * There is an instance of this struct for every active thread
- */
-struct thr_lock_info {
- /*! The thread's ID */
- pthread_t thread_id;
- /*! The thread name which includes where the thread was started */
- const char *thread_name;
- /*! This is the actual container of info for what locks this thread holds */
- struct {
- const char *file;
- int line_num;
- const char *func;
- const char *lock_name;
- void *lock_addr;
- int times_locked;
- enum ast_lock_type type;
- /*! This thread is waiting on this lock */
- int pending:2;
- } locks[AST_MAX_LOCKS];
- /*! This is the number of locks currently held by this thread.
- * The index (num_locks - 1) has the info on the last one in the
- * locks member */
- unsigned int num_locks;
- /*! Protects the contents of the locks member
- * Intentionally not ast_mutex_t */
- pthread_mutex_t lock;
- AST_LIST_ENTRY(thr_lock_info) entry;
-};
-
-/*!
- * \brief Locked when accessing the lock_infos list
- */
-AST_MUTEX_DEFINE_STATIC(lock_infos_lock);
-/*!
- * \brief A list of each thread's lock info
- */
-static AST_LIST_HEAD_NOLOCK_STATIC(lock_infos, thr_lock_info);
-
-/*!
- * \brief Destroy a thread's lock info
- *
- * This gets called automatically when the thread stops
- */
-static void lock_info_destroy(void *data)
-{
- struct thr_lock_info *lock_info = data;
- int i;
-
- pthread_mutex_lock(&lock_infos_lock.mutex);
- AST_LIST_REMOVE(&lock_infos, lock_info, entry);
- pthread_mutex_unlock(&lock_infos_lock.mutex);
-
-
- for (i = 0; i < lock_info->num_locks; i++) {
- if (lock_info->locks[i].pending == -1) {
- /* This just means that the last lock this thread went for was by
- * using trylock, and it failed. This is fine. */
- break;
- }
-
- ast_log(LOG_ERROR,
- "Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
- lock_info->thread_name,
- lock_info->locks[i].lock_name,
- lock_info->locks[i].lock_addr,
- lock_info->locks[i].func,
- lock_info->locks[i].file,
- lock_info->locks[i].line_num
- );
- }
-
- pthread_mutex_destroy(&lock_info->lock);
- free((void *) lock_info->thread_name);
- free(lock_info);
-}
-
-/*!
- * \brief The thread storage key for per-thread lock info
- */
-AST_THREADSTORAGE_CUSTOM(thread_lock_info, thread_lock_info_init, lock_info_destroy);
-
-void ast_store_lock_info(enum ast_lock_type type, const char *filename,
- int line_num, const char *func, const char *lock_name, void *lock_addr)
-{
- struct thr_lock_info *lock_info;
- int i;
-
- if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
- return;
-
- pthread_mutex_lock(&lock_info->lock);
-
- for (i = 0; i < lock_info->num_locks; i++) {
- if (lock_info->locks[i].lock_addr == lock_addr) {
- lock_info->locks[i].times_locked++;
- pthread_mutex_unlock(&lock_info->lock);
- return;
- }
- }
-
- if (lock_info->num_locks == AST_MAX_LOCKS) {
- /* Can't use ast_log here, because it will cause infinite recursion */
- fprintf(stderr, "XXX ERROR XXX A thread holds more locks than '%d'."
- " Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
- pthread_mutex_unlock(&lock_info->lock);
- return;
- }
-
- if (i && lock_info->locks[i - 1].pending == -1) {
- /* The last lock on the list was one that this thread tried to lock but
- * failed at doing so. It has now moved on to something else, so remove
- * the old lock from the list. */
- i--;
- lock_info->num_locks--;
- memset(&lock_info->locks[i], 0, sizeof(lock_info->locks[0]));
- }
-
- lock_info->locks[i].file = filename;
- lock_info->locks[i].line_num = line_num;
- lock_info->locks[i].func = func;
- lock_info->locks[i].lock_name = lock_name;
- lock_info->locks[i].lock_addr = lock_addr;
- lock_info->locks[i].times_locked = 1;
- lock_info->locks[i].type = type;
- lock_info->locks[i].pending = 1;
- lock_info->num_locks++;
-
- pthread_mutex_unlock(&lock_info->lock);
-}
-
-void ast_mark_lock_acquired(void *lock_addr)
-{
- struct thr_lock_info *lock_info;
-
- if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
- return;
-
- pthread_mutex_lock(&lock_info->lock);
- if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
- lock_info->locks[lock_info->num_locks - 1].pending = 0;
- }
- pthread_mutex_unlock(&lock_info->lock);
-}
-
-void ast_mark_lock_failed(void *lock_addr)
-{
- struct thr_lock_info *lock_info;
-
- if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
- return;
-
- pthread_mutex_lock(&lock_info->lock);
- if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
- lock_info->locks[lock_info->num_locks - 1].pending = -1;
- lock_info->locks[lock_info->num_locks - 1].times_locked--;
- }
- pthread_mutex_unlock(&lock_info->lock);
-}
-
-int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, int *lineno, char *func, size_t func_size, char *mutex_name, size_t mutex_name_size)
-{
- struct thr_lock_info *lock_info;
- int i = 0;
-
- if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
- return -1;
-
- pthread_mutex_lock(&lock_info->lock);
-
- for (i = lock_info->num_locks - 1; i >= 0; i--) {
- if (lock_info->locks[i].lock_addr == lock_addr)
- break;
- }
-
- if (i == -1) {
- /* Lock not found :( */
- pthread_mutex_unlock(&lock_info->lock);
- return -1;
- }
-
- ast_copy_string(filename, lock_info->locks[i].file, filename_size);
- *lineno = lock_info->locks[i].line_num;
- ast_copy_string(func, lock_info->locks[i].func, func_size);
- ast_copy_string(mutex_name, lock_info->locks[i].lock_name, mutex_name_size);
-
- pthread_mutex_unlock(&lock_info->lock);
-
- return 0;
-}
-
-void ast_remove_lock_info(void *lock_addr)
-{
- struct thr_lock_info *lock_info;
- int i = 0;
-
- if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
- return;
-
- pthread_mutex_lock(&lock_info->lock);
-
- for (i = lock_info->num_locks - 1; i >= 0; i--) {
- if (lock_info->locks[i].lock_addr == lock_addr)
- break;
- }
-
- if (i == -1) {
- /* Lock not found :( */
- pthread_mutex_unlock(&lock_info->lock);
- return;
- }
-
- if (lock_info->locks[i].times_locked > 1) {
- lock_info->locks[i].times_locked--;
- pthread_mutex_unlock(&lock_info->lock);
- return;
- }
-
- if (i < lock_info->num_locks - 1) {
- /* Not the last one ... *should* be rare! */
- memmove(&lock_info->locks[i], &lock_info->locks[i + 1],
- (lock_info->num_locks - (i + 1)) * sizeof(lock_info->locks[0]));
- }
-
- lock_info->num_locks--;
-
- pthread_mutex_unlock(&lock_info->lock);
-}
-
-static const char *locktype2str(enum ast_lock_type type)
-{
- switch (type) {
- case AST_MUTEX:
- return "MUTEX";
- case AST_RDLOCK:
- return "RDLOCK";
- case AST_WRLOCK:
- return "WRLOCK";
- }
-
- return "UNKNOWN";
-}
-
-static int handle_show_locks(int fd, int argc, char *argv[])
-{
- struct thr_lock_info *lock_info;
- struct ast_dynamic_str *str;
-
- if (!(str = ast_dynamic_str_create(4096)))
- return RESULT_FAILURE;
-
- ast_dynamic_str_append(&str, 0, "\n"
- "=======================================================================\n"
- "=== Currently Held Locks ==============================================\n"
- "=======================================================================\n"
- "===\n"
- "=== <file> <line num> <function> <lock name> <lock addr> (times locked)\n"
- "===\n");
-
- if (!str)
- return RESULT_FAILURE;
-
- pthread_mutex_lock(&lock_infos_lock.mutex);
- AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
- int i;
- if (lock_info->num_locks) {
- ast_dynamic_str_append(&str, 0, "=== Thread ID: %u (%s)\n", (int) lock_info->thread_id,
- lock_info->thread_name);
- pthread_mutex_lock(&lock_info->lock);
- for (i = 0; str && i < lock_info->num_locks; i++) {
- int j;
- ast_mutex_t *lock;
-
- ast_dynamic_str_append(&str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n",
- lock_info->locks[i].pending > 0 ? "Waiting for " :
- lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
- lock_info->locks[i].file,
- locktype2str(lock_info->locks[i].type),
- lock_info->locks[i].line_num,
- lock_info->locks[i].func, lock_info->locks[i].lock_name,
- lock_info->locks[i].lock_addr,
- lock_info->locks[i].times_locked);
-
- if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
- continue;
-
- /* We only have further details for mutexes right now */
- if (lock_info->locks[i].type != AST_MUTEX)
- continue;
-
- lock = lock_info->locks[i].lock_addr;
-
- ast_reentrancy_lock(lock);
- for (j = 0; str && j < lock->reentrancy; j++) {
- ast_dynamic_str_append(&str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
- lock->file[j], lock->lineno[j], lock->func[j]);
- }
- ast_reentrancy_unlock(lock);
- }
- pthread_mutex_unlock(&lock_info->lock);
- if (!str)
- break;
- ast_dynamic_str_append(&str, 0, "=== -------------------------------------------------------------------\n"
- "===\n");
- if (!str)
- break;
- }
- }
- pthread_mutex_unlock(&lock_infos_lock.mutex);
-
- if (!str)
- return RESULT_FAILURE;
-
- ast_dynamic_str_append(&str, 0, "=======================================================================\n"
- "\n");
-
- if (!str)
- return RESULT_FAILURE;
-
- ast_cli(fd, "%s", str->str);
-
- free(str);
-
- return RESULT_SUCCESS;
-}
-
-static char show_locks_help[] =
-"Usage: core show locks\n"
-" This command is for lock debugging. It prints out which locks\n"
-"are owned by each active thread.\n";
-
-static struct ast_cli_entry utils_cli[] = {
- { { "core", "show", "locks", NULL }, handle_show_locks,
- "Show which locks are locked by which thread", show_locks_help },
-};
-
-#endif /* DEBUG_THREADS */
-
-
-
-/*
- * support for 'show threads'. The start routine is wrapped by
- * dummy_start(), so that ast_register_thread() and
- * ast_unregister_thread() know the thread identifier.
- */
-struct thr_arg {
- void *(*start_routine)(void *);
- void *data;
- char *name;
-};
-
-/*
- * on OS/X, pthread_cleanup_push() and pthread_cleanup_pop()
- * are odd macros which start and end a block, so they _must_ be
- * used in pairs (the latter with a '1' argument to call the
- * handler on exit.
- * On BSD we don't need this, but we keep it for compatibility.
- */
-static void *dummy_start(void *data)
-{
- void *ret;
- struct thr_arg a = *((struct thr_arg *) data); /* make a local copy */
-#ifdef DEBUG_THREADS
- struct thr_lock_info *lock_info;
- pthread_mutexattr_t mutex_attr;
-#endif
-
- /* note that even though data->name is a pointer to allocated memory,
- we are not freeing it here because ast_register_thread is going to
- keep a copy of the pointer and then ast_unregister_thread will
- free the memory
- */
- free(data);
- ast_register_thread(a.name);
- pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
-
-#ifdef DEBUG_THREADS
- if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
- return NULL;
-
- lock_info->thread_id = pthread_self();
- lock_info->thread_name = strdup(a.name);
-
- pthread_mutexattr_init(&mutex_attr);
- pthread_mutexattr_settype(&mutex_attr, AST_MUTEX_KIND);
- pthread_mutex_init(&lock_info->lock, &mutex_attr);
- pthread_mutexattr_destroy(&mutex_attr);
-
- pthread_mutex_lock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
- AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry);
- pthread_mutex_unlock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
-#endif /* DEBUG_THREADS */
-
- ret = a.start_routine(a.data);
-
- pthread_cleanup_pop(1);
-
- return ret;
-}
-
-#endif /* !LOW_MEMORY */
-
-int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
- void *data, size_t stacksize, const char *file, const char *caller,
- int line, const char *start_fn)
-{
-#if !defined(LOW_MEMORY)
- struct thr_arg *a;
-#endif
-
- if (!attr) {
- attr = alloca(sizeof(*attr));
- pthread_attr_init(attr);
- }
-
-#ifdef __linux__
- /* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
- which is kind of useless. Change this here to
- PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
- priority will propagate down to new threads by default.
- This does mean that callers cannot set a different priority using
- PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
- the priority afterwards with pthread_setschedparam(). */
- if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
- ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
-#endif
-
- if (!stacksize)
- stacksize = AST_STACKSIZE;
-
- if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
- ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
-
-#if !defined(LOW_MEMORY)
- if ((a = ast_malloc(sizeof(*a)))) {
- a->start_routine = start_routine;
- a->data = data;
- start_routine = dummy_start;
- if (asprintf(&a->name, "%-20s started at [%5d] %s %s()",
- start_fn, line, file, caller) < 0) {
- ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
- a->name = NULL;
- }
- data = a;
- }
-#endif /* !LOW_MEMORY */
-
- return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
-}
-
-int ast_wait_for_input(int fd, int ms)
-{
- struct pollfd pfd[1];
- memset(pfd, 0, sizeof(pfd));
- pfd[0].fd = fd;
- pfd[0].events = POLLIN|POLLPRI;
- return poll(pfd, 1, ms);
-}
-
-int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
-{
- struct timeval start = ast_tvnow();
- int res = 0;
- int elapsed = 0;
-
- while (len) {
- struct pollfd pfd = {
- .fd = fd,
- .events = POLLOUT,
- };
-
- /* poll() until the fd is writable without blocking */
- while ((res = poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
- if (res == 0) {
- /* timed out. */
- ast_log(LOG_NOTICE, "Timed out trying to write\n");
- return -1;
- } else if (res == -1) {
- /* poll() returned an error, check to see if it was fatal */
-
- if (errno == EINTR || errno == EAGAIN) {
- elapsed = ast_tvdiff_ms(ast_tvnow(), start);
- if (elapsed > timeoutms) {
- /* We've taken too long to write
- * This is only an error condition if we haven't finished writing. */
- res = len ? -1 : 0;
- break;
- }
- /* This was an acceptable error, go back into poll() */
- continue;
- }
-
- /* Fatal error, bail. */
- ast_log(LOG_ERROR, "poll returned error: %s\n", strerror(errno));
-
- return -1;
- }
- }
-
- res = write(fd, s, len);
-
- if (res < 0 && errno != EAGAIN && errno != EINTR) {
- /* fatal error from write() */
- ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));
- return -1;
- }
-
- if (res < 0) {
- /* It was an acceptable error */
- res = 0;
- }
-
- /* Update how much data we have left to write */
- len -= res;
- s += res;
- res = 0;
-
- elapsed = ast_tvdiff_ms(ast_tvnow(), start);
- if (elapsed > timeoutms) {
- /* We've taken too long to write
- * This is only an error condition if we haven't finished writing. */
- res = len ? -1 : 0;
- break;
- }
- }
-
- return res;
-}
-
-char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
-{
- char *e;
- char *q;
-
- s = ast_strip(s);
- if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
- e = s + strlen(s) - 1;
- if (*e == *(end_quotes + (q - beg_quotes))) {
- s++;
- *e = '\0';
- }
- }
-
- return s;
-}
-
-char *ast_unescape_semicolon(char *s)
-{
- char *e;
- char *work = s;
-
- while ((e = strchr(work, ';'))) {
- if ((e > work) && (*(e-1) == '\\')) {
- memmove(e - 1, e, strlen(e) + 1);
- work = e;
- } else {
- work = e + 1;
- }
- }
-
- return s;
-}
-
-int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
-{
- int result;
-
- if (!buffer || !*buffer || !space || !*space)
- return -1;
-
- result = vsnprintf(*buffer, *space, fmt, ap);
-
- if (result < 0)
- return -1;
- else if (result > *space)
- result = *space;
-
- *buffer += result;
- *space -= result;
- return 0;
-}
-
-int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
-{
- va_list ap;
- int result;
-
- va_start(ap, fmt);
- result = ast_build_string_va(buffer, space, fmt, ap);
- va_end(ap);
-
- return result;
-}
-
-int ast_true(const char *s)
-{
- if (ast_strlen_zero(s))
- return 0;
-
- /* Determine if this is a true value */
- if (!strcasecmp(s, "yes") ||
- !strcasecmp(s, "true") ||
- !strcasecmp(s, "y") ||
- !strcasecmp(s, "t") ||
- !strcasecmp(s, "1") ||
- !strcasecmp(s, "on"))
- return -1;
-
- return 0;
-}
-
-int ast_false(const char *s)
-{
- if (ast_strlen_zero(s))
- return 0;
-
- /* Determine if this is a false value */
- if (!strcasecmp(s, "no") ||
- !strcasecmp(s, "false") ||
- !strcasecmp(s, "n") ||
- !strcasecmp(s, "f") ||
- !strcasecmp(s, "0") ||
- !strcasecmp(s, "off"))
- return -1;
-
- return 0;
-}
-
-#define ONE_MILLION 1000000
-/*
- * put timeval in a valid range. usec is 0..999999
- * negative values are not allowed and truncated.
- */
-static struct timeval tvfix(struct timeval a)
-{
- if (a.tv_usec >= ONE_MILLION) {
- ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
- a.tv_sec, (long int) a.tv_usec);
- a.tv_sec += a.tv_usec / ONE_MILLION;
- a.tv_usec %= ONE_MILLION;
- } else if (a.tv_usec < 0) {
- ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
- a.tv_sec, (long int) a.tv_usec);
- a.tv_usec = 0;
- }
- return a;
-}
-
-struct timeval ast_tvadd(struct timeval a, struct timeval b)
-{
- /* consistency checks to guarantee usec in 0..999999 */
- a = tvfix(a);
- b = tvfix(b);
- a.tv_sec += b.tv_sec;
- a.tv_usec += b.tv_usec;
- if (a.tv_usec >= ONE_MILLION) {
- a.tv_sec++;
- a.tv_usec -= ONE_MILLION;
- }
- return a;
-}
-
-struct timeval ast_tvsub(struct timeval a, struct timeval b)
-{
- /* consistency checks to guarantee usec in 0..999999 */
- a = tvfix(a);
- b = tvfix(b);
- a.tv_sec -= b.tv_sec;
- a.tv_usec -= b.tv_usec;
- if (a.tv_usec < 0) {
- a.tv_sec-- ;
- a.tv_usec += ONE_MILLION;
- }
- return a;
-}
-#undef ONE_MILLION
-
-/*! \brief glibc puts a lock inside random(3), so that the results are thread-safe.
- * BSD libc (and others) do not. */
-#ifndef linux
-
-AST_MUTEX_DEFINE_STATIC(randomlock);
-
-long int ast_random(void)
-{
- long int res;
- ast_mutex_lock(&randomlock);
- res = random();
- ast_mutex_unlock(&randomlock);
- return res;
-}
-#endif
-
-char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
-{
- char *dataPut = start;
- int inEscape = 0;
- int inQuotes = 0;
-
- for (; *start; start++) {
- if (inEscape) {
- *dataPut++ = *start; /* Always goes verbatim */
- inEscape = 0;
- } else {
- if (*start == '\\') {
- inEscape = 1; /* Do not copy \ into the data */
- } else if (*start == '\'') {
- inQuotes = 1 - inQuotes; /* Do not copy ' into the data */
- } else {
- /* Replace , with |, unless in quotes */
- *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
- }
- }
- }
- if (start != dataPut)
- *dataPut = 0;
- return dataPut;
-}
-
-void ast_join(char *s, size_t len, char * const w[])
-{
- int x, ofs = 0;
- const char *src;
-
- /* Join words into a string */
- if (!s)
- return;
- for (x = 0; ofs < len && w[x]; x++) {
- if (x > 0)
- s[ofs++] = ' ';
- for (src = w[x]; *src && ofs < len; src++)
- s[ofs++] = *src;
- }
- if (ofs == len)
- ofs--;
- s[ofs] = '\0';
-}
-
-const char __ast_string_field_empty[] = "";
-
-static int add_string_pool(struct ast_string_field_mgr *mgr, size_t size)
-{
- struct ast_string_field_pool *pool;
-
- if (!(pool = ast_calloc(1, sizeof(*pool) + size)))
- return -1;
-
- pool->prev = mgr->pool;
- mgr->pool = pool;
- mgr->size = size;
- mgr->space = size;
- mgr->used = 0;
-
- return 0;
-}
-
-int __ast_string_field_init(struct ast_string_field_mgr *mgr, size_t size,
- ast_string_field *fields, int num_fields)
-{
- int index;
-
- if (add_string_pool(mgr, size))
- return -1;
-
- for (index = 0; index < num_fields; index++)
- fields[index] = __ast_string_field_empty;
-
- return 0;
-}
-
-ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr, size_t needed,
- ast_string_field *fields, int num_fields)
-{
- char *result = NULL;
-
- if (__builtin_expect(needed > mgr->space, 0)) {
- size_t new_size = mgr->size * 2;
-
- while (new_size < needed)
- new_size *= 2;
-
- if (add_string_pool(mgr, new_size))
- return NULL;
- }
-
- result = mgr->pool->base + mgr->used;
- mgr->used += needed;
- mgr->space -= needed;
- return result;
-}
-
-void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
- ast_string_field *fields, int num_fields,
- int index, const char *format, va_list ap1, va_list ap2)
-{
- size_t needed;
-
- needed = vsnprintf(mgr->pool->base + mgr->used, mgr->space, format, ap1) + 1;
-
- va_end(ap1);
-
- if (needed > mgr->space) {
- size_t new_size = mgr->size * 2;
-
- while (new_size < needed)
- new_size *= 2;
-
- if (add_string_pool(mgr, new_size))
- return;
-
- vsprintf(mgr->pool->base + mgr->used, format, ap2);
- }
-
- fields[index] = mgr->pool->base + mgr->used;
- mgr->used += needed;
- mgr->space -= needed;
-}
-
-void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
- ast_string_field *fields, int num_fields,
- int index, const char *format, ...)
-{
- va_list ap1, ap2;
-
- va_start(ap1, format);
- va_start(ap2, format); /* va_copy does not exist on FreeBSD */
-
- __ast_string_field_index_build_va(mgr, fields, num_fields, index, format, ap1, ap2);
-
- va_end(ap1);
- va_end(ap2);
-}
-
-AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
-
-int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
-{
- int ret;
- ast_mutex_lock(&fetchadd_m);
- ret = *p;
- *p += v;
- ast_mutex_unlock(&fetchadd_m);
- return ret;
-}
-
-/*! \brief
- * get values from config variables.
- */
-int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
-{
- long t;
- int scanned;
-
- if (dst == NULL)
- return -1;
-
- *dst = _default;
-
- if (ast_strlen_zero(src))
- return -1;
-
- /* only integer at the moment, but one day we could accept more formats */
- if (sscanf(src, "%ld%n", &t, &scanned) == 1) {
- *dst = t;
- if (consumed)
- *consumed = scanned;
- return 0;
- } else
- return -1;
-}
-
-int ast_dynamic_str_thread_build_va(struct ast_dynamic_str **buf, size_t max_len,
- struct ast_threadstorage *ts, int append, const char *fmt, va_list ap)
-{
- int res;
- int offset = (append && (*buf)->len) ? strlen((*buf)->str) : 0;
-#if defined(DEBUG_THREADLOCALS)
- struct ast_dynamic_str *old_buf = *buf;
-#endif /* defined(DEBUG_THREADLOCALS) */
-
- res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, ap);
-
- /* Check to see if there was not enough space in the string buffer to prepare
- * the string. Also, if a maximum length is present, make sure the current
- * length is less than the maximum before increasing the size. */
- if ((res + offset + 1) > (*buf)->len && (max_len ? ((*buf)->len < max_len) : 1)) {
- /* Set the new size of the string buffer to be the size needed
- * to hold the resulting string (res) plus one byte for the
- * terminating '\0'. If this size is greater than the max, set
- * the new length to be the maximum allowed. */
- if (max_len)
- (*buf)->len = ((res + offset + 1) < max_len) ? (res + offset + 1) : max_len;
- else
- (*buf)->len = res + offset + 1;
-
- if (!(*buf = ast_realloc(*buf, (*buf)->len + sizeof(*(*buf)))))
- return AST_DYNSTR_BUILD_FAILED;
-
- if (append)
- (*buf)->str[offset] = '\0';
-
- if (ts) {
- pthread_setspecific(ts->key, *buf);
-#if defined(DEBUG_THREADLOCALS)
- __ast_threadstorage_object_replace(old_buf, *buf, (*buf)->len + sizeof(*(*buf)));
-#endif /* defined(DEBUG_THREADLOCALS) */
- }
-
- /* va_end() and va_start() must be done before calling
- * vsnprintf() again. */
- return AST_DYNSTR_BUILD_RETRY;
- }
-
- return res;
-}
-
-void ast_enable_packet_fragmentation(int sock)
-{
-#if defined(HAVE_IP_MTU_DISCOVER)
- int val = IP_PMTUDISC_DONT;
-
- if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
- ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
-#endif /* HAVE_IP_MTU_DISCOVER */
-}
-
-int ast_utils_init(void)
-{
- base64_init();
-#ifdef DEBUG_THREADS
-#if !defined(LOW_MEMORY)
- ast_cli_register_multiple(utils_cli, sizeof(utils_cli) / sizeof(utils_cli[0]));
-#endif
-#endif
- return 0;
-}
-
-#ifndef __AST_DEBUG_MALLOC
-int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...)
-{
- int res;
- va_list ap;
-
- va_start(ap, fmt);
- if ((res = vasprintf(ret, fmt, ap)) == -1) {
- MALLOC_FAILURE_MSG;
- }
- va_end(ap);
-
- return res;
-}
-#endif