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
, "\"\t ", &last
);
75 /* Allow new entry found */
76 new = mk_mem_malloc(sizeof(struct mk_config
));
77 new->key
= mk_string_dup(key
);
79 new->val
= mk_string_dup(val
);
82 /* Link to main list */
99 void mk_config_free(struct mk_config
*cnf
)
101 struct mk_config
*prev
= 0, *target
;
105 while (target
->next
) {
107 target
= target
->next
;
120 void *mk_config_getval(struct mk_config
*cnf
, char *key
, int mode
)
127 if (strcasecmp(p
->key
, key
) == 0) {
129 case MK_CONFIG_VAL_STR
:
130 return (void *) p
->val
;
131 case MK_CONFIG_VAL_NUM
:
132 return (void *) atoi(p
->val
);
133 case MK_CONFIG_VAL_BOOL
:
134 on
= strcasecmp(p
->val
, VALUE_ON
);
135 off
= strcasecmp(p
->val
, VALUE_OFF
);
137 if (on
!= 0 && off
!= 0) {
141 return (void *) VAR_ON
;
144 return (void *) VAR_OFF
;
146 case MK_CONFIG_VAL_LIST
:
147 return mk_string_split_line(p
->val
);
157 /* Read configuration files */
158 void mk_config_read_files(char *path_conf
, char *file_conf
)
162 struct stat checkdir
;
163 struct mk_config
*cnf
;
164 struct mk_string_line
*line
, *line_val
;
166 config
->serverconf
= mk_string_dup(path_conf
);
167 config
->workers
= MK_WORKERS_DEFAULT
;
169 if (stat(config
->serverconf
, &checkdir
) == -1) {
170 fprintf(stderr
, "ERROR: Invalid path to configuration files.");
174 m_build_buffer(&path
, &len
, "%s/%s", path_conf
, file_conf
);
176 cnf
= mk_config_create(path
);
179 config
->listen_addr
= mk_config_getval(cnf
, "Listen", MK_CONFIG_VAL_STR
);
180 if (!config
->listen_addr
) {
181 config
->listen_addr
= MK_DEFAULT_LISTEN_ADDR
;
184 /* Connection port */
185 config
->serverport
= (int) mk_config_getval(cnf
,
186 "Port", MK_CONFIG_VAL_NUM
);
187 if (!config
->serverport
>= 1 && !config
->serverport
<= 65535) {
188 mk_config_print_error_msg("Port", path
);
191 /* Number of thread workers */
192 config
->workers
= (int) mk_config_getval(cnf
,
193 "Workers", MK_CONFIG_VAL_NUM
);
194 if (config
->maxclients
< 1) {
195 mk_config_print_error_msg("Workers", path
);
199 config
->timeout
= (int) mk_config_getval(cnf
,
200 "Timeout", MK_CONFIG_VAL_NUM
);
201 if (config
->timeout
< 1) {
202 mk_config_print_error_msg("Timeout", path
);
206 config
->keep_alive
= (int) mk_config_getval(cnf
,
209 if (config
->keep_alive
== VAR_ERR
) {
210 mk_config_print_error_msg("KeepAlive", path
);
213 /* MaxKeepAliveRequest */
214 config
->max_keep_alive_request
= (int) mk_config_getval(cnf
,
215 "MaxKeepAliveRequest",
217 if (config
->max_keep_alive_request
== 0) {
218 mk_config_print_error_msg("MaxKeepAliveRequest", path
);
221 /* KeepAliveTimeout */
222 config
->keep_alive_timeout
= (int) mk_config_getval(cnf
,
225 if (config
->keep_alive_timeout
== 0) {
226 mk_config_print_error_msg("KeepAliveTimeout", path
);
230 config
->pid_file_path
= mk_config_getval(cnf
,
231 "PidFile", MK_CONFIG_VAL_STR
);
233 /* Home user's directory /~ */
234 config
->user_dir
= mk_config_getval(cnf
, "UserDir", MK_CONFIG_VAL_STR
);
237 line_val
= line
= mk_config_getval(cnf
, "Indexfile", MK_CONFIG_VAL_LIST
);
238 while (line_val
!= NULL
) {
239 mk_config_add_index(line_val
->val
);
240 line_val
= line_val
->next
;
243 /* HideVersion Variable */
244 config
->hideversion
= (int) mk_config_getval(cnf
,
247 if (config
->hideversion
== VAR_ERR
) {
248 mk_config_print_error_msg("HideVersion", path
);
252 config
->user
= mk_config_getval(cnf
, "User", MK_CONFIG_VAL_STR
);
255 config
->resume
= (int) mk_config_getval(cnf
,
256 "Resume", MK_CONFIG_VAL_BOOL
);
257 if (config
->resume
== VAR_ERR
) {
258 mk_config_print_error_msg("Resume", path
);
262 config
->symlink
= (int) mk_config_getval(cnf
,
263 "SymLink", MK_CONFIG_VAL_BOOL
);
264 if (config
->symlink
== VAR_ERR
) {
265 mk_config_print_error_msg("SymLink", path
);
270 mk_config_read_hosts(path_conf
);
273 void mk_config_read_hosts(char *path
)
279 struct host
*p_host
, *new_host
; /* debug */
282 m_build_buffer(&buf
, &len
, "%s/sites/default", path
);
283 config
->hosts
= mk_config_get_host(buf
);
287 if (!config
->hosts
) {
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
) {
301 if (strcmp((char *) ent
->d_name
, ".") == 0)
303 if (strcmp((char *) ent
->d_name
, "..") == 0)
305 if (strcasecmp((char *) ent
->d_name
, "default") == 0)
308 m_build_buffer(&file
, &len
, "%s/sites/%s", path
, ent
->d_name
);
310 new_host
= (struct host
*) mk_config_get_host(file
);
316 p_host
->next
= new_host
;
326 printf("*** HOST ***\n");
327 printf(" [servername]\t\t%s\n", h->servername);
328 printf(" [documentroot]\t\t%s\n", h->documentroot);
329 printf(" [conf file]\t\t%s\n", h->file);
330 printf(" [access log]\t\t%s\n", h->access_log_path);
331 printf(" [error log]\t\t%s\n", h->error_log_path);
332 printf(" [script alias]\t\t%s %s\n", h->scriptalias[0], h->scriptalias[1]);
333 printf(" [get dir]\t\t%i\n", h->getdir);
334 printf(" [header file]\t\t%s\n", h->header_file);
335 printf(" [footer file]\t\t%s\n\n", h->footer_file);
343 struct host
*mk_config_get_host(char *path
)
345 unsigned long len
= 0;
346 struct stat checkdir
;
348 struct mk_config
*cnf
;
350 cnf
= mk_config_create(path
);
352 host
= mk_mem_malloc_z(sizeof(struct host
));
353 host
->servername
= 0;
354 host
->file
= mk_string_dup(path
);
356 host
->servername
= mk_config_getval(cnf
, "Servername", MK_CONFIG_VAL_STR
);
357 host
->documentroot
.data
= mk_config_getval(cnf
,
360 host
->documentroot
.len
= strlen(host
->documentroot
.data
);
361 if (stat(host
->documentroot
.data
, &checkdir
) == -1) {
362 fprintf(stderr
, "ERROR: Invalid path to Server_root in %s\n\n", path
);
365 else if (!(checkdir
.st_mode
& S_IFDIR
)) {
367 "ERROR: DocumentRoot variable in %s has an invalid directory path\n\n",
373 host
->access_log_path
= mk_config_getval(cnf
,
374 "AccessLog", MK_CONFIG_VAL_STR
);
376 host
->error_log_path
= mk_config_getval(cnf
,
377 "ErrorLog", MK_CONFIG_VAL_STR
);
380 host
->getdir
= (int) mk_config_getval(cnf
, "GetDir", MK_CONFIG_VAL_BOOL
);
381 if (host
->getdir
== VAR_ERR
) {
382 mk_config_print_error_msg("GetDir", path
);
385 if (!host
->servername
) {
390 /* Server Signature */
391 if (config
->hideversion
== VAR_OFF
) {
392 m_build_buffer(&host
->host_signature
, &len
,
393 "Monkey/%s", VERSION
);
396 m_build_buffer(&host
->host_signature
, &len
, "Monkey");
398 m_build_buffer(&host
->header_host_signature
.data
,
399 &host
->header_host_signature
.len
,
400 "Server: %s", host
->host_signature
);
402 if( host
->access_log_path
!= NULL
) {
403 if (pipe(host
->log_access
) < 0) {
406 fcntl(host
->log_access
[1], F_SETFL
, O_NONBLOCK
);
410 if( host
->error_log_path
!= NULL
) {
411 if (pipe(host
->log_error
) < 0) {
414 fcntl(host
->log_error
[1], F_SETFL
, O_NONBLOCK
);
423 /* Imprime error de configuracion y cierra */
424 void mk_config_print_error_msg(char *variable
, char *path
)
426 fprintf(stderr
, "\nError: %s variable in %s has an invalid value.\n",
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 */
456 config
->timeout
= 15;
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
->listen_addr
= MK_DEFAULT_LISTEN_ADDR
;
466 config
->serverport
= 2001;
467 config
->symlink
= VAR_OFF
;
470 config
->open_flags
= O_RDONLY
| O_NONBLOCK
;
473 config
->plugins
= mk_mem_malloc_z(sizeof(struct plugin_stages
));
476 /* read main configuration from monkey.conf */
477 void mk_config_start_configure(void)
481 mk_config_set_init_values();
482 mk_config_read_files(config
->file_config
, M_DEFAULT_CONFIG_FILE
);
484 /* if not index names defined, set default */
485 if (first_index
== NULL
) {
486 mk_config_add_index("index.html");
490 mk_mimetype_read_config();
492 /* Basic server information */
493 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
;
499 m_build_buffer(&config
->server_software
.data
, &len
, "Monkey Server");
500 config
->server_software
.len
= len
;
504 struct host
*mk_config_host_find(mk_pointer host
)
506 struct host
*aux_host
;
508 aux_host
= config
->hosts
;
511 if (strncasecmp(aux_host
->servername
, host
.data
, host
.len
) == 0)
514 aux_host
= aux_host
->next
;
520 void mk_config_sanity_check()
522 /* Check O_NOATIME for current user, flag will just be used
523 * if running user is allowed to.
525 int fd
, flags
= config
->open_flags
;
528 fd
= open(config
->file_config
, flags
);
531 config
->open_flags
= flags
;