Back to index

opendkim  2.6.2
Defines | Functions | Variables
config.c File Reference
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <dkim.h>
#include <dkim-strl.h>
#include "config.h"

Go to the source code of this file.

Defines

#define _REENTRANT
#define BUFRSZ   1024 /* generic buffer size */
#define MAXLEVEL   5 /* max. include recursion */
#define FALSE   0
#define TRUE   1
#define CONF_UNKNOWN   (-1) /* unknown status */
#define CONF_SUCCESS   0 /* no error */
#define CONF_MISSING   1 /* required value missing */
#define CONF_UNRECOG   2 /* unrecognized parameter */
#define CONF_ILLEGAL   3 /* illegal value */
#define CONF_NESTING   4 /* "include" nesting too deep */
#define CONF_READING   5 /* error reading (see errno) */
#define CONF_NMEMORY   6 /* malloc() failure */

Functions

static void config_attach __P ((struct config *, struct config **))
static void config_attach (struct config *c1, struct config **c2)
static struct configconfig_load_level (char *file, struct configdef *def, unsigned int *line, char *outpath, size_t outpathlen, int level)
char * config_error (void)
void config_free (struct config *head)
struct configconfig_load (char *file, struct configdef *def, unsigned int *line, char *path, size_t pathlen)
char * config_check (struct config *head, struct configdef *def)
int config_get (struct config *head, const char *name, void *value, size_t size)
_Bool config_validname (struct configdef *def, const char *name)
unsigned int config_dump (struct config *cfg, FILE *out, const char *name)

Variables

static char config_c_id [] = "@(#)$Id: config.c,v 1.10.10.1 2010/10/27 21:43:09 cm-msk Exp $"
static int conf_error

Define Documentation

#define _REENTRANT

Definition at line 16 of file config.c.

#define BUFRSZ   1024 /* generic buffer size */

Definition at line 34 of file config.c.

#define CONF_ILLEGAL   3 /* illegal value */

Definition at line 52 of file config.c.

#define CONF_MISSING   1 /* required value missing */

Definition at line 50 of file config.c.

#define CONF_NESTING   4 /* "include" nesting too deep */

Definition at line 53 of file config.c.

#define CONF_NMEMORY   6 /* malloc() failure */

Definition at line 55 of file config.c.

#define CONF_READING   5 /* error reading (see errno) */

Definition at line 54 of file config.c.

#define CONF_SUCCESS   0 /* no error */

Definition at line 49 of file config.c.

#define CONF_UNKNOWN   (-1) /* unknown status */

Definition at line 48 of file config.c.

#define CONF_UNRECOG   2 /* unrecognized parameter */

Definition at line 51 of file config.c.

#define FALSE   0

Definition at line 38 of file config.c.

#define MAXLEVEL   5 /* max. include recursion */

Definition at line 35 of file config.c.

#define TRUE   1

Definition at line 41 of file config.c.


Function Documentation

static void config_attach __P ( (struct config *, struct config **)  ) [static]
static void config_attach ( struct config c1,
struct config **  c2 
) [static]

Definition at line 72 of file config.c.

{
       struct config *prev;
       struct config *cur;

       assert(c1 != NULL);

       if (*c2 == NULL)
       {
              *c2 = c1;
       }
       else
       {
              prev = NULL;

              for (cur = c1; cur != NULL; cur = cur->cfg_next)
                     prev = cur;

              prev->cfg_next = *c2;
       }
}

Here is the caller graph for this function:

char* config_check ( struct config head,
struct configdef def 
)

Definition at line 508 of file config.c.

{
       int n;
       struct config *cur;

       assert(head != NULL);
       assert(def != NULL);

       conf_error = CONF_UNKNOWN;

       for (n = 0; ; n++)
       {
              if (def[n].cd_name == NULL)
              {
                     conf_error = CONF_SUCCESS;
                     return NULL;
              }
              if (!def[n].cd_req)
                     continue;

              for (cur = head; cur != NULL; cur = cur->cfg_next)
              {
                     if (cur->cfg_name == def[n].cd_name)
                            break;
              }

              if (cur == NULL)
              {
                     conf_error = CONF_MISSING;

                     return def[n].cd_name;
              }
       }

       /* NOTREACHED */
}

Here is the caller graph for this function:

unsigned int config_dump ( struct config cfg,
FILE *  out,
const char *  name 
)

Definition at line 669 of file config.c.

{
       unsigned int nprinted = 0;
       struct config *cur;

       assert(cfg != NULL);
       assert(out != NULL);

       for (cur = cfg; cur != NULL; cur = cur->cfg_next)
       {
              if (name != NULL)
              {
                     if (strcasecmp(name, cur->cfg_name) != 0)
                            continue;
              }
              else
              {
                     fprintf(out, "%p: \"%s\" ", cur, cur->cfg_name);
              }

              switch (cur->cfg_type)
              {
                case CONFIG_TYPE_STRING:
                     fprintf(out, "%s\n", cur->cfg_string);
                     break;

                case CONFIG_TYPE_INTEGER:
                     fprintf(out, "%d\n", cur->cfg_int);
                     break;

                case CONFIG_TYPE_BOOLEAN:
                     fprintf(out, "%s\n", cur->cfg_bool ? "True" : "False");
                     break;

                default:
                     assert(0);
              }

              nprinted++;
       }

       return nprinted;
}

Here is the caller graph for this function:

char* config_error ( void  )

Definition at line 405 of file config.c.

{
       switch (conf_error)
       {
         case CONF_SUCCESS:
              return "no error";

         case CONF_MISSING:
              return "required value missing";

         case CONF_UNRECOG:
              return "unrecognized parameter";

         case CONF_ILLEGAL:
              return "illegal value";

         case CONF_NESTING:
              return "nesting too deep";

         case CONF_READING:
              return "error reading configuration file";

         case CONF_NMEMORY:
              return "memory allocation failure";

         case CONF_UNKNOWN:
         default:
              return "unknown error";
       }

       /* NOTREACHED */
}

Here is the caller graph for this function:

void config_free ( struct config head)

Definition at line 449 of file config.c.

{
       struct config *next;
       struct config *cur;

       cur = head;
       while (cur != NULL)
       {
              next = cur->cfg_next;
              if (cur->cfg_type == CONFIG_TYPE_STRING)
                     free(cur->cfg_string);
              free(cur);
              cur = next;
       }
}

Here is the caller graph for this function:

int config_get ( struct config head,
const char *  name,
void *  value,
size_t  size 
)

Definition at line 566 of file config.c.

{
       struct config *cur;

       assert(head != NULL);
       assert(name != NULL);
       assert(value != NULL);
       assert(size > 0);

       conf_error = CONF_UNKNOWN;

       for (cur = head; cur != NULL; cur = cur->cfg_next)
       {
              if (strcasecmp(cur->cfg_name, name) == 0)
              {
                     switch (cur->cfg_type)
                     {
                       case CONFIG_TYPE_BOOLEAN:
                            if (size != sizeof(_Bool))
                            {
                                   conf_error = CONF_ILLEGAL;
                                   return -1;
                            }
                            memcpy(value, &cur->cfg_bool, size);
                            break;

                       case CONFIG_TYPE_INTEGER:
                            if (size != sizeof(int))
                            {
                                   conf_error = CONF_ILLEGAL;
                                   return -1;
                            }
                            memcpy(value, &cur->cfg_int, size);
                            break;

                       case CONFIG_TYPE_INCLUDE:
                            conf_error = CONF_ILLEGAL;
                            return -1;

                       default:
                            if (size != sizeof(char *))
                            {
                                   conf_error = CONF_ILLEGAL;
                                   return -1;
                            }
                            memcpy(value, &cur->cfg_string, size);
                            break;
                     }

                     return 1;
              }
       }

       conf_error = CONF_SUCCESS;

       return 0;
}

Here is the caller graph for this function:

struct config* config_load ( char *  file,
struct configdef def,
unsigned int *  line,
char *  path,
size_t  pathlen 
) [read]

Definition at line 486 of file config.c.

{
       conf_error = CONF_UNKNOWN;

       return config_load_level(file, def, line, path, pathlen, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct config* config_load_level ( char *  file,
struct configdef def,
unsigned int *  line,
char *  outpath,
size_t  outpathlen,
int  level 
) [static, read]

Definition at line 116 of file config.c.

{
       int n = -1;
       int err = 0;
       unsigned int myline = 0;
       int value = -1;
       FILE *in;
       char *p;
       char *s;
       char *str = NULL;
       struct config *new = NULL;
       struct config *cur = NULL;
       char buf[BUFRSZ + 1];

       assert(def != NULL);

       if (level > MAXLEVEL)
       {
              conf_error = CONF_NESTING;
              return NULL;
       }

       memset(buf, '\0', sizeof buf);

       if (file == NULL || (file[0] == '-' && file[1] == '\0'))
       {
              in = stdin;
              file = "(stdin)";
       }
       else
       {
              in = fopen(file, "r");
              if (in == NULL)
              {
                     conf_error = CONF_READING;
                     if (line != NULL)
                            *line = myline;
                     if (outpath != NULL)
                            strlcpy(outpath, file, outpathlen);
                     return NULL;
              }
       }

       while (fgets(buf, sizeof buf - 1, in) != NULL)
       {
              myline++;
              str = NULL;

              /* read a line; truncate at newline or "#" */
              for (p = buf; *p != '\0'; p++)
              {
                     if (*p == '#' || *p == '\n')
                     {
                            *p = '\0';
                            break;
                     }
              }

              /* break down the line */
              p = strtok_r(buf, " \t", &s);
              if (p != NULL)
              {
                     /* recognize the directive? */
                     for (n = 0; ; n++)
                     {
                            /* nope */
                            if (def[n].cd_name == NULL)
                            {
                                   conf_error = CONF_UNRECOG;
                                   err = 1;
                                   break;
                            }

                            if (strcasecmp(def[n].cd_name, p) == 0)
                                   break;
                     }

                     if (!err)
                     {
                            char *q;

                            /* skip leading whitespace on value */
                            for (p = s; *p == ' ' || *p == '\t'; p++)
                                   continue;

                            /* ...and trim trailing whitespace */
                            q = p + strlen(p) - 1;
                            while (p <= q && (*q == '\t' || *q == ' '))
                                   *q-- = '\0';
                     }

                     if (*p == '\0' && !err)
                     {
                            conf_error = CONF_MISSING;
                            err = 1;
                     }

                     if (!err)
                     {
                            char *q;

                            switch (def[n].cd_type)
                            {
                              case CONFIG_TYPE_STRING:
                              case CONFIG_TYPE_INCLUDE:
                                   str = p;
                                   break;

                              case CONFIG_TYPE_BOOLEAN:
                                   if (p[0] == 't' ||
                                       p[0] == 'T' ||
                                       p[0] == 'y' ||
                                       p[0] == 'Y' ||
                                       p[0] == '1')
                                   {
                                          value = 1;
                                   }
                                   else if (p[0] == 'f' ||
                                            p[0] == 'F' ||
                                            p[0] == 'n' ||
                                            p[0] == 'N' ||
                                            p[0] == '0')
                                   {
                                          value = 0;
                                   }
                                   else
                                   {
                                          conf_error = CONF_ILLEGAL;
                                          err = 1;
                                   }

                                   break;

                              case CONFIG_TYPE_INTEGER:
                                   value = (int) strtol(p, &q, 0);
                                   if (*q != '\0')
                                   {
                                          conf_error = CONF_ILLEGAL;
                                          err = 1;
                                   }

                                   str = p;

                                   break;

                              default:
                                   assert(0);
                                   /* NOTREACHED */
                                   return NULL;
                            }
                     }
              }
              else
              {
                     continue;                   /* blank line */
              }

              /* a parse error, or only one argument, is no good */
              if (err)
              {
                     config_free(cur);

                     if (line != NULL)
                            *line = myline;
                     if (outpath != NULL)
                            strlcpy(outpath, file, outpathlen);

                     if (in != stdin)
                            fclose(in);

                     return NULL;
              }

              if (def[n].cd_type != CONFIG_TYPE_INCLUDE)
              {
                     new = (struct config *) malloc(sizeof(struct config));
                     if (new == NULL)
                     {
                            config_free(cur);

                            conf_error = CONF_NMEMORY;

                            if (line != NULL)
                                   *line = myline;
                            if (outpath != NULL)
                                   strlcpy(outpath, file, outpathlen);

                            if (in != stdin)
                                   fclose(in);

                            return NULL;
                     }

                     new->cfg_next = cur;
                     new->cfg_name = def[n].cd_name;
                     new->cfg_type = def[n].cd_type;
              }

              switch (def[n].cd_type)
              {
                case CONFIG_TYPE_INCLUDE:
                {
                     struct config *incl;

                     incl = config_load_level(str, def, line, outpath,
                                              outpathlen, level + 1);
                     if (incl == NULL)
                     {
                            if (in != stdin)
                                   fclose(in);

                            return NULL;
                     }

                     config_attach(incl, &cur);
                     new = incl;

                     break;
                }

                case CONFIG_TYPE_STRING:
                     new->cfg_string = strdup(str);
                     break;

                case CONFIG_TYPE_BOOLEAN:
                     new->cfg_bool = (_Bool) value;
                     break;

                case CONFIG_TYPE_INTEGER:
                     new->cfg_int = value;
                     break;

                default:
                     assert(0);
              }

              cur = new;
       }

       conf_error = CONF_SUCCESS;

       if (in != stdin)
              fclose(in);

       if (myline == 0)
       {
              cur = (struct config *) malloc(sizeof *cur);
              if (cur != NULL)
              {
                     cur->cfg_bool = FALSE;
                     cur->cfg_type = CONFIG_TYPE_STRING;
                     cur->cfg_int = 0;
                     cur->cfg_name = "";
                     cur->cfg_string = "";
                     cur->cfg_next = NULL;

                     return cur;
              }
              else
              {
                     conf_error = CONF_NMEMORY;

                     if (line != NULL)
                            *line = myline;
                     if (outpath != NULL)
                            strlcpy(outpath, file, outpathlen);

                     return NULL;
              }
       }
       else
       {
              return cur;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

_Bool config_validname ( struct configdef def,
const char *  name 
)

Definition at line 636 of file config.c.

{
       unsigned int n;

       assert(def != NULL);
       assert(name != NULL);

       for (n = 0; ; n++)
       {
              if (def[n].cd_name == NULL)
                     return FALSE;

              if (strcasecmp(name, def[n].cd_name) == 0)
                     return TRUE;
       }

       assert(0);
       /* NOTREACHED */
}

Here is the caller graph for this function:


Variable Documentation

int conf_error [static]

Definition at line 58 of file config.c.

char config_c_id[] = "@(#)$Id: config.c,v 1.10.10.1 2010/10/27 21:43:09 cm-msk Exp $" [static]

Definition at line 11 of file config.c.