diff options
Diffstat (limited to 'core/isdn4k-utils/isdn4k-utils-3.2p1-build.patch')
-rw-r--r-- | core/isdn4k-utils/isdn4k-utils-3.2p1-build.patch | 2028 |
1 files changed, 2028 insertions, 0 deletions
diff --git a/core/isdn4k-utils/isdn4k-utils-3.2p1-build.patch b/core/isdn4k-utils/isdn4k-utils-3.2p1-build.patch new file mode 100644 index 000000000..63239fcad --- /dev/null +++ b/core/isdn4k-utils/isdn4k-utils-3.2p1-build.patch @@ -0,0 +1,2028 @@ +diff -Naur isdn4k-utils-orig//eicon/eiconctrl.c isdn4k-utils/eicon/eiconctrl.c +--- isdn4k-utils-orig//eicon/eiconctrl.c 2001-06-22 02:34:45.000000000 +1000 ++++ isdn4k-utils/eicon/eiconctrl.c 2010-12-04 20:44:11.093338893 +1000 +@@ -1970,7 +1970,7 @@ + val = strtol(p, &q, 16); + p = q; + val = strtol(p, &q, 16); +- (unsigned short) *buffer = (unsigned short) val; ++ *buffer = (unsigned short) val; + pos = 2; + while ((p != q) && (*q != 0)) { + p = q; +diff -Naur isdn4k-utils-orig//hisax/hisaxctrl.c isdn4k-utils/hisax/hisaxctrl.c +--- isdn4k-utils-orig//hisax/hisaxctrl.c 2000-06-30 19:37:38.000000000 +1000 ++++ isdn4k-utils/hisax/hisaxctrl.c 2010-12-04 20:44:11.093338893 +1000 +@@ -43,7 +43,8 @@ + fprintf(stderr, "cannot open file %s\n", fname); + exit(-1); + } +- p = (int *) buffer = (unsigned char *) malloc(MAX_SIZE+4); ++ buffer = (unsigned char *) malloc(MAX_SIZE+4); ++ p = (int *) buffer; + if (!buffer) { + fprintf(stderr, "cannot get %d byte memory\n", MAX_SIZE+4); + exit(-1); +diff -Naur isdn4k-utils-orig//hisax/Makefile.in isdn4k-utils/hisax/Makefile.in +--- isdn4k-utils-orig//hisax/Makefile.in 2002-07-20 05:03:51.000000000 +1000 ++++ isdn4k-utils/hisax/Makefile.in 2010-12-04 20:44:03.726672225 +1000 +@@ -30,7 +30,7 @@ + #.SUFFIXES: + #.SUFFIXES: .c .o + +-%.8: %.man ++%.8: %.man.in + cp $< $@ + + all: $(PROGRAMS) $(MANPAGES) +diff -Naur isdn4k-utils-orig//ipppd/main.c isdn4k-utils/ipppd/main.c +--- isdn4k-utils-orig//ipppd/main.c 2002-07-18 10:06:21.000000000 +1000 ++++ isdn4k-utils/ipppd/main.c 2010-12-04 20:44:11.093338893 +1000 +@@ -1041,9 +1041,14 @@ + static char line[256]; /* line to be logged accumulated here */ + static char *linep; + ++#ifdef __STDC__ ++static void pr_log(void *arg, char *fmt, ...); ++#else /* __STDC__ */ ++static void pr_log(arg, fmt, va_alist); ++#endif ++ + void log_packet(u_char *p,int len,char *prefix,int linkunit) + { +- static void pr_log __P((void *, char *, ...)); + + int i, n; + u_short proto; +diff -Naur isdn4k-utils-orig//ipppd/options.c isdn4k-utils/ipppd/options.c +--- isdn4k-utils-orig//ipppd/options.c 2002-07-06 10:34:08.000000000 +1000 ++++ isdn4k-utils/ipppd/options.c 2010-12-04 20:43:57.890005560 +1000 +@@ -479,26 +479,24 @@ + #define IMPLEMENTATION "" + #endif + +-static char *usage_string = "\ +-ipppd version %s patch level %d%s\n\ +-Usage: %s [ options ], where options are:\n\ +-\t<device> Communicate over the named device\n\ ++static char *usage_string = "ipppd version %s patch level %d%s\n" ++"Usage: %s [ options ], where options are:\n" ++"\t<device> Communicate over the named device\n" + #ifdef INCLUDE_OBSOLETE_FEATURES +-\tcrtscts Use hardware RTS/CTS flow control\n\ +-\t<speed> Set the baud rate to <speed>\n\ +-\tmodem Use modem control lines\n\ ++"\tcrtscts Use hardware RTS/CTS flow control\n" ++"\t<speed> Set the baud rate to <speed>\n" ++"\tmodem Use modem control lines\n" + #endif +-\t<loc>:<rem> Set the local and/or remote interface IP\n\ +-\t\taddresses. (you also may use the option 'useifip' to get IPs).\n\ +-\tasyncmap <n> Set the desired async map to hex <n>\n\ +-\tauth Require authentication from peer\n\ +-\tconnect <p> Invoke shell command <p> to set up the serial line\n\ +-\tdefaultroute Add default route through interface\n\ +-\tfile <f> Take options from file <f>\n\ +-\tmru <n> Set MRU value to <n> for negotiation\n\ +-\tnetmask <n> Set interface netmask to <n>\n\ +-See ipppd(8) for more options.\n\ +-"; ++"\t<loc>:<rem> Set the local and/or remote interface IP\n" ++"\t\t\taddresses. (you also may use the option 'useifip' to get IPs).\n" ++"\tasyncmap <n> Set the desired async map to hex <n>\n" ++"\tauth Require authentication from peer\n" ++"\tconnect <p> Invoke shell command <p> to set up the serial line\n" ++"\tdefaultroute Add default route through interface\n" ++"\tfile <f> Take options from file <f>\n" ++"\tmru <n> Set MRU value to <n> for negotiation\n" ++"\tnetmask <n> Set interface netmask to <n>\n" ++"See ipppd(8) for more options.\n"; + + static char *current_option; /* the name of the option being parsed */ + +diff -Naur isdn4k-utils-orig//isdnlog/isdnlog/isdnlog.h isdn4k-utils/isdnlog/isdnlog/isdnlog.h +--- isdn4k-utils-orig//isdnlog/isdnlog/isdnlog.h 2001-06-22 02:34:56.000000000 +1000 ++++ isdn4k-utils/isdnlog/isdnlog/isdnlog.h 2010-12-04 20:44:03.780005559 +1000 +@@ -460,7 +460,7 @@ + + _EXTERN void dotrace(void); + _EXTERN int morectrl(int card); +-_EXTERN void moreinfo(void); ++extern void moreinfo(void); + _EXTERN void morekbd(void); + _EXTERN void processcint(void); + _EXTERN void processflow(void); +diff -Naur isdn4k-utils-orig//isdnlog/isdnlog/processor.c isdn4k-utils/isdnlog/isdnlog/processor.c +--- isdn4k-utils-orig//isdnlog/isdnlog/processor.c 2002-04-02 04:06:10.000000000 +1000 ++++ isdn4k-utils/isdnlog/isdnlog/processor.c 2010-12-04 20:44:03.783338893 +1000 +@@ -5293,7 +5293,7 @@ + tei = BROADCAST; /* Wenn nach einer tei-Zeile keine hex:-Zeile kommt, tei ungueltig machen! */ + + if ((type == SETUP) && !replay) { /* fetch additional info from "/dev/isdninfo" */ +- static void moreinfo(); /* soviel zu Objektorientiertem Denken ;-) */ ++ /*static void moreinfo(); */ /* soviel zu Objektorientiertem Denken ;-) */ + moreinfo(); + } /* if */ + +diff -Naur isdn4k-utils-orig//isdnlog/Makefile.in isdn4k-utils/isdnlog/Makefile.in +--- isdn4k-utils-orig//isdnlog/Makefile.in 2002-07-20 05:03:55.000000000 +1000 ++++ isdn4k-utils/isdnlog/Makefile.in 2010-12-04 20:44:03.730005560 +1000 +@@ -1842,9 +1842,6 @@ + $(INSTALL_DATA) $$f $(DESTDIR)$(DATADIR); \ + echo Installing $(DESTDIR)$(DATADIR)/$$f; \ + done +- @(grep isdnlog $(SERVICEFILE) >/dev/null) || \ +- (echo "";echo "";echo "Add a line to the file $(SERVICEFILE)" ;echo "";echo ""; \ +- echo "isdnlog $(SERV_PORT)/tcp isdnlog" >> $(SERVICEFILE)) + + install-strip: + $(MAKE) INSTALL_BIN='$(INSTALL_BIN) -s' \ +diff -Naur isdn4k-utils-orig//isdnlog/tools/cdb/cdbmake.c isdn4k-utils/isdnlog/tools/cdb/cdbmake.c +--- isdn4k-utils-orig//isdnlog/tools/cdb/cdbmake.c 2002-02-22 21:10:25.000000000 +1000 ++++ isdn4k-utils/isdnlog/tools/cdb/cdbmake.c 2010-12-04 20:44:03.786672226 +1000 +@@ -3,8 +3,6 @@ + #include "freecdbmake.h" + #include <unistd.h> + +-extern char *malloc(); +- + void diesys(why) char *why; { perror(why); exit(111); } + + void writeerror() { diesys("cdbmake: fatal: unable to write"); } +diff -Naur isdn4k-utils-orig//isdnlog/tools/isdnrate.c isdn4k-utils/isdnlog/tools/isdnrate.c +--- isdn4k-utils-orig//isdnlog/tools/isdnrate.c 2001-06-22 02:34:56.000000000 +1000 ++++ isdn4k-utils/isdnlog/tools/isdnrate.c 2010-12-04 20:44:11.096672226 +1000 +@@ -304,7 +304,7 @@ + + static void print_header(void); + +-static char *myname, *myshortname; ++char *myname, *myshortname; + static char options[] = "ab:d:f:h:l:op:st:v::x:CD::G:HLNP:O:S:TUVX::Z"; + static char usage[] = "%s: usage: %s [ -%s ] Destination ...\n"; + +@@ -313,7 +313,7 @@ + static int usestat = 0; + static int duration = LCR_DURATION; + static time_t start; +-static int day, month, year, hour, min, sec; ++int day, month, year, hour, min, sec; + static char ignore[MAXPROVIDER]; + static char *fromarea = 0; + static char wanted_day; +diff -Naur isdn4k-utils-orig//isdnlog/tools/isdnrate.c.orig isdn4k-utils/isdnlog/tools/isdnrate.c.orig +--- isdn4k-utils-orig//isdnlog/tools/isdnrate.c.orig 1970-01-01 10:00:00.000000000 +1000 ++++ isdn4k-utils/isdnlog/tools/isdnrate.c.orig 2001-06-22 02:34:56.000000000 +1000 +@@ -0,0 +1,1806 @@ ++/* $Id: isdnrate.c,v 1.38 2001/03/01 14:59:16 paul Exp $ ++ ++ * ISDN accounting for isdn4linux. (rate evaluation) ++ * ++ * Copyright 1995 .. 2000 by Andreas Kool (akool@isdn4linux.de) ++ * ++ * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * $Log: isdnrate.c,v $ ++ * Revision 1.38 2001/03/01 14:59:16 paul ++ * Various patches to fix errors when using the newest glibc, ++ * replaced use of insecure tempnam() function ++ * and to remove warnings etc. ++ * ++ * Revision 1.37 2000/07/17 16:34:23 akool ++ * isdnlog-4.32 ++ * - added new Prefixes 0160 (D1) and 0162 (D2) to "country-de.dat" ++ * - corrected all german mobil phone numbers (many thank's to ++ * Tobias Becker <i4l-projects@talypso.de> for the tool "fix_rates.pl") ++ * - isdnlog/tools/rate.c ... New R:-tag ++ * - isdnlog/tools/isdnrate.c ... print warnings from getRate if verbose ++ * - isdnlog/tools/rate-files.man ... New R:-tag ++ * - isdnlog/tools/NEWS ... New R:-tag ++ * - isdnlog/README ... New R:-tag ++ * - isdnlog/samples/rtest.dat ... example rate-file for testing R: ++ * ++ * Revision 1.36 2000/03/09 18:50:03 akool ++ * isdnlog-4.16 ++ * - isdnlog/samples/isdn.conf.no ... changed VBN ++ * - isdnlog/isdnlog/isdnlog.c .. ciInterval ++ * - isdnlog/isdnlog/processor.c .. ciInterval ++ * - isdnlog/tools/tools.h .. ciInterval, abclcr conf option ++ * - isdnlog/tools/isdnconf.c .. ciInterval, abclcr conf option ++ * - isdnlog/tools/isdnrate.c .. removed a warning ++ * - isdnlog/NEWS ... updated ++ * - isdnlog/README ... updated ++ * - isdnlog/isdnlog/isdnlog.8.in ... updated ++ * - isdnlog/isdnlog/isdnlog.5.in ... updated ++ * - isdnlog/samples/provider ... NEW ++ * ++ * ==> Please run a make clean, and be sure to read isdnlog/NEWS for changes ++ * ==> and new features. ++ * ++ * Revision 1.35 2000/03/06 07:03:21 akool ++ * isdnlog-4.15 ++ * - isdnlog/tools/tools.h ... moved one_call, sum_calls to isdnrep.h ++ * ==> DO A 'make clean' PLEASE ++ * - isdnlog/tools/telnum.c ... fixed a small typo ++ * - isdnlog/isdnrep/rep_main.c ... incl. dest.h ++ * - isdnlog/isdnrep/isdnrep.c ... fixed %l, %L ++ * - isdnlog/isdnrep/isdnrep.h ... struct one_call, sum_calls are now here ++ * ++ * Support for Norway added. Many thanks to Tore Ferner <torfer@pvv.org> ++ * - isdnlog/rate-no.dat ... NEW ++ * - isdnlog/holiday-no.dat ... NEW ++ * - isdnlog/samples/isdn.conf.no ... NEW ++ * - isdnlog/samples/rate.conf.no ... NEW ++ * ++ * Revision 1.34 2000/02/28 19:53:56 akool ++ * isdnlog-4.14 ++ * - Patch from Roland Rosenfeld <roland@spinnaker.de> fix for isdnrep ++ * - isdnlog/tools/rate.c ... epnum ++ * - isdnlog/tools/rate-at.c ... new rates ++ * - isdnlog/rate-at.dat ++ * - isdnlog/tools/rate-files.man ... %.3f ++ * - doc/Configure.help ... unknown cc ++ * - isdnlog/configure.in ... unknown cc ++ * - isdnlog/.Config.in ... unknown cc ++ * - isdnlog/Makefile.in ... unknown cc ++ * - isdnlog/tools/dest/Makefile.in ... LANG => DEST_LANG ++ * - isdnlog/samples/rate.conf.pl ... NEW ++ * - isdnlog/samples/isdn.conf.pl ... NEW ++ * - isdnlog/rate-pl.dat ... NEW ++ * - isdnlog/tools/isdnrate.c ... fixed -P pid_dir, restarts on HUP now ++ * - isdnlog/tools/isdnrate.man ... SIGHUP documented ++ * ++ * Revision 1.33 2000/02/12 16:40:24 akool ++ * isdnlog-4.11 ++ * - isdnlog/Makefile.in ... sep install-targets, installs samples, no isdnconf ++ * - isdnlog/samples/rate.conf.{lu,nl} ... NEW ++ * - isdnlog/samples/isdn.conf.lu ... chg provider ++ * - isdnlog/samples/stop ... chg \d,\d => \d.\d ++ * - isdnlog/samples/isdnlog.isdnctrl0.options ... NEW ++ * - isdnlog/samples/isdnlog.users ... NEW ++ * - isdnlog/country-de.dat ... _DEMF again ++ * - isdnlog/isdnlog/processor.c ... LCR ++ * - isdnlog/tools/isdnrate.c ... fmt of s ++ * ++ * Old config is not installed anymore, to acomplish this do ++ * ++ * make install-old-conf ++ * make install ++ * ++ * A running isdnlog is now HUP-ed not KILL-ed ++ * ++ * Revision 1.32 2000/02/03 18:24:51 akool ++ * isdnlog-4.08 ++ * isdnlog/tools/rate.c ... LCR patch again ++ * isdnlog/tools/isdnrate.c ... LCR patch again ++ * isdnbill enhanced/fixed ++ * DTAG AktivPlus fixed ++ * ++ * Revision 1.31 1999/12/31 13:57:20 akool ++ * isdnlog-4.00 (Millenium-Edition) ++ * - Oracle support added by Jan Bolt (Jan.Bolt@t-online.de) ++ * - resolved *any* warnings against rate-de.dat ++ * - Many new rates ++ * - CREDITS file added ++ * ++ * Revision 1.30 1999/12/24 14:17:05 akool ++ * isdnlog-3.81 ++ * - isdnlog/tools/NEWS ++ * - isdnlog/tools/telrate/info.html.in ... bugfix ++ * - isdnlog/tools/telrate/telrate.cgi.in ... new Service query ++ * - isdnlog/tools/telrate/Makefile.in ... moved tmp below telrate ++ * - isdnlog/samples/rate.conf.at ... fixed ++ * - isdnlog/tools/rate-at.c ... some changes ++ * - isdnlog/rate-at.dat ... ditto ++ * - isdnlog/tools/Makefile ... added path to pp_rate ++ * - isdnlog/tools/rate.{c,h} ... getServiceNames, Date-Range in T:-Tag ++ * - isdnlog/tools/isdnrate.c ... fixed sorting of services, -X52 rets service names ++ * - isdnlog/tools/rate-files.man ... Date-Range in T:-Tag, moved from doc ++ * - isdnlog/tools/isdnrate.man ... moved from doc ++ * - doc/Makefile.in ... moved man's from doc to tools ++ * - isdnlog/Makefile.in ... man's, install isdn.conf.5 ++ * - isdnlog/configure{,.in} ... sed, awk for man's ++ * - isdnlog/tools/zone/Makefile.in ... dataclean ++ * - isdnlog/tools/dest/Makefile.in ... dataclean ++ * - isdnlog/isdnlog/isdnlog.8.in ... upd ++ * - isdnlog/isdnlog/isdn.conf.5.in ... upd ++ * ++ * Revision 1.29 1999/12/17 22:51:55 akool ++ * isdnlog-3.79 ++ * - isdnlog/isdnrep/isdnrep.{c,h} ... error -handling, print_msg ++ * - isdnlog/isdnrep/rep_main.c ++ * - isdnlog/isdnrep/isdnrep.1.in ++ * - isdnlog/tools/rate.c ... dupl entry in rate.conf ++ * - isdnlog/tools/NEWS ++ * - isdnlog/tools/isdnrate.c ++ * - isdnlog/tools/dest/configure{,.in} ++ * - isdnlog/tools/zone/configure{,.in} ++ * ++ * Revision 1.28 1999/12/16 23:08:28 akool ++ * isdnlog-3.78 ++ * - isdnlog/tools/isdnrate.c ... new sOcket option ++ * - isdnlog/tools/NEWS ... new sOcket option ++ * - doc/isdnrate.man ... ditto ++ * - isdnlog/tools/telrate/config.in ... ditto ++ * - isdnlog/tools/telrate/telrate.cgi.in ... ditto ++ * - isdnlog/tools/telrate/README-telrate ditto ++ * ++ * Revision 1.27 1999/12/02 19:28:02 akool ++ * isdnlog-3.73 ++ * - isdnlog/tools/telrate/telrate.cgi.in faster ++ * - doc/isdnrate.man ... -P ++ * - isdnlog/tools/isdnrate.c ... -P ++ * - isdnlog/tools/NEWS ... -P ++ * - isdnlog/tools/rate-at.c ... 194040 ++ * - isdnlog/rate-at.dat ++ * - isdnlog/tools/rate.c ... SIGSEGV ++ * ++ * Revision 1.26 1999/12/01 21:47:25 akool ++ * isdnlog-3.72 ++ * - new rates for 01051 ++ * - next version of isdnbill ++ * ++ * - isdnlog/tools/telnum.c ... cleanup ++ * - isdnlog/tools/isdnrate.c ... -s Service ++ * - isdnlog/tools/rate.{c,h} ... -s ++ * - isdnlog/tools/NEWS ... -s ++ * - doc/isdnrate.man .. updated -o, -s ++ * - doc/rate-files.man ... updated ++ * - isdnlog/tools/dest/README.makedest ... updt. ++ * - isdnlog/isdnlog/isdnlog.8.in .. updt. ++ * ++ * Telrate ++ * - isdnlog/tools/telrate/README-telrate ++ * - isdnlog/tools/telrate/config.in NEW ++ * - isdnlog/tools/telrate/configure NEW ++ * - isdnlog/tools/telrate/Makefile.in NEW ++ * - isdnlog/tools/telrate/index.html.in was index.html ++ * - isdnlog/tools/telrate/info.html.in was info.html ++ * - isdnlog/tools/telrate/telrate.cgi.in was telrate.cgi ++ * - isdnlog/tools/telrate/leo.sample NEW sample config ++ * - isdnlog/tools/telrate/alex.sample NEW sample config ++ * ++ * Revision 1.25 1999/11/08 21:09:41 akool ++ * isdnlog-3.65 ++ * - added "B:" Tag to "rate-xx.dat" ++ * ++ * Revision 1.24 1999/11/07 13:29:28 akool ++ * isdnlog-3.64 ++ * - new "Sonderrufnummern" handling ++ * ++ * Revision 1.22 1999/10/26 18:17:14 akool ++ * isdnlog-3.62 ++ * - many new rates ++ * - next try to fix "Sonderrufnummern" ++ * ++ * isdnlog-3.58 ++ * - big cleanup ( > 1.3 Mb removed!) ++ * - v0.02 of destination support - better, but not perfect ++ * (does't work with gcc-2.7.2.3 yet - use egcs!) ++ * ++ * Revision 1.21 1999/10/25 18:30:03 akool ++ * isdnlog-3.57 ++ * WARNING: Experimental version! ++ * Please use isdnlog-3.56 for production systems! ++ * ++ * Revision 1.20 1999/09/19 14:16:27 akool ++ * isdnlog-3.53 ++ * ++ * Revision 1.19 1999/09/16 20:27:21 akool ++ * isdnlog-3.52 ++ * ++ * Revision 1.18 1999/09/13 09:09:44 akool ++ * isdnlog-3.51 ++ * - changed getProvider() to not return NULL on unknown providers ++ * many thanks to Matthias Eder <mateder@netway.at> ++ * - corrected zone-processing when doing a internal -> world call ++ * ++ * Revision 1.17 1999/09/09 11:21:05 akool ++ * isdnlog-3.49 ++ * ++ * Revision 1.16 1999/08/04 23:06:52 akool ++ * Better codeall for .at ++ * ++ * Revision 1.15 1999/07/31 09:25:36 akool ++ * getRate() speedup ++ * ++ * Revision 1.14 1999/07/26 16:28:41 akool ++ * getRate() speedup from Leo ++ * ++ * Revision 1.13 1999/07/25 15:57:46 akool ++ * isdnlog-3.43 ++ * added "telnum" module ++ * ++ * Revision 1.12 1999/07/24 08:45:17 akool ++ * isdnlog-3.42 ++ * rate-de.dat 1.02-Germany [18-Jul-1999 10:44:21] ++ * better Support for Ackermann Euracom ++ * WEB-Interface for isdnrate ++ * many small fixes ++ * ++ * Revision 1.11 1999/07/15 16:42:04 akool ++ * small enhancement's and fixes ++ * ++ * Revision 1.10 1999/07/07 19:44:07 akool ++ * patches from Michael and Leo ++ * ++ * Revision 1.9 1999/07/04 20:47:05 akool ++ * rate-de.dat V:1.02-Germany [04-Jul-1999 22:56:37] ++ * ++ * Revision 1.8 1999/07/03 10:24:14 akool ++ * fixed Makefile ++ * ++ * Revision 1.7 1999/07/02 19:18:00 akool ++ * rate-de.dat V:1.02-Germany [02-Jul-1999 21:27:20] ++ * ++ * Revision 1.6 1999/07/02 18:20:50 akool ++ * rate-de.dat V:1.02-Germany [02-Jul-1999 20:29:21] ++ * country-de.dat V:1.02-Germany [02-Jul-1999 19:13:54] ++ * ++ * Revision 1.5 1999/07/01 20:40:07 akool ++ * isdnrate optimized ++ * ++ * Revision 1.4 1999/06/30 20:53:28 akool ++ * added "-t" option to "isdnrate" ++ * ++ * Revision 1.3 1999/06/30 17:17:37 akool ++ * isdnlog Version 3.39 ++ * ++ * Revision 1.2 1999/06/29 20:11:25 akool ++ * now compiles with ndbm ++ * (many thanks to Nima <nima_ghasseminejad@public.uni-hamburg.de>) ++ * ++ * Revision 1.1 1999/06/28 19:16:33 akool ++ * isdnlog Version 3.38 ++ * - new utility "isdnrate" started ++ * ++ */ ++ ++#include "isdnlog.h" ++#include "tools/zone.h" ++#include <unistd.h> ++#include "dest.h" ++ ++#define WIDTH 19 ++#define _MAXLAST 20 /* the real max */ ++#define MAXLAST ((best>=_MAXLAST||best<=2)?5:best) ++ ++ ++static void print_header(void); ++ ++static char *myname, *myshortname; ++static char options[] = "ab:d:f:h:l:op:st:v::x:CD::G:HLNP:O:S:TUVX::Z"; ++static char usage[] = "%s: usage: %s [ -%s ] Destination ...\n"; ++ ++static int header = 0, best = MAXPROVIDER, table = 0, explain = 0; ++int verbose = 0; ++static int usestat = 0; ++static int duration = LCR_DURATION; ++static time_t start; ++static int day, month, year, hour, min, sec; ++static char ignore[MAXPROVIDER]; ++static char *fromarea = 0; ++static char wanted_day; ++static int list = 0; ++static char *comment; ++static char **providers = 0; /* incl these */ ++static int n_providers = 0; ++static int business = 0; ++static char **xproviders = 0; /* excl these */ ++static int nx_providers = 0; ++static int xbusiness = 0; ++static int all = 0; ++static int booked = 0; ++static int service = 0; ++ ++#define SOCKNAME "/tmp/isdnrate" ++static int is_daemon = 0; ++static int is_client = 0; ++static int we_are_daemon = 0; ++static int takt = 99999; ++static char sortby; ++static int need_dest; ++static int h_param = 0; ++static int lcr = 0; ++static TELNUM srcnum, destnum; ++static char *pid_dir = 0; ++static char *pid_file = 0; ++static char *socket_file = 0; ++static char **hup_argv; /* args to restart with */ ++ ++typedef struct { ++ int prefix; ++ double rate; ++ char *name; ++ char *explain; ++} SORT; ++ ++typedef struct { ++ int weight; ++ int index; ++} SORT2; ++ ++static SORT sort[MAXPROVIDER]; ++ ++#undef MAXPROVIDER ++#define MAXPROVIDER getNProvider() ++ ++#undef BUFSIZ /* sorry but 8192 is too much for me */ ++#define BUFSIZ 256 ++ ++int print_msg(int Level, const char *fmt,...) ++{ ++ auto va_list ap; ++ auto char String[BUFSIZ * 3]; ++ ++ if ((Level > PRT_ERR && !verbose) || (Level > PRT_WARN && verbose < 2)) ++ return (1); ++ ++ va_start(ap, fmt); ++ (void) vsnprintf(String, BUFSIZ * 3, fmt, ap); ++ va_end(ap); ++ ++ fprintf(stderr, "%s", String); ++ ++ return (0); ++} /* print_msg */ ++ ++ ++static void init() ++{ ++ auto char *version, **message; ++ ++ if (readconfig(myshortname) < 0) ++ exit(1); ++ ++ if (verbose) ++ message = &version; ++ else ++ message = NULL; ++ ++ initHoliday(holifile, message); ++ ++ if (verbose && *version) ++ print_msg(PRT_V, "%s\n", version); ++ initDest(destfile, message); ++ if (verbose && *version) ++ print_msg(PRT_V, "%s\n", version); ++ ++ initRate(rateconf, ratefile, zonefile, message); ++ ++ if (verbose && *version) ++ print_msg(PRT_V, "%s\n", version); ++ ++} /* init */ ++ ++#if 0 ++static void deinit(void) ++{ ++ exitRate(); ++ exitDest(); ++ exitHoliday(); ++} ++#endif ++ ++/* calc a day/time W | E | H */ ++static void get_day(char d) ++{ ++ struct tm *tm; ++ bitfield mask; ++ int what = 0; ++ ++ tm = localtime(&start); /* now */ ++ switch (d) { ++ case 'W': /* we need a normal weekday, so we take ++ today and inc. day if today is ++ holiday */ ++ what = WORKDAY; ++ if (!h_param) ++ hour = 10; ++ break; ++ case 'N': ++ what = WORKDAY; ++ if (!h_param) ++ hour = 23; ++ break; ++ case 'E': ++ what = SUNDAY; ++ if (!h_param) ++ hour = 10; ++ break; ++ } ++ mask = 1 << what; ++ while (isDay(tm, mask, 0) != what) { ++ tm->tm_mday++; ++ } ++ min = sec = 0; ++ day = tm->tm_mday; ++ month = tm->tm_mon + 1; ++ year = tm->tm_year + 1900; ++} ++ ++static void post_init() ++{ ++ ++ clearNum(&srcnum); ++ if (fromarea) { ++ Strncpy(srcnum.area, fromarea, TN_MAX_AREA_LEN); ++ free(fromarea); ++ fromarea = 0; ++ } ++ initNum(&srcnum); ++ ++ if (wanted_day) ++ get_day(wanted_day); ++} /* post_init */ ++ ++static int opts(int argc, char *argv[]) ++{ ++ register int c; ++ register char *p; ++ int x; ++ ++ h_param = 0; ++ ++ optind = 0; /* make it repeatable */ ++ need_dest = 1; ++ while ((c = getopt(argc, argv, options)) != EOF) { ++ switch (c) { ++ case 'a': /* all rates old/newer */ ++ all++; ++ break; ++ case 'b': ++ best = strtol(optarg, NIL, 0); ++ break; ++ ++/* case 'c': country */ ++ break; ++ ++ case 'd': ++ for (p = optarg; *p && isspace(*p); p++) ; ++ if (isdigit(*p)) { ++ wanted_day = '\0'; ++ day = atoi(optarg); ++ if ((p = strchr(optarg, '.'))) { ++ month = atoi(p + 1); ++ if ((p = strchr(p + 1, '.'))) { ++ year = atoi(p + 1); ++ if (year < 50) ++ year += 2000; ++ else if (year < 100) ++ year += 1900; ++ } ++ } ++ } /* isdigit */ ++ else { ++ wanted_day = *p; ++ } ++ break; ++ ++ case 'f': ++ if (optarg) { /* from */ ++ for (p = optarg; (isspace(*p) || *p == '0') && *p; p++) ; ++ fromarea = strdup(p); ++ } ++ break; ++ ++ case 'h': ++ hour = atoi(optarg); ++ h_param++; ++ sec = 0; ++ if ((p = strchr(optarg + 1, ':'))) { ++ min = atoi(p + 1); ++ if ((p = strchr(p + 1, ':'))) ++ sec = atoi(p + 1); ++ } ++ else ++ min = 0; ++ break; ++ ++ case 'l': ++ duration = strtol(optarg, NIL, 0); /* l wie lt */ ++ break; ++ ++ case 'o': /* booked only */ ++ booked++; ++ break; ++ ++ case 's': /* service */ ++ service++; ++ break; ++ ++ case 't': ++ x = strtol(optarg, NIL, 0); ++ if (x > 0) ++ takt = x; ++ break; ++ ++ case 'x': /* eXclude Poviders */ ++ { ++ char *arg = strdup(optarg); ++ ++ p = strtok(arg, ","); ++ while (p) { ++ if (*p == 'B') { /* Business Provider */ ++ xbusiness = 1; ++ p = strtok(0, ","); ++ continue; ++ } ++ xproviders = realloc(xproviders, (nx_providers + 1) * sizeof(char *)); ++ ++ xproviders[nx_providers] = strdup(p); ++ p = strtok(0, ","); ++ nx_providers++; ++ } ++ free(arg); ++ } ++ break; ++ ++ case 'p': /* Providers ... */ ++ { ++ char *arg = strdup(optarg); ++ ++ p = strtok(arg, ","); ++ while (p) { ++ if (*p == 'B') { /* Business Provider */ ++ business = 1; ++ p = strtok(0, ","); ++ continue; ++ } ++ providers = realloc(providers, (n_providers + 1) * sizeof(char *)); ++ ++ providers[n_providers] = strdup(p); ++ p = strtok(0, ","); ++ n_providers++; ++ } ++ free(arg); ++ } ++ break; ++ ++ case 'v': ++ verbose++; ++ if (optarg && (x = atoi(optarg))) ++ verbose = x; ++ break; ++/* Uppercase options are for output format */ ++ ++ case 'C': ++ is_client = 1; ++ break; ++ ++ case 'D': ++ is_daemon = 1; ++ need_dest = 0; ++ if (optarg) { ++ x = atoi(optarg); ++ is_daemon = x; ++ if (we_are_daemon && x == 3) { ++ kill(getppid(), SIGTERM); ++ exit(EXIT_SUCCESS); ++ } ++ } ++ break; ++ ++ case 'G': ++ explain = atoi(optarg); ++ break; ++ case 'H': ++ header++; ++ break; ++ case 'L': ++ list++; ++ explain = 9; ++ break; ++ case 'N': ++ explain = 55; ++ break; ++ case 'P': ++ pid_dir = strdup(optarg); ++ break; ++ case 'O': ++ free(socket_file); ++ socket_file = strdup(optarg); ++ break; ++ case 'S': ++ sortby = *optarg; ++ break; ++ case 'T': ++ table++; ++ break; ++/* Fixme: check/warn illegal kombinations of options */ ++ case 'U': ++ usestat++; ++ break; ++ ++ case 'V': ++ print_version(myshortname); ++ exit(0); ++ ++ case 'X': ++ if (explain == 0) { ++ explain++; ++ if (optarg && isdigit(*optarg) && (x = atoi(optarg))) { ++ explain = x; ++ if (x == 50 || x == 51 || x == 52) ++ need_dest = 0; ++ } ++ else if (optarg) { ++ comment = strdup(optarg); ++ explain = 8; ++ need_dest = 0; ++ } ++ break; ++ } ++ /* fallthrough */ ++ case '?': ++ print_msg(PRT_A, usage, myshortname, myshortname, options); ++ break; ++ ++ case 'Z': ++ lcr++; ++ break; ++ } /* switch */ ++ } /* while */ ++ if (is_client && is_daemon != 3 && is_daemon) { ++ is_daemon = 0; ++ print_msg(PRT_V, "Conflicting options, -D disabled\n"); ++ } ++ if (list && table) { ++ table = 0; ++ print_msg(PRT_V, "Conflicting options, -T disabled\n"); ++ } ++ if (usestat && !table) ++ print_msg(PRT_V, "Conflicting options, -U ignored\n"); ++ if ((list || table) && explain >= 10) { ++ list = table = 0; ++ print_msg(PRT_V, "Conflicting options, -T, -L disabled\n"); ++ } ++ if (best < 1) { ++ best = MAXPROVIDER; ++ print_msg(PRT_V, "Illegal options, -b ignored\n"); ++ } ++ if ((explain == 50 || explain == 51 || explain == 52) && header) { ++ print_msg(PRT_V, "Conflicting options, -H ignored\n"); ++ } ++ if (explain >= 10 && service) { ++ print_msg(PRT_V, "Conflicting options, -s ignored\n"); ++ service = 0; ++ } ++ if (argc > optind) ++ return (optind); ++ else ++ return (0); ++} /* opts */ ++ ++ ++static int (*compare_func) (const void *s1, const void *s2); ++static int compare(const void *s1, const void *s2) ++{ ++ return (((SORT *) s1)->rate > ((SORT *) s2)->rate); ++} /* compare */ ++static int compare_vbn(const void *s1, const void *s2) ++{ ++ return (((SORT *) s1)->prefix > ((SORT *) s2)->prefix); ++} ++static int compare_name(const void *s1, const void *s2) ++{ ++ return strcasecmp(((SORT *) s1)->name, ((SORT *) s2)->name); ++} ++ ++static int compare2(const void *s1, const void *s2) ++{ ++ return (((SORT2 *) s1)->weight < ((SORT2 *) s2)->weight); ++} /* compare2 */ ++ ++char *short_explainRate(RATE * Rate) ++{ ++ ++ static char buffer[BUFSIZ]; ++ char *p = buffer; ++ ++ if (service && Rate->dst[1] && *Rate->dst[1]) ++ p += sprintf(p, "%s, ", Rate->dst[1]); ++ ++ if (Rate->Zone && *Rate->Zone) ++ p += sprintf(p, "%s", Rate->Zone); ++ else ++ p += sprintf(p, "Zone %d", Rate->zone); ++ ++ if (!Rate->domestic && Rate->Country && *Rate->Country) ++ p += sprintf(p, " (%s)", Rate->Country); ++ ++ if (Rate->Day && *Rate->Day) ++ p += sprintf(p, ", %s", Rate->Day); ++ ++ if (Rate->Hour && *Rate->Hour) ++ p += sprintf(p, ", %s", Rate->Hour); ++ ++ return buffer; ++} ++ ++static char *printrate(RATE * Rate) ++{ ++ static char message[BUFSIZ]; ++ ++ if (Rate->Basic > 0) ++ sprintf(message, "%s + %s/%.1fs = %s + %s/Min (%s)", ++ printRate(Rate->Basic), ++ printRate(Rate->Price), ++ Rate->Duration, ++ printRate(Rate->Basic), ++ printRate(60 * Rate->Price / Rate->Duration), ++ short_explainRate(Rate)); ++ else ++ sprintf(message, "%s/%.1fs = %s/Min (%s)", ++ printRate(Rate->Price), ++ Rate->Duration, ++ printRate(60 * Rate->Price / Rate->Duration), ++ short_explainRate(Rate)); ++ ++ return (message); ++} /* printrate */ ++ ++ ++static void buildtime() ++{ ++ auto struct tm tm; ++ ++ tm.tm_sec = sec; ++ tm.tm_min = min; ++ tm.tm_hour = hour; ++ tm.tm_mday = day; ++ tm.tm_mon = month - 1; ++ tm.tm_year = year - 1900; /* ja, ja, ich weiá ;-) */ ++ tm.tm_isdst = -1; ++ ++ start = mktime(&tm); ++} /* buildtime */ ++ ++ ++static void splittime() ++{ ++ auto struct tm *tm; ++ ++ tm = localtime(&start); ++ sec = tm->tm_sec; ++ min = tm->tm_min; ++ hour = tm->tm_hour; ++ day = tm->tm_mday; ++ month = tm->tm_mon + 1; ++ year = tm->tm_year + 1900; ++} /* splittime */ ++ ++static char *Provider(int prefix) ++{ ++ register char *p, *p1; ++ register int l; ++ static char s[BUFSIZ]; ++ char prov[TN_MAX_PROVIDER_LEN]; ++ ++ if (prefix == UNKNOWN) ++ return ("?"); ++ ++ p = getProvider(prefix); ++ ++ l = max(WIDTH, strlen(p)) - strlen(p); ++ ++ p1 = prefix2provider_variant(prefix, prov); ++ ++ l += (8 - strlen(p1)); ++ ++ sprintf(s, "%s:%s%*s", p1, p, l, ""); ++ ++ return (s); ++} /* Provider */ ++ ++static char *takt_str(RATE * Rate) ++{ ++ static char s[BUFSIZ]; ++ ++ if (floor(Rate->Rhythm[0]) == Rate->Rhythm[0]) ++ sprintf(s, "%.0f/", Rate->Rhythm[0]); ++ else ++ sprintf(s, "%.3f/", Rate->Rhythm[0]); ++ if (floor(Rate->Rhythm[1]) == Rate->Rhythm[1]) ++ sprintf(s + strlen(s), "%.0f", Rate->Rhythm[1]); ++ else ++ sprintf(s + strlen(s), "%.3f", Rate->Rhythm[1]); ++ return s; ++} ++ ++static inline char *P_EMPTY(char *s) ++{ ++ char *p = s; ++ ++ return p ? p : ""; ++} ++ ++#define DEL ';' ++static int compute(char *num) ++{ ++ register int i, n = 0; ++ register int low = 0, high = MAXPROVIDER - 1; ++ auto RATE Rate; ++ auto char s[BUFSIZ]; ++ struct tm *tm; ++ char prov[TN_MAX_PROVIDER_LEN]; ++ int first = 1; ++ static char BUSINESS[] = "Business"; /* in C:GT:Tag */ ++ ++ if (destnum.nprovider != UNKNOWN) { ++ low = high = destnum.nprovider; ++ } /* if */ ++ compare_func = compare; ++ switch (sortby) { ++ case 'v': ++ compare_func = compare_vbn; ++ break; ++ case 'n': ++ compare_func = compare_name; ++ break; ++ } ++ ++ buildtime(); ++ if (explain == 98 || explain == 97) { /* Minutenpreis fuer ++ diese Woche */ ++ tm = localtime(&start); ++ tm->tm_hour = 0; ++ tm->tm_min = 1; ++ tm->tm_sec = 0; ++ start = mktime(tm); ++ if (explain == 98) { ++ while (tm->tm_wday) { /* find last monday */ ++ start -= (60 * 60 * 24); ++ tm = localtime(&start); ++ } /* while */ ++ start += (60 * 60 * 24); ++ } ++ } ++ if (service) { ++ num = getServiceNum(num); ++ if (!num || !*num) { ++ return 0; ++ } ++ } ++ do { ++ for (i = low; i <= high; i++) { ++ int found, p; ++ char *t; ++ ++ if (ignore[i]) /* Fixme: */ ++ continue; ++ if (booked && !isProviderBooked(i)) ++ continue; ++ if (!all && !isProviderValid(i, start)) ++ continue; ++ t = getProvider(i); ++ if (!t || t[strlen(t) - 1] == '?') /* UNKNOWN Provider */ ++ continue; ++ ++ t = getComment(i, "GT"); /* get Geb. Text comment */ ++ if (business) { /* only business wanted */ ++ if (t == 0) ++ continue; ++ else if (strstr(t, BUSINESS) == 0) ++ continue; ++ } ++ if (xbusiness) { /* no business wanted */ ++ if (t && strstr(t, BUSINESS) > 0) ++ continue; ++ } ++ found = 0; ++ if (n_providers) { ++ for (p = 0; p < n_providers; p++) ++ if (pnum2prefix_variant(providers[p], start) == i) { ++ found = 1; ++ break; ++ } ++ if (!found) ++ continue; ++ } ++ if (nx_providers) { ++ for (p = 0; p < nx_providers; p++) ++ if (pnum2prefix_variant(xproviders[p], start) == i) { ++ found = 1; ++ break; ++ } ++ if (found) ++ continue; ++ } ++ clearRate(&Rate); ++ Rate.src[0] = srcnum.country; ++ Rate.src[1] = srcnum.area; ++ Rate.src[2] = ""; ++ ++ destnum.nprovider = i; ++ Strncpy(destnum.provider, getProvider(i), TN_MAX_PROVIDER_LEN); ++ if (normalizeNumber(num, &destnum, TN_ALL) == UNKNOWN) { ++ continue; ++ } ++ ++ Rate.dst[0] = destnum.country; ++ Rate.dst[1] = destnum.area; ++ Rate.dst[2] = destnum.msn; ++ /* Rate.Service = "Internet by call"; */ ++ ++ Rate.prefix = i; ++ ++ Rate.start = start; ++ Rate.now = start + duration - 1; ++ if (explain == 99) { ++ int j; ++ double oldCharge = -1.0; ++ ++ if (first && header) ++ print_header(); ++ first = 0; ++ printf("@ %s\n", prefix2provider_variant(Rate.prefix, prov)); ++ Rate.now = start + 1; ++ for (j = 1; j < duration; j++) { ++ if (!getRate(&Rate, NULL) && (Rate.Price != 99.99)) { ++ if (Rate.Charge != oldCharge || j == duration - 1) { ++ printf("%d %.4f\n", j, Rate.Charge); ++ oldCharge = Rate.Charge; ++ } ++ } ++ else ++ break; ++ Rate.now++; ++ } ++ if (Rate.Duration <= takt) ++ printf("@----- %s %s\n", currency, Rate.Provider); ++ } ++ if (explain == 98 || explain == 97) { /* Minutenpreis fuer ++ diese Woche/Tag */ ++ int j; ++ ++ if (first && header) ++ print_header(); ++ first = 0; ++ printf("@ %s\n", prefix2provider_variant(Rate.prefix, prov)); ++ for (j = 0; j < (explain == 98 ? 7 * 24 : 24); j++) { ++ if (!getRate(&Rate, NULL) && (Rate.Price != 99.99)) { ++ printf("%d %.4f\n", j, Rate.Charge); ++ } ++ else ++ break; ++ Rate.now += 3600; ++ Rate.start += 3600; ++ } ++ if (Rate.Duration <= takt) ++ printf("@----- %s %s\n", currency, Rate.Provider); ++ } ++ else if (explain == 50 || explain == 51) { ++ int fi = 1; ++ ++ while (getZoneRate(&Rate, explain - 50, fi) == 0) { ++ double cpm = Rate.Duration > 0 ? 60 * Rate.Price / Rate.Duration : 99.99; ++ ++ if (Rate.Price == 0) ++ cpm = Rate.Basic; ++ ++ fi = 0; ++ if (Rate.Price != 99.99) ++ printf("%s%c%s%c%s%c%.2f%c%.2f%c%s\n", prefix2provider(Rate.prefix, prov), DEL, ++ Rate.Provider, DEL, currency, DEL, Rate.Charge, DEL, cpm, DEL, ++ P_EMPTY(Rate.Country)); ++ free(Rate.Country); ++ } ++ } ++ else { ++ /* kludge to suppress "impossible" Rates */ ++ char **message, *msg; ++ if(verbose) ++ message = &msg; ++ else ++ message = NULL; ++ if (!getRate(&Rate, message) && (Rate.Price != 99.99)) { ++ if (!(Rate.Duration <= takt)) ++ continue; ++ sort[n].prefix = Rate.prefix; ++ sort[n].rate = Rate.Charge; ++ sort[n].name = Rate.Provider; ++ switch (explain) { ++ case 1: ++ if (service) ++ sprintf(s, " (%s, %s)", P_EMPTY(Rate.dst[1]), Rate.Zone); ++ else ++ sprintf(s, " (%s)", Rate.Zone); ++ sort[n].explain = strdup(s); ++ break; ++ case 2: ++ sprintf(s, " (%s)", printrate(&Rate)); ++ sort[n].explain = strdup(s); ++ break; ++ case 8: ++ sort[n].explain = strdup(P_EMPTY(getComment(i, comment))); ++ break; ++ case 9: /* used by list */ ++ { ++ double cpm = Rate.Duration > 0 ? 60 * Rate.Price / Rate.Duration : 99.99; ++ ++ if (Rate.Price == 0) ++ cpm = Rate.Basic; ++ ++ sprintf(s, "%s%c" ++ "%s%c%s%c%s%c%s%c" ++ "%s%c" ++ "%.3f%c%.4f%c%.4f%c%.2f%c%.3f%c" ++ "%s%c%.2f", ++ prefix2provider_variant(Rate.prefix, prov), DEL, ++ Rate.Provider, DEL, P_EMPTY(Rate.Zone), DEL, P_EMPTY(Rate.Day), DEL, P_EMPTY(Rate.Hour), DEL, ++ currency, DEL, /* Fixme: global or per ++ Provider?? wg. EURO */ ++ Rate.Charge, DEL, Rate.Basic, DEL, Rate.Price, DEL, Rate.Duration, DEL, cpm, DEL, ++ takt_str(&Rate), DEL, Rate.Sales); ++ sort[n].explain = strdup(s); ++ } ++ break; ++ default: ++ sort[n].explain = strdup(""); ++ break; ++ } ++ ++ n++; ++ } /* if */ ++ else if(verbose && *msg) ++ print_msg(PRT_V, "%s\n", msg); ++ ++ } /* else 99 */ ++ } /* for i */ ++ if (service) ++ num = getServiceNum(0); /* get next service num */ ++ else ++ num = 0; ++ } while (num && *num); ++ if (explain < 10) { ++ qsort((void *) sort, n, sizeof(SORT), compare_func); ++ if (lcr && n) { ++ RATE Cheap; ++ int res = getLeastCost(&Rate, &Cheap, booked, -1); ++ ++ if (res != UNKNOWN) { ++ sort[n].prefix = Cheap.prefix; ++ sort[n].rate = Cheap.Charge; ++ sort[n].name = Cheap.Provider; ++ sprintf(s, "(Cheapest: %s %s %s %s)", Cheap.dst[0], Cheap.dst[1], Cheap.dst[2], P_EMPTY(Cheap.Zone)); ++ sort[n].explain = strdup(s); ++ n++; ++ } /* res */ ++ } /* lcr */ ++ } /* explain */ ++ return (n); ++} /* compute */ ++ ++static void print_header(void) ++{ ++ printf("Eine %d Sekunden lange Verbindung von %s nach %s kostet am %s\n", ++ duration, formatNumber("%F", &srcnum), formatNumber("%F", &destnum), ++ ctime(&start)); ++} ++ ++static void printList(int n) ++{ ++ int i; ++ ++ if (header) ++ print_header(); ++ if (n > best) ++ n = best; ++ ++ for (i = 0; i < n; i++) ++ printf("%s\n", sort[i].explain); ++} ++ ++static void result(int n) ++{ ++ ++ register int i; ++ ++ if (header) ++ print_header(); ++ ++ if (n > best) ++ n = best; ++ for (i = 0; i < n; i++) ++ printf("%s %s %8.3f %s\n", ++ Provider(sort[i].prefix), currency, sort[i].rate, sort[i].explain); ++} /* result */ ++ ++ ++static void purge(int n) ++{ ++ register int i; ++ ++ for (i = 0; i < n; i++) ++ if (sort[i].explain) ++ free(sort[i].explain); ++} /* purge */ ++ ++/* ++ Werktag ++ Wochenende ++ Ortszone ++ Regionalzone ++ Fernzone ++ Handy ++ Internet ++ 0..23 Uhr ++ */ ++ ++#define STARTHOUR 8 ++ ++static void printTable(char *num) ++{ ++ register int n, d, i, h, lasthour; ++ auto struct tm *tm; ++ auto SORT last[_MAXLAST]; ++ auto int used[MAXPROVIDER]; ++ auto int hours[MAXPROVIDER]; ++ auto int weight[MAXPROVIDER]; ++ auto int useds = 0, maxhour; ++ auto SORT2 wsort[MAXPROVIDER]; ++ static int firsttime = 1; ++ int first; ++ int prefix; ++ ++ memset(used, 0, sizeof(used)); ++ memset(hours, 0, sizeof(hours)); ++ memset(weight, 0, sizeof(weight)); ++ ++ for (d = 0; d < 3; d++) { /* Werktag, Samstag, Sonntag */ ++ last[0].prefix = UNKNOWN; ++ lasthour = UNKNOWN; ++ ++ buildtime(); ++ tm = localtime(&start); ++ ++ if (!d) { /* first time */ ++ while (tm->tm_wday != 5) { /* find next Friday */ ++ start += (60 * 60 * 24); ++ tm = localtime(&start); ++ } /* while */ ++ } ++ else /* erst Samstag, dann */ ++ start += (60 * 60 * 24); /* Sonntag */ ++ ++ splittime(); ++ buildtime(); ++ ++ hour = STARTHOUR; ++ min = 0; ++ ++ first = 1; ++ ++ while (1) { ++ destnum.nprovider = UNKNOWN; ++ if (provider2prefix(num, &prefix)) /* set provider if it is in number */ ++ normalizeNumber(num, &destnum, TN_PROVIDER); ++ n = compute(num); ++ ++ if (header && first && d == 0 && firsttime) ++ print_header(); ++ ++ if (header && first) { ++ switch (d) { ++ case 0 : printf("\nWerktag:\n"); break; ++ case 1 : printf("\nSamstag:\n"); break; ++ case 2 : printf("\nSonntag:\n"); break; ++ } /* switch */ ++ ++ first = 0; ++ } /* if */ ++ ++ if (last[0].prefix == UNKNOWN) { ++ for (i = 0; i < min(n, MAXLAST); i++) { ++ if (sort[i].prefix) { ++ last[i].prefix = sort[i].prefix; ++ last[i].rate = sort[i].rate; ++ last[i].explain = strdup(sort[i].explain); ++ } /* if */ ++ } /* for */ ++ } /* if */ ++ ++ if (lasthour == UNKNOWN) ++ lasthour = hour; ++ ++ if (sort[0].prefix != last[0].prefix) { ++ for (i = 0; i < min(n, MAXLAST); i++) { ++ ++ if (!i) ++ printf(" %02d:00 .. %02d:59 %s = %s %s%s\n", ++ lasthour, hour - 1, Provider(last[i].prefix), ++ currency, ++ double2str(last[i].rate, 5, 3, DEB), ++ last[i].explain); ++ else ++ printf(" %s = %s %s%s\n", ++ Provider(last[i].prefix), ++ currency, ++ double2str(last[i].rate, 5, 3, DEB), ++ last[i].explain); ++ } /* for */ ++ ++ used[last[0].prefix]++; ++ ++ if (lasthour >= hour) ++ h = ((24 - lasthour) + hour); ++ else ++ h = hour - lasthour; ++ ++ hours[last[0].prefix] += h; ++ ++ if ((lasthour > 8) && (lasthour < 21)) ++ h *= 2; ++ ++ weight[last[0].prefix] += h * (d ? 1 : 5); ++ ++ for (i = 0; i < min(n, MAXLAST); i++) { ++ last[i].prefix = sort[i].prefix; ++ last[i].rate = sort[i].rate; ++ last[i].explain = strdup(sort[i].explain); ++ } /* for */ ++ ++ lasthour = hour; ++ } /* if */ ++ ++ purge(n); ++ ++ hour++; ++ ++ if (hour == 24) ++ hour = 0; ++ else if (hour == STARTHOUR) ++ break; ++ } /* while */ ++ ++ for (i = 0; i < min(n, MAXLAST); i++) { ++ ++ if (!i) { ++ if ((lasthour == STARTHOUR) && (hour == STARTHOUR)) ++ printf(" immer %s = %s %s%s\n", ++ Provider(last[i].prefix), ++ currency, ++ double2str(last[i].rate, 5, 3, DEB), ++ last[i].explain); ++ else ++ printf(" %02d:00 .. %02d:59 %s = %s %s%s\n", ++ lasthour, hour - 1, Provider(last[i].prefix), ++ currency, ++ double2str(last[i].rate, 5, 3, DEB), ++ last[i].explain); ++ } ++ else ++ printf(" %s = %s %s%s\n", ++ Provider(last[i].prefix), ++ currency, ++ double2str(last[i].rate, 5, 3, DEB), ++ last[i].explain); ++ } /* for */ ++ ++ used[last[0].prefix]++; ++ ++ if (lasthour >= hour) ++ h = ((24 - lasthour) + hour); ++ else ++ h = hour - lasthour; ++ ++ hours[last[0].prefix] += h; ++ ++ if ((lasthour > 8) && (lasthour < 21)) ++ h *= 2; ++ ++ weight[last[0].prefix] += h * (d ? 1 : 5); ++ ++ } /* for */ ++ ++ if (usestat) { ++ printf("\nProvider(s) used:\n"); ++ ++ maxhour = 9999999; ++ useds = 0; ++ ++ for (i = 0; i < MAXPROVIDER; i++) ++ if (used[i]) { ++ printf("%s %d times, %d hours, weight = %d\n", ++ Provider(i), used[i], hours[i], weight[i]); ++ ++ wsort[useds].weight = weight[i]; ++ wsort[useds].index = i; ++ ++ useds++; ++ ++ if (hours[i] < maxhour) ++ maxhour = hours[i]; ++ } /* if */ ++ ++ if ((best < MAXPROVIDER) && (best < useds)) { ++ printf("Retrying with only %d provider(s), eliminating %d provider(s)\n", best, useds - best); ++ ++ qsort((void *) wsort, useds, sizeof(SORT2), compare2); ++ ++ for (i = 0; i < useds; i++) { ++ printf("%s %d times, %d hours, weight = %d\n", ++ Provider(wsort[i].index), used[wsort[i].index], hours[wsort[i].index], weight[wsort[i].index]); ++ ++ if (i == best - 1) ++ printf("\n"); ++ ++ if (i >= best - 1) ++ ignore[wsort[i].index]++; ++ } /* for */ ++ ++ if (firsttime) ++ printTable(num); ++ ++ firsttime = 0; ++ ++ } /* if */ ++ } /* if */ ++} /* printTable */ ++ ++ ++static void clean_up() ++{ ++ if (providers) ++ free(providers); ++ providers = 0; ++ fromarea = 0; ++ table = list = header = explain = 0; ++ usestat = 0; ++ duration = LCR_DURATION; ++ wanted_day = '\0'; ++ takt = 99999; ++ if (comment) ++ free(comment); ++ comment = 0; ++ sortby = 0; ++ need_dest = 1; ++} ++ ++static char * sub_sp(char *p) ++{ ++ char *o = p; ++ int allupper=1; ++ for (; *p; p++) ++ if(!isupper(*p) && *p != '_' && !isdigit(*p)) { /* e.g. _DEMD1 */ ++ allupper = 0; ++ break; ++ } ++ if (!allupper) ++ for (p = o; *p; p++) ++ if(*p == '_') ++ *p = ' '; ++ return o; ++} ++static void doit(int i, int argc, char *argv[]) ++{ ++ int n; ++ int prefix; ++ char *num; ++ ++ post_init(); ++ memset(ignore, 0, sizeof(ignore)); ++ if (!need_dest && i == 0) { ++ i = 0; ++ argc = 1; ++ argv[0] = "2345"; ++ } ++ while (i < argc) { ++ num = sub_sp(argv[i]); ++ if (explain == 55) { ++ if (n_providers) { ++ destnum.nprovider = pnum2prefix_variant(providers[0], 0); ++ Strncpy(destnum.provider, getProvider(destnum.nprovider), TN_MAX_PROVIDER_LEN); ++ normalizeNumber(num, &destnum, TN_NO_PROVIDER); ++ } ++ else ++ normalizeNumber(num, &destnum, TN_ALL); ++ printf("%s => %s \n", num, formatNumber("%l - %p", &destnum)); ++ i++; ++ continue; ++ } ++ else if (explain == 52) { // enum Servce names ++ ++ int first = 1; ++ char *p; ++ ++ do { ++ p = getServiceNames(first); ++ if (p) ++ printf("%s\n", p); ++ first = 0; ++ } ++ while (p); ++ return; ++ } ++ destnum.nprovider = UNKNOWN; ++ if (provider2prefix(num, &prefix)) /* set provider if it is in ++ number */ ++ normalizeNumber(num, &destnum, TN_PROVIDER); ++ if (table) ++ printTable(num); ++ else { ++ n = compute(num); ++ if (list) ++ printList(n); ++ else if (explain < 10) ++ result(n); ++ purge(n); ++ } ++ i++; ++ } /* while */ ++ clean_up(); ++} ++ ++static void err(char *s) ++{ ++ print_msg(PRT_A, "%s - '%s'\n", s, strerror(errno)); ++ if (is_daemon == 2) ++ kill(getppid(), SIGTERM); ++ exit(2); ++} ++ ++static int handle_client(int fd) ++{ ++ char buffer[BUFSIZ]; ++ int argc, n, i; ++ char **argv; ++ char *p; ++ ++ if ((n = read(fd, buffer, BUFSIZ)) < 0) ++ err("Read"); ++ if (n) { ++ argv = calloc(sizeof(char *), 20); ++ ++ buffer[n] = '\0'; ++ if (verbose) ++ fprintf(stderr, "got '%s'\n", buffer); ++ argc = 0; ++ argv[argc++] = strdup(myname); ++ p = strtok(buffer, "\t\n "); ++ while (p) { ++ argv[argc++] = strdup(p); ++ p = strtok(0, "\t\n "); ++ if (argc >= 20) ++ break; ++ } ++ time(&start); /* set time of call */ ++ splittime(); /* date time my be overridden by opts */ ++ we_are_daemon = 1; ++ if ((i = opts(argc, argv)) || need_dest == 0) { ++ if (shutdown(fd, 0) < 0) /* no read any more */ ++ err("shutdown"); ++ if (dup2(fd, STDOUT_FILENO) < 0) /* stdout to sock */ ++ err("dup"); ++ doit(i, argc, argv); ++ fflush(stdout); ++ fclose(stdout); ++ } ++ for (i = 0; i < argc; i++) ++ free(argv[i]); ++ free(argv); ++ } ++ return n == 0 ? -1 : 0; ++} ++ ++void catch_sig(int sig) ++{ ++ print_msg(PRT_A, "Signal %d\n", sig); ++ unlink(socket_file); ++ if (pid_dir) ++ unlink(pid_file); ++ err("Sig"); ++} ++ ++static void del_sock(void) ++{ ++ if (getppid() > 0) { ++ unlink(socket_file); ++ if (pid_dir) ++ unlink(pid_file); ++ } ++} ++ ++static volatile sig_atomic_t stopped = 0; ++static volatile sig_atomic_t reinit = 0; ++ ++static void catch_term(int sig) ++{ ++ stopped = 1; ++} ++ ++static void catch_hup(int sig) ++{ ++ print_msg(PRT_A, "Signal %d restarting %s\n", sig, myname); ++ del_sock(); ++ execvp(myname, hup_argv); ++ print_msg(PRT_A, "- failed\n"); ++} ++ ++static void do_reinit(void) ++{ ++ /* deinit(), init() doesn't */ ++ reinit=0; ++} ++ ++/* thank's to Jochen Erwied for this: */ ++#ifndef TEMP_FAILURE_RETRY ++#define TEMP_FAILURE_RETRY(expression) \ ++ (__extension__ \ ++ ({ long int __result; \ ++ do __result = (long int) (expression); \ ++ while (__result == -1L && errno == EINTR); \ ++ __result; })) \ ++ ++#endif ++ ++static void setup_daemon() ++{ ++ int sock; ++ struct sockaddr_un sa; ++ struct sockaddr_in client; ++ fd_set active_fd_set, read_fd_set; ++ char *sock_name = socket_file; ++ socklen_t size; ++ struct stat stat_buf; ++ int i; ++ pid_t pid; ++ char pidname[] = "isdnrate.pid"; ++ FILE *fp; ++ ++ if (verbose) ++ fprintf(stderr, "Setup sockets\n"); ++ signal(SIGTERM, catch_term); ++ signal(SIGINT, catch_sig); ++ signal(SIGHUP, catch_hup); ++ ++ if (is_daemon == 2) { /* go background */ ++ ++ fprintf(stderr, "Going background\n"); ++ verbose = 0; ++ pid = fork(); ++ if (pid < 0) ++ err("Going bg failed"); ++ else if (pid > 0) { ++ exit(EXIT_SUCCESS); ++ } ++ } ++ if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) ++ err("Can't open socket"); ++ sa.sun_family = AF_UNIX; ++ strcpy(sa.sun_path, sock_name); ++ size = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path) + 1; ++ ++ if (bind(sock, (struct sockaddr *) &sa, size) < 0) ++ err("Can't bind sock"); ++ ++ stat(sock_name, &stat_buf); ++ chmod(sock_name, stat_buf.st_mode | S_IWOTH | S_IWGRP); ++/* should better have perm wwwrun.nogroup */ ++ ++ if (listen(sock, SOMAXCONN) < 0) ++ err("Can't listen"); ++ if (pid_dir) { ++ pid_file = malloc(strlen(pid_dir) + strlen(pidname) + 2); ++ strcpy(pid_file, pid_dir); ++ if (pid_file[strlen(pid_file) - 1] != '/') ++ strcat(pid_file, "/"); ++ strcat(pid_file, pidname); ++ if ((fp = fopen(pid_file, "w")) == 0) ++ fprintf(stderr, "Can't write %s\n", pid_file); ++ else { ++ fprintf(fp, "%d\n", getpid()); ++ fclose(fp); ++ } ++ } ++ atexit(del_sock); ++ FD_ZERO(&active_fd_set); ++ FD_SET(sock, &active_fd_set); ++ while (!stopped) { ++ if (reinit) ++ do_reinit(); ++ read_fd_set = active_fd_set; ++ if (TEMP_FAILURE_RETRY(select(FD_SETSIZE, &read_fd_set, 0, 0, 0)) < 0) ++ err("select"); ++ for (i = 0; i < FD_SETSIZE; i++) ++ if (FD_ISSET(i, &read_fd_set)) { ++ if (i == sock) { /* request on orig */ ++ int new; ++ ++ size = sizeof(client); ++ if ((new = accept(sock, (struct sockaddr *) &client, &size)) < 0) ++ err("accept"); ++ if (verbose) ++ fprintf(stderr, "Accepted %d\n", new); ++ FD_SET(new, &active_fd_set); ++ } ++ else { /* already connected */ ++ pid_t pid; ++ int status; ++ ++ if (verbose) ++ fprintf(stderr, "Handle client %d\n", i); ++ pid = fork(); ++ if (pid == 0) { ++ handle_client(i); ++ _exit(EXIT_SUCCESS); ++ } ++ else if (pid < 0) ++ err("fork"); ++ else { ++ if (waitpid(pid, &status, 0) != pid) ++ err("waitpid"); ++ close(i); ++ FD_CLR(i, &active_fd_set); ++ } ++ } /* if i */ ++ } /* if ISSET */ ++ } /* while */ ++ del_sock(); ++ exit(EXIT_SUCCESS); ++} ++ ++static int connect_2_daemon(int argc, char *argv[]) ++{ ++ int sock; ++ struct sockaddr_un sa; ++ char *sock_name = socket_file; ++ size_t size; ++ int i, c, len; ++ char *p, *q, buffer[BUFSIZ]; ++ ++ if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) ++ err("Can't open socket"); ++ sa.sun_family = AF_UNIX; ++ strcpy(sa.sun_path, sock_name); ++ size = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path) + 1; ++ ++ if (connect(sock, (struct sockaddr *) &sa, size) < 0) ++ err("Can't connect sock"); ++ p = buffer; ++ optind = 0; /* reinit */ ++ len = 0; ++ while ((c = getopt(argc, argv, options)) != EOF && len < BUFSIZ - 10) { ++ switch (c) { ++ case '?': ++ case 'C': ++ break; ++ case 'D': ++ if (optarg && atoi(optarg) == 3) ; /* goon, kill a running ++ daemon */ ++ else ++ break; ++ default: ++ *p++ = '-'; ++ *p++ = c; ++ len += 3; ++ if (optarg) ++ for (q = optarg; *q && len < BUFSIZ - 10; len++) ++ *p++ = *q++; ++ *p++ = ' '; ++ break; ++ } ++ } ++ for (i = optind; i < argc; i++) { ++ for (q = argv[i]; *q && len < BUFSIZ - 10; len++) ++ *p++ = *q++; ++ *p++ = ' '; ++ len++; ++ } ++ *--p = '\x0'; ++ i = write(sock, buffer, strlen(buffer) + 1); ++ if (i < 0) ++ err("Write sock"); ++ while ((i = read(sock, buffer, BUFSIZ)) > 0) ++ write(1, buffer, i); ++ close(sock); ++ return EXIT_SUCCESS; ++} ++ ++ ++int main(int argc, char *argv[], char *envp[]) ++{ ++ register int i; ++ sigset_t unblock_set; ++ ++ myname = argv[0]; ++ myshortname = basename(myname); ++ ++ time(&start); ++ splittime(); ++ socket_file = strdup(SOCKNAME); ++ /* borrowed from isdnlog.c, thanks */ ++ hup_argv = argv; ++ sigemptyset(&unblock_set); ++ sigaddset(&unblock_set, SIGHUP); ++ sigprocmask(SIG_UNBLOCK, &unblock_set, NULL); ++ ++ if ((i = opts(argc, argv)) || need_dest == 0) { ++ if (is_client) ++ exit(connect_2_daemon(argc, argv)); ++ else ++ init(); ++ if (is_daemon) { ++ clean_up(); ++ setup_daemon(); ++ } ++ else ++ doit(i, argc, argv); ++ } ++ else { ++ print_msg(PRT_A, usage, myshortname, myshortname, options); ++ print_msg(PRT_A, "\n"); ++ print_msg(PRT_A, "\t-a \tall=show old and newer rates (default actual only)\n", MAXPROVIDER); ++ print_msg(PRT_A, "\t-b best\tshow only the first <best> provider(s) (default %d)\n", MAXPROVIDER); ++ print_msg(PRT_A, "\t-d d[.m[.y]] | {W|N|E}\tstart date of call (default now)\n"); ++ print_msg(PRT_A, "\t-f areacode\tyou are calling from <areacode>\n"); ++ print_msg(PRT_A, "\t-h h[:m[:s]]\tstart time of call (default now)\n"); ++ print_msg(PRT_A, "\t-l duration\tduration of call in seconds (default %d seconds)\n", LCR_DURATION); ++ print_msg(PRT_A, "\t-o \t show only booked providers\n"); ++ print_msg(PRT_A, "\t-p prov|B[,prov...]\t show only these providers\n"); ++ print_msg(PRT_A, "\t-s \t consider 'Destination' as a service name\n"); ++ print_msg(PRT_A, "\t-t takt\t\tshow providers if chargeduration<=takt\n"); ++ print_msg(PRT_A, "\t-v [level]\tverbose\n"); ++ print_msg(PRT_A, "\t-x prov|B[,prov...]\t exclude these providers\n"); ++ ++ print_msg(PRT_A, "\tOutput and run options\n"); ++ print_msg(PRT_A, "\t-C\trun as client, connecting to a running daemon\n"); ++ print_msg(PRT_A, "\t-CD3\tkill a running daemon\n"); ++ print_msg(PRT_A, "\t-D\trun as daemon\n"); ++ print_msg(PRT_A, "\t-D2\trun as daemon & go background\n"); ++ print_msg(PRT_A, "\t-G which\tshow raw data\n"); ++ print_msg(PRT_A, "\t-H\tshow a header\n"); ++ print_msg(PRT_A, "\t-L\tshow a detailed list\n"); ++ print_msg(PRT_A, "\t-O sOcket-path\twrite socket to this file (def:tmp/isdnrate)\n"); ++ print_msg(PRT_A, "\t-P pid-dir\twrite own PID to pid-dir/isdnrate.pid\n"); ++ print_msg(PRT_A, "\t-N\tparse the given telefon numbers\n"); ++ print_msg(PRT_A, "\t-S[v|n]\tsort by v=VBN, n=Name, default=Charge\n"); ++ print_msg(PRT_A, "\t-T\tshow a table of day/night week/weekend\n"); ++ print_msg(PRT_A, "\t-U\tshow usage stats for table\n"); ++ print_msg(PRT_A, "\t-V\tshow version info\n"); ++ print_msg(PRT_A, "\t-X\texplain each rate\n"); ++ print_msg(PRT_A, "\t-X2\texplain more\n"); ++ print_msg(PRT_A, "\t-X comment\tprint <comment> from C:tag\n"); ++ print_msg(PRT_A, "\t-Z show entry from getLeastCost\n"); ++ print_msg(PRT_A, "\n\te.g.\t%s -b5 -f30 -TH -t1 Zaire\n", myshortname); ++ } /* else */ ++/* deinit(); Fixme: this SIGSEGVs in exitHoliday */ ++ return (0); ++} /* isdnrate */ +diff -Naur isdn4k-utils-orig//isdnlog/tools/rate.c isdn4k-utils/isdnlog/tools/rate.c +--- isdn4k-utils-orig//isdnlog/tools/rate.c 2002-07-06 09:22:33.000000000 +1000 ++++ isdn4k-utils/isdnlog/tools/rate.c 2010-12-04 20:44:03.786672226 +1000 +@@ -1773,6 +1773,7 @@ + number=realloc(number, numbers*sizeof(int)); + number[numbers-1]=i; + skip: ++ ; + } + + while (isblank(*s)) s++; +@@ -2344,6 +2345,7 @@ + } + return UNKNOWN; + done: ++ ; + } + } + } +diff -Naur isdn4k-utils-orig//lib/libtools.c isdn4k-utils/lib/libtools.c +--- isdn4k-utils-orig//lib/libtools.c 1999-11-04 02:13:36.000000000 +1000 ++++ isdn4k-utils/lib/libtools.c 2010-12-04 20:44:03.786672226 +1000 +@@ -711,6 +711,7 @@ + case 'r': _mode |= R_OK; + break; + default : ++ ; + } + } + +diff -Naur isdn4k-utils-orig//Makefile isdn4k-utils/Makefile +--- isdn4k-utils-orig//Makefile 2002-07-20 05:03:49.000000000 +1000 ++++ isdn4k-utils/Makefile 2010-12-04 20:43:57.890005560 +1000 +@@ -132,12 +132,6 @@ + + install: rootperm + set -e; for i in `echo $(SUBDIRS)`; do $(MAKE) -C $$i install; done +- @if [ -c $(DESTDIR)/dev/isdnctrl0 ] && ls -l $(DESTDIR)/dev/isdnctrl0 | egrep "[[:space:]]45,[[:space:]]+64[[:space:]]" > /dev/null; \ +- then \ +- /bin/echo -e '(some) ISDN devices already exist, not creating them.\nUse scripts/makedev.sh manually if necessary.'; \ +- else \ +- sh scripts/makedev.sh $(DESTDIR) ; \ +- fi + + uninstall: rootperm + set -e; for i in `echo $(SUBDIRS)`; do $(MAKE) -C $$i uninstall; done |