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