summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-02-09 18:03:45 +0000
committerLennart Poettering <lennart@poettering.net>2004-02-09 18:03:45 +0000
commite36910ad6e13c82ab6b1d1206241c676ab3265ba (patch)
treed174a71895f5933dbf55f48f27b2ff9227569fc6
parent299552c0ffc90d69b0593eecdc19fc859d445cbd (diff)
add patches bei Wolfgang Ocker
git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@61 dbf6933d-3bce-0310-9bcc-ed052ba35b35
-rwxr-xr-xclients/ivam-autobox9
-rwxr-xr-xclients/ivam-voicebox7
-rw-r--r--clients/ivamVoiceBox.py10
-rw-r--r--conf/msntab23
-rw-r--r--configure.ac2
-rw-r--r--doc/README.html.in32
-rw-r--r--man/msntab.5.xml.in13
-rw-r--r--src/modem.c9
-rw-r--r--src/msntab.c227
-rw-r--r--src/msntab.h3
10 files changed, 297 insertions, 38 deletions
diff --git a/clients/ivam-autobox b/clients/ivam-autobox
index 800953e..fbe5e10 100755
--- a/clients/ivam-autobox
+++ b/clients/ivam-autobox
@@ -25,12 +25,12 @@ from ivamUtil import getContents, setContents
import ivamCore, ivamVoiceBox
def usage():
- log("%s [--record-time=SECS] [--pin=PIN] [--pin-file=PINFILE] [--default-record-time=SECS] [--default-pin=PIN] [--default-pin-file=PINFILE] [--record-only] [--no-record] [--debug] [--notify-script=PATH] [--email=EMAIL] [DIRECTORY]" % sys.argv[0])
+ log("%s [--record-time=SECS] [--welcome-message=MESSAGE] [--pin=PIN] [--pin-file=PINFILE] [--default-record-time=SECS] [--default-pin=PIN] [--default-pin-file=PINFILE] [--record-only] [--no-record] [--debug] [--notify-script=PATH] [--email=EMAIL] [DIRECTORY]" % sys.argv[0])
def parseArgs(vb, argv):
try:
- opts, args = getopt.getopt(argv[1:], "dh", ["help", "record-time=", "pin=", "pin-file=", "default-record-time=", "default-pin=", "default-pin-file=", "debug", "record-only", "no-record", "email=", "notify-script="])
+ opts, args = getopt.getopt(argv[1:], "dh", ["help", "record-time=", "welcome-message=", "pin=", "pin-file=", "default-record-time=", "default-pin=", "default-pin-file=", "debug", "record-only", "no-record", "email=", "notify-script="])
except getopt.GetoptError:
usage()
sys.exit(1)
@@ -86,7 +86,10 @@ def parseArgs(vb, argv):
elif o in ("--pin",):
vb.setPin(a)
-
+
+ elif o in ("--welcome-message",):
+ vb.setWelcomeMessage(a)
+
elif o in ("--pin-file",):
vb.setPin(getContents(a))
diff --git a/clients/ivam-voicebox b/clients/ivam-voicebox
index 88b6778..02e5b33 100755
--- a/clients/ivam-voicebox
+++ b/clients/ivam-voicebox
@@ -25,12 +25,12 @@ from ivamUtil import getContents, setContents
import ivamCore, ivamVoiceBox
def usage():
- log("%s [--record-time=SECS] [--pin=PIN] [--pin-file=PINFILE] [--message-program=BINARY] [--debug] [--record-only] [--no-record] DIRECTORY" % sys.argv[0])
+ log("%s [--record-time=SECS] [--welcome-message=MESSAGE] [--pin=PIN] [--pin-file=PINFILE] [--message-program=BINARY] [--debug] [--record-only] [--no-record] DIRECTORY" % sys.argv[0])
def parseArgs(vb, argv):
try:
- opts, args = getopt.getopt(argv[1:], "hd", ["help", "record-time=", "pin=", "pin-file=", "debug", "message-program=", "record-only", "no-record"])
+ opts, args = getopt.getopt(argv[1:], "hd", ["help", "record-time=", "welcome-message=", "pin=", "pin-file=", "debug", "message-program=", "record-only", "no-record"])
except getopt.GetoptError:
usage()
sys.exit(1)
@@ -54,6 +54,9 @@ def parseArgs(vb, argv):
elif o in ("--record-time",):
vb.recordTime = int(a)
+ elif o in ("--welcome-message",):
+ vb.setWelcomeMessage(a)
+
elif o in ("--pin",):
vb.setPin(a)
diff --git a/clients/ivamVoiceBox.py b/clients/ivamVoiceBox.py
index 68eff9c..e358e7b 100644
--- a/clients/ivamVoiceBox.py
+++ b/clients/ivamVoiceBox.py
@@ -32,6 +32,7 @@ class VoiceBox(ivamApi.Processor):
fileSuffix = ".ulaw.gz"
recordOnly = False
noRecord = False
+ welcomeMessage = "welcome"
def getClip(self, s):
return "%s/%s%s" % (self.directory, s, self.fileSuffix)
@@ -48,7 +49,7 @@ class VoiceBox(ivamApi.Processor):
self.authNow(c)
else:
self.currentState = self.STATE_WELCOME
- c.playClip(self.getClip("welcome"))
+ c.playClip(self.getClip(self.welcomeMessage))
def loginComplete(self, c):
self.messages = self.getMessageNames()
@@ -267,6 +268,13 @@ class VoiceBox(ivamApi.Processor):
return "%s/%010u:%s:%s%s" % (self.messageDirectory, time.time(), self.ringNumber, self.callerNumber, self.fileSuffix)
+ def setWelcomeMessage(self, welcomeMessage):
+
+ if ivamCore.DEBUG:
+ ivamCore.log("setWelcomeMessage('%s')" % welcomeMessage)
+
+ self.welcomeMessage = welcomeMessage
+
def setPin(self, pin):
if ivamCore.DEBUG:
diff --git a/conf/msntab b/conf/msntab
index 0c5ea5d..3731b66 100644
--- a/conf/msntab
+++ b/conf/msntab
@@ -38,19 +38,24 @@
# See msntab(5) for more information
-# local MSN remote MSN options action
-* * rings=8,pipehack ivam-autobox
+# local MSN remote MSN days times options action
+#* * * * rings=8,pipehack ivam-autobox
# Some more examples
-#41264179 * rings=0,pipehack ivam-autobox
+#41264179 * * * rings=0,pipehack ivam-autobox
-#41264179 41264177 rings=0 ivam-dialup --pin=4711 ppp0
-#* 41264179 rings=0 @hangup
-#41264179 * rings=2,shbuf ivam-voicebox --pin=4711
+#41264179 41264177 * * rings=0 ivam-dialup --pin=4711 ppp0
+#* 41264179 * * rings=0 @hangup
+#41264179 * * * rings=2,shbuf ivam-voicebox --pin=4711
-#46 36 defaults @hangup
-#46 36 rings=0 ivam-play /var/spool/ivam/welcome.ulaw
-#46 * defaults ivam-echo
+#46 36 * * defaults @hangup
+#46 36 * * rings=0 ivam-play /var/spool/ivam/welcome.ulaw
+#46 * * * defaults ivam-echo
+
+#47 * WORK 08:00-11:59,13:00-17:59 rings=6,pipehack ivam-voicebox --welcome-message=welcome-day
+#47 * WORK 12:00-12:59 rings=2,pipehack ivam-voicebox --welcome-message=welcome-noon
+#47 * WORK 18:00-23:59,00:00-07:59 rings=2,pipehack ivam-voicebox --welcome-message=welcome-night
+#47 * WEEKEND * rings=2,pipehack ivam-voicebox --welcome-message=welcome-weekend
# $Id$
diff --git a/configure.ac b/configure.ac
index b031e56..db37672 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
AC_PREREQ(2.59)
-AC_INIT([ivam2],[0.2],[mzvinzgjb (at) 0pointer (dot) de])
+AC_INIT([ivam2],[0.3],[mzvinzgjb (at) 0pointer (dot) de])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign -Wall])
diff --git a/doc/README.html.in b/doc/README.html.in
index 4aacbd4..266f62d 100644
--- a/doc/README.html.in
+++ b/doc/README.html.in
@@ -42,6 +42,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.</p>
<h2><a name="news">News</a></h2>
+<div class="news-date">Mon Feb 9 2004: </div>
+
+<p class="news-text"><a href="@PACKAGE_URL@ivam2-0.3.tar.gz">Version
+0.3</a> released, changes include: time dependent configuration; this
+version breaks <tt>msntab</tt> compatibility as two new columns (time
+and date) are introduced - <b>you need update the file manually</b>; compatibility fixes with Python 2.2; assorted bug fixes</p>
+
<div class="news-date">Mon Jan 26 2004: </div>
<p class="news-text"><a href="@PACKAGE_URL@ivam2-0.2.tar.gz">Version 0.2</a> released, changes include: compatiblity with non-C99 compilers (such as gcc 2.95), python script fixes.</p>
@@ -97,20 +104,23 @@ command line arguments and the file <tt>msntab</tt>. The latter
specifies which telephony application to start for which caller/callee
pairs. An example:</p>
-<pre>47110816 * defaults @ignore
-47110815 12345678 defaults @hangup
-47110815 87654321 rings=2 ivam-play /path/to/an/ulaw/file.ulaw.gz
-47110815 47110815 rings=0,pipehack ivam-autobox
-47110815 * rings=8,pipehack ivam-autobox
+<pre># Local Remote Days Times Options Action
+47110816 * * * defaults @ignore
+47110815 * * 12:00-12:15 defaults @ignore
+47110815 12345678 * * defaults @hangup
+47110815 87654321 * * rings=2 ivam-play /path/to/an/ulaw/file.ulaw.gz
+47110815 47110815 * * rings=0,pipehack ivam-autobox
+47110815 * * * rings=8,pipehack ivam-autobox
</pre>
<p>This configuration can be explained as follows: all calls to the
local phone number 47110816 are ignored. Calls to the local phone
-number 47110815 are dispatched as follows: if the caller is 87654321,
-he will listen to a static message after two rings. If someone is
-calling the local number from the same number he enters the voice box
-system immediately. All other callers will be dispatched to the voice
-box system after eight rings.</p>
+number 47110815 are dispatched as follows: during lunch break all calls
+are ignored, if if the caller is 87654321, he will listen to a static
+message after two rings. If someone is calling the local number from
+the same number he enters the voice box system immediately. All other
+callers will be dispatched to the voice box system after eight
+rings.</p>
<p>For more information on this configuration file see the manual page <a href="@PACKAGE_URL@msntab.5.xml"><tt>msntab(5)</tt></a>.</p>
@@ -211,6 +221,8 @@ the telephony services you want to use.</p>
<p>Wolfram Schlich for many suggestions and beta testing.</p>
+<p>Wolfgang Ocker for some patches.</p>
+
<h2><a name="download">Download</a></h2>
<p>The newest release is always available from <a href="@PACKAGE_URL@">@PACKAGE_URL@</a></p>
diff --git a/man/msntab.5.xml.in b/man/msntab.5.xml.in
index fad8946..3df919e 100644
--- a/man/msntab.5.xml.in
+++ b/man/msntab.5.xml.in
@@ -32,9 +32,10 @@
<p>msntab is the phone call routing table for ivam2. For each
incoming call the first matching line in the file is used, all
- others are ignored. Each line consists of four fields: an
+ others are ignored. Each line consists of six fields: an
expression for matching the local phone number, an expression
- for matching the remote phone number, an option list and an
+ for matching the remote phone number, a day specification,
+ a time specification, an option list and an
action filed, specifying an executable file with its arguments
which is run for a matching call. If no line matches a call, the
call is ignored.</p>
@@ -49,6 +50,14 @@
to the end is taken es regular expression and matched with
<manref name="regexec" section="4"/>.</p>
+ <p>The day specification is a comma separated list of the week
+ days "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT". It
+ also may be specified as "WORK" or "WEEKEND" to match work
+ days or weekend days, respectively.</p>
+
+ <p>The time specification is a comma separated list of time
+ ranges in the format "HH:MM".</p>
+
<p>The option field consists of a comma separated list of
options. The following options are defined: "rings=n" specifies
after how many rings a call is accepted. "pipehack" enables the
diff --git a/src/modem.c b/src/modem.c
index f98079a..3a3f656 100644
--- a/src/modem.c
+++ b/src/modem.c
@@ -73,8 +73,7 @@
#define INPUT_RANGE_CHILD 64
#define OUTPUT_RANGE_CHILD 1024
-#define INIT_AT_COMMANDS 16
-static const char* const init_at_commands[INIT_AT_COMMANDS*2] = {
+static const char* const init_at_commands[] = {
"\nAT&F\n", /* Reset to fabric defaults */
"OK\r\n",
@@ -108,7 +107,7 @@ static const char* const init_at_commands[INIT_AT_COMMANDS*2] = {
"ATS23=1\n",
"OK\r\n",
- "ATS16=1\n", /* send packet size */
+ "ATS16=4\n", /* send packet size (set to 4 instead of 1 to avoid a play distortion with a B1) */
"OK\r\n",
"AT\n", //S12.3=0\n", /* DCD always on */
@@ -124,6 +123,8 @@ static const char* const init_at_commands[INIT_AT_COMMANDS*2] = {
"OK\r\n",
};
+#define INIT_AT_COMMANDS ((sizeof(init_at_commands)/sizeof(init_at_commands[0]))/2)
+
static const char hup_sequence[] = { DLE, DC4, DLE, ETX, 0 };
static const char ath_sequence[] = "\nATH\n";
@@ -251,7 +252,7 @@ static void modem_next_command(struct modem *m) {
if (m->command_index == 0)
buffio_command(m->buffio, hup_sequence);
- else if (m->command_index == 15) {
+ else if (!strncmp(p, "AT&L", 4)) {
char *l = m->listen_msn ? m->listen_msn : "*";
daemon_log(LOG_INFO, "[%s] Listening on '%s'.", m->name, l);
snprintf(tmp, sizeof(tmp), p, l);
diff --git a/src/msntab.c b/src/msntab.c
index 12002d5..446971c 100644
--- a/src/msntab.c
+++ b/src/msntab.c
@@ -30,6 +30,8 @@
#include <stdio.h>
#include <unistd.h>
#include <regex.h>
+#include <time.h>
+#include <ctype.h>
#include <libdaemon/dlog.h>
@@ -82,12 +84,196 @@ int glob_match(const char *e, const char *s) {
}
}
+
+/*
+**
+** The functions make_time, time_match, and day_match have
+** been borrowed from the file rcvbox.c of vbox.
+**
+** Original Copyright:
+**
+** Copyright (C) 1996, 1997 Michael 'Ghandi' Herold
+*/
+
+static time_t make_time(time_t timenow, char *timestr, int mode)
+{
+ struct tm *locala;
+ struct tm localb;
+
+ char timestring[5 + 1];
+ char *hourstr, *minsstr;
+ int hourint, minsint, secsint;
+
+ strncpy(timestring, timestr, 5);
+
+ hourstr = timestring;
+ minsstr = index(hourstr, ':');
+
+ if (!minsstr) {
+ if (!mode)
+ minsstr = "00";
+ else
+ minsstr = "59";
+ }
+ else
+ *minsstr++ = '\0';
+
+ if (!mode)
+ secsint = 0;
+ else
+ secsint = 59;
+
+ hourint = atoi(hourstr);
+ minsint = atoi(minsstr);
+
+ if (hourint < 0 || hourint > 23)
+ return 0;
+ if (minsint < 0 || minsint > 59)
+ return 0;
+
+ locala = localtime(&timenow);
+ if (!locala)
+ return 0;
+
+ localb = *locala;
+
+ localb.tm_sec = secsint;
+ localb.tm_min = minsint;
+ localb.tm_hour = hourint;
+
+ return mktime(&localb);
+}
+
+int time_match(char *timestr)
+{
+ char *timestring;
+ char *timeptr;
+ char *timenxt;
+ char *timebeg, *timeend;
+ time_t timenow;
+ time_t timesecsbeg, timesecsend;
+ int res = 0;
+
+ timestring = strdup(timestr);
+ assert(timestring);
+
+ timeptr = timestring;
+ timenow = time(NULL);
+
+ if (!strcmp(timestring, "*")) {
+ res = 1;
+ goto out;
+ }
+
+ if (!strcmp(timestring, "!") || !strcmp(timestring, "-"))
+ goto out;
+
+ while (timeptr) {
+ timenxt = index(timeptr, ',');
+ if (timenxt)
+ *timenxt++ = '\0';
+
+ timebeg = timeptr;
+ timeend = index(timebeg, '-');
+
+ if (timeend)
+ *timeend++ = '\0';
+ else
+ timeend = timebeg;
+
+ if (!timeend)
+ timeend = timebeg;
+
+ timesecsbeg = make_time(timenow, timebeg, 0);
+ timesecsend = make_time(timenow, timeend, 1);
+
+ if (timesecsbeg < 0 || timesecsend < timesecsbeg)
+ daemon_log(LOG_WARNING, "End time less then begin time in timestring %s", timestr);
+ else if (timenow >= timesecsbeg && timenow <= timesecsend) {
+ res = 1;
+ goto out;
+ }
+
+ timeptr = timenxt;
+ }
+
+out:
+ if (timestring)
+ free(timestring);
+
+ return res;
+}
+
+int day_match(char *strdays)
+{
+ static char *weekdaynames[] = {
+ "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT",
+ "WEEKEND", "WORK", "WORK", "WORK", "WORK", "WORK", "WEEKEND",
+ NULL
+ };
+
+ struct tm *timelocal;
+ char *beg, *nxt;
+ char *days;
+ int i;
+ time_t timenow;
+ int res = 0;
+
+ days = strdup(strdays);
+ assert(days);
+
+ if (!strcmp(days, "*")) {
+ res = 1;
+ goto out;
+ }
+
+ if (!strcmp(days, "-") || !strcmp(days, "!") )
+ goto out;
+
+ timenow = time(NULL);
+
+ timelocal = localtime(&timenow);
+ if (!timelocal)
+ goto out;
+
+ for (i = 0; i < strlen(days); i++) {
+ if (!isalpha(days[i]) && days[i] != ',') {
+ daemon_log(LOG_WARNING, "Error in daystring %s", strdays);
+ goto out;
+ }
+ }
+
+ beg = days;
+
+ while (beg) {
+ nxt = index(beg, ',');
+ if (nxt)
+ *nxt++ = 0;
+
+ for (i = 0; weekdaynames[i]; i++) {
+ if (!strcasecmp(weekdaynames[i], beg) && (i%7) == timelocal->tm_wday) {
+ res = 1;
+ goto out;
+ }
+ }
+
+ beg = nxt;
+ }
+
+out:
+ if (days)
+ free(days);
+
+ return res;
+}
+
+
struct tabentry* msntab_check_call(const char *callee, const char *caller) {
struct tabentry *l = first;
while (l) {
- int a, b;
- assert(l->local && l->remote);
+ int a, b, c, d;
+ assert(l->local && l->remote && l->dayspec && l->timespec);
if (l->local[0] == '~')
a = !regex_match(l->local+1, callee);
@@ -99,8 +285,11 @@ struct tabentry* msntab_check_call(const char *callee, const char *caller) {
b = !regex_match(l->remote+1, caller);
else
b = !glob_match(l->remote, caller);
-
- if (a && b) {
+
+ c = day_match(l->dayspec);
+ d = time_match(l->timespec);
+
+ if (a && b && c && d) {
daemon_log(LOG_INFO, "MSN table entry from '%s:%u' matched.", l->filename, l->line);
return msntab_ref(l);
}
@@ -135,6 +324,8 @@ void msntab_unref(struct tabentry *t) {
free(t->local);
free(t->remote);
+ free(t->dayspec);
+ free(t->timespec);
free(t->filename);
free(t);
@@ -222,7 +413,7 @@ int msntab_load(const char *fn) {
n = 0;
while (!feof(f)) {
- char l[256], *c, *e, *local, *remote, *options, *action;
+ char l[256], *c, *e, *local, *remote, *dayspec, *timespec, *options, *action;
n++;
@@ -274,6 +465,22 @@ int msntab_load(const char *fn) {
if (c)
c+=strspn(c, " \t");
+ if (!(dayspec = strsep(&c, " \t"))) {
+ daemon_log(LOG_ERR, "Parse failure on dayspec field in '%s:%i'.", fn, n);
+ goto fail;
+ }
+
+ if (c)
+ c+=strspn(c, " \t");
+
+ if (!(timespec = strsep(&c, " \t"))) {
+ daemon_log(LOG_ERR, "Parse failure on timespec field in '%s:%i'.", fn, n);
+ goto fail;
+ }
+
+ if (c)
+ c+=strspn(c, " \t");
+
if (!(options = strsep(&c, " \t"))) {
daemon_log(LOG_ERR, "Parse failure on options field in '%s:%i'.", fn, n);
goto fail;
@@ -302,6 +509,12 @@ int msntab_load(const char *fn) {
t->remote = strdup(remote);
assert(t->remote);
+ t->dayspec = strdup(dayspec);
+ assert(t->dayspec);
+
+ t->timespec = strdup(timespec);
+ assert(t->timespec);
+
if (action[0] == '@') {
if (!strcmp(action, "@hangup"))
t->action = CALL_ACTION_HANGUP;
@@ -372,11 +585,13 @@ static void dump_entry(struct tabentry *t) {
} else
strncpy(s, "NOARGS", sizeof(s));
- daemon_log(LOG_INFO, "[%s:%02u] %-12s -> %-12s; shbuf=%c; pipehack=%c; rings=%u; action=%s; args=<%s>",
+ daemon_log(LOG_INFO, "[%s:%02u] %-12s -> %-12s; %s %s; shbuf=%c; pipehack=%c; rings=%u; action=%s; args=<%s>",
t->filename,
t->line,
t->local,
t->remote,
+ t->dayspec,
+ t->timespec,
t->shbuf ? 'y' : 'n',
t->pipehack ? 'y' : 'n',
t->rings,
diff --git a/src/msntab.h b/src/msntab.h
index 2a09f2a..fd6acc8 100644
--- a/src/msntab.h
+++ b/src/msntab.h
@@ -31,6 +31,9 @@ struct tabentry {
char *local;
char *remote;
+ char *timespec;
+ char *dayspec;
+
struct tabentry *next;
struct tabentry *prev;