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>
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
;
104 while (target
->next
) {
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
);
136 if (on
!= 0 && off
!= 0) {
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
);
178 config
->listen_addr
= mk_config_getval(cnf
, "Listen", MK_CONFIG_VAL_STR
);
179 if (!config
->listen_addr
) {
180 config
->listen_addr
= MK_DEFAULT_LISTEN_ADDR
;
183 /* Connection port */
184 config
->serverport
= (int) mk_config_getval(cnf
,
185 "Port", MK_CONFIG_VAL_NUM
);
186 if (!config
->serverport
>= 1 && !config
->serverport
<= 65535) {
187 mk_config_print_error_msg("Port", path
);
190 /* Number of thread workers */
191 config
->workers
= (int) mk_config_getval(cnf
,
192 "Workers", MK_CONFIG_VAL_NUM
);
193 if (config
->maxclients
< 1) {
194 mk_config_print_error_msg("Workers", path
);
198 config
->timeout
= (int) mk_config_getval(cnf
,
199 "Timeout", MK_CONFIG_VAL_NUM
);
200 if (config
->timeout
< 1) {
201 mk_config_print_error_msg("Timeout", path
);
205 config
->keep_alive
= (int) mk_config_getval(cnf
,
208 if (config
->keep_alive
== VAR_ERR
) {
209 mk_config_print_error_msg("KeepAlive", path
);
212 /* MaxKeepAliveRequest */
213 config
->max_keep_alive_request
= (int) mk_config_getval(cnf
,
214 "MaxKeepAliveRequest",
216 if (config
->max_keep_alive_request
== 0) {
217 mk_config_print_error_msg("MaxKeepAliveRequest", path
);
220 /* KeepAliveTimeout */
221 config
->keep_alive_timeout
= (int) mk_config_getval(cnf
,
224 if (config
->keep_alive_timeout
== 0) {
225 mk_config_print_error_msg("KeepAliveTimeout", path
);
229 config
->pid_file_path
= mk_config_getval(cnf
,
230 "PidFile", MK_CONFIG_VAL_STR
);
232 /* Home user's directory /~ */
233 config
->user_dir
= mk_config_getval(cnf
, "UserDir", MK_CONFIG_VAL_STR
);
236 line_val
= line
= mk_config_getval(cnf
, "Indexfile", MK_CONFIG_VAL_LIST
);
237 while (line_val
!= NULL
) {
238 mk_config_add_index(line_val
->val
);
239 line_val
= line_val
->next
;
242 /* HideVersion Variable */
243 config
->hideversion
= (int) mk_config_getval(cnf
,
246 if (config
->hideversion
== VAR_ERR
) {
247 mk_config_print_error_msg("HideVersion", path
);
251 config
->user
= mk_config_getval(cnf
, "User", MK_CONFIG_VAL_STR
);
254 config
->resume
= (int) mk_config_getval(cnf
,
255 "Resume", MK_CONFIG_VAL_BOOL
);
256 if (config
->resume
== VAR_ERR
) {
257 mk_config_print_error_msg("Resume", path
);
261 config
->symlink
= (int) mk_config_getval(cnf
,
262 "SymLink", MK_CONFIG_VAL_BOOL
);
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
);
286 if (!config
->hosts
) {
287 printf("\nError parsing main configuration file 'default'\n");
291 m_build_buffer(&buf
, &len
, "%s/sites/", path
);
292 if (!(dir
= opendir(buf
)))
296 p_host
= config
->hosts
;
298 /* Reading content */
299 while ((ent
= readdir(dir
)) != NULL
) {
300 if (strcmp((char *) ent
->d_name
, ".") == 0)
302 if (strcmp((char *) ent
->d_name
, "..") == 0)
304 if (strcasecmp((char *) ent
->d_name
, "default") == 0)
307 m_build_buffer(&file
, &len
, "%s/sites/%s", path
, ent
->d_name
);
309 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
)
344 unsigned long len
= 0;
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) {
361 fprintf(stderr
, "ERROR: Invalid path to Server_root in %s\n\n", path
);
364 else if (!(checkdir
.st_mode
& S_IFDIR
)) {
366 "ERROR: DocumentRoot variable in %s has an invalid directory path\n\n",
372 host
->access_log_path
= mk_config_getval(cnf
,
373 "AccessLog", MK_CONFIG_VAL_STR
);
375 host
->error_log_path
= mk_config_getval(cnf
,
376 "ErrorLog", MK_CONFIG_VAL_STR
);
379 host
->getdir
= (int) mk_config_getval(cnf
, "GetDir", MK_CONFIG_VAL_BOOL
);
380 if (host
->getdir
== VAR_ERR
) {
381 mk_config_print_error_msg("GetDir", path
);
384 if (!host
->servername
) {
389 /* Server Signature */
390 if (config
->hideversion
== VAR_OFF
) {
391 m_build_buffer(&host
->host_signature
, &len
,
392 "Monkey/%s", VERSION
);
395 m_build_buffer(&host
->host_signature
, &len
, "Monkey");
397 m_build_buffer(&host
->header_host_signature
.data
,
398 &host
->header_host_signature
.len
,
399 "Server: %s", host
->host_signature
);
401 if( host
->access_log_path
!= NULL
) {
402 if (pipe(host
->log_access
) < 0) {
405 fcntl(host
->log_access
[1], F_SETFL
, O_NONBLOCK
);
409 if( host
->error_log_path
!= NULL
) {
410 if (pipe(host
->log_error
) < 0) {
413 fcntl(host
->log_error
[1], F_SETFL
, O_NONBLOCK
);
422 /* Imprime error de configuracion y cierra */
423 void mk_config_print_error_msg(char *variable
, char *path
)
425 fprintf(stderr
, "\nError: %s variable in %s has an invalid value.\n",
431 /* Agrega distintos index.xxx */
432 void mk_config_add_index(char *indexname
)
434 struct indexfile
*new_index
= 0, *aux_index
;
436 new_index
= (struct indexfile
*) malloc(sizeof(struct indexfile
));
437 strncpy(new_index
->indexname
, indexname
, MAX_INDEX_NOMBRE
- 1);
438 new_index
->indexname
[MAX_INDEX_NOMBRE
- 1] = '\0';
439 new_index
->next
= NULL
;
441 if (first_index
== NULL
) {
442 first_index
= new_index
;
445 aux_index
= first_index
;
446 while (aux_index
->next
!= NULL
)
447 aux_index
= aux_index
->next
;
448 aux_index
->next
= new_index
;
452 void mk_config_set_init_values(void)
454 /* Valores iniciales */
455 config
->timeout
= 15;
456 config
->hideversion
= VAR_OFF
;
457 config
->keep_alive
= VAR_ON
;
458 config
->keep_alive_timeout
= 15;
459 config
->max_keep_alive_request
= 50;
460 config
->maxclients
= 150;
462 config
->resume
= VAR_ON
;
463 config
->standard_port
= 80;
464 config
->listen_addr
= MK_DEFAULT_LISTEN_ADDR
;
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
) {
493 m_build_buffer(&config
->server_software
.data
,
494 &len
, "Monkey/%s (%s)", VERSION
, OS
);
495 config
->server_software
.len
= len
;
498 m_build_buffer(&config
->server_software
.data
, &len
, "Monkey Server");
499 config
->server_software
.len
= len
;
503 struct host
*mk_config_host_find(mk_pointer host
)
505 struct host
*aux_host
;
507 aux_host
= config
->hosts
;
510 if (strncasecmp(aux_host
->servername
, host
.data
, host
.len
) == 0)
513 aux_host
= aux_host
->next
;
519 void mk_config_sanity_check()
521 /* Check O_NOATIME for current user, flag will just be used
522 * if running user is allowed to.
524 int fd
, flags
= config
->open_flags
;
527 fd
= open(config
->file_config
, flags
);
530 config
->open_flags
= flags
;