00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 static const char *rcsid = "$Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATConfig.c,v 1.18 2004/04/28 10:50:10 hartmutkaiser Exp $";
00022
00023
00024
00025 #include <errno.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <ctype.h>
00030 #include <limits.h>
00031 #include <unistd.h>
00032 #include <sys/stat.h>
00033
00034
00035
00036 #include "GATUtil.h"
00037 #include "GATConfig.h"
00038 #include "GATTable.h"
00039 #include "GATContext.h"
00040 #include "GATErrors.h"
00041
00042
00043
00044 #define LINE_LENGTH 1024
00045 #define RC_FILENAME ".gatrc"
00046
00047 #if !defined(MAX_PATH)
00048 #define MAX_PATH _POSIX_PATH_MAX
00049 #endif
00050
00051
00052
00053 enum linetype {line_blank,
00054 line_comment,
00055 line_section,
00056 line_adaptor,
00057 line_string};
00058
00059 enum parse_error
00060 {
00061 parse_success,
00062 parse_empty_token,
00063 parse_memory_failure,
00064 parse_malformed_line
00065 };
00066
00067 struct adaptor_list
00068 {
00069 struct adaptor_list *next;
00070 char *name;
00071 GATConfigTableList configs;
00072 };
00073
00074 struct GATConfig_S
00075 {
00076 GATTable system_config;
00077 struct adaptor_list *adaptor_configs;
00078 };
00079
00080
00081
00082 static GATResult
00083 AddToAdaptorConfig(GATContext error_context, struct adaptor_list *adaptor,
00084 const char *nickname, GATTable config);
00085
00086 static GATResult
00087 ParseConfigFile(GATConfig this, GATContext error_context,
00088 const char *filename);
00089
00090 static enum parse_error Tokenise(const char *line,
00091 char **token1,
00092 char **token2,
00093 enum linetype *type);
00094
00095 static enum parse_error ParseKeyVal(const char *string,
00096 char **token1,
00097 char **token2,
00098 enum linetype *type);
00099
00100 static enum parse_error ParseString(const char *token_start,
00101 char **buffer);
00102
00103 static enum parse_error ParseSection(const char *token_start,
00104 char **buffer);
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 GATConfig GATConfig_Create(GATContext error_context)
00117 {
00118 GAT_USES_STATUS(error_context, "GATConfig_Create");
00119
00120 GATConfig new_config = (GATConfig)malloc(sizeof(struct GATConfig_S));
00121
00122
00123 if (NULL != new_config)
00124 {
00125 char *config_path = NULL;
00126 char const *env_var = NULL;
00127
00128 new_config->system_config = GATTable_Create();
00129 new_config->adaptor_configs = NULL;
00130
00131
00132 if (NULL != (env_var = getenv("GAT_CONFIG_FILE")))
00133 {
00134 config_path = GATUtil_strdup(env_var);
00135 }
00136 else if (NULL != (env_var = getenv("HOME")))
00137 {
00138 config_path = (char *)malloc(strlen(env_var)+sizeof(RC_FILENAME)+2);
00139 if (NULL != config_path)
00140 {
00141 struct stat buf;
00142 sprintf(config_path, "%s/%s", env_var, RC_FILENAME);
00143 if (stat(config_path, &buf))
00144 {
00145
00146 int fd = creat(config_path, S_IREAD | S_IWRITE);
00147 close(fd);
00148
00149
00150 free(config_path);
00151 config_path = NULL;
00152 }
00153 }
00154 else
00155 {
00156 GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00157 }
00158 }
00159
00160
00161
00162
00163 if (NULL != config_path)
00164 {
00165 GATResult retval = ParseConfigFile(new_config, error_context, config_path);
00166 if (GAT_FAILED(retval))
00167 {
00168 char buffer[MAX_PATH+100];
00169 sprintf(buffer, "Error opening config file '%s'", config_path);
00170 GAT_CREATE_STATUS_MSG(retval, buffer);
00171 }
00172 free(config_path);
00173 }
00174 }
00175 else
00176 {
00177 GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00178 }
00179
00180 if (GAT_FAILED(GAT_CURRENT_STATUS()))
00181 {
00182 GATConfig_Destroy(&new_config);
00183 }
00184
00185 GAT_STORE_STATUS();
00186 return new_config;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 void GATConfig_Destroy(GATConfig *object)
00196 {
00197 if(NULL != object && NULL != *object)
00198 {
00199 struct adaptor_list *current = (*object)->adaptor_configs;
00200 while(NULL != current)
00201 {
00202 struct adaptor_list *next = current->next;
00203 GATConfigTableList current_config_table = current->configs;
00204
00205 while (NULL != current_config_table)
00206 {
00207 GATConfigTableList next_config_table = current_config_table->next;
00208
00209 GATTable_Destroy(¤t_config_table->config);
00210 free(current_config_table->nickname);
00211 free(current_config_table);
00212
00213 current_config_table = next_config_table;
00214 }
00215 free(current->name);
00216 free(current);
00217
00218 current = next;
00219 }
00220
00221 GATTable_Destroy(&((*object)->system_config));
00222 free (*object);
00223 *object = NULL;
00224 }
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 GATTable_const GATConfig_GetSystemConfig(GATConfig_const this)
00236 {
00237 return this->system_config;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 GATConfigTableList_const
00252 GATConfig_GetAdaptorConfigs(GATConfig_const this, const char *adaptor)
00253 {
00254 GATConfigTableList retval = NULL;
00255 struct adaptor_list *current = this->adaptor_configs;
00256
00257 for(; NULL != current; current = current->next)
00258 {
00259 if (!strcmp(current->name, adaptor))
00260 {
00261 retval = current->configs;
00262 break;
00263 }
00264 }
00265 return retval;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 GATResult
00281 GATConfig_AddAdaptorConfig(GATConfig this, GATContext error_context,
00282 const char *adaptor, const char *nickname, GATTable config)
00283 {
00284 GAT_USES_STATUS(error_context, "GATConfig_AddAdaptorConfig");
00285
00286 struct adaptor_list *current = NULL;
00287 struct adaptor_list *last = NULL;
00288
00289
00290 for(current = this->adaptor_configs; NULL != current;
00291 last = current, current = current->next)
00292 {
00293 if (!strcmp(current->name, adaptor))
00294 {
00295 break;
00296 }
00297 }
00298
00299 if (NULL == current)
00300 {
00301 struct adaptor_list *new_adaptor =
00302 (struct adaptor_list *)malloc(sizeof(*new_adaptor));
00303 if (NULL != new_adaptor)
00304 {
00305 new_adaptor->name = GATUtil_strdup(adaptor);
00306 if (new_adaptor->name)
00307 {
00308
00309 new_adaptor->next = NULL;
00310 if (NULL != last)
00311 {
00312 last->next = new_adaptor;
00313 }
00314 else
00315 {
00316 this->adaptor_configs = new_adaptor;
00317 }
00318 new_adaptor->configs = NULL;
00319 }
00320 else
00321 {
00322 free(new_adaptor);
00323 new_adaptor = NULL;
00324 GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00325 }
00326 }
00327 else
00328 {
00329 GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00330 }
00331 current = new_adaptor;
00332 }
00333
00334 if (NULL != current)
00335 {
00336 GAT_CREATE_STATUS(AddToAdaptorConfig(error_context, current, nickname,
00337 config));
00338 }
00339
00340 return GAT_RETURN_STATUS();
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 static GATResult
00356 AddToAdaptorConfig(GATContext error_context, struct adaptor_list *adaptor,
00357 const char *nickname, GATTable config)
00358 {
00359 GAT_USES_STATUS(error_context, "AddToAdaptorConfig");
00360
00361 GATConfigTableList current;
00362 GATConfigTableList last = NULL;
00363
00364
00365 for (current = adaptor->configs; NULL != current;
00366 last = current, current = current->next)
00367 {
00368 if (!strcmp(current->nickname, nickname))
00369 {
00370
00371 GAT_CREATE_STATUS(GAT_DUPLICATE_CONFIG);
00372 break;
00373 }
00374 }
00375
00376 if (NULL == current)
00377 {
00378 GATConfigTableList new_config =
00379 (GATConfigTableList)malloc(sizeof(*new_config));
00380 if (NULL != new_config)
00381 {
00382 new_config->nickname = GATUtil_strdup(nickname);
00383 if (NULL != new_config->nickname)
00384 {
00385
00386 new_config->next = NULL;
00387 if (NULL != last)
00388 {
00389 last->next = new_config;
00390 }
00391 else
00392 {
00393 adaptor->configs = new_config;
00394 }
00395 new_config->config = config;
00396 }
00397 else
00398 {
00399 free(new_config);
00400 new_config = NULL;
00401 GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00402 }
00403 }
00404 else
00405 {
00406 GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00407 }
00408 }
00409
00410 return GAT_RETURN_STATUS();
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 static GATResult
00424 ParseConfigFile(GATConfig this, GATContext error_context, const char *filename)
00425 {
00426 GAT_USES_STATUS(error_context, "ParseConfigFile");
00427
00428 FILE *file = NULL;
00429
00430 if (NULL != (file = fopen(filename, "r")))
00431 {
00432 enum parse_error error;
00433 enum linetype type;
00434 char line[LINE_LENGTH+1];
00435 int linenumber = 0;
00436 char *section = NULL;
00437 char *adaptor = NULL;
00438 GATTable current_config = this->system_config;
00439
00440
00441
00442
00443
00444 while (NULL != fgets(line, LINE_LENGTH+1, file))
00445 {
00446 char *token1 = NULL;
00447 char *token2 = NULL;
00448
00449 linenumber++;
00450 error = Tokenise(line, &token1, &token2, &type);
00451
00452 switch(error)
00453 {
00454 case parse_success:
00455 switch(type)
00456 {
00457 case line_blank:
00458 break;
00459
00460 case line_comment:
00461 break;
00462
00463 case line_section:
00464 if (NULL != section)
00465 {
00466 if (NULL != adaptor)
00467 {
00468 GAT_CREATE_STATUS(GATConfig_AddAdaptorConfig(this,
00469 error_context, adaptor, section, current_config));
00470 free(adaptor);
00471 adaptor = NULL;
00472 }
00473 else
00474 {
00475 char buffer[MAX_PATH+100];
00476
00477 sprintf(buffer, "Error <%s:%d>: No adaptor defined in "
00478 "section '%s'.", filename, linenumber, section);
00479 GAT_CREATE_STATUS_MSG(GAT_INVALID_CONFIG_FORMAT, buffer);
00480 }
00481 free(section);
00482 }
00483 section = token1;
00484 current_config = GATTable_Create();
00485 break;
00486
00487 case line_adaptor:
00488 if (NULL != adaptor)
00489 {
00490 char buffer[MAX_PATH+100];
00491 sprintf(buffer, "Error <%s:%d>: Second adaptor defined in "
00492 "section '%s'", filename, linenumber, section);
00493 GAT_CREATE_STATUS_MSG(GAT_INVALID_CONFIG_FORMAT, buffer);
00494 }
00495 else if (NULL == section)
00496 {
00497 char buffer[MAX_PATH+100];
00498 sprintf(buffer, "Error <%s:%d>: Can't define adaptor in "
00499 "default section", filename, linenumber);
00500 }
00501 else
00502 {
00503 adaptor = token1;
00504 }
00505 break;
00506
00507 case line_string:
00508
00509
00510
00511 GATTable_Add_String(current_config, token1, token2);
00512 free(token1);
00513 free(token2);
00514 token1 = NULL;
00515 token2 = NULL;
00516 break;
00517 }
00518 break;
00519
00520 case parse_empty_token:
00521 {
00522 char buffer[MAX_PATH+100];
00523 sprintf(buffer, "Error <%s:%d>: Empty token when parsing line",
00524 filename, linenumber);
00525 GAT_CREATE_STATUS_MSG(GAT_INVALID_CONFIG_FORMAT, buffer);
00526 }
00527 break;
00528
00529 case parse_memory_failure:
00530 {
00531 char buffer[MAX_PATH+100];
00532 sprintf(buffer, "Error <%s:%d>: Out of memory when parsing line",
00533 filename, linenumber);
00534 GAT_CREATE_STATUS_MSG(GAT_INVALID_CONFIG_FORMAT, buffer);
00535 }
00536 break;
00537
00538 case parse_malformed_line:
00539 {
00540 char buffer[MAX_PATH+100];
00541 sprintf(buffer, "Error <%s:%d>: Malformed line", filename,
00542 linenumber);
00543 GAT_CREATE_STATUS_MSG(GAT_INVALID_CONFIG_FORMAT, buffer);
00544 }
00545 break;
00546 }
00547 }
00548
00549
00550
00551 if (NULL != section)
00552 {
00553 if (NULL != adaptor)
00554 {
00555 GAT_CREATE_STATUS(GATConfig_AddAdaptorConfig(this, error_context,
00556 adaptor, section, current_config));
00557 free(adaptor);
00558 adaptor = NULL;
00559 }
00560 else
00561 {
00562 char buffer[MAX_PATH+100];
00563 sprintf(buffer, "Error <%s:%d>: No adaptor defined in section '%s'.",
00564 filename, linenumber, section);
00565 GAT_CREATE_STATUS_MSG(GAT_INVALID_CONFIG_FORMAT, buffer);
00566 }
00567 free(section);
00568 }
00569 }
00570 else
00571 {
00572 GAT_CREATE_STATUS(GAT_FILEOPEN_ERROR);
00573 }
00574
00575 return GAT_RETURN_STATUS();
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 static enum parse_error Tokenise(const char *line,
00594 char **token1,
00595 char **token2,
00596 enum linetype *type)
00597 {
00598 enum parse_error error;
00599 const char *token_start;
00600
00601 error = parse_success;
00602
00603
00604 for(token_start = line;
00605 isspace(*token_start);
00606 token_start++)
00607 {
00608
00609 }
00610
00611 switch(*token_start)
00612 {
00613 case 0 :
00614 *type = line_blank;
00615 break;
00616 case '#' :
00617 *type = line_comment;
00618 break;
00619 case '[' :
00620 *type = line_section;
00621 error = ParseSection(token_start+1, token1);
00622 break;
00623 default :
00624 error = ParseKeyVal(token_start, token1, token2, type);
00625 }
00626
00627 return error;
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 static enum parse_error ParseKeyVal(const char *string,
00645 char **token1,
00646 char **token2,
00647 enum linetype *type)
00648 {
00649 enum parse_error error;
00650 const char *equals;
00651 const char *token_end;
00652 int i;
00653
00654 if((equals = strchr(string, '=')))
00655 {
00656 for(token_end = equals-1;
00657 token_end >= string && isspace(*token_end);
00658 token_end--)
00659 {
00660
00661 }
00662
00663 if(!strncmp(string, "Adaptor", token_end - string))
00664 {
00665 *type = line_adaptor;
00666 error = ParseString(equals+1, token1);
00667 }
00668 else
00669 {
00670 *type = line_string;
00671
00672 if(token_end - string > 0)
00673 {
00674 *token1 = (char *)malloc(token_end-string+2);
00675
00676 if(*token1)
00677 {
00678 for(i=0; i <= token_end - string; i++)
00679 {
00680 (*token1)[i] = string[i];
00681 }
00682 (*token1)[i] = 0;
00683
00684 error = ParseString(equals+1, token2);
00685 }
00686 else
00687 {
00688 error = parse_memory_failure;
00689 }
00690 }
00691 else
00692 {
00693 error = parse_empty_token;
00694 }
00695 }
00696 }
00697 else
00698 {
00699 error = parse_malformed_line;
00700 }
00701
00702 return error;
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 static enum parse_error ParseString(const char *token_start,
00716 char **buffer)
00717 {
00718 enum parse_error error;
00719 const char *token_end;
00720 int i;
00721
00722 error = parse_success;
00723
00724
00725 for(;
00726 isspace(*token_start);
00727 token_start++)
00728 {
00729
00730 }
00731
00732
00733 token_end = strchr(token_start, '#');
00734
00735 if(! token_end)
00736 {
00737 token_end = token_start+strlen(token_start)-1;
00738 }
00739 else
00740 {
00741 token_end--;
00742 }
00743
00744
00745 for(;
00746 token_end >= token_start && isspace(*token_end);
00747 token_end--)
00748 {
00749
00750 }
00751
00752 if(token_end - token_start > 0)
00753 {
00754 *buffer = (char *)malloc(token_end - token_start+2);
00755
00756 if(*buffer)
00757 {
00758 for(i=0; i <= token_end - token_start; i++)
00759 {
00760 (*buffer)[i] = token_start[i];
00761 }
00762 (*buffer)[i] = 0;
00763 }
00764 else
00765 {
00766 error = parse_memory_failure;
00767 }
00768 }
00769 else
00770 {
00771 error = parse_empty_token;
00772 }
00773
00774
00775 return error;
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 static enum parse_error ParseSection(const char *token_start,
00788 char **buffer)
00789 {
00790 enum parse_error error;
00791 const char *token_end;
00792 int i;
00793
00794 error = parse_success;
00795
00796
00797 for(;
00798 isspace(*token_start);
00799 token_start++)
00800 {
00801
00802 }
00803
00804 for(token_end = token_start;
00805 *token_end && *token_end != ']';
00806 token_end++)
00807 {
00808
00809 }
00810
00811 if(*token_end != ']')
00812 {
00813 error = parse_malformed_line;
00814 }
00815 else
00816 {
00817 token_end--;
00818 }
00819
00820 if(error == parse_success)
00821 {
00822 if(token_end - token_start > 0)
00823 {
00824 *buffer = (char *)malloc(token_end - token_start+2);
00825
00826 if(*buffer)
00827 {
00828 for(i=0; i <= token_end - token_start; i++)
00829 {
00830 (*buffer)[i] = token_start[i];
00831 }
00832 (*buffer)[i] = 0;
00833 }
00834 else
00835 {
00836 error = parse_memory_failure;
00837 }
00838 }
00839 else
00840 {
00841 error = parse_empty_token;
00842 }
00843 }
00844
00845
00846
00847
00848
00849 return error;
00850 }
00851