Annotation of embedaddon/lighttpd/src/configfile.c, revision 1.1.1.3

1.1.1.3 ! misho       1: #include "first.h"
        !             2: 
1.1       misho       3: #include "server.h"
                      4: #include "log.h"
                      5: #include "stream.h"
                      6: #include "plugin.h"
                      7: 
                      8: #include "configparser.h"
                      9: #include "configfile.h"
                     10: #include "proc_open.h"
1.1.1.3 ! misho      11: #include "request.h"
        !            12: #include "version.h"
1.1       misho      13: 
                     14: #include <sys/stat.h>
                     15: 
                     16: #include <stdlib.h>
                     17: #include <fcntl.h>
                     18: #include <unistd.h>
                     19: #include <errno.h>
                     20: #include <string.h>
                     21: #include <stdio.h>
                     22: #include <ctype.h>
                     23: #include <limits.h>
                     24: #include <assert.h>
1.1.1.3 ! misho      25: #include <glob.h>
1.1       misho      26: 
                     27: 
                     28: static int config_insert(server *srv) {
                     29:        size_t i;
                     30:        int ret = 0;
                     31:        buffer *stat_cache_string;
                     32: 
                     33:        config_values_t cv[] = {
1.1.1.3 ! misho      34:                { "server.bind",                       NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 0 */
        !            35:                { "server.errorlog",                   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 1 */
        !            36:                { "server.errorfile-prefix",           NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 2 */
        !            37:                { "server.chroot",                     NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 3 */
        !            38:                { "server.username",                   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 4 */
        !            39:                { "server.groupname",                  NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 5 */
        !            40:                { "server.port",                       NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER     }, /* 6 */
        !            41:                { "server.tag",                        NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 7 */
        !            42:                { "server.use-ipv6",                   NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
        !            43:                { "server.modules",                    NULL, T_CONFIG_ARRAY,   T_CONFIG_SCOPE_SERVER     }, /* 9 */
        !            44: 
        !            45:                { "server.event-handler",              NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 10 */
        !            46:                { "server.pid-file",                   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 11 */
        !            47:                { "server.max-request-size",           NULL, T_CONFIG_INT,     T_CONFIG_SCOPE_SERVER     }, /* 12 */
        !            48:                { "server.max-worker",                 NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER     }, /* 13 */
        !            49:                { "server.document-root",              NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 14 */
        !            50:                { "server.force-lowercase-filenames",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
        !            51:                { "debug.log-condition-handling",      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
        !            52:                { "server.max-keep-alive-requests",    NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 17 */
        !            53:                { "server.name",                       NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 18 */
        !            54:                { "server.max-keep-alive-idle",        NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 19 */
        !            55: 
        !            56:                { "server.max-read-idle",              NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 20 */
        !            57:                { "server.max-write-idle",             NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 21 */
        !            58:                { "server.error-handler",              NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 22 */
        !            59:                { "server.max-fds",                    NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER     }, /* 23 */
1.1       misho      60: #ifdef HAVE_LSTAT
1.1.1.3 ! misho      61:                { "server.follow-symlink",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 24 */
1.1       misho      62: #else
                     63:                { "server.follow-symlink",
1.1.1.3 ! misho      64:                        "Your system lacks lstat(). We can not differ symlinks from files."
        !            65:                        "Please remove server.follow-symlinks from your config.",
        !            66:                        T_CONFIG_UNSUPPORTED, T_CONFIG_SCOPE_UNSET },
        !            67: #endif
        !            68:                { "server.kbytes-per-second",          NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 25 */
        !            69:                { "connection.kbytes-per-second",      NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 26 */
        !            70:                { "mimetype.use-xattr",                NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
        !            71:                { "mimetype.assign",                   NULL, T_CONFIG_ARRAY,   T_CONFIG_SCOPE_CONNECTION }, /* 28 */
        !            72:                { "ssl.pemfile",                       NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 29 */
        !            73: 
        !            74:                { "ssl.engine",                        NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 30 */
        !            75:                { "debug.log-file-not-found",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 31 */
        !            76:                { "debug.log-request-handling",        NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 32 */
        !            77:                { "debug.log-response-header",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 33 */
        !            78:                { "debug.log-request-header",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 34 */
        !            79:                { "debug.log-ssl-noise",               NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 35 */
        !            80:                { "server.protocol-http11",            NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 36 */
        !            81:                { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER     }, /* 37 */
        !            82:                { "debug.log-state-handling",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER     }, /* 38 */
        !            83:                { "ssl.ca-file",                       NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 39 */
        !            84: 
        !            85:                { "server.errorlog-use-syslog",        NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER     }, /* 40 */
        !            86:                { "server.range-requests",             NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
        !            87:                { "server.stat-cache-engine",          NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 42 */
        !            88:                { "server.max-connections",            NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_SERVER     }, /* 43 */
        !            89:                { "server.network-backend",            NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 44 */
        !            90:                { "server.upload-dirs",                NULL, T_CONFIG_ARRAY,   T_CONFIG_SCOPE_SERVER     }, /* 45 */
        !            91:                { "server.core-files",                 NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER     }, /* 46 */
        !            92:                { "ssl.cipher-list",                   NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 47 */
        !            93:                { "ssl.use-sslv2",                     NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 48 */
        !            94:                { "etag.use-inode",                    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 49 */
        !            95: 
        !            96:                { "etag.use-mtime",                    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 50 */
        !            97:                { "etag.use-size",                     NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 51 */
        !            98:                { "server.reject-expect-100-with-417", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER     }, /* 52 */
        !            99:                { "debug.log-timeouts",                NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 53 */
        !           100:                { "server.defer-accept",               NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 54 */
        !           101:                { "server.breakagelog",                NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 55 */
        !           102:                { "ssl.verifyclient.activate",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 56 */
        !           103:                { "ssl.verifyclient.enforce",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 57 */
        !           104:                { "ssl.verifyclient.depth",            NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 58 */
        !           105:                { "ssl.verifyclient.username",         NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 59 */
        !           106: 
        !           107:                { "ssl.verifyclient.exportcert",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 60 */
        !           108:                { "server.set-v6only",                 NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 61 */
        !           109:                { "ssl.use-sslv3",                     NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 62 */
        !           110:                { "ssl.dh-file",                       NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 63 */
        !           111:                { "ssl.ec-curve",                      NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 64 */
        !           112:                { "ssl.disable-client-renegotiation",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 65 */
        !           113:                { "ssl.honor-cipher-order",            NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 66 */
        !           114:                { "ssl.empty-fragments",               NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 67 */
        !           115:                { "server.upload-temp-file-size",      NULL, T_CONFIG_INT,     T_CONFIG_SCOPE_SERVER     }, /* 68 */
        !           116:                { "mimetype.xattr-name",               NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_SERVER     }, /* 69 */
        !           117:                { "server.listen-backlog",             NULL, T_CONFIG_INT,     T_CONFIG_SCOPE_CONNECTION }, /* 70 */
        !           118:                { "server.error-handler-404",          NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 71 */
        !           119:                { "server.http-parseopt-header-strict",NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER     }, /* 72 */
        !           120:                { "server.http-parseopt-host-strict",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER     }, /* 73 */
        !           121:                { "server.http-parseopt-host-normalize",NULL,T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER     }, /* 74 */
        !           122:                { "server.bsd-accept-filter",          NULL, T_CONFIG_STRING,  T_CONFIG_SCOPE_CONNECTION }, /* 75 */
        !           123:                { "server.stream-request-body",        NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 76 */
        !           124:                { "server.stream-response-body",       NULL, T_CONFIG_SHORT,   T_CONFIG_SCOPE_CONNECTION }, /* 77 */
1.1       misho     125: 
1.1.1.3 ! misho     126:                { NULL,                                NULL, T_CONFIG_UNSET,   T_CONFIG_SCOPE_UNSET      }
1.1       misho     127:        };
                    128: 
1.1.1.3 ! misho     129:        /* all T_CONFIG_SCOPE_SERVER options */
1.1       misho     130:        cv[0].destination = srv->srvconf.bindhost;
                    131:        cv[1].destination = srv->srvconf.errorlog_file;
                    132:        cv[3].destination = srv->srvconf.changeroot;
                    133:        cv[4].destination = srv->srvconf.username;
                    134:        cv[5].destination = srv->srvconf.groupname;
                    135:        cv[6].destination = &(srv->srvconf.port);
                    136:        cv[9].destination = srv->srvconf.modules;
1.1.1.3 ! misho     137: 
1.1       misho     138:        cv[10].destination = srv->srvconf.event_handler;
                    139:        cv[11].destination = srv->srvconf.pid_file;
                    140:        cv[13].destination = &(srv->srvconf.max_worker);
1.1.1.3 ! misho     141: 
1.1       misho     142:        cv[23].destination = &(srv->srvconf.max_fds);
1.1.1.3 ! misho     143: 
1.1       misho     144:        cv[37].destination = &(srv->srvconf.log_request_header_on_error);
                    145:        cv[38].destination = &(srv->srvconf.log_state_handling);
                    146: 
                    147:        cv[40].destination = &(srv->srvconf.errorlog_use_syslog);
                    148:        stat_cache_string = buffer_init();
                    149:        cv[42].destination = stat_cache_string;
1.1.1.3 ! misho     150:        cv[43].destination = &(srv->srvconf.max_conns);
1.1       misho     151:        cv[44].destination = srv->srvconf.network_backend;
                    152:        cv[45].destination = srv->srvconf.upload_tempdirs;
                    153:        cv[46].destination = &(srv->srvconf.enable_cores);
                    154: 
                    155:        cv[52].destination = &(srv->srvconf.reject_expect_100_with_417);
                    156:        cv[55].destination = srv->srvconf.breakagelog_file;
                    157: 
1.1.1.3 ! misho     158:        cv[68].destination = &(srv->srvconf.upload_temp_file_size);
        !           159:        cv[69].destination = srv->srvconf.xattr_name;
        !           160:        cv[72].destination = &(srv->srvconf.http_header_strict);
        !           161:        cv[73].destination = &(srv->srvconf.http_host_strict);
        !           162:        cv[74].destination = &(srv->srvconf.http_host_normalize);
        !           163: 
1.1       misho     164:        srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
                    165: 
1.1.1.2   misho     166:        force_assert(srv->config_storage);
1.1       misho     167: 
                    168:        for (i = 0; i < srv->config_context->used; i++) {
1.1.1.3 ! misho     169:                data_config const* config = (data_config const*)srv->config_context->data[i];
1.1       misho     170:                specific_config *s;
                    171: 
                    172:                s = calloc(1, sizeof(specific_config));
1.1.1.2   misho     173:                force_assert(s);
1.1       misho     174:                s->document_root = buffer_init();
                    175:                s->mimetypes     = array_init();
                    176:                s->server_name   = buffer_init();
                    177:                s->ssl_pemfile   = buffer_init();
                    178:                s->ssl_ca_file   = buffer_init();
                    179:                s->error_handler = buffer_init();
1.1.1.3 ! misho     180:                s->error_handler_404 = buffer_init();
        !           181:                s->server_tag    = buffer_init_string(PACKAGE_DESC);
1.1       misho     182:                s->ssl_cipher_list = buffer_init();
                    183:                s->ssl_dh_file   = buffer_init();
                    184:                s->ssl_ec_curve  = buffer_init();
                    185:                s->errorfile_prefix = buffer_init();
1.1.1.3 ! misho     186:              #if defined(__FreeBSD__) || defined(__NetBSD__) \
        !           187:               || defined(__OpenBSD__) || defined(__DragonflyBSD__)
        !           188:                s->bsd_accept_filter = (i == 0)
        !           189:                  ? buffer_init()
        !           190:                  : buffer_init_buffer(srv->config_storage[0]->bsd_accept_filter);
        !           191:              #endif
1.1       misho     192:                s->max_keep_alive_requests = 16;
                    193:                s->max_keep_alive_idle = 5;
                    194:                s->max_read_idle = 60;
                    195:                s->max_write_idle = 360;
1.1.1.3 ! misho     196:                s->max_request_size = 0;
1.1       misho     197:                s->use_xattr     = 0;
                    198:                s->ssl_enabled   = 0;
                    199:                s->ssl_honor_cipher_order = 1;
                    200:                s->ssl_empty_fragments = 0;
                    201:                s->ssl_use_sslv2 = 0;
1.1.1.3 ! misho     202:                s->ssl_use_sslv3 = 0;
        !           203:                s->use_ipv6      = (i == 0) ? 0 : srv->config_storage[0]->use_ipv6;
        !           204:                s->set_v6only    = (i == 0) ? 1 : srv->config_storage[0]->set_v6only;
        !           205:                s->defer_accept  = (i == 0) ? 0 : srv->config_storage[0]->defer_accept;
1.1       misho     206: #ifdef HAVE_LSTAT
                    207:                s->follow_symlink = 1;
                    208: #endif
                    209:                s->kbytes_per_second = 0;
                    210:                s->allow_http11  = 1;
                    211:                s->etag_use_inode = 1;
                    212:                s->etag_use_mtime = 1;
                    213:                s->etag_use_size  = 1;
                    214:                s->range_requests = 1;
                    215:                s->force_lowercase_filenames = (i == 0) ? 2 : 0; /* we wan't to detect later if user changed this for global section */
                    216:                s->global_kbytes_per_second = 0;
                    217:                s->global_bytes_per_second_cnt = 0;
                    218:                s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
                    219:                s->ssl_verifyclient = 0;
                    220:                s->ssl_verifyclient_enforce = 1;
                    221:                s->ssl_verifyclient_username = buffer_init();
                    222:                s->ssl_verifyclient_depth = 9;
                    223:                s->ssl_verifyclient_export_cert = 0;
                    224:                s->ssl_disable_client_renegotiation = 1;
1.1.1.3 ! misho     225:                s->listen_backlog = (0 == i ? 1024 : srv->config_storage[0]->listen_backlog);
        !           226:                s->stream_request_body = 0;
        !           227:                s->stream_response_body = 0;
1.1       misho     228: 
1.1.1.3 ! misho     229:                /* all T_CONFIG_SCOPE_CONNECTION options */
1.1       misho     230:                cv[2].destination = s->errorfile_prefix;
                    231:                cv[7].destination = s->server_tag;
                    232:                cv[8].destination = &(s->use_ipv6);
                    233: 
1.1.1.3 ! misho     234:                cv[12].destination = &(s->max_request_size);
1.1       misho     235:                cv[14].destination = s->document_root;
                    236:                cv[15].destination = &(s->force_lowercase_filenames);
                    237:                cv[16].destination = &(s->log_condition_handling);
                    238:                cv[17].destination = &(s->max_keep_alive_requests);
                    239:                cv[18].destination = s->server_name;
                    240:                cv[19].destination = &(s->max_keep_alive_idle);
1.1.1.3 ! misho     241: 
1.1       misho     242:                cv[20].destination = &(s->max_read_idle);
                    243:                cv[21].destination = &(s->max_write_idle);
                    244:                cv[22].destination = s->error_handler;
                    245: #ifdef HAVE_LSTAT
                    246:                cv[24].destination = &(s->follow_symlink);
                    247: #endif
                    248:                cv[25].destination = &(s->global_kbytes_per_second);
                    249:                cv[26].destination = &(s->kbytes_per_second);
                    250:                cv[27].destination = &(s->use_xattr);
                    251:                cv[28].destination = s->mimetypes;
                    252:                cv[29].destination = s->ssl_pemfile;
                    253: 
1.1.1.3 ! misho     254:                cv[30].destination = &(s->ssl_enabled);
1.1       misho     255:                cv[31].destination = &(s->log_file_not_found);
                    256:                cv[32].destination = &(s->log_request_handling);
                    257:                cv[33].destination = &(s->log_response_header);
                    258:                cv[34].destination = &(s->log_request_header);
                    259:                cv[35].destination = &(s->log_ssl_noise);
                    260:                cv[36].destination = &(s->allow_http11);
                    261:                cv[39].destination = s->ssl_ca_file;
                    262: 
1.1.1.3 ! misho     263:                cv[41].destination = &(s->range_requests);
1.1       misho     264:                cv[47].destination = s->ssl_cipher_list;
                    265:                cv[48].destination = &(s->ssl_use_sslv2);
                    266:                cv[49].destination = &(s->etag_use_inode);
1.1.1.3 ! misho     267: 
1.1       misho     268:                cv[50].destination = &(s->etag_use_mtime);
                    269:                cv[51].destination = &(s->etag_use_size);
1.1.1.3 ! misho     270:                cv[53].destination = &(s->log_timeouts);
        !           271:                cv[54].destination = &(s->defer_accept);
1.1       misho     272:                cv[56].destination = &(s->ssl_verifyclient);
                    273:                cv[57].destination = &(s->ssl_verifyclient_enforce);
                    274:                cv[58].destination = &(s->ssl_verifyclient_depth);
                    275:                cv[59].destination = s->ssl_verifyclient_username;
1.1.1.3 ! misho     276: 
1.1       misho     277:                cv[60].destination = &(s->ssl_verifyclient_export_cert);
1.1.1.3 ! misho     278:                cv[61].destination = &(s->set_v6only);
        !           279:                cv[62].destination = &(s->ssl_use_sslv3);
        !           280:                cv[63].destination = s->ssl_dh_file;
        !           281:                cv[64].destination = s->ssl_ec_curve;
1.1       misho     282:                cv[65].destination = &(s->ssl_disable_client_renegotiation);
1.1.1.3 ! misho     283:                cv[66].destination = &(s->ssl_honor_cipher_order);
        !           284:                cv[67].destination = &(s->ssl_empty_fragments);
        !           285:                cv[70].destination = &(s->listen_backlog);
        !           286:                cv[71].destination = s->error_handler_404;
        !           287:              #if defined(__FreeBSD__) || defined(__NetBSD__) \
        !           288:               || defined(__OpenBSD__) || defined(__DragonflyBSD__)
        !           289:                cv[75].destination = s->bsd_accept_filter;
        !           290:              #endif
        !           291:                cv[76].destination = &(s->stream_request_body);
        !           292:                cv[77].destination = &(s->stream_response_body);
1.1       misho     293: 
                    294:                srv->config_storage[i] = s;
                    295: 
1.1.1.3 ! misho     296:                if (0 != (ret = config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION))) {
1.1       misho     297:                        break;
                    298:                }
1.1.1.3 ! misho     299: 
        !           300:                if (s->stream_request_body & FDEVENT_STREAM_REQUEST_BUFMIN) {
        !           301:                        s->stream_request_body |= FDEVENT_STREAM_REQUEST;
        !           302:                }
        !           303:                if (s->stream_response_body & FDEVENT_STREAM_RESPONSE_BUFMIN) {
        !           304:                        s->stream_response_body |= FDEVENT_STREAM_RESPONSE;
        !           305:                }
        !           306:        }
        !           307: 
        !           308:        {
        !           309:                specific_config *s = srv->config_storage[0];
        !           310:                s->http_parseopts= /*(global, but stored in con->conf.http_parseopts)*/
        !           311:                   (srv->srvconf.http_header_strict  ?(HTTP_PARSEOPT_HEADER_STRICT) :0)
        !           312:                  |(srv->srvconf.http_host_strict    ?(HTTP_PARSEOPT_HOST_STRICT
        !           313:                                                      |HTTP_PARSEOPT_HOST_NORMALIZE):0)
        !           314:                  |(srv->srvconf.http_host_normalize ?(HTTP_PARSEOPT_HOST_NORMALIZE):0);
1.1       misho     315:        }
                    316: 
1.1.1.3 ! misho     317:        if (buffer_string_is_empty(stat_cache_string)) {
1.1       misho     318:                srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
                    319:        } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
                    320:                srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
                    321: #ifdef HAVE_FAM_H
                    322:        } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("fam"))) {
                    323:                srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_FAM;
                    324: #endif
                    325:        } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
                    326:                srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
                    327:        } else {
                    328:                log_error_write(srv, __FILE__, __LINE__, "sb",
                    329:                                "server.stat-cache-engine can be one of \"disable\", \"simple\","
                    330: #ifdef HAVE_FAM_H
                    331:                                " \"fam\","
                    332: #endif
                    333:                                " but not:", stat_cache_string);
                    334:                ret = HANDLER_ERROR;
                    335:        }
                    336: 
                    337:        buffer_free(stat_cache_string);
                    338: 
1.1.1.3 ! misho     339:        {
        !           340:                data_string *ds;
        !           341:                int prepend_mod_indexfile = 1;
        !           342:                int append_mod_dirlisting = 1;
        !           343:                int append_mod_staticfile = 1;
        !           344: 
        !           345:                /* prepend default modules */
        !           346:                for (i = 0; i < srv->srvconf.modules->used; i++) {
        !           347:                        ds = (data_string *)srv->srvconf.modules->data[i];
        !           348: 
        !           349:                        if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_indexfile"))) {
        !           350:                                prepend_mod_indexfile = 0;
        !           351:                        }
        !           352: 
        !           353:                        if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_staticfile"))) {
        !           354:                                append_mod_staticfile = 0;
        !           355:                        }
        !           356: 
        !           357:                        if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_dirlisting"))) {
        !           358:                                append_mod_dirlisting = 0;
        !           359:                        }
        !           360: 
        !           361:                        if (0 == prepend_mod_indexfile &&
        !           362:                            0 == append_mod_dirlisting &&
        !           363:                            0 == append_mod_staticfile) {
        !           364:                                break;
        !           365:                        }
        !           366:                }
        !           367: 
        !           368:                if (prepend_mod_indexfile) {
        !           369:                        /* mod_indexfile has to be loaded before mod_fastcgi and friends */
        !           370:                        array *modules = array_init();
        !           371: 
        !           372:                        ds = data_string_init();
        !           373:                        buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile"));
        !           374:                        array_insert_unique(modules, (data_unset *)ds);
        !           375: 
        !           376:                        for (i = 0; i < srv->srvconf.modules->used; i++) {
        !           377:                                data_unset *du = srv->srvconf.modules->data[i];
        !           378:                                array_insert_unique(modules, du->copy(du));
        !           379:                        }
        !           380: 
        !           381:                        array_free(srv->srvconf.modules);
        !           382:                        srv->srvconf.modules = modules;
        !           383:                }
        !           384: 
        !           385:                /* append default modules */
        !           386:                if (append_mod_dirlisting) {
        !           387:                        ds = data_string_init();
        !           388:                        buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting"));
        !           389:                        array_insert_unique(srv->srvconf.modules, (data_unset *)ds);
        !           390:                }
        !           391: 
        !           392:                if (append_mod_staticfile) {
        !           393:                        ds = data_string_init();
        !           394:                        buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile"));
        !           395:                        array_insert_unique(srv->srvconf.modules, (data_unset *)ds);
        !           396:                }
        !           397:        }
        !           398: 
1.1       misho     399:        return ret;
                    400: 
                    401: }
                    402: 
                    403: 
                    404: #define PATCH(x) con->conf.x = s->x
                    405: int config_setup_connection(server *srv, connection *con) {
                    406:        specific_config *s = srv->config_storage[0];
                    407: 
1.1.1.3 ! misho     408:        PATCH(http_parseopts);
        !           409: 
1.1       misho     410:        PATCH(allow_http11);
                    411:        PATCH(mimetypes);
                    412:        PATCH(document_root);
1.1.1.3 ! misho     413:        PATCH(high_precision_timestamps);
1.1       misho     414:        PATCH(max_keep_alive_requests);
                    415:        PATCH(max_keep_alive_idle);
                    416:        PATCH(max_read_idle);
                    417:        PATCH(max_write_idle);
1.1.1.3 ! misho     418:        PATCH(max_request_size);
1.1       misho     419:        PATCH(use_xattr);
                    420:        PATCH(error_handler);
1.1.1.3 ! misho     421:        PATCH(error_handler_404);
1.1       misho     422:        PATCH(errorfile_prefix);
                    423: #ifdef HAVE_LSTAT
                    424:        PATCH(follow_symlink);
                    425: #endif
                    426:        PATCH(server_tag);
                    427:        PATCH(kbytes_per_second);
                    428:        PATCH(global_kbytes_per_second);
                    429:        PATCH(global_bytes_per_second_cnt);
                    430: 
                    431:        con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
1.1.1.3 ! misho     432:        buffer_copy_buffer(con->server_name, s->server_name);
1.1       misho     433: 
                    434:        PATCH(log_request_header);
                    435:        PATCH(log_response_header);
                    436:        PATCH(log_request_handling);
                    437:        PATCH(log_condition_handling);
                    438:        PATCH(log_file_not_found);
                    439:        PATCH(log_ssl_noise);
                    440:        PATCH(log_timeouts);
                    441: 
                    442:        PATCH(range_requests);
                    443:        PATCH(force_lowercase_filenames);
1.1.1.3 ! misho     444:        /*PATCH(listen_backlog);*//*(not necessary; used only at startup)*/
        !           445:        PATCH(stream_request_body);
        !           446:        PATCH(stream_response_body);
        !           447: 
1.1       misho     448:        PATCH(ssl_enabled);
                    449: 
                    450:        PATCH(ssl_pemfile);
                    451: #ifdef USE_OPENSSL
1.1.1.2   misho     452:        PATCH(ssl_pemfile_x509);
                    453:        PATCH(ssl_pemfile_pkey);
1.1       misho     454: #endif
                    455:        PATCH(ssl_ca_file);
1.1.1.2   misho     456: #ifdef USE_OPENSSL
                    457:        PATCH(ssl_ca_file_cert_names);
                    458: #endif
1.1       misho     459:        PATCH(ssl_cipher_list);
                    460:        PATCH(ssl_dh_file);
                    461:        PATCH(ssl_ec_curve);
                    462:        PATCH(ssl_honor_cipher_order);
                    463:        PATCH(ssl_empty_fragments);
                    464:        PATCH(ssl_use_sslv2);
                    465:        PATCH(ssl_use_sslv3);
                    466:        PATCH(etag_use_inode);
                    467:        PATCH(etag_use_mtime);
                    468:        PATCH(etag_use_size);
                    469: 
                    470:        PATCH(ssl_verifyclient);
                    471:        PATCH(ssl_verifyclient_enforce);
                    472:        PATCH(ssl_verifyclient_depth);
                    473:        PATCH(ssl_verifyclient_username);
                    474:        PATCH(ssl_verifyclient_export_cert);
                    475:        PATCH(ssl_disable_client_renegotiation);
                    476: 
                    477:        return 0;
                    478: }
                    479: 
1.1.1.3 ! misho     480: int config_patch_connection(server *srv, connection *con) {
1.1       misho     481:        size_t i, j;
                    482: 
                    483:        /* skip the first, the global context */
                    484:        for (i = 1; i < srv->config_context->used; i++) {
                    485:                data_config *dc = (data_config *)srv->config_context->data[i];
                    486:                specific_config *s = srv->config_storage[i];
                    487: 
                    488:                /* condition didn't match */
                    489:                if (!config_check_cond(srv, con, dc)) continue;
                    490: 
                    491:                /* merge config */
                    492:                for (j = 0; j < dc->value->used; j++) {
                    493:                        data_unset *du = dc->value->data[j];
                    494: 
                    495:                        if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
                    496:                                PATCH(document_root);
                    497:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
                    498:                                PATCH(range_requests);
1.1.1.3 ! misho     499:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.error-handler"))) {
1.1       misho     500:                                PATCH(error_handler);
1.1.1.3 ! misho     501:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.error-handler-404"))) {
        !           502:                                PATCH(error_handler_404);
1.1       misho     503:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.errorfile-prefix"))) {
                    504:                                PATCH(errorfile_prefix);
                    505:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.assign"))) {
                    506:                                PATCH(mimetypes);
                    507:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-requests"))) {
                    508:                                PATCH(max_keep_alive_requests);
                    509:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-idle"))) {
                    510:                                PATCH(max_keep_alive_idle);
                    511:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-write-idle"))) {
                    512:                                PATCH(max_write_idle);
                    513:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-read-idle"))) {
                    514:                                PATCH(max_read_idle);
1.1.1.3 ! misho     515:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-request-size"))) {
        !           516:                                PATCH(max_request_size);
1.1       misho     517:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.use-xattr"))) {
                    518:                                PATCH(use_xattr);
                    519:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-inode"))) {
                    520:                                PATCH(etag_use_inode);
                    521:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-mtime"))) {
                    522:                                PATCH(etag_use_mtime);
                    523:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-size"))) {
                    524:                                PATCH(etag_use_size);
                    525:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) {
                    526:                                PATCH(ssl_pemfile);
                    527: #ifdef USE_OPENSSL
1.1.1.2   misho     528:                                PATCH(ssl_pemfile_x509);
                    529:                                PATCH(ssl_pemfile_pkey);
1.1       misho     530: #endif
                    531:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) {
                    532:                                PATCH(ssl_ca_file);
1.1.1.2   misho     533: #ifdef USE_OPENSSL
                    534:                                PATCH(ssl_ca_file_cert_names);
                    535: #endif
1.1       misho     536:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.honor-cipher-order"))) {
                    537:                                PATCH(ssl_honor_cipher_order);
                    538:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.empty-fragments"))) {
                    539:                                PATCH(ssl_empty_fragments);
                    540:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) {
                    541:                                PATCH(ssl_use_sslv2);
                    542:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv3"))) {
                    543:                                PATCH(ssl_use_sslv3);
                    544:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) {
                    545:                                PATCH(ssl_cipher_list);
                    546:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) {
                    547:                                PATCH(ssl_enabled);
                    548:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.dh-file"))) {
                    549:                                PATCH(ssl_dh_file);
                    550:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ec-curve"))) {
                    551:                                PATCH(ssl_ec_curve);
                    552: #ifdef HAVE_LSTAT
                    553:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.follow-symlink"))) {
                    554:                                PATCH(follow_symlink);
                    555: #endif
                    556:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.name"))) {
1.1.1.3 ! misho     557:                                buffer_copy_buffer(con->server_name, s->server_name);
1.1       misho     558:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.tag"))) {
                    559:                                PATCH(server_tag);
1.1.1.3 ! misho     560:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.stream-request-body"))) {
        !           561:                                PATCH(stream_request_body);
        !           562:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.stream-response-body"))) {
        !           563:                                PATCH(stream_response_body);
1.1       misho     564:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("connection.kbytes-per-second"))) {
                    565:                                PATCH(kbytes_per_second);
                    566:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-handling"))) {
                    567:                                PATCH(log_request_handling);
                    568:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-header"))) {
                    569:                                PATCH(log_request_header);
                    570:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-response-header"))) {
                    571:                                PATCH(log_response_header);
                    572:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
                    573:                                PATCH(log_condition_handling);
                    574:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
                    575:                                PATCH(log_file_not_found);
                    576:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-ssl-noise"))) {
                    577:                                PATCH(log_ssl_noise);
                    578:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-timeouts"))) {
                    579:                                PATCH(log_timeouts);
                    580:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
                    581:                                PATCH(allow_http11);
                    582:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
                    583:                                PATCH(force_lowercase_filenames);
1.1.1.3 ! misho     584:                      #if 0 /*(not necessary; used only at startup)*/
        !           585:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.listen-backlog"))) {
        !           586:                                PATCH(listen_backlog);
        !           587:                      #endif
1.1       misho     588:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
                    589:                                PATCH(global_kbytes_per_second);
                    590:                                PATCH(global_bytes_per_second_cnt);
                    591:                                con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
                    592:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.activate"))) {
                    593:                                PATCH(ssl_verifyclient);
                    594:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.enforce"))) {
                    595:                                PATCH(ssl_verifyclient_enforce);
                    596:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.depth"))) {
                    597:                                PATCH(ssl_verifyclient_depth);
                    598:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) {
                    599:                                PATCH(ssl_verifyclient_username);
                    600:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) {
                    601:                                PATCH(ssl_verifyclient_export_cert);
                    602:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.disable-client-renegotiation"))) {
                    603:                                PATCH(ssl_disable_client_renegotiation);
                    604:                        }
                    605:                }
                    606:        }
                    607: 
                    608:                con->etag_flags = (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) |
                    609:                                  (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) |
                    610:                                  (con->conf.etag_use_size  ? ETAG_USE_SIZE  : 0);
                    611: 
                    612:        return 0;
                    613: }
                    614: #undef PATCH
                    615: 
                    616: typedef struct {
                    617:        int foo;
                    618:        int bar;
                    619: 
                    620:        const buffer *source;
                    621:        const char *input;
                    622:        size_t offset;
                    623:        size_t size;
                    624: 
                    625:        int line_pos;
                    626:        int line;
                    627: 
                    628:        int in_key;
                    629:        int in_brace;
                    630:        int in_cond;
                    631: } tokenizer_t;
                    632: 
                    633: #if 0
                    634: static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const char *fn) {
1.1.1.3 ! misho     635:        if (buffer_string_is_empty(basedir) ||
1.1       misho     636:                        (fn[0] == '/' || fn[0] == '\\') ||
                    637:                        (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
                    638:                t->file = buffer_init_string(fn);
                    639:        } else {
                    640:                t->file = buffer_init_buffer(basedir);
                    641:                buffer_append_string(t->file, fn);
                    642:        }
                    643: 
                    644:        if (0 != stream_open(&(t->s), t->file)) {
                    645:                log_error_write(srv, __FILE__, __LINE__, "sbss",
                    646:                                "opening configfile ", t->file, "failed:", strerror(errno));
                    647:                buffer_free(t->file);
                    648:                return -1;
                    649:        }
                    650: 
                    651:        t->input = t->s.start;
                    652:        t->offset = 0;
                    653:        t->size = t->s.size;
                    654:        t->line = 1;
                    655:        t->line_pos = 1;
                    656: 
                    657:        t->in_key = 1;
                    658:        t->in_brace = 0;
                    659:        t->in_cond = 0;
                    660:        return 0;
                    661: }
                    662: 
                    663: static int tokenizer_close(server *srv, tokenizer_t *t) {
                    664:        UNUSED(srv);
                    665: 
                    666:        buffer_free(t->file);
                    667:        return stream_close(&(t->s));
                    668: }
                    669: #endif
                    670: static int config_skip_newline(tokenizer_t *t) {
                    671:        int skipped = 1;
1.1.1.2   misho     672:        force_assert(t->input[t->offset] == '\r' || t->input[t->offset] == '\n');
1.1       misho     673:        if (t->input[t->offset] == '\r' && t->input[t->offset + 1] == '\n') {
                    674:                skipped ++;
                    675:                t->offset ++;
                    676:        }
                    677:        t->offset ++;
                    678:        return skipped;
                    679: }
                    680: 
                    681: static int config_skip_comment(tokenizer_t *t) {
                    682:        int i;
1.1.1.2   misho     683:        force_assert(t->input[t->offset] == '#');
1.1       misho     684:        for (i = 1; t->input[t->offset + i] &&
                    685:             (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
                    686:             i++);
                    687:        t->offset += i;
                    688:        return i;
                    689: }
                    690: 
                    691: static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
                    692:        int tid = 0;
                    693:        size_t i;
                    694: 
                    695:        for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
                    696:                char c = t->input[t->offset];
                    697:                const char *start = NULL;
                    698: 
                    699:                switch (c) {
                    700:                case '=':
                    701:                        if (t->in_brace) {
                    702:                                if (t->input[t->offset + 1] == '>') {
                    703:                                        t->offset += 2;
                    704: 
                    705:                                        buffer_copy_string_len(token, CONST_STR_LEN("=>"));
                    706: 
                    707:                                        tid = TK_ARRAY_ASSIGN;
                    708:                                } else {
                    709:                                        log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
                    710:                                                        "source:", t->source,
                    711:                                                        "line:", t->line, "pos:", t->line_pos,
                    712:                                                        "use => for assignments in arrays");
                    713:                                        return -1;
                    714:                                }
                    715:                        } else if (t->in_cond) {
                    716:                                if (t->input[t->offset + 1] == '=') {
                    717:                                        t->offset += 2;
                    718: 
                    719:                                        buffer_copy_string_len(token, CONST_STR_LEN("=="));
                    720: 
                    721:                                        tid = TK_EQ;
                    722:                                } else if (t->input[t->offset + 1] == '~') {
                    723:                                        t->offset += 2;
                    724: 
                    725:                                        buffer_copy_string_len(token, CONST_STR_LEN("=~"));
                    726: 
                    727:                                        tid = TK_MATCH;
                    728:                                } else {
                    729:                                        log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
                    730:                                                        "source:", t->source,
                    731:                                                        "line:", t->line, "pos:", t->line_pos,
                    732:                                                        "only =~ and == are allowed in the condition");
                    733:                                        return -1;
                    734:                                }
                    735:                                t->in_key = 1;
                    736:                                t->in_cond = 0;
                    737:                        } else if (t->in_key) {
                    738:                                tid = TK_ASSIGN;
                    739: 
                    740:                                buffer_copy_string_len(token, t->input + t->offset, 1);
                    741: 
                    742:                                t->offset++;
                    743:                                t->line_pos++;
                    744:                        } else {
                    745:                                log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
                    746:                                                "source:", t->source,
                    747:                                                "line:", t->line, "pos:", t->line_pos,
                    748:                                                "unexpected equal-sign: =");
                    749:                                return -1;
                    750:                        }
                    751: 
                    752:                        break;
                    753:                case '!':
                    754:                        if (t->in_cond) {
                    755:                                if (t->input[t->offset + 1] == '=') {
                    756:                                        t->offset += 2;
                    757: 
                    758:                                        buffer_copy_string_len(token, CONST_STR_LEN("!="));
                    759: 
                    760:                                        tid = TK_NE;
                    761:                                } else if (t->input[t->offset + 1] == '~') {
                    762:                                        t->offset += 2;
                    763: 
                    764:                                        buffer_copy_string_len(token, CONST_STR_LEN("!~"));
                    765: 
                    766:                                        tid = TK_NOMATCH;
                    767:                                } else {
                    768:                                        log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
                    769:                                                        "source:", t->source,
                    770:                                                        "line:", t->line, "pos:", t->line_pos,
                    771:                                                        "only !~ and != are allowed in the condition");
                    772:                                        return -1;
                    773:                                }
                    774:                                t->in_key = 1;
                    775:                                t->in_cond = 0;
                    776:                        } else {
                    777:                                log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
                    778:                                                "source:", t->source,
                    779:                                                "line:", t->line, "pos:", t->line_pos,
                    780:                                                "unexpected exclamation-marks: !");
                    781:                                return -1;
                    782:                        }
                    783: 
                    784:                        break;
                    785:                case '\t':
                    786:                case ' ':
                    787:                        t->offset++;
                    788:                        t->line_pos++;
                    789:                        break;
                    790:                case '\n':
                    791:                case '\r':
                    792:                        if (t->in_brace == 0) {
                    793:                                int done = 0;
                    794:                                while (!done && t->offset < t->size) {
                    795:                                        switch (t->input[t->offset]) {
                    796:                                        case '\r':
                    797:                                        case '\n':
                    798:                                                config_skip_newline(t);
                    799:                                                t->line_pos = 1;
                    800:                                                t->line++;
                    801:                                                break;
                    802: 
                    803:                                        case '#':
                    804:                                                t->line_pos += config_skip_comment(t);
                    805:                                                break;
                    806: 
                    807:                                        case '\t':
                    808:                                        case ' ':
                    809:                                                t->offset++;
                    810:                                                t->line_pos++;
                    811:                                                break;
                    812: 
                    813:                                        default:
                    814:                                                done = 1;
                    815:                                        }
                    816:                                }
                    817:                                t->in_key = 1;
                    818:                                tid = TK_EOL;
                    819:                                buffer_copy_string_len(token, CONST_STR_LEN("(EOL)"));
                    820:                        } else {
                    821:                                config_skip_newline(t);
                    822:                                t->line_pos = 1;
                    823:                                t->line++;
                    824:                        }
                    825:                        break;
                    826:                case ',':
                    827:                        if (t->in_brace > 0) {
                    828:                                tid = TK_COMMA;
                    829: 
                    830:                                buffer_copy_string_len(token, CONST_STR_LEN("(COMMA)"));
                    831:                        }
                    832: 
                    833:                        t->offset++;
                    834:                        t->line_pos++;
                    835:                        break;
                    836:                case '"':
                    837:                        /* search for the terminating " */
                    838:                        start = t->input + t->offset + 1;
                    839:                        buffer_copy_string_len(token, CONST_STR_LEN(""));
                    840: 
                    841:                        for (i = 1; t->input[t->offset + i]; i++) {
                    842:                                if (t->input[t->offset + i] == '\\' &&
                    843:                                    t->input[t->offset + i + 1] == '"') {
                    844: 
                    845:                                        buffer_append_string_len(token, start, t->input + t->offset + i - start);
                    846: 
                    847:                                        start = t->input + t->offset + i + 1;
                    848: 
                    849:                                        /* skip the " */
                    850:                                        i++;
                    851:                                        continue;
                    852:                                }
                    853: 
                    854: 
                    855:                                if (t->input[t->offset + i] == '"') {
                    856:                                        tid = TK_STRING;
                    857: 
                    858:                                        buffer_append_string_len(token, start, t->input + t->offset + i - start);
                    859: 
                    860:                                        break;
                    861:                                }
                    862:                        }
                    863: 
                    864:                        if (t->input[t->offset + i] == '\0') {
                    865:                                /* ERROR */
                    866: 
                    867:                                log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
                    868:                                                "source:", t->source,
                    869:                                                "line:", t->line, "pos:", t->line_pos,
                    870:                                                "missing closing quote");
                    871: 
                    872:                                return -1;
                    873:                        }
                    874: 
                    875:                        t->offset += i + 1;
                    876:                        t->line_pos += i + 1;
                    877: 
                    878:                        break;
                    879:                case '(':
                    880:                        t->offset++;
                    881:                        t->in_brace++;
                    882: 
                    883:                        tid = TK_LPARAN;
                    884: 
                    885:                        buffer_copy_string_len(token, CONST_STR_LEN("("));
                    886:                        break;
                    887:                case ')':
                    888:                        t->offset++;
                    889:                        t->in_brace--;
                    890: 
                    891:                        tid = TK_RPARAN;
                    892: 
                    893:                        buffer_copy_string_len(token, CONST_STR_LEN(")"));
                    894:                        break;
                    895:                case '$':
                    896:                        t->offset++;
                    897: 
                    898:                        tid = TK_DOLLAR;
                    899:                        t->in_cond = 1;
                    900:                        t->in_key = 0;
                    901: 
                    902:                        buffer_copy_string_len(token, CONST_STR_LEN("$"));
                    903: 
                    904:                        break;
                    905: 
                    906:                case '+':
                    907:                        if (t->input[t->offset + 1] == '=') {
                    908:                                t->offset += 2;
                    909:                                buffer_copy_string_len(token, CONST_STR_LEN("+="));
                    910:                                tid = TK_APPEND;
                    911:                        } else {
                    912:                                t->offset++;
                    913:                                tid = TK_PLUS;
                    914:                                buffer_copy_string_len(token, CONST_STR_LEN("+"));
                    915:                        }
                    916:                        break;
                    917: 
                    918:                case '{':
                    919:                        t->offset++;
                    920: 
                    921:                        tid = TK_LCURLY;
                    922: 
                    923:                        buffer_copy_string_len(token, CONST_STR_LEN("{"));
                    924: 
                    925:                        break;
                    926: 
                    927:                case '}':
                    928:                        t->offset++;
                    929: 
                    930:                        tid = TK_RCURLY;
                    931: 
                    932:                        buffer_copy_string_len(token, CONST_STR_LEN("}"));
                    933: 
                    934:                        break;
                    935: 
                    936:                case '[':
                    937:                        t->offset++;
                    938: 
                    939:                        tid = TK_LBRACKET;
                    940: 
                    941:                        buffer_copy_string_len(token, CONST_STR_LEN("["));
                    942: 
                    943:                        break;
                    944: 
                    945:                case ']':
                    946:                        t->offset++;
                    947: 
                    948:                        tid = TK_RBRACKET;
                    949: 
                    950:                        buffer_copy_string_len(token, CONST_STR_LEN("]"));
                    951: 
                    952:                        break;
                    953:                case '#':
                    954:                        t->line_pos += config_skip_comment(t);
                    955: 
                    956:                        break;
                    957:                default:
                    958:                        if (t->in_cond) {
                    959:                                for (i = 0; t->input[t->offset + i] &&
                    960:                                     (isalpha((unsigned char)t->input[t->offset + i])
                    961:                                      ); i++);
                    962: 
                    963:                                if (i && t->input[t->offset + i]) {
                    964:                                        tid = TK_SRVVARNAME;
                    965:                                        buffer_copy_string_len(token, t->input + t->offset, i);
                    966: 
                    967:                                        t->offset += i;
                    968:                                        t->line_pos += i;
                    969:                                } else {
                    970:                                        /* ERROR */
                    971:                                        log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
                    972:                                                        "source:", t->source,
                    973:                                                        "line:", t->line, "pos:", t->line_pos,
                    974:                                                        "invalid character in condition");
                    975:                                        return -1;
                    976:                                }
                    977:                        } else if (isdigit((unsigned char)c)) {
                    978:                                /* take all digits */
                    979:                                for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]);  i++);
                    980: 
                    981:                                /* was there it least a digit ? */
                    982:                                if (i) {
                    983:                                        tid = TK_INTEGER;
                    984: 
                    985:                                        buffer_copy_string_len(token, t->input + t->offset, i);
                    986: 
                    987:                                        t->offset += i;
                    988:                                        t->line_pos += i;
                    989:                                }
                    990:                        } else {
                    991:                                /* the key might consist of [-.0-9a-z] */
                    992:                                for (i = 0; t->input[t->offset + i] &&
                    993:                                     (isalnum((unsigned char)t->input[t->offset + i]) ||
                    994:                                      t->input[t->offset + i] == '.' ||
                    995:                                      t->input[t->offset + i] == '_' || /* for env.* */
                    996:                                      t->input[t->offset + i] == '-'
                    997:                                      ); i++);
                    998: 
                    999:                                if (i && t->input[t->offset + i]) {
                   1000:                                        buffer_copy_string_len(token, t->input + t->offset, i);
                   1001: 
                   1002:                                        if (strcmp(token->ptr, "include") == 0) {
                   1003:                                                tid = TK_INCLUDE;
                   1004:                                        } else if (strcmp(token->ptr, "include_shell") == 0) {
                   1005:                                                tid = TK_INCLUDE_SHELL;
                   1006:                                        } else if (strcmp(token->ptr, "global") == 0) {
                   1007:                                                tid = TK_GLOBAL;
                   1008:                                        } else if (strcmp(token->ptr, "else") == 0) {
                   1009:                                                tid = TK_ELSE;
                   1010:                                        } else {
                   1011:                                                tid = TK_LKEY;
                   1012:                                        }
                   1013: 
                   1014:                                        t->offset += i;
                   1015:                                        t->line_pos += i;
                   1016:                                } else {
                   1017:                                        /* ERROR */
                   1018:                                        log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
                   1019:                                                        "source:", t->source,
                   1020:                                                        "line:", t->line, "pos:", t->line_pos,
                   1021:                                                        "invalid character in variable name");
                   1022:                                        return -1;
                   1023:                                }
                   1024:                        }
                   1025:                        break;
                   1026:                }
                   1027:        }
                   1028: 
                   1029:        if (tid) {
                   1030:                *token_id = tid;
                   1031: #if 0
                   1032:                log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
                   1033:                                "source:", t->source,
                   1034:                                "line:", t->line, "pos:", t->line_pos,
                   1035:                                token, token->used - 1, tid);
                   1036: #endif
                   1037: 
                   1038:                return 1;
                   1039:        } else if (t->offset < t->size) {
                   1040:                fprintf(stderr, "%s.%d: %d, %s\n",
                   1041:                        __FILE__, __LINE__,
                   1042:                        tid, token->ptr);
                   1043:        }
                   1044:        return 0;
                   1045: }
                   1046: 
                   1047: static int config_parse(server *srv, config_t *context, tokenizer_t *t) {
                   1048:        void *pParser;
                   1049:        int token_id;
                   1050:        buffer *token, *lasttoken;
                   1051:        int ret;
                   1052: 
                   1053:        pParser = configparserAlloc( malloc );
1.1.1.3 ! misho    1054:        force_assert(pParser);
1.1       misho    1055:        lasttoken = buffer_init();
                   1056:        token = buffer_init();
                   1057:        while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
1.1.1.3 ! misho    1058:                buffer_copy_buffer(lasttoken, token);
1.1       misho    1059:                configparser(pParser, token_id, token, context);
                   1060: 
                   1061:                token = buffer_init();
                   1062:        }
                   1063:        buffer_free(token);
                   1064: 
                   1065:        if (ret != -1 && context->ok) {
                   1066:                /* add an EOL at EOF, better than say sorry */
                   1067:                configparser(pParser, TK_EOL, buffer_init_string("(EOL)"), context);
                   1068:                if (context->ok) {
                   1069:                        configparser(pParser, 0, NULL, context);
                   1070:                }
                   1071:        }
                   1072:        configparserFree(pParser, free);
                   1073: 
                   1074:        if (ret == -1) {
                   1075:                log_error_write(srv, __FILE__, __LINE__, "sb",
                   1076:                                "configfile parser failed at:", lasttoken);
                   1077:        } else if (context->ok == 0) {
                   1078:                log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
                   1079:                                "source:", t->source,
                   1080:                                "line:", t->line, "pos:", t->line_pos,
                   1081:                                "parser failed somehow near here:", lasttoken);
                   1082:                ret = -1;
                   1083:        }
                   1084:        buffer_free(lasttoken);
                   1085: 
                   1086:        return ret == -1 ? -1 : 0;
                   1087: }
                   1088: 
                   1089: static int tokenizer_init(tokenizer_t *t, const buffer *source, const char *input, size_t size) {
                   1090: 
                   1091:        t->source = source;
                   1092:        t->input = input;
                   1093:        t->size = size;
                   1094:        t->offset = 0;
                   1095:        t->line = 1;
                   1096:        t->line_pos = 1;
                   1097: 
                   1098:        t->in_key = 1;
                   1099:        t->in_brace = 0;
                   1100:        t->in_cond = 0;
                   1101:        return 0;
                   1102: }
                   1103: 
1.1.1.3 ! misho    1104: static int config_parse_file_stream(server *srv, config_t *context, const buffer *filename) {
1.1       misho    1105:        tokenizer_t t;
                   1106:        stream s;
                   1107:        int ret;
                   1108: 
1.1.1.3 ! misho    1109:        if (0 != stream_open(&s, filename)) {
        !          1110:                log_error_write(srv, __FILE__, __LINE__, "sbss",
        !          1111:                                "opening configfile ", filename, "failed:", strerror(errno));
        !          1112:                return -1;
        !          1113:        } else {
        !          1114:                tokenizer_init(&t, filename, s.start, s.size);
        !          1115:                ret = config_parse(srv, context, &t);
        !          1116:        }
        !          1117: 
        !          1118:        stream_close(&s);
        !          1119:        return ret;
        !          1120: }
        !          1121: 
        !          1122: int config_parse_file(server *srv, config_t *context, const char *fn) {
        !          1123:        buffer *filename;
        !          1124:        size_t i;
        !          1125:        int ret = -1;
        !          1126:       #ifdef GLOB_BRACE
        !          1127:        int flags = GLOB_BRACE;
        !          1128:       #else
        !          1129:        int flags = 0;
        !          1130:       #endif
        !          1131:        glob_t gl;
        !          1132: 
        !          1133:        if ((fn[0] == '/' || fn[0] == '\\') ||
        !          1134:            (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\')) ||
        !          1135:            (fn[0] == '.' && fn[1] == '.' && (fn[2] == '/' || fn[2] == '\\'))) {
1.1       misho    1136:                filename = buffer_init_string(fn);
                   1137:        } else {
                   1138:                filename = buffer_init_buffer(context->basedir);
                   1139:                buffer_append_string(filename, fn);
                   1140:        }
                   1141: 
1.1.1.3 ! misho    1142:        switch (glob(filename->ptr, flags, NULL, &gl)) {
        !          1143:        case 0:
        !          1144:                for (i = 0; i < gl.gl_pathc; ++i) {
        !          1145:                        buffer_copy_string(filename, gl.gl_pathv[i]);
        !          1146:                        ret = config_parse_file_stream(srv, context, filename);
        !          1147:                        if (0 != ret) break;
        !          1148:                }
        !          1149:                globfree(&gl);
        !          1150:                break;
        !          1151:        case GLOB_NOMATCH:
        !          1152:                if (filename->ptr[strcspn(filename->ptr, "*?[]{}")] != '\0') { /*(contains glob metachars)*/
        !          1153:                        ret = 0; /* not an error if no files match glob pattern */
        !          1154:                }
        !          1155:                else {
        !          1156:                        log_error_write(srv, __FILE__, __LINE__, "sb", "include file not found: ", filename);
        !          1157:                }
        !          1158:                break;
        !          1159:        case GLOB_ABORTED:
        !          1160:        case GLOB_NOSPACE:
        !          1161:                log_error_write(srv, __FILE__, __LINE__, "sbss", "glob()", filename, "failed:", strerror(errno));
        !          1162:                break;
1.1       misho    1163:        }
                   1164: 
                   1165:        buffer_free(filename);
                   1166:        return ret;
                   1167: }
                   1168: 
                   1169: static char* getCWD(void) {
                   1170:        char *s, *s1;
                   1171:        size_t len;
                   1172: #ifdef PATH_MAX
                   1173:        len = PATH_MAX;
                   1174: #else
                   1175:        len = 4096;
                   1176: #endif
                   1177: 
                   1178:        s = malloc(len);
                   1179:        if (!s) return NULL;
                   1180:        while (NULL == getcwd(s, len)) {
1.1.1.2   misho    1181:                if (errno != ERANGE || SSIZE_MAX - len < len) {
                   1182:                        free(s);
                   1183:                        return NULL;
                   1184:                }
1.1       misho    1185:                len *= 2;
                   1186:                s1 = realloc(s, len);
                   1187:                if (!s1) {
                   1188:                        free(s);
                   1189:                        return NULL;
                   1190:                }
                   1191:                s = s1;
                   1192:        }
                   1193:        return s;
                   1194: }
                   1195: 
                   1196: int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
                   1197:        tokenizer_t t;
                   1198:        int ret;
                   1199:        buffer *source;
                   1200:        buffer *out;
                   1201:        char *oldpwd;
                   1202: 
                   1203:        if (NULL == (oldpwd = getCWD())) {
                   1204:                log_error_write(srv, __FILE__, __LINE__, "s",
1.1.1.3 ! misho    1205:                        "cannot get cwd", strerror(errno));
1.1       misho    1206:                return -1;
                   1207:        }
                   1208: 
1.1.1.3 ! misho    1209:        if (!buffer_string_is_empty(context->basedir)) {
        !          1210:                if (0 != chdir(context->basedir->ptr)) {
        !          1211:                        log_error_write(srv, __FILE__, __LINE__, "sbs",
        !          1212:                                "cannot change directory to", context->basedir, strerror(errno));
        !          1213:                        free(oldpwd);
        !          1214:                        return -1;
        !          1215:                }
        !          1216:        }
        !          1217: 
1.1       misho    1218:        source = buffer_init_string(cmd);
                   1219:        out = buffer_init();
                   1220: 
                   1221:        if (0 != proc_open_buffer(cmd, NULL, out, NULL)) {
                   1222:                log_error_write(srv, __FILE__, __LINE__, "sbss",
1.1.1.3 ! misho    1223:                        "opening", source, "failed:", strerror(errno));
1.1       misho    1224:                ret = -1;
                   1225:        } else {
1.1.1.3 ! misho    1226:                tokenizer_init(&t, source, CONST_BUF_LEN(out));
1.1       misho    1227:                ret = config_parse(srv, context, &t);
                   1228:        }
                   1229: 
                   1230:        buffer_free(source);
                   1231:        buffer_free(out);
1.1.1.3 ! misho    1232:        if (0 != chdir(oldpwd)) {
        !          1233:                log_error_write(srv, __FILE__, __LINE__, "sss",
        !          1234:                        "cannot change directory to", oldpwd, strerror(errno));
        !          1235:                free(oldpwd);
        !          1236:                return -1;
        !          1237:        }
1.1       misho    1238:        free(oldpwd);
                   1239:        return ret;
                   1240: }
                   1241: 
                   1242: static void context_init(server *srv, config_t *context) {
                   1243:        context->srv = srv;
                   1244:        context->ok = 1;
1.1.1.3 ! misho    1245:        vector_config_weak_init(&context->configs_stack);
1.1       misho    1246:        context->basedir = buffer_init();
                   1247: }
                   1248: 
                   1249: static void context_free(config_t *context) {
1.1.1.3 ! misho    1250:        vector_config_weak_clear(&context->configs_stack);
1.1       misho    1251:        buffer_free(context->basedir);
                   1252: }
                   1253: 
                   1254: int config_read(server *srv, const char *fn) {
                   1255:        config_t context;
                   1256:        data_config *dc;
                   1257:        data_integer *dpid;
                   1258:        data_string *dcwd;
                   1259:        int ret;
                   1260:        char *pos;
1.1.1.3 ! misho    1261:        buffer *filename;
1.1       misho    1262: 
                   1263:        context_init(srv, &context);
                   1264:        context.all_configs = srv->config_context;
                   1265: 
                   1266: #ifdef __WIN32
                   1267:        pos = strrchr(fn, '\\');
                   1268: #else
                   1269:        pos = strrchr(fn, '/');
                   1270: #endif
                   1271:        if (pos) {
                   1272:                buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
                   1273:        }
                   1274: 
                   1275:        dc = data_config_init();
                   1276:        buffer_copy_string_len(dc->key, CONST_STR_LEN("global"));
                   1277: 
1.1.1.2   misho    1278:        force_assert(context.all_configs->used == 0);
1.1       misho    1279:        dc->context_ndx = context.all_configs->used;
                   1280:        array_insert_unique(context.all_configs, (data_unset *)dc);
                   1281:        context.current = dc;
                   1282: 
                   1283:        /* default context */
                   1284:        dpid = data_integer_init();
                   1285:        dpid->value = getpid();
                   1286:        buffer_copy_string_len(dpid->key, CONST_STR_LEN("var.PID"));
1.1.1.3 ! misho    1287:        array_insert_unique(dc->value, (data_unset *)dpid);
1.1       misho    1288: 
                   1289:        dcwd = data_string_init();
1.1.1.3 ! misho    1290:        buffer_string_prepare_copy(dcwd->value, 1023);
1.1       misho    1291:        if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
1.1.1.3 ! misho    1292:                buffer_commit(dcwd->value, strlen(dcwd->value->ptr));
1.1       misho    1293:                buffer_copy_string_len(dcwd->key, CONST_STR_LEN("var.CWD"));
1.1.1.3 ! misho    1294:                array_insert_unique(dc->value, (data_unset *)dcwd);
1.1.1.2   misho    1295:        } else {
                   1296:                dcwd->free((data_unset*) dcwd);
1.1       misho    1297:        }
                   1298: 
1.1.1.3 ! misho    1299:        filename = buffer_init_string(fn);
        !          1300:        ret = config_parse_file_stream(srv, &context, filename);
        !          1301:        buffer_free(filename);
1.1       misho    1302: 
                   1303:        /* remains nothing if parser is ok */
1.1.1.3 ! misho    1304:        force_assert(!(0 == ret && context.ok && 0 != context.configs_stack.used));
1.1       misho    1305:        context_free(&context);
                   1306: 
                   1307:        if (0 != ret) {
                   1308:                return ret;
                   1309:        }
                   1310: 
                   1311:        if (0 != config_insert(srv)) {
                   1312:                return -1;
                   1313:        }
                   1314: 
                   1315:        return 0;
                   1316: }
                   1317: 
                   1318: int config_set_defaults(server *srv) {
                   1319:        size_t i;
                   1320:        specific_config *s = srv->config_storage[0];
                   1321:        struct stat st1, st2;
                   1322: 
                   1323:        struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
                   1324:        {
                   1325:                /* - epoll is most reliable
                   1326:                 * - select works everywhere
                   1327:                 */
                   1328: #ifdef USE_LINUX_EPOLL
                   1329:                { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" },
                   1330: #endif
                   1331: #ifdef USE_POLL
                   1332:                { FDEVENT_HANDLER_POLL,           "poll" },
                   1333: #endif
                   1334: #ifdef USE_SELECT
                   1335:                { FDEVENT_HANDLER_SELECT,         "select" },
                   1336: #endif
                   1337: #ifdef USE_LIBEV
                   1338:                { FDEVENT_HANDLER_LIBEV,          "libev" },
                   1339: #endif
                   1340: #ifdef USE_SOLARIS_DEVPOLL
                   1341:                { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" },
                   1342: #endif
                   1343: #ifdef USE_SOLARIS_PORT
                   1344:                { FDEVENT_HANDLER_SOLARIS_PORT,   "solaris-eventports" },
                   1345: #endif
                   1346: #ifdef USE_FREEBSD_KQUEUE
                   1347:                { FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue" },
                   1348:                { FDEVENT_HANDLER_FREEBSD_KQUEUE, "kqueue" },
                   1349: #endif
                   1350:                { FDEVENT_HANDLER_UNSET,          NULL }
                   1351:        };
                   1352: 
1.1.1.3 ! misho    1353:        if (!buffer_string_is_empty(srv->srvconf.changeroot)) {
1.1       misho    1354:                if (-1 == stat(srv->srvconf.changeroot->ptr, &st1)) {
                   1355:                        log_error_write(srv, __FILE__, __LINE__, "sb",
                   1356:                                        "server.chroot doesn't exist:", srv->srvconf.changeroot);
                   1357:                        return -1;
                   1358:                }
                   1359:                if (!S_ISDIR(st1.st_mode)) {
                   1360:                        log_error_write(srv, __FILE__, __LINE__, "sb",
                   1361:                                        "server.chroot isn't a directory:", srv->srvconf.changeroot);
                   1362:                        return -1;
                   1363:                }
                   1364:        }
                   1365: 
1.1.1.3 ! misho    1366:        if (!srv->srvconf.upload_tempdirs->used) {
        !          1367:                data_string *ds = data_string_init();
        !          1368:                const char *tmpdir = getenv("TMPDIR");
        !          1369:                if (NULL == tmpdir) tmpdir = "/var/tmp";
        !          1370:                buffer_copy_string(ds->value, tmpdir);
        !          1371:                array_insert_unique(srv->srvconf.upload_tempdirs, (data_unset *)ds);
        !          1372:        }
        !          1373: 
        !          1374:        if (srv->srvconf.upload_tempdirs->used) {
        !          1375:                buffer * const b = srv->tmp_buf;
        !          1376:                size_t len;
        !          1377:                if (!buffer_string_is_empty(srv->srvconf.changeroot)) {
        !          1378:                        buffer_copy_buffer(b, srv->srvconf.changeroot);
        !          1379:                        buffer_append_slash(b);
        !          1380:                } else {
        !          1381:                        buffer_reset(b);
        !          1382:                }
        !          1383:                len = buffer_string_length(b);
        !          1384: 
        !          1385:                for (i = 0; i < srv->srvconf.upload_tempdirs->used; ++i) {
        !          1386:                        const data_string * const ds = (data_string *)srv->srvconf.upload_tempdirs->data[i];
        !          1387:                        buffer_string_set_length(b, len); /*(truncate)*/
        !          1388:                        buffer_append_string_buffer(b, ds->value);
        !          1389:                        if (-1 == stat(b->ptr, &st1)) {
        !          1390:                                log_error_write(srv, __FILE__, __LINE__, "sb",
        !          1391:                                        "server.upload-dirs doesn't exist:", b);
        !          1392:                        } else if (!S_ISDIR(st1.st_mode)) {
        !          1393:                                log_error_write(srv, __FILE__, __LINE__, "sb",
        !          1394:                                        "server.upload-dirs isn't a directory:", b);
        !          1395:                        }
        !          1396:                }
        !          1397:        }
        !          1398: 
        !          1399:        chunkqueue_set_tempdirs_default(
        !          1400:                srv->srvconf.upload_tempdirs,
        !          1401:                srv->srvconf.upload_temp_file_size);
        !          1402: 
        !          1403:        if (buffer_string_is_empty(s->document_root)) {
1.1       misho    1404:                log_error_write(srv, __FILE__, __LINE__, "s",
                   1405:                                "a default document-root has to be set");
                   1406: 
                   1407:                return -1;
                   1408:        }
                   1409: 
1.1.1.3 ! misho    1410:        buffer_copy_buffer(srv->tmp_buf, s->document_root);
1.1       misho    1411: 
                   1412:        buffer_to_lower(srv->tmp_buf);
                   1413: 
                   1414:        if (2 == s->force_lowercase_filenames) { /* user didn't configure it in global section? */
                   1415:                s->force_lowercase_filenames = 0; /* default to 0 */
                   1416: 
                   1417:                if (0 == stat(srv->tmp_buf->ptr, &st1)) {
                   1418:                        int is_lower = 0;
                   1419: 
                   1420:                        is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
                   1421: 
                   1422:                        /* lower-case existed, check upper-case */
1.1.1.3 ! misho    1423:                        buffer_copy_buffer(srv->tmp_buf, s->document_root);
1.1       misho    1424: 
                   1425:                        buffer_to_upper(srv->tmp_buf);
                   1426: 
                   1427:                        /* we have to handle the special case that upper and lower-casing results in the same filename
                   1428:                         * as in server.document-root = "/" or "/12345/" */
                   1429: 
                   1430:                        if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
                   1431:                                /* lower-casing and upper-casing didn't result in
                   1432:                                 * an other filename, no need to stat(),
                   1433:                                 * just assume it is case-sensitive. */
                   1434: 
                   1435:                                s->force_lowercase_filenames = 0;
                   1436:                        } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
                   1437: 
                   1438:                                /* upper case exists too, doesn't the FS handle this ? */
                   1439: 
                   1440:                                /* upper and lower have the same inode -> case-insensitve FS */
                   1441: 
                   1442:                                if (st1.st_ino == st2.st_ino) {
                   1443:                                        /* upper and lower have the same inode -> case-insensitve FS */
                   1444: 
                   1445:                                        s->force_lowercase_filenames = 1;
                   1446:                                }
                   1447:                        }
                   1448:                }
                   1449:        }
                   1450: 
                   1451:        if (srv->srvconf.port == 0) {
                   1452:                srv->srvconf.port = s->ssl_enabled ? 443 : 80;
                   1453:        }
                   1454: 
1.1.1.3 ! misho    1455:        if (buffer_string_is_empty(srv->srvconf.event_handler)) {
1.1       misho    1456:                /* choose a good default
                   1457:                 *
                   1458:                 * the event_handler list is sorted by 'goodness'
                   1459:                 * taking the first available should be the best solution
                   1460:                 */
                   1461:                srv->event_handler = event_handlers[0].et;
                   1462: 
                   1463:                if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
                   1464:                        log_error_write(srv, __FILE__, __LINE__, "s",
                   1465:                                        "sorry, there is no event handler for this system");
                   1466: 
                   1467:                        return -1;
                   1468:                }
                   1469:        } else {
                   1470:                /*
                   1471:                 * User override
                   1472:                 */
                   1473: 
                   1474:                for (i = 0; event_handlers[i].name; i++) {
                   1475:                        if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
                   1476:                                srv->event_handler = event_handlers[i].et;
                   1477:                                break;
                   1478:                        }
                   1479:                }
                   1480: 
                   1481:                if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
                   1482:                        log_error_write(srv, __FILE__, __LINE__, "sb",
                   1483:                                        "the selected event-handler in unknown or not supported:",
                   1484:                                        srv->srvconf.event_handler );
                   1485: 
                   1486:                        return -1;
                   1487:                }
                   1488:        }
                   1489: 
                   1490:        if (s->ssl_enabled) {
1.1.1.3 ! misho    1491:                if (buffer_string_is_empty(s->ssl_pemfile)) {
1.1       misho    1492:                        /* PEM file is require */
                   1493: 
                   1494:                        log_error_write(srv, __FILE__, __LINE__, "s",
                   1495:                                        "ssl.pemfile has to be set");
                   1496:                        return -1;
                   1497:                }
                   1498: 
                   1499: #ifndef USE_OPENSSL
                   1500:                log_error_write(srv, __FILE__, __LINE__, "s",
                   1501:                                "ssl support is missing, recompile with --with-openssl");
                   1502: 
                   1503:                return -1;
                   1504: #endif
                   1505:        }
                   1506: 
                   1507:        return 0;
                   1508: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>