From e36910ad6e13c82ab6b1d1206241c676ab3265ba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 9 Feb 2004 18:03:45 +0000 Subject: add patches bei Wolfgang Ocker git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@61 dbf6933d-3bce-0310-9bcc-ed052ba35b35 --- clients/ivam-autobox | 9 +- clients/ivam-voicebox | 7 +- clients/ivamVoiceBox.py | 10 ++- conf/msntab | 23 +++-- configure.ac | 2 +- doc/README.html.in | 32 ++++--- man/msntab.5.xml.in | 13 ++- src/modem.c | 9 +- src/msntab.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++-- src/msntab.h | 3 + 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.

News

+
Mon Feb 9 2004:
+ +

Version +0.3 released, changes include: time dependent configuration; this +version breaks msntab compatibility as two new columns (time +and date) are introduced - you need update the file manually; compatibility fixes with Python 2.2; assorted bug fixes

+
Mon Jan 26 2004:

Version 0.2 released, changes include: compatiblity with non-C99 compilers (such as gcc 2.95), python script fixes.

@@ -97,20 +104,23 @@ command line arguments and the file msntab. The latter specifies which telephony application to start for which caller/callee pairs. An example:

-
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
+
# 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
 

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.

+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.

For more information on this configuration file see the manual page msntab(5).

@@ -211,6 +221,8 @@ the telephony services you want to use.

Wolfram Schlich for many suggestions and beta testing.

+

Wolfgang Ocker for some patches.

+

Download

The newest release is always available from @PACKAGE_URL@

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 @@

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.

@@ -49,6 +50,14 @@ to the end is taken es regular expression and matched with .

+

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.

+ +

The time specification is a comma separated list of time + ranges in the format "HH:MM".

+

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 #include #include +#include +#include #include @@ -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++; @@ -271,6 +462,22 @@ int msntab_load(const char *fn) { goto fail; } + 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"); @@ -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; -- cgit