1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
5 * Copyright (C) 2001-2010, Eduardo Silva P. <edsiper@gmail.com>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
44 /* Raise a configuration error */
45 void mk_config_error(const char *path
, int line
, const char *msg
)
47 printf("\nReading %s", path
);
48 printf("\nError in line %i: %s\n\n", line
, msg
);
53 /* Returns a configuration section by [section name] */
54 struct mk_config_section
*mk_config_section_get(struct mk_config
*conf
,
55 const char *section_name
)
57 struct mk_config_section
*section
;
59 section
= conf
->section
;
61 if (strcasecmp(section
->name
, section_name
) == 0) {
64 section
= section
->next
;
70 /* Register a new section into the configuration struct */
71 void mk_config_section_add(struct mk_config
*conf
, char *section_name
)
73 struct mk_config_section
*new, *aux
;
75 /* Alloc section node */
76 new = mk_mem_malloc(sizeof(struct mk_config_section
));
77 new->name
= mk_string_dup(section_name
);
86 /* go to last section available */
96 /* Register a key/value entry in the last section available of the struct */
97 void mk_config_entry_add(struct mk_config
*conf
,
98 const char *key
, const char *val
)
100 struct mk_config_section
*section
;
101 struct mk_config_entry
*aux_entry
, *new_entry
;
103 if (!conf
->section
) {
104 puts("Error: there are not sections available!");
108 /* Go to last section */
109 section
= conf
->section
;
110 while (section
->next
) {
111 section
= section
->next
;
114 /* Alloc new entry */
115 new_entry
= mk_mem_malloc(sizeof(struct mk_config_entry
));
116 new_entry
->key
= mk_string_dup(key
);
117 new_entry
->val
= mk_string_dup(val
);
118 new_entry
->next
= NULL
;
120 /* Add first entry */
121 if (!section
->entry
) {
122 section
->entry
= new_entry
;
126 /* Go to last entry */
127 aux_entry
= section
->entry
;
128 while (aux_entry
->next
) {
129 aux_entry
= aux_entry
->next
;
132 aux_entry
->next
= new_entry
;
135 struct mk_config
*mk_config_create(const char *path
)
143 char *key
, *val
, *last
;
144 struct mk_config
*conf
= 0;
147 /* Open configuration file */
148 if ((f
= fopen(path
, "r")) == NULL
) {
149 fprintf(stderr
, "\nConfig Error: I can't open %s file\n\n", path
);
153 /* Alloc configuration node */
154 conf
= mk_mem_malloc(sizeof(struct mk_config
));
155 conf
->created
= time(NULL
);
156 conf
->file
= mk_string_dup(path
);
157 conf
->section
= NULL
;
159 /* looking for configuration directives */
160 while (fgets(buf
, 255, f
)) {
162 if (buf
[len
- 1] == '\n') {
164 if (len
&& buf
[len
- 1] == '\r') {
176 /* Skip commented lines */
179 mk_mem_free(section
);
185 /* Section definition */
188 end
= mk_string_char_search(buf
, ']', len
);
190 section
= mk_string_copy_substr(buf
, 1, end
);
191 mk_config_section_add(conf
, section
);
195 mk_config_error(path
, line
, "Bad header definition");
199 /* No separator defined */
203 do { i
++; } while (i
< len
&& isblank(buf
[i
]));
205 indent
= mk_string_copy_substr(buf
, 0, i
);
206 indent_len
= strlen(indent
);
208 /* Blank indented line */
214 /* Validate indentation level */
215 if (strncmp(buf
, indent
, indent_len
) != 0 || !section
||
216 isblank(buf
[indent_len
]) != 0) {
217 mk_config_error(path
, line
, "Invalid indentation level");
220 if (buf
[indent_len
] == '#' || indent_len
== len
) {
224 /* get line key and value */
225 key
= strtok_r(buf
+ indent_len
, "\"\t ", &last
);
226 val
= strtok_r(NULL
, "\"\t", &last
);
229 mk_config_error(path
, line
, "Each key must have a value");
234 mk_string_trim(&key
);
235 mk_string_trim(&val
);
238 mk_config_entry_add(conf
, key
, val
);
243 struct mk_config_section *s;
244 struct mk_config_entry *e;
248 printf("\n[%s]", s->name);
251 printf("\n %s = %s", e->key, e->val);
263 void mk_config_free(struct mk_config
*conf
)
265 struct mk_config_section
*prev
=0, *section
;
268 section
= conf
->section
;
270 while (section
->next
) {
272 section
= section
->next
;
275 /* Free section entries */
276 mk_config_free_entries(section
);
278 /* Free section node */
279 mk_mem_free(section
->name
);
280 mk_mem_free(section
);
282 if (section
== conf
->section
) {
286 section
= conf
->section
;
290 void mk_config_free_entries(struct mk_config_section
*section
)
292 struct mk_config_entry
*prev
= 0, *target
;
294 target
= section
->entry
;
296 while (target
->next
) {
298 target
= target
->next
;
301 /* Free memory assigned */
302 mk_mem_free(target
->key
);
303 mk_mem_free(target
->val
);
305 if (target
== section
->entry
) {
306 section
->entry
= NULL
;
311 target
= section
->entry
;
315 void *mk_config_section_getval(struct mk_config_section
*section
, char *key
, int mode
)
318 struct mk_config_entry
*entry
;
320 entry
= section
->entry
;
322 if (strcasecmp(entry
->key
, key
) == 0) {
324 case MK_CONFIG_VAL_STR
:
325 return (void *) entry
->val
;
326 case MK_CONFIG_VAL_NUM
:
327 return (void *) (size_t) atoi(entry
->val
);
328 case MK_CONFIG_VAL_BOOL
:
329 on
= strcasecmp(entry
->val
, VALUE_ON
);
330 off
= strcasecmp(entry
->val
, VALUE_OFF
);
332 if (on
!= 0 && off
!= 0) {
336 return (void *) VAR_ON
;
339 return (void *) VAR_OFF
;
341 case MK_CONFIG_VAL_LIST
:
342 return mk_string_split_line(entry
->val
);
352 /* Read configuration files */
353 void mk_config_read_files(char *path_conf
, char *file_conf
)
357 struct stat checkdir
;
358 struct mk_config
*cnf
;
359 struct mk_config_section
*section
;
361 config
->serverconf
= mk_string_dup(path_conf
);
362 config
->workers
= MK_WORKERS_DEFAULT
;
364 if (stat(config
->serverconf
, &checkdir
) == -1) {
365 fprintf(stderr
, "\nERROR: Invalid path to configuration files");
366 fprintf(stderr
, "\nCannot find/open '%s'\n", config
->serverconf
);
370 mk_string_build(&path
, &len
, "%s/%s", path_conf
, file_conf
);
372 cnf
= mk_config_create(path
);
373 section
= mk_config_section_get(cnf
, "SERVER");
376 fprintf(stderr
, "\nERROR: No 'SERVER' section defined\n");
380 /* Map source configuration */
381 config
->config
= cnf
;
384 config
->listen_addr
= mk_config_section_getval(section
, "Listen",
386 if (!config
->listen_addr
) {
387 config
->listen_addr
= MK_DEFAULT_LISTEN_ADDR
;
390 /* Connection port */
391 config
->serverport
= (size_t) mk_config_section_getval(section
,
394 if (!config
->serverport
>= 1 && !config
->serverport
<= 65535) {
395 mk_config_print_error_msg("Port", path
);
397 /* Set connection port to mk_pointer */
398 config
->port
.data
= mk_mem_malloc(6);
399 mk_string_itop(config
->serverport
, &config
->port
);
400 config
->port
.len
= config
->port
.len
- 2;
403 /* Number of thread workers */
404 config
->workers
= (size_t) mk_config_section_getval(section
,
407 if (config
->workers
< 1) {
408 mk_config_print_error_msg("Workers", path
);
410 /* Get each worker clients capacity based on FDs system limits */
411 config
->worker_capacity
= mk_server_worker_capacity(config
->workers
);
414 config
->timeout
= (size_t) mk_config_section_getval(section
,
415 "Timeout", MK_CONFIG_VAL_NUM
);
416 if (config
->timeout
< 1) {
417 mk_config_print_error_msg("Timeout", path
);
421 config
->keep_alive
= (size_t) mk_config_section_getval(section
,
424 if (config
->keep_alive
== VAR_ERR
) {
425 mk_config_print_error_msg("KeepAlive", path
);
428 /* MaxKeepAliveRequest */
429 config
->max_keep_alive_request
= (size_t)
430 mk_config_section_getval(section
,
431 "MaxKeepAliveRequest",
434 if (config
->max_keep_alive_request
== 0) {
435 mk_config_print_error_msg("MaxKeepAliveRequest", path
);
438 /* KeepAliveTimeout */
439 config
->keep_alive_timeout
= (size_t) mk_config_section_getval(section
,
442 if (config
->keep_alive_timeout
== 0) {
443 mk_config_print_error_msg("KeepAliveTimeout", path
);
447 config
->pid_file_path
= mk_config_section_getval(section
,
448 "PidFile", MK_CONFIG_VAL_STR
);
450 /* Home user's directory /~ */
451 config
->user_dir
= mk_config_section_getval(section
,
452 "UserDir", MK_CONFIG_VAL_STR
);
455 config
->index_files
= mk_config_section_getval(section
,
456 "Indexfile", MK_CONFIG_VAL_LIST
);
458 /* HideVersion Variable */
459 config
->hideversion
= (size_t) mk_config_section_getval(section
,
462 if (config
->hideversion
== VAR_ERR
) {
463 mk_config_print_error_msg("HideVersion", path
);
467 config
->user
= mk_config_section_getval(section
, "User", MK_CONFIG_VAL_STR
);
470 config
->resume
= (size_t) mk_config_section_getval(section
,
471 "Resume", MK_CONFIG_VAL_BOOL
);
472 if (config
->resume
== VAR_ERR
) {
473 mk_config_print_error_msg("Resume", path
);
476 /* Max Request Size */
477 config
->max_request_size
= (size_t) mk_config_section_getval(section
,
480 if (config
->max_request_size
<= 0) {
481 mk_config_print_error_msg("MaxRequestSize", path
);
484 config
->max_request_size
*= 1024;
488 config
->symlink
= (size_t) mk_config_section_getval(section
,
489 "SymLink", MK_CONFIG_VAL_BOOL
);
490 if (config
->symlink
== VAR_ERR
) {
491 mk_config_print_error_msg("SymLink", path
);
495 mk_config_read_hosts(path_conf
);
498 void mk_config_read_hosts(char *path
)
504 struct host
*p_host
, *new_host
; /* debug */
507 mk_string_build(&buf
, &len
, "%s/sites/default", path
);
508 config
->hosts
= mk_config_get_host(buf
);
512 if (!config
->hosts
) {
513 printf("\nError parsing main configuration file 'default'\n");
517 mk_string_build(&buf
, &len
, "%s/sites/", path
);
518 if (!(dir
= opendir(buf
)))
522 p_host
= config
->hosts
;
524 /* Reading content */
525 while ((ent
= readdir(dir
)) != NULL
) {
526 if (strcmp((char *) ent
->d_name
, ".") == 0)
528 if (strcmp((char *) ent
->d_name
, "..") == 0)
530 if (strcasecmp((char *) ent
->d_name
, "default") == 0)
533 mk_string_build(&file
, &len
, "%s/sites/%s", path
, ent
->d_name
);
535 new_host
= (struct host
*) mk_config_get_host(file
);
541 p_host
->next
= new_host
;
549 struct host
*mk_config_get_host(char *path
)
551 unsigned long len
= 0;
552 struct stat checkdir
;
554 struct mk_config
*cnf
;
555 struct mk_config_section
*section
;
557 /* Read configuration file */
558 cnf
= mk_config_create(path
);
560 /* Read tag 'HOST' */
561 section
= mk_config_section_get(cnf
, "HOST");
563 /* Alloc configuration node */
564 host
= mk_mem_malloc_z(sizeof(struct host
));
566 host
->file
= mk_string_dup(path
);
567 host
->servername
= mk_config_section_getval(section
, "Servername",
570 /* document root handled by a mk_pointer */
571 host
->documentroot
.data
= mk_config_section_getval(section
,
574 host
->documentroot
.len
= strlen(host
->documentroot
.data
);
576 /* validate document root configured */
577 if (stat(host
->documentroot
.data
, &checkdir
) == -1) {
578 fprintf(stderr
, "ERROR: Invalid path to DocumentRoot in %s\n\n", path
);
581 else if (!(checkdir
.st_mode
& S_IFDIR
)) {
583 "ERROR: DocumentRoot variable in %s has an invalid directory path\n\n",
588 if (!host
->servername
) {
593 /* Server Signature */
594 if (config
->hideversion
== VAR_OFF
) {
595 mk_string_build(&host
->host_signature
, &len
,
596 "Monkey/%s", VERSION
);
599 mk_string_build(&host
->host_signature
, &len
, "Monkey");
601 mk_string_build(&host
->header_host_signature
.data
,
602 &host
->header_host_signature
.len
,
603 "Server: %s", host
->host_signature
);
607 host
->access_log_path
= mk_config_section_getval(section
,
611 host
->error_log_path
= mk_config_section_getval(section
,
618 /* Imprime error de configuracion y cierra */
619 void mk_config_print_error_msg(char *variable
, char *path
)
621 fprintf(stderr
, "\nError: %s variable in %s has an invalid value.\n",
627 void mk_config_set_init_values(void)
630 config
->timeout
= 15;
631 config
->hideversion
= VAR_OFF
;
632 config
->keep_alive
= VAR_ON
;
633 config
->keep_alive_timeout
= 15;
634 config
->max_keep_alive_request
= 50;
635 config
->resume
= VAR_ON
;
636 config
->standard_port
= 80;
637 config
->listen_addr
= MK_DEFAULT_LISTEN_ADDR
;
638 config
->serverport
= 2001;
639 config
->symlink
= VAR_OFF
;
642 config
->open_flags
= O_RDONLY
| O_NONBLOCK
;
643 config
->index_files
= NULL
;
645 /* Max request buffer size allowed
646 * right now, every chunk size is 4KB (4096 bytes),
647 * so we are setting a maximum request size to 32 KB */
648 config
->max_request_size
= MK_REQUEST_CHUNK
* 8;
651 config
->plugins
= NULL
;
654 /* read main configuration from monkey.conf */
655 void mk_config_start_configure(void)
659 mk_config_set_init_values();
660 mk_config_read_files(config
->file_config
, M_DEFAULT_CONFIG_FILE
);
663 mk_mimetype_read_config();
665 /* Basic server information */
666 if (config
->hideversion
== VAR_OFF
) {
667 mk_string_build(&config
->server_software
.data
,
668 &len
, "Monkey/%s (%s)", VERSION
, OS
);
669 config
->server_software
.len
= len
;
672 mk_string_build(&config
->server_software
.data
, &len
, "Monkey Server");
673 config
->server_software
.len
= len
;
677 struct host
*mk_config_host_find(mk_pointer host
)
679 struct host
*aux_host
;
681 aux_host
= config
->hosts
;
684 if (strncasecmp(aux_host
->servername
, host
.data
, host
.len
) == 0) {
687 aux_host
= aux_host
->next
;
693 void mk_config_sanity_check()
695 /* Check O_NOATIME for current user, flag will just be used
696 * if running user is allowed to.
698 int fd
, flags
= config
->open_flags
;
701 fd
= open(config
->file_config
, flags
);
704 config
->open_flags
= flags
;