initial load of upstream version 1.06.32
[xmlrpc-c] / lib / abyss / src / conf.c
diff --git a/lib/abyss/src/conf.c b/lib/abyss/src/conf.c
new file mode 100644 (file)
index 0000000..84d7c97
--- /dev/null
@@ -0,0 +1,379 @@
+/******************************************************************************
+**
+** conf.c
+**
+** This file is part of the ABYSS Web server project.
+**
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+** 
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+**
+******************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined(WIN32) && !defined(__BORLANDC__)
+#include <direct.h>
+#endif
+
+#ifdef _UNIX
+#include <pwd.h>
+#endif
+
+#include "xmlrpc_config.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/abyss.h"
+#include "trace.h"
+#include "server.h"
+#include "http.h"
+
+/*********************************************************************
+** Configuration Files Parsing Functions
+*********************************************************************/
+
+
+
+static abyss_bool
+ConfReadLine(TFile *f,char *buffer,uint32_t len) {
+    abyss_bool r=TRUE;
+    char c,*p,*z=buffer;
+
+    while ((--len)>0)
+    {
+        if (FileRead(f,buffer,1)<1)
+        {
+            if (z==buffer)
+                r=FALSE;
+            break;
+        };
+
+        if ((*buffer==CR) || (*buffer==LF) )
+            break;
+
+        buffer++;
+    };
+
+    if (len==0)
+        while (FileRead(f,&c,1)==1)
+            if ((c==CR) || (c==LF))
+                break;
+
+    *buffer='\0';
+
+    /* Discard comments */
+    p=strchr(z,'#');
+    if (p)
+        *p='\0';
+
+    return r;
+}
+
+static abyss_bool
+ConfNextToken(char **p) {
+    while (1)
+        switch (**p)
+        {
+        case '\t':
+        case ' ':
+            (*p)++;
+            break;
+        case '\0':
+            return FALSE;
+        default:
+            return TRUE;
+        };
+}
+
+static char *
+ConfGetToken(char **p) {
+    char *p0=*p;
+
+    while (1)
+        switch (**p)
+        {
+        case '\t':
+        case ' ':
+        case CR:
+        case LF:
+        case '\0':
+            if (p0==*p)
+                return NULL;
+
+            if (**p)
+            {
+                **p='\0';
+                (*p)++;
+            };
+            return p0;
+
+        default:
+            (*p)++;
+        };
+}
+
+static abyss_bool
+ConfReadInt(const char * const p,
+            int32_t *    const n,
+            int32_t      const min,
+            int32_t      const max) {
+/*----------------------------------------------------------------------------
+   Convert string 'p' to integer *n.
+
+   If it isn't a valid integer or is not with the bounds [min, max],
+   return FALSE.  Otherwise, return TRUE.
+-----------------------------------------------------------------------------*/
+    char * e;
+
+    *n = strtol(p, &e, 10);
+
+    if (min != max)
+        return ((e != p) && (*n >= min) && (*n <= max));
+    else
+        return (e != p);
+}
+
+
+
+static abyss_bool
+ConfReadBool(char *p, abyss_bool *b) {
+    if (strcasecmp(p,"yes")==0)
+    {
+        *b=TRUE;
+        return TRUE;
+    };
+
+    if (strcasecmp(p,"no")==0)
+    {
+        *b=FALSE;
+        return TRUE;
+    };
+
+    return FALSE;
+}
+
+/*********************************************************************
+** MIME Types File
+*********************************************************************/
+
+static void
+readMIMETypesFile(const char * const filename,
+                  MIMEType **  const MIMETypePP) {
+
+    abyss_bool success;
+    MIMEType * MIMETypeP;
+
+    MIMETypeP = MIMETypeCreate();
+    if (MIMETypeP) {
+        TFile file;
+        abyss_bool fileOpened;
+
+        fileOpened = FileOpen(&file, filename, O_RDONLY);
+        if (fileOpened) {
+            char z[512];
+            while (ConfReadLine(&file, z, 512)) {
+                char * p;
+                p = &z[0];
+            
+                if (ConfNextToken(&p)) {
+                    const char * mimetype = ConfGetToken(&p);
+                    if (mimetype) {
+                        while (ConfNextToken(&p)) {
+                            const char * const ext = ConfGetToken(&p);
+                            if (ext)
+                                MIMETypeAdd2(MIMETypeP, mimetype, ext);
+                            else
+                                break;
+                        }
+                    }
+                }
+            }
+            FileClose(&file);
+            success = TRUE;
+        } else
+            success = FALSE;
+        if (!success)
+            MIMETypeDestroy(MIMETypeP);
+    } else
+        success = FALSE;
+
+    if (success)
+        *MIMETypePP = MIMETypeP;
+    else
+        *MIMETypePP = NULL;
+}
+
+/*********************************************************************
+** Server Configuration File
+*********************************************************************/
+
+static void
+chdirx(const char * const newdir,
+       abyss_bool * const successP) {
+    
+#if defined(WIN32) && !defined(__BORLANDC__)
+    *successP = _chdir(newdir) == 0;
+#else
+    *successP = chdir(newdir) == 0;
+#endif
+}
+
+
+
+static void
+parseUser(const char *      const p, 
+          struct _TServer * const srvP) {
+#ifdef _UNIX
+    if (p[0] == '#') {
+        int32_t n;
+        
+        if (!ConfReadInt(&p[1], &n, 0, 0))
+            TraceExit("Bad user number '%s'", p);
+        else
+            srvP->uid = n;
+    } else {
+        struct passwd * pwd;
+
+        if (!(pwd = getpwnam(p)))
+            TraceExit("Unknown user '%s'", p);
+        
+        srvP->uid = pwd->pw_uid;
+        if ((int)srvP->gid==(-1))
+            srvP->gid = pwd->pw_gid;
+    };
+#else
+    TraceMsg("User option ignored");
+#endif  /* _UNIX */ 
+}
+
+
+
+static void
+parsePidfile(const char *      const p,
+             struct _TServer * const srvP) {
+#ifdef _UNIX
+    if (!FileOpenCreate(&srvP->pidfile, p, O_TRUNC | O_WRONLY)) {
+        srvP->pidfile = -1;
+        TraceMsg("Bad PidFile value '%s'", p);
+    };
+#else
+    TraceMsg("PidFile option ignored");
+#endif  /* _UNIX */ 
+}
+
+
+
+abyss_bool
+ConfReadServerFile(const char * const filename,
+                   TServer *    const serverP) {
+
+    struct _TServer * const srvP = serverP->srvP;
+
+    TFile f;
+    char z[512];
+    char * p;
+    unsigned int lineNum;
+    TFileStat fs;
+
+    if (!FileOpen(&f, filename, O_RDONLY))
+        return FALSE;
+
+    lineNum = 0;
+
+    while (ConfReadLine(&f, z, 512)) {
+        ++lineNum;
+        p = z;
+
+        if (ConfNextToken(&p)) {
+            const char * const option = ConfGetToken(&p);
+            if (option) {
+                ConfNextToken(&p);
+
+                if (strcasecmp(option, "port") == 0) {
+                    int32_t n;
+                    if (ConfReadInt(p, &n, 1, 65535))
+                        srvP->port = n;
+                    else
+                        TraceExit("Invalid port '%s'", p);
+                } else if (strcasecmp(option, "serverroot") == 0) {
+                    abyss_bool success;
+                    chdirx(p, &success);
+                    if (!success)
+                        TraceExit("Invalid server root '%s'",p);
+                } else if (strcasecmp(option, "path") == 0) {
+                    if (FileStat(p, &fs))
+                        if (fs.st_mode & S_IFDIR) {
+                            xmlrpc_strfree(srvP->filespath);
+                            srvP->filespath = strdup(p);
+                            continue;
+                        }
+                    TraceExit("Invalid path '%s'", p);
+                } else if (strcasecmp(option, "default") == 0) {
+                    const char * filename;
+                    
+                    while ((filename = ConfGetToken(&p))) {
+                        ListAdd(&srvP->defaultfilenames, strdup(filename));
+                        if (!ConfNextToken(&p))
+                            break;
+                    }
+                } else if (strcasecmp(option, "keepalive") == 0) {
+                    int32_t n;
+                    if (ConfReadInt(p, &n, 1, 65535))
+                        srvP->keepalivemaxconn = n;
+                    else
+                        TraceExit("Invalid KeepAlive value '%s'", p);
+                } else if (strcasecmp(option, "timeout") == 0) {
+                    int32_t n;
+                    if (ConfReadInt(p, &n, 1, 3600)) {
+                        srvP->keepalivetimeout = n;
+                        /* Must see what to do with that */
+                        srvP->timeout = n;
+                    } else
+                        TraceExit("Invalid TimeOut value '%s'", p);
+                } else if (strcasecmp(option, "mimetypes") == 0) {
+                    readMIMETypesFile(p, &srvP->mimeTypeP);
+                    if (!srvP->mimeTypeP)
+                        TraceExit("Can't read MIME Types file '%s'", p);
+                } else if (strcasecmp(option,"logfile") == 0) {
+                    srvP->logfilename = strdup(p);
+                } else if (strcasecmp(option,"user") == 0) {
+                    parseUser(p, srvP);
+                } else if (strcasecmp(option, "pidfile")==0) {
+                    parsePidfile(p, srvP);
+                } else if (strcasecmp(option, "advertiseserver") == 0) {
+                    if (!ConfReadBool(p, &srvP->advertise))
+                        TraceExit("Invalid boolean value "
+                                  "for AdvertiseServer option");
+                } else
+                    TraceExit("Invalid option '%s' at line %u",
+                              option, lineNum);
+            }
+        }
+    }
+
+    FileClose(&f);
+    return TRUE;
+}