pre-threading improves (Felipe)
[MonkeyD.git] / src / config.c
blob84d84137df43f5d5c50279e245a4baa866b797b5
1 /* Monkey HTTP Daemon
2 * ------------------
3 * Copyright (C) 2001-2003, Eduardo Silva P.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <dirent.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <stdlib.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <string.h>
30 #include "monkey.h"
32 /* Read configuration files */
33 void M_Config_read_files(char *path_conf, char *file_conf)
35 int bool;
36 char *path=0, buffer[255];
37 char *variable=0, *value=0, *last=0, *auxarg=0;
38 FILE *configfile;
39 struct stat checkdir;
41 config->serverconf = M_strdup(path_conf);
43 if(stat(config->serverconf, &checkdir)==-1){
44 fprintf(stderr, "ERROR: Invalid path to configuration files.");
45 exit(1);
48 path = m_build_buffer("%s/%s", path_conf, file_conf);
50 if( (configfile=fopen(path,"r"))==NULL ) {
51 fprintf(stderr, "Error: I can't open %s file.\n", path);
52 exit(1);
55 while(fgets(buffer,255,configfile)) {
56 int len;
57 len = strlen(buffer);
58 if(buffer[len-1] == '\n') {
59 buffer[--len] = 0;
60 if(len && buffer[len-1] == '\r')
61 buffer[--len] = 0;
64 if(!buffer[0] || buffer[0] == '#')
65 continue;
67 variable = strtok_r(buffer, "\"\t ", &last);
68 value = strtok_r(NULL, "\"\t ", &last);
70 if (!variable || !value) continue;
72 /* Puerto de conexion */
73 if(strcasecmp(variable, "Port")==0) {
74 config->serverport=atoi(value);
75 if(!config->serverport>=1 && !config->serverport<=65535)
76 M_Config_print_error_msg("Port", path);
79 /* Timeout */
80 if(strcasecmp(variable,"Timeout")==0) {
81 config->timeout=atoi(value);
82 if(config->timeout<1 || !value)
83 M_Config_print_error_msg("Timeout", path);
86 /* KeepAlive */
87 if(strcasecmp(variable,"KeepAlive")==0) {
88 bool = M_Config_Get_Bool(value);
89 if(bool == VAR_ERR)
91 M_Config_print_error_msg("KeepAlive", path);
93 else{
94 config->keep_alive=bool;
98 /* MaxKeepAliveRequest */
99 if(strcasecmp(variable,"MaxKeepAliveRequest")==0){
100 config->max_keep_alive_request=atoi(value);
101 if(config->max_keep_alive_request!=0)
102 config->max_keep_alive_request++;
103 if(config->max_keep_alive_request==0)
104 M_Config_print_error_msg("MaxKeepAliveRequest", path);
107 /* KeepAliveTimeout */
108 if(strcasecmp(variable,"KeepAliveTimeout")==0){
109 config->keep_alive_timeout=atoi(value);
110 if(config->keep_alive_timeout==0)
111 M_Config_print_error_msg("KeepAliveTimeout", path);
114 /* MaxClients */
115 if(strcasecmp(variable,"MaxClients")==0) {
116 config->maxclients=atoi(value);
117 if(config->maxclients < 1)
118 M_Config_print_error_msg("MaxClients", path);
121 /* Pid File */
122 if(strcasecmp(variable,"PidFile")==0)
123 config->pid_file_path=m_build_buffer("%s", value);
125 /* Directorio para /~ */
126 if(strcasecmp(variable,"UserDir")==0){
127 config->user_dir = m_build_buffer("%s", value);
130 /* Variable INDEX */
131 if(strcasecmp(variable,"Indexfile")==0) {
132 auxarg=value;
133 while(auxarg!=NULL) {
134 M_Config_add_index(auxarg);
135 auxarg=strtok_r(NULL,"\"\t ", &last);
139 /* HideVersion Variable */
140 if(strcasecmp(variable,"HideVersion")==0) {
141 bool = M_Config_Get_Bool(value);
142 if(bool == VAR_ERR)
144 M_Config_print_error_msg("HideVersion", path);
146 else{
147 config->hideversion=bool;
151 /* Scripts */
152 if(strcasecmp(variable,"AddScript")==0){
153 char *mimescript[4];
155 mimescript[0]=value; /* Mime Type */
156 mimescript[1]=strtok_r(NULL,"\"\t ", &last); /* Bin Path */
157 mimescript[2]=strtok_r(NULL,"\"\t ", &last); /* Ext */
158 mimescript[3]='\0';
160 if(strlen(mimescript[0])<1){
161 printf("Error: AddScript variable in %s -> mime type not found.\n", path);
162 exit(1);
165 if(access(mimescript[1],X_OK)!=0 || CheckFile(mimescript[1])!=0){
166 printf("Error: AddScript variable in %s -> binary file not valid.\n", path);
167 exit(1);
169 if(strlen(mimescript[2])<1){
170 printf("Error: AddScript variable in %s -> extension not found.\n", path);
171 exit(1);
173 Mimetype_Add(mimescript[2],mimescript[0],mimescript[1]);
176 /* User Variable */
177 if(strcasecmp(variable,"User")==0) {
178 config->user = m_build_buffer("%s", value);
181 /* Resume */
182 if(strcasecmp(variable, "Resume")==0)
184 bool = M_Config_Get_Bool(value);
185 if(bool == VAR_ERR)
187 M_Config_print_error_msg("Resume", path);
189 else{
190 config->resume=bool;
194 /* Symbolic Links */
195 if(strcasecmp(variable, "SymLink")==0) {
196 bool = M_Config_Get_Bool(value);
197 if(bool == VAR_ERR)
199 M_Config_print_error_msg("SymLink", path);
201 else{
202 config->symlink=bool;
205 /* Max connection per IP */
206 if(strcasecmp(variable, "Max_IP")==0) {
207 config->max_ip = atoi(value);
208 if(config->max_ip < 0)
209 M_Config_print_error_msg("Max_IP", path);
212 /* Including files */
213 if(strcasecmp(variable,"Include")==0) {
214 M_Config_read_files(path_conf, value);
217 fclose(configfile);
218 M_free(path);
219 M_Config_Read_Hosts(path_conf);
222 void M_Config_Read_Hosts(char *path)
224 DIR *dir;
225 char *buf;
226 char *file;
227 struct host *p_host, *new_host; /* debug */
228 struct dirent *ent;
230 buf = m_build_buffer("%s/sites/default", path);
231 config->hosts = M_Config_Get_Host(buf);
232 M_free(buf);
234 if(!config->hosts)
236 printf("\nError parsing main configuration file 'default'\n");
237 exit(1);
240 buf = m_build_buffer("%s/sites/", path);
241 if (!(dir = opendir(buf)))
242 exit(1);
245 p_host = config->hosts;
247 /* Reading content */
248 while ((ent = readdir(dir)) != NULL)
250 if (strcmp((char *) ent->d_name, "." ) == 0) continue;
251 if (strcmp((char *) ent->d_name, ".." ) == 0) continue;
252 if (strcasecmp((char *) ent->d_name, "default" ) == 0) continue;
254 file = m_build_buffer("%s/sites/%s", path, ent->d_name);
256 new_host = (struct host *) M_Config_Get_Host(file);
257 M_free(file);
258 if(!new_host)
260 continue;
262 else{
263 p_host->next = new_host;
264 p_host = new_host;
268 h = config->hosts;
269 while(h)
271 printf("*** HOST ***\n");
272 printf(" [servername]\t\t%s\n", h->servername);
273 printf(" [documentroot]\t\t%s\n", h->documentroot);
274 printf(" [conf file]\t\t%s\n", h->file);
275 printf(" [access log]\t\t%s\n", h->access_log_path);
276 printf(" [error log]\t\t%s\n", h->error_log_path);
277 printf(" [script alias]\t\t%s %s\n", h->scriptalias[0], h->scriptalias[1]);
278 printf(" [get dir]\t\t%i\n", h->getdir);
279 printf(" [header file]\t\t%s\n", h->header_file);
280 printf(" [footer file]\t\t%s\n\n", h->footer_file);
282 h = h->next;
284 fflush(stdout);
288 int M_Config_Get_Bool(char *value)
290 int on, off;
292 on = strcasecmp(value, VALUE_ON);
293 off = strcasecmp(value,VALUE_OFF);
295 if(on!=0 && off!=0)
297 return -1;
299 else if(on>=0)
301 return VAR_ON;
303 else{
304 return VAR_OFF;
308 struct host *M_Config_Get_Host(char *path)
310 char buffer[255];
311 char *variable=0, *value=0, *last=0, *auxarg=0;
312 FILE *configfile;
313 struct stat checkdir;
314 struct host *host;
316 printf("[PARSING HOST FILE]: %s\n", path);
317 fflush(stdout);
319 if( (configfile=fopen(path,"r"))==NULL ) {
320 fprintf(stderr, "Error: I can't open %s file.\n", path);
321 return NULL;
324 host = M_malloc(sizeof(struct host));
325 host->file = M_strdup(path);
327 while(fgets(buffer,255,configfile)) {
328 int len;
329 len = strlen(buffer);
330 if(buffer[len-1] == '\n') {
331 buffer[--len] = 0;
332 if(len && buffer[len-1] == '\r')
333 buffer[--len] = 0;
336 if(!buffer[0] || buffer[0] == '#')
337 continue;
339 variable = strtok_r(buffer, "\"\t ", &last);
340 value = strtok_r(NULL, "\"\t ", &last);
342 if (!variable || !value) continue;
345 /* Server Name */
346 if(strcasecmp(variable,"Servername")==0)
347 host->servername = m_build_buffer("%s", value);
349 /* Ubicacion directorio servidor */
350 if(strcasecmp(variable,"DocumentRoot")==0) {
351 host->documentroot=M_strdup(value);
352 if(stat(host->documentroot, &checkdir)==-1) {
353 fprintf(stderr, "ERROR: Invalid path to Server_root in %s.", path);
354 exit(1);
356 else if(!(checkdir.st_mode & S_IFDIR)) {
357 fprintf(stderr, "ERROR: DocumentRoot variable in %s has an invalid directory path.", path);
358 exit(1);
362 /* Access log */
363 if(strcasecmp(variable,"AccessLog")==0)
364 host->access_log_path=m_build_buffer("%s", value);
366 /* Error log */
367 if(strcasecmp(variable,"ErrorLog")==0)
368 host->error_log_path = m_build_buffer("%s", value);
370 /* GetDir Variable */
371 if(strcasecmp(variable,"GetDir")==0)
373 if(strcasecmp(value,VALUE_ON) && strcasecmp(value,VALUE_OFF))
374 M_Config_print_error_msg("GetDir", path);
375 else if(strcasecmp(value,VALUE_OFF)==0)
376 host->getdir=VAR_OFF;
379 /* Script_Alias del server */
380 if(strcasecmp(variable,"ScriptAlias")==0)
382 if(!value) M_Config_print_error_msg("ScriptAlias", path);
383 host->scriptalias = (char **) M_malloc(sizeof(char *) * 3);
384 host->scriptalias[0]=M_strdup(value);
385 auxarg=strtok_r(NULL,"\"\t ", &last);
387 if(!auxarg) M_Config_print_error_msg("ScriptAlias", path);
388 host->scriptalias[1]=M_strdup(auxarg);
389 host->scriptalias[2]='\0';
392 if(strcasecmp(variable, "Header_file")==0)
393 host->header_file = m_build_buffer("%s", value);
395 if(strcasecmp(variable, "Footer_file")==0)
396 host->footer_file = m_build_buffer("%s", value);
399 fclose(configfile);
400 if(!host->servername)
402 return NULL;
405 /* Server Signature */
406 if(config->hideversion==VAR_OFF){
407 host->host_signature = m_build_buffer("Monkey/%s Server (Host: %s, Port: %i)",
408 VERSION, host->servername, config->serverport);
410 else{
411 host->host_signature = m_build_buffer("Monkey Server (Host: %s, Port: %i)",
412 host->servername, config->serverport);
415 host->next = NULL;
416 return host;
419 /* Imprime error de configuracion y cierra */
420 void M_Config_print_error_msg(char *variable, char *path)
422 fprintf(stderr, "\nError: %s variable in %s has an invalid value.\n", variable, path);
423 fflush(stderr);
424 exit(1);
427 /* Agrega distintos index.xxx */
428 void M_Config_add_index(char *indexname)
430 struct indexfile *new_index=0, *aux_index;
432 new_index = (struct indexfile *) malloc(sizeof(struct indexfile));
433 strncpy(new_index->indexname,indexname,MAX_INDEX_NOMBRE - 1);
434 new_index->indexname[MAX_INDEX_NOMBRE - 1]='\0';
435 new_index->next=NULL;
437 if(first_index==NULL) {
438 first_index=new_index;
440 else {
441 aux_index=first_index;
442 while(aux_index->next!=NULL)
443 aux_index=aux_index->next;
444 aux_index->next=new_index;
448 void M_Config_set_init_values(void)
450 /* Valores iniciales */
451 config->timeout=15;
452 config->hideversion=VAR_OFF;
453 config->keep_alive=VAR_ON;
454 config->keep_alive_timeout=15;
455 config->max_keep_alive_request=50;
456 config->maxclients=150;
457 config->max_ip = 15;
458 config->resume=VAR_ON;
459 config->standard_port=80;
460 config->serverport=2001;
461 config->server_addr=NULL;
462 config->symlink=VAR_OFF;
465 /* Lee la configuraci�n principal desde monkey.conf */
466 void M_Config_start_configure(void)
469 M_Config_set_init_values();
471 M_Config_read_files(config->file_config, M_DEFAULT_CONFIG_FILE);
473 /* Si no fueron definidas variables
474 INDEX, se asume index.html por omisi�n */
475 if(first_index==NULL)
476 M_Config_add_index("index.html");
478 /* Almacenar en estructura los mimetypes definidos */
479 Mimetype_Read_Config();
481 /* Carga directorios e IP's a denegar */
482 Deny_Read_Config();
484 /* Informaci�n b�sica del server */
485 if(config->hideversion==VAR_OFF)
486 config->server_software = m_build_buffer("Monkey/%s (%s)",VERSION,OS);
487 else
488 config->server_software = m_build_buffer("Monkey Server");