binutils/ld: Don't add /usr/lib to the library search path twice.
[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.4 2004/03/26 00:30:12 cpressey 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
62 main(int argc, char **argv)
63 {
64         int ret;
65         ret = readrates("/etc/isdn/isdnd.rates");
66         if(ret == ERROR)
67                 fprintf(stderr, "readrates returns [%d], [%s]\n", ret, error);
68         else
69                 {
70                 int type = 0;
71
72                 got_rate = 1;
73
74                 fprintf(stderr, "readrates returns [%d]\n", ret);
75
76                 for( type=0; type<4; type++ )
77                         {
78                         int unit = getrate( type );
79                         fprintf(stderr, "getrate(%d) => %d\n", type, unit );
80                         }
81                 }
82
83         return(ret);
84 }
85
86 #endif
87
88 #include "isdnd.h"
89
90 /*---------------------------------------------------------------------------*
91  *      parse rates file
92  *---------------------------------------------------------------------------*/
93 int
94 readrates(char *filename)
95 {
96         char buffer[MAXPATHLEN];
97         char *bp;
98         struct rates *rt, *ort;
99         int rateindx;
100         int indx;
101         int line = 0;
102         FILE *fp;
103         int first;
104 #if DEBUG
105         int i, j;
106 #endif
107         
108         indx = 0;
109         rt = ort = NULL;
110
111         if((fp = fopen(filename, "r")) == NULL)
112         {
113                 snprintf(error, sizeof(error), "error open %s: %s", filename, sys_errlist[errno]);
114                 rate_error = error;
115                 return(WARNING);
116         }
117
118         while((fgets(buffer, MAXPATHLEN, fp)) != NULL)
119         {
120                 line++;
121
122 /* comments */
123                 if(buffer[0] == '#'  || buffer[0] == ' ' ||
124                    buffer[0] == '\t' || buffer[0] == '\n')
125                 {
126                         continue;
127                 }
128
129                 bp = &buffer[0];
130
131                 /* rate type */
132
133                 if (*bp == 'r' && *(bp+1) == 'a' && isdigit(*(bp+2)))
134                 {
135                                 rateindx = *(bp+2) - '0';
136                                 bp += 3;
137
138                                 /* eat space delimiter */
139
140                                 while(isspace(*bp))
141                                         bp++;
142                 }
143                 else
144                 {
145                         snprintf(error, sizeof(error), "rates: invalid rate type %c%c%c in line %d", *bp, *(bp+1), *(bp+2), line);
146                         goto rate_error;
147                 }
148                 if (rateindx >= NRATES)
149                 {
150                         snprintf(error, sizeof(error), "rates: invalid rate index %d in line %d", rateindx, line);
151                         goto rate_error;
152                 }
153
154                 /* day */
155                 
156                 if(isdigit(*bp) && *bp >= '0' && *bp <= '6')
157                 {
158                         indx = *bp - '0';
159
160                         DBGL(DL_RATES, (dolog(LL_DBG, "rates: index = %d", indx)));
161                 }
162                 else
163                 {
164                         snprintf(error, sizeof(error), "rates: invalid day digit %c in line %d", *bp, line);
165                         goto rate_error;
166                 }
167
168                 if(rates[rateindx][indx] == NULL)
169                 {
170                         rt = (struct rates *)malloc(sizeof (struct rates));
171                         if (rt == NULL)
172                         {
173                                 snprintf(error, sizeof(error), "rates: cannot malloc space for rate structure");
174                                 goto rate_error;
175                         }
176                         rt->next = NULL;
177                         rates[rateindx][indx] = rt;
178                 }
179
180                 bp++;
181                 
182                 /* eat space delimiter */
183
184                 while(isspace(*bp))
185                         bp++;
186
187                 /* now loop to get the rates entries */
188
189                 first = 1;
190                 
191                 while(*bp && isdigit(*bp))
192                 {
193                         int hour = 0;
194                         int min = 0;
195
196                         if(first)
197                         {
198                                 first = 0;
199                         }
200                         else
201                         {
202                                 ort = rt;
203         
204                                 rt = (struct rates *)malloc(sizeof (struct rates));
205                                 if (rt == NULL)
206                                 {
207                                         snprintf(error, sizeof(error), "rates: cannot malloc space2 for rate structure");
208                                         goto rate_error;
209                                 }
210                                 ort->next = rt;
211                                 rt->next = NULL;
212                         }
213                         
214                         /* start hour */
215                         
216                         if(isdigit(*bp) && isdigit(*(bp+1)))
217                         {
218                                 hour = atoi(bp);
219                                 bp += 2;
220                         }
221                         else
222                         {
223                                 snprintf(error, sizeof(error), "rates: start_hr error in line %d", line);
224                                 goto rate_error;
225                         }
226
227                         /* point */
228                         
229                         if(*bp == '.')
230                         {
231                                 bp++;
232                         }
233                         else
234                         {
235                                 snprintf(error, sizeof(error), "rates: no '.' after start_hr in line %d", line);
236                                 goto rate_error;
237                         }
238                         
239                         /* start minute */
240                         
241                         if(isdigit(*bp) && isdigit(*(bp+1)))
242                         {
243                                 min = atoi(bp);
244                                 bp += 2;
245                         }
246                         else
247                         {
248                                 snprintf(error, sizeof(error), "rates: start_min error in line %d", line);
249                                 goto rate_error;
250                         }
251
252                         rt->start_time = hour*60 + min;
253
254                         /* minus */
255                         
256                         if(*bp == '-')
257                         {
258                                 bp++;
259                         }
260                         else
261                         {
262                                 snprintf(error, sizeof(error), "rates: no '-' after start_min in line %d", line);
263                                 goto rate_error;
264                         }
265
266                         /* end hour */
267                         
268                         if(isdigit(*bp) && isdigit(*(bp+1)))
269                         {
270                                 hour = atoi(bp);
271                                 bp += 2;
272                         }
273                         else
274                         {
275                                 snprintf(error, sizeof(error), "rates: end_hr error in line %d", line);
276                                 goto rate_error;
277                         }
278
279                         /* point */
280                         
281                         if(*bp == '.')
282                         {
283                                 bp++;
284                         }
285                         else
286                         {
287                                 snprintf(error, sizeof(error), "rates: no '.' after end_hr in line %d", line);
288                                 goto rate_error;
289                         }
290                         
291                         /* end minute */
292                         
293                         if(isdigit(*bp) && isdigit(*(bp+1)))
294                         {
295                                 min = atoi(bp);
296                                 bp += 2;
297                         }
298                         else
299                         {
300                                 snprintf(error, sizeof(error), "rates: end_min error in line %d", line);
301                                 goto rate_error;
302                         }
303
304                         /* if hour is 0 assume it means midnight */
305                         if( hour == 0 )
306                                 hour = 24;
307                         rt->end_time = hour * 60 + min;
308
309                         if( rt->end_time <= rt->start_time )
310                                 {
311                                 snprintf(error, sizeof(error), "rates: end_time must be greater then start_time %d", line);
312                                 goto rate_error;
313                                 }
314
315                         /* colon */
316                         
317                         if(*bp == ':')
318                         {
319                                 bp++;
320                         }
321                         else
322                         {
323                                 snprintf(error, sizeof(error), "rates: no ':' after end_min in line %d", line);
324                                 goto rate_error;
325                         }
326
327                         /* time */
328                         
329                         if(isdigit(*bp))
330                         {
331                                 rt->rate = atoi(bp);
332                                 while(!isspace(*bp))
333                                         bp++;
334                         }
335                         else
336                         {
337                                 snprintf(error, sizeof(error), "rates: first rate digit error in line %d", line);
338                                 goto rate_error;
339                         }
340
341                         /* eat space delimiter */
342
343                         while(isspace(*bp))
344                                 bp++;
345                 }
346         }
347
348 #if DEBUG
349         if(debug_flags & DL_RATES)
350         {
351                 for (j = 0; j < NRATES; j++)
352                 {
353                         for (i = 0; i < NDAYS; i++)
354                         {
355                                 if (rates [j][i] != NULL)
356                                 {
357                                         rt = rates [j][i];
358                                         for (; rt; rt = rt->next)
359                                         {
360                                                 dolog(LL_DBG, "rates: index %d day %d = %d.%2.2d-%d.%2.2d:%d",
361                                                         j, i, rt->start_time/60, rt->start_time%60,
362                                                         rt->end_time/60,rt->end_time%60,rt->rate);
363                                         }
364                                 }
365                                 else
366                                 {
367                                         dolog(LL_DBG, "rates: NO entry for day %d !!\n", i);
368                                 }
369                         }
370                 }
371         }
372 #endif
373         fclose(fp);
374         return(GOOD);
375
376 rate_error:
377         fclose(fp);
378         rate_error = error;
379         return(ERROR);
380 }
381
382 #ifndef PARSE_DEBUG_MAIN
383
384 /*---------------------------------------------------------------------------*
385  *      get unit length time from configured source
386  *---------------------------------------------------------------------------*/
387 int
388 get_current_rate(cfg_entry_t *cep, int logit)
389 {
390         int rt;
391         
392         switch(cep->unitlengthsrc)
393         {
394                 case ULSRC_CMDL:        /* specified on commandline     */
395                         if(logit)
396                                 dolog(LL_CHD, "%05d %s rate %d sec/unit (cmdl)",
397                                         cep->cdid, cep->name, unit_length);
398                         return(unit_length);
399                         break;
400
401                 case ULSRC_CONF:        /* get it from config file      */
402                         if(logit)
403                                 dolog(LL_CHD, "%05d %s rate %d sec/unit (conf)",
404                                         cep->cdid, cep->name, cep->unitlength);
405                         return(cep->unitlength);
406
407                 case ULSRC_RATE:        /* get it dynamic from ratesfile*/
408                         if(!got_rate)   /* got valid rates struct ?? */
409                         {
410                                 if(logit)
411                                         dolog(LL_CHD, "%05d %s rate %d sec/unit (no ratefile)",
412                                                 cep->cdid, cep->name, UNITLENGTH_DEFAULT);
413                                 return(UNITLENGTH_DEFAULT);
414                         }
415                         if((cep->ratetype >= NRATES) ||
416                            (cep->ratetype == INVALID_RATE))
417                         {
418                                 if(logit)
419                                         dolog(LL_CHD, "%05d %s rate %d sec/unit (rate out of range)",
420                                                 cep->cdid, cep->name, UNITLENGTH_DEFAULT);
421                                 return(UNITLENGTH_DEFAULT);
422                         }
423                         
424                         if((rt = getrate(cep->ratetype)) != -1)
425                         {
426                                 if(logit)
427                                         dolog(LL_CHD, "%05d %s rate %d sec/unit (rate)",
428                                                 cep->cdid, cep->name, rt);
429                                 return(rt);
430                         }
431
432                         if(logit)                       
433                                 dolog(LL_CHD, "%05d %s rate %d sec/unit (ratescan fail)",
434                                         cep->cdid, cep->name, UNITLENGTH_DEFAULT);
435
436                         return(UNITLENGTH_DEFAULT);
437                         break;
438
439                 case ULSRC_DYN: /* dynamically calculated from AOC */
440                         if((rt = getrate(cep->ratetype)) != -1)
441                         {
442                                 if(logit)
443                                         dolog(LL_CHD, "%05d %s rate %d sec/unit (aocd, rate)",
444                                                 cep->cdid, cep->name, rt);
445                                 return(rt);
446                         }
447                         if(logit)
448                                 dolog(LL_CHD, "%05d %s rate %d sec/unit (aocd, default)",
449                                         cep->cdid, cep->name, UNITLENGTH_DEFAULT);
450
451                         return(UNITLENGTH_DEFAULT);
452                         break;
453
454                 default:
455                         if(logit)
456                                 dolog(LL_CHD, "%05d %s rate %d sec/unit (unitlen unknown)",
457                                         cep->cdid, cep->name, UNITLENGTH_DEFAULT);
458
459                         return(UNITLENGTH_DEFAULT);
460                         break;
461         }
462 }
463 #endif /* PARSE_DEBUG_MAIN */
464
465
466 /*---------------------------------------------------------------------------*
467  *      get the currently active rate
468  *---------------------------------------------------------------------------*/
469 static int
470 getrate(int rate_type)
471 {
472         struct tm *ptr;
473         time_t now;
474         struct rates *hd;
475         int time_now;
476
477         if((!got_rate) ||
478            (rate_type >= NRATES) ||
479            (rate_type == INVALID_RATE))
480         {
481                 return -1;
482         }
483
484         time(&now);                     /* get current time */
485
486         ptr = localtime(&now);
487
488         time_now = ptr->tm_hour*60 + ptr->tm_min;
489
490         /* walk thru the rates for weekday until rate for current time found */
491
492         for (hd = rates[rate_type][ptr->tm_wday]; hd; hd = hd->next)
493         {
494                 /* current time within window ? */
495                 if((time_now >= hd->start_time ) &&
496                    (time_now < hd->end_time ))
497                 {
498                         DBGL(DL_RATES, (dolog(LL_DBG, "rate=%d sec/unit (day=%d, beg=%d:%2.2d, end=%d:2.2d, current=%d:%2.2d)",
499                                 hd->rate,
500                                 ptr->tm_wday,
501                                 hd->start_time/60, hd->start_time%60,
502                                 hd->end_time/60, hd->end_time%60,
503                                 time_now/60, time_now%60)));
504                                 
505                         return hd->rate;
506                 }
507         }
508         return -1;
509 }
510
511 /* EOF */