1 //==========================================================================
3 // ./lib/current/src/read_config.c
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.
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.
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
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.
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.
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.
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####
41 // -------------------------------------------
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.
49 // The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2"
50 // -------------------------------------------
52 //####UCDSNMPCOPYRIGHTEND####
53 //==========================================================================
54 //#####DESCRIPTIONBEGIN####
59 // Purpose: Port of UCD-SNMP distribution to eCos.
63 //####DESCRIPTIONEND####
65 //==========================================================================
66 /********************************************************************
67 Copyright 1989, 1991, 1992 by Carnegie Mellon University
70 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
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
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 *********************************************************************/
96 #include <pkgconf/snmplib.h>
112 #include <sys/types.h>
114 #include <sys/param.h>
116 #if TIME_WITH_SYS_TIME
118 # include <sys/timeb.h>
120 # include <sys/time.h>
125 # include <sys/time.h>
130 #ifdef HAVE_SYS_STAT_H
131 #include <sys/stat.h>
133 #if HAVE_NETINET_IN_H
134 #include <netinet/in.h>
137 #include <arpa/inet.h>
139 #if HAVE_SYS_SELECT_H
140 #include <sys/select.h>
145 #if HAVE_SYS_SOCKET_H
146 #include <sys/socket.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"
168 #include "read_config.h"
173 struct config_files *config_files = NULL;
176 register_premib_handler(const char *type,
178 void (*parser) (const char *, char *),
179 void (*releaser) (void),
182 struct config_line *ltmp;
183 ltmp = register_config_handler(type, token, parser, releaser, help);
185 ltmp->config_time = PREMIB_CONFIG;
190 register_app_premib_handler(const char *token,
191 void (*parser) (const char *, char *),
192 void (*releaser) (void),
195 return(register_premib_handler( NULL, token, parser, releaser, help ));
198 /*******************************************************************-o-******
199 * register_config_handler
208 * Pointer to a new config line entry -OR- NULL on error.
211 register_config_handler(const char *type_param,
213 void (*parser) (const char *, char *),
214 void (*releaser) (void),
217 struct config_files **ctmp = &config_files;
218 struct config_line **ltmp;
219 const char *type = type_param;
222 type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE);
225 * Find type in current list -OR- create a new file type.
227 while (*ctmp != NULL && strcmp((*ctmp)->fileHeader, type)) {
228 ctmp = &((*ctmp)->next);
232 *ctmp = (struct config_files *)
233 malloc(sizeof(struct config_files));
238 (*ctmp)->next = NULL;
239 (*ctmp)->start = NULL;
240 (*ctmp)->fileHeader = strdup(type);
244 * Find parser type in current list -OR- create a new
247 ltmp = &((*ctmp)->start);
249 while (*ltmp != NULL && strcmp((*ltmp)->config_token, token)) {
250 ltmp = &((*ltmp)->next);
254 *ltmp = (struct config_line *)
255 malloc(sizeof(struct config_line));
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);
266 (*ltmp)->help = strdup(help);
271 * Add/Replace the parse/free functions for the given line type
272 * in the given file type.
274 (*ltmp)->parse_line = parser;
275 (*ltmp)->free_func = releaser;
279 } /* end register_config_handler() */
282 register_app_config_handler(const char *token,
283 void (*parser) (const char *, char *),
284 void (*releaser) (void),
287 return(register_config_handler( NULL, token, parser, releaser, help ));
291 unregister_config_handler(const char *type_param,
294 struct config_files **ctmp = &config_files;
295 struct config_line **ltmp, *ltmp2;
296 const char *type = type_param;
299 type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE);
301 /* find type in current list */
302 while (*ctmp != NULL && strcmp((*ctmp)->fileHeader,type)) {
303 ctmp = &((*ctmp)->next);
307 /* Not found, return. */
311 ltmp = &((*ctmp)->start);
313 /* Not found, return. */
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);
324 while ((*ltmp)->next != NULL && strcmp((*ltmp)->next->config_token,token)) {
325 ltmp = &((*ltmp)->next);
328 free((*ltmp)->config_token);
329 SNMP_FREE((*ltmp)->help);
330 ltmp2 = (*ltmp)->next->next;
332 (*ltmp)->next = ltmp2;
337 unregister_app_config_handler(const char *token)
339 unregister_config_handler( NULL, token );
343 void print_config_handlers (void)
345 struct config_files *ctmp = config_files;
346 struct config_line *ltmp;
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));
357 const char *curfilename;
359 void read_config_with_type(const char *filename,
362 struct config_files *ctmp = config_files;
363 for(;ctmp != NULL && strcmp(ctmp->fileHeader,type); ctmp = ctmp->next);
365 read_config(filename, ctmp->start, EITHER_CONFIG);
367 DEBUGMSGTL(("read_config", "read_config: I have no registrations for type:%s,file:%s\n",
371 /*******************************************************************-o-******
379 * Read <filename> and process each line in accordance with the list of
380 * <line_handler> functions.
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
387 * For each match, check that <when> is the designated time for the
388 * <line_handler> function to be executed before processing the line.
390 void read_config(const char *filename,
391 struct config_line *line_handler,
394 #ifdef CYGPKG_SNMPLIB_FILESYSTEM_SUPPORT
397 char line[STRINGMAX], token[STRINGMAX], tmpbuf[STRINGMAX];
400 struct config_line *lptr;
403 curfilename = filename;
405 if ((ifile = fopen(filename, "r")) == NULL) {
407 if (errno == ENOENT) {
408 DEBUGMSGTL(("read_config", "%s: %s\n", filename, strerror(errno)));
412 if (errno == EACCES) {
413 DEBUGMSGTL(("read_config", "%s: %s\n", filename, strerror(errno)));
416 #if defined(ENOENT) || defined(EACCES)
418 snmp_log_perror(filename);
420 #else /* defined(ENOENT) || defined(EACCES) */
421 snmp_log_perror(filename);
425 DEBUGMSGTL(("read_config", "Reading configuration %s\n", filename));
428 while (fgets(line, sizeof(line), ifile) != NULL)
436 /* check blank line or # comment */
437 if ((cptr = skip_white(cptr)))
439 cptr = copy_word(cptr,token);
441 sprintf(tmpbuf,"Blank line following %s token.", token);
442 config_perror(tmpbuf);
444 for(lptr = line_handler, done=0;
445 lptr != NULL && !done;
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);
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);
468 } /* end read_config() */
475 struct config_files *ctmp = config_files;
476 struct config_line *ltmp;
478 for(;ctmp != NULL; ctmp = ctmp->next)
479 for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next)
481 (*(ltmp->free_func))();
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);
491 DEBUGMSGTL(("read_config","reading normal configuration tokens\n"));
493 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS))
494 read_config_files(NORMAL_CONFIG);
496 /* do this even when the normal above wasn't done */
497 if (optional_config && type)
498 read_config_with_type(optional_config, type);
500 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG,
505 read_premib_configs (void)
507 DEBUGMSGTL(("read_config","reading premib configuration tokens\n"));
509 if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS))
510 read_config_files(PREMIB_CONFIG);
512 snmp_call_callbacks(SNMP_CALLBACK_LIBRARY,
513 SNMP_CALLBACK_POST_PREMIB_READ_CONFIG,
520 /*******************************************************************-o-******
524 * when == PREMIB_CONFIG, NORMAL_CONFIG -or- EITHER_CONFIG
527 * Traverse the list of config file types, performing the following actions
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):
534 * SNMPSHAREPATH:SNMPLIBPATH:${HOME}/.snmp
536 * Then, In each of these directories, read config files by the name of:
538 * <dir>/<fileHeader>.conf -AND-
539 * <dir>/<fileHeader>.local.conf
541 * where <fileHeader> is taken from the config file type structure.
544 * PREMIB_CONFIG causes free_config() to be invoked prior to any other action.
547 * EXITs if any 'config_errors' are logged while parsing config file lines.
550 read_config_files (int when)
552 #ifdef CYGPKG_SNMPLIB_FILESYSTEM_SUPPORT
555 char configfile[300];
556 char *envconfpath, *homepath;
558 char defaultPath[SPRINT_MAX_LEN];
560 struct config_files *ctmp = config_files;
561 struct config_line *ltmp;
564 if (when == PREMIB_CONFIG)
567 /* read all config file types */
568 for(;ctmp != NULL; ctmp = ctmp->next) {
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;
584 envconfpath = strdup(envconfpath); /* prevent actually writing in env */
585 DEBUGMSGTL(("read_config","config path used:%s\n", envconfpath));
586 cptr1 = cptr2 = envconfpath;
588 while (i && *cptr2 != 0) {
589 while(*cptr1 != 0 && *cptr1 != ENV_SEPARATOR_CHAR)
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
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 */
615 /* backup exists, read it */
616 DEBUGMSGTL(("read_config_files","old config file found: %s, parsing\n", configfile));
617 read_config (configfile, ltmp, when);
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);
631 #ifdef CYGPKG_SNMPLIB_PERSISTENT_FILESYSTEM
633 snmp_log(LOG_ERR, "ucd-snmp: %d errors in config file\n", config_errors);
640 void read_config_print_usage(const char *lead)
642 struct config_files *ctmp = config_files;
643 struct config_line *ltmp;
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,
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,
659 /*******************************************************************-o-******
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.
671 * Intended for use by applications to store permenant configuration
672 * information generated by sets or persistent counters.
676 read_config_store(const char *type, const char *line)
678 #ifdef CYGPKG_SNMPLIB_PERSISTENT_FILESYSTEM
679 char file[512], *filep;
681 #ifdef PERSISTENT_MASK
685 /* store configuration directives in the following order of preference:
686 1. ENV variable SNMP_PERSISTENT_FILE
687 2. configured <PERSISTENT_DIRECTORY>/<type>.conf
689 if ((filep = getenv("SNMP_PERSISTENT_FILE")) == NULL) {
690 sprintf(file,"%s/%s.conf",PERSISTENT_DIRECTORY,type);
694 #ifdef PERSISTENT_MASK
695 oldmask = umask(PERSISTENT_MASK);
697 if (mkdirhier(filep, AGENT_DIRECTORY_MODE, 1)) {
698 snmp_log(LOG_ERR, "Failed to create the persistent directory for %s\n",
701 if ((fout = fopen(filep, "a")) != NULL) {
703 if (line[strlen(line)] != '\n')
705 DEBUGMSGTL(("read_config","storing: %s\n",line));
708 DEBUGMSGTL(("read_config","open failure"));
710 #ifdef PERSISTENT_MASK
715 } /* end read_config_store() */
718 read_app_config_store(const char *line)
720 read_config_store(ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE), line);
726 /*******************************************************************-o-******
727 * snmp_save_persistent
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.
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.
742 * Note: on an rename error, the files are removed rather than saved.
746 snmp_save_persistent(const char *type)
748 #ifndef ECOSFIXME_NEEDFILESYSTEM
750 char file[512], fileold[512];
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. */
773 /*******************************************************************-o-******
774 * snmp_clean_persistent
780 * Unlink all backup files called "<PERSISTENT_DIRECTORY>/<type>.%d.conf".
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.
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.
791 snmp_clean_persistent(const char *type)
793 #ifndef ECOSFIXME_NEEDFILESYSTEM
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));
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)
820 config_pwarn(string);
824 void config_pwarn(const char *string)
826 snmp_log(LOG_WARNING, "%s: line %d: %s\n", curfilename, linecount, string);
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)
834 if (ptr == NULL) return (NULL);
835 while (*ptr != 0 && isspace(*ptr)) ptr++;
836 if (*ptr == 0 || *ptr == '#') return (NULL);
840 char *skip_not_white(char *ptr)
843 if (ptr == NULL) return (NULL);
844 while (*ptr != 0 && !isspace(*ptr)) ptr++;
845 if (*ptr == 0 || *ptr == '#') return (NULL);
849 char *skip_token(char *ptr)
851 ptr = skip_white(ptr);
852 ptr = skip_not_white(ptr);
853 ptr = skip_white(ptr);
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.*/
867 char *copy_word(char *from, char *to)
870 if ( (*from == '\"') || (*from =='\'') ){
872 while ( (*from != quote) && (*from != 0) ) {
873 if ((*from == '\\') && (*(from+1) != 0)) {
877 else *to++ = *from++;
880 DEBUGMSGTL(("read_config_copy_word",
881 "no end quote found in config string\n"));
885 while (*from != 0 && !isspace(*from)) {
886 if ((*from == '\\') && (*(from+1) != 0)) {
890 else *to++ = *from++;
894 from = skip_white(from);
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) {
903 sprintf(saveto, "0x");
905 for(i = 0; i < (int)len; i++) {
906 sprintf(saveto,"%02x", str[i]);
911 sprintf(saveto,"\"\"");
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) {
925 if (readfrom == NULL || str == NULL)
928 if (strncasecmp(readfrom,"0x",2) == 0) {
929 /* A hex string submitted. How long? */
931 cptr1 = skip_not_white(readfrom);
933 *len = (cptr1 - readfrom);
935 *len = strlen(readfrom);
938 DEBUGMSGTL(("read_config_read_octet_string","invalid hex string: wrong length"));
943 /* malloc data space if needed */
946 /* null length string found */
949 } else if (*len > 0 && (str == NULL || (cptr = (u_char *)malloc(*len)) == NULL)) {
958 for(i = 0; i < (int)*len; i++) {
959 sscanf(readfrom,"%2x",&tmp);
960 *cptr++ = (u_char) tmp;
963 readfrom = skip_white(readfrom);
967 /* malloc data space if needed */
969 char buf[SNMP_MAXBUF];
970 readfrom = copy_word(readfrom, buf);
973 /* malloc an extra space to add a null */
974 if (*len > 0 && (str == NULL ||
975 (cptr = (u_char *) malloc(*len + 1))
980 memcpy(cptr, buf, (*len+1));
982 readfrom = copy_word(readfrom, (char *)*str);
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) {
995 strcat(saveto, "NULL");
996 saveto += strlen(saveto);
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);
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) {
1011 if (objid == NULL || readfrom == NULL)
1014 if (*objid != NULL) {
1015 char buf[SPRINT_MAX_LEN];
1017 if (strncmp(readfrom,"NULL",4) == 0) {
1018 /* null length oid */
1021 /* read_objid is touchy with trailing stuff */
1022 copy_word(readfrom, buf);
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"));
1031 readfrom = skip_token(readfrom);
1033 if (strncmp(readfrom,"NULL",4) == 0) {
1034 /* null length oid */
1036 readfrom = skip_token(readfrom);
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;
1043 oid **oidpp = &oidp; /* done this way for odd, untrue, gcc warnings */
1045 readfrom = read_config_read_objid(readfrom, oidpp, &obuflen);
1047 /* Then malloc and copy the results */
1049 if (*len > 0 && (*objid = (oid*)malloc(*len * sizeof(oid))) == NULL)
1053 memcpy(*objid, obuf, obuflen*sizeof(oid));
1059 /* read_config_read_data():
1060 reads data of a given type from a token(s) on a configuration line.
1062 Returns: character pointer to the next token in the configuration line.
1064 NULL if an unknown type.
1066 char *read_config_read_data(int type, char *readfrom, void *dataptr, size_t *len) {
1072 if (dataptr == NULL || readfrom == NULL)
1077 intp = (int *) dataptr;
1078 *intp = atoi(readfrom);
1079 readfrom = skip_token(readfrom);
1083 charpp = (char **) dataptr;
1084 return read_config_read_octet_string(readfrom, (u_char **) charpp, len);
1087 oidpp = (oid **) dataptr;
1088 return read_config_read_objid(readfrom, oidpp, len);
1091 DEBUGMSGTL(("read_config_read_data","Fail: Unknown type: %d", type));
1097 /* read_config_read_data():
1098 reads data of a given type from a token(s) on a configuration line.
1100 Returns: character pointer to the next token in the configuration line.
1102 NULL if an unknown type.
1104 char *read_config_store_data(int type, char *storeto, void *dataptr, size_t *len) {
1110 if (dataptr == NULL || storeto == NULL)
1115 intp = (int *) dataptr;
1116 sprintf(storeto," %d", *intp);
1117 return (storeto + strlen(storeto));
1120 charpp = (u_char **) dataptr;
1121 return read_config_save_octet_string(storeto, *charpp, *len);
1124 oidpp = (oid **) dataptr;
1125 return read_config_save_objid(storeto, *oidpp, *len);
1128 DEBUGMSGTL(("read_config_store_data","Fail: Unknown type: %d", type));