diff --git a/.cvsignore b/.cvsignore index 3215751..57b375a 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,3 +1,4 @@ v21_softmodem test +amodemd *.o diff --git a/Makefile b/Makefile index 3b9e062..2cd42ce 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ LDFLAGS=-lm CFLAGS=-O2 -g -Wall -pedantic -Iinclude -SUBDIRS = lib modules +SUBDIRS = lib modules misc -MODULES = modules/modules.a lib/isdnlib.a +MODULES = modules/modules.a lib/isdnlib.a misc/misc.a -PROGRAMS = v21_softmodem test +PROGRAMS = v21_softmodem test amodemd all: subdirs $(PROGRAMS) @@ -18,6 +18,12 @@ v21_softmodem: v21_softmodem.o $(OBJECTS) $(MODULES) test: test.o $(OBJECTS) $(MODULES) $(CC) -o $@ $^ $(LDFLAGS) +amodemd: amodemd.o $(MODULES) + $(CC) -o $@ $^ $(LDFLAGS) + +misc/misc.a: misc/*.o + make -C misc + clean: rm -f $(OBJECTS) $(MODULES) $(PROGRAMS) *~ *.o for a in $(SUBDIRS) ; do make -C $$a clean; done diff --git a/amodemd.c b/amodemd.c new file mode 100644 index 0000000..15a50f0 --- /dev/null +++ b/amodemd.c @@ -0,0 +1,125 @@ +/* $Id$ +****************************************************************************** + + Fax program for ISDN. + Initial startup of daemon 'amodemd' - contains main() etc. + + Copyright (C) 1998 Morten Rolland [Morten.Rolland@asker.mail.telia.com] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + +/* This file holds the 'main()' function for the 'amodemd' daemon program + * that enables communication with analog modems and faxes without the + * use of a dedicated modem. This is made possible by collecting all the + * digital signal processing algorithms usually found in modems inside + * this daemon program. This daemon will as a result of this, consume + * significant resources when communication is commencing. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* Parse command-line arguments and bail out with an error message if + * something is wrong. + */ + +static void usage(void) +{ + fprintf(stderr,"Usage: %s [-d] [-c ]\n",progname); + exit(1); +} + +static void parse_arguments(int argc, char **argv) +{ + int t; + + if ( argc > 0 && argv[0] != 0 ) { + progname = rindex(argv[0],'/'); + if ( progname != 0 ) { + progname++; + } else { + progname = argv[0]; + } + } + + t = 1; + while ( t < argc ) { + + if ( !strcmp("-c",argv[t]) ) { + t++; + if ( t >= argc ) + usage(); + config_file = argv[t]; + t++; + } + + if ( !strcmp("-d",argv[t]) ) { + t++; + run_as_daemon = 1; + } + } +} + + +/* Startup point for 'amodemd' - parse args, initialize and off we go */ + +void main(int argc, char **argv) +{ + int t; + + parse_arguments(argc,argv); + read_configuration_file(); + + if ( run_as_daemon ) + start_daemon(); + + if ( watchdog_timeout > 0 ) { + initialize_watchdog_timer(); + reset_watchdog_timer(); + } + + /* Next up is: + * initialize_fax(); + * and later maybe: + * initialize_v34(); + * ... + */ + + initialize_realtime(); + + /* main_loop(); */ + + /* Waste some cycles to test watchdog timer.... */ + for ( t=0; t < 1000000000; t++ ) + ; + + check_stack_usage(); + + exit(0); +} diff --git a/doc/amodemd.conf b/doc/amodemd.conf new file mode 100644 index 0000000..6a49547 --- /dev/null +++ b/doc/amodemd.conf @@ -0,0 +1,56 @@ +# File: /etc/amodemd.conf +# +# Example of a configuration file for 'amodemd'. +# + + +# When the 'amodemd' starts as a daemon, it writes a pid-file to make it +# easy to kill the daemon off again at a later stage: + +pidfile = /var/run/amodemd.pid + + +# When 'amodemd' is used on top of ISDN supporting audio, the device has +# to be specified, the phone-number to use (MSN), etc.: + +isdn-device = /dev/ttyI5 # /dev/ttyI* are used for ISDN-audio +isdn-msn = 5551234 # Full number when using Euro-ISDN +country = 47 # Country of installation +international-prefix = 00 # Prefix to reach foreign destinations + + +# The daemon 'amodemd' performs a lot of timing critical digital signal +# processing. In order to get enough CPU-resources to avoid dropping +# a connection when the system load increases, the daemon installs +# itself as a "Real-Time" process. This way, it is guaranteed to get +# enough attention from the CPU. The realtime-priority option indicates +# which real-time level it should run at. Valid values are 0-99. +# When there are other real-time processes on the system, their +# individual priorities may have to be adjusted. A value of 0 disables +# real-time scheduling of 'amodemd', which is safer, but has a much +# higher chance of dropping a connection. +# +# If a real-time process goes wild, using all of the CPU, the system will +# be left completely unusable. Do not install a real-time daemon like +# 'amodemd' on a production system without being aware of the possibility +# of a system crash. +# +# In order to minimize the risk of having to reset a system as a result +# of a wild-running daemon, 'amodemd' features a watchdog timer that will +# kill itself off if there seems to be a problem. The watchdog timer +# period is in seconds, and is reset regularly when 'amodemd' thinks that +# it is behaving nicely. +# +# Please observe that the watchdog timer period must expire before it +# triggers, so leave the system alone for the timeout period (at least) +# before resetting or other dramatic action is taken (the system may +# recover by 'amodemd' committing suicide). + +realtime-priority = 1 # Valid values: 0 => off, 1-99 => real-time run-level +watchdog-timer = 60 # 60 seconds of hung system => abort 'amodemd' + +# If you try to run this daemon as a non-root user, it will not be able +# to fix its memory pages to always stay in main memory (no swapping), +# so the 'lock-memory' option must be used ( 0 => Don't lock, 1 => lock ): + +lock-memory = 0 diff --git a/include/ifax/misc/environment.h b/include/ifax/misc/environment.h new file mode 100644 index 0000000..fc448bb --- /dev/null +++ b/include/ifax/misc/environment.h @@ -0,0 +1,40 @@ +/* $Id$ +****************************************************************************** + + Fax program for ISDN. + Set up environment for a real-time daemon process like the 'amodemd' + + Copyright (C) 1999 Morten Rolland [Morten.Rolland@asker.mail.telia.com] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + +/* Sufficient space (in bytes) to hold the machine-stack with + * auto-variables, arguments and return addresses. Modify if + * more space is needed, or the current value is too large. + * However; it should never be smaller than the actual maximum + * stack-usage. One megabyte is probably generous. + */ +#define TOTAL_STACK_USAGE 1048576 +#define MINIMUM_FREE_STACK_SAFETY_MARGIN 20480 + +extern void initialize_realtime(void); +extern void start_daemon(void); +extern void check_stack_usage(void); diff --git a/include/ifax/misc/globals.h b/include/ifax/misc/globals.h new file mode 100644 index 0000000..e51c4b5 --- /dev/null +++ b/include/ifax/misc/globals.h @@ -0,0 +1,30 @@ +/* $Id$ +****************************************************************************** + + Fax program for ISDN. + Definition of common globals + + Copyright (C) 1999 Morten Rolland [Morten.Rolland@asker.mail.telia.com] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + +extern char *progname; /* Name of executable/program */ +extern int run_as_daemon; /* nonzero if running as daemon */ diff --git a/include/ifax/misc/readconfig.h b/include/ifax/misc/readconfig.h new file mode 100644 index 0000000..1f2a437 --- /dev/null +++ b/include/ifax/misc/readconfig.h @@ -0,0 +1,39 @@ +/* $Id$ +****************************************************************************** + + Fax program for ISDN. + Read the configuration file. + + Copyright (C) 1999 Morten Rolland [Morten.Rolland@asker.mail.telia.com] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + +extern char *config_file; +extern char *pid_file; +extern char *isdn_device; +extern char *isdn_msn; +extern char *home_country; +extern char *int_prefix; +extern int watchdog_timeout; +extern int realtime_priority; +extern int do_lock_memory; + +extern void read_configuration_file(void); diff --git a/include/ifax/misc/watchdog.h b/include/ifax/misc/watchdog.h new file mode 100644 index 0000000..854067d --- /dev/null +++ b/include/ifax/misc/watchdog.h @@ -0,0 +1,30 @@ +/* $Id$ +****************************************************************************** + + Fax program for ISDN. + Watchdog timer in case of misbehaving real-time process. + + Copyright (C) 1999 Morten Rolland [Morten.Rolland@asker.mail.telia.com] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + +extern void initialize_watchdog_timer(void); +extern void reset_watchdog_timer(void); diff --git a/misc/Makefile b/misc/Makefile new file mode 100644 index 0000000..dcb8b51 --- /dev/null +++ b/misc/Makefile @@ -0,0 +1,11 @@ +CFLAGS=-O2 -g -Wall -pedantic -I../include + +OBJECTS = globals.o readconfig.o watchdog.o environment.o + +all: misc.a + +misc.a: $(OBJECTS) + $(AR) rcs $@ $^ + +clean: + rm -f $(OBJECTS) misc.a *~ diff --git a/misc/environment.c b/misc/environment.c new file mode 100644 index 0000000..09d791b --- /dev/null +++ b/misc/environment.c @@ -0,0 +1,139 @@ +/* $Id$ +****************************************************************************** + + Fax program for ISDN. + Set up environment for a real-time daemon process like the 'amodemd' + + Copyright (C) 1999 Morten Rolland [Morten.Rolland@asker.mail.telia.com] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +char *bottom_unused_stack = 0; /* This part of the stack shouldn't be used */ +char *top_used_stack = 0; /* Top of stack, used a lot */ + +/* The following function puts this daemon into a mode of operation + * where it will get the CPU-power needed to carry out its task. + * This is needed since generating and interpreting the audio- + * signals must be carried out "live", and with no pauses. + * The remaining CPU-resources is available to other programs. + * + * This function should be called after all allocations have completed, + * and if possible, initialized (so all memory is mapped). + */ + +void initialize_realtime(void) +{ + char stack_initialization[TOTAL_STACK_USAGE]; + struct sched_param schedparams; + + /* In order to get predictable response-times, we lock this daemon and + * its data into RAM, and tell the OS to avoid paging. The assumed + * stack-usage is 1MB, which is probably way to much, but RAM is cheap. + * We have to initialize the stack-segment to make sure all pages + * making up the stack is mapped. + */ + + if ( do_lock_memory ) { + memset(stack_initialization,TOTAL_STACK_USAGE,0); + + if ( mlockall(MCL_CURRENT|MCL_FUTURE) != 0 ) { + fprintf(stderr,"Can't lock memory\n"); + exit(1); + } + + bottom_unused_stack = &stack_initialization[0]; + top_used_stack = &stack_initialization[TOTAL_STACK_USAGE-1]; + } + + /* Next up is requesting the full attention of the CPU. This + * basically means that our program will start to run when data + * is available, no matter how badly other standard programs wants + * to run. NOTE: This will work since this daemon waits for + * data regularly. During these waits, other processes are + * allowed to run, so the system can operate normally. + * However: If this daemon fails to wait, the entire system will + * become useless, since all other programs will be blocked. + * A watchdog timer is implemented to try avoid a hard reset. + */ + + if ( realtime_priority > 0 ) { + schedparams.sched_priority = realtime_priority; + if ( sched_setscheduler((pid_t)0,SCHED_FIFO,&schedparams) < 0 ) { + fprintf(stderr,"Couldn't enable real-time scheduling\n"); + exit(1); + } + } +} + + +/* When running as daemon, there are a few things we need to do. + * Most important is disconnecting the tty. + */ + +void start_daemon(void) +{ + pid_t child_pid; + + if ( (child_pid=fork()) < 0 ) { + fprintf(stderr,"%s: Unable to fork a daemon\n",progname); + exit(1); + } + + if ( child_pid ) + exit(0); + + setsid(); +} + +void check_stack_usage(void) +{ + char *p; + int unused_stack; + + if ( bottom_unused_stack == 0 ) + return; + + for ( p = bottom_unused_stack; p < top_used_stack; p++ ) + if ( *p != 0 ) + break; + + unused_stack = p - bottom_unused_stack; + + if ( unused_stack < MINIMUM_FREE_STACK_SAFETY_MARGIN ) { + fprintf(stderr,"%s: Internal error - only %d bytes of headroom on stack\n", + progname,unused_stack); + exit(1); + } + + fprintf(stderr,"%s: INFO - There is %d bytes of headroom on stack\n", + progname,unused_stack); +} diff --git a/misc/globals.c b/misc/globals.c new file mode 100644 index 0000000..07c6f63 --- /dev/null +++ b/misc/globals.c @@ -0,0 +1,30 @@ +/* $Id$ +****************************************************************************** + + Fax program for ISDN. + Common globals. + + Copyright (C) 1999 Morten Rolland [Morten.Rolland@asker.mail.telia.com] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + +char *progname = "amodemd"; +int run_as_daemon = 0; diff --git a/misc/readconfig.c b/misc/readconfig.c new file mode 100644 index 0000000..120ee00 --- /dev/null +++ b/misc/readconfig.c @@ -0,0 +1,294 @@ +/* $Id$ +****************************************************************************** + + Fax program for ISDN. + Read the configuration file. + + Copyright (C) 1999 Morten Rolland [Morten.Rolland@asker.mail.telia.com] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + +/* Open and read the configuration file, parse it, and set + * the relevnt variables accordingly. + */ + +#include +#include +#include +#include + +#include +#include + + +#ifndef DEFAULT_CONFIG_FILE +#define DEFAULT_CONFIG_FILE "/etc/amodemd.conf" +#endif + +#ifndef DEFAULT_PID_FILE +#define DEFAULT_PID_FILE "/var/run/amodemd.pid" +#endif + +#ifndef DEFAULT_ISDN_DEVICE +#define DEFAULT_ISDN_DEVICE "/dev/ttyI5" +#endif + +#ifndef DEFAULT_WATCHDOG_TIMEOUT +#define DEFAULT_WATCHDOG_TIMEOUT 0 +#endif + +#ifndef DEFAULT_REALTIME_PRIORITY +#define DEFAULT_REALTIME_PRIORITY 0 +#endif + +#ifndef DEFAULT_ISDN_MSN +#define DEFAULT_ISDN_MSN "5551234" +#endif + +#ifndef DEFAULT_COUNTRY +#define DEFAULT_COUNTRY "47" +#endif + +#ifndef DEFAULT_INT_PREFIX +#define DEFAULT_INT_PREFIX "00" +#endif + +char *config_file = DEFAULT_CONFIG_FILE; +char *pid_file = DEFAULT_PID_FILE; +char *isdn_device = DEFAULT_ISDN_DEVICE; +char *isdn_msn = DEFAULT_ISDN_MSN; +char *home_country = DEFAULT_COUNTRY; +char *int_prefix = DEFAULT_INT_PREFIX; +int watchdog_timeout = DEFAULT_WATCHDOG_TIMEOUT; +int realtime_priority = DEFAULT_REALTIME_PRIORITY; +int do_lock_memory = 1; + + +#define MAXCFGLINE 128 + +static int cmd_match(char *cmd, char **pp) +{ + char *c, *p; + + c = cmd; + p = *pp; + + while ( *c && *p ) { + if ( tolower(*c) != tolower(*p) ) + return 0; + c++, p++; + } + + if ( *c ) + return 0; + + *pp = p; + + return 1; +} + +static void skip_assignment(char **pp) +{ + char *p = *pp; + + while ( isspace(*p) ) + p++; + + if ( *p++ != '=' ) { + fprintf(stderr,"%s: Missing assigment operator in config file\n",progname); + exit(1); + } + + while ( isspace(*p) ) + p++; + + *pp = p; +} + +static int get_int(char **pp) +{ + int t; + char buffer[32]; + char *p = *pp; + + if ( !isdigit(*p) ) { + fprintf(stderr,"%s: Bad integer in config file\n",progname); + exit(1); + } + + for ( t=0; t < 30; t++ ) { + if ( !isdigit(*p) ) { + buffer[t] = 0; + *pp = p; + return atoi(buffer); + } + buffer[t] = *p++; + } + + fprintf(stderr,"%s: Integer too long in config file\n",progname); + exit(1); +} + +static char *get_string(char **pp) +{ + int length; + char *string; + char *p = *pp, *start, *stop; + + while ( isspace(*p) ) + p++; + + if ( *p == '"' ) { + start = p + 1; + stop = index(start,'"'); + if ( stop == 0 ) { + fprintf(stderr,"%s: Missing terminating \" in string in config file\n", + progname); + exit(1); + } + *pp = stop + 1; + } else { + start = p; + while ( !isspace(*p) ) + p++; + *pp = stop = p; + } + + length = stop - start; + string = malloc(length+1); + strncpy(string,start,length); + string[length] = 0; + + return string; +} + +static void end_line(char **pp) +{ + char *p = *pp; + + while ( isspace(*p) ) + p++; + if ( *p == '#' || *p == 0 ) + return; + + fprintf(stderr,"%s: Garbage at end of line in config file\n",progname); + exit(1); +} + +void read_configuration_file(void) +{ + FILE *cfg; + char *p; + char buffer[MAXCFGLINE+4]; + + if ( (cfg=fopen(config_file,"r")) == 0 ) { + fprintf(stderr,"%s: Unable to read config file '%s'\n", + progname,config_file); + exit(1); + } + + for (;;) { + + if ( fgets(buffer,MAXCFGLINE,cfg) == 0 ) + break; + + p = buffer; + + while ( isspace(*p) ) + p++; + + if ( *p == '#' ) + continue; + + if ( cmd_match("pidfile",&p) ) { + skip_assignment(&p); + pid_file = get_string(&p); + end_line(&p); + continue; + } + + if ( cmd_match("isdn-device",&p) ) { + skip_assignment(&p); + isdn_device = get_string(&p); + end_line(&p); + continue; + } + + if ( cmd_match("isdn-msn",&p) ) { + skip_assignment(&p); + isdn_msn = get_string(&p); + end_line(&p); + continue; + } + + if ( cmd_match("country",&p) ) { + skip_assignment(&p); + home_country = get_string(&p); + end_line(&p); + continue; + } + + if ( cmd_match("international-prefix",&p) ) { + skip_assignment(&p); + int_prefix = get_string(&p); + end_line(&p); + continue; + } + + if ( cmd_match("watchdog-timer",&p) ) { + skip_assignment(&p); + watchdog_timeout = get_int(&p); + end_line(&p); + if ( watchdog_timeout < 0 ) { + fprintf(stderr,"%s: Watchdog timer must be positive or zero\n", + progname); + exit(1); + } + continue; + } + + if ( cmd_match("realtime-priority",&p) ) { + skip_assignment(&p); + realtime_priority = get_int(&p); + end_line(&p); + if ( realtime_priority < 0 || realtime_priority > 99 ) { + fprintf(stderr,"%s: Real-Time priority must be in range 0-99\n", + progname); + exit(1); + } + continue; + } + + if ( cmd_match("lock-memory",&p) ) { + skip_assignment(&p); + do_lock_memory = get_int(&p); + end_line(&p); + if ( do_lock_memory < 0 || do_lock_memory > 1 ) { + fprintf(stderr,"%s: 'lock-memory' must be 0 or 1 in config file\n", + progname); + exit(1); + } + continue; + } + } + + fclose(cfg); +} diff --git a/misc/watchdog.c b/misc/watchdog.c new file mode 100644 index 0000000..ce8730e --- /dev/null +++ b/misc/watchdog.c @@ -0,0 +1,67 @@ +/* $Id$ +****************************************************************************** + + Fax program for ISDN. + Watchdog timer in case of misbehaving real-time process. + + Copyright (C) 1999 Morten Rolland [Morten.Rolland@asker.mail.telia.com] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + + +#include +#include +#include +#include + +#include +#include +#include + + +static struct itimerval timer; + + +static void watchdog_trigger(int signum) +{ + fprintf(stderr,"\n\n%s: Watchdog timer triggered a termination\n",progname); + exit(17); +} + +void initialize_watchdog_timer(void) +{ + if ( signal(SIGPROF,watchdog_trigger) == SIG_ERR ) { + fprintf(stderr,"%s: Can't install watchdog signal handeler\n",progname); + exit(1); + } +} + +void reset_watchdog_timer(void) +{ + timer.it_value.tv_sec = watchdog_timeout; + timer.it_value.tv_usec = 0; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = 0; + if ( setitimer(ITIMER_PROF, &timer, (struct itimerval *)0) < 0 ) { + fprintf(stderr,"%s: Can't install watchdog timer\n",progname); + exit(1); + } +}