OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [snmp/] [lib/] [v2_0/] [src/] [read_config.c] - Blame information for rev 201

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      ./lib/current/src/read_config.c
4
//
5
//
6
//==========================================================================
7
//####ECOSGPLCOPYRIGHTBEGIN####
8
// -------------------------------------------
9
// This file is part of eCos, the Embedded Configurable Operating System.
10
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
11
//
12
// eCos is free software; you can redistribute it and/or modify it under
13
// the terms of the GNU General Public License as published by the Free
14
// Software Foundation; either version 2 or (at your option) any later version.
15
//
16
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
17
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19
// for more details.
20
//
21
// You should have received a copy of the GNU General Public License along
22
// with eCos; if not, write to the Free Software Foundation, Inc.,
23
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
24
//
25
// As a special exception, if other files instantiate templates or use macros
26
// or inline functions from this file, or you compile this file and link it
27
// with other works to produce a work based on this file, this file does not
28
// by itself cause the resulting work to be covered by the GNU General Public
29
// License. However the source code for this file must still be made available
30
// in accordance with section (3) of the GNU General Public License.
31
//
32
// This exception does not invalidate any other reasons why a work based on
33
// this file might be covered by the GNU General Public License.
34
//
35
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
36
// at http://sources.redhat.com/ecos/ecos-license/
37
// -------------------------------------------
38
//####ECOSGPLCOPYRIGHTEND####
39
//####UCDSNMPCOPYRIGHTBEGIN####
40
//
41
// -------------------------------------------
42
//
43
// Portions of this software may have been derived from the UCD-SNMP
44
// project,  <http://ucd-snmp.ucdavis.edu/>  from the University of
45
// California at Davis, which was originally based on the Carnegie Mellon
46
// University SNMP implementation.  Portions of this software are therefore
47
// covered by the appropriate copyright disclaimers included herein.
48
//
49
// The release used was version 4.1.2 of May 2000.  "ucd-snmp-4.1.2"
50
// -------------------------------------------
51
//
52
//####UCDSNMPCOPYRIGHTEND####
53
//==========================================================================
54
//#####DESCRIPTIONBEGIN####
55
//
56
// Author(s):    hmt
57
// Contributors: hmt
58
// Date:         2000-05-30
59
// Purpose:      Port of UCD-SNMP distribution to eCos.
60
// Description:  
61
//              
62
//
63
//####DESCRIPTIONEND####
64
//
65
//==========================================================================
66
/********************************************************************
67
       Copyright 1989, 1991, 1992 by Carnegie Mellon University
68
 
69
                          Derivative Work -
70
Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
71
 
72
                         All Rights Reserved
73
 
74
Permission to use, copy, modify and distribute this software and its
75
documentation for any purpose and without fee is hereby granted,
76
provided that the above copyright notice appears in all copies and
77
that both that copyright notice and this permission notice appear in
78
supporting documentation, and that the name of CMU and The Regents of
79
the University of California not be used in advertising or publicity
80
pertaining to distribution of the software without specific written
81
permission.
82
 
83
CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
84
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
85
WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL CMU OR
86
THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
87
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
88
FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
89
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
90
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
91
*********************************************************************/
92
/*
93
 * read_config.c
94
 */
95
 
96
#include <pkgconf/snmplib.h>
97
#include <config.h>
98
 
99
#include <stdio.h>
100
#include <ctype.h>
101
#if HAVE_STDLIB_H
102
#include <stdlib.h>
103
#endif
104
#if HAVE_STRING_H
105
#include <string.h>
106
#else
107
#include <strings.h>
108
#endif
109
#if HAVE_UNISTD_H
110
#include <unistd.h>
111
#endif
112
#include <sys/types.h>
113
#if HAVE_SYS_PARAM_H
114
#include <sys/param.h>
115
#endif
116
#if TIME_WITH_SYS_TIME
117
# ifdef WIN32
118
#  include <sys/timeb.h>
119
# else
120
#  include <sys/time.h>
121
# endif
122
# include <time.h>
123
#else
124
# if HAVE_SYS_TIME_H
125
#  include <sys/time.h>
126
# else
127
#  include <time.h>
128
# endif
129
#endif
130
#ifdef HAVE_SYS_STAT_H
131
#include <sys/stat.h>
132
#endif
133
#if HAVE_NETINET_IN_H
134
#include <netinet/in.h>
135
#endif
136
#if HAVE_ARPA_INET_H
137
#include <arpa/inet.h>
138
#endif
139
#if HAVE_SYS_SELECT_H
140
#include <sys/select.h>
141
#endif
142
#if HAVE_WINSOCK_H
143
#include <winsock.h>
144
#endif
145
#if HAVE_SYS_SOCKET_H
146
#include <sys/socket.h>
147
#endif
148
#if HAVE_NETDB_H
149
#include <netdb.h>
150
#endif
151
#include <errno.h>
152
 
153
#if HAVE_DMALLOC_H
154
#include <dmalloc.h>
155
#endif
156
 
157
#include "asn1.h"
158
#include "mib.h"
159
#include "parse.h"
160
#include "system.h"
161
#include "snmp_api.h"
162
#include "snmp_debug.h"
163
#include "snmp_logging.h"
164
#include "snmp_impl.h"
165
#include "default_store.h"
166
#include "callback.h"
167
 
168
#include "read_config.h"
169
#include "tools.h"
170
 
171
int config_errors;
172
 
173
struct config_files *config_files = NULL;
174
 
175
struct config_line *
176
register_premib_handler(const char *type,
177
                        const char *token,
178
                        void (*parser) (const char *, char *),
179
                        void (*releaser) (void),
180
                        const char *help)
181
{
182
  struct config_line *ltmp;
183
  ltmp = register_config_handler(type, token, parser, releaser, help);
184
  if (ltmp != NULL)
185
    ltmp->config_time = PREMIB_CONFIG;
186
  return (ltmp);
187
}
188
 
189
struct config_line *
190
register_app_premib_handler(const char *token,
191
                        void (*parser) (const char *, char *),
192
                        void (*releaser) (void),
193
                        const char *help)
194
{
195
  return(register_premib_handler( NULL, token, parser, releaser, help ));
196
}
197
 
198
/*******************************************************************-o-******
199
 * register_config_handler
200
 *
201
 * Parameters:
202
 *      *type
203
 *      *token
204
 *      *parser
205
 *      *releaser
206
 *
207
 * Returns:
208
 *      Pointer to a new config line entry  -OR-  NULL on error.
209
 */
210
struct config_line *
211
register_config_handler(const char *type_param,
212
                        const char *token,
213
                        void (*parser) (const char *, char *),
214
                        void (*releaser) (void),
215
                        const char *help)
216
{
217
  struct config_files **ctmp = &config_files;
218
  struct config_line **ltmp;
219
  const char *type = type_param;
220
 
221
  if ( type == NULL )
222
    type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE);
223
 
224
  /*
225
   * Find type in current list  -OR-  create a new file type.
226
   */
227
  while (*ctmp != NULL && strcmp((*ctmp)->fileHeader, type)) {
228
    ctmp = &((*ctmp)->next);
229
  }
230
 
231
  if (*ctmp == NULL) {
232
    *ctmp = (struct config_files *)
233
      malloc(sizeof(struct config_files));
234
    if ( !*ctmp ) {
235
      return NULL;
236
    }
237
 
238
    (*ctmp)->next                = NULL;
239
    (*ctmp)->start               = NULL;
240
    (*ctmp)->fileHeader  = strdup(type);
241
  }
242
 
243
  /*
244
   * Find parser type in current list  -OR-  create a new
245
   * line parser entry.
246
   */
247
  ltmp = &((*ctmp)->start);
248
 
249
  while (*ltmp != NULL && strcmp((*ltmp)->config_token, token)) {
250
    ltmp = &((*ltmp)->next);
251
  }
252
 
253
  if (*ltmp == NULL) {
254
    *ltmp = (struct config_line *)
255
      malloc(sizeof(struct config_line));
256
    if ( !*ltmp ) {
257
      return NULL;
258
    }
259
 
260
    (*ltmp)->next                = NULL;
261
    (*ltmp)->config_time         = NORMAL_CONFIG;
262
    (*ltmp)->parse_line  = 0;
263
    (*ltmp)->free_func   = 0;
264
    (*ltmp)->config_token        = strdup(token);
265
    if (help != NULL)
266
      (*ltmp)->help = strdup(help);
267
 
268
  }
269
 
270
  /*
271
   * Add/Replace the parse/free functions for the given line type
272
   * in the given file type.
273
   */
274
  (*ltmp)->parse_line = parser;
275
  (*ltmp)->free_func  = releaser;
276
 
277
  return (*ltmp);
278
 
279
}  /* end register_config_handler() */
280
 
281
struct config_line *
282
register_app_config_handler(const char *token,
283
                        void (*parser) (const char *, char *),
284
                        void (*releaser) (void),
285
                        const char *help)
286
{
287
  return(register_config_handler( NULL, token, parser, releaser, help ));
288
}
289
 
290
void
291
unregister_config_handler(const char *type_param,
292
                          const char *token)
293
{
294
  struct config_files **ctmp = &config_files;
295
  struct config_line **ltmp, *ltmp2;
296
  const char *type = type_param;
297
 
298
  if ( type == NULL )
299
    type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE);
300
 
301
  /* find type in current list */
302
  while (*ctmp != NULL && strcmp((*ctmp)->fileHeader,type)) {
303
    ctmp = &((*ctmp)->next);
304
  }
305
 
306
  if (*ctmp == NULL) {
307
    /* Not found, return. */
308
    return;
309
  }
310
 
311
  ltmp = &((*ctmp)->start);
312
  if (*ltmp == NULL) {
313
    /* Not found, return. */
314
    return;
315
  }
316
  if (strcmp((*ltmp)->config_token,token) == 0) {
317
    /* found it at the top of the list */
318
    (*ctmp)->start = (*ltmp)->next;
319
    free((*ltmp)->config_token);
320
    SNMP_FREE((*ltmp)->help);
321
    free(*ltmp);
322
    return;
323
  }
324
  while ((*ltmp)->next != NULL && strcmp((*ltmp)->next->config_token,token)) {
325
    ltmp = &((*ltmp)->next);
326
  }
327
  if (*ltmp == NULL) {
328
    free((*ltmp)->config_token);
329
    SNMP_FREE((*ltmp)->help);
330
    ltmp2 = (*ltmp)->next->next;
331
    free((*ltmp)->next);
332
    (*ltmp)->next = ltmp2;
333
  }
334
}
335
 
336
void
337
unregister_app_config_handler(const char *token)
338
{
339
  unregister_config_handler( NULL, token );
340
}
341
 
342
#ifdef TESTING
343
void print_config_handlers (void)
344
{
345
  struct config_files *ctmp = config_files;
346
  struct config_line *ltmp;
347
 
348
  for(;ctmp != NULL; ctmp = ctmp->next) {
349
    DEBUGMSGTL(("read_config", "read_conf: %s\n", ctmp->fileHeader));
350
    for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next)
351
      DEBUGMSGTL(("read_config", "                   %s\n", ltmp->config_token));
352
  }
353
}
354
#endif
355
 
356
int linecount;
357
const char *curfilename;
358
 
359
void read_config_with_type(const char *filename,
360
                           const char *type)
361
{
362
  struct config_files *ctmp = config_files;
363
  for(;ctmp != NULL && strcmp(ctmp->fileHeader,type); ctmp = ctmp->next);
364
  if (ctmp)
365
    read_config(filename, ctmp->start, EITHER_CONFIG);
366
  else
367
    DEBUGMSGTL(("read_config", "read_config: I have no registrations for type:%s,file:%s\n",
368
           type, filename));
369
}
370
 
371
/*******************************************************************-o-******
372
 * read_config
373
 *
374
 * Parameters:
375
 *      *filename
376
 *      *line_handler
377
 *       when
378
 *
379
 * Read <filename> and process each line in accordance with the list of
380
 * <line_handler> functions.
381
 *
382
 *
383
 * For each line in <filename>, search the list of <line_handler>'s
384
 * for an entry that matches the first token on the line.  This comparison is
385
 * case insensitive.
386
 *
387
 * For each match, check that <when> is the designated time for the
388
 * <line_handler> function to be executed before processing the line.
389
 */
390
void read_config(const char *filename,
391
                 struct config_line *line_handler,
392
                 int when)
393
{
394
#ifdef CYGPKG_SNMPLIB_FILESYSTEM_SUPPORT
395
 
396
  FILE *ifile;
397
  char line[STRINGMAX], token[STRINGMAX], tmpbuf[STRINGMAX];
398
  char *cptr;
399
  int i, done;
400
  struct config_line *lptr;
401
 
402
  linecount = 0;
403
  curfilename = filename;
404
 
405
  if ((ifile = fopen(filename, "r")) == NULL) {
406
#ifdef ENOENT
407
    if (errno == ENOENT) {
408
      DEBUGMSGTL(("read_config", "%s: %s\n", filename, strerror(errno)));
409
    } else
410
#endif /* ENOENT */
411
#ifdef EACCES
412
    if (errno == EACCES) {
413
      DEBUGMSGTL(("read_config", "%s: %s\n", filename, strerror(errno)));
414
    } else
415
#endif /* EACCES */
416
#if defined(ENOENT) || defined(EACCES)
417
    {
418
      snmp_log_perror(filename);
419
    }
420
#else /* defined(ENOENT) || defined(EACCES) */
421
    snmp_log_perror(filename);
422
#endif /* ENOENT */
423
    return;
424
  } else {
425
    DEBUGMSGTL(("read_config", "Reading configuration %s\n", filename));
426
  }
427
 
428
  while (fgets(line, sizeof(line), ifile) != NULL)
429
    {
430
      lptr = line_handler;
431
      linecount++;
432
      cptr = line;
433
      i = strlen(line)-1;
434
      if (line[i] == '\n')
435
        line[i] = 0;
436
      /* check blank line or # comment */
437
      if ((cptr = skip_white(cptr)))
438
        {
439
          cptr = copy_word(cptr,token);
440
          if (cptr == NULL) {
441
            sprintf(tmpbuf,"Blank line following %s token.", token);
442
            config_perror(tmpbuf);
443
          } else {
444
            for(lptr = line_handler, done=0;
445
                lptr != NULL && !done;
446
                lptr = lptr->next) {
447
              if (!strcasecmp(token,lptr->config_token)) {
448
                if (when == EITHER_CONFIG || lptr->config_time == when) {
449
                    DEBUGMSGTL(("read_config", "%s:%d Parsing: %s\n",
450
                                filename, linecount, line));
451
                    (*(lptr->parse_line))(token,cptr);
452
                }
453
                done = 1;
454
              }
455
            }
456
            if (!done && when != PREMIB_CONFIG &&
457
                !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_NO_TOKEN_WARNINGS)) {
458
              sprintf(tmpbuf,"Unknown token: %s.", token);
459
              config_pwarn(tmpbuf);
460
            }
461
          }
462
        }
463
    }
464
  fclose(ifile);
465
#endif
466
  return;
467
 
468
}  /* end read_config() */
469
 
470
 
471
 
472
void
473
free_config (void)
474
{
475
  struct config_files *ctmp = config_files;
476
  struct config_line *ltmp;
477
 
478
  for(;ctmp != NULL; ctmp = ctmp->next)
479
    for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next)
480
      if (ltmp->free_func)
481
        (*(ltmp->free_func))();
482
}
483
 
484
void
485
read_configs (void)
486
{
487
 
488
  char *optional_config = ds_get_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG);
489
  char *type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE);
490
 
491
  DEBUGMSGTL(("read_config","reading normal configuration tokens\n"));
492
 
493
  if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS))
494
    read_config_files(NORMAL_CONFIG);
495
 
496
 /* do this even when the normal above wasn't done */
497
  if (optional_config && type)
498
    read_config_with_type(optional_config, type);
499
 
500
  snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG,
501
                      NULL);
502
}
503
 
504
void
505
read_premib_configs (void)
506
{
507
  DEBUGMSGTL(("read_config","reading premib configuration tokens\n"));
508
 
509
  if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS))
510
    read_config_files(PREMIB_CONFIG);
511
 
512
  snmp_call_callbacks(SNMP_CALLBACK_LIBRARY,
513
                      SNMP_CALLBACK_POST_PREMIB_READ_CONFIG,
514
                      NULL);
515
}
516
 
517
 
518
 
519
 
520
/*******************************************************************-o-******
521
 * read_config_files
522
 *
523
 * Parameters:
524
 *      when    == PREMIB_CONFIG, NORMAL_CONFIG  -or-  EITHER_CONFIG
525
 *
526
 *
527
 * Traverse the list of config file types, performing the following actions
528
 * for each --
529
 *
530
 * First, build a search path for config files.  If the contents of
531
 * environment variable SNMPCONFPATH are NULL, then use the following
532
 * path list (where the last entry exists only if HOME is non-null):
533
 *
534
 *      SNMPSHAREPATH:SNMPLIBPATH:${HOME}/.snmp
535
 *
536
 * Then, In each of these directories, read config files by the name of:
537
 *
538
 *      <dir>/<fileHeader>.conf         -AND-
539
 *      <dir>/<fileHeader>.local.conf
540
 *
541
 * where <fileHeader> is taken from the config file type structure.
542
 *
543
 *
544
 * PREMIB_CONFIG causes free_config() to be invoked prior to any other action.
545
 *
546
 *
547
 * EXITs if any 'config_errors' are logged while parsing config file lines.
548
 */
549
void
550
read_config_files (int when)
551
{
552
#ifdef CYGPKG_SNMPLIB_FILESYSTEM_SUPPORT
553
 
554
  int i, j;
555
  char configfile[300];
556
  char *envconfpath, *homepath;
557
  char *cptr1, *cptr2;
558
  char defaultPath[SPRINT_MAX_LEN];
559
 
560
  struct config_files *ctmp = config_files;
561
  struct config_line *ltmp;
562
  struct stat statbuf;
563
 
564
  if (when == PREMIB_CONFIG)
565
    free_config();
566
 
567
  /* read all config file types */
568
  for(;ctmp != NULL; ctmp = ctmp->next) {
569
 
570
    ltmp = ctmp->start;
571
 
572
    /* read the config files */
573
    if ((envconfpath = getenv("SNMPCONFPATH")) == NULL) {
574
      homepath=getenv("HOME");
575
      sprintf(defaultPath,"%s%c%s%c%s%s%s%s%c%s",
576
              SNMPCONFPATH, ENV_SEPARATOR_CHAR,
577
              SNMPSHAREPATH, ENV_SEPARATOR_CHAR, SNMPLIBPATH,
578
              ((homepath == NULL) ? "" : ENV_SEPARATOR),
579
              ((homepath == NULL) ? "" : homepath),
580
              ((homepath == NULL) ? "" : "/.snmp"),
581
              ENV_SEPARATOR_CHAR, PERSISTENT_DIRECTORY);
582
      envconfpath = defaultPath;
583
    }
584
    envconfpath = strdup(envconfpath);  /* prevent actually writing in env */
585
    DEBUGMSGTL(("read_config","config path used:%s\n", envconfpath));
586
    cptr1 = cptr2 = envconfpath;
587
    i = 1;
588
    while (i && *cptr2 != 0) {
589
      while(*cptr1 != 0 && *cptr1 != ENV_SEPARATOR_CHAR)
590
        cptr1++;
591
      if (*cptr1 == 0)
592
        i = 0;
593
      else
594
        *cptr1 = 0;
595
      /*
596
       * for proper persistent storage retrival, we need to read old backup
597
       * copies of the previous storage files.  If the application in
598
       * question has died without the proper call to snmp_clean_persistent,
599
       * then we read all the configuration files we can, starting with
600
       * the oldest first.
601
       */
602
#ifdef CYGPKG_SNMPLIB_PERSISTENT_FILESYSTEM
603
      if (strncmp(cptr2, PERSISTENT_DIRECTORY,
604
                  strlen(PERSISTENT_DIRECTORY)) == 0 ||
605
          (getenv("SNMP_PERSISTENT_FILE") != NULL &&
606
           strncmp(cptr2, getenv("SNMP_PERSISTENT_FILE"),
607
                   strlen(getenv("SNMP_PERSISTENT_FILE"))) == 0)) {
608
        /* limit this to the known storage directory only */
609
        for(j=0; j <= MAX_PERSISTENT_BACKUPS; j++) {
610
          sprintf(configfile,"%s/%s.%d.conf",cptr2, ctmp->fileHeader, j);
611
          if (stat(configfile, &statbuf) != 0) {
612
            /* file not there, continue */
613
            break;
614
          } else {
615
            /* backup exists, read it */
616
            DEBUGMSGTL(("read_config_files","old config file found: %s, parsing\n", configfile));
617
            read_config (configfile, ltmp, when);
618
          }
619
        }
620
      }
621
#endif
622
      sprintf(configfile,"%s/%s.conf",cptr2, ctmp->fileHeader);
623
      read_config (configfile, ltmp, when);
624
      sprintf(configfile,"%s/%s.local.conf",cptr2, ctmp->fileHeader);
625
      read_config (configfile, ltmp, when);
626
      cptr2 = ++cptr1;
627
    }
628
    free(envconfpath);
629
  }
630
 
631
#ifdef CYGPKG_SNMPLIB_PERSISTENT_FILESYSTEM
632
  if (config_errors) {
633
    snmp_log(LOG_ERR, "ucd-snmp: %d errors in config file\n", config_errors);
634
/*    exit(1); */
635
  }
636
#endif
637
#endif
638
}
639
 
640
void read_config_print_usage(const char *lead)
641
{
642
  struct config_files *ctmp = config_files;
643
  struct config_line *ltmp;
644
 
645
  if (lead == NULL)
646
    lead = "";
647
 
648
  for(ctmp = config_files; ctmp != NULL; ctmp = ctmp->next) {
649
    snmp_log(LOG_INFO, "%sIn %s.conf and %s.local.conf:\n", lead, ctmp->fileHeader,
650
            ctmp->fileHeader);
651
    for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next) {
652
      if (ltmp->help != NULL)
653
        snmp_log(LOG_INFO, "%s%s%-15s %s\n", lead, lead, ltmp->config_token,
654
                 ltmp->help);
655
    }
656
  }
657
}
658
 
659
/*******************************************************************-o-******
660
 * read_config_store
661
 *
662
 * Parameters:
663
 *      *type
664
 *      *line
665
 *
666
 *
667
 * Append line to a file named either ENV(SNMP_PERSISTENT_FILE) or
668
 *   "<PERSISTENT_DIRECTORY>/<type>.conf".
669
 * Add a trailing newline to the stored file if necessary.
670
 *
671
 * Intended for use by applications to store permenant configuration
672
 * information generated by sets or persistent counters.
673
 *
674
 */
675
void
676
read_config_store(const char *type, const char *line)
677
{
678
#ifdef CYGPKG_SNMPLIB_PERSISTENT_FILESYSTEM
679
  char file[512], *filep;
680
  FILE *fout;
681
#ifdef PERSISTENT_MASK
682
  mode_t oldmask;
683
#endif
684
 
685
  /* store configuration directives in the following order of preference:
686
     1. ENV variable SNMP_PERSISTENT_FILE
687
     2. configured <PERSISTENT_DIRECTORY>/<type>.conf
688
  */
689
  if ((filep = getenv("SNMP_PERSISTENT_FILE")) == NULL) {
690
    sprintf(file,"%s/%s.conf",PERSISTENT_DIRECTORY,type);
691
    filep = file;
692
  }
693
 
694
#ifdef PERSISTENT_MASK
695
  oldmask = umask(PERSISTENT_MASK);
696
#endif
697
  if (mkdirhier(filep, AGENT_DIRECTORY_MODE, 1)) {
698
      snmp_log(LOG_ERR, "Failed to create the persistent directory for %s\n",
699
               file);
700
  }
701
  if ((fout = fopen(filep, "a")) != NULL) {
702
    fprintf(fout,line);
703
    if (line[strlen(line)] != '\n')
704
      fprintf(fout,"\n");
705
    DEBUGMSGTL(("read_config","storing: %s\n",line));
706
    fclose(fout);
707
  } else {
708
    DEBUGMSGTL(("read_config","open failure"));
709
  }
710
#ifdef PERSISTENT_MASK
711
  umask(oldmask);
712
#endif
713
 
714
#endif
715
}  /* end read_config_store() */
716
 
717
void
718
read_app_config_store(const char *line)
719
{
720
  read_config_store(ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE), line);
721
}
722
 
723
 
724
 
725
 
726
/*******************************************************************-o-******
727
 * snmp_save_persistent
728
 *
729
 * Parameters:
730
 *      *type
731
 *
732
 *
733
 * Save the file "<PERSISTENT_DIRECTORY>/<type>.conf" into a backup copy
734
 * called "<PERSISTENT_DIRECTORY>/<type>.%d.conf", which %d is an
735
 * incrementing number on each call, but less than MAX_PERSISTENT_BACKUPS.
736
 *
737
 * Should be called just before all persistent information is supposed to be
738
 * written to move aside the existing persistent cache.
739
 * snmp_clean_persistent should then be called afterward all data has been
740
 * saved to remove these backup files.
741
 *
742
 * Note: on an rename error, the files are removed rather than saved.
743
 *
744
 */
745
void
746
snmp_save_persistent(const char *type)
747
{
748
#ifndef ECOSFIXME_NEEDFILESYSTEM
749
 
750
  char file[512], fileold[512];
751
  struct stat statbuf;
752
  int j;
753
 
754
  DEBUGMSGTL(("snmp_save_persistent","saving %s files...\n", type));
755
  sprintf(file,"%s/%s.conf", PERSISTENT_DIRECTORY, type);
756
  if (stat(file, &statbuf) == 0) {
757
    for(j=0; j <= MAX_PERSISTENT_BACKUPS; j++) {
758
      sprintf(fileold,"%s/%s.%d.conf", PERSISTENT_DIRECTORY, type, j);
759
      if (stat(fileold, &statbuf) != 0) {
760
        DEBUGMSGTL(("snmp_save_persistent"," saving old config file: %s -> %s.\n", file, fileold));
761
        if (rename(file, fileold)) {
762
          unlink(file);/* moving it failed, try nuking it, as leaving
763
                          it around is very bad. */
764
        }
765
        break;
766
      }
767
    }
768
  }
769
#endif
770
}
771
 
772
 
773
/*******************************************************************-o-******
774
 * snmp_clean_persistent
775
 *
776
 * Parameters:
777
 *      *type
778
 *
779
 *
780
 * Unlink all backup files called "<PERSISTENT_DIRECTORY>/<type>.%d.conf".
781
 *
782
 * Should be called just after we successfull dumped the last of the
783
 * persistent data, to remove the backup copies of previous storage dumps.
784
 *
785
 * XXX  Worth overwriting with random bytes first?  This would
786
 *      ensure that the data is destroyed, even a buffer containing the
787
 *      data persists in memory or swap.  Only important if secrets
788
 *      will be stored here.
789
 */
790
void
791
snmp_clean_persistent(const char *type)
792
{
793
#ifndef ECOSFIXME_NEEDFILESYSTEM
794
 
795
  char file[512];
796
  struct stat statbuf;
797
  int j;
798
 
799
  DEBUGMSGTL(("snmp_clean_persistent","cleaning %s files...\n", type));
800
  sprintf(file,"%s/%s.conf",PERSISTENT_DIRECTORY,type);
801
  if (stat(file, &statbuf) == 0) {
802
    for(j=0; j <= MAX_PERSISTENT_BACKUPS; j++) {
803
      sprintf(file,"%s/%s.%d.conf", PERSISTENT_DIRECTORY, type, j);
804
      if (stat(file, &statbuf) == 0) {
805
        DEBUGMSGTL(("snmp_clean_persistent"," removing old config file: %s\n", file));
806
        unlink(file);
807
      }
808
    }
809
  }
810
#endif
811
}
812
 
813
 
814
 
815
 
816
/* config_perror: prints a warning string associated with a file and
817
   line number of a .conf file and increments the error count. */
818
void config_perror(const char *string)
819
{
820
  config_pwarn(string);
821
  config_errors++;
822
}
823
 
824
void config_pwarn(const char *string)
825
{
826
  snmp_log(LOG_WARNING, "%s: line %d: %s\n", curfilename, linecount, string);
827
}
828
 
829
/* skip all white spaces and return 1 if found something either end of
830
   line or a comment character */
831
char *skip_white(char *ptr)
832
{
833
 
834
  if (ptr == NULL) return (NULL);
835
  while (*ptr != 0 && isspace(*ptr)) ptr++;
836
  if (*ptr == 0 || *ptr == '#') return (NULL);
837
  return (ptr);
838
}
839
 
840
char *skip_not_white(char *ptr)
841
{
842
 
843
  if (ptr == NULL) return (NULL);
844
  while (*ptr != 0 && !isspace(*ptr)) ptr++;
845
  if (*ptr == 0 || *ptr == '#') return (NULL);
846
  return (ptr);
847
}
848
 
849
char *skip_token(char *ptr)
850
{
851
  ptr = skip_white(ptr);
852
  ptr = skip_not_white(ptr);
853
  ptr = skip_white(ptr);
854
  return (ptr);
855
}
856
 
857
/* copy_word
858
   copies the next 'token' from 'from' into 'to'.
859
   currently a token is anything seperate by white space
860
   or within quotes (double or single) (i.e. "the red rose"
861
   is one token, \"the red rose\" is three tokens)
862
   a '\' character will allow a quote character to be treated
863
   as a regular character
864
   It returns a pointer to first non-white space after the end of the token
865
   being copied or to 0 if we reach the end.*/
866
 
867
char *copy_word(char *from, char *to)
868
{
869
  char quote;
870
  if ( (*from == '\"') || (*from =='\'') ){
871
    quote = *(from++);
872
    while ( (*from != quote) && (*from != 0) ) {
873
      if ((*from == '\\') && (*(from+1) != 0)) {
874
        *to++ = *(from+1);
875
        from = from +2;
876
      }
877
      else  *to++ = *from++;
878
    }
879
    if (*from == 0) {
880
      DEBUGMSGTL(("read_config_copy_word",
881
                  "no end quote found in config string\n"));
882
    } else from++;
883
  }
884
  else {
885
    while (*from != 0 && !isspace(*from)) {
886
      if ((*from == '\\') && (*(from+1) != 0)) {
887
        *to++ = *(from+1);
888
        from = from +2;
889
      }
890
      else  *to++ = *from++;
891
    }
892
  }
893
  *to = 0;
894
  from = skip_white(from);
895
  return(from);
896
}  /* copy_word */
897
 
898
/* read_config_save_octet_string(): saves an octet string as a length
899
   followed by a string of hex */
900
char *read_config_save_octet_string(char *saveto, u_char *str, size_t len) {
901
  int i;
902
  if (str != NULL) {
903
    sprintf(saveto, "0x");
904
    saveto += 2;
905
    for(i = 0; i < (int)len; i++) {
906
      sprintf(saveto,"%02x", str[i]);
907
      saveto = saveto + 2;
908
    }
909
    return saveto;
910
  } else {
911
    sprintf(saveto,"\"\"");
912
    saveto += 2;
913
  }
914
  return saveto;
915
}
916
 
917
/* read_config_read_octet_string(): reads an octet string that was
918
   saved by the read_config_save_octet_string() function */
919
char *read_config_read_octet_string(char *readfrom, u_char **str, size_t *len) {
920
  u_char *cptr=NULL;
921
  char *cptr1;
922
  u_int tmp;
923
  int i;
924
 
925
  if (readfrom == NULL || str == NULL)
926
    return NULL;
927
 
928
  if (strncasecmp(readfrom,"0x",2) == 0) {
929
    /* A hex string submitted. How long? */
930
    readfrom += 2;
931
    cptr1 = skip_not_white(readfrom);
932
    if (cptr1)
933
      *len = (cptr1 - readfrom);
934
    else
935
      *len = strlen(readfrom);
936
 
937
    if (*len % 2) {
938
      DEBUGMSGTL(("read_config_read_octet_string","invalid hex string: wrong length"));
939
      return NULL;
940
    }
941
    *len = *len / 2;
942
 
943
    /* malloc data space if needed */
944
    if (*str == NULL) {
945
      if (*len == 0) {
946
        /* null length string found */
947
        cptr = NULL;
948
 
949
      } else if (*len > 0 && (str == NULL || (cptr = (u_char *)malloc(*len)) == NULL)) {
950
        return NULL;
951
      }
952
      *str = cptr;
953
    } else {
954
      cptr = *str;
955
    }
956
 
957
    /* copy data */
958
    for(i = 0; i < (int)*len; i++) {
959
      sscanf(readfrom,"%2x",&tmp);
960
      *cptr++ = (u_char) tmp;
961
      readfrom += 2;
962
    }
963
    readfrom = skip_white(readfrom);
964
  } else {
965
    /* Normal string */
966
 
967
    /* malloc data space if needed */
968
    if (*str == NULL) {
969
      char buf[SNMP_MAXBUF];
970
      readfrom = copy_word(readfrom, buf);
971
 
972
      *len = strlen(buf);
973
      /* malloc an extra space to add a null */
974
      if (*len > 0 && (str == NULL ||
975
                       (cptr = (u_char *) malloc(*len + 1))
976
                       == NULL))
977
        return NULL;
978
      *str = cptr;
979
      if (cptr)
980
        memcpy(cptr, buf, (*len+1));
981
    } else {
982
      readfrom = copy_word(readfrom, (char *)*str);
983
    }
984
  }
985
 
986
  return readfrom;
987
}
988
 
989
 
990
/* read_config_save_objid(): saves an objid as a numerical string */
991
char *read_config_save_objid(char *saveto, oid *objid, size_t len) {
992
  int i;
993
 
994
  if (len == 0) {
995
    strcat(saveto, "NULL");
996
    saveto += strlen(saveto);
997
    return saveto;
998
  }
999
 
1000
  /* in case len=0, this makes it easier to read it back in */
1001
  for(i=0; i < (int)len; i++) {
1002
    sprintf(saveto,".%ld", objid[i]);
1003
    saveto += strlen(saveto);
1004
  }
1005
  return saveto;
1006
}
1007
 
1008
/* read_config_read_objid(): reads an objid from a format saved by the above */
1009
char *read_config_read_objid(char *readfrom, oid **objid, size_t *len) {
1010
 
1011
  if (objid == NULL || readfrom == NULL)
1012
    return NULL;
1013
 
1014
  if (*objid != NULL) {
1015
    char buf[SPRINT_MAX_LEN];
1016
 
1017
    if (strncmp(readfrom,"NULL",4) == 0) {
1018
      /* null length oid */
1019
      *len = 0;
1020
    } else {
1021
      /* read_objid is touchy with trailing stuff */
1022
      copy_word(readfrom, buf);
1023
 
1024
      /* read the oid into the buffer passed to us */
1025
      if (!read_objid(buf, *objid, len)) {
1026
        DEBUGMSGTL(("read_config_read_objid","Invalid OID"));
1027
        return NULL;
1028
      }
1029
    }
1030
 
1031
    readfrom = skip_token(readfrom);
1032
  } else {
1033
    if (strncmp(readfrom,"NULL",4) == 0) {
1034
      /* null length oid */
1035
      *len = 0;
1036
      readfrom = skip_token(readfrom);
1037
    } else {
1038
      /* space needs to be malloced.  Call ourself recursively to figure
1039
       out how long the oid actually is */
1040
      oid obuf[MAX_OID_LEN];
1041
      size_t obuflen = MAX_OID_LEN;
1042
      oid *oidp = obuf;
1043
      oid **oidpp = &oidp;   /* done this way for odd, untrue, gcc warnings */
1044
 
1045
      readfrom = read_config_read_objid(readfrom, oidpp, &obuflen);
1046
 
1047
      /* Then malloc and copy the results */
1048
      *len = obuflen;
1049
      if (*len > 0 && (*objid = (oid*)malloc(*len * sizeof(oid))) == NULL)
1050
        return NULL;
1051
 
1052
      if (obuflen > 0)
1053
        memcpy(*objid, obuf, obuflen*sizeof(oid));
1054
    }
1055
  }
1056
  return readfrom;
1057
}
1058
 
1059
/* read_config_read_data():
1060
   reads data of a given type from a token(s) on a configuration line.
1061
 
1062
   Returns: character pointer to the next token in the configuration line.
1063
            NULL if none left.
1064
            NULL if an unknown type.
1065
*/
1066
char *read_config_read_data(int type, char *readfrom, void *dataptr, size_t *len) {
1067
 
1068
  int *intp;
1069
  char **charpp;
1070
  oid  **oidpp;
1071
 
1072
  if (dataptr == NULL || readfrom == NULL)
1073
    return NULL;
1074
 
1075
  switch(type) {
1076
    case ASN_INTEGER:
1077
      intp = (int *) dataptr;
1078
      *intp = atoi(readfrom);
1079
      readfrom = skip_token(readfrom);
1080
      return readfrom;
1081
 
1082
    case ASN_OCTET_STR:
1083
      charpp = (char **) dataptr;
1084
      return read_config_read_octet_string(readfrom, (u_char **) charpp, len);
1085
 
1086
    case ASN_OBJECT_ID:
1087
      oidpp = (oid **) dataptr;
1088
      return read_config_read_objid(readfrom, oidpp, len);
1089
 
1090
    default:
1091
      DEBUGMSGTL(("read_config_read_data","Fail: Unknown type: %d", type));
1092
      return NULL;
1093
  }
1094
  return NULL;
1095
}
1096
 
1097
/* read_config_read_data():
1098
   reads data of a given type from a token(s) on a configuration line.
1099
 
1100
   Returns: character pointer to the next token in the configuration line.
1101
            NULL if none left.
1102
            NULL if an unknown type.
1103
*/
1104
char *read_config_store_data(int type, char *storeto, void *dataptr, size_t *len) {
1105
 
1106
  int *intp;
1107
  u_char **charpp;
1108
  oid  **oidpp;
1109
 
1110
  if (dataptr == NULL || storeto == NULL)
1111
    return NULL;
1112
 
1113
  switch(type) {
1114
    case ASN_INTEGER:
1115
      intp = (int *) dataptr;
1116
      sprintf(storeto," %d", *intp);
1117
      return (storeto + strlen(storeto));
1118
 
1119
    case ASN_OCTET_STR:
1120
      charpp = (u_char **) dataptr;
1121
      return read_config_save_octet_string(storeto, *charpp, *len);
1122
 
1123
    case ASN_OBJECT_ID:
1124
      oidpp = (oid **) dataptr;
1125
      return read_config_save_objid(storeto, *oidpp, *len);
1126
 
1127
    default:
1128
      DEBUGMSGTL(("read_config_store_data","Fail: Unknown type: %d", type));
1129
      return NULL;
1130
  }
1131
  return NULL;
1132
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.