OSSP CVS Repository

ossp - Check-in [192]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 192
Date: 2000-Dec-12 14:19:08 (local)
2000-Dec-12 13:19:08 (UTC)
User:simons
Branch:
Comment: Imported Petidomo 2.2 as found on www.petidomo.com.
Tickets:
Inspections:
Files:
ossp-pkg/petidomo/libconfigfile/config.c      added-> 1.1.1.1

ossp-pkg/petidomo/libconfigfile/config.c -> 1.1.1.1

*** /dev/null    Thu May 16 18:11:00 2024
--- -    Thu May 16 18:12:21 2024
***************
*** 0 ****
--- 1,453 ----
+ /*
+  *      $Source: /v/ossp/cvs/ossp-pkg/petidomo/libconfigfile/config.c,v $
+  *      $Revision: 1.1.1.1 $
+  *      $Date: 2000/12/13 13:19:08 $
+  *
+  *      Copyright (C) 1996,97 CyberSolutions GmbH.
+  *      All rights reserved.
+  */
+ 
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <errno.h>
+ #include <syslog.h>
+ 
+ #include "../liblists/lists.h"
+ #include "../libtext/text.h"
+ #include "configfile.h"
+ 
+ char * loadfile(const char *);
+ 
+ static List Files = NULL;
+ 
+ /* Remove a trailing carrige return from a string */
+ 
+ static void
+ ChopCR(char * p)
+ {
+     while (*p != '\0' && *p != '\n')
+       p++;
+ 
+     *p = '\0';
+ }
+ 
+ /* Turn a string into the number of an array element that matches this
+    string. */
+ 
+ static int
+ FindCFEntry(struct ConfigFile cf[], const char * keyword)
+ {
+     int  i;
+ 
+     for (i = 0; (&(cf[i]))->keyword != NULL; i++) {
+        if ((strcasecmp((&(cf[i]))->keyword, keyword)) == 0)
+          return i;
+     }
+ 
+     return -1;
+ }
+ 
+ /* ReadConfig() will read and parse a given config file and fill the
+    parsed tags into the ConfigFile structure given on the command
+    line. The 'ConfigFile' structure consists of three fields: The name
+    of the config tag to look for, a description of how to interpret
+    the parameter specified with it and a pointer to a 'void
+    pointer'-type, which will contain the result when ReadConfig()
+    returns.
+ 
+    Valid tag types are CF_STRING (result buffer will contain a string
+    pointer to the text), CF_INTEGER (parameter will be turned into an
+    integer and stored into the result buffer) and CF_YES_NO
+    (parameter is expected to be a 'yes', 'no', 'true' or 'false' and
+    the appropriate binary setting will be stored).
+ 
+    RETURNS: A return code of zero (0) indicates success, -1 indicates
+    failure. In case of a failure, ReadConfig() will log an error
+    description using the syslog(3) mechanism.
+ 
+  */
+ 
+ int
+ ReadConfig(const char * filename, /* path to the config file to parse */
+           struct ConfigFile cf[] /* structure describing the config tags */
+           )
+ {
+     Node         node;
+     char *       file_buf;
+     char *       currLine;
+     char *       nextLine;
+     char *       keyword;
+     char *       data;
+     int          rc;
+     int          i;
+     unsigned int numLine;
+ 
+     /* Initialize list of loaded config files. */
+ 
+     if (Files == NULL) {
+        Files = InitList(NULL);
+        if (Files == NULL) {
+            syslog(LOG_ERR, "ReadConfig: Failed to initialize my internal config file list.");
+            return -1;
+        }
+     }
+     else {
+        /* Check whether we already parsed that file. */
+ 
+        node = FindNodeByKey(Files, filename);
+        if (node != NULL)
+          return 0;
+     }
+ 
+     /* Load the file into memory. */
+ 
+     file_buf = loadfile(filename);
+     if (file_buf == NULL) {
+        syslog(LOG_WARNING, "ReadConfig: Failed to load config file \"%s\": %m", filename);
+        return -1;
+     }
+ 
+     /* Store the buffer details in the linked list. */
+ 
+     filename = strdup(filename);
+     if (filename == NULL) {
+        syslog(LOG_ERR, "ReadConfig: Failed to load config file \"%s\": %m", filename);
+        return -1;
+     }
+     node = AppendNode(Files, filename, file_buf);
+     if (node == NULL) {
+        syslog(LOG_ERR, "ReadConfig: Internal Error: Couldn't add config file data to my list.");
+        return -1;
+     }
+ 
+     /* Parse the file line by line. */
+ 
+     for (numLine = 1, nextLine = currLine = file_buf; *currLine != '\0'; currLine = nextLine, numLine++) {
+        nextLine = text_find_next_line(currLine);
+        ChopCR(currLine);
+ 
+        /* Ignore comments or empty lines. */
+ 
+        if ((text_easy_pattern_match(currLine, "^[\t ]*#|^[\t ]*$")) == TRUE)
+          continue;             /* ignore it */
+ 
+        /* Line is supposed to contain a config statement, so we
+            should do a consistency check first. If the line passes,
+            there're no surprises when we actually parse it. */
+ 
+        if ((text_easy_pattern_match(currLine, "^[[:alnum:]_-]+[\t ]+[^\t ]")) == FALSE) {
+            syslog(LOG_WARNING, "ReadConfig: Line \"%s\" is syntactically incorrect.",
+                   currLine);
+            continue;           /* ignore it */
+        }
+ 
+        /* Remove all unnecessary whitespace. */
+ 
+        rc = text_transform_text(currLine, currLine, "^([^\t ]+)[\t ]+([^\t ].*)[\t ]*$", "\\1 \\2");
+        if (rc != 0) {
+            syslog(LOG_WARNING, "ReadConfig: Internal error while parsing line: %d.", rc);
+            continue;           /* ignore it */
+        }
+ 
+        /* Locate the keyword and data part. */
+ 
+        for (keyword = currLine; *currLine != ' '; currLine++)
+          ;
+        *currLine++ = '\0';
+        data = currLine;
+ 
+        /* Find appropriate entry in the ConfigFile structure and
+            check whether we know the keyword. */
+ 
+        i = FindCFEntry(cf, keyword);
+        if (i == -1) {
+            syslog(LOG_WARNING, "ReadConfig: Unrecognized keyword \"%s\" in file \"%s\", line %d.",
+                   keyword, filename, numLine);
+            continue;           /* ignore it */
+        }
+ 
+        /* Determine type of data and store it appropriately. */
+ 
+        switch ((&(cf[i]))->type) {
+          case CF_STRING:
+              /* Handle strings included in quotes. */
+ 
+              rc = text_transform_text(data, data, "^\"([^\"]*)\"$", "\\1");
+              if (rc != 0 && rc != TEXT_REGEX_TRANSFORM_DIDNT_MATCH) {
+                  syslog(LOG_WARNING, "ReadConfig: Internal error while parsing file \"%s\", line: %d.",
+                      filename, numLine);
+                  continue;
+              }
+ 
+              /* Store the string. */
+ 
+              if ((&(cf[i]))->data != NULL)
+                *((char **)(&(cf[i]))->data) = data;
+              break;
+ 
+          case CF_INTEGER:
+              /* Integers will have an additional consistency check to
+                  warn the user about typing errors. */
+ 
+              if ((text_easy_pattern_match(data, "^[-+][[:digit:]]+$|^[[:digit:]]+$")) == FALSE) {
+                  syslog(LOG_WARNING, "ReadConfig: Specified parameter \"%s\" in file \"%s\", line %d, is not a number.", data, filename, numLine);
+                  continue;             /* ignore it */
+              }
+              if ((&(cf[i]))->data != NULL)
+                *((int *)(&(cf[i]))->data) = atoi(data);
+              break;
+          case CF_YES_NO:
+              if ((text_easy_pattern_match(data, "^yes$|^true$|^y$")) == TRUE) {
+                  if ((&(cf[i]))->data != NULL)
+                    *((bool *)(&(cf[i]))->data) = TRUE;
+              } else if ((text_easy_pattern_match(data, "^no$|^false$|^n$")) == TRUE) {
+                  if ((&(cf[i]))->data != NULL)
+                    *((bool *)(&(cf[i]))->data) = FALSE;
+              } else {
+                  syslog(LOG_WARNING, "ReadConfig: Specified parameter \"%s\" in file \"%s\", line %d, is not a yes or a no.", data, filename, numLine);
+                  continue;             /* ignore it */
+              }
+              break;
+          case CF_MULTI:
+              syslog(LOG_WARNING, "ReadConfig: Method not supported at the moment.");
+              break;
+          default:
+              syslog(LOG_ERR, "ReadConfig internal error: ConfigFile structure element %d has unknown type %d.", i++, (&(cf[i]))->type);
+        }
+ 
+     }
+ 
+     return 0;
+ }
+ 
+ /* This routine must be used to return all resources to the system,
+    that have been allocaged by a specific ReadConfig(3) call. After
+    that, all result buffers provided by ReadConfig() will be invalid. */
+ 
+ void
+ FreeConfig(const char * filename)
+ {
+     Node   node;
+ 
+     node = FindNodeByKey(Files, filename);
+     if (node == NULL)
+       return;
+ 
+     free((void *) getNodeData(node));
+     free((void *) getNodeKey(node));
+     RemoveNode(node);
+     FreeNode(node);
+ }
+ 
+ /* This function call will free all resources for all previous
+    ReadConfig(3) calls.
+ 
+    BUGS: Not implemented at the moment.
+ */
+ 
+ void
+ FreeAllConfigs(void)
+ {
+ 
+ }
+ 
+ static char *
+ LocateKeywordInBuffer(char * buffer, char * keyword)
+ {
+     char *   p;
+ 
+     for (p = buffer; p != NULL; ) {
+        p = text_find_string(p, keyword);
+        if (p != NULL) {
+            if (p == buffer || p[-1] == '\n' || p[-1] == '\r')
+              break;
+            else
+              p++;              /* Not a keyword, look again. */
+        }
+     }
+ 
+     return p;
+ }
+ 
+ /* Load a config file and parse it for the required keyword. Then
+    return the parameter. The buffer containing the parameter should be
+    free()'d by the caller. #
+ 
+    RETURNS: If the keyword is not found, NULL is returned and errno is
+    set to 0. If an error occurs, NULL is returned also, but errno is
+    set accordingly.
+ */
+ 
+ char *
+ GetConfig(const char * filename, char * keyword)
+ {
+     char *   file_buf;
+     char *   result_buf;
+     char *   p;
+     int      rc;
+ 
+     /* Load the config file. */
+ 
+     file_buf = loadfile(filename);
+     if (file_buf == NULL) {
+        syslog(LOG_ERR, "GetConfig: Failed to load config file \"%s\". %m", filename);
+        return NULL;
+     }
+ 
+     /* Find the keyword. */
+ 
+     p = LocateKeywordInBuffer(file_buf, keyword);
+ 
+     if (p == NULL) {
+        /* No luck, keyword doesn't exist. */
+        errno = 0;
+        return NULL;
+     }
+ 
+     /* Okay, keyword found. Now extract the parameter. */
+ 
+     ChopCR(p);
+     rc = text_transform_text(p, p, "^[^\t ]+[\t ]+([^\t ].*)[\t ]*$", "\\1");
+     if (rc != 0) {
+        syslog(LOG_WARNING, "GetConfig: Config file entry \"%s\" is corrupt.", keyword);
+        errno = -1;
+        return NULL;
+     }
+     rc = text_transform_text(p, p, "^\"([^\"]*)\"$", "\\1");
+     if (rc != 0 && rc != TEXT_REGEX_TRANSFORM_DIDNT_MATCH) {
+        syslog(LOG_WARNING, "GetConfig: Config file entry \"%s\" is corrupt.", keyword);
+        errno = -1;
+        return NULL;
+     }
+ 
+ 
+     /* Copy the parameter into a new buffer. */
+ 
+     result_buf = strdup(p);
+     if (result_buf == NULL) {
+        syslog(LOG_ERR, "GetConfig: Failed to allocate %d byte of memory.", strlen(p));
+        errno = ENOMEM;
+        return NULL;
+     }
+ 
+     /* Free the used memory and return the result. */
+ 
+     free(file_buf);
+     return result_buf;
+ }
+ 
+ /* This routine will set a given config entry in a config file. When
+    the keyword is already there, the parameter will be changed.
+    Otherwise the string "keyword<tab>data" is appended at the end of
+    the file.
+ 
+    RETURNS: If something goes wrong, the routine returns -1 and sets
+    errno. Otherwise we return 0.
+ 
+    BUGS: This routine may DESTRUCT THE FILE if some I/O error occurs.
+    It is the caller's responsibility to backup the file before calling
+    us.
+ */
+ 
+ int
+ SetConfig(const char * filename,
+          char * keyword,       /* string pointer to the tag name */
+          const char * data     /* string pointer to the tag data */
+          )
+ {
+     struct flock  lock;
+     char *        file_buf;
+     int           file_len;
+     char *        p;
+     char *        nextLine;
+     int           fd;
+     int           rc;
+ 
+     /* Load the config file. */
+ 
+     file_buf = loadfile(filename);
+     if (file_buf == NULL) {
+        syslog(LOG_ERR, "SetConfig: Failed to load config file \"%s\": %m", filename);
+        return -1;
+     }
+     file_len = errno;
+ 
+     /* Find the keyword. */
+ 
+     p = LocateKeywordInBuffer(file_buf, keyword);
+ 
+     if (p == NULL) {
+        /* No luck, keyword doesn't exist. Append the data. */
+ 
+        fd = open(filename, O_WRONLY | O_APPEND, 0666);
+        if (fd == -1)
+          goto io_error;
+ 
+        lock.l_start  = 0;
+        lock.l_len    = 0;
+        lock.l_type   = F_WRLCK;
+        lock.l_whence = SEEK_SET;
+        fcntl(fd, F_SETLKW, &lock);
+ 
+        /* Does the file end in a '\n' or must we append one? */
+ 
+        if (file_buf[file_len - 1] != '\n') {
+            rc = write(fd, "\n", 1);
+            if (rc == -1)
+              goto io_error;
+        }
+ 
+        /* Write the actual keyword and data. */
+ 
+         if ((write(fd, keyword, strlen(keyword)) == -1)
+            || (write(fd, "\t", 1) == -1)
+            || (write(fd, data, strlen(data)) == -1)
+            || (write(fd, "\n", 1) == -1)) {
+            goto io_error;
+        }
+     }
+     else {
+        fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+        if (fd == -1)
+          goto io_error;
+ 
+        lock.l_start  = 0;
+        lock.l_len    = 0;
+        lock.l_type   = F_WRLCK;
+        lock.l_whence = SEEK_SET;
+        fcntl(fd, F_SETLKW, &lock);
+ 
+        nextLine = text_find_next_line(p);
+        *p = '\0';
+ 
+        /* Write buffer back until the to-be-replaced keyword. */
+ 
+        rc = write(fd, file_buf, strlen(file_buf));
+        if (fd == -1)
+          goto io_error;
+ 
+        /* Write the actual keyword and data. */
+ 
+         if ((write(fd, keyword, strlen(keyword)) == -1)
+            || (write(fd, "\t", 1) == -1)
+            || (write(fd, data, strlen(data)) == -1)
+            || (write(fd, "\n", 1) == -1)) {
+            goto io_error;
+        }
+ 
+        /* Write the rest of the buffer. */
+ 
+        rc = write(fd, nextLine, strlen(nextLine));
+        if (fd == -1)
+          goto io_error;
+     }
+ 
+     close(fd);
+     free(file_buf);
+     return 0;
+ 
+ io_error:
+     syslog(LOG_ERR, "SetConfig: Failed to write to file \"%s\": %m", filename);
+     free(file_buf);
+     return -1;
+ }

CVSTrac 2.0.1