00001 #include <net-snmp/net-snmp-config.h>
00002 #include <net-snmp/net-snmp-includes.h>
00003
00004 #include <stdio.h>
00005 #include <ctype.h>
00006 #if HAVE_STDLIB_H
00007 # include <stdlib.h>
00008 #endif
00009 #if HAVE_UNISTD_H
00010 # include <unistd.h>
00011 #endif
00012 #if HAVE_STRING_H
00013 # include <string.h>
00014 #else
00015 # include <strings.h>
00016 #endif
00017
00018 #include <sys/types.h>
00019
00020 #if HAVE_LIMITS_H
00021 # include <limits.h>
00022 #endif
00023 #if HAVE_SYS_PARAM_H
00024 # include <sys/param.h>
00025 #endif
00026 #ifdef HAVE_SYS_STAT_H
00027 # include <sys/stat.h>
00028 #endif
00029 #ifdef HAVE_FCNTL_H
00030 # include <fcntl.h>
00031 #endif
00032
00033 #include <errno.h>
00034
00035 #if HAVE_DMALLOC_H
00036 # include <dmalloc.h>
00037 #endif
00038
00039 #include <net-snmp/types.h>
00040 #include <net-snmp/library/snmp_debug.h>
00041 #include <net-snmp/library/container.h>
00042 #include <net-snmp/library/file_utils.h>
00043 #include <net-snmp/library/text_utils.h>
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 void
00055 _pm_save_index_string_string(FILE *f, netsnmp_container *cin,
00056 int flags);
00057 void
00058 _pm_save_everything(FILE *f, netsnmp_container *cin, int flags);
00059 void
00060 _pm_user_function(FILE *f, netsnmp_container *cin,
00061 netsnmp_line_process_info *lpi, int flags);
00062
00063
00064
00065
00066
00067 int _process_line_tvi(netsnmp_line_info *line_info, void *mem,
00068 struct netsnmp_line_process_info_s* lpi);
00069
00070
00071
00072
00073
00074
00075
00076
00077
00081 netsnmp_container *
00082 netsnmp_file_text_parse(netsnmp_file *f, netsnmp_container *cin,
00083 int parse_mode, u_int flags, void *context)
00084 {
00085 netsnmp_container *c = cin;
00086 FILE *fin;
00087 int rc;
00088
00089 if (NULL == f)
00090 return NULL;
00091
00092 if ((NULL == c) && (!(flags & PM_FLAG_NO_CONTAINER))) {
00093 c = netsnmp_container_find("text_parse:binary_array");
00094 if (NULL == c)
00095 return NULL;
00096 }
00097
00098 rc = netsnmp_file_open(f);
00099 if (rc < 0) {
00100 if ((NULL !=c) && (c != cin))
00101 CONTAINER_FREE(c);
00102 return NULL;
00103 }
00104
00105
00106
00107
00108
00109 fin = fdopen(f->fd, "r");
00110 if (NULL == fin) {
00111 if (NS_FI_AUTOCLOSE(f->ns_flags))
00112 close(f->fd);
00113 if ((NULL !=c) && (c != cin))
00114 CONTAINER_FREE(c);
00115 return NULL;
00116 }
00117
00118 switch (parse_mode) {
00119
00120 case PM_SAVE_EVERYTHING:
00121 _pm_save_everything(fin, c, flags);
00122 break;
00123
00124 case PM_INDEX_STRING_STRING:
00125 _pm_save_index_string_string(fin, c, flags);
00126 break;
00127
00128 case PM_USER_FUNCTION:
00129 if (NULL != context)
00130 _pm_user_function(fin, c, (netsnmp_line_process_info*)context,
00131 flags);
00132 break;
00133
00134 default:
00135 snmp_log(LOG_ERR, "unknown parse mode %d\n", parse_mode);
00136 break;
00137 }
00138
00139
00140
00141
00142
00143
00144 fclose(fin);
00145 f->fd = -1;
00146
00147 return c;
00148 }
00149
00150 netsnmp_container *
00151 netsnmp_text_token_container_from_file(const char *file, u_int flags,
00152 netsnmp_container *cin, void *context)
00153 {
00154 netsnmp_line_process_info lpi;
00155 netsnmp_container *c = cin, *c_rc;
00156 netsnmp_file *fp;
00157
00158 if (NULL == file)
00159 return NULL;
00160
00161
00162
00163
00164 fp = netsnmp_file_fill(NULL, file, O_RDONLY, 0, 0);
00165 if (NULL == fp)
00166 return NULL;
00167
00168 memset(&lpi, 0x0, sizeof(lpi));
00169 lpi.mem_size = sizeof(netsnmp_token_value_index);
00170 lpi.process = _process_line_tvi;
00171 lpi.user_context = context;
00172
00173 if (NULL == c) {
00174 c = netsnmp_container_find("string:binary_array");
00175 if (NULL == c) {
00176 snmp_log(LOG_ERR,"malloc failed\n");
00177 netsnmp_file_release(fp);
00178 return NULL;
00179 }
00180 }
00181
00182 c_rc = netsnmp_file_text_parse(fp, c, PM_USER_FUNCTION, 0, &lpi);
00183
00184
00185
00186
00187
00188 if ((NULL == c_rc) && (NULL == cin)) {
00189 CONTAINER_FREE(c);
00190 c = NULL;
00191 }
00192 else
00193 c = c_rc;
00194
00195
00196
00197
00198 netsnmp_file_release(fp);
00199
00200 return c;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00214 void
00215 _pm_save_everything(FILE *f, netsnmp_container *cin, int flags)
00216 {
00217 char line[STRINGMAX], *ptr;
00218 size_t len;
00219
00220 netsnmp_assert(NULL != f);
00221 netsnmp_assert(NULL != cin);
00222
00223 while (fgets(line, sizeof(line), f) != NULL) {
00224
00225 ptr = line;
00226 len = strlen(line) - 1;
00227 if (line[len] == '\n')
00228 line[len] = 0;
00229
00230
00231
00232
00233 if (flags & PM_FLAG_SKIP_WHITESPACE) {
00234 if (NULL == (ptr = skip_white(ptr)))
00235 continue;
00236 }
00237
00238 ptr = strdup(line);
00239 if (NULL == ptr) {
00240 snmp_log(LOG_ERR,"malloc failed\n");
00241 break;
00242 }
00243
00244 CONTAINER_INSERT(cin,ptr);
00245 }
00246 }
00247
00252 void
00253 _pm_save_index_string_string(FILE *f, netsnmp_container *cin,
00254 int flags)
00255 {
00256 char line[STRINGMAX], *ptr;
00257 netsnmp_token_value_index *tvi;
00258 size_t count = 0, len;
00259
00260 netsnmp_assert(NULL != f);
00261 netsnmp_assert(NULL != cin);
00262
00263 while (fgets(line, sizeof(line), f) != NULL) {
00264
00265 ++count;
00266 ptr = line;
00267 len = strlen(line) - 1;
00268 if (line[len] == '\n')
00269 line[len] = 0;
00270
00271
00272
00273
00274 if (flags & PM_FLAG_SKIP_WHITESPACE) {
00275 if (NULL == (ptr = skip_white(ptr)))
00276 continue;
00277 }
00278
00279 tvi = SNMP_MALLOC_TYPEDEF(netsnmp_token_value_index);
00280 if (NULL == tvi) {
00281 snmp_log(LOG_ERR,"malloc failed\n");
00282 break;
00283 }
00284
00285
00286
00287
00288
00289 tvi->index = count;
00290 tvi->token = strdup(line);
00291 if (NULL == tvi->token) {
00292 snmp_log(LOG_ERR,"malloc failed\n");
00293 free(tvi);
00294 break;
00295 }
00296 tvi->value.cp = skip_not_white(tvi->token);
00297 if (NULL != tvi->value.cp) {
00298 *(tvi->value.cp) = 0;
00299 ++(tvi->value.cp);
00300 }
00301 CONTAINER_INSERT(cin, tvi);
00302 }
00303 }
00304
00309 void
00310 _pm_user_function(FILE *f, netsnmp_container *cin,
00311 netsnmp_line_process_info *lpi, int flags)
00312 {
00313 char buf[STRINGMAX];
00314 netsnmp_line_info li;
00315 void *mem = NULL;
00316 int rc;
00317
00318 netsnmp_assert(NULL != f);
00319 netsnmp_assert(NULL != cin);
00320
00321
00322
00323
00324 if (flags & PMLP_FLAG_ALLOC_LINE) {
00325 if (0 != lpi->line_max)
00326 li.line_max = lpi->line_max;
00327 else
00328 li.line_max = STRINGMAX;
00329 li.line = calloc(li.line_max, 1);
00330 if (NULL == li.line) {
00331 snmp_log(LOG_ERR,"malloc failed\n");
00332 return;
00333 }
00334 }
00335 else {
00336 li.line = buf;
00337 li.line_max = sizeof(buf);
00338 }
00339
00340 li.index = 0;
00341 while (fgets(li.line, li.line_max, f) != NULL) {
00342
00343 ++li.index;
00344 li.start = li.line;
00345 li.line_len = strlen(li.line) - 1;
00346 if ((!(lpi->flags & PMLP_FLAG_LEAVE_NEWLINE)) &&
00347 (li.line[li.line_len] == '\n'))
00348 li.line[li.line_len] = 0;
00349
00350
00351
00352
00353 if (!(lpi->flags & PMLP_FLAG_PROCESS_WHITESPACE)) {
00354 if (NULL == (li.start = skip_white(li.start)))
00355 continue;
00356 }
00357
00358
00359
00360
00361
00362
00363 if ((0 != lpi->mem_size) && (NULL == mem)) {
00364 mem = calloc(lpi->mem_size, 1);
00365 if (NULL == mem) {
00366 snmp_log(LOG_ERR,"malloc failed\n");
00367 break;
00368 }
00369 }
00370
00371
00372
00373
00374 if (lpi->flags & PMLP_FLAG_STRDUP_LINE) {
00375 li.start = strdup(li.start);
00376 if (NULL == li.start) {
00377 snmp_log(LOG_ERR,"malloc failed\n");
00378 break;
00379 }
00380 }
00381 else if (lpi->flags & PMLP_FLAG_ALLOC_LINE) {
00382 li.start = li.line;
00383 }
00384
00385
00386
00387
00388
00389
00390 li.start_len = strlen(li.start);
00391 rc = (*lpi->process)(&li, mem, lpi);
00392 if (PMLP_RC_MEMORY_USED == rc) {
00393
00394 if (!(lpi->flags & PMLP_FLAG_NO_CONTAINER))
00395 CONTAINER_INSERT(cin, mem);
00396
00397 mem = NULL;
00398
00399 if (lpi->flags & PMLP_FLAG_ALLOC_LINE) {
00400 li.line = calloc(li.line_max, 1);
00401 if (NULL == li.line) {
00402 snmp_log(LOG_ERR,"malloc failed\n");
00403 break;
00404 }
00405 }
00406 }
00407 else if (PMLP_RC_MEMORY_UNUSED == rc ) {
00408
00409
00410
00411
00412 if (lpi->flags & PMLP_FLAG_STRDUP_LINE)
00413 free(li.start);
00414 }
00415 else {
00416 if (PMLP_RC_STOP_PROCESSING != rc )
00417 snmp_log(LOG_ERR, "unknown rc %d from text processor\n", rc);
00418 break;
00419 }
00420 }
00421 SNMP_FREE(mem);
00422 }
00423
00424
00425
00426
00427
00428
00433 int
00434 _process_line_tvi(netsnmp_line_info *line_info, void *mem,
00435 struct netsnmp_line_process_info_s* lpi)
00436 {
00437 netsnmp_token_value_index *tvi = (netsnmp_token_value_index *)mem;
00438 char *ptr;
00439
00440
00441
00442
00443 ptr = skip_not_white(line_info->start);
00444 if (NULL == ptr) {
00445 DEBUGMSGTL(("text:util:tvi", "no value after token '%s'\n",
00446 line_info->start));
00447 return PMLP_RC_MEMORY_UNUSED;
00448 }
00449
00450
00451
00452
00453 *(ptr++) = 0;
00454 ptr = skip_white(ptr);
00455 if (NULL == ptr) {
00456 DEBUGMSGTL(("text:util:tvi", "no value after token '%s'\n",
00457 line_info->start));
00458 return PMLP_RC_MEMORY_UNUSED;
00459 }
00460
00461
00462
00463
00464 switch((int)lpi->user_context) {
00465
00466 case PMLP_TYPE_UNSIGNED:
00467 tvi->value.ul = strtoul(ptr, NULL, 0);
00468 if ((errno == ERANGE) &&(ULONG_MAX == tvi->value.sl))
00469 snmp_log(LOG_WARNING,"value overflow\n");
00470 break;
00471
00472
00473 case PMLP_TYPE_INTEGER:
00474 tvi->value.ul = strtol(ptr, NULL, 0);
00475 if ((errno == ERANGE) &&
00476 ((LONG_MAX == tvi->value.sl) ||
00477 (LONG_MIN == tvi->value.sl)))
00478 snmp_log(LOG_WARNING,"value over/under-flow\n");
00479 break;
00480
00481 case PMLP_TYPE_STRING:
00482 tvi->value.cp = strdup(ptr);
00483 break;
00484
00485 case PMLP_TYPE_BOOLEAN:
00486 if (isdigit(*ptr))
00487 tvi->value.ul = strtoul(ptr, NULL, 0);
00488 else if (strcasecmp(ptr,"true") == 0)
00489 tvi->value.ul = 1;
00490 else if (strcasecmp(ptr,"false") == 0)
00491 tvi->value.ul = 0;
00492 else {
00493 snmp_log(LOG_WARNING,"bad value for boolean\n");
00494 return PMLP_RC_MEMORY_UNUSED;
00495 }
00496 break;
00497
00498 default:
00499 snmp_log(LOG_ERR,"unsupported value type %d\n",
00500 (int)lpi->user_context);
00501 break;
00502 }
00503
00504
00505
00506
00507 tvi->token = strdup(line_info->start);
00508 tvi->index = line_info->index;
00509
00510 return PMLP_RC_MEMORY_USED;
00511 }
00512