config.c (34339B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * SAL Configuration Variable Support 8 * 9 * The SAL layer maintains a set of configuration variables for use 10 * by any upper layers (such as SOC or BCM). It is maintained in the 11 * SAL layer without using anything other than the standard lib calls 12 * to avoid requiring anything other than just itself. 13 * 14 * These config variables can either be compiled into the image or read 15 * from a file during initialization. 16 * 17 * Precompiled values are defined in the function sal_config_init_defaults() 18 * which is automatically built from the uncommented values 19 * in $SDK/rc/config.bcm using the bcm2c.pl script. This generates a source 20 * file called platform_defines.c 21 * 22 * Runtime values are loaded by reading the file config.bcm, typically 23 * stored in the switch's flash file system. The variables are stored one 24 * per line in the file, in the form VARIABLE=VALUE. Comment lines beginning 25 * with a # character and empty lines consisting of only white space are 26 * ignored. The file $SDK/rc/config.bcm is an example that can be used 27 * as a guide. 28 * 29 * If the image is compile with NO_FILEIO or SAL_CONFIG_FILE_DISABLE 30 * defined, then the runtime values are not loaded from an external file. 31 */ 32 33 #ifdef __KERNEL__ 34 #include <linux/string.h> 35 #include <linux/ctype.h> 36 #else 37 #include <string.h> 38 #include <ctype.h> 39 #include <stdlib.h> 40 #include <stdio.h> 41 #endif 42 #include <assert.h> 43 44 #include <sal/core/libc.h> 45 #include <sal/core/alloc.h> 46 #include <sal/core/spl.h> 47 #include <sal/types.h> 48 #include <sal/appl/config.h> 49 #include <sal/appl/io.h> 50 #include <sal/appl/sal.h> 51 #include <shared/util.h> 52 53 #ifdef NO_FILEIO 54 #undef SAL_CONFIG_FILE_DISABLE 55 #define SAL_CONFIG_FILE_DISABLE 56 #endif /* NO_FILEIO */ 57 58 typedef uint16 sc_hash_t; 59 60 /* 61 * Speed up searches by first checking if a hash matches. 62 * It encodes the first and last character, as well as string length. 63 */ 64 65 #define MAX_CONFIG_HASH_COUNT 1024 66 #define SC_HASH(_n, _h) do { \ 67 uint32 _hash = 5381; \ 68 uint32 _i = 0; \ 69 while (_n[_i] != 0) { \ 70 _hash = ((_hash << 5) + _hash) + _n[_i]; \ 71 _i++; \ 72 } \ 73 _hash = ((_hash << 5) + _hash) + _i; \ 74 _h = (sc_hash_t)(_hash % MAX_CONFIG_HASH_COUNT); \ 75 } while (0) 76 77 typedef struct sc_s { 78 struct sc_s *sc_next; 79 char *sc_name; 80 char *sc_value; 81 uint16 sc_flag; /* Used for duplicate checking, flushing, and hits */ 82 uint16 sc_line; 83 sc_hash_t sc_hash; 84 } sc_t; 85 86 /* Defines for sc_t->sc_flag */ 87 #define SC_COMPILE_VALUE 0x0001 88 #define SC_FLUSHED 0x0002 89 #define SC_HIT 0x0004 90 91 static char *sal_config_file_name = NULL; 92 static char *sal_config_temp_name = NULL; 93 94 static sc_t *sal_config_list[MAX_CONFIG_HASH_COUNT]; 95 96 /* 97 * sal_config_compiled_values is the count of compiled values 98 * sal_config_imported_values is the count of imported values 99 * from sal_config_file_name (ex. config.bcm) 100 */ 101 102 static uint32 sal_config_compiled_values = 0; 103 static uint32 sal_config_imported_values = 0; 104 105 #define FREE_SC(_s) if (_s) { \ 106 if ((_s)->sc_name) sal_free((_s)->sc_name); \ 107 if ((_s)->sc_value) sal_free((_s)->sc_value);\ 108 sal_free(_s); \ 109 } 110 111 #ifndef SAL_CONFIG_FILE_DISABLE 112 #include <soc/property.h> 113 static char *sal_config_prop_names[] = BCM_SOC_PROP_NAMES_INITIALIZER; 114 #endif 115 116 /* 117 * Function: 118 * wildcard_search 119 * Purpose: 120 * search for "*" in name and save prefix as wildcard 121 * 122 * Returns: 123 * wildcard returns prefix of name 124 * length returns length of wildcard 125 */ 126 char* 127 wildcard_search(const char *name, char *wildcard, int *length) 128 { 129 int len, index = 0; 130 const char *m = name; 131 132 len = strlen(name); 133 wildcard = sal_alloc(len + 1, "wildcard"); 134 135 while (index < len) { 136 if (*m == '*') { 137 *(wildcard+index) = 0; 138 *length = index; 139 return wildcard; 140 } 141 else { 142 *(wildcard+index) = *m; 143 m++; 144 index++; 145 } 146 } 147 148 /* no '*' found */ 149 sal_free(wildcard); 150 return NULL; 151 } 152 153 154 /* 155 * Function: 156 * sal_config_file_set 157 * Purpose: 158 * Set the name of the active configuration file. 159 * Parameters: 160 * fname - name of config file (if NULL, use default; if empty 161 * string, there is no config file) 162 * tname - name of temporary file that gets renamed to config file 163 * (must be given if fname is non-NULL and non-empty) 164 * Returns: 165 * -1 Illegal parameter 166 * 0 Success 167 * Notes: 168 * Makes a copy of the input string. 169 */ 170 171 int 172 sal_config_file_set(const char *fname, const char *tname) 173 { 174 if (sal_config_file_name != NULL) { 175 sal_free(sal_config_file_name); 176 sal_config_file_name = NULL; 177 } 178 179 if (sal_config_temp_name != NULL) { 180 sal_free(sal_config_temp_name); 181 sal_config_temp_name = NULL; 182 } 183 184 if (fname != NULL) { 185 sal_config_file_name = sal_strdup(fname); 186 187 if (fname[0] != 0) { 188 if (tname == NULL || tname[0] == 0) { 189 return -1; 190 } 191 192 sal_config_temp_name = sal_strdup(tname); 193 } 194 } 195 196 return 0; 197 } 198 199 /* 200 * Function: 201 * sal_config_file_get 202 * Purpose: 203 * Return the config file names 204 * Parameters: 205 * fname - (OUT) Name of config file, NULL if none 206 * tname - (OUT) Name of temporary file, NULL if none 207 * Returns: 208 * 0 Success 209 */ 210 211 int 212 sal_config_file_get(const char **fname, const char **tname) 213 { 214 *fname = (sal_config_file_name != NULL ? 215 sal_config_file_name : SAL_CONFIG_FILE); 216 *tname = (sal_config_temp_name != NULL ? 217 sal_config_temp_name : SAL_CONFIG_TEMP); 218 219 return 0; 220 } 221 222 /* 223 * Function: 224 * sal_config_find 225 * Purpose: 226 * Find a config entry for the specified name. 227 * Parameters: 228 * name - name of variable to recover 229 * Returns: 230 * NULL - not found 231 * !NULL - pointer to value 232 */ 233 234 static sc_t * 235 sal_config_find(const char *name) 236 { 237 sc_t *sc; 238 sc_hash_t hash; 239 SC_HASH(name, hash); 240 SAL_GLOBAL_LOCK; 241 sc = sal_config_list[hash]; 242 while (sc != NULL) { 243 if ((sc->sc_name != NULL) && (sc->sc_value != NULL) && (sal_strcmp(sc->sc_name, name) == 0)) { 244 break; 245 } 246 sc = sc->sc_next; 247 } 248 249 SAL_GLOBAL_UNLOCK; 250 return sc; 251 } 252 253 #ifndef SAL_CONFIG_FILE_DISABLE /* Only used by fileio functions */ 254 static int 255 sal_config_get_lvalue(char *str, sc_t *sc) 256 { 257 char *equals_loc; 258 259 if ((equals_loc = strchr(str, '=')) == NULL) { 260 if (sc != NULL) { 261 FREE_SC(sc); 262 } 263 return FALSE; 264 } 265 266 while (isspace((unsigned)*str)) { 267 str++; /* skip leading whitespace */ 268 } 269 270 if (str == equals_loc) { 271 if (sc != NULL) { 272 FREE_SC(sc); 273 } 274 return FALSE; /* lvalue is empty or only whitespace */ 275 } 276 277 while (isspace((unsigned)*(equals_loc - 1)) && equals_loc > str) { 278 equals_loc--; /* trim trailing whitespace */ 279 } 280 281 sc->sc_name = sal_alloc(equals_loc - str + 1, "config name"); 282 sal_strncpy(sc->sc_name, str, equals_loc - str); 283 284 sc->sc_name[equals_loc - str] = '\0'; 285 286 SC_HASH(sc->sc_name, sc->sc_hash); 287 return TRUE; 288 } 289 290 static int 291 sal_config_get_rvalue(char *str, sc_t *sc) 292 { 293 char *begin; 294 char *end; 295 296 if ((begin = strchr(str, '=')) == NULL) { 297 if (sc != NULL) { 298 FREE_SC(sc); 299 } 300 return FALSE; 301 } 302 303 begin++; /* Move past '=' */ 304 while (isspace((unsigned)*begin)) { 305 begin++; /* Trim leading whitespace */ 306 } 307 308 for (end = begin + strlen(begin) - 1; isspace((unsigned)*end); end--) 309 *end = '\0'; /* Trim trailing whitespace */ 310 311 sc->sc_value = sal_alloc(end - begin + 2, "config value"); 312 if (sc->sc_value == NULL) { 313 sal_printf("sal_config_parse: Memory allocation failed\n"); 314 FREE_SC(sc); 315 return FALSE; 316 } 317 318 sal_strncpy(sc->sc_value, begin, end - begin + 1); 319 sc->sc_value[end - begin + 1] = '\0'; 320 321 return TRUE; 322 } 323 324 /* 325 * Function: 326 * sal_config_parse 327 * Purpose: 328 * Parse a single input line. 329 * Parameters: 330 * str - pointer to null terminated input line. 331 * Returns: 332 * NULL - failed to parse 333 * !NULL - pointer to sc entry. 334 * Notes: 335 * Does not modify input line. 336 */ 337 static sc_t * 338 sal_config_parse(char *str) 339 { 340 sc_t *sc; 341 342 sc = (sc_t *)sal_alloc(sizeof(sc_t), "config parse"); 343 if (sc != NULL) { 344 sal_memset(sc, 0, sizeof(sc_t)); 345 } 346 347 if (!sc || !sal_config_get_lvalue(str, sc) || 348 !sal_config_get_rvalue(str, sc)) { 349 return NULL; 350 } 351 352 sc->sc_next = NULL; 353 return sc; 354 } 355 #endif /* SAL_CONFIG_FILE_DISABLE */ 356 357 /* 358 * Function: 359 * sal_config_init 360 * Purpose: 361 * If not already initialized, call refresh. 362 * Parameters: 363 * None 364 * Returns: 365 * 0 - success 366 * -1 - failed. 367 */ 368 369 int 370 sal_config_init(void) 371 { 372 static int initdone = FALSE; 373 374 if (!initdone) { 375 sal_memset(sal_config_list, 0, sizeof(sal_config_list)); 376 initdone = TRUE; 377 return sal_config_refresh(); 378 } 379 380 return 0; 381 } 382 383 #ifndef SAL_CONFIG_FILE_DISABLE 384 int 385 sal_config_search_valid_prop(char *name) 386 { 387 int i; 388 389 for (i = 0; sal_config_prop_names[i][0] != '\0'; i++) { 390 if (sal_strcasecmp(sal_config_prop_names[i], name) == 0) { 391 return TRUE; 392 } 393 } 394 395 return FALSE; 396 } 397 398 /* 399 * Function: 400 * sal_config_prop_is_known 401 * Purpose: 402 * Determine if a given property is valid or not 403 * Returns: 404 * TRUE if property exists in property.h, FALSE if it does not 405 */ 406 int 407 sal_config_prop_is_known(sc_t *sc) 408 { 409 static char name[256]; 410 char *loc; 411 412 sal_strncpy(name, sc->sc_name, sizeof(name) - 1); 413 name[sizeof(name) - 1] = '\0'; 414 if (sal_config_search_valid_prop(name)) { 415 return TRUE; 416 } 417 418 /* try removing the . if there is one, for "prop.0" style */ 419 loc = sal_strrchr(name, '.'); 420 if (loc != NULL) { 421 *loc = '\0'; 422 if (sal_config_search_valid_prop(name)) { 423 return TRUE; 424 } 425 } 426 427 /* try removing the . again if there is another one, 428 for "prop.port.0" style */ 429 loc = sal_strrchr(name, '.'); 430 if (loc != NULL) { 431 *loc = '\0'; 432 if (sal_config_search_valid_prop(name)) { 433 return TRUE; 434 } 435 } 436 437 /* try removing the . again if there is another one, 438 for "prop.prop1.port.0" style */ 439 loc = sal_strrchr(name, '.'); 440 if (loc != NULL) { 441 *loc = '\0'; 442 if (sal_config_search_valid_prop(name)) { 443 return TRUE; 444 } 445 } 446 447 /* try removing the . again if there is another one, 448 for "prop.prop1.prop2.port.0" style */ 449 loc = sal_strrchr(name, '.'); 450 if (loc != NULL) { 451 *loc = '\0'; 452 if (sal_config_search_valid_prop(name)) { 453 return TRUE; 454 } 455 } 456 457 /* try removing the . again if there is another one, 458 for "prop.prop1.prop2.prop3.port.0" style */ 459 loc = sal_strrchr(name, '.'); 460 if (loc != NULL) { 461 *loc = '\0'; 462 if (sal_config_search_valid_prop(name)) { 463 return TRUE; 464 } 465 } 466 467 /* try removing the last brace if it exists, for "prop{0}" style */ 468 loc = sal_strrchr(name, '{'); 469 if (loc != NULL) { 470 *loc = '\0'; 471 if (sal_config_search_valid_prop(name)) { 472 return TRUE; 473 } 474 } 475 476 /* try removing the last underscore if it exists, for "prop_xe.0" style */ 477 loc = sal_strrchr(name, '_'); 478 if (loc != NULL) { 479 *loc = '\0'; 480 if (sal_config_search_valid_prop(name)) { 481 return TRUE; 482 } 483 } 484 485 /* 486 * try removing one more underscore if it exists, for "prop_in_203.bcm88650" 487 * style 488 */ 489 loc = sal_strrchr(name, '_'); 490 if (loc != NULL) { 491 *loc = '\0'; 492 if (sal_config_search_valid_prop(name)) { 493 return TRUE; 494 } 495 } 496 497 /* 498 * try removing one more underscore if it exists, for "prop_dram0_byte0_bit0.BCM88675" 499 * style 500 */ 501 502 loc = sal_strrchr(name, '_'); 503 if (loc != NULL) { 504 *loc = '\0'; 505 if (sal_config_search_valid_prop(name)) { 506 return TRUE; 507 } 508 } 509 510 /* 511 * try removing 2 more underscore if exists, for "serdes_lane_config_cl72_auto_polarity_en_<port>.BCM8879X" 512 * and "serdes_lane_config_cl72_restart_timeout_en_<port>.BCM8879X" 513 */ 514 515 loc = sal_strrchr(name, '_'); 516 if (loc != NULL) { 517 *loc = '\0'; 518 if (sal_config_search_valid_prop(name)) { 519 return TRUE; 520 } 521 } 522 523 loc = sal_strrchr(name, '_'); 524 if (loc != NULL) { 525 *loc = '\0'; 526 if (sal_config_search_valid_prop(name)) { 527 return TRUE; 528 } 529 } 530 531 return FALSE; 532 } 533 #endif 534 535 #ifndef SAL_CONFIG_FILE_DISABLE 536 #define SAL_CONFIG_MAX_IMPORTED_CONFIG_FILES 1024 537 538 /** 539 * 540 * 541 * 542 * @param import_fname 543 * @param nof_imported_config_files 544 * @param already_imported_tables 545 * check if file already 546 * imported 547 * 548 * @return int 549 */ 550 static int 551 sal_config_already_imported(char *import_fname,int *nof_imported_config_files, char *already_imported_tables[]) 552 { 553 int i; 554 555 /* 556 * the function save the file names to keep we are not enter 557 * into infinite loop of imports 558 * the saved name is 559 * 1.basename(config.bcm) - first time 560 * 2. the argument to import command 561 */ 562 if (SAL_CONFIG_MAX_IMPORTED_CONFIG_FILES<=*nof_imported_config_files) { 563 sal_printf("nof imported files exceeded its limit: %d:\n ",SAL_CONFIG_MAX_IMPORTED_CONFIG_FILES); 564 return 1; 565 } 566 for (i=0;i<*nof_imported_config_files;i++) { 567 if (!sal_strcmp(import_fname, already_imported_tables[i])) { 568 #if defined(BROADCOM_DEBUG) 569 sal_printf("sal_config_already_imported: file: %s, " 570 "is already imported\n", 571 import_fname); 572 #endif /* BROADCOM_DEBUG */ 573 return 1; 574 } 575 } 576 already_imported_tables[i] = sal_alloc(sal_strlen(import_fname)+1," alloc bcm file name"); 577 sal_strcpy(already_imported_tables[i],import_fname); 578 (*nof_imported_config_files)++; 579 return 0; 580 } 581 582 /** 583 * import config file 584 * to one config file 585 */ 586 587 static int 588 sal_config_line_import(char *str,char *import_fname) { 589 char line[SAL_CONFIG_STR_MAX]; 590 char *sep=" \t\n\r"; 591 char *token; 592 /* 593 * we check the case if the 594 * line of the form 595 * import <filename> 596 */ 597 598 599 if ((sal_strlen(str)) < SAL_CONFIG_STR_MAX) { 600 sal_strcpy(line,str); 601 } else { 602 return 0; 603 } 604 /* 605 * split the line into 2 tokens 606 */ 607 token=sal_strtok(line,sep); 608 if (token==NULL) { 609 return 0; 610 } 611 612 /* 613 * if the first token is import 614 * then we look for the second token to be the file name 615 */ 616 617 if (sal_strcmp(token,"import")) { 618 return 0; 619 } 620 token = sal_strtok(NULL, sep); 621 if (token==NULL) { 622 return 0; 623 } 624 625 /* 626 * we build the import file name as 627 * dirname/filename contained at the second token 628 */ 629 sal_strcpy(import_fname, token); 630 631 return 1; 632 } 633 634 /** 635 * Function: 636 * sal_config_file_process 637 * Purpose: 638 * parse single config-bcm file . 639 * if find import statement in the parsed file 640 * call recursively itself with the import file name 641 * @param fname 642 * @param nof_imported_config_files 643 * @param already_imported_tables 644 * @param dir_name - the location of the file. 645 * @param override_duplicates - set to 1 to override existing soc properties 646 * @return int 647 */ 648 int 649 sal_config_file_process(char *fname,int *nof_imported_config_files, char *already_imported_tables[], char *dirname, int override_duplicates) 650 { 651 FILE *fp; 652 sc_t *found_sc; 653 char str[SAL_CONFIG_STR_MAX], *c; 654 int line = 0; 655 int suppress_unknown_warnings = 0; 656 char import_fname[SAL_NAME_MAX]; 657 char fname_full_path[SAL_NAME_MAX]; 658 sc_t *sc; 659 660 661 if (dirname!=NULL && sal_strcasecmp(dirname,".")) { 662 sal_sprintf(fname_full_path, "%s/%s", dirname, fname); 663 } else { 664 sal_strncpy(fname_full_path, fname,sizeof(fname_full_path)-1); 665 } 666 if ((fp = sal_fopen(fname_full_path, "r")) == NULL) { 667 sal_printf("sal_config_refresh: cannot read file: %s, " 668 "variables not loaded\n", 669 fname_full_path); 670 return -1; 671 } 672 673 /* Read the entire file - parsing as we go */ 674 675 while (sal_fgets(str, sizeof(str), fp)) { 676 677 line++; 678 679 /* Skip comment lines */ 680 681 if (str[0] == '#') { 682 continue; 683 } 684 if (sal_config_line_import(str,import_fname)) { 685 if (already_imported_tables == NULL) 686 { 687 sal_printf("import is not allowed \n"); 688 continue; 689 } 690 else 691 { 692 if (sal_config_already_imported(import_fname, nof_imported_config_files,already_imported_tables)) { 693 sal_printf("%s already imported\n",import_fname); 694 continue; 695 } 696 if (sal_config_file_process(import_fname, nof_imported_config_files,already_imported_tables,dirname, override_duplicates) == -1) { 697 continue; 698 } 699 continue; 700 } 701 } 702 703 /* Strip trailing newline/blanks */ 704 705 c = str + strlen(str); 706 while (c > str && isspace((unsigned) c[-1])) { 707 c--; 708 } 709 710 *c = '\0'; 711 712 /* Skip blank lines */ 713 714 if (str[0] == 0) { 715 continue; 716 } 717 718 if ((sc = sal_config_parse(str)) == NULL) { 719 sal_printf("sal_config_refresh: format error " 720 "in %s on line %d (ignored)\n", 721 fname, line); 722 continue; 723 } 724 725 /* 726 * Scan for "suppress_unknown_prop_warnings" directly as we go 727 * instead of sal_config_find() because it's much faster 728 */ 729 if (sal_strcasecmp("suppress_unknown_prop_warnings", 730 sc->sc_name) == 0) { 731 suppress_unknown_warnings = _shr_ctoi(sc->sc_value); 732 continue; 733 } 734 735 /* Check for pre-existing default or duplicates in the file */ 736 found_sc = sal_config_list[sc->sc_hash]; 737 while (found_sc != NULL) { 738 if (sal_strcmp(found_sc->sc_name, sc->sc_name) == 0) { 739 break; 740 } 741 found_sc = found_sc->sc_next; 742 } 743 744 if (found_sc != NULL) { 745 if (!(found_sc->sc_flag & SC_COMPILE_VALUE) && !override_duplicates) { 746 sal_printf("sal_config_refresh: ignoring duplicate entry " 747 "\"%s\"\n" 748 " %s line %d " 749 "(first defined on line %d)\n", 750 sc->sc_name, fname, 751 line, found_sc->sc_line); 752 } 753 else { 754 /* Clobber the compiled-in default value */ 755 char *temp = sc->sc_value; /* New value */ 756 sc->sc_value = found_sc->sc_value; /* Old, to be freed */ 757 found_sc->sc_value = temp; 758 found_sc->sc_line = line; /* Line # of 1st definition */ 759 } 760 FREE_SC(sc); 761 continue; 762 } 763 764 if (!suppress_unknown_warnings) { 765 if (sal_config_prop_is_known(sc) == FALSE) { 766 sal_printf("sal_config_refresh: unknown entry \"%s\"" 767 " on %s line %d\n", sc->sc_name, fname, line); 768 } 769 } 770 771 sc->sc_line = line; /* Line # of 1st definition */ 772 sc->sc_next = sal_config_list[sc->sc_hash]; 773 sal_config_list[sc->sc_hash] = sc; 774 sal_config_imported_values++; 775 } /* parse config file */ 776 sal_fclose(fp); 777 return 0; 778 } 779 #endif 780 /* 781 * Function: 782 * sal_config_refresh 783 * Purpose: 784 * Refresh default (compiled-in) configuration. 785 * Refresh the memory image from the configuration file, 786 * clobbering default values (if the config file exists). 787 * Parameters: 788 * None 789 * Returns: 790 * 0 - success 791 * -1 - failed. 792 */ 793 int 794 sal_config_refresh(void) 795 { 796 sc_t *sc, *sc_tmp; 797 int i; 798 799 #ifndef SAL_CONFIG_FILE_DISABLE 800 char *fname; 801 int nof_imported_config_files=1; 802 char *already_imported_tables[SAL_CONFIG_MAX_IMPORTED_CONFIG_FILES]={NULL}; 803 int rv; 804 char dirname[SAL_NAME_MAX]; 805 int flen; 806 807 808 fname = (sal_config_file_name != NULL ? 809 sal_config_file_name : SAL_CONFIG_FILE); 810 811 if (fname[0] == 0) { 812 return 0; /* No config file */ 813 } 814 815 /* Try to load config file ... */ 816 #endif 817 818 /* Clear all previous state */ 819 for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) { 820 sc = sal_config_list[i]; 821 sal_config_list[i] = NULL; 822 while (sc != NULL) { 823 sc_tmp = sc->sc_next; 824 FREE_SC(sc); 825 sc = sc_tmp; 826 } 827 } 828 /* load precompiled values from platform_defines.c */ 829 sal_config_init_defaults(); 830 831 #ifndef SAL_CONFIG_FILE_DISABLE 832 /* 833 * Add new file-based variables, superseding any matching compiled 834 * variables. Find end-of-list, and initialize the default-or-file 835 * flag. 836 */ 837 sal_config_compiled_values = 0; 838 sal_config_imported_values = 0; 839 840 for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) { 841 for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) { 842 sc->sc_flag |= SC_COMPILE_VALUE; 843 sal_config_compiled_values++; 844 } 845 } 846 flen = sal_strnlen(fname, SAL_NAME_MAX); 847 if (flen == SAL_NAME_MAX) 848 { 849 sal_printf("sal_config_refresh: config file path length is not supported (max length supported %d) \n", SAL_NAME_MAX); 850 return -1; /*throw a failure*/ 851 } 852 sal_dirname(fname,dirname); 853 already_imported_tables[0] = sal_alloc(sal_strlen(fname)+1 ," alloc bcm file name"); 854 sal_basename(fname, already_imported_tables[0]); 855 rv = sal_config_file_process(already_imported_tables[0],&nof_imported_config_files,already_imported_tables, dirname, 0); 856 857 for (i=0;i<nof_imported_config_files;i++) { 858 sal_free(already_imported_tables[i]); 859 } 860 861 return rv; 862 863 #endif /* SAL_CONFIG_FILE_DISABLE */ 864 865 return 0; 866 } 867 868 /* 869 * Function: 870 * sal_config_flush 871 * Purpose: 872 * Flush the memory image to the configuration file. 873 * Parameters: 874 * None 875 * Returns: 876 * 0 - success 877 * -1 - failed. 878 */ 879 880 int 881 sal_config_flush(void) 882 { 883 int rv = 0; 884 #ifndef SAL_CONFIG_FILE_DISABLE 885 FILE *old_fp, *new_fp; 886 sc_t *sc, *new_sc; 887 char str[SAL_CONFIG_STR_MAX], *c; 888 int line = 0; 889 char *fname, *tname; 890 int i; 891 892 fname = (sal_config_file_name != NULL ? 893 sal_config_file_name : SAL_CONFIG_FILE); 894 895 if (fname[0] == 0) { 896 return 0; /* No config file */ 897 } 898 899 tname = (sal_config_temp_name != NULL ? 900 sal_config_temp_name : SAL_CONFIG_TEMP); 901 902 assert(tname != NULL && tname[0] != 0); 903 904 /* Attempt to create temp file */ 905 906 if ((new_fp = sal_fopen(tname, "w")) == NULL) { 907 rv = -1; 908 goto done; 909 } 910 911 /* old_fp can be NULL if creating config file for first time */ 912 913 old_fp = sal_fopen(fname, "r"); 914 915 /* Initialize the "flushed" flag */ 916 for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) { 917 for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) { 918 sc->sc_flag &= ~SC_FLUSHED; 919 } 920 } 921 922 /* Read the entire file - parsing as we go */ 923 924 while (old_fp != NULL && sal_fgets(str, sizeof(str), old_fp)) { 925 char *s; 926 927 line++; 928 929 /* Strip trailing newline/blanks */ 930 931 c = str + strlen(str); 932 while (c > str && isspace((unsigned) c[-1])) { 933 c--; 934 } 935 936 *c = '\0'; 937 938 /* 939 * Transfer blank lines and comment lines, but NOT commented-out 940 * variable settings (yet) 941 */ 942 943 if (str[0] == 0 || (str[0] == '#' && strchr(str, '=') == NULL)) { 944 sal_fprintf(new_fp, "%s\n", str); 945 continue; 946 } 947 948 s = str; 949 if (*s == '#') { 950 s++; 951 } 952 953 if ((sc = sal_config_parse(s)) == NULL) { 954 sal_printf("sal_config_flush: format error " 955 "in %s on line %d (removed)\n", 956 fname, line); 957 continue; 958 } 959 960 /* Write new value (or comment) for this entry */ 961 962 if ((new_sc = sal_config_find(sc->sc_name)) == NULL || 963 (new_sc->sc_flag & SC_FLUSHED)) { 964 /* Not found or a dup, write out commented assignment */ 965 sal_fprintf(new_fp, "#%s=%s\n", sc->sc_name, sc->sc_value); 966 } else { 967 sal_fprintf(new_fp, "%s=%s\n", new_sc->sc_name, new_sc->sc_value); 968 new_sc->sc_flag |= SC_FLUSHED; 969 } 970 971 FREE_SC(sc); 972 } 973 974 /* Write out the current values that were not in the old_fp file */ 975 for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) { 976 for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) { 977 if (!(sc->sc_flag & SC_FLUSHED)) { 978 sal_fprintf(new_fp, "%s=%s\n", sc->sc_name, sc->sc_value); 979 } 980 } 981 } 982 983 sal_fclose(new_fp); 984 985 if (old_fp != NULL) { 986 sal_fclose(old_fp); 987 } 988 989 if (rv == 0) { /* No error, rename file */ 990 rv = sal_rename(tname, fname); 991 } 992 993 if (rv != 0) { /* Error, remove temp file */ 994 (void)sal_remove(tname); 995 } 996 997 done: 998 if (rv < 0) { 999 sal_printf("sal_config_flush: variables not saved\n"); 1000 } 1001 #endif /* SAL_CONFIG_FILE_DISABLE */ 1002 1003 return rv; 1004 } 1005 1006 /* 1007 * Function: 1008 * sal_config_save 1009 * Purpose: 1010 * Flush the config to the a given file. 1011 * Parameters: 1012 * None 1013 * Returns: 1014 * 0 - success 1015 * -1 - failed. 1016 */ 1017 1018 int 1019 sal_config_save(char *fname, char *pat, int append) 1020 { 1021 int rv = 0; 1022 #ifndef SAL_CONFIG_FILE_DISABLE 1023 FILE *new_fp; 1024 sc_t *sc; 1025 int pat_len = 0; 1026 int i; 1027 1028 if (fname == NULL) { 1029 return 0; /* No config file */ 1030 } 1031 1032 if(append) { 1033 new_fp = sal_fopen(fname, "a"); 1034 } else { 1035 new_fp = sal_fopen(fname, "w"); 1036 } 1037 1038 if (new_fp == NULL) { 1039 rv = -1; 1040 goto done; 1041 } 1042 1043 if (pat) { 1044 pat_len = strlen(pat); 1045 } 1046 /* Write out the current values */ 1047 for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) { 1048 for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) { 1049 if ((pat == NULL) || (sal_strncasecmp(sc->sc_name, pat, pat_len) == 0)) { 1050 sal_fprintf(new_fp, "%s=%s\n", sc->sc_name, sc->sc_value); 1051 } 1052 } 1053 } 1054 1055 sal_fclose(new_fp); 1056 1057 done: 1058 if (rv < 0) { 1059 sal_printf("sal_config_flush: variables not saved\n"); 1060 } 1061 #endif /* SAL_CONFIG_FILE_DISABLE */ 1062 1063 return rv; 1064 } 1065 1066 /* 1067 * Function: 1068 * sal_config_get 1069 * Purpose: 1070 * Recover a sal configuration variable 1071 * Parameters: 1072 * name - name of variable to recover 1073 * Returns: 1074 * NULL - not found 1075 * !NULL - pointer to value 1076 */ 1077 1078 char * 1079 sal_config_get(const char *name) 1080 { 1081 sc_t *sc; 1082 1083 sc = sal_config_find(name); 1084 if (sc != NULL) { 1085 sc->sc_flag |= SC_HIT; 1086 return sc->sc_value; 1087 } else { 1088 return NULL; 1089 } 1090 } 1091 1092 /* 1093 * Function: 1094 * sal_config_get_next 1095 * Purpose: 1096 * Recover a sal configuration variables in order. 1097 * Parameters: 1098 * name - (IN/OUT) name of last variable recovered. 1099 * value- (OUT) value of variable recovered. 1100 * Returns: 1101 * 0 - variable recovered. 1102 * -1 - All complete, not more variables. 1103 */ 1104 1105 int 1106 sal_config_get_next(char **name, char **value) 1107 { 1108 sc_t *sc; 1109 sc_hash_t hash; 1110 char * nm = *name; 1111 1112 SAL_GLOBAL_LOCK; 1113 if (nm) { 1114 SC_HASH(nm, hash); 1115 sc = sal_config_list[hash]; 1116 while (sc != NULL) { 1117 if (sal_strcmp(sc->sc_name, nm) == 0) { 1118 break; 1119 } 1120 sc = sc->sc_next; 1121 } 1122 if (sc != NULL) { 1123 sc = sc->sc_next; 1124 if (sc == NULL) { 1125 hash++; 1126 for (;hash < MAX_CONFIG_HASH_COUNT; hash++) { 1127 sc = sal_config_list[hash]; 1128 if (sc != NULL) { 1129 break; 1130 } 1131 } 1132 } 1133 } 1134 1135 } else { 1136 for (hash = 0; hash < MAX_CONFIG_HASH_COUNT; hash++) { 1137 sc = sal_config_list[hash]; 1138 if (sc != NULL) { 1139 break; 1140 } 1141 } 1142 } 1143 SAL_GLOBAL_UNLOCK; 1144 1145 if (sc) { 1146 *name = sc->sc_name; 1147 *value = sc->sc_value; 1148 return 0; 1149 } else { 1150 return -1; 1151 } 1152 } 1153 1154 /* 1155 * Function: 1156 * sal_config_set 1157 * Purpose: 1158 * Set a sal configuration variable 1159 * Parameters: 1160 * name - name of variable to set 1161 * value - name of value; can be NULL to delete a variable 1162 * Returns: 1163 * 0 - found and changed 1164 * -1 - not found or out of memory 1165 */ 1166 1167 int 1168 sal_config_set(char *name, char *value) 1169 { 1170 sc_t *sc, *psc; 1171 char *newval; 1172 char *wildcard = NULL; 1173 char *sc_wildcard; 1174 int length; 1175 sc_hash_t hash; 1176 1177 if (name == NULL || *name == '\0') { 1178 return -1; 1179 } 1180 1181 SAL_GLOBAL_LOCK; 1182 1183 SC_HASH(name, hash); 1184 sc = sal_config_list[hash]; 1185 psc = NULL; 1186 while (sc != NULL) { 1187 if (sal_strcmp(sc->sc_name, name) == 0) { 1188 break; 1189 } 1190 psc = sc; 1191 sc = sc->sc_next; 1192 } 1193 1194 if (sc != NULL) { /* found */ 1195 if (value == NULL) { /* delete */ 1196 if (sal_config_list[hash] == sc) { 1197 sal_config_list[hash] = sc->sc_next; 1198 } else { 1199 if (psc !=NULL) { 1200 psc->sc_next = sc->sc_next; 1201 } 1202 } 1203 FREE_SC(sc); 1204 SAL_GLOBAL_UNLOCK; 1205 return 0; 1206 } else { /* replace */ 1207 newval = sal_alloc(strlen(value) + 1, "config value"); 1208 if (newval == NULL) { 1209 SAL_GLOBAL_UNLOCK; 1210 return -1; 1211 } 1212 sc->sc_flag = 0; 1213 sal_strncpy(newval, value, strlen(value)); 1214 newval[strlen(value)] = '\0'; 1215 sal_free(sc->sc_value); 1216 sc->sc_value = newval; 1217 SAL_GLOBAL_UNLOCK; 1218 return 0; 1219 } 1220 } 1221 1222 /* not found, delete */ 1223 if (value == NULL) { 1224 int i; 1225 wildcard = wildcard_search(name, wildcard, &length); 1226 if (wildcard != NULL) { 1227 sc_wildcard = sal_alloc((length + 1), "sc_wildcard"); 1228 *(sc_wildcard+length) = 0; 1229 for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) { 1230 sc = sal_config_list[i]; 1231 psc = NULL; 1232 while (sc != NULL){ 1233 sc_wildcard = sal_strncpy(sc_wildcard, sc->sc_name, length); 1234 sc_wildcard[length] = '\0'; 1235 if (sal_strcmp(sc_wildcard, wildcard) == 0) { 1236 if (sal_config_list[i] == sc) { 1237 sal_config_list[i] = sc->sc_next; 1238 FREE_SC(sc); 1239 sc = sal_config_list[i]; 1240 psc = NULL; 1241 } else { 1242 if (psc !=NULL) { 1243 psc->sc_next = sc->sc_next; 1244 } 1245 FREE_SC(sc); 1246 if (psc !=NULL) { 1247 sc = psc->sc_next; 1248 } 1249 } 1250 } else { 1251 psc = sc; 1252 sc = sc->sc_next; 1253 } 1254 } 1255 } 1256 sal_free(wildcard); 1257 sal_free(sc_wildcard); 1258 SAL_GLOBAL_UNLOCK; 1259 return 0; 1260 } else { 1261 SAL_GLOBAL_UNLOCK; 1262 return -1; 1263 } 1264 } 1265 1266 1267 1268 /* not found, add */ 1269 if ((sc = sal_alloc(sizeof(sc_t), "config set")) == NULL) { 1270 SAL_GLOBAL_UNLOCK; 1271 return -1; 1272 } 1273 sc->sc_flag = 0; 1274 sc->sc_line = 0; 1275 1276 sc->sc_name = sal_alloc(strlen(name) + 1, "config name"); 1277 sc->sc_value = sal_alloc(strlen(value) + 1, "config value"); 1278 1279 if (sc->sc_name == NULL || sc->sc_value == NULL) { 1280 FREE_SC(sc); 1281 SAL_GLOBAL_UNLOCK; 1282 return -1; 1283 } 1284 1285 sal_strncpy(sc->sc_name, name, strlen(name)); 1286 sc->sc_name[strlen(name)] = '\0'; 1287 sal_strncpy(sc->sc_value, value, strlen(value)); 1288 sc->sc_value[strlen(value)] = '\0'; 1289 sc->sc_hash = hash; 1290 1291 sc->sc_next = sal_config_list[hash]; 1292 sal_config_list[hash] = sc; 1293 1294 SAL_GLOBAL_UNLOCK; 1295 return 0; 1296 } 1297 1298 /* 1299 * Function: 1300 * sal_config_show 1301 * Purpose: 1302 * Display current configuration variables. 1303 * Parameters: 1304 * none 1305 * Returns: 1306 * Nothing 1307 */ 1308 1309 void 1310 sal_config_show(void) 1311 { 1312 sc_t *sc; 1313 int i; 1314 1315 SAL_GLOBAL_LOCK; 1316 for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) { 1317 for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) { 1318 sal_printf("\t%s=%s\n", sc->sc_name, sc->sc_value); 1319 } 1320 } 1321 SAL_GLOBAL_UNLOCK; 1322 } 1323 1324 void 1325 sal_config_dump(void) 1326 { 1327 sc_t *sc; 1328 int i; 1329 const char *fname, *tname; 1330 1331 1332 SAL_GLOBAL_LOCK; 1333 for (i = 0; i < MAX_CONFIG_HASH_COUNT; i++) { 1334 for (sc = sal_config_list[i]; sc != NULL; sc = sc->sc_next) { 1335 sal_printf("hash:%4d, line:%4d, flag: 0x%04x, %s=%s\n", 1336 i, 1337 sc->sc_line, 1338 sc->sc_flag, 1339 sc->sc_name, 1340 sc->sc_value); 1341 } 1342 } 1343 SAL_GLOBAL_UNLOCK; 1344 1345 sal_config_file_get(&fname, &tname); 1346 sal_printf("\nconfig file:\n\t%s\n", fname); 1347 1348 sal_printf("\nNumber of compiled values:\n\t%4d\n", 1349 sal_config_compiled_values); 1350 1351 sal_printf("\nNumber of imported values from %s:\n\t%4d\n", 1352 fname, 1353 sal_config_imported_values); 1354 1355 sal_printf("\nflags:\n"); 1356 sal_printf("\t#define SC_COMPILE_VALUE 0x%04x\n",SC_COMPILE_VALUE); 1357 sal_printf("\t#define SC_FLUSHED 0x%04x\n",SC_FLUSHED); 1358 sal_printf("\t#define SC_HIT 0x%04x\n",SC_HIT); 1359 1360 1361 }