00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037 #include <string.h>
00038
00039 #if defined(WIN32) && !defined(__BORLANDC__)
00040 #include <direct.h>
00041 #endif
00042
00043 #ifdef _UNIX
00044 #include <pwd.h>
00045 #endif
00046
00047 #include <xmlrpc-c/config.h>
00048 #include "abyss_xmlrpc_int.h"
00049 #include <xmlrpc-c/abyss.h>
00050 #include "abyss_trace.h"
00051 #include "abyss_server.h"
00052 #include "abyss_http.h"
00053
00054
00055
00056
00057
00058
00059
00060 static abyss_bool
00061 ConfReadLine(TFile *f,char *buffer,uint32_t len) {
00062 abyss_bool r=TRUE;
00063 char c,*p,*z=buffer;
00064
00065 while ((--len)>0)
00066 {
00067 if (FileRead(f,buffer,1)<1)
00068 {
00069 if (z==buffer)
00070 r=FALSE;
00071 break;
00072 };
00073
00074 if ((*buffer==CR) || (*buffer==LF) )
00075 break;
00076
00077 buffer++;
00078 };
00079
00080 if (len==0)
00081 while (FileRead(f,&c,1)==1)
00082 if ((c==CR) || (c==LF))
00083 break;
00084
00085 *buffer='\0';
00086
00087
00088 p=strchr(z,'#');
00089 if (p)
00090 *p='\0';
00091
00092 return r;
00093 }
00094
00095 static abyss_bool
00096 ConfNextToken(char **p) {
00097 while (1)
00098 switch (**p)
00099 {
00100 case '\t':
00101 case ' ':
00102 (*p)++;
00103 break;
00104 case '\0':
00105 return FALSE;
00106 default:
00107 return TRUE;
00108 };
00109 }
00110
00111 static char *
00112 ConfGetToken(char **p) {
00113 char *p0=*p;
00114
00115 while (1)
00116 switch (**p)
00117 {
00118 case '\t':
00119 case ' ':
00120 case CR:
00121 case LF:
00122 case '\0':
00123 if (p0==*p)
00124 return NULL;
00125
00126 if (**p)
00127 {
00128 **p='\0';
00129 (*p)++;
00130 };
00131 return p0;
00132
00133 default:
00134 (*p)++;
00135 };
00136 }
00137
00138 static abyss_bool
00139 ConfReadInt(const char * const p,
00140 int32_t * const n,
00141 int32_t const min,
00142 int32_t const max) {
00143
00144
00145
00146
00147
00148
00149 char * e;
00150
00151 *n = strtol(p, &e, 10);
00152
00153 if (min != max)
00154 return ((e != p) && (*n >= min) && (*n <= max));
00155 else
00156 return (e != p);
00157 }
00158
00159
00160
00161 static abyss_bool
00162 ConfReadBool(char *p, abyss_bool *b) {
00163 if (strcasecmp(p,"yes")==0)
00164 {
00165 *b=TRUE;
00166 return TRUE;
00167 };
00168
00169 if (strcasecmp(p,"no")==0)
00170 {
00171 *b=FALSE;
00172 return TRUE;
00173 };
00174
00175 return FALSE;
00176 }
00177
00178
00179
00180
00181
00182 static void
00183 readMIMETypesFile(const char * const filename,
00184 MIMEType ** const MIMETypePP) {
00185
00186 abyss_bool success;
00187 MIMEType * MIMETypeP;
00188
00189 MIMETypeP = MIMETypeCreate();
00190 if (MIMETypeP) {
00191 TFile file;
00192 abyss_bool fileOpened;
00193
00194 fileOpened = FileOpen(&file, filename, O_RDONLY);
00195 if (fileOpened) {
00196 char z[512];
00197 while (ConfReadLine(&file, z, 512)) {
00198 char * p;
00199 p = &z[0];
00200
00201 if (ConfNextToken(&p)) {
00202 const char * mimetype = ConfGetToken(&p);
00203 if (mimetype) {
00204 while (ConfNextToken(&p)) {
00205 const char * const ext = ConfGetToken(&p);
00206 if (ext)
00207 MIMETypeAdd2(MIMETypeP, mimetype, ext);
00208 else
00209 break;
00210 }
00211 }
00212 }
00213 }
00214 FileClose(&file);
00215 success = TRUE;
00216 } else
00217 success = FALSE;
00218 if (!success)
00219 MIMETypeDestroy(MIMETypeP);
00220 } else
00221 success = FALSE;
00222
00223 if (success)
00224 *MIMETypePP = MIMETypeP;
00225 else
00226 *MIMETypePP = NULL;
00227 }
00228
00229
00230
00231
00232
00233 static void
00234 chdirx(const char * const newdir,
00235 abyss_bool * const successP) {
00236
00237 #if defined(WIN32) && !defined(__BORLANDC__)
00238 *successP = _chdir(newdir) == 0;
00239 #else
00240 *successP = chdir(newdir) == 0;
00241 #endif
00242 }
00243
00244
00245
00246 static void
00247 parseUser(const char * const p,
00248 struct _TServer * const srvP) {
00249 #ifdef _UNIX
00250 if (p[0] == '#') {
00251 int32_t n;
00252
00253 if (!ConfReadInt(&p[1], &n, 0, 0))
00254 TraceExit("Bad user number '%s'", p);
00255 else
00256 srvP->uid = n;
00257 } else {
00258 struct passwd * pwd;
00259
00260 if (!(pwd = getpwnam(p)))
00261 TraceExit("Unknown user '%s'", p);
00262
00263 srvP->uid = pwd->pw_uid;
00264 if ((int)srvP->gid==(-1))
00265 srvP->gid = pwd->pw_gid;
00266 };
00267 #else
00268 TraceMsg("User option ignored");
00269 #endif
00270 }
00271
00272
00273
00274 static void
00275 parsePidfile(const char * const p,
00276 struct _TServer * const srvP) {
00277 #ifdef _UNIX
00278 if (!FileOpenCreate(&srvP->pidfile, p, O_TRUNC | O_WRONLY)) {
00279 srvP->pidfile = -1;
00280 TraceMsg("Bad PidFile value '%s'", p);
00281 };
00282 #else
00283 TraceMsg("PidFile option ignored");
00284 #endif
00285 }
00286
00287
00288
00289 abyss_bool
00290 ConfReadServerFile(const char * const filename,
00291 TServer * const serverP) {
00292
00293 struct _TServer * const srvP = serverP->srvP;
00294
00295 TFile f;
00296 char z[512];
00297 char * p;
00298 unsigned int lineNum;
00299 TFileStat fs;
00300
00301 if (!FileOpen(&f, filename, O_RDONLY))
00302 return FALSE;
00303
00304 lineNum = 0;
00305
00306 while (ConfReadLine(&f, z, 512)) {
00307 ++lineNum;
00308 p = z;
00309
00310 if (ConfNextToken(&p)) {
00311 const char * const option = ConfGetToken(&p);
00312 if (option) {
00313 ConfNextToken(&p);
00314
00315 if (strcasecmp(option, "port") == 0) {
00316 int32_t n;
00317 if (ConfReadInt(p, &n, 1, 65535))
00318 srvP->port = n;
00319 else
00320 TraceExit("Invalid port '%s'", p);
00321 } else if (strcasecmp(option, "serverroot") == 0) {
00322 abyss_bool success;
00323 chdirx(p, &success);
00324 if (!success)
00325 TraceExit("Invalid server root '%s'",p);
00326 } else if (strcasecmp(option, "path") == 0) {
00327 if (FileStat(p, &fs))
00328 if (fs.st_mode & S_IFDIR) {
00329 xmlrpc_strfree(srvP->filespath);
00330 srvP->filespath = strdup(p);
00331 continue;
00332 }
00333 TraceExit("Invalid path '%s'", p);
00334 } else if (strcasecmp(option, "default") == 0) {
00335 const char * filename;
00336
00337 while ((filename = ConfGetToken(&p))) {
00338 ListAdd(&srvP->defaultfilenames, strdup(filename));
00339 if (!ConfNextToken(&p))
00340 break;
00341 }
00342 } else if (strcasecmp(option, "keepalive") == 0) {
00343 int32_t n;
00344 if (ConfReadInt(p, &n, 1, 65535))
00345 srvP->keepalivemaxconn = n;
00346 else
00347 TraceExit("Invalid KeepAlive value '%s'", p);
00348 } else if (strcasecmp(option, "timeout") == 0) {
00349 int32_t n;
00350 if (ConfReadInt(p, &n, 1, 3600)) {
00351 srvP->keepalivetimeout = n;
00352
00353 srvP->timeout = n;
00354 } else
00355 TraceExit("Invalid TimeOut value '%s'", p);
00356 } else if (strcasecmp(option, "mimetypes") == 0) {
00357 readMIMETypesFile(p, &srvP->mimeTypeP);
00358 if (!srvP->mimeTypeP)
00359 TraceExit("Can't read MIME Types file '%s'", p);
00360 } else if (strcasecmp(option,"logfile") == 0) {
00361 srvP->logfilename = strdup(p);
00362 } else if (strcasecmp(option,"user") == 0) {
00363 parseUser(p, srvP);
00364 } else if (strcasecmp(option, "pidfile")==0) {
00365 parsePidfile(p, srvP);
00366 } else if (strcasecmp(option, "advertiseserver") == 0) {
00367 if (!ConfReadBool(p, &srvP->advertise))
00368 TraceExit("Invalid boolean value "
00369 "for AdvertiseServer option");
00370 } else
00371 TraceExit("Invalid option '%s' at line %u",
00372 option, lineNum);
00373 }
00374 }
00375 }
00376
00377 FileClose(&f);
00378 return TRUE;
00379 }