summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README6
-rw-r--r--action.cpp6
-rw-r--r--action_vbox.cpp5
-rw-r--r--apppbx.cpp15
-rw-r--r--chan_lcr.c29
-rw-r--r--chan_lcr.h2
-rw-r--r--crypt.cpp2
-rw-r--r--debian/README.source2
-rw-r--r--debian/TODO8
-rw-r--r--debian/changelog77
-rw-r--r--debian/compat1
-rw-r--r--debian/control24
-rw-r--r--debian/copyright37
-rw-r--r--debian/dirs1
-rw-r--r--debian/docs4
-rw-r--r--debian/genextension.832
-rw-r--r--debian/gentones.153
-rw-r--r--debian/lcr.default7
-rw-r--r--debian/lcr.init203
-rw-r--r--debian/lcr.logrotate9
-rw-r--r--debian/lcr.manpages3
-rw-r--r--debian/lcradmin.149
-rw-r--r--debian/patches/configure_warning19
-rw-r--r--debian/patches/replace_local.patch79
-rw-r--r--debian/patches/series2
-rwxr-xr-xdebian/rules101
-rw-r--r--debian/watch5
-rw-r--r--default/options.conf8
-rw-r--r--dss1.cpp7
-rw-r--r--extension.c20
-rw-r--r--gsm_conf.c4
-rw-r--r--interface.c4
-rw-r--r--joinpbx.cpp15
-rw-r--r--joinpbx.h2
-rw-r--r--macro.h18
-rw-r--r--message.h1
-rw-r--r--options.c28
-rw-r--r--options.h3
-rw-r--r--route.c11
-rw-r--r--route.h1
-rw-r--r--socket_server.c6
-rw-r--r--ss5.cpp27
-rw-r--r--ss5.h7
-rw-r--r--ss5_decode.c51
44 files changed, 913 insertions, 81 deletions
diff --git a/README b/README
index 85e8d96..8a33e07 100644
--- a/README
+++ b/README
@@ -520,6 +520,10 @@ Changes after Version 1.6
-> Just add 'extern' right below your external interface definition, or give
external interface name in routing.conf: ": extern interfaces=XXXXX"
- Added experimental CCITT No. 5 signalling system. (for educational purpose)
-
+- Added socket owner/group options to options.conf
+- Fixed/simplyfied config parser. The last digit of the last line was ignored.
+- Added Keypad facility
+ -> New option for chan_lcr: 'k'
+ -> New dialing parameter for LCR: keypad
diff --git a/action.cpp b/action.cpp
index 8c06137..d720dbe 100644
--- a/action.cpp
+++ b/action.cpp
@@ -213,6 +213,12 @@ void EndpointAppPBX::action_dialing_external(void)
if ((rparam = routeparam(e_action, PARAM_PREFIX)))
SPRINT(dialinginfo.id, "%s%s", rparam->string_value, e_extdialing);
+ /* process keypad */
+ if ((rparam = routeparam(e_action, PARAM_KEYPAD))) {
+ SCPY(dialinginfo.keypad, dialinginfo.id);
+ dialinginfo.id[0] = '\0';
+ }
+
/* process number complete */
if ((rparam = routeparam(e_action, PARAM_COMPLETE)))
if ((rparam = routeparam(e_action, PARAM_PREFIX)))
diff --git a/action_vbox.cpp b/action_vbox.cpp
index 2426610..e325c0f 100644
--- a/action_vbox.cpp
+++ b/action_vbox.cpp
@@ -142,10 +142,7 @@ void EndpointAppPBX::vbox_index_read(int num)
fduse++;
i = 0;
- while((fgets(buffer,sizeof(buffer),fp))) {
- buffer[sizeof(buffer)-1] = '\0';
- if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
-
+ while((GETLINE(buffer, fp))) {
name[0] = callerid[0] = '\0';
mon = mday = hour = min = 0;
sscanf(buffer, "%s %d %d %d %d %d %s", name, &year, &mon, &mday, &hour, &min, callerid);
diff --git a/apppbx.cpp b/apppbx.cpp
index 06e3d92..9dee717 100644
--- a/apppbx.cpp
+++ b/apppbx.cpp
@@ -1128,9 +1128,12 @@ void EndpointAppPBX::out_setup(void)
/* *********************** external call */
default:
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
/* call to extenal interfaces */
- p = e_dialinginfo.id;
+ if (e_dialinginfo.keypad[0])
+ p = e_dialinginfo.keypad;
+ else
+ p = e_dialinginfo.id;
do {
number[0] = '\0';
while(*p!=',' && *p!='\0')
@@ -1168,7 +1171,10 @@ void EndpointAppPBX::out_setup(void)
earlyb = mISDNport->earlyb;
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
memset(&dialinginfo, 0, sizeof(dialinginfo));
- SCPY(dialinginfo.id, number);
+ if (e_dialinginfo.keypad[0])
+ SCPY(dialinginfo.keypad, number);
+ else
+ SCPY(dialinginfo.id, number);
dialinginfo.itype = INFO_ITYPE_ISDN;
dialinginfo.ntype = e_dialinginfo.ntype;
portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
@@ -1180,7 +1186,6 @@ void EndpointAppPBX::out_setup(void)
//printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
- SCPY(message->param.setup.dialinginfo.id, number);
memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
@@ -3844,6 +3849,8 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
}
if (param->setup.dialinginfo.id[0])
add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
+ if (param->setup.dialinginfo.keypad[0])
+ add_trace("keypad", NULL, "%s", param->setup.dialinginfo.keypad);
if (param->setup.dialinginfo.display[0])
add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
if (param->setup.dialinginfo.sending_complete)
diff --git a/chan_lcr.c b/chan_lcr.c
index d1b57e6..e50847c 100644
--- a/chan_lcr.c
+++ b/chan_lcr.c
@@ -555,6 +555,15 @@ void apply_opt(struct chan_call *call, char *data)
bchannel_gain(call->bchannel, call->tx_gain, 1);
}
break;
+ case 'k':
+ if (opt[1] != '\0') {
+ CERROR(call, call->ast, "Option 'k' (keypad) expects no parameter.\n", opt);
+ break;
+ }
+ CDEBUG(call, call->ast, "Option 'k' (keypad).\n");
+ if (!call->keypad)
+ call->keypad = 1;
+ break;
default:
CERROR(call, call->ast, "Option '%s' unknown.\n", opt);
}
@@ -586,7 +595,10 @@ static void send_setup_to_lcr(struct chan_call *call)
memset(&newparam, 0, sizeof(union parameter));
newparam.setup.dialinginfo.itype = INFO_ITYPE_ISDN;
newparam.setup.dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
- strncpy(newparam.setup.dialinginfo.id, call->dialstring, sizeof(newparam.setup.dialinginfo.id)-1);
+ if (call->keypad)
+ strncpy(newparam.setup.dialinginfo.keypad, call->dialstring, sizeof(newparam.setup.dialinginfo.keypad)-1);
+ else
+ strncpy(newparam.setup.dialinginfo.id, call->dialstring, sizeof(newparam.setup.dialinginfo.id)-1);
strncpy(newparam.setup.dialinginfo.interfaces, call->interface, sizeof(newparam.setup.dialinginfo.interfaces)-1);
newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN;
newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
@@ -657,7 +669,10 @@ static void send_dialque_to_lcr(struct chan_call *call)
/* send setup message to LCR */
memset(&newparam, 0, sizeof(union parameter));
- strncpy(newparam.information.id, call->dialque, sizeof(newparam.information.id)-1);
+ if (call->keypad)
+ strncpy(newparam.information.keypad, call->dialque, sizeof(newparam.information.keypad)-1);
+ else
+ strncpy(newparam.information.id, call->dialque, sizeof(newparam.information.id)-1);
call->dialque[0] = '\0';
send_message(MESSAGE_INFORMATION, call->ref, &newparam);
}
@@ -1927,8 +1942,13 @@ static int lcr_digit(struct ast_channel *ast, char digit)
if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING) {
CDEBUG(call, ast, "Sending digit to LCR, because we are in dialing state.\n");
memset(&newparam, 0, sizeof(union parameter));
- newparam.information.id[0] = digit;
- newparam.information.id[1] = '\0';
+ if (call->keypad) {
+ newparam.information.keypad[0] = digit;
+ newparam.information.keypad[1] = '\0';
+ } else {
+ newparam.information.id[0] = digit;
+ newparam.information.id[1] = '\0';
+ }
send_message(MESSAGE_INFORMATION, call->ref, &newparam);
} else
if (!call->ref
@@ -2742,6 +2762,7 @@ int load_module(void)
" vr - rxgain control\n"
" vt - txgain control\n"
" Volume changes at factor 2 ^ optarg.\n"
+ " k - use keypad to dial this call.\n"
);
diff --git a/chan_lcr.h b/chan_lcr.h
index 60a64fd..5905ea1 100644
--- a/chan_lcr.h
+++ b/chan_lcr.h
@@ -65,6 +65,8 @@ struct chan_call {
/* echo cancel pipeline by option */
int tx_gain, rx_gain;
/* gain by option */
+ int keypad;
+ /* use keypad to dial number */
unsigned char bf_key[56];
int bf_len; /* blowfish crypt key */
struct ast_dsp *dsp; /* ast dsp processor for fax/tone detection */
diff --git a/crypt.cpp b/crypt.cpp
index ee8e7cc..44e901c 100644
--- a/crypt.cpp
+++ b/crypt.cpp
@@ -216,7 +216,7 @@ static unsigned int get_bogomips(void)
}
fduse++;
buffer[sizeof(buffer-1)] = '\0';
- while(fgets(buffer, sizeof(buffer)-1, fp)) {
+ while(GETLINE(buffer, fp)) {
if (!!strncmp(buffer, "bogomips", 8))
continue;
if (!strchr(buffer, ':'))
diff --git a/debian/README.source b/debian/README.source
new file mode 100644
index 0000000..bbe996f
--- /dev/null
+++ b/debian/README.source
@@ -0,0 +1,2 @@
+This package uses the quilt patch system. See
+/usr/share/doc/quilt/README.source for further information
diff --git a/debian/TODO b/debian/TODO
new file mode 100644
index 0000000..79eedfc
--- /dev/null
+++ b/debian/TODO
@@ -0,0 +1,8 @@
+* Add manpages for:
+ - usr/sbin/genextension ( first draft already done debian/genextension.8 )
+ - usr/bin/gentones ( debian/gentones.1 )
+ - usr/bin/genwave
+ - usr/sbin/lcr
+ - usr/bin/lcradmin ( debian.lcradmin.1)
+
+* Check udev rules for permissions of /dev/mISDNtimer
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..dff4e41
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,77 @@
+lcr (1.6~20090906-1) UNRELEASED; urgency=low
+
+ [ Joerg Dorchain ]
+ * New upstream version
+ * debian/control:
+ - update debian policy 3.8.3
+ * Added link to /usr/share/doc/quilt/README.source
+ * refreshed patches
+ * Integrated in upstream source
+
+ -- Joerg Dorchain <joerg@dorchain.net> Mon, 7 Sep 2009 11:00:00 +0200
+
+lcr (1.5~20090615-1) UNRELEASED; urgency=low
+
+ [ Victor Seva ]
+ * New upstream update
+ * debian/patches:
+ - removed lcr_as_vbox.patch, chan_lcr_compiles_asterisk_1.6-2.patch,
+ pid.patch, chan_lcr_compiles_asterisk_1.6-git.patch,
+ chan_lcr_dtmf.patch ( applied upstream )
+ - refresh configure_warning, replace_local.patch
+
+ [ Joerg Dorchain ]
+ * Bump standards to 3.8.1. No changes necessary
+ * init script depends on lsb-base (>= 3.0-6)
+ * logdir needs to be set in Makefile.am
+
+ -- Victor Seva <linuxmaniac@torreviejawireless.org> Fri, 19 Jun 2009 16:23:02 +0200
+
+lcr (1.3~20090107-1) unstable; urgency=low
+
+ [ Joerg Dorchain ]
+ * Initial release (Closes: #510476) ITP
+ * New upstream version
+ * Added initscripts
+ * debian/control:
+ - Added Vcs-Svn, Vcs-Browser fields
+ - Changed Maintainer, Added Uploaders field
+ * debian/rules:
+ - slightly more fault-tolerant for get-orig-source
+ * debian:
+ - Set mergeWithUpstream property
+ * debian/patches:
+ - chan_lcr_compiles_asterisk_1.6-2.patch
+ - chan_lcr_compiles_asterisk_1.6-git.patch
+ * Fix build with asterisk-1.6
+ * Bump standards to 3.8.0. Changes done by Victor and me
+ * Fix some lintian errors
+
+ [ Victor Seva ]
+ * Remove all debian/*.ex debian/*.EX files. Just examples.
+ * debian/rules:
+ - added some variables to handle versioning.
+ - added get-orig-source.
+ - remove patch/unpatch rules. Added quilt.make reference.
+ - remoce some redundant rule dependences.
+ * Changed the upstream version ( 0.0.DATE -> 1.3~DATE ).
+ Seems that they are using that versioning style.
+ * Added debian/watch.
+ * debian/patches:
+ - configure_warning ( remove warnings )
+ * debian/control:
+ - add myself as an Uploaders.
+ * debian/docs:
+ Fix lintian errors:
+ - W: lcr: extra-license-file usr/share/doc/lcr/COPYING
+ - W: lcr: package-contains-upstream-install-documentation
+ usr/share/doc/lcr/INSTALL.gz
+ - W: lcr: extra-license-file usr/share/doc/lcr/LICENSE.gz
+ - W: lcr: zero-byte-file-in-doc-directory usr/share/doc/lcr/changelog.gz
+ Deleted COPYING INSTALL LICENCE ChangeLog files.
+ * debian/copyright:
+ - add proper copyright description.
+ * debian/lcr.default
+ - don't run lcr by default.
+
+ -- Joerg Dorchain <joerg@dorchain.net> Fri, 26 Dec 2008 11:46:23 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..3c1f4f5
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,24 @@
+Source: lcr
+Section: comm
+Priority: extra
+Maintainer: Debian VoIP Team <pkg-voip-maintainers@lists.alioth.debian.org>
+Uploaders: Joerg Dorchain <joerg@dorchain.net>, Victor Seva <linuxmaniac@torreviejawireless.org>
+Build-Depends: debhelper (>= 7), autotools-dev, libmisdnv2user-dev, asterisk-dev, libncurses-dev, automake1.9, quilt
+Standards-Version: 3.8.3
+Homepage: http://isdn.eversberg.eu/download/lcr-1.3/
+Vcs-Svn: svn://svn.debian.org/pkg-voip/lcr/trunk
+Vcs-Browser: http://svn.debian.org/wsvn/pkg-voip/lcr/?op=log
+
+Package: lcr
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.0-6)
+Suggests: asterisk
+Description: LinuxCallRouter - an ISDN based PBX for Linux
+ Formerly known as "PBX4Linux", Linux-Call-Router is not only a router,
+ it is a real ISDN PBX which interconnects ISDN telephones and ISDN lines.
+ It is possible to connect telephones to a Linux box. It is a pure software
+ solution except for the ISDN cards and telephones. The great benefit is
+ the NT-mode that allows to connect telephones to an ISDN card. Special
+ cards are needed and a little bit of different cabeling. It supports lots
+ of features, that only expensive PBXs have. It include a channel driver
+ that can link LCR to Asterisk PBX.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..5950397
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,37 @@
+This package was debianized by Joerg Dorchain <joerg@dorchain.net> on
+Fri, 26 Dec 2008 11:46:23 +0100.
+
+It is now maintained by the Debian VoIP Team
+<pkg-voip-maintainers@lists.alioth.debian.org>
+
+It was downloaded from http://isdn.eversberg.eu/download/lcr-1.3/
+
+Upstream Author:
+
+ Andreas Eversberg <jolly@eversberg.eu>
+
+Copyright:
+
+ Copyright (C) 2008 Andreas Eversberg
+
+License:
+
+ 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
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ On Debian systems, you find a copy at '/usr/share/common-licenses/GPL-2'
+
+The Debian packaging is (C) 2008, Joerg Dorchain <joerg@dorchain.net> and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
+
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..5057bcc
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1 @@
+/var/log/lcr
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..9712a01
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,4 @@
+NEWS
+README
+message.txt
+todo.txt
diff --git a/debian/genextension.8 b/debian/genextension.8
new file mode 100644
index 0000000..5380bda
--- /dev/null
+++ b/debian/genextension.8
@@ -0,0 +1,32 @@
+.TH GENEXTENSION 8
+.SH NAME
+genextension \- Linux Call Route extension generator
+.SH SYNOPSIS
+genextension EXTENSION INTERFACES CALLERID
+.SH DESCRIPTION
+Extensions can be easily created by using the "genextension" command.
+After executing the command the extension will be created at "/usr/share/lcr/extensions/EXTENSION/".
+.SS EXTENSION
+Extension number.
+.br
+Any number for the extension (e.g 200)
+.SS INTERFACES
+Extension’s interface to be used for calls to the extension.
+.br
+"Int" would send a call to the internal interface as defined in "/etc/lcr/interface.conf".
+If calls should ring on more then one port, they must be separated by commas without spaces.
+Internal ports must be defined in "/etc/lcr/options.conf"
+.br
+Internal interface(s) to reach extension, NOT port numbers -> seperate multiple
+interfaces with commas without spaces. (e.g Int1,Int2)
+.SS CALLERID
+Caller ID to be used, whenever the extension makes a call (to external line).
+The type of caller ID is "undefined", that is the standard type for normal
+external ISDN lines. If the external ISDN line has the "CLIP No Screening"
+feature, it must be given with type "subscriber", "national" or "international".
+.SH SEE ALSO
+http://www.linux-call-router.de/doc.html
+.SH AUTHOR
+This minimal man page was written by Victor Seva <linuxmaniac@torreviejawireless.org>
+.br
+from documentation created by Andreas Eversberg <jolly@eversberg.eu>
diff --git a/debian/gentones.1 b/debian/gentones.1
new file mode 100644
index 0000000..6d7c7e3
--- /dev/null
+++ b/debian/gentones.1
@@ -0,0 +1,53 @@
+.TH GENTONES 1
+.SH NAME
+gentones \- generates tones
+.SH SYNOPSIS
+gentone wave2alaw <wav file> <alaw file>
+.br
+gentone wave2ulaw <wav file> <ulaw file>
+.br
+gentone tone2alaw <frq1> <frq2> <length> <fade in> <fade out> <alaw file>
+.br
+gentone tone2ulaw <frq1> <frq2> <length> <fade in> <fade out> <ulaw file>
+.SH DESCRIPTION
+Length and fade lengths must be given in samples (8000 samples are one second).
+Tones will append to existing files, wav files don't.
+Frequencies may be given as floating point values.
+.br
+It can be used, to generate law encoded tones with one or two frequencies.
+This is mainly used to create patterns, like dial tones, busy tone and other audio
+patterns. Depending on your telephone system, you need to use "tones2alaw" or "tones2ulaw".
+There are two frequencies to specify "frq1" and "frq2". If only one frequency should be
+used, enter 0 for "frq2". The "length" specifies the total length of the tone in samples. 8000
+samples are one second. 2000 samples are 1/4 of a second. "fade in" and "fade out" is used to
+make the start and stop of the tone soft. If "fade in" is 800, the sound will fade in
+within 1/10 of a second.
+This makes tones very smooth and avoids the ‘click’ sound at the beginning.
+"fade out" respectively. Whatever specified for "fade in" and "fade out", the tone will
+be as long as given at "length". If you don’t want to use fades, set "frq1" and "frq2" to
+"0". I suggest at least 50 sample for fade to silence.
+.br
+The given file will be appended to "alaw file" or "ulaw file". If you like
+to create a new one, but the name still exist, delete the file and then start creating it. This
+is useful to create a sample with more than one tone. Example: A busy tone normally is made out of
+1/2 second of a tone, and one 1/2 second of silence. To add silence, just enter 0 for "frq1"
+and "frq2".
+.br
+It is also possible to convert a wave file to a-law or mu-law. The wave file
+must have a sampling rate of 8000. It doesn’t matte what bit-resolution or how many
+channels it has (stereo or mono). The sampling rate will not be converted, so it must be
+8000 samples/second. The resolution should be 16 bits for best quality. a-law and
+mu-law have better resolution than 8 bits. The data of a-law and mu-law is 8 bits
+sample, but since it is quantised, the quality will be 12 bits. 12 bits sounds almost as good as 16
+bits. Wave files are only available with 8 or 16 bits resolution.
+.br
+The use of a-law or mu-law files, result in a faster processing, since the
+samples must not be converted into a-law or mu-law for ISDN use. ISDN uses only a-law or mu-law
+samples.
+.SH SEE ALSO
+http://www.linux-call-router.de/doc.html
+.SH AUTHOR
+This minimal man page was written by Victor Seva
+<linuxmaniac@torreviejawireless.org>
+.br
+from documentation created by Andreas Eversberg <jolly@eversberg.eu>
diff --git a/debian/lcr.default b/debian/lcr.default
new file mode 100644
index 0000000..d11fad4
--- /dev/null
+++ b/debian/lcr.default
@@ -0,0 +1,7 @@
+# This file allows you to alter the configuration of the lcr
+# init.d script. Normally you should leave the file as-is.
+#
+# RUNLCR: If set to anything other that 'yes', the lcr init.d script
+# will not run. The default is 'yes'.
+RUNLCR=no
+
diff --git a/debian/lcr.init b/debian/lcr.init
new file mode 100644
index 0000000..422bf8d
--- /dev/null
+++ b/debian/lcr.init
@@ -0,0 +1,203 @@
+#! /bin/sh
+#
+# lcr start the lcr isdn PBX
+# (c) Joerg Dorchain <joerg@dorchain.net>
+#
+# This package 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.
+#
+# Based on:
+#
+# skeleton example file to build /etc/init.d/ scripts.
+# This file should be used to construct scripts for
+# /etc/init.d.
+#
+# Written by Miquel van Smoorenburg
+# <miquels@cistron.nl>.
+# Modified for Debian GNU/Linux
+# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
+#
+# Version: @(#)skeleton 1.9 26-Feb-2001
+# miquels@cistron.nl
+#
+
+### BEGIN INIT INFO
+# Provides: lcr
+# Required-Start: $remote_fs
+# Required-Stop: $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: lcr PBX
+# Description: Controls the Linux Call Router ISDN PBX
+### END INIT INFO
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="lcr PBX"
+NAME=lcr
+DAEMON=/usr/sbin/$NAME
+DAEMON_ARGS="fork"
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+RUNLCR=yes
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+if [ "$RUNLCR" != "yes" ];then
+ echo "lcr not yet configured. Edit /etc/default/lcr first."
+ exit 0
+fi
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+status() {
+ plist=`ps ax | awk "{ if (\\$5 == \"$DAEMON\") print \\$1
+}"`
+ if [ "$plist" = "" ]; then
+ echo "$DESC is stopped"
+ return 1
+ else
+ echo "$DESC is running: $plist"
+ return 0
+ fi
+}
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+ # Return
+ # 0 if daemon has been started
+ # 1 if daemon was already running
+ # 2 if daemon could not be started
+ if status > /dev/null; then
+ echo "$DESC is already running. Use restart."
+ exit 1
+ fi
+
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+ || return 1
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
+ $DAEMON_ARGS \
+ || return 2
+ # Add code here, if necessary, that waits for the process to be ready
+ # to handle requests from services started subsequently which depend
+ # on this one. As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+ # Return
+ # 0 if daemon has been stopped
+ # 1 if daemon was already stopped
+ # 2 if daemon could not be stopped
+ # other if a failure occurred
+ start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+ RETVAL="$?"
+ [ "$RETVAL" = 2 ] && return 2
+ # Wait for children to finish too if this is a daemon that forks
+ # and if the daemon is only ever run from this initscript.
+ # If the above conditions are not satisfied then add some other code
+ # that waits for the process to drop all resources that could be
+ # needed by services started subsequently. A last resort is to
+ # sleep for some time.
+ start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+ [ "$?" = 2 ] && return 2
+ # Many daemons don't delete their pidfiles when they exit.
+ rm -f $PIDFILE
+ return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+ #
+ # If the daemon can reload its configuration without
+ # restarting (for example, when it is sent a SIGHUP),
+ # then implement that here.
+ #
+ #start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+ lcradmin route
+ lcradmin interface
+ return 0
+}
+
+case "$1" in
+ start)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+ do_start
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ stop)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ reload)
+ #
+ # If do_reload() is not implemented then leave this commented out
+ # and leave 'force-reload' as an alias for 'restart'.
+ #
+ log_daemon_msg "Reloading $DESC" "$NAME"
+ do_reload
+ log_end_msg $?
+ ;;
+ status)
+ status
+ ;;
+ restart|force-reload)
+ #
+ # If the "reload" option is implemented then remove the
+ # 'force-reload' alias
+ #
+ log_daemon_msg "Restarting $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1)
+ do_start
+ case "$?" in
+ 0) log_end_msg 0 ;;
+ 1) log_end_msg 1 ;; # Old process is still running
+ *) log_end_msg 1 ;; # Failed to start
+ esac
+ ;;
+ *)
+ # Failed to stop
+ log_end_msg 1
+ ;;
+ esac
+ ;;
+ *)
+ #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+ echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+ exit 3
+ ;;
+esac
+
+:
diff --git a/debian/lcr.logrotate b/debian/lcr.logrotate
new file mode 100644
index 0000000..22b67e0
--- /dev/null
+++ b/debian/lcr.logrotate
@@ -0,0 +1,9 @@
+/var/log/lcr/log {
+ weekly
+ missingok
+ rotate 8
+ compress
+ delaycompress
+ notifempty
+# No signalling necessary, lcr does not keep logiles open
+}
diff --git a/debian/lcr.manpages b/debian/lcr.manpages
new file mode 100644
index 0000000..8046f34
--- /dev/null
+++ b/debian/lcr.manpages
@@ -0,0 +1,3 @@
+debian/genextension.8
+debian/gentones.1
+debian/lcradmin.1
diff --git a/debian/lcradmin.1 b/debian/lcradmin.1
new file mode 100644
index 0000000..364225c
--- /dev/null
+++ b/debian/lcradmin.1
@@ -0,0 +1,49 @@
+.TH GENTONES 1
+.SH NAME
+lcradmin \- view and modify the state of a running lcr
+.SH SYNOPSIS
+lcradmin state
+.br
+lcradmin route
+.br
+lcradmin interface
+.br
+lcradmin block <port number>
+.br
+lcradmin unload <port number>
+.br
+lcradmin unload <port number>
+.br
+lcradmin release <endpoint id>
+.SH DESCRIPTION
+.SS lcradmin state
+starts lcradmin in interactive mode. You will see
+a screen with the current calls and a list of keys for possible
+options.
+.SS lcradmin route
+makes lcr reload the routing.conf
+.SS lcradmin interface
+makes lcr reload the interface.conf
+.SS lcradmin block
+makes lcr block the specified port for further
+incoming and outgoing calls.
+.SS lcradmin unblock
+unblocks the port again
+.SS lcradmin unload
+makes lcr cease using the specified port. The port
+the be used by a different application, or to unload the mISDN
+driver. To load the port again, use lcradmin unblock as described above,
+or use lcradmin interface to reload all interfaces.
+.SS lcradmin release
+makes lcr release a pending call. The endpoint ID
+is shown in the status screen, as well as in the log, starting
+with "EP(<ID>)". This can be useful, if two members are joined
+in a conference, but they don't or even can't hang up for some
+reason. Also lost parked calls can be released.
+.SH SEE ALSO
+http://www.linux-call-router.de/doc.html
+.SH AUTHOR
+This minimal man page was written by Joerg Dorchain
+<joerg@dorchain.net>
+.br
+from documentation created by Andreas Eversberg <jolly@eversberg.eu>
diff --git a/debian/patches/configure_warning b/debian/patches/configure_warning
new file mode 100644
index 0000000..959751a
--- /dev/null
+++ b/debian/patches/configure_warning
@@ -0,0 +1,19 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -25,13 +25,13 @@ dnl This keeps being the first instructi
+ dnl Change the 2nd argument if the version increases
+ dnl 1st + 2nd argument is used for distribution package name
+ AC_INIT(lcr, 1.6, andreas@eversberg.eu)
+-AC_PREREQ(2.59)
++AC_PREREQ(2.60)
+ AC_CONFIG_SRCDIR([main.c])
+ AM_CONFIG_HEADER(config.h)
+
+ # fix warnings from autoconf + automake
+-AC_GNU_SOURCE
+-# AC_USE_SYSTEM_EXTENSIONS
++#AC_GNU_SOURCE
++AC_USE_SYSTEM_EXTENSIONS
+ AM_INIT_AUTOMAKE(lcr,1.6)
+
+
diff --git a/debian/patches/replace_local.patch b/debian/patches/replace_local.patch
new file mode 100644
index 0000000..2067d14
--- /dev/null
+++ b/debian/patches/replace_local.patch
@@ -0,0 +1,79 @@
+Author: <joerg@dorchain.net>
+Description: Replace all occurences of local in pathnames
+Index: lcr-1.6~20090906/Makefile.am
+===================================================================
+--- lcr-1.6~20090906.orig/Makefile.am 2009-09-07 13:35:03.834457538 +0200
++++ lcr-1.6~20090906/Makefile.am 2009-09-07 13:36:12.292950699 +0200
+@@ -20,19 +20,19 @@
+ ## the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ ## Boston, MA 02110-1301, USA.
+
+-INSTALLdir = $(DESTDIR)/usr/local/lcr
++INSTALLdir = $(DESTDIR)/usr/share/lcr
+
+ pkglogdir=$(localstatedir)/log/@PACKAGE@
+-pkgsysconfdir=$(sysconfdir)/@PACKAGE@
++pkgsysconfdir=/etc/@PACKAGE@
+
+-#CONFIGdir=$(DESTDIR)$(pkgsysconfdir)
++CONFIGdir=$(DESTDIR)$(pkgsysconfdir)
+ #SHAREdir=$(DESTDIR)$(pkgdatadir)
+-#LOGdir=$(DESTDIR)$(pkglogdir)
++LOGdir=$(DESTDIR)$(pkglogdir)
+ #EXTENSIONdir=$(DESTDIR)$(localstatedir)/lib/lcr
+
+-CONFIGdir=$(INSTALLdir)
++#CONFIGdir=$(INSTALLdir)
+ SHAREdir=$(INSTALLdir)
+-LOGdir=$(INSTALLdir)
++#LOGdir=$(INSTALLdir)
+ EXTENSIONdir=$(INSTALLdir)/extensions
+
+ astmoddir = $(DESTDIR)/usr/lib/asterisk/modules
+Index: lcr-1.6~20090906/genrc.c
+===================================================================
+--- lcr-1.6~20090906.orig/genrc.c 2009-09-07 13:35:03.878459355 +0200
++++ lcr-1.6~20090906/genrc.c 2009-09-07 13:36:12.292950699 +0200
+@@ -80,12 +80,12 @@
+
+ n = i;
+
+- printf("\nWhere do you like to load the modules from, enter 0 for default, 1 for\n'/usr/local/lcr/modules/' or the full path.\n[0 | 1 | <path>]: "); fflush(stdout);
++ printf("\nWhere do you like to load the modules from, enter 0 for default, 1 for\n'/usr/lib/lcr/modules/' or the full path.\n[0 | 1 | <path>]: "); fflush(stdout);
+ scanf("%s", input);
+ if (!strcmp(input, "0"))
+ SCPY(input, "");
+ if (!strcmp(input, "1"))
+- SCPY(input, "/usr/local/lcr/modules");
++ SCPY(input, "/usr/lib/lcr/modules");
+ if (input[0]) if (input[strlen(input)-1] != '/')
+ SCAT(input, "/");
+
+Index: lcr-1.6~20090906/options.c
+===================================================================
+--- lcr-1.6~20090906.orig/options.c 2009-09-07 13:35:03.898459331 +0200
++++ lcr-1.6~20090906/options.c 2009-09-07 13:36:12.296951419 +0200
+@@ -19,7 +19,7 @@
+ #include "options.h"
+
+ struct options options = {
+- "/usr/local/lcr/log", /* log file */
++ "/var/log/lcr/log", /* log file */
+ 0x0000, /* debug mode */
+ 'a', /* a-law */
+ "0", /* national prefix */
+Index: lcr-1.6~20090906/default/options.conf
+===================================================================
+--- lcr-1.6~20090906.orig/default/options.conf 2009-09-07 13:35:03.858458743 +0200
++++ lcr-1.6~20090906/default/options.conf 2009-09-07 13:36:12.296951419 +0200
+@@ -24,8 +24,8 @@
+
+ # The log file can be used to track actions by the LCR. Omit the parameter
+ # to turn off log file. By default, log file is located inside the directory
+-# "/usr/local/lcr/log".
+-#log /usr/local/lcr/log
++# "/var/log/lcr/log".
++#log /var/log/lcr/log
+
+ # Use "alaw" (default) or "ulaw" samples.
+ #alaw
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..a77967f
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,2 @@
+replace_local.patch
+configure_warning
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..4ed2d9b
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,101 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# quilt
+include /usr/share/quilt/quilt.make
+
+DEBVERSION:=$(shell head -n 1 debian/changelog \
+ | sed -e 's/^[^(]*(\([^)]*\)).*/\1/')
+LOCAL_TAR_VER:=$(shell echo $(DEBVERSION) | sed -e 's/^.*://' -e 's/-[0-9.]*$$//')
+UP_MAJOR_VER:=$(shell echo $(LOCAL_TAR_VER) | sed -e 's/~[0-9.]*//')
+UP_DATE_VER:=$(shell echo $(LOCAL_TAR_VER) | sed -e 's/[0-9.]*~//')
+
+UPFILENAME := lcr_$(UP_DATE_VER).tar.gz
+FILENAME := lcr_$(LOCAL_TAR_VER).orig.tar.gz
+URL := http://isdn.eversberg.eu/download/lcr-$(UP_MAJOR_VER)/$(UPFILENAME)
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
+CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
+else
+CROSS= --build $(DEB_BUILD_GNU_TYPE)
+endif
+
+
+
+config.status: patch configure
+ dh_testdir
+ # Add here commands to configure the package.
+ifneq "$(wildcard /usr/share/misc/config.sub)" ""
+ cp -f /usr/share/misc/config.sub config.sub
+endif
+ifneq "$(wildcard /usr/share/misc/config.guess)" ""
+ cp -f /usr/share/misc/config.guess config.guess
+endif
+ CPPFLAGS="-I/usr/include/mISDNuser" ./configure $(CROSS) --without-ssl --without-gsm --prefix=/usr --localstatedir=/var --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" # LDFLAGS="-Wl,-z,defs"
+
+build: build-stamp
+build-stamp: config.status
+ dh_testdir
+ $(MAKE)
+ touch $@
+
+clean: clean-patched unpatch
+clean-patched:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+ [ ! -f Makefile ] || $(MAKE) distclean
+ rm -f config.sub config.guess
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_prep
+ dh_installdirs
+ $(MAKE) DESTDIR=$(CURDIR)/debian/lcr install
+ rm $(CURDIR)/debian/lcr/usr/sbin/genrc
+
+
+# Build architecture-independent files here.
+binary-indep: install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs
+ dh_installdocs
+ dh_installlogrotate
+ dh_installinit -- defaults 21
+ dh_installman
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+
+print-version:
+ @@echo "Debian version: $(DEBVERSION)"
+ @@echo "Upstream version: $(UP_DATE_VER)"
+
+get-orig-source:
+ @@dh_testdir
+ @@[ -d ../tarballs/. ] || mkdir -p ../tarballs
+ @@wget -nv -T10 -t3 --verbose -O ../tarballs/$(FILENAME) $(URL)
+
+.PHONY: build clean binary-indep binary-arch binary install patch unpatch
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..91fb103
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,5 @@
+version=3
+# only using the date part of the debian version.
+# How can I use the match of the directory?
+opts="dversionmangle=s/([\d.]+)~//" \
+ http://isdn.eversberg.eu/download/lcr-([\d.]+)/lcr_([\d]+)\.tar\.gz debian uupdate
diff --git a/default/options.conf b/default/options.conf
index 4875773..f63bd33 100644
--- a/default/options.conf
+++ b/default/options.conf
@@ -96,6 +96,14 @@
# Rights must have 0 in front, if octal values above are used.
#socketrights 0700
+# Change user of LCR socket, where lcradmin or chan_lcr connects to.
+# So: change to asterisk, if you have asterisk run as user "asterisk" e.g.
+#socketuser asterisk
+
+# Change group of LCR socket, where lcradmin or chan_lcr connects to.
+# So: change to asterisk, if you have asterisk run in group "asterisk" e.g.
+#socketgroup asterisk
+
# Enable GSM network capability.
# This option turns LCR into a GSM network. Additional options are specified
# in 'gsm.conf'. You also need openbsc at compile time and of yourse -
diff --git a/dss1.cpp b/dss1.cpp
index 1cb52d1..e318aa3 100644
--- a/dss1.cpp
+++ b/dss1.cpp
@@ -402,7 +402,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
int bearer_coding, bearer_capability, bearer_mode, bearer_rate, bearer_multi, bearer_user;
int exclusive, channel;
int ret;
- unsigned char keypad[32] = "";
+ unsigned char keypad[33] = "";
unsigned char useruser[128];
int useruser_len = 0, useruser_protocol;
class Endpoint *epoint;
@@ -746,7 +746,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
void Pdss1::information_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
{
int type, plan;
- unsigned char keypad[32] = "", display[128] = "";
+ unsigned char keypad[33] = "", display[128] = "";
struct lcr_msg *message;
l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_IND, DIRECTION_IN);
@@ -2098,6 +2098,9 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
enc_ie_called_pn(l3m, 0, 1, (unsigned char *)p_dialinginfo.id, max);
SCPY(p_m_d_queue, p_dialinginfo.id + max);
}
+ /* keypad */
+ if (p_dialinginfo.keypad[0])
+ enc_ie_keypad(l3m, (unsigned char *)p_dialinginfo.keypad);
/* sending complete */
if (p_dialinginfo.sending_complete)
enc_ie_complete(l3m, 1);
diff --git a/extension.c b/extension.c
index a1c3aa7..00e5326 100644
--- a/extension.c
+++ b/extension.c
@@ -68,10 +68,8 @@ int read_extension(struct extension *ext, char *num)
ext->vbox_codec = CODEC_MONO;
line=0;
- while((fgets(buffer, sizeof(buffer), fp))) {
+ while((GETLINE(buffer, fp))) {
line++;
- buffer[sizeof(buffer)-1] = '\0';
- if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
p = buffer;
while(*p <= 32) { /* skip spaces */
@@ -1228,10 +1226,8 @@ int parse_phonebook(char *number, char **abbrev_pointer, char **phone_pointer, c
}
line=0;
- while((fgets(buffer, sizeof(buffer), fp))) {
+ while((GETLINE(buffer, fp))) {
line++;
- buffer[sizeof(buffer)-1] = '\0';
- if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
p = buffer;
while(*p <= 32) { /* skip spaces */
@@ -1351,10 +1347,8 @@ int parse_secrets(char *number, char *remote_id, char **auth_pointer, char **cry
}
line=0;
- while((fgets(buffer, sizeof(buffer), fp))) {
+ while((GETLINE(buffer, fp))) {
line++;
- buffer[sizeof(buffer)-1] = '\0';
- if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
p = buffer;
while(*p <= 32) { /* skip spaces */
@@ -1476,10 +1470,8 @@ char *parse_directory(char *number, int type)
}
line=0;
- while((fgets(buffer, sizeof(buffer), fp))) {
+ while((GETLINE(buffer, fp))) {
line++;
- buffer[sizeof(buffer)-1] = '\0';
- if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
p = buffer;
while(*p <= 32) { /* skip spaces */
@@ -1611,10 +1603,8 @@ int parse_callbackauth(char *number, struct caller_info *callerinfo)
}
line=0;
- while((fgets(buffer, sizeof(buffer), fp))) {
+ while((GETLINE(buffer, fp))) {
line++;
- buffer[sizeof(buffer)-1] = '\0';
- if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
p = buffer;
while(*p <= 32) { /* skip spaces */
diff --git a/gsm_conf.c b/gsm_conf.c
index 08d49dd..efde7bd 100644
--- a/gsm_conf.c
+++ b/gsm_conf.c
@@ -47,10 +47,8 @@ int gsm_conf(struct gsm_conf *gsm_conf)
}
line=0;
- while((fgets(buffer,sizeof(buffer),fp))) {
+ while((GETLINE(buffer, fp))) {
line++;
- buffer[sizeof(buffer)-1]=0;
- if (buffer[0]) buffer[strlen(buffer)-1]=0;
p=buffer;
while(*p <= 32) { /* skip spaces */
diff --git a/interface.c b/interface.c
index 42f409c..8e21c75 100644
--- a/interface.c
+++ b/interface.c
@@ -1148,9 +1148,7 @@ struct interface *read_interfaces(void)
}
line=0;
- while((fgets(buffer,sizeof(buffer),fp))) {
- buffer[sizeof(buffer)-1]=0;
- if (buffer[0]) buffer[strlen(buffer)-1]=0;
+ while((GETLINE(buffer, fp))) {
p=buffer;
line++;
diff --git a/joinpbx.cpp b/joinpbx.cpp
index af070b1..d21daf3 100644
--- a/joinpbx.cpp
+++ b/joinpbx.cpp
@@ -855,12 +855,17 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par
if (param->setup.dialinginfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
numbers = param->setup.dialinginfo.id;
while((number = strsep(&numbers, ","))) {
- if (out_setup(epoint_id, message_type, param, number))
+ if (out_setup(epoint_id, message_type, param, number, NULL))
+ return; // join destroyed
+ }
+ numbers = param->setup.dialinginfo.id;
+ while((number = strsep(&numbers, ","))) {
+ if (out_setup(epoint_id, message_type, param, NULL, number))
return; // join destroyed
}
break;
}
- if (out_setup(epoint_id, message_type, param, NULL))
+ if (out_setup(epoint_id, message_type, param, NULL, NULL))
return; // join destroyed
break;
@@ -945,7 +950,7 @@ int track_notify(int oldstate, int notify)
* if other outgoing endpoints already exists, they are release as well.
* note: if this functions fails, it will destroy its own join object!
*/
-int JoinPBX::out_setup(unsigned int epoint_id, int message_type, union parameter *param, char *newnumber)
+int JoinPBX::out_setup(unsigned int epoint_id, int message_type, union parameter *param, char *newnumber, char *newkeypad)
{
struct join_relation *relation;
struct lcr_msg *message;
@@ -974,7 +979,9 @@ int JoinPBX::out_setup(unsigned int epoint_id, int message_type, union parameter
memcpy(&message->param, param, sizeof(union parameter));
if (newnumber)
SCPY(message->param.setup.dialinginfo.id, newnumber);
- PDEBUG(DEBUG_JOIN, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
+ if (newkeypad)
+ SCPY(message->param.setup.dialinginfo.keypad, newkeypad);
+ PDEBUG(DEBUG_JOIN, "setup message sent to ep %d with number='%s' keypad='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id, message->param.setup.dialinginfo.keypad);
message_put(message);
return(0);
}
diff --git a/joinpbx.h b/joinpbx.h
index 3e275b7..18e38c0 100644
--- a/joinpbx.h
+++ b/joinpbx.h
@@ -70,7 +70,7 @@ class JoinPBX : public Join
void bridge_data(unsigned int epoint_from, struct join_relation *relation_from, union parameter *param);
void remove_relation(struct join_relation *relation);
struct join_relation *add_relation(void);
- int out_setup(unsigned int epoint_id, int message, union parameter *param, char *newnumber);
+ int out_setup(unsigned int epoint_id, int message, union parameter *param, char *newnumber, char *newkeypad);
void play_jingle(int in);
};
diff --git a/macro.h b/macro.h
index 29b2794..9e4bcd1 100644
--- a/macro.h
+++ b/macro.h
@@ -92,7 +92,7 @@ static inline void *_malloc(unsigned int size, const char *function, int line)
if (!addr)
fatal(function, line, "No memory for %d bytes.\n", size);
memset(addr, 0, size);
- return(addr);
+ return addr;
}
/* memory freeing with clearing memory to prevent using freed memory */
@@ -104,4 +104,20 @@ static inline void _free(void *addr, int size)
free(addr);
}
+/* fill buffer and be sure that it's result is 0-terminated, also remove newline */
+#define GETLINE(buffer, fp) _getline(buffer, sizeof(buffer), fp)
+static inline char *_getline(char *buffer, int size, FILE *fp)
+{
+ if (!fgets(buffer, size-1, fp))
+ return NULL;
+ buffer[size-1] = '\0';
+ if (!buffer[0])
+ return buffer;
+ if (buffer[strlen(buffer)-1] == '\n')
+ buffer[strlen(buffer)-1] = '\0';
+ if (buffer[strlen(buffer)-1] == '\r')
+ buffer[strlen(buffer)-1] = '\0';
+ return buffer;
+}
+
diff --git a/message.h b/message.h
index 0849f54..63abc65 100644
--- a/message.h
+++ b/message.h
@@ -178,6 +178,7 @@ struct dialing_info {
int ntype; /* type of number */
int sending_complete; /* end of dialing */
char display[84]; /* display information */
+ char keypad[33]; /* send keypad facility */
};
/* call-info structure CONNECT */
diff --git a/options.c b/options.c
index 6f74533..f58d7f9 100644
--- a/options.c
+++ b/options.c
@@ -17,6 +17,8 @@
#include "macro.h"
#include "extension.h"
#include "options.h"
+#include <grp.h>
+#include <pwd.h>
struct options options = {
"/usr/local/lcr/log", /* log file */
@@ -31,6 +33,8 @@ struct options options = {
"lcr@your.machine", /* source mail adress */
"/var/tmp", /* path of lock files */
0700, /* rights of lcr admin socket */
+ -1, /* socket user (-1= no change) */
+ -1, /* socket group (-1= no change) */
0 /* enable gsm */
};
@@ -202,6 +206,30 @@ int read_options(void)
SCPY(options.lock, param);
} else
+ if (!strcmp(option,"socketuser")) {
+ char * endptr = NULL;
+ options.socketuser = strtol(param, &endptr, 10);
+ if (*endptr != '\0') {
+ struct passwd * pwd = getpwnam(param);
+ if (pwd == NULL) {
+ SPRINT(options_error, "Error in %s (line %d): no such user: %s.\n",filename,line,param);
+ goto error;
+ }
+ options.socketuser = pwd->pw_uid;
+ }
+ } else
+ if (!strcmp(option,"socketgroup")) {
+ char * endptr = NULL;
+ options.socketgroup = strtol(param, &endptr, 10);
+ if (*endptr != '\0') {
+ struct group * grp = getgrnam(param);
+ if (grp == NULL) {
+ SPRINT(options_error, "Error in %s (line %d): no such group: %s.\n",filename,line,param);
+ goto error;
+ }
+ options.socketgroup = grp->gr_gid;
+ }
+ } else
if (!strcmp(option,"socketrights")) {
options.socketrights = strtol(param, NULL, 0);
} else
diff --git a/options.h b/options.h
index ec8f1c1..ecf8244 100644
--- a/options.h
+++ b/options.h
@@ -27,7 +27,8 @@ struct options {
char email[128]; /* source email address */
char lock[128]; /* path of lock files */
int socketrights; /* rights of lcr admin socket */
-
+ int socketuser; /* socket chown to this user */
+ int socketgroup; /* socket chgrp to this group */
int gsm; /* enable gsm support */
};
diff --git a/route.c b/route.c
index d47f8c2..126424f 100644
--- a/route.c
+++ b/route.c
@@ -242,13 +242,16 @@ struct param_defs param_defs[] = {
{ PARAM_ON,
"on", PARAM_TYPE_STRING,
"on=[init|hangup]", "Defines if the action is executed on call init or on hangup."},
+ { PARAM_KEYPAD,
+ "keypad", PARAM_TYPE_NULL,
+ "keypad", "Use 'keypad facility' for dialing, instead of 'called number'."},
{ 0, NULL, 0, NULL, NULL}
};
struct action_defs action_defs[] = {
{ ACTION_EXTERNAL,
"extern", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_external, &EndpointAppPBX::action_hangup_call,
- PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_TIMEOUT,
+ PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_KEYPAD | PARAM_TIMEOUT,
"Call is routed to extern number as dialed."},
{ ACTION_INTERNAL,
"intern", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_internal, &EndpointAppPBX::action_hangup_call,
@@ -256,7 +259,7 @@ struct action_defs action_defs[] = {
"Call is routed to intern extension as given by the dialed number or specified by option."},
{ ACTION_OUTDIAL,
"outdial", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_external, &EndpointAppPBX::action_hangup_call,
- PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_TIMEOUT,
+ PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_KEYPAD | PARAM_TIMEOUT,
"Same as 'extern'"},
{ ACTION_REMOTE,
"remote", &EndpointAppPBX::action_init_remote, &EndpointAppPBX::action_dialing_remote, &EndpointAppPBX::action_hangup_call,
@@ -839,11 +842,9 @@ struct route_ruleset *ruleset_parse(void)
go_leaf:
line[nesting]=0;
go_root:
- while((fgets(buffer,sizeof(buffer),fp[nesting])))
+ while((GETLINE(buffer, fp[nesting])))
{
line[nesting]++;
- buffer[sizeof(buffer)-1]=0;
- if (buffer[0]) buffer[strlen(buffer)-1]=0;
p = buffer;
/* remove tabs */
diff --git a/route.h b/route.h
index 837aebd..3530ef4 100644
--- a/route.h
+++ b/route.h
@@ -146,6 +146,7 @@ enum { /* defines when a statement should be executed */
#define PARAM_CONTEXT (1LL<<45)
#define PARAM_EXTEN (1LL<<46)
#define PARAM_ON (1LL<<47)
+#define PARAM_KEYPAD (1LL<<48)
/* action index
* NOTE: The given index is the actual entry number of action_defs[], so add/remove both lists!!!
diff --git a/socket_server.c b/socket_server.c
index 7a08680..a33f626 100644
--- a/socket_server.c
+++ b/socket_server.c
@@ -64,8 +64,12 @@ int admin_init(void)
return(-1);
}
if (chmod(socket_name, options.socketrights) < 0) {
- PERROR("Failed to change socket rigts to %d. (errno=%d)\n", options.socketrights, errno);
+ PERROR("Failed to change socket rights to %d. (errno=%d)\n", options.socketrights, errno);
}
+ if (chown(socket_name, options.socketuser, options.socketgroup) < 0) {
+ PERROR("Failed to change socket user/group to %d/%d. (errno=%d)\n", options.socketuser, options.socketgroup, errno);
+ }
+
return(0);
}
diff --git a/ss5.cpp b/ss5.cpp
index 0d453e4..5f4d706 100644
--- a/ss5.cpp
+++ b/ss5.cpp
@@ -346,6 +346,7 @@ Pss5::Pss5(int type, struct mISDNport *mISDNport, char *portname, struct port_se
p_m_s_digit_i = 0;
p_m_s_pulsecount = 0;
p_m_s_last_digit = ' ';
+ p_m_s_last_digit_used = ' ';
p_m_s_signal_loss = 0;
p_m_s_decoder_count = 0;
//p_m_s_decoder_buffer;
@@ -428,7 +429,7 @@ void Pss5::inband_receive(unsigned char *buffer, int len)
PDEBUG(DEBUG_SS5, "%s: detecting signal '%c' start (state=%s signal=%s)\n", p_name, digit, ss5_state_name[p_m_s_state], ss5_signal_name[p_m_s_signal]);
#endif
- /* ignore short loss of signal */
+ /* ignore short loss of signal, or change within one decode window */
if (p_m_s_signal_loss) {
if (digit == ' ') {
/* still lost */
@@ -460,11 +461,19 @@ void Pss5::inband_receive(unsigned char *buffer, int len)
p_m_s_last_digit = digit;
/* starting to loose signal */
p_m_s_signal_loss = SS5_DECODER_NPOINTS;
+ } else if (digit != p_m_s_last_digit) {
+ /* digit changes, but we keep old digit until it is detected twice */
+#ifdef DEBUG_DETECT
+ PDEBUG(DEBUG_SS5, "%s: signal '%c' changes to '%c'\n", p_name, p_m_s_last_digit, digit);
+#endif
+ p_m_s_last_digit = digit;
+ digit = p_m_s_last_digit_used;
} else {
/* storing last signal, in case it is lost */
p_m_s_last_digit = digit;
}
}
+ p_m_s_last_digit_used = digit;
/* update mute */
if ((p_m_mISDNport->ss5 & SS5_FEATURE_SUPPRESS)) {
@@ -1347,7 +1356,7 @@ void Pss5::digit_ind(char digit)
end_trace();
new_ss5_state(SS5_STATE_IDLE);
- do_setup(dial);
+ do_setup(dial, 1);
new_state(PORT_STATE_IN_PROCEEDING);
}
@@ -1392,7 +1401,7 @@ void Pss5::pulse_ind(int on)
}
if (p_state == PORT_STATE_IN_SETUP) {
/* sending digit as setup */
- do_setup(dial); /* include 'a' == KP1 */
+ do_setup(dial, 0); /* include 'a' == KP1 */
new_state(PORT_STATE_IN_OVERLAP);
} else {
/* sending digit as information */
@@ -1597,6 +1606,8 @@ void Pss5::do_release(int cause, int location)
{
struct lcr_msg *message;
+ p_m_s_timer = 0.0;
+
/* sending release to endpoint */
while(p_epointlist) {
message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
@@ -1618,13 +1629,13 @@ void Pss5::do_release(int cause, int location)
/*
* create endpoint and send setup
*/
-void Pss5::do_setup(char *dial)
+void Pss5::do_setup(char *dial, int complete)
{
class Endpoint *epoint;
struct lcr_msg *message;
SCPY(p_dialinginfo.id, dial);
- p_dialinginfo.sending_complete = 1;
+ p_dialinginfo.sending_complete = complete;
p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
p_callerinfo.screen = INFO_SCREEN_NETWORK;
p_callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
@@ -1926,6 +1937,8 @@ if (0 || p_type==PORT_TYPE_SS5_OUT) { /* outgoing exchange */
start_signal(SS5_STATE_CLEAR_BACK);
new_state(PORT_STATE_OUT_DISCONNECT);
+// p_m_s_timer_fn = &Pss5::register_timeout;
+// p_m_s_timer = now + 30.0;
}
/* MESSAGE_RELEASE */
@@ -1934,6 +1947,10 @@ void Pss5::message_release(unsigned int epoint_id, int message_id, union paramet
do_release(param->disconnectinfo.cause, param->disconnectinfo.location);
}
+void Pss5::register_timeout(void)
+{
+ do_release(CAUSE_NORMAL, LOCATION_BEYOND);
+}
/*
* endpoint sends messages to the port
diff --git a/ss5.h b/ss5.h
index 6897abd..b1cc215 100644
--- a/ss5.h
+++ b/ss5.h
@@ -34,7 +34,8 @@ class Pss5 : public PmISDN
char p_m_s_dial[64]; /* current dialing register */
int p_m_s_digit_i; /* current digit of register counter */
int p_m_s_pulsecount; /* counts pule dialing half cycles */
- char p_m_s_last_digit; /* stores last digit to fill short signal losses */
+ char p_m_s_last_digit; /* stores last digit that was detected, to fill short signal losses */
+ char p_m_s_last_digit_used; /* stores last digit that was used, to ignore short changes of signal due to noise */
int p_m_s_signal_loss; /* sample counter for loss of signal check */
int p_m_s_decoder_count; /* samples currently decoded */
unsigned char p_m_s_decoder_buffer[SS5_DECODER_NPOINTS]; /* buffer for storing one goertzel window */
@@ -57,7 +58,7 @@ class Pss5 : public PmISDN
void start_signal(int);
void start_outgoing(void);
void do_release(int cause, int location);
- void do_setup(char *digit);
+ void do_setup(char *digit, int complete);
void seizing_ind(void);
void digit_ind(char digit);
@@ -76,6 +77,8 @@ class Pss5 : public PmISDN
void message_disconnect(unsigned int epoint_id, int message_id, union parameter *param);
void message_release(unsigned int epoint_id, int message_id, union parameter *param);
+ void register_timeout(void);
+
};
#define new_ss5_state(a) _new_ss5_state(a, __FUNCTION__, __LINE__)
diff --git a/ss5_decode.c b/ss5_decode.c
index 0a00a6f..35e2664 100644
--- a/ss5_decode.c
+++ b/ss5_decode.c
@@ -18,8 +18,9 @@
#define NCOEFF 8 /* number of frequencies to be analyzed */
-#define MIN_DB 0.01995262 /* -17 db */
-#define DIFF_DB 0.2 // 0.31622777 /* -5 db */
+#define TONE_MIN_DB 0.01995262 /* -17 db */
+#define TONE_DIFF_DB 0.2 // 0.31622777 /* -5 db */
+#define NOISE_MIN_DB (TONE_MIN_DB / 2) /* noise must be higher than the minimum of two tones */
#define SNR 1.3 /* noise may not exceed signal by that factor */
/* For DTMF recognition:
@@ -65,6 +66,22 @@ char ss5_decode(unsigned char *data, int len)
for (i = 0; i < len; i++)
buf[i] = audio_law_to_s32[*data++];
+ /* now we do noise level calculation */
+ low = 32767;
+ high = -32768;
+ for (n = 0; n < len; n++) {
+ sk = buf[n];
+ if (sk < low)
+ low = sk;
+ if (sk > high)
+ high = sk;
+ }
+ noise = ((double)(high-low) / 65536.0);
+
+ /* check for minimum noise, or tone detection will not be necessary */
+ if (noise < NOISE_MIN_DB)
+ return digit;
+
/* now we have a full buffer of signed long samples - we do goertzel */
for (k = 0; k < NCOEFF; k++) {
sk = 0;
@@ -88,18 +105,6 @@ char ss5_decode(unsigned char *data, int len)
) / len / 62; /* level of 1 is 0 db*/
}
- /* now we do noise level calculation */
- low = 32767;
- high = -32768;
- for (n = 0; n < len; n++) {
- sk = buf[n];
- if (sk < low)
- low = sk;
- if (sk > high)
- high = sk;
- }
- noise = ((double)(high-low) / 65536.0);
-
/* find the two loudest frequencies + one less lower frequency to detect noise */
power = 0.0;
for (i = 0; i < NCOEFF; i++) {
@@ -118,15 +123,15 @@ char ss5_decode(unsigned char *data, int len)
snr = 0;
/* check one frequency */
- if (result[f1] > MIN_DB /* must be at least -17 db */
+ if (result[f1] > TONE_MIN_DB /* must be at least -17 db */
&& result[f1]*SNR > noise) { /* */
digit = decode_one[f1];
if (digit != ' ')
snr = result[f1] / noise;
}
/* check two frequencies */
- if (result[f1] > MIN_DB && result[f2] > MIN_DB /* must be at lease -17 db */
- && result[f1]*DIFF_DB <= result[f2] /* f2 must be not less than 5 db below f1 */
+ if (result[f1] > TONE_MIN_DB && result[f2] > TONE_MIN_DB /* must be at lease -17 db */
+ && result[f1]*TONE_DIFF_DB <= result[f2] /* f2 must be not less than 5 db below f1 */
&& (result[f1]+result[f2])*SNR > noise) { /* */
digit = decode_two[f1][f2];
if (digit != ' ')
@@ -135,13 +140,11 @@ char ss5_decode(unsigned char *data, int len)
/* debug powers */
#ifdef DEBUG_LEVELS
- if (noise > 0.2) {
- for (i = 0; i < NCOEFF; i++)
- printf("%d:%3d %c ", i, (int)(result[i]*100), (f1==i || f2==i)?'*':' ');
- printf("N:%3d digit:%c snr=%3d\n", (int)(noise*100), digit, (int)(snr*100));
- if (result[f1]*DIFF_DB <= result[f2]) /* f2 must be not less than 5 db below f1 */
- printf("jo!");
- }
+ for (i = 0; i < NCOEFF; i++)
+ printf("%d:%3d %c ", i, (int)(result[i]*100), (f1==i || f2==i)?'*':' ');
+ printf("N:%3d digit:%c snr=%3d\n", (int)(noise*100), digit, (int)(snr*100));
+// if (result[f1]*TONE_DIFF_DB <= result[f2]) /* f2 must be not less than 5 db below f1 */
+// printf("jo!");
#endif
return digit;