From 7b3475368a1950d2adc638bdc4d0bbda4b3d1e18 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 8 Jan 2004 23:42:08 +0000 Subject: made ivamd a real daemon git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@20 dbf6933d-3bce-0310-9bcc-ed052ba35b35 --- clients/ivam-autobox | 22 +++++++--- clients/ivam-voicebox | 11 +++-- clients/ivamApi.py | 2 +- clients/ivamPipeConnector.py | 4 +- clients/ivamVoiceBox.py | 5 ++- doc/TODO | 7 ++- src/Makefile | 11 +++-- src/buffio.c | 6 +-- src/ivamd.ggo | 29 +++++++++++++ src/main.c | 100 ++++++++++++++++++++++++++++++++++++++----- src/main.h | 6 ++- src/modem.c | 10 ++--- src/modem.h | 2 - src/modemman.c | 2 - 14 files changed, 176 insertions(+), 41 deletions(-) create mode 100644 src/ivamd.ggo diff --git a/clients/ivam-autobox b/clients/ivam-autobox index bb7fcfc..8b11f8e 100755 --- a/clients/ivam-autobox +++ b/clients/ivam-autobox @@ -4,14 +4,15 @@ import sys, os, getopt from ivamCore import log import ivamCore, ivamVoiceBox +from optparse import OptionParser def usage(): - log("%s [--record-time=SECS] [--pin=PIN] [--pin-file=PINFILE] [--debug] [DIRECTORY]" % sys.argv[0]) + log("%s [--record-time=SECS] [--pin=PIN] [--pin-file=PINFILE] [--default-record-time=SECS] [--default-pin=PIN] [--default-pin-file=PINFILE] [--debug] [DIRECTORY]" % sys.argv[0]) def parseArgs(vb, argv): try: - opts, args = getopt.getopt(argv[1:], "ht:p:P:de:", ["help", "record-time=", "pin=", "pin-file=", "debug", "message-program"]) + opts, args = getopt.getopt(argv[1:], "dh", ["help", "record-time=", "pin=", "pin-file=", "default-record-time=", "default-pin=", "default-pin-file=", "debug"]) except getopt.GetoptError: usage() sys.exit(1) @@ -27,13 +28,13 @@ def parseArgs(vb, argv): usage() sys.exit() - elif o in ("-t", "--record-time"): + elif o in ("--default-record-time"): recordTime = int(a) - elif o in ("-p", "--pin"): + elif o in ("--default-pin"): pin = a - elif o in ("-P", "--pin-file"): + elif o in ("--default-pin-file"): pin = getContents(a) dname = "msn-" + os.getenv("RINGMSN") @@ -48,6 +49,17 @@ def parseArgs(vb, argv): vb.setDirectory(dname) + for o, a in opts: + if o in ("--record-time"): + vb.recordTime = int(a) + + elif o in ("--pin"): + vb.setPin(a) + + elif o in ("--pin-file"): + vb.setPin(getContents(a)) + + def main(): vb = ivamVoiceBox.VoiceBox() parseArgs(vb, sys.argv) diff --git a/clients/ivam-voicebox b/clients/ivam-voicebox index fbf6afa..1ec19d5 100755 --- a/clients/ivam-voicebox +++ b/clients/ivam-voicebox @@ -11,7 +11,7 @@ def usage(): def parseArgs(vb, argv): try: - opts, args = getopt.getopt(argv[1:], "ht:p:P:de:", ["help", "record-time=", "pin=", "pin-file=", "debug", "message-program"]) + opts, args = getopt.getopt(argv[1:], "hd", ["help", "record-time=", "pin=", "pin-file=", "debug", "message-program="]) except getopt.GetoptError: usage() sys.exit(1) @@ -32,19 +32,18 @@ def parseArgs(vb, argv): usage() sys.exit() - elif o in ("-t", "--record-time"): + elif o in ("--record-time"): vb.recordTime = int(a) - elif o in ("-p", "--pin"): + elif o in ("--pin"): vb.setPin(a) - elif o in ("-P", "--pin-file"): + elif o in ("--pin-file"): vb.setPin(getContents(a)) - elif o in ("-e", "--message-program"): + elif o in ("--message-program"): vb.messageProgram = a - def main(): vb = ivamVoiceBox.VoiceBox() parseArgs(vb, sys.argv) diff --git a/clients/ivamApi.py b/clients/ivamApi.py index 8cab6f9..97534ff 100644 --- a/clients/ivamApi.py +++ b/clients/ivamApi.py @@ -10,7 +10,7 @@ class Processor: def onDtmfEvent(self, c, event): pass - def onClipFinish(self, c, fname): + def onClipFinish(self, c, fname, length): pass def onTimeout(self, c): diff --git a/clients/ivamPipeConnector.py b/clients/ivamPipeConnector.py index af302b8..bbaf9ed 100644 --- a/clients/ivamPipeConnector.py +++ b/clients/ivamPipeConnector.py @@ -92,6 +92,7 @@ class PipeConnector(ivamApi.Connector): self.recordName = fname self.recording = True + self.recordLength = 0 def stopRecording(self): @@ -102,7 +103,7 @@ class PipeConnector(ivamApi.Connector): self.recordFile.close() self.recording = False - self.processor.onRecordFinish(self, self.recordName) + self.processor.onRecordFinish(self, self.recordName, self.recordLength) def setTimeout(self, t): @@ -198,6 +199,7 @@ class PipeConnector(ivamApi.Connector): self.quit = 1 elif self.recording: self.recordFile.write(buf) + self.recordLength += len(buf) def writeStdout(self): diff --git a/clients/ivamVoiceBox.py b/clients/ivamVoiceBox.py index 252ce98..9dc84f9 100644 --- a/clients/ivamVoiceBox.py +++ b/clients/ivamVoiceBox.py @@ -216,7 +216,7 @@ class VoiceBox(ivamApi.Processor): self.currentState = self.STATE_FINISH c.hangup() - def onRecordFinish(self, c, fname): + def onRecordFinish(self, c, fname, length): if ivamCore.DEBUG: ivamCore.log("onRecordFinish(%s)" % fname) @@ -224,6 +224,9 @@ class VoiceBox(ivamApi.Processor): ivamCore.log("Sucessfully recorded new message '%s' from %s for MSN %s." % (fname, self.callerNumber, self.ringNumber)) os.environ["SPOOLDIR"] = self.directory + os.environ["LENGTH"] = `c.recordLength` + os.environ["SEC_LENGTH"] = "%0.1f" % (c.recordLength/8000.0) + ivamCore.log("Starting new message notification program.") r=os.spawnvp(os.P_WAIT, self.messageProgram, (self.messageProgram, fname)) ivamCore.log("Program finished (return value is %i)." % r) diff --git a/doc/TODO b/doc/TODO index 874d9fe..78fc329 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,9 +1,14 @@ * implement shbuf support * uid switching support -* make it a daemon * autoconf * documentation +* regexp support +* @same support +* uid switching for each client +* init script +* make it a daemon (DONE) +* newmessage script (DONE) * python part (DONE) * implement msntab.c (DONE) * dtmf fifo (DONE) diff --git a/src/Makefile b/src/Makefile index c689956..8dcb48e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,9 +1,14 @@ CC=gcc -CFLAGS=`pkg-config --cflags libdaemon shbuf liboop` -Wall -O0 -pipe -g -LIBS=`pkg-config --libs libdaemon shbuf liboop` -Wall -O0 -pipe -g +CFLAGS=`pkg-config --cflags libdaemon liboop` -Wall -O0 -pipe -g +LIBS=`pkg-config --libs libdaemon liboop` -Wall -O0 -pipe -g -ivamd: modem.o main.o modemman.o buffio.o exec.o dle.o lock.o util.o msntab.o timevalarith.o dtmffifo.o +ivamd: modem.o main.o modemman.o buffio.o exec.o dle.o lock.o util.o msntab.o timevalarith.o dtmffifo.o cmdline.o $(CC) $(LIBS) -o $@ $^ + +cmdline.c cmdline.h: ivamd.ggo + gengetopt < $< + clean: rm -f *.o ivamd + diff --git a/src/buffio.c b/src/buffio.c index 95e3dec..4771b1c 100644 --- a/src/buffio.c +++ b/src/buffio.c @@ -257,6 +257,7 @@ static void do_read(struct buffio *b) { m = b->input_max_length-i; s = read(b->ifd, b->input_buf+i, m); + buffio_set_readable(b, 0); //daemon_log(LOG_INFO, "%p: Read %u (%u) bytes.", b, s, m); if (s < 0) { @@ -284,8 +285,6 @@ static void do_read(struct buffio *b) { b->input_length += s; buffio_normalize(b); - buffio_set_readable(b, 0); - if (b->input_length) buffio_sched_cb(b, BUFFIO_SCHED_CB_INPUT_READY); } @@ -310,6 +309,8 @@ static void do_write(struct buffio *b) { m = b->output_max_length-b->output_index; s = write(b->ofd, b->output_buf+b->output_index, m); + buffio_set_writable(b, 0); + //daemon_log(LOG_INFO, "%p: Wrote %u (%u) bytes.", b, s, m); if (s < 0) { @@ -338,7 +339,6 @@ static void do_write(struct buffio *b) { b->output_length -= s; buffio_normalize(b); - buffio_set_writable(b, 0); buffio_delay(b, s); if (b->output_length < b->output_range) diff --git a/src/ivamd.ggo b/src/ivamd.ggo new file mode 100644 index 0000000..67e6f7e --- /dev/null +++ b/src/ivamd.ggo @@ -0,0 +1,29 @@ +# $Id$ + +# This file is part of ivamd. +# +# ivamd 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. +# +# ivamd 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 ivamd; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +purpose "ISDN Voice Box Answering Machine" +package "ivam" +version "0.1" + +option "kill" k "Kill a running daemon" flag off +option "no-daemon" n "Do not daemonize" flag off +option "no-syslog" s "Do not log to syslog" flag off +option "check" c "Check if the daemon is currently running" flag off +option "channels" C "Specify how many channels to allocate, defaults to 2" int default="2" no +option "msntab" T "Specify non standard msntab file" string no +option "listen" L "Specify a glob pattern matchin the MSNs to listen on" string no diff --git a/src/main.c b/src/main.c index 4f5a273..204fc69 100644 --- a/src/main.c +++ b/src/main.c @@ -1,17 +1,23 @@ #include #include +#include +#include + #include +#include +#include #include "main.h" #include "exec.h" #include "modemman.h" #include "msntab.h" - -#define CHANNELS 1 +#include "cmdline.h" oop_source* event_source = NULL; +struct gengetopt_args_info args; +const char *appname = NULL, *username = NULL; -#define MSNTABLE "../conf/msntab" +#define DEFAULT_MSNTABLE "../conf/msntab" static void *oop_exit_cb(oop_source *source, int sig, void *user) { daemon_log(LOG_ERR, "Recieved signal %s", sig == SIGINT ? "SIGINT" : (sig == SIGTERM ? "SIGTERM" : "UNKNWON")); @@ -22,7 +28,7 @@ static void *oop_reload_cb(oop_source *source, int sig, void *user) { daemon_log(LOG_ERR, "Reloading MSN table."); msntab_flush(); - if (msntab_load(MSNTABLE) < 0) { + if (msntab_load(args.msntab_arg ? args.msntab_arg : DEFAULT_MSNTABLE) < 0) { daemon_log(LOG_ERR, "Ignoring all calls."); msntab_flush(); } @@ -37,7 +43,7 @@ static void *oop_dump_cb(oop_source *source, int sig, void *user) { int main_loop(void) { - int r = -1; + int r = -1, retval_sent = 0; oop_source_sys *sys = NULL; daemon_log(LOG_INFO, "Starting up."); @@ -53,10 +59,10 @@ int main_loop(void) { if (child_process_init() < 0) goto finish; - if (msntab_load(MSNTABLE) < 0) + if (msntab_load(args.msntab_arg ? args.msntab_arg : DEFAULT_MSNTABLE) < 0) goto finish; - if (modem_manager_init(CHANNELS) < 0) + if (modem_manager_init(args.channels_arg) < 0) goto finish; event_source->on_signal(event_source, SIGINT, oop_exit_cb, NULL); @@ -65,6 +71,11 @@ int main_loop(void) { event_source->on_signal(event_source, SIGUSR1, oop_dump_cb, NULL); signal(SIGPIPE, SIG_IGN); + if (!args.no_daemon_flag) { + daemon_retval_send(0); + retval_sent = 1; + } + daemon_log(LOG_INFO, "Start up complete."); if (oop_sys_run(sys) == OOP_ERROR) { @@ -73,11 +84,14 @@ int main_loop(void) { } r = 0; - + finish: - + daemon_log(LOG_INFO, "Shutting down."); + if (!retval_sent && !args.no_daemon_flag) + daemon_retval_send(1); + event_source->cancel_signal(event_source, SIGTERM, oop_exit_cb, NULL); event_source->cancel_signal(event_source, SIGINT, oop_exit_cb, NULL); event_source->cancel_signal(event_source, SIGHUP, oop_reload_cb, NULL); @@ -99,5 +113,71 @@ finish: } int main(int argc, char*argv[]) { - return main_loop() < 0 ? 1 : 0; + pid_t pid; + int ret; + + appname = daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); + + cmdline_parser(argc, argv, &args); + + if (args.no_syslog_flag) + daemon_log_use = DAEMON_LOG_STDERR; + + if (args.kill_flag) { + int ret; + + if ((ret = daemon_pid_file_kill_wait(SIGINT, 5)) < 0) + daemon_log(LOG_WARNING, "Failed to kill daemon."); + + return ret < 0 ? 1 : 0; + } + + if (args.check_flag) { + if ((pid = daemon_pid_file_is_running()) >= 0) + daemon_log(LOG_INFO, "Daemon running on PID %u.", pid); + else + daemon_log(LOG_INFO, "Daemon not running."); + + return 1; + } + + if ((pid = daemon_pid_file_is_running()) >= 0) { + daemon_log(LOG_ERR, "Daemon already running on PID %u.", pid); + return 1; + } + + if (!args.no_daemon_flag) { + daemon_retval_init(); + + if ((pid = daemon_fork()) < 0) { + daemon_retval_done(); + return 1; + } else if (pid) { + int ret; + + if ((ret = daemon_retval_wait(20)) < 0) { + daemon_log(LOG_ERR, "Failed to recieve return value from daemon process."); + return 255; + } + + if (ret) + daemon_log(LOG_ERR, "Daemon returned %i as return value.", ret); + return ret; + } + } + + if (daemon_pid_file_create() < 0) { + daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); + + if (!args.no_daemon_flag) + daemon_retval_send(1); + + return 1; + } + + ret = main_loop() < 0 ? 1 : 0; + + daemon_pid_file_remove(); + return ret; } + diff --git a/src/main.h b/src/main.h index aa2f35a..c23d87d 100644 --- a/src/main.h +++ b/src/main.h @@ -3,8 +3,12 @@ #include +#include "cmdline.h" + extern oop_source* event_source; -const char *appname, *username; +extern const char *appname, *username; + +extern struct gengetopt_args_info args; #endif diff --git a/src/modem.c b/src/modem.c index ecc0019..3035969 100644 --- a/src/modem.c +++ b/src/modem.c @@ -132,7 +132,6 @@ struct modem *modem_open(const char *dev) { m->child_pid = -1; m->child_buffio = NULL; - m->listen_msn = "41264179"; // "46"; m->tabentry = NULL; if (modem_reopen(m) < 0) @@ -214,7 +213,9 @@ 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) { - snprintf(tmp, sizeof(tmp), p, m->listen_msn); + char *l = args.listen_arg ? args.listen_arg : "*"; + daemon_log(LOG_INFO, "Listening on '%s'.", l); + snprintf(tmp, sizeof(tmp), p, l); p = tmp; } @@ -449,8 +450,8 @@ static int modem_start_child(struct modem *m) { setenv("CALLERMSN", m->caller_number ? m->caller_number : "", 1); assert(m->dtmf_fifo->fname); setenv("DTMFFIFO", m->dtmf_fifo->fname, 1); - if (m->listen_msn) - setenv("LISTENMSN", m->listen_msn, 1); + if (args.listen_arg) + setenv("LISTENMSN", args.listen_arg, 1); else unsetenv("LISTENMSN"); @@ -552,7 +553,6 @@ static int modem_input_ready_cb(struct buffio *b, void *user) { m->command_index++; if (m->command_index >= INIT_AT_COMMANDS) { - daemon_log(LOG_INFO, "Listening on '%s'.", m->listen_msn); daemon_log(LOG_INFO, "Modem successfully initialised, waiting for calls."); m->state = MODEM_STATE_CALLER_NUMBER_EXPECT; modem_timeout(m, 0); diff --git a/src/modem.h b/src/modem.h index 8fed726..08e20b8 100644 --- a/src/modem.h +++ b/src/modem.h @@ -41,8 +41,6 @@ struct modem { struct timeval timeout; - char *listen_msn; - char *ring_number; char *caller_number; diff --git a/src/modemman.c b/src/modemman.c index cccaef9..ba3c3e2 100644 --- a/src/modemman.c +++ b/src/modemman.c @@ -40,8 +40,6 @@ int modem_manager_init(int channels) { assert(channels <= MAX_CHANNELS && channels > 0); assert(n_llist == 0); - modem_try_open("/dev/ttyz0"); - for (i = TTY_START; i < TTY_START+MAX_CHANNELS && n_llist < channels; i++) { char d[PATH_MAX]; snprintf(d, sizeof(d), "/dev/ttyI%i", i); -- cgit