/* $Id: function.c,v 1.1 1997/03/24 22:52:09 luethje Exp $ * * ISDN accounting for isdn4linux. (Report-module) * * Copyright 1995, 1997 by Andreas Kool (akool@Kool.f.EUnet.de) * and Stefan Luethje (luethje@sl-gw.lake.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: function.c,v $ * Revision 1.1 1997/03/24 22:52:09 luethje * isdnrep completed. * * Revision 1.4 1997/03/23 23:11:59 luethje * improved performance * * Revision 1.3 1997/03/23 20:25:23 luethje * tmporary (running) result of the new structure of isdnrep * * Revision 1.2 1997/03/20 00:19:13 luethje * inserted the line #include in avmb1/avmcapictrl.c and imon/imon.c, * some bugfixes, new structure in isdnlog/isdnrep/isdnrep.c. * * Revision 1.1 1997/03/16 20:59:05 luethje * Added the source code isdnlog. isdnlog is not working yet. * A workaround for that problem: * copy lib/policy.h into the root directory of isdn4k-utils. * * Revision 2.6.19 1997/01/04 13:00:35 akool * Korrektur bzgl. ISDN_CH * Danke an Markus Maeder (mmaeder@cyberlink.ch) * * Revision 2.6.15 1997/01/02 11:32:35 akool * -V Option added * * Revision 2.6.11 1996/12/30 10:17:35 akool * Dutch accounting (Ad Aerts ) * * Revision 2.50 1996/08/25 11:48:35 akool * Auswertung bei non-AOCE-Anschluessen verbessert * * Revision 2.13 1996/03/16 16:11:35 akool * Andruck der "ibytes" implementiert * * Revision 2.10 1996/01/16 01:04:35 sl * Ausgabe von bestimmten MSN's ergaenzt, Nur ankommende dor ausgehende * Gespraeche anzeigen, Ueberarbeitung der kompletten Sourcen. * Funktion fuer fremde Waehrungen ergaenzt * * Revision 2.03 1996/01/07 03:35:17 sl * Optionen -c und -6 entfernt, Tab-Bug behoben, Bug in automatischer * Gebuehrenberechnung beim alten Logformat behoben, * Zeitangabe beim Summary, * * Revision 2.02 1996/01/07 03:35:17 sl * Zeitraumausgabe angepasst, loeschen von isdn.log-Eintraegen * * Revision 2.01 1996/01/06 18:15:20 sl * Zeitraumausgabe, nur Calls-Anzeige, optionales Logfile * * Revision 2.00 1996/01/01 17:50:19 akool * Auswertung der neuen Eintraege (I/O, Cause) implementiert * Vollstaendiges Redesign * * Revision 1.25 1995/11/19 09:56:19 akool * Neue Option "-c" aktiviert die eigene Berechnung der Einheiten bei * fehlender Gebuehreninfo * * Revision 1.24 1995/11/12 11:09:19 akool * Formatfelder vergroessert * Fremdverursachte Einheiten werden ge-() * Alle Floating-Point-Zahlen werden deutsch (mit Komma) ausgegeben * * Revision 1.23 1995/11/06 18:04:19 akool * Denkfehler in der "-6" Berechnung :-( * * Revision 1.22 1995/10/22 15:31:19 akool * Aufschluesselung bach Tarifzonen implementiert * * Revision 1.21 1995/10/17 19:53:19 akool * Auf echte Charging-Info umgestellt * * Revision 1.20 1995/10/15 17:58:19 akool * Vergleich errechnete zu uebermittelten Einheiten implementiert * * Revision 1.16 1995/10/12 13:50:19 akool * Neue Option "MYMSNS=x" in der "isdnlog.conf" zum definieren der Anzahl * eigener MSN's * * Revision 1.15 1995/10/09 18:42:18 akool * Offensichtlich sinnlose Daten i.d. "isdn.log" werden nun ignoriert * * Revision 1.14 1995/10/08 10:25:16 akool * Ueberschreitung verschiedener Zeittakte bei einer Verbindung implementiert. * * Revision 1.6 1995/09/30 19:55:17 akool * First public release * * Revision 1.1 1995/09/23 16:44:19 akool * Initial revision * */ #define _REP_FUNC_C_ #include "isdnrep.h" /*****************************************************************************/ #define END_TIME 1 /*****************************************************************************/ static time_t get_month(char *String, int TimeStatus); static time_t get_time(char *String, int TimeStatus); static int show_msn(one_call *cur_call); static int add_sum_calls(sum_calls *s1, sum_calls *s2); static int print_sum_calls(sum_calls *s, int computed); static int add_one_call(sum_calls *s1, one_call *s2, double units); static int clear_sum(sum_calls *s1); static char *print_currency(int units, double money, int Format); static void strich(int type); static int n_match(char *Pattern, char* Number, char* version); static int set_caller_infos(one_call *cur_call, char *string); static int set_alias(one_call *cur_call, int *nx, char *myname); static int print_header(int lday, char *time_string, sum_calls *day_sum, sum_calls *day_com_sum, sum_calls *all_sum, sum_calls *all_com_sum); static int print_entries(one_call *cur_call, sum_calls *day_sum, sum_calls *day_com_sum, double unit, int Tarif96, int *nx, char *myname); /*****************************************************************************/ static int invertnumbers = 0; static int unknowns = 0; static UNKNOWN unknown[MAXUNKNOWN]; static int zones[MAXZONES]; static int zones_usage[MAXZONES]; static double zones_dm[MAXZONES]; static double zones_dur[MAXZONES]; static char** ShowMSN = NULL; /*****************************************************************************/ static char msg1[] = "%s: Can't open %s (%s)\n"; static char wrongdate2[] = "wrong date for delete: %s\n"; static char nomemory[] = "Out of memory!\n"; /*****************************************************************************/ static double restdur = 0.0; static double restidur = 0.0; static double restdm = 0.0; static int restiusage = 0; static int restusage = 0; static int resteh = 0; /*****************************************************************************/ /* char *lfnam = LOGFILE; int (*print_msg)(int Level, const char *, ...) = NULL; int incomingonly = 0; int outgoingonly = 0; int verbose = 0; int timearea = 0, phonenumberonly = 0; int compute = 0; time_t begintime, endtime; int delentries = 0; int numbers = 0; int header = 1; char timestring[256] = ""; */ /*****************************************************************************/ void set_print_fct_for_isdnrep(int (*new_print_msg)(int Level, const char *, ...)) { print_msg = new_print_msg; } /*****************************************************************************/ int read_logfile(char *myname) { auto int Tarif96 = 0, Tarif962 = 0; auto double einheit = 0.23; auto int nx[2]; auto time_t now, from = (time_t)0; auto struct tm *tm; auto int lday = -1; auto char start[20] = "", stop[20]; auto char* tmpfile = NULL; auto FILE *fi, *ftmp = NULL; auto char string[BUFSIZ], s[BUFSIZ], s1[BUFSIZ]; register char *p = NULL; register int i, k; one_call cur_call; sum_calls day_sum, day_com_sum, all_sum, all_com_sum, tmp_sum; clear_sum(&day_sum); clear_sum(&day_com_sum); clear_sum(&all_sum); clear_sum(&all_com_sum); if (delentries) if(begintime) { print_msg(PRT_ERR, wrongdate2, timestring); return -1; } else { if ((tmpfile = tmpnam(NULL)) == NULL) return -1; if ((ftmp = fopen(tmpfile, "w")) == (FILE *)NULL) { print_msg(PRT_ERR, msg1, tmpfile, strerror(errno)); return -1; } } if (!timearea) { /* from darf nicht gesetzt werden, wenn alle Telefonate angezeigt werden sollen */ time(&now); /* aktuelle Zeit wird gesetzt */ tm = localtime(&now); /* Zeit von 1970 nach Struktur */ tm->tm_sec = tm->tm_min = tm->tm_hour = 0; from = mktime(tm); /* Struktur nach Zeit von 1970 */ /* from hat den aktuellen Tag 0.00 Uhr */ } /* if */ if ((fi = fopen(lfnam, "r")) == (FILE *)NULL){ print_msg(PRT_ERR,"Can not open file `%s': %s!\n",lfnam,strerror(errno)); return -1; } memset(zones, 0, sizeof(zones)); while (fgets(s, BUFSIZ, fi)) { strcpy(string,s); if (*s == '#') continue; if (set_caller_infos(&cur_call,s) != 0) continue; if (!begintime) begintime = cur_call.t; if (timearea) { if (delentries) if (cur_call.t > endtime) fputs(string,ftmp); else continue; if (cur_call.t < begintime || cur_call.t > endtime) continue; } else if (cur_call.t < from) continue; /* Einlesen des naechsten Telefonats */ if (!verbose && cur_call.duration == 0) continue; if (phonenumberonly) if (!show_msn(&cur_call)) continue; if (incomingonly && cur_call.dir == DIALOUT) continue; if (outgoingonly && cur_call.dir == DIALIN) continue; tm = localtime(&(cur_call.t)); /* Zeit von 1970 nach Struktur */ day = tm->tm_mday; month = tm->tm_mon; Tarif96 = tm->tm_year > 95; /* Ab Juli '96 gibt's noch mal eine Senkung in den Zonen 3 und 4 genaue Preise sind jedoch noch nicht bekannt. FIX-ME */ Tarif962 = Tarif96 && (tm->tm_mon > 5); /* Andreas, warum ist diese Abfrage hier drin, warum soll das nicht moeglich sein? */ if (cur_call.duration > 172800.0) /* laenger als 2 Tage? Das KANN nicht sein! */ cur_call.duration = 0; set_alias(&cur_call,nx,myname); strcpy(s1, ctime(&cur_call.t)); if ((p = strchr(s1, '\n'))) *p = 0; if (day != lday) { *(s1 + 10) = 0; if (header) print_header(lday,s1,&day_sum,&day_com_sum,&all_sum,&day_com_sum); lday = day; if (!*start) { sprintf(start, "%s %s", s1, s1 + 20); sprintf(stop, "%s %s", s1, s1 + 20); } else sprintf(stop, "%s %s", s1, s1 + 20); } /* if */ if (!currency_factor) #ifdef ISDN_NL einheit = 0.0011; /* cost of one second local tariff during office hours */ #elif defined(ISDN_CH) einheit = 0.01; #else einheit = Tarif96 ? 0.12 : 0.23; #endif else einheit = currency_factor; print_entries(&cur_call,&day_sum,&day_com_sum,einheit,Tarif96,nx,myname); } /* while */ fclose(fi); if (delentries) /* Erzeugt neue verkuerzte Datei */ lday = -1; if (lday != -1) { if (timearea) { strich(1); print_sum_calls(&day_sum,0); if (day_com_sum.eh) { print_sum_calls(&day_com_sum,1); clear_sum(&tmp_sum); add_sum_calls(&tmp_sum,&day_sum); add_sum_calls(&tmp_sum,&day_com_sum); strich(1); print_sum_calls(&tmp_sum,0); } else print_msg(PRT_NORMAL,"\n"); } /* if */ add_sum_calls(&all_sum,&day_sum); add_sum_calls(&all_com_sum,&day_com_sum); strich(2); print_sum_calls(&all_sum,0); if (all_com_sum.eh) { print_sum_calls(&all_com_sum,1); clear_sum(&tmp_sum); add_sum_calls(&tmp_sum,&all_sum); add_sum_calls(&tmp_sum,&all_com_sum); strich(2); print_sum_calls(&tmp_sum,0); } else print_msg(PRT_NORMAL,"\n"); if (!incomingonly) { if (timearea) print_msg(PRT_NORMAL,"\nDIALOUT Summary for %s .. %s\n", start, stop); else print_msg(PRT_NORMAL,"\nDIALOUT Summary for %s\n", start); strich(3); for (i = mymsns; i < knowns; i++) { if (known[i]->usage[DIALOUT]) { print_msg(PRT_NORMAL,"%-14s %4d call(s) %s %s\n", !numbers?known[i]->who:known[i]->num, known[i]->usage[DIALOUT], double2clock(known[i]->dur[DIALOUT]), print_currency(known[i]->eh,known[i]->dm,7)); } /* if */ } /* for */ if (restusage) { print_msg(PRT_NORMAL,"%-14s %4d call(s) %s %s\n", S_UNKNOWN, restusage, double2clock(restdur), print_currency(resteh,restdm,7)); } /* if */ print_msg(PRT_NORMAL,"\n"); } if (!outgoingonly) { if (timearea) print_msg(PRT_NORMAL,"\nDIALIN Summary for %s .. %s\n", start, stop); else print_msg(PRT_NORMAL,"\nDIALIN Summary for %s\n", start); strich(3); for (i = mymsns; i < knowns; i++) { if (known[i]->usage[DIALIN]) { print_msg(PRT_NORMAL,"%-14s %4d call(s) %s\n", !numbers?known[i]->who:known[i]->num, known[i]->usage[DIALIN], double2clock(known[i]->dur[CALLED])); } /* if */ } /* for */ if (restiusage) { print_msg(PRT_NORMAL,"%-14s %4d call(s) %s\n", S_UNKNOWN, restiusage, double2clock(restidur)); } /* if */ print_msg(PRT_NORMAL,"\n\n"); } for (i = 1; i < MAXZONES; i++) if (zones[i]) { p = ""; switch (i) { case 1 : p = "City"; break; case 2 : p = "Region 50"; break; case 3 : p = "Region 200"; break; case 4 : p = "Fernzone"; break; } /* switch */ print_msg(PRT_NORMAL,"Zone %d : %-15s %4d call(s) %s %s\n", i, p, zones_usage[i], double2clock(zones_dur[i]), print_currency(zones[i],zones_dm[i],7)); } /* if */ if (resteh) { print_msg(PRT_NORMAL,"Zone x : %-15s %4d call(s) %s %s\n", S_UNKNOWN, restusage, double2clock(restdur), #ifdef ISDN_NL print_currency(resteh, resteh * einheit + restusage * 0.0825,7)); #else print_currency(resteh, resteh * einheit, 7)); #endif } if (unknowns) { print_msg(PRT_NORMAL,"\n\nUnknown caller(s)\n"); strich(3); for (i = 0; i < unknowns; i++) { print_msg(PRT_NORMAL,"%s %-14s ", unknown[i].called ? "called by" : " calling", unknown[i].num); for (k = 0; k < unknown[i].connects; k++) { strcpy(s1, ctime(&unknown[i].connect[k])); if ((p = strchr(s1, '\n'))) *p = 0; *(s1 + 19) = 0; if (k && (k + 1) % 2) { print_msg(PRT_NORMAL,"\n\t\t\t "); } /* if */ print_msg(PRT_NORMAL,"%s%s", k & 1 ? ", " : "", s1 + 4); } /* for */ print_msg(PRT_NORMAL,"\n"); } /* for */ } /* if */ } /* if */ if (delentries) /* Erzeugt neue verkuerzte Datei */ { fclose(ftmp); if ((ftmp = fopen(tmpfile, "r")) == (FILE *)NULL) { print_msg(PRT_ERR, msg1, tmpfile, strerror(errno)); return -1; } if ((fi = fopen(lfnam, "w")) == (FILE *)NULL) { print_msg(PRT_ERR, msg1, lfnam, strerror(errno)); return -1; } while (fgets(s, BUFSIZ, ftmp)) fputs(s,fi); fclose(fi); fclose(ftmp); unlink(tmpfile); } return 0; } /* read_logfile */ /*****************************************************************************/ static int print_entries(one_call *cur_call, sum_calls *day_sum, sum_calls *day_com_sum, double unit, int Tarif96, int *nx, char *myname) { auto time_t t1, t2; auto double takt; auto int computed = 0, go, zone = 1, zeit = -1; char time_string[SHORT_STRING_SIZE]; auto struct tm *tm; tm = localtime(&cur_call->t); strftime(time_string,SHORT_STRING_SIZE,"%X",tm); print_msg(PRT_NORMAL," %s %s", time_string, double2clock(cur_call->duration)); if (cur_call->dir) print_msg(PRT_NORMAL," %14s <- %-14s", cur_call->num[CALLED], cur_call->num[CALLING]); else print_msg(PRT_NORMAL," %14s -> %-14s", cur_call->num[CALLING], cur_call->num[CALLED]); if (cur_call->pay && !cur_call->eh) /* Falls Betrag vorhanden und Einheiten nicht, Einheiten berechnen */ cur_call->eh = cur_call->pay/unit; else if (cur_call->currency_factor && cur_call->currency_factor != unit && cur_call->eh>0 ) /* Falls Einheiten sich auf anderen Einheiten-Faktor beziehen, Einheiten korrigieren */ cur_call->eh /= unit / cur_call->currency_factor; #if 0 if (compute && !currency_factor && !cur_call->dir && ((cur_call->eh == -1) || (!cur_call->eh && cur_call->duration && cur_call->cause == -1))) { /* DIALOUT, keine AOCE Meldung */ #else go = 0; if ((cur_call->eh == -1) && !cur_call->dir) { /* Rauswahl, Gebuehr unbekannt */ if (nx[1] == -1) { /* Gegner unbekannt! */ if (compute) { zone = compute; /* in "-c x" Zone vermuten */ go = 1; } else { /* mit 0 DM berechnen */ cur_call->eh = 0; go = 0; } /* else */ } else { go = 1; if (!(zone = known[nx[1]]->zone)) go = cur_call->eh = 0; } /* else */ } /* if */ if (go) { #endif t1 = cur_call->t; t2 = cur_call->t + cur_call->duration; cur_call->eh = takt = 0; computed = 1; while (t1 < t2) { if (Tarif96) takt = cheap96((time_t)t1, zone, &zeit); else takt = cheap((time_t)t1, zone); if (!takt) { print_msg(PRT_ERR, "%s: OOPS! Abbruch: Zeittakt==0 ???\n", myname); break; } /* if */ cur_call->eh++; t1 += takt; } /* while */ } /* if */ if (cur_call->duration || (cur_call->eh > 0)) { add_one_call(computed?day_com_sum:day_sum,cur_call,unit); if (cur_call->dir) { if (nx[CALLING] == -1) { restiusage++; if (cur_call->duration > 0) restidur += cur_call->duration; } /* if */ } else { if (nx[CALLED] == -1) { resteh += cur_call->eh; restdm += cur_call->dm; restusage++; if (cur_call->duration > 0) restdur += cur_call->duration; } else { known[nx[CALLED]]->eh += cur_call->eh; known[nx[CALLED]]->dm += cur_call->dm; zones[known[nx[CALLED]]->zone] += cur_call->eh; zones_dm[known[nx[CALLED]]->zone] += cur_call->dm; if (cur_call->duration > 0) zones_dur[known[nx[CALLED]]->zone] += cur_call->duration; zones_usage[known[nx[CALLED]]->zone]++; } /* if */ print_msg(PRT_NORMAL," %s", print_currency(cur_call->eh,cur_call->dm,4)); if (computed) print_msg(PRT_NORMAL," *"); } /* else */ } else { if (cur_call->cause != -1) { print_msg(PRT_NORMAL," %s", qmsg(TYPE_CAUSE, VERSION_EDSS1, cur_call->cause)); day_sum->err++; } } /* else */ print_msg(PRT_NORMAL, " %*s", cur_call->dir ? 21 : 0, ""); if (cur_call->ibytes) print_msg(PRT_NORMAL, " I=%s kB", double2str((double)cur_call->ibytes / 1024.0, 10, 2, 0)); if (cur_call->obytes) print_msg(PRT_NORMAL, " O=%s kB", double2str((double)cur_call->obytes / 1024.0, 10, 2, 0)); print_msg(PRT_NORMAL,"\n"); return 0; } /*****************************************************************************/ static int print_header(int lday, char *time_string, sum_calls *day_sum, sum_calls *day_com_sum,sum_calls *all_sum, sum_calls *all_com_sum ) { sum_calls tmp_sum; time_t now; if (lday == -1) { time(&now); print_msg(PRT_NORMAL,"I S D N Connection Report - %s", ctime(&now)); } else { strich(1); print_sum_calls(day_sum,0); if (day_com_sum->eh) { print_sum_calls(day_com_sum,1); clear_sum(&tmp_sum); add_sum_calls(&tmp_sum,day_sum); add_sum_calls(&tmp_sum,day_com_sum); strich(1); print_sum_calls(&tmp_sum,0); } else print_msg(PRT_NORMAL,"\n"); add_sum_calls(all_sum,day_sum); clear_sum(day_sum); add_sum_calls(all_com_sum,day_com_sum); clear_sum(day_com_sum); } /* if */ print_msg(PRT_NORMAL,"\n\n%s %s\n", time_string, time_string + 20); return 0; } /*****************************************************************************/ static int set_alias(one_call *cur_call, int *nx, char *myname) { auto int n, cc, i, j; auto int hit; for (n = CALLING; n <= CALLED; n++) { nx[n] = -1; hit = 0; if (!*(cur_call->num[n])) { if (!numbers) { cur_call->num[n][0] = C_UNKNOWN; cur_call->num[n][1] = '\0'; } /* Wenn keine Nummer, dann Name "UNKNOWN" */ hit++; } else { /* In der folg. Schleife werden Nummern durch Namen ersetzt */ cc = 0; for (j = 0; ((j < 2) && !cc); j++) { for (i = 0; i < knowns; i++) { if (cur_call->version[0] != '\0') { if (!strcmp(cur_call->version,LOG_VERSION_2) || !strcmp(cur_call->version,LOG_VERSION_3) ) cc = ((known[i]->si == cur_call->si) || j) && !n_match(known[i]->num, cur_call->num[n], cur_call->version); } else { if (*cur_call->num[n] != '0') { /* Alte Syntax der "isdn.log" : Ohne vorlaufene "0" */ cc = ((known[i]->si == cur_call->si) || j) && !match(known[i]->num+1, cur_call->num[n], 0); if (!cc) { /* Ganz alte Syntax der "isdn.log" : Ohne Vorwahl */ cc = ((known[i]->si == cur_call->si) || j) && !n_match(known[i]->num, cur_call->num[n], LOG_VERSION_1); } /* if */ } } if (cc) { if (!numbers) strcpy(cur_call->num[n], known[i]->who); nx[n] = i; known[i]->usage[cur_call->dir]++; /* Gesamte Anrufe auf gleiche Nummern werden gezeahlt */ known[i]->dur[cur_call->dir] += cur_call->duration; /* Gesamte Gespraechsdauer auf gleiche Nummern wird gezeahlt */ hit++; break; } /* if */ } /* for */ } /* for */ /* In der naechsten Schleife werden die unbekannten Nummern registriert */ if (!hit) { for (i = 0; i < unknowns; i++) if (!strcmp(unknown[i].num, cur_call->num[n])) { hit++; break; } /* if */ strcpy(unknown[i].num, cur_call->num[n]); unknown[i].called = !n; unknown[i].connect[unknown[i].connects] = cur_call->t; /* ACHTUNG: MAXCONNECTS und MAXUNKNOWN sollten unbedingt groesser sein ! */ if (unknown[i].connects + 1 < MAXCONNECTS) unknown[i].connects++; else print_msg(PRT_ERR, "%s: WARNING: Too many unknown connection's from %s\n", myname, unknown[i].num); if (!hit) { if (unknowns < MAXUNKNOWN) unknowns++; else print_msg(PRT_ERR, "%s: WARNING: Too many unknown number's\n", myname); } /* if */ } /* if */ } /* else */ } /* for */ return 0; } /*****************************************************************************/ static int set_caller_infos(one_call *cur_call, char *string) { register int i = 0; auto char **array; auto char *ptr; if ((ptr = strrchr(string,C_DELIM)) != NULL) *ptr = '\0'; if ((array = String_to_Array(string,C_DELIM)) == NULL) { print_msg(PRT_ERR,"Can not allocate memory!\n"); return -1; } if (array[0] == NULL) { del_Array(array); return -1; } cur_call->eh = 0; cur_call->dir = -1; cur_call->cause = -1; cur_call->ibytes = cur_call->obytes = 0L; cur_call->dm = 0.0; cur_call->version[0] = '\0'; cur_call->pay = 0.0; cur_call->si = cur_call->si1 = 0; cur_call->dir = DIALOUT; for (i = 1; array[i] != NULL; i++) { switch (i) { case 0 : cur_call->t = atom(array[i]); break; case 1 : strcpy(cur_call->num[0], Kill_Blanks(array[i])); break; case 2 : strcpy(cur_call->num[1], Kill_Blanks(array[i])); break; case 3 : cur_call->duration = (double)atoi(array[i]); break; case 4 : cur_call->duration = atoi(array[i]) / 100.0; break; case 5 : cur_call->t = atol(array[i]); break; case 6 : cur_call->eh = atoi(array[i]); break; case 7 : cur_call->dir = (*array[i] == 'I') ? DIALIN : DIALOUT; break; case 8 : cur_call->cause = atoi(array[i]); break; case 9 : cur_call->ibytes = atol(array[i]); break; case 10: cur_call->obytes = atol(array[i]); break; case 11: strcpy(cur_call->version,array[i]); break; case 12: cur_call->si = atoi(array[i]); break; case 13: cur_call->si1 = atoi(array[i]); break; case 14: cur_call->currency_factor = atoi(array[i]); break; case 15: strncpy(cur_call->currency, array[i], 3); break; case 16: cur_call->pay = atof(array[i]); break; default : print_msg(PRT_ERR,"Unknown element found `%s'!\n",array[i]); break; } } if (i < 3) return -1; return 0; } /*****************************************************************************/ int get_term (char *String, time_t *Begin, time_t *End,int delentries) { time_t now; time_t Date[2]; int Cnt; char DateStr[2][256] = {"",""}; time(&now); if (String[0] == '-') strcpy(DateStr[1],String+1); else if (String[strlen(String)-1] == '-') { strcpy(DateStr[0],String); DateStr[0][strlen(String)-1] ='\0'; } else if (strchr(String,'-')) { if (sscanf(String,"%[/.0-9]-%[/.0-9]",DateStr[0],DateStr[1]) != 2) return 0; } else { strcpy(DateStr[0],String); strcpy(DateStr[1],String); } for (Cnt = 0; Cnt < 2; Cnt++) { if (strchr(DateStr[Cnt],'/')) Date[Cnt] = get_month(DateStr[Cnt],delentries?0:Cnt); else Date[Cnt] = get_time(DateStr[Cnt],delentries?0:Cnt); } *Begin = DateStr[0][0] == '\0' ? 0 : Date[0]; *End = DateStr[1][0] == '\0' ? now : Date[1]; return 1; } /*****************************************************************************/ static time_t get_month(char *String, int TimeStatus) { time_t now; int Cnt = 0; struct tm *TimeStruct; int Args[3]; int ArgCnt; time(&now); TimeStruct = localtime(&now); TimeStruct->tm_sec = 0; TimeStruct->tm_min = 0; TimeStruct->tm_hour= 0; TimeStruct->tm_mday= 1; TimeStruct->tm_isdst= -1; ArgCnt = sscanf(String,"%d/%d/%d",&(Args[0]),&(Args[1]),&(Args[2])); switch (ArgCnt) { case 3: TimeStruct->tm_mday = Args[0]; Cnt++; case 2: if (Args[Cnt+1] > 99) TimeStruct->tm_year = ((Args[Cnt+1] / 100) - 19) * 100 + (Args[Cnt+1]%100); else TimeStruct->tm_year = Args[Cnt+1]; case 1: TimeStruct->tm_mon = Args[Cnt]; break; default: return 0; } if (TimeStatus == END_TIME) { if (ArgCnt == 3) /* Wenn Tag angegeben ist */ { TimeStruct->tm_mday++; TimeStruct->tm_mon--; } } else TimeStruct->tm_mon--; return mktime(TimeStruct); } /*****************************************************************************/ static time_t get_time(char *String, int TimeStatus) { time_t now; int Len = 0; int Year; char *Ptr; struct tm *TimeStruct; time(&now); TimeStruct = localtime(&now); TimeStruct->tm_sec = 0; TimeStruct->tm_min = 0; TimeStruct->tm_hour= 0; TimeStruct->tm_isdst= -1; switch (strlen(String)) { case 0: return 0; case 1: case 2: TimeStruct->tm_mday = atoi(String); break; default: Len = strlen(String); if ((Ptr = strchr(String,'.')) != NULL) { TimeStruct->tm_sec = atoi(Ptr+1); Len -= strlen(Ptr); } if (Len % 2) return 0; if (sscanf(String,"%2d%2d%2d%2d%d", &(TimeStruct->tm_mon), &(TimeStruct->tm_mday), &(TimeStruct->tm_hour), &(TimeStruct->tm_min), &Year ) > 4) if (Year > 99) TimeStruct->tm_year = ((Year / 100) - 19) * 100 + (Year%100); else TimeStruct->tm_year = Year; TimeStruct->tm_mon--; break; } if (TimeStatus == END_TIME) if (TimeStruct->tm_sec == 0 && TimeStruct->tm_min == 0 && TimeStruct->tm_hour== 0 ) TimeStruct->tm_mday++; else if (TimeStruct->tm_sec == 0 && TimeStruct->tm_min == 0 ) TimeStruct->tm_hour++; else if (TimeStruct->tm_sec == 0 ) TimeStruct->tm_min++; else TimeStruct->tm_sec++; return mktime(TimeStruct); } /*****************************************************************************/ int set_msnlist(char *String) { int Cnt; int Value = 1; char *Ptr = String; if (ShowMSN) return 0; while((Ptr = strchr(Ptr,',')) != NULL) { Ptr++; Value++; } ShowMSN = (char**) calloc(Value+1,sizeof(char*)); for(Cnt = 0; Cnt < Value; Cnt++) ShowMSN[Cnt] = (char*) calloc(NUMSIZE,sizeof(char)); if (!ShowMSN) { print_msg(PRT_ERR, nomemory); exit(1); } if (*String == 'n') { ++String; invertnumbers++; } Cnt = 0; while(String) { if (*String == 'm') { Value = atoi(++String); if (Value > 0 && Value <= mymsns) { strcpy(ShowMSN[Cnt],known[Value-1]->num); Cnt++; } else { print_msg(PRT_ERR,"Invalid MSN %d!\n",Cnt); } } else sscanf(String,"%[^,],",ShowMSN[Cnt++]); String = strchr(String,','); if (String) String++; } return 0; } /*****************************************************************************/ static int show_msn(one_call *cur_call) { int Cnt; for(Cnt = 0; ShowMSN[Cnt] != NULL; Cnt++) if (!num_match(ShowMSN[Cnt], cur_call->num[0]) || !num_match(ShowMSN[Cnt] , cur_call->num[1])) return !invertnumbers; else if (!strcmp(ShowMSN[Cnt],"0")) return !invertnumbers; return invertnumbers; } /*****************************************************************************/ static char *print_currency(int units, double money, int Format) { static char RetCode[256]; if (!currency_factor) sprintf(RetCode,"%*d EH %s DM",Format,units,double2str(money,8,2,0)); else sprintf(RetCode,"%.*s %s %s",Format," ", double2str(money,8,2,0),currency); return RetCode; } /*****************************************************************************/ static int print_sum_calls(sum_calls *s, int computed) { static char String[256]; if (!computed) sprintf(String,"%3d IN=%s, %3d OUT=%s, %3d failed %s I=%s kB O=%s kB\n", s->in, double2clock(s->din), s->out, double2clock(s->dout), s->err, print_currency(s->eh,s->dm,7), double2str((double)s->ibytes / 1024.0, 10, 2, 0), double2str((double)s->obytes / 1024.0, 10, 2, 0)); else sprintf(String," %3d OUT=%s, %s *\n", s->out, double2clock(s->dout), print_currency(s->eh,s->dm,7)); return print_msg(PRT_NORMAL,String); } /*****************************************************************************/ static int add_one_call(sum_calls *s1, one_call *s2, double units) { if (s2->dir == DIALIN) { s1->in++; s1->din += s2->duration > 0?s2->duration:0; } else { s2->dm = s2->eh * units; s1->out++; s1->dout += s2->duration > 0?s2->duration:0; s1->eh += s2->eh; s1->dm += s2->dm; } s1->ibytes += s2->ibytes; s1->obytes += s2->obytes; #ifdef ISDN_NL s1->dm += 0.0825; /* add call setup charge */ s2->dm += 0.0825; #endif return 0; } /*****************************************************************************/ static int clear_sum(sum_calls *s1) { s1->in = 0; s1->out = 0; s1->eh = 0; s1->err = 0; s1->din = 0; s1->dout = 0; s1->dm = 0; s1->ibytes = 0L; s1->obytes = 0L; return 0; } /*****************************************************************************/ static int add_sum_calls(sum_calls *s1, sum_calls *s2) { s1->in += s2->in; s1->out += s2->out; s1->eh += s2->eh; s1->err += s2->err; s1->din += s2->din; s1->dout += s2->dout; s1->dm += s2->dm; s1->ibytes += s2->ibytes; s1->obytes += s2->obytes; return 0; } /*****************************************************************************/ static void strich(int type) { switch (type) { case 1 : print_msg(PRT_NORMAL,"----------------------------------------------------------------------------------------\n"); break; case 2 : print_msg(PRT_NORMAL,"========================================================================================\n"); break; case 3 : print_msg(PRT_NORMAL,"------------------------------------------------------------\n"); break; } /* switch */ } /* strich */ /*****************************************************************************/ static int n_match(char *Pattern, char* Number, char* version) { int RetCode = -1; char s[SHORT_STRING_SIZE]; if (!strcmp(version,LOG_VERSION_3)) { RetCode = num_match(Pattern,Number); } else if (!strcmp(version,LOG_VERSION_2)) { strcpy(s,expand_number(Number)); RetCode = num_match(Pattern,s); } else if (!strcmp(version,LOG_VERSION_1)) { if ((RetCode = match(Pattern, Number,0)) != 0 && !strncmp(Pattern,S_AREA_PREFIX,strlen(S_AREA_PREFIX)) ) { sprintf(s,"*%s%s",myarea/*+strlen(S_AREA_PREFIX)*/,Pattern); RetCode = match(s,Number,0); } } else print_msg(PRT_ERR,"Unknown Version of logfile entries!\n"); return RetCode; } /*****************************************************************************/