1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
5 * Copyright (C) 2001-2003, Eduardo Silva P.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
43 struct mk_config
*mk_config_create(char *path
)
48 char *key
=0, *val
=0, *last
=0;
49 struct mk_config
*cnf
=0, *new, *p
;
51 if((f
=fopen(path
, "r")) == NULL
) {
52 fprintf(stderr
, "\nConfig Error: I can't open %s file\n\n", path
);
56 /* looking for configuration directives */
57 while(fgets(buf
, 255, f
)){
59 if(buf
[len
-1] == '\n') {
61 if(len
&& buf
[len
-1] == '\r')
65 if(!buf
[0] || buf
[0] == '#')
68 key
= strtok_r(buf
, "\"\t ", &last
);
69 val
= strtok_r(NULL
, "\n", &last
);
75 /* Allow new entry found */
76 new = mk_mem_malloc(sizeof(struct mk_config
));
77 new->key
= mk_string_dup(key
);
78 new->val
= mk_string_dup(val
);
81 /* Link to main list */
98 void mk_config_free(struct mk_config
*cnf
)
100 struct mk_config
*prev
=0, *target
;
106 target
= target
->next
;
119 void *mk_config_getval(struct mk_config
*cnf
, char *key
, int mode
)
126 if(strcasecmp(p
->key
, key
) == 0){
128 case MK_CONFIG_VAL_STR
:
129 return (void *) p
->val
;
130 case MK_CONFIG_VAL_NUM
:
131 return (void *) atoi(p
->val
);
132 case MK_CONFIG_VAL_BOOL
:
133 on
= strcasecmp(p
->val
, VALUE_ON
);
134 off
= strcasecmp(p
->val
,VALUE_OFF
);
140 return (void *) VAR_ON
;
143 return (void *) VAR_OFF
;
145 case MK_CONFIG_VAL_LIST
:
146 return mk_string_split_line(p
->val
);
156 /* Read configuration files */
157 void mk_config_read_files(char *path_conf
, char *file_conf
)
161 struct stat checkdir
;
162 struct mk_config
*cnf
;
163 struct mk_string_line
*line
, *line_val
;
165 config
->serverconf
= mk_string_dup(path_conf
);
166 config
->workers
= MK_WORKERS_DEFAULT
;
168 if(stat(config
->serverconf
, &checkdir
)==-1){
169 fprintf(stderr
, "ERROR: Invalid path to configuration files.");
173 m_build_buffer(&path
, &len
, "%s/%s", path_conf
, file_conf
);
175 cnf
= mk_config_create(path
);
177 /* Connection port */
178 config
->serverport
= (int) mk_config_getval(cnf
,
181 if(!config
->serverport
>=1 && !config
->serverport
<=65535){
182 mk_config_print_error_msg("Port", path
);
185 /* Number of thread workers */
186 config
->workers
= (int) mk_config_getval(cnf
,
189 if(config
->maxclients
< 1){
190 mk_config_print_error_msg("Workers", path
);
194 config
->timeout
= (int) mk_config_getval(cnf
,
197 if(config
->timeout
< 1){
198 mk_config_print_error_msg("Timeout", path
);
202 config
->keep_alive
= (int) mk_config_getval(cnf
,
205 if(config
->keep_alive
== VAR_ERR
){
206 mk_config_print_error_msg("KeepAlive", path
);
209 /* MaxKeepAliveRequest */
210 config
->max_keep_alive_request
= (int) mk_config_getval(cnf
,
211 "MaxKeepAliveRequest",
213 if(config
->max_keep_alive_request
== 0){
214 mk_config_print_error_msg("MaxKeepAliveRequest", path
);
217 /* KeepAliveTimeout */
218 config
->keep_alive_timeout
= (int) mk_config_getval(cnf
,
221 if(config
->keep_alive_timeout
== 0){
222 mk_config_print_error_msg("KeepAliveTimeout", path
);
226 config
->pid_file_path
= mk_config_getval(cnf
,
230 /* Home user's directory /~ */
231 config
->user_dir
= mk_config_getval(cnf
, "UserDir", MK_CONFIG_VAL_STR
);
234 line_val
= line
= mk_config_getval(cnf
, "Indexfile", MK_CONFIG_VAL_LIST
);
235 while(line_val
!=NULL
) {
236 mk_config_add_index(line_val
->val
);
237 line_val
= line_val
->next
;
240 /* HideVersion Variable */
241 config
->hideversion
= (int) mk_config_getval(cnf
,
244 if(config
->hideversion
== VAR_ERR
){
245 mk_config_print_error_msg("HideVersion", path
);
249 config
->user
= mk_config_getval(cnf
, "User", MK_CONFIG_VAL_STR
);
252 config
->resume
= (int) mk_config_getval(cnf
,
255 if(config
->resume
== VAR_ERR
){
256 mk_config_print_error_msg("Resume", path
);
260 config
->symlink
= (int) mk_config_getval(cnf
,
263 if(config
->symlink
== VAR_ERR
){
264 mk_config_print_error_msg("SymLink", path
);
269 mk_config_read_hosts(path_conf
);
272 void mk_config_read_hosts(char *path
)
278 struct host
*p_host
, *new_host
; /* debug */
281 m_build_buffer(&buf
, &len
, "%s/sites/default", path
);
282 config
->hosts
= mk_config_get_host(buf
);
288 printf("\nError parsing main configuration file 'default'\n");
292 m_build_buffer(&buf
, &len
, "%s/sites/", path
);
293 if (!(dir
= opendir(buf
)))
297 p_host
= config
->hosts
;
299 /* Reading content */
300 while ((ent
= readdir(dir
)) != NULL
)
302 if (strcmp((char *) ent
->d_name
, "." ) == 0) continue;
303 if (strcmp((char *) ent
->d_name
, ".." ) == 0) continue;
304 if (strcasecmp((char *) ent
->d_name
, "default" ) == 0) continue;
306 m_build_buffer(&file
, &len
, "%s/sites/%s", path
, ent
->d_name
);
308 new_host
= (struct host
*) mk_config_get_host(file
);
315 p_host
->next
= new_host
;
325 printf("*** HOST ***\n");
326 printf(" [servername]\t\t%s\n", h->servername);
327 printf(" [documentroot]\t\t%s\n", h->documentroot);
328 printf(" [conf file]\t\t%s\n", h->file);
329 printf(" [access log]\t\t%s\n", h->access_log_path);
330 printf(" [error log]\t\t%s\n", h->error_log_path);
331 printf(" [script alias]\t\t%s %s\n", h->scriptalias[0], h->scriptalias[1]);
332 printf(" [get dir]\t\t%i\n", h->getdir);
333 printf(" [header file]\t\t%s\n", h->header_file);
334 printf(" [footer file]\t\t%s\n\n", h->footer_file);
342 struct host
*mk_config_get_host(char *path
)
345 struct stat checkdir
;
347 struct mk_config
*cnf
;
349 cnf
= mk_config_create(path
);
351 host
= mk_mem_malloc_z(sizeof(struct host
));
352 host
->servername
= 0;
353 host
->file
= mk_string_dup(path
);
355 host
->servername
= mk_config_getval(cnf
, "Servername", MK_CONFIG_VAL_STR
);
356 host
->documentroot
.data
= mk_config_getval(cnf
,
359 host
->documentroot
.len
= strlen(host
->documentroot
.data
);
360 if(stat(host
->documentroot
.data
, &checkdir
)==-1) {
362 "ERROR: Invalid path to Server_root in %s\n\n",
366 else if(!(checkdir
.st_mode
& S_IFDIR
)) {
368 "ERROR: DocumentRoot variable in %s has an invalid directory path\n\n",
374 host
->access_log_path
= mk_config_getval(cnf
,
378 host
->error_log_path
= mk_config_getval(cnf
,
383 host
->getdir
= (int) mk_config_getval(cnf
, "GetDir", MK_CONFIG_VAL_BOOL
);
384 if(host
->getdir
== VAR_ERR
){
385 mk_config_print_error_msg("GetDir", path
);
388 if(!host
->servername
){
393 /* Server Signature */
394 if(config
->hideversion
==VAR_OFF
){
395 m_build_buffer(&host
->host_signature
, &len
,
396 "Monkey/%s Server (Host: %s, Port: %i)",
397 VERSION
, host
->servername
, config
->serverport
);
400 m_build_buffer(&host
->host_signature
, &len
,
401 "Monkey Server (Host: %s, Port: %i)",
402 host
->servername
, config
->serverport
);
404 m_build_buffer(&host
->header_host_signature
.data
,
405 &host
->header_host_signature
.len
,
406 "Server: %s", host
->host_signature
);
408 if(pipe(host
->log_access
)<0){
412 if(pipe(host
->log_error
)<0){
416 fcntl(host
->log_access
[1], F_SETFL
, O_NONBLOCK
);
417 fcntl(host
->log_error
[1], F_SETFL
, O_NONBLOCK
);
424 /* Imprime error de configuracion y cierra */
425 void mk_config_print_error_msg(char *variable
, char *path
)
427 fprintf(stderr
, "\nError: %s variable in %s has an invalid value.\n", variable
, path
);
432 /* Agrega distintos index.xxx */
433 void mk_config_add_index(char *indexname
)
435 struct indexfile
*new_index
=0, *aux_index
;
437 new_index
= (struct indexfile
*) malloc(sizeof(struct indexfile
));
438 strncpy(new_index
->indexname
,indexname
,MAX_INDEX_NOMBRE
- 1);
439 new_index
->indexname
[MAX_INDEX_NOMBRE
- 1]='\0';
440 new_index
->next
=NULL
;
442 if(first_index
==NULL
) {
443 first_index
=new_index
;
446 aux_index
=first_index
;
447 while(aux_index
->next
!=NULL
)
448 aux_index
=aux_index
->next
;
449 aux_index
->next
=new_index
;
453 void mk_config_set_init_values(void)
455 /* Valores iniciales */
457 config
->hideversion
=VAR_OFF
;
458 config
->keep_alive
=VAR_ON
;
459 config
->keep_alive_timeout
=15;
460 config
->max_keep_alive_request
=50;
461 config
->maxclients
=150;
463 config
->resume
=VAR_ON
;
464 config
->standard_port
=80;
465 config
->serverport
=2001;
466 config
->symlink
=VAR_OFF
;
469 config
->open_flags
= O_RDONLY
| O_NONBLOCK
;
472 config
->plugins
= mk_mem_malloc_z(sizeof(struct plugin_stages
));
475 /* read main configuration from monkey.conf */
476 void mk_config_start_configure(void)
480 mk_config_set_init_values();
481 mk_config_read_files(config
->file_config
, M_DEFAULT_CONFIG_FILE
);
483 /* if not index names defined, set default */
484 if(first_index
==NULL
){
485 mk_config_add_index("index.html");
489 mk_mimetype_read_config();
491 /* Basic server information */
492 if(config
->hideversion
==VAR_OFF
)
494 m_build_buffer(&config
->server_software
.data
,
495 &len
, "Monkey/%s (%s)",VERSION
,OS
);
496 config
->server_software
.len
= len
;
500 m_build_buffer(&config
->server_software
.data
, &len
,
502 config
->server_software
.len
= len
;
506 struct host
*mk_config_host_find(mk_pointer host
)
508 struct host
*aux_host
;
510 aux_host
= config
->hosts
;
513 if(strncasecmp(aux_host
->servername
, host
.data
, host
.len
)==0)
516 aux_host
=aux_host
->next
;
522 void mk_config_sanity_check()
524 /* Check O_NOATIME for current user, flag will just be used
525 * if running user is allowed to.
527 int fd
, flags
=config
->open_flags
;
530 fd
= open(config
->file_config
, flags
);
533 config
->open_flags
= flags
;