read_config.c
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:28k
源码类别:

SNMP编程

开发平台:

C/C++

  1. /*
  2.  * read_config.c
  3.  */
  4. #include <config.h>
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #if HAVE_STDLIB_H
  8. #include <stdlib.h>
  9. #endif
  10. #if HAVE_STRING_H
  11. #include <string.h>
  12. #else
  13. #include <strings.h>
  14. #endif
  15. #if HAVE_UNISTD_H
  16. #include <unistd.h>
  17. #endif
  18. #include <sys/types.h>
  19. #if HAVE_SYS_PARAM_H
  20. #include <sys/param.h>
  21. #endif
  22. #if TIME_WITH_SYS_TIME
  23. # ifdef WIN32
  24. #  include <sys/timeb.h>
  25. # else
  26. #  include <time.h>
  27. # endif
  28. # include <time.h>
  29. #else
  30. # if HAVE_SYS_TIME_H
  31. #  include <sys/time.h>
  32. # else
  33. #  include <time.h>
  34. # endif
  35. #endif
  36. #ifdef HAVE_SYS_STAT_H
  37. #endif
  38. #if HAVE_NETINET_IN_H
  39. #include <netinet/in.h>
  40. #endif
  41. #if HAVE_ARPA_INET_H
  42. #include <arpa/inet.h>
  43. #endif
  44. #if HAVE_SYS_SELECT_H
  45. #include <sys/select.h>
  46. #endif
  47. #if HAVE_WINSOCK_H
  48. #include <ip/socket.h>
  49. #endif
  50. #if HAVE_SYS_SOCKET_H
  51. #include <sys/socket.h>
  52. #endif
  53. #if HAVE_NETDB_H
  54. #include <netdb.h>
  55. #endif
  56. #include <errno.h>
  57. #if HAVE_DMALLOC_H
  58. #include <dmalloc.h>
  59. #endif
  60. #include "asn1.h"
  61. #include "mib.h"
  62. #include "parse.h"
  63. #include "system.h"
  64. #include "snmp_api.h"
  65. #include "snmp_debug.h"
  66. #include "snmp_logging.h"
  67. #include "snmp_impl.h"
  68. #include "default_store.h"
  69. #include "callback.h"
  70. #include "read_config.h"
  71. #include "tools.h"
  72. #include <libsys/misc.h>
  73. int config_errors;
  74. struct config_files *config_files = NULL;
  75. extern char *strdup (const char *);
  76. extern char *staticstrdup(const char *);
  77. extern void vacm_parse_view (const char *, char *);
  78. struct config_line *
  79. register_premib_handler(const char *type,
  80. const char *token,
  81. void (*parser) (const char *, char *),
  82. void (*releaser) (void),
  83. const char *help)
  84. {
  85.   struct config_line *ltmp;
  86.   ltmp = register_config_handler(type, token, parser, releaser, help);
  87.   if (ltmp != NULL)
  88.     ltmp->config_time = PREMIB_CONFIG;
  89.   return (ltmp);
  90. }
  91. struct config_line *
  92. register_app_premib_handler(const char *token,
  93. void (*parser) (const char *, char *),
  94. void (*releaser) (void),
  95. const char *help)
  96. {
  97.   return(register_premib_handler( NULL, token, parser, releaser, help ));
  98. }
  99. /*******************************************************************-o-******
  100.  * register_config_handler
  101.  *
  102.  * Parameters:
  103.  * *type
  104.  * *token
  105.  * *parser
  106.  * *releaser
  107.  *      
  108.  * Returns:
  109.  * Pointer to a new config line entry  -OR-  NULL on error.
  110.  */
  111. struct config_line *
  112. register_config_handler(const char *type_param,
  113. const char *token,
  114. void (*parser) (const char *, char *),
  115. void (*releaser) (void),
  116. const char *help)
  117. {
  118.   struct config_files **ctmp = &config_files;
  119.   struct config_line **ltmp;
  120.   const char *type = type_param;
  121.   if ( type == NULL )
  122.     type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE);
  123.   /* 
  124.    * Find type in current list  -OR-  create a new file type.
  125.    */
  126.   while (*ctmp != NULL && strcmp((*ctmp)->fileHeader, type)) {
  127.     ctmp = &((*ctmp)->next);
  128.   }
  129.   if (*ctmp == NULL) {
  130.     *ctmp = (struct config_files *)
  131.       malloc(sizeof(struct config_files));
  132.     if ( !*ctmp ) {
  133.       return NULL;
  134.     }
  135.     (*ctmp)->next  = NULL;
  136.     (*ctmp)->start  = NULL;
  137.     (*ctmp)->fileHeader  = strdup(type);
  138.   }
  139.   /* 
  140.    * Find parser type in current list  -OR-  create a new
  141.    * line parser entry.
  142.    */
  143.   ltmp = &((*ctmp)->start);
  144.   while (*ltmp != NULL && strcmp((*ltmp)->config_token, token)) {
  145.     ltmp = &((*ltmp)->next);
  146.   }
  147.   if (*ltmp == NULL) {
  148.     *ltmp = (struct config_line *)
  149.       malloc(sizeof(struct config_line));
  150.     if ( !*ltmp ) {
  151.       return NULL;
  152.     }
  153.     (*ltmp)->next  = NULL;
  154.     (*ltmp)->config_time  = NORMAL_CONFIG;
  155.     (*ltmp)->parse_line  = 0;
  156.     (*ltmp)->free_func  = 0;
  157.     (*ltmp)->config_token  = staticstrdup(token);
  158.     if (help != NULL)
  159.       (*ltmp)->help = staticstrdup(help);
  160.   }
  161.   /* 
  162.    * Add/Replace the parse/free functions for the given line type
  163.    * in the given file type.
  164.    */
  165.   (*ltmp)->parse_line = parser;
  166.   (*ltmp)->free_func  = releaser;
  167.   return (*ltmp);
  168. }  /* end register_config_handler() */
  169. struct config_line *
  170. register_app_config_handler(const char *token,
  171. void (*parser) (const char *, char *),
  172. void (*releaser) (void),
  173. const char *help)
  174. {
  175.   return(register_config_handler( NULL, token, parser, releaser, help ));
  176. }
  177. #if 0
  178. void
  179. unregister_config_handler(const char *type_param, 
  180.   const char *token)
  181. {
  182.   struct config_files **ctmp = &config_files;
  183.   struct config_line **ltmp, *ltmp2;
  184.   const char *type = type_param;
  185.   if ( type == NULL )
  186.     type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE);
  187.   /* find type in current list */
  188.   while (*ctmp != NULL && strcmp((*ctmp)->fileHeader,type)) {
  189.     ctmp = &((*ctmp)->next);
  190.   }
  191.   if (*ctmp == NULL) {
  192.     /* Not found, return. */
  193.     return;
  194.   }
  195.   
  196.   ltmp = &((*ctmp)->start);
  197.   if (*ltmp == NULL) {
  198.     /* Not found, return. */
  199.     return;
  200.   }
  201.   if (strcmp((*ltmp)->config_token,token) == 0) {
  202.     /* found it at the top of the list */
  203.     (*ctmp)->start = (*ltmp)->next;
  204.     free((*ltmp)->config_token);
  205.     SNMP_FREE((*ltmp)->help);
  206.     free(*ltmp);
  207.     return;
  208.   }
  209.   while ((*ltmp)->next != NULL && strcmp((*ltmp)->next->config_token,token)) {
  210.     ltmp = &((*ltmp)->next);
  211.   }
  212.   if (*ltmp == NULL) {
  213.     free((*ltmp)->config_token);
  214.     SNMP_FREE((*ltmp)->help);
  215.     ltmp2 = (*ltmp)->next->next;
  216.     free((*ltmp)->next);
  217.     (*ltmp)->next = ltmp2;
  218.   }
  219. }
  220. void
  221. unregister_app_config_handler(const char *token)
  222. {
  223.   unregister_config_handler( NULL, token );
  224. }
  225. #endif
  226. #ifdef TESTING
  227. void print_config_handlers (void)
  228. {
  229.   struct config_files *ctmp = config_files;
  230.   struct config_line *ltmp;
  231.   for(;ctmp != NULL; ctmp = ctmp->next) {
  232.     DEBUGMSGTL(("read_config", "read_conf: %sn", ctmp->fileHeader));
  233.     for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next)
  234.       DEBUGMSGTL(("read_config", "                   %sn", ltmp->config_token));
  235.   }
  236. }
  237. #endif
  238. int linecount;
  239. const char *curfilename;
  240. void read_config_with_type(const char *filename, 
  241.    const char *type)
  242. {
  243.   struct config_files *ctmp = config_files;
  244.   for(;ctmp != NULL && strcmp(ctmp->fileHeader,type); ctmp = ctmp->next);
  245.   if (ctmp)
  246.     read_config(filename, ctmp->start, EITHER_CONFIG);
  247.   else
  248.     DEBUGMSGTL(("read_config", "read_config: I have no registrations for type:%s,file:%sn",
  249.            type, filename));
  250. }
  251. /*******************************************************************-o-******
  252.  * read_config
  253.  *
  254.  * Parameters:
  255.  * *filename
  256.  * *line_handler
  257.  *  when
  258.  *
  259.  * Read <filename> and process each line in accordance with the list of
  260.  * <line_handler> functions.
  261.  *
  262.  *
  263.  * For each line in <filename>, search the list of <line_handler>'s 
  264.  * for an entry that matches the first token on the line.  This comparison is
  265.  * case insensitive.
  266.  *
  267.  * For each match, check that <when> is the designated time for the
  268.  * <line_handler> function to be executed before processing the line.
  269.  */
  270. void read_config(const char *filename,
  271.  struct config_line *line_handler,
  272.  int when)
  273. {
  274. #ifdef UCD_SNMP
  275.   FILE *ifile;
  276.   char line[STRINGMAX], token[STRINGMAX], tmpbuf[STRINGMAX];
  277.   char *cptr;
  278.   int i, done;
  279.   struct config_line *lptr;
  280.   linecount = 0;
  281.   curfilename = filename;
  282.   
  283.   if ((ifile = fopen(filename, "r")) == NULL) {
  284. #ifdef ENOENT
  285.     if (errno == ENOENT) {
  286.       DEBUGMSGTL(("read_config", "%s: %sn", filename, strerror(errno)));
  287.     } else
  288. #endif /* ENOENT */
  289. #ifdef EACCES
  290.     if (errno == EACCES) {
  291.       DEBUGMSGTL(("read_config", "%s: %sn", filename, strerror(errno)));
  292.     } else
  293. #endif /* EACCES */
  294. #if defined(ENOENT) || defined(EACCES)
  295.     {
  296.       snmp_log_perror(filename);
  297.     }
  298. #else /* defined(ENOENT) || defined(EACCES) */
  299.     snmp_log_perror(filename);
  300. #endif /* ENOENT */
  301.     return;
  302.   } else {
  303.     DEBUGMSGTL(("read_config", "Reading configuration %sn", filename));
  304.   }
  305.   while (fgets(line, sizeof(line), ifile) != NULL) 
  306.     {
  307.       lptr = line_handler;
  308.       linecount++;
  309.       cptr = line;
  310.       i = strlen(line)-1;
  311.       if (line[i] == 'n')
  312.         line[i] = 0;
  313.       /* check blank line or # comment */
  314.       if ((cptr = skip_white(cptr)))
  315. {
  316.           cptr = copy_word(cptr,token);
  317.           if (cptr == NULL) {
  318.             sprintf(tmpbuf,"Blank line following %s token.", token);
  319.             config_perror(tmpbuf);
  320.           } else {
  321.             for(lptr = line_handler, done=0;
  322.                 lptr != NULL && !done;
  323.                 lptr = lptr->next) {
  324.               if (!strcasecmp(token,lptr->config_token)) {
  325.                 if (when == EITHER_CONFIG || lptr->config_time == when) {
  326.                     DEBUGMSGTL(("read_config", "%s:%d Parsing: %sn",
  327.                                 filename, linecount, line));
  328.                     (*(lptr->parse_line))(token,cptr);
  329.                 }
  330.                 done = 1;
  331.               }
  332.             }
  333.             if (!done && when != PREMIB_CONFIG &&
  334.                 !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_NO_TOKEN_WARNINGS)) {
  335.               sprintf(tmpbuf,"Unknown token: %s.", token);
  336.               config_pwarn(tmpbuf);
  337.             }
  338.           }
  339. }
  340.     }
  341.   fclose(ifile);
  342.   return;
  343. #endif
  344. }  /* end read_config() */
  345. void
  346. free_config (void)
  347. {
  348.   struct config_files *ctmp = config_files;
  349.   struct config_line *ltmp;
  350.   for(;ctmp != NULL; ctmp = ctmp->next)
  351.     for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next)
  352.       if (ltmp->free_func)
  353.         (*(ltmp->free_func))();
  354. }
  355. static char snmpv3_default_view_str[] = SNMPV3_DEFAULT_VIEW" included .1.3.6.1";
  356. void
  357. read_configs (void)
  358. {
  359.   char *optional_config = ds_get_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG);
  360.   char *type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE);
  361.   DEBUGMSGTL(("read_config","reading normal configuration tokensn"));
  362.   
  363.   if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS))
  364.     read_config_files(NORMAL_CONFIG);
  365.  /* do this even when the normal above wasn't done */
  366.   if (optional_config && type)
  367.     read_config_with_type(optional_config, type);
  368.   snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG,
  369.                       NULL);
  370.   vacm_parse_view("view",snmpv3_default_view_str/*SNMPV3_DEFAULT_VIEW" included .1.3.6.1"*/);
  371. }
  372. void
  373. read_premib_configs (void)
  374. {
  375.   DEBUGMSGTL(("read_config","reading premib configuration tokensn"));
  376.   if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS))
  377.     read_config_files(PREMIB_CONFIG);
  378.   snmp_call_callbacks(SNMP_CALLBACK_LIBRARY,
  379.                       SNMP_CALLBACK_POST_PREMIB_READ_CONFIG,
  380.                       NULL);
  381. }
  382. /*******************************************************************-o-******
  383.  * read_config_files
  384.  *
  385.  * Parameters:
  386.  * when == PREMIB_CONFIG, NORMAL_CONFIG  -or-  EITHER_CONFIG
  387.  *
  388.  *
  389.  * Traverse the list of config file types, performing the following actions
  390.  * for each --
  391.  *
  392.  * First, build a search path for config files.  If the contents of 
  393.  * environment variable SNMPCONFPATH are NULL, then use the following
  394.  * path list (where the last entry exists only if HOME is non-null):
  395.  *
  396.  * SNMPSHAREPATH:SNMPLIBPATH:${HOME}/.snmp
  397.  *
  398.  * Then, In each of these directories, read config files by the name of:
  399.  *
  400.  * <dir>/<fileHeader>.conf -AND-
  401.  * <dir>/<fileHeader>.local.conf
  402.  *
  403.  * where <fileHeader> is taken from the config file type structure.
  404.  *
  405.  *
  406.  * PREMIB_CONFIG causes free_config() to be invoked prior to any other action.
  407.  *
  408.  *
  409.  * EXITs if any 'config_errors' are logged while parsing config file lines.
  410.  */
  411. void
  412. read_config_files (int when)
  413. {
  414. #ifdef UCD_SNMP
  415.   int i, j;
  416.   char configfile[300];
  417.   char *envconfpath, *homepath;
  418.   char *cptr1, *cptr2;
  419.   char defaultPath[SPRINT_MAX_LEN];
  420.   struct config_files *ctmp = config_files;
  421.   struct config_line *ltmp;
  422.   struct stat statbuf;
  423.   
  424.   if (when == PREMIB_CONFIG)
  425.     free_config();
  426.   /* read all config file types */
  427.   for(;ctmp != NULL; ctmp = ctmp->next) {
  428.     ltmp = ctmp->start;
  429.     /* read the config files */
  430.     if ((envconfpath = getenv("SNMPCONFPATH")) == NULL) {
  431.       homepath=getenv("HOME");
  432.       sprintf(defaultPath,"%s%c%s%c%s%s%s%s%c%s",
  433.       SNMPCONFPATH, ENV_SEPARATOR_CHAR,
  434.               SNMPSHAREPATH, ENV_SEPARATOR_CHAR, SNMPLIBPATH,
  435.               ((homepath == NULL) ? "" : ENV_SEPARATOR),
  436.               ((homepath == NULL) ? "" : homepath),
  437.               ((homepath == NULL) ? "" : "/.snmp"),
  438.               ENV_SEPARATOR_CHAR, PERSISTENT_DIRECTORY);
  439.       envconfpath = defaultPath;
  440.     }
  441.     envconfpath = strdup(envconfpath);  /* prevent actually writing in env */
  442.     DEBUGMSGTL(("read_config","config path used:%sn", envconfpath));
  443.     cptr1 = cptr2 = envconfpath;
  444.     i = 1;
  445.     while (i && *cptr2 != 0) {
  446.       while(*cptr1 != 0 && *cptr1 != ENV_SEPARATOR_CHAR)
  447.         cptr1++;
  448.       if (*cptr1 == 0)
  449.         i = 0;
  450.       else
  451.         *cptr1 = 0;
  452.       /*
  453.        * for proper persistent storage retrival, we need to read old backup
  454.        * copies of the previous storage files.  If the application in
  455.        * question has died without the proper call to snmp_clean_persistent,
  456.        * then we read all the configuration files we can, starting with
  457.        * the oldest first.
  458.        */
  459.       if (strncmp(cptr2, PERSISTENT_DIRECTORY,
  460.                   strlen(PERSISTENT_DIRECTORY)) == 0 ||
  461.           (getenv("SNMP_PERSISTENT_FILE") != NULL &&
  462.            strncmp(cptr2, getenv("SNMP_PERSISTENT_FILE"),
  463.                    strlen(getenv("SNMP_PERSISTENT_FILE"))) == 0)) {
  464.         /* limit this to the known storage directory only */
  465.         for(j=0; j <= MAX_PERSISTENT_BACKUPS; j++) {
  466.           sprintf(configfile,"%s/%s.%d.conf",cptr2, ctmp->fileHeader, j);
  467.           if (stat(configfile, &statbuf) != 0) {
  468.             /* file not there, continue */
  469.             break;
  470.           } else {
  471.             /* backup exists, read it */
  472.             DEBUGMSGTL(("read_config_files","old config file found: %s, parsingn", configfile));
  473.             read_config (configfile, ltmp, when);
  474.           }
  475.         }
  476.       }
  477.       sprintf(configfile,"%s/%s.conf",cptr2, ctmp->fileHeader);
  478.       read_config (configfile, ltmp, when);
  479.       sprintf(configfile,"%s/%s.local.conf",cptr2, ctmp->fileHeader);
  480.       read_config (configfile, ltmp, when);
  481.       cptr2 = ++cptr1;
  482.     }
  483.     free(envconfpath);
  484.   }
  485.   
  486.   if (config_errors) {
  487.     snmp_log(LOG_ERR, "ucd-snmp: %d errors in config filen", config_errors);
  488. /*    exit(1); */
  489.   }
  490. #endif
  491. }
  492. void read_config_print_usage(const char *lead)
  493. {
  494.   struct config_files *ctmp = config_files;
  495.   struct config_line *ltmp;
  496.   if (lead == NULL)
  497.     lead = "";
  498.   for(ctmp = config_files; ctmp != NULL; ctmp = ctmp->next) {
  499.     snmp_log(LOG_INFO, "%sIn %s.conf and %s.local.conf:n", lead, ctmp->fileHeader,
  500.             ctmp->fileHeader);
  501.     for(ltmp = ctmp->start; ltmp != NULL; ltmp = ltmp->next) {
  502.       if (ltmp->help != NULL)
  503.         snmp_log(LOG_INFO, "%s%s%-15s %sn", lead, lead, ltmp->config_token,
  504.                  ltmp->help);
  505.     }
  506.   }
  507. }
  508. /*******************************************************************-o-******
  509.  * read_config_store
  510.  *
  511.  * Parameters:
  512.  * *type
  513.  * *line
  514.  *      
  515.  * 
  516.  * Append line to a file named either ENV(SNMP_PERSISTENT_FILE) or
  517.  *   "<PERSISTENT_DIRECTORY>/<type>.conf".
  518.  * Add a trailing newline to the stored file if necessary.
  519.  *
  520.  * Intended for use by applications to store permenant configuration 
  521.  * information generated by sets or persistent counters.
  522.  *
  523.  */
  524. void
  525. read_config_store(const char *type, const char *line)
  526. {
  527. #ifdef UCD_SNMP
  528. #ifdef PERSISTENT_DIRECTORY
  529.   char file[512], *filep;
  530.   FILE *fout;
  531. #ifdef PERSISTENT_MASK
  532.   mode_t oldmask;
  533. #endif
  534.   /* store configuration directives in the following order of preference:
  535.      1. ENV variable SNMP_PERSISTENT_FILE
  536.      2. configured <PERSISTENT_DIRECTORY>/<type>.conf
  537.   */
  538.   if ((filep = getenv("SNMP_PERSISTENT_FILE")) == NULL) {
  539.     sprintf(file,"%s/%s.conf",PERSISTENT_DIRECTORY,type);
  540.     filep = file;
  541.   }
  542.   
  543. #ifdef PERSISTENT_MASK
  544.   oldmask = umask(PERSISTENT_MASK);
  545. #endif
  546.   if (mkdirhier(filep, AGENT_DIRECTORY_MODE, 1)) {
  547.       snmp_log(LOG_ERR, "Failed to create the persistent directory for %sn",
  548.                file);
  549.   }
  550.   if ((fout = fopen(filep, "a")) != NULL) {
  551.     fprintf(fout,line);
  552.     if (line[strlen(line)] != 'n')
  553.       fprintf(fout,"n");
  554.     DEBUGMSGTL(("read_config","storing: %sn",line));
  555.     fclose(fout);
  556.   } else {
  557.     DEBUGMSGTL(("read_config","open failure"));
  558.   }
  559. #ifdef PERSISTENT_MASK
  560.   umask(oldmask);
  561. #endif
  562. #endif
  563. #endif
  564. }  /* end read_config_store() */
  565. void
  566. read_app_config_store(const char *line)
  567. {
  568.   read_config_store(ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE), line);
  569. }
  570. /*******************************************************************-o-******
  571.  * snmp_save_persistent
  572.  *
  573.  * Parameters:
  574.  * *type
  575.  *      
  576.  *
  577.  * Save the file "<PERSISTENT_DIRECTORY>/<type>.conf" into a backup copy
  578.  * called "<PERSISTENT_DIRECTORY>/<type>.%d.conf", which %d is an
  579.  * incrementing number on each call, but less than MAX_PERSISTENT_BACKUPS.
  580.  *
  581.  * Should be called just before all persistent information is supposed to be
  582.  * written to move aside the existing persistent cache.
  583.  * snmp_clean_persistent should then be called afterward all data has been
  584.  * saved to remove these backup files.
  585.  *
  586.  * Note: on an rename error, the files are removed rather than saved.
  587.  *
  588.  */
  589. void
  590. snmp_save_persistent(const char *type)
  591. {
  592. #ifdef UCD_SNMP
  593.   char file[512], fileold[512];
  594.   struct stat statbuf;
  595.   int j;
  596.   DEBUGMSGTL(("snmp_save_persistent","saving %s files...n", type));
  597.   sprintf(file,"%s/%s.conf", PERSISTENT_DIRECTORY, type);
  598.   if (stat(file, &statbuf) == 0) {
  599.     for(j=0; j <= MAX_PERSISTENT_BACKUPS; j++) {
  600.       sprintf(fileold,"%s/%s.%d.conf", PERSISTENT_DIRECTORY, type, j);
  601.       if (stat(fileold, &statbuf) != 0) {
  602.         DEBUGMSGTL(("snmp_save_persistent"," saving old config file: %s -> %s.n", file, fileold));
  603.         if (rename(file, fileold)) {
  604.           unlink(file);/* moving it failed, try nuking it, as leaving
  605.                           it around is very bad. */
  606.         }
  607.         break;
  608.       }
  609.     }
  610.   }
  611. #endif
  612. }
  613. /*******************************************************************-o-******
  614.  * snmp_clean_persistent
  615.  *
  616.  * Parameters:
  617.  * *type
  618.  *      
  619.  *
  620.  * Unlink all backup files called "<PERSISTENT_DIRECTORY>/<type>.%d.conf".
  621.  *
  622.  * Should be called just after we successfull dumped the last of the
  623.  * persistent data, to remove the backup copies of previous storage dumps.
  624.  *
  625.  * XXX  Worth overwriting with random bytes first?  This would
  626.  * ensure that the data is destroyed, even a buffer containing the
  627.  * data persists in memory or swap.  Only important if secrets
  628.  * will be stored here.
  629.  */
  630. void
  631. snmp_clean_persistent(const char *type)
  632. {
  633. #ifdef UCD_SNMP
  634.   char file[512];
  635.   struct stat statbuf;
  636.   int j;
  637.   DEBUGMSGTL(("snmp_clean_persistent","cleaning %s files...n", type));
  638.   sprintf(file,"%s/%s.conf",PERSISTENT_DIRECTORY,type);
  639.   if (stat(file, &statbuf) == 0) {
  640.     for(j=0; j <= MAX_PERSISTENT_BACKUPS; j++) {
  641.       sprintf(file,"%s/%s.%d.conf", PERSISTENT_DIRECTORY, type, j);
  642.       if (stat(file, &statbuf) == 0) {
  643.         DEBUGMSGTL(("snmp_clean_persistent"," removing old config file: %sn", file));
  644.         unlink(file);
  645.       }
  646.     }
  647.   }
  648. #endif
  649. }
  650.   
  651. /* config_perror: prints a warning string associated with a file and
  652.    line number of a .conf file and increments the error count. */
  653. void config_perror(const char *string)
  654. {
  655.   config_pwarn(string);
  656.   config_errors++;
  657. }
  658. void config_pwarn(const char *string)
  659. {
  660.   snmp_log(LOG_WARNING, "%s: line %d: %sn", curfilename, linecount, string);
  661. }
  662. /* skip all white spaces and return 1 if found something either end of
  663.    line or a comment character */
  664. char *skip_white(char *ptr)
  665. {
  666.   if (ptr == NULL) return (NULL);
  667.   while (*ptr != 0 && isspace(*ptr)) ptr++;
  668.   if (*ptr == 0 || *ptr == '#') return (NULL);
  669.   return (ptr);
  670. }
  671. char *skip_not_white(char *ptr)
  672. {
  673.   
  674.   if (ptr == NULL) return (NULL);
  675.   while (*ptr != 0 && !isspace(*ptr)) ptr++;
  676.   if (*ptr == 0 || *ptr == '#') return (NULL);
  677.   return (ptr);
  678. }
  679. char *skip_token(char *ptr)
  680. {
  681.   ptr = skip_white(ptr);
  682.   ptr = skip_not_white(ptr);
  683.   ptr = skip_white(ptr);
  684.   return (ptr);
  685. }
  686. /* copy_word
  687.    copies the next 'token' from 'from' into 'to'.
  688.    currently a token is anything seperate by white space
  689.    or within quotes (double or single) (i.e. "the red rose" 
  690.    is one token, "the red rose" is three tokens)
  691.    a '' character will allow a quote character to be treated
  692.    as a regular character 
  693.    It returns a pointer to first non-white space after the end of the token
  694.    being copied or to 0 if we reach the end.*/
  695. char *copy_word(char *from, char *to)
  696. {
  697.   char quote;
  698.   if ( (*from == '"') || (*from ==''') ){
  699.     quote = *(from++);
  700.     while ( (*from != quote) && (*from != 0) ) {
  701.       if ((*from == '\') && (*(from+1) != 0)) {
  702. *to++ = *(from+1);
  703. from = from +2;
  704.       }
  705.       else  *to++ = *from++;
  706.     }
  707.     if (*from == 0) {
  708.       DEBUGMSGTL(("read_config_copy_word",
  709.                   "no end quote found in config stringn"));
  710.     } else from++;
  711.   }
  712.   else {
  713.     while (*from != 0 && !isspace(*from)) {
  714.       if ((*from == '\') && (*(from+1) != 0)) {
  715. *to++ = *(from+1);
  716. from = from +2;
  717.       }
  718.       else  *to++ = *from++;
  719.     }
  720.   }
  721.   *to = 0;
  722.   from = skip_white(from);
  723.   return(from);
  724. }  /* copy_word */
  725. /* read_config_save_octet_string(): saves an octet string as a length
  726.    followed by a string of hex */
  727. char *read_config_save_octet_string(char *saveto, u_char *str, size_t len) {
  728.   int i;
  729.   if (str != NULL) {
  730.     sprintf(saveto, "0x");
  731.     saveto += 2;
  732.     for(i = 0; i < (int)len; i++) {
  733.       sprintf(saveto,"%02x", str[i]);
  734.       saveto = saveto + 2;
  735.     }
  736.     return saveto;
  737.   } else {
  738.     sprintf(saveto,"""");
  739.     saveto += 2;
  740.   }
  741.   return saveto;
  742. }
  743. /* read_config_read_octet_string(): reads an octet string that was
  744.    saved by the read_config_save_octet_string() function */
  745. char *read_config_read_octet_string(char *readfrom, u_char **str, size_t *len) {
  746.   u_char *cptr=NULL;
  747.   char *cptr1;
  748.   u_int tmp;
  749.   int i;
  750.   if (readfrom == NULL || str == NULL)
  751.     return NULL;
  752.   
  753.   if (strncasecmp(readfrom,"0x",2) == 0) {
  754.     /* A hex string submitted. How long? */
  755.     readfrom += 2;
  756.     cptr1 = skip_not_white(readfrom);
  757.     if (cptr1)
  758.       *len = (cptr1 - readfrom);
  759.     else
  760.       *len = strlen(readfrom);
  761.     if (*len % 2) {
  762.       DEBUGMSGTL(("read_config_read_octet_string","invalid hex string: wrong length"));
  763.       return NULL;
  764.     }
  765.     *len = *len / 2;
  766.     /* malloc data space if needed */
  767.     if (*str == NULL) {
  768.       if (*len == 0) {
  769.         /* null length string found */
  770.         cptr = NULL;
  771.       } else if (*len > 0 && (str == NULL || (cptr = (u_char *)malloc(*len)) == NULL)) {
  772.         return NULL;
  773.       }
  774.       *str = cptr;
  775.     } else {
  776.       cptr = *str;
  777.     }
  778.     /* copy data */
  779.     for(i = 0; i < (int)*len; i++) {
  780.       sscanf(readfrom,"%2x",&tmp);
  781.       *cptr++ = (u_char) tmp;
  782.       readfrom += 2;
  783.     }
  784.     readfrom = skip_white(readfrom);
  785.   } else {
  786.     /* Normal string */
  787.     /* malloc data space if needed */
  788.     if (*str == NULL) {
  789.       char buf[SNMP_MAXBUF];
  790.       readfrom = copy_word(readfrom, buf);
  791.       *len = strlen(buf);
  792.       /* malloc an extra space to add a null */
  793.       if (*len > 0 && (str == NULL ||
  794.                        (cptr = (u_char *) malloc(*len + 1))
  795.                        == NULL))
  796.         return NULL;
  797.       *str = cptr;
  798.       if (cptr)
  799.         memcpy(cptr, buf, (*len+1));
  800.     } else {
  801.       readfrom = copy_word(readfrom, (char *)*str);
  802.     }
  803.   }
  804.   return readfrom;
  805. }
  806. /* read_config_save_objid(): saves an objid as a numerical string */
  807. char *read_config_save_objid(char *saveto, oid *objid, size_t len) {
  808.   int i;
  809.   
  810.   if (len == 0) {
  811.     strcat(saveto, "NULL");
  812.     saveto += strlen(saveto);
  813.     return saveto;
  814.   }
  815.   /* in case len=0, this makes it easier to read it back in */
  816.   for(i=0; i < (int)len; i++) {
  817.     sprintf(saveto,".%ld", objid[i]);
  818.     saveto += strlen(saveto);
  819.   }
  820.   return saveto;
  821. }
  822. /* read_config_read_objid(): reads an objid from a format saved by the above */
  823. char *read_config_read_objid(char *readfrom, oid **objid, size_t *len) {
  824.   if (objid == NULL || readfrom == NULL)
  825.     return NULL;
  826.   if (*objid != NULL) {
  827.     char buf[SPRINT_MAX_LEN];
  828.     if (strncmp(readfrom,"NULL",4) == 0) {
  829.       /* null length oid */
  830.       *len = 0;
  831.     } else {
  832.       /* read_objid is touchy with trailing stuff */
  833.       copy_word(readfrom, buf);
  834.       /* read the oid into the buffer passed to us */
  835.       if (!read_objid(buf, *objid, len)) {
  836.         DEBUGMSGTL(("read_config_read_objid","Invalid OID"));
  837.         return NULL;
  838.       }
  839.     }
  840.     
  841.     readfrom = skip_token(readfrom);
  842.   } else {
  843.     if (strncmp(readfrom,"NULL",4) == 0) {
  844.       /* null length oid */
  845.       *len = 0;
  846.       readfrom = skip_token(readfrom);
  847.     } else {
  848.       /* space needs to be malloced.  Call ourself recursively to figure
  849.        out how long the oid actually is */
  850.       oid obuf[MAX_OID_LEN];
  851.       size_t obuflen = MAX_OID_LEN;
  852.       oid *oidp = obuf;
  853.       oid **oidpp = &oidp;   /* done this way for odd, untrue, gcc warnings */
  854.       readfrom = read_config_read_objid(readfrom, oidpp, &obuflen);
  855.       /* Then malloc and copy the results */
  856.       *len = obuflen;
  857.       if (*len > 0 && (*objid = (oid*)malloc(*len * sizeof(oid))) == NULL)
  858.         return NULL;
  859.       if (obuflen > 0)
  860.         memcpy(*objid, obuf, obuflen*sizeof(oid));
  861.     }
  862.   }
  863.   return readfrom;
  864. }
  865. /* read_config_read_data():
  866.    reads data of a given type from a token(s) on a configuration line.
  867.    Returns: character pointer to the next token in the configuration line.
  868.             NULL if none left.
  869.             NULL if an unknown type.
  870. */
  871. char *read_config_read_data(int type, char *readfrom, void *dataptr, size_t *len) {
  872.   int *intp;
  873.   char **charpp;
  874.   oid  **oidpp;
  875.   if (dataptr == NULL || readfrom == NULL)
  876.     return NULL;
  877.   
  878.   switch(type) {
  879.     case ASN_INTEGER:
  880.       intp = (int *) dataptr;
  881.       *intp = atoi(readfrom);
  882.       readfrom = skip_token(readfrom);
  883.       return readfrom;
  884.       
  885.     case ASN_OCTET_STR:
  886.       charpp = (char **) dataptr;
  887.       return read_config_read_octet_string(readfrom, (u_char **) charpp, len);
  888.     case ASN_OBJECT_ID:
  889.       oidpp = (oid **) dataptr;
  890.       return read_config_read_objid(readfrom, oidpp, len);
  891.     default:
  892.       DEBUGMSGTL(("read_config_read_data","Fail: Unknown type: %d", type));
  893.       return NULL;
  894.   }
  895.   return NULL;
  896. }
  897. /* read_config_read_data():
  898.    reads data of a given type from a token(s) on a configuration line.
  899.    Returns: character pointer to the next token in the configuration line.
  900.             NULL if none left.
  901.             NULL if an unknown type.
  902. */
  903. char *read_config_store_data(int type, char *storeto, void *dataptr, size_t *len) {
  904.   int *intp;
  905.   u_char **charpp;
  906.   oid  **oidpp;
  907.   if (dataptr == NULL || storeto == NULL)
  908.     return NULL;
  909.   
  910.   switch(type) {
  911.     case ASN_INTEGER:
  912.       intp = (int *) dataptr;
  913.       sprintf(storeto," %d", *intp);
  914.       return (storeto + strlen(storeto));
  915.       
  916.     case ASN_OCTET_STR:
  917.       charpp = (u_char **) dataptr;
  918.       return read_config_save_octet_string(storeto, *charpp, *len);
  919.     case ASN_OBJECT_ID:
  920.       oidpp = (oid **) dataptr;
  921.       return read_config_save_objid(storeto, *oidpp, *len);
  922.     default:
  923.       DEBUGMSGTL(("read_config_store_data","Fail: Unknown type: %d", type));
  924.       return NULL;
  925.   }
  926.   return NULL;
  927. }