Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / i4b / isdnd / rates.c
1 /*
2  *   Copyright (c) 1997 Gary Jennejohn. All rights reserved.
3  * 
4  *   Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *   1. Redistributions of source code must retain the above copyright
11  *      notice, this list of conditions and the following disclaimer.
12  *   2. Redistributions in binary form must reproduce the above copyright
13  *      notice, this list of conditions and the following disclaimer in the
14  *      documentation and/or other materials provided with the distribution.
15  *   3. Neither the name of the author nor the names of any co-contributors
16  *      may be used to endorse or promote products derived from this software
17  *      without specific prior written permission.
18  *   4. Altered versions must be plainly marked as such, and must not be
19  *      misrepresented as being the original software and/or documentation.
20  *   
21  *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  *   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  *   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  *   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  *   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  *   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  *   SUCH DAMAGE.
32  *
33  *---------------------------------------------------------------------------
34  *
35  *      i4b daemon - charging rates description file handling
36  *      -----------------------------------------------------
37  *
38  *      $Id: rates.c,v 1.11 2000/10/09 12:53:29 hm Exp $ 
39  *
40  * $FreeBSD: src/usr.sbin/i4b/isdnd/rates.c,v 1.6.2.2 2001/08/01 17:45:03 obrien Exp $
41  * $DragonFly: src/usr.sbin/i4b/isdnd/rates.c,v 1.2 2003/06/17 04:29:54 dillon Exp $
42  *
43  *      last edit-date: [Mon Dec 13 21:48:31 1999]
44  *
45  *---------------------------------------------------------------------------*/
46
47 static char error[256];
48
49 static int getrate(int rate_type);
50
51 #ifdef PARSE_DEBUG_MAIN
52
53 #include <stdio.h>
54
55 #define MAIN
56
57 #define ERROR (-1)
58
59 extern int got_rate;
60
61 int main( int argc, char **argv )
62 {
63         int ret;
64         ret = readrates("/etc/isdn/isdnd.rates");
65         if(ret == ERROR)
66                 fprintf(stderr, "readrates returns [%d], [%s]\n", ret, error);
67         else
68                 {
69                 int type = 0;
70
71                 got_rate = 1;
72
73                 fprintf(stderr, "readrates returns [%d]\n", ret);
74
75                 for( type=0; type<4; type++ )
76                         {
77                         int unit = getrate( type );
78                         fprintf(stderr, "getrate(%d) => %d\n", type, unit );
79                         }
80                 }
81
82         return(ret);
83 }
84
85 #endif
86
87 #include "isdnd.h"
88
89 /*---------------------------------------------------------------------------*
90  *      parse rates file
91  *---------------------------------------------------------------------------*/
92 int
93 readrates(char *filename)
94 {
95         char buffer[MAXPATHLEN];
96         register char *bp;
97         struct rates *rt, *ort;
98         int rateindx;
99         int indx;
100         int line = 0;
101         FILE *fp;
102         int first;
103 #if DEBUG
104         int i, j;
105 #endif
106         
107         indx = 0;
108         rt = ort = NULL;
109
110         if((fp = fopen(filename, "r")) == NULL)
111         {
112                 snprintf(error, sizeof(error), "error open %s: %s", filename, sys_errlist[errno]);
113                 rate_error = error;
114                 return(WARNING);
115         }
116
117         while((fgets(buffer, MAXPATHLEN, fp)) != NULL)
118         {
119                 line++;
120
121 /* comments */
122                 if(buffer[0] == '#'  || buffer[0] == ' ' ||
123                    buffer[0] == '\t' || buffer[0] == '\n')
124                 {
125                         continue;
126                 }
127
128                 bp = &buffer[0];
129
130                 /* rate type */
131
132                 if (*bp == 'r' && *(bp+1) == 'a' && isdigit(*(bp+2)))
133                 {
134                                 rateindx = *(bp+2) - '0';
135                                 bp += 3;
136
137                                 /* eat space delimiter */
138
139                                 while(isspace(*bp))
140                                         bp++;
141                 }
142                 else
143                 {
144                         snprintf(error, sizeof(error), "rates: invalid rate type %c%c%c in line %d", *bp, *(bp+1), *(bp+2), line);
145                         goto rate_error;
146                 }
147                 if (rateindx >= NRATES)
148                 {
149                         snprintf(error, sizeof(error), "rates: invalid rate index %d in line %d", rateindx, line);
150                         goto rate_error;
151                 }
152
153                 /* day */
154                 
155                 if(isdigit(*bp) && *bp >= '0' && *bp <= '6')
156                 {
157                         indx = *bp - '0';
158
159                         DBGL(DL_RATES, (log(LL_DBG, "rates: index = %d", indx)));
160                 }
161                 else
162                 {
163                         snprintf(error, sizeof(error), "rates: invalid day digit %c in line %d", *bp, line);
164                         goto rate_error;
165                 }
166
167                 if(rates[rateindx][indx] == NULL)
168                 {
169                         rt = (struct rates *)malloc(sizeof (struct rates));
170                         if (rt == NULL)
171                         {
172                                 snprintf(error, sizeof(error), "rates: cannot malloc space for rate structure");
173                                 goto rate_error;
174                         }
175                         rt->next = NULL;
176                         rates[rateindx][indx] = rt;
177                 }
178
179                 bp++;
180                 
181                 /* eat space delimiter */
182
183                 while(isspace(*bp))
184                         bp++;
185
186                 /* now loop to get the rates entries */
187
188                 first = 1;
189                 
190                 while(*bp && isdigit(*bp))
191                 {
192                         int hour = 0;
193                         int min = 0;
194
195                         if(first)
196                         {
197                                 first = 0;
198                         }
199                         else
200                         {
201                                 ort = rt;
202         
203                                 rt = (struct rates *)malloc(sizeof (struct rates));
204                                 if (rt == NULL)
205                                 {
206                                         snprintf(error, sizeof(error), "rates: cannot malloc space2 for rate structure");
207                                         goto rate_error;
208                                 }
209                                 ort->next = rt;
210                                 rt->next = NULL;
211                         }
212                         
213                         /* start hour */
214                         
215                         if(isdigit(*bp) && isdigit(*(bp+1)))
216                         {
217                                 hour = atoi(bp);
218                                 bp += 2;
219                         }
220                         else
221                         {
222                                 snprintf(error, sizeof(error), "rates: start_hr error in line %d", line);
223                                 goto rate_error;
224                         }
225
226                         /* point */
227                         
228                         if(*bp == '.')
229                         {
230                                 bp++;
231                         }
232                         else
233                         {
234                                 snprintf(error, sizeof(error), "rates: no '.' after start_hr in line %d", line);
235                                 goto rate_error;
236                         }
237                         
238                         /* start minute */
239                         
240                         if(isdigit(*bp) && isdigit(*(bp+1)))
241                         {
242                                 min = atoi(bp);
243                                 bp += 2;
244                         }
245                         else
246                         {
247                                 snprintf(error, sizeof(error), "rates: start_min error in line %d", line);
248                                 goto rate_error;
249                         }
250
251                         rt->start_time = hour*60 + min;
252
253                         /* minus */
254                         
255                         if(*bp == '-')
256                         {
257                                 bp++;
258                         }
259                         else
260                         {
261                                 snprintf(error, sizeof(error), "rates: no '-' after start_min in line %d", line);
262                                 goto rate_error;
263                         }
264
265                         /* end hour */
266                         
267                         if(isdigit(*bp) && isdigit(*(bp+1)))
268                         {
269                                 hour = atoi(bp);
270                                 bp += 2;
271                         }
272                         else
273                         {
274                                 snprintf(error, sizeof(error), "rates: end_hr error in line %d", line);
275                                 goto rate_error;
276                         }
277
278                         /* point */
279                         
280                         if(*bp == '.')
281                         {
282                                 bp++;
283                         }
284                         else
285                         {
286                                 snprintf(error, sizeof(error), "rates: no '.' after end_hr in line %d", line);
287                                 goto rate_error;
288                         }
289                         
290                         /* end minute */
291                         
292                         if(isdigit(*bp) && isdigit(*(bp+1)))
293                         {
294                                 min = atoi(bp);
295                                 bp += 2;
296                         }
297                         else
298                         {
299                                 snprintf(error, sizeof(error), "rates: end_min error in line %d", line);
300                                 goto rate_error;
301                         }
302
303                         /* if hour is 0 assume it means midnight */
304                         if( hour == 0 )
305                                 hour = 24;
306                         rt->end_time = hour * 60 + min;
307
308                         if( rt->end_time <= rt->start_time )
309                                 {
310                                 snprintf(error, sizeof(error), "rates: end_time must be greater then start_time %d", line);
311                                 goto rate_error;
312                                 }
313
314                         /* colon */
315                         
316                         if(*bp == ':')
317                         {
318                                 bp++;
319                         }
320                         else
321                         {
322                                 snprintf(error, sizeof(error), "rates: no ':' after end_min in line %d", line);
323                                 goto rate_error;
324                         }
325
326                         /* time */
327                         
328                         if(isdigit(*bp))
329                         {
330                                 rt->rate = atoi(bp);
331                                 while(!isspace(*bp))
332                                         bp++;
333                         }
334                         else
335                         {
336                                 snprintf(error, sizeof(error), "rates: first rate digit error in line %d", line);
337                                 goto rate_error;
338                         }
339
340                         /* eat space delimiter */
341
342                         while(isspace(*bp))
343                                 bp++;
344                 }
345         }
346
347 #if DEBUG
348         if(debug_flags & DL_RATES)
349         {
350                 for (j = 0; j < NRATES; j++)
351                 {
352                         for (i = 0; i < NDAYS; i++)
353                         {
354                                 if (rates [j][i] != NULL)
355                                 {
356                                         rt = rates [j][i];
357                                         for (; rt; rt = rt->next)
358                                         {
359                                                 log(LL_DBG, "rates: index %d day %d = %d.%2.2d-%d.%2.2d:%d",
360                                                         j, i, rt->start_time/60, rt->start_time%60,
361                                                         rt->end_time/60,rt->end_time%60,rt->rate);
362                                         }
363                                 }
364                                 else
365                                 {
366                                         log(LL_DBG, "rates: NO entry for day %d !!\n", i);
367                                 }
368                         }
369                 }
370         }
371 #endif
372         fclose(fp);
373         return(GOOD);
374
375 rate_error:
376         fclose(fp);
377         rate_error = error;
378         return(ERROR);
379 }
380
381 #ifndef PARSE_DEBUG_MAIN
382
383 /*---------------------------------------------------------------------------*
384  *      get unit length time from configured source
385  *---------------------------------------------------------------------------*/
386 int
387 get_current_rate(cfg_entry_t *cep, int logit)
388 {
389         int rt;
390         
391         switch(cep->unitlengthsrc)
392         {
393                 case ULSRC_CMDL:        /* specified on commandline     */
394                         if(logit)
395                                 log(LL_CHD, "%05d %s rate %d sec/unit (cmdl)",
396                                         cep->cdid, cep->name, unit_length);
397                         return(unit_length);
398                         break;
399
400                 case ULSRC_CONF:        /* get it from config file      */
401                         if(logit)
402                                 log(LL_CHD, "%05d %s rate %d sec/unit (conf)",
403                                         cep->cdid, cep->name, cep->unitlength);
404                         return(cep->unitlength);
405
406                 case ULSRC_RATE:        /* get it dynamic from ratesfile*/
407                         if(!got_rate)   /* got valid rates struct ?? */
408                         {
409                                 if(logit)
410                                         log(LL_CHD, "%05d %s rate %d sec/unit (no ratefile)",
411                                                 cep->cdid, cep->name, UNITLENGTH_DEFAULT);
412                                 return(UNITLENGTH_DEFAULT);
413                         }
414                         if((cep->ratetype >= NRATES) ||
415                            (cep->ratetype == INVALID_RATE))
416                         {
417                                 if(logit)
418                                         log(LL_CHD, "%05d %s rate %d sec/unit (rate out of range)",
419                                                 cep->cdid, cep->name, UNITLENGTH_DEFAULT);
420                                 return(UNITLENGTH_DEFAULT);
421                         }
422                         
423                         if((rt = getrate(cep->ratetype)) != -1)
424                         {
425                                 if(logit)
426                                         log(LL_CHD, "%05d %s rate %d sec/unit (rate)",
427                                                 cep->cdid, cep->name, rt);
428                                 return(rt);
429                         }
430
431                         if(logit)                       
432                                 log(LL_CHD, "%05d %s rate %d sec/unit (ratescan fail)",
433                                         cep->cdid, cep->name, UNITLENGTH_DEFAULT);
434
435                         return(UNITLENGTH_DEFAULT);
436                         break;
437
438                 case ULSRC_DYN: /* dynamically calculated from AOC */
439                         if((rt = getrate(cep->ratetype)) != -1)
440                         {
441                                 if(logit)
442                                         log(LL_CHD, "%05d %s rate %d sec/unit (aocd, rate)",
443                                                 cep->cdid, cep->name, rt);
444                                 return(rt);
445                         }
446                         if(logit)
447                                 log(LL_CHD, "%05d %s rate %d sec/unit (aocd, default)",
448                                         cep->cdid, cep->name, UNITLENGTH_DEFAULT);
449
450                         return(UNITLENGTH_DEFAULT);
451                         break;
452
453                 default:
454                         if(logit)
455                                 log(LL_CHD, "%05d %s rate %d sec/unit (unitlen unknown)",
456                                         cep->cdid, cep->name, UNITLENGTH_DEFAULT);
457
458                         return(UNITLENGTH_DEFAULT);
459                         break;
460         }
461 }
462 #endif /* PARSE_DEBUG_MAIN */
463
464
465 /*---------------------------------------------------------------------------*
466  *      get the currently active rate
467  *---------------------------------------------------------------------------*/
468 static int
469 getrate(int rate_type )
470 {
471         struct tm *ptr;
472         time_t now;
473         register struct rates *hd;
474         int time_now;
475
476         if((!got_rate) ||
477            (rate_type >= NRATES) ||
478            (rate_type == INVALID_RATE))
479         {
480                 return -1;
481         }
482
483         time(&now);                     /* get current time */
484
485         ptr = localtime(&now);
486
487         time_now = ptr->tm_hour*60 + ptr->tm_min;
488
489         /* walk thru the rates for weekday until rate for current time found */
490
491         for (hd = rates[rate_type][ptr->tm_wday]; hd; hd = hd->next)
492         {
493                 /* current time within window ? */
494                 if((time_now >= hd->start_time ) &&
495                    (time_now < hd->end_time ))
496                 {
497                         DBGL(DL_RATES, (log(LL_DBG, "rate=%d sec/unit (day=%d, beg=%d:%2.2d, end=%d:2.2d, current=%d:%2.2d)",
498                                 hd->rate,
499                                 ptr->tm_wday,
500                                 hd->start_time/60, hd->start_time%60,
501                                 hd->end_time/60, hd->end_time%60,
502                                 time_now/60, time_now%60)));
503                                 
504                         return hd->rate;
505                 }
506         }
507         return -1;
508 }
509
510 /* EOF */