Ignore:
Timestamp:
Aug 25, 2008, 7:32:06 PM (13 years ago)
Author:
charles
Message:

upgrade to shttpd 1.42

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/third-party/shttpd/shttpd.c

    r6391 r6644  
    1111/*
    1212 * Small and portable HTTP server, http://shttpd.sourceforge.net
    13  * $Id: shttpd.c,v 1.44 2008/05/31 18:20:02 drozd Exp $
     13 * $Id: shttpd.c,v 1.57 2008/08/23 21:00:38 drozd Exp $
    1414 */
    1515
    1616#include "defs.h"
    1717
    18 time_t  current_time;   /* Current UTC time             */
    19 int     tz_offset;      /* Time zone offset from UTC    */
    20 int     exit_flag;      /* Program exit flag            */
    21 
    22 const struct vec known_http_methods[] = {
     18time_t  _shttpd_current_time;   /* Current UTC time             */
     19int     _shttpd_tz_offset;      /* Time zone offset from UTC    */
     20int     _shttpd_exit_flag;      /* Program exit flag            */
     21
     22const struct vec _shttpd_known_http_methods[] = {
    2323        {"GET",         3},
    2424        {"POST",        4},
     
    5454
    5555int
    56 is_true(const char *str)
     56_shttpd_is_true(const char *str)
    5757{
    5858        static const char       *trues[] = {"1", "yes", "true", "jawohl", NULL};
     
    103103
    104104int
    105 url_decode(const char *src, int src_len, char *dst, int dst_len)
     105_shttpd_url_decode(const char *src, int src_len, char *dst, int dst_len)
    106106{
    107107        int     i, j, a, b;
     
    158158
    159159void
    160 stop_stream(struct stream *stream)
     160_shttpd_stop_stream(struct stream *stream)
    161161{
    162162        if (stream->io_class != NULL && stream->io_class->close != NULL)
     
    193193        if ((sock = socket(PF_INET, SOCK_STREAM, 6)) == -1)
    194194                goto fail;
    195         if (set_non_blocking_mode(sock) != 0)
     195        if (_shttpd_set_non_blocking_mode(sock) != 0)
    196196                goto fail;
    197197        if (setsockopt(sock, SOL_SOCKET,
     
    211211        if (sock != -1)
    212212                (void) closesocket(sock);
    213         elog(E_LOG, NULL, "open_listening_port(%d): %s", port, strerror(errno));
     213        _shttpd_elog(E_LOG, NULL, "open_listening_port(%d): %s", port, strerror(errno));
    214214        return (-1);
    215215}
     
    219219 */
    220220int
    221 get_headers_len(const char *buf, size_t buflen)
     221_shttpd_get_headers_len(const char *buf, size_t buflen)
    222222{
    223223        const char      *s, *e;
     
    242242 */
    243243void
    244 send_server_error(struct conn *c, int status, const char *reason)
     244_shttpd_send_server_error(struct conn *c, int status, const char *reason)
    245245{
    246246        struct llhead           *lp;
     
    255255                                c->loc.io_class->close(&c->loc);
    256256                        io_clear(&c->loc.io);
    257                         setup_embedded_stream(c, e->callback, e->callback_data);
     257                        _shttpd_setup_embedded_stream(c,
     258                            e->callback, e->callback_data);
    258259                        return;
    259260                }
     
    261262
    262263        io_clear(&c->loc.io);
    263         c->loc.io.head = my_snprintf(c->loc.io.buf, c->loc.io.size,
     264        c->loc.io.head = _shttpd_snprintf(c->loc.io.buf, c->loc.io.size,
    264265            "HTTP/1.1 %d %s\r\n"
    265266            "Content-Type: text/plain\r\n"
     
    270271        c->loc.content_len = 10;
    271272        c->status = status;
    272         stop_stream(&c->loc);
     273        _shttpd_stop_stream(&c->loc);
    273274}
    274275
     
    328329
    329330        /* Set Daylight Saving Time field */
    330         tmp = localtime(&current_time);
     331        tmp = localtime(&_shttpd_current_time);
    331332        tm.tm_isdst = tmp->tm_isdst;
    332333
     
    349350
    350351void
    351 parse_headers(const char *s, int len, struct headers *parsed)
     352_shttpd_parse_headers(const char *s, int len, struct headers *parsed)
    352353{
    353354        const struct http_header        *h;
     
    366367                for (h = http_headers; h->len != 0; h++)
    367368                        if (e - s > h->len &&
    368                             !my_strncasecmp(s, h->name, h->len))
     369                            !_shttpd_strncasecmp(s, h->name, h->len))
    369370                                break;
    370371
     
    439440
    440441void
    441 get_mime_type(struct shttpd_ctx *ctx, const char *uri, int len, struct vec *vec)
     442_shttpd_get_mime_type(struct shttpd_ctx *ctx,
     443                const char *uri, int len, struct vec *vec)
    442444{
    443445        const char      *eq, *p = ctx->options[OPT_MIME_TYPES];
     
    450452                ext_len = eq - p;
    451453                if (len > ext_len && uri[len - ext_len - 1] == '.' &&
    452                     !my_strncasecmp(p, &uri[len - ext_len], ext_len)) {
     454                    !_shttpd_strncasecmp(p, &uri[len - ext_len], ext_len)) {
    453455                        vec->ptr = eq + 1;
    454456                        vec->len = p + n - vec->ptr;
     
    461463                ext_len = builtin_mime_types[i].ext_len;
    462464                if (len > ext_len && uri[len - ext_len - 1] == '.' &&
    463                     !my_strncasecmp(builtin_mime_types[i].extension,
     465                    !_shttpd_strncasecmp(builtin_mime_types[i].extension,
    464466                            &uri[len - ext_len], ext_len)) {
    465467                        vec->ptr = builtin_mime_types[i].mime_type;
     
    486488
    487489        FOR_EACH_WORD_IN_LIST(s, len) {
    488                 my_snprintf(buf, sizeof(buf), "%s%c%.*s",path, DIRSEP, len, s);
    489                 if (my_stat(buf, stp) == 0) {
    490                         my_strlcpy(path, buf, maxpath);
    491                         get_mime_type(c->ctx, s, len, &c->mime_type);
     490                /* path must end with '/' character */
     491                _shttpd_snprintf(buf, sizeof(buf), "%s%.*s", path, len, s);
     492                if (_shttpd_stat(buf, stp) == 0) {
     493                        _shttpd_strlcpy(path, buf, maxpath);
     494                        _shttpd_get_mime_type(c->ctx, s, len, &c->mime_type);
    492495                        return (0);
    493496                }
     
    507510        char    *p, *e;
    508511
    509         if (my_stat(path, stp) == 0)
     512        if (_shttpd_stat(path, stp) == 0)
    510513                return (0);
    511514
     
    517520                if (*p == '/') {
    518521                        *p = '\0';
    519                         if (!my_stat(path, stp) && !S_ISDIR(stp->st_mode)) {
     522                        if (!_shttpd_stat(path, stp) && !S_ISDIR(stp->st_mode)) {
    520523                                c->path_info = p + 1;
    521524                                return (0);
     
    542545                *c->query++ = '\0';
    543546
    544         url_decode(c->uri, strlen(c->uri), c->uri, strlen(c->uri) + 1);
     547        _shttpd_url_decode(c->uri, strlen(c->uri), c->uri, strlen(c->uri) + 1);
    545548        remove_double_dots(c->uri);
    546549       
    547550        root = c->ctx->options[OPT_ROOT];
    548551        if (strlen(c->uri) + strlen(root) >= sizeof(path)) {
    549                 send_server_error(c, 400, "URI is too long");
     552                _shttpd_send_server_error(c, 400, "URI is too long");
    550553                return;
    551554        }
    552555
    553         (void) my_snprintf(path, sizeof(path), "%s%s", root, c->uri);
     556        (void) _shttpd_snprintf(path, sizeof(path), "%s%s", root, c->uri);
    554557
    555558        /* User may use the aliases - check URI for mount point */
    556559        if (is_alias(c->ctx, c->uri, &alias_uri, &alias_path) != NULL) {
    557                 (void) my_snprintf(path, sizeof(path), "%.*s%s",
     560                (void) _shttpd_snprintf(path, sizeof(path), "%.*s%s",
    558561                    alias_path.len, alias_path.ptr, c->uri + alias_uri.len);
    559562                DBG(("using alias %.*s -> %.*s", alias_uri.len, alias_uri.ptr,
     
    562565
    563566#if !defined(NO_AUTH)
    564         if (check_authorization(c, path) != 1) {
    565                 send_authorization_request(c);
     567        if (_shttpd_check_authorization(c, path) != 1) {
     568                _shttpd_send_authorization_request(c);
    566569        } else
    567570#endif /* NO_AUTH */
    568         if ((ruri = is_registered_uri(c->ctx, c->uri)) != NULL) {
    569                 setup_embedded_stream(c, ruri->callback, ruri->callback_data);
     571        if ((ruri = _shttpd_is_registered_uri(c->ctx, c->uri)) != NULL) {
     572                _shttpd_setup_embedded_stream(c,
     573                    ruri->callback, ruri->callback_data);
    570574        } else
    571575        if (strstr(path, HTPASSWD)) {
    572576                /* Do not allow to view passwords files */
    573                 send_server_error(c, 403, "Forbidden");
     577                _shttpd_send_server_error(c, 403, "Forbidden");
    574578        } else
    575579#if !defined(NO_AUTH)
    576580        if ((c->method == METHOD_PUT || c->method == METHOD_DELETE) &&
    577581            (c->ctx->options[OPT_AUTH_PUT] == NULL ||
    578              !is_authorized_for_put(c))) {
    579                 send_authorization_request(c);
     582             !_shttpd_is_authorized_for_put(c))) {
     583                _shttpd_send_authorization_request(c);
    580584        } else
    581585#endif /* NO_AUTH */
    582586        if (c->method == METHOD_PUT) {
    583                 c->status = my_stat(path, &st) == 0 ? 200 : 201;
     587                c->status = _shttpd_stat(path, &st) == 0 ? 200 : 201;
    584588
    585589                if (c->ch.range.v_vec.len > 0) {
    586                         send_server_error(c, 501, "PUT Range Not Implemented");
    587                 } else if ((rc = put_dir(path)) == 0) {
    588                         send_server_error(c, 200, "OK");
     590                        _shttpd_send_server_error(c, 501,
     591                            "PUT Range Not Implemented");
     592                } else if ((rc = _shttpd_put_dir(path)) == 0) {
     593                        _shttpd_send_server_error(c, 200, "OK");
    589594                } else if (rc == -1) {
    590                         send_server_error(c, 500, "PUT Directory Error");
     595                        _shttpd_send_server_error(c, 500, "PUT Directory Error");
    591596                } else if (c->rem.content_len == 0) {
    592                         send_server_error(c, 411, "Length Required");
    593                 } else if ((c->loc.chan.fd = my_open(path, O_WRONLY | O_BINARY |
     597                        _shttpd_send_server_error(c, 411, "Length Required");
     598                } else if ((c->loc.chan.fd = _shttpd_open(path, O_WRONLY | O_BINARY |
    594599                    O_CREAT | O_NONBLOCK | O_TRUNC, 0644)) == -1) {
    595                         send_server_error(c, 500, "PUT Error");
     600                        _shttpd_send_server_error(c, 500, "PUT Error");
    596601                } else {
    597602                        DBG(("PUT file [%s]", c->uri));
    598                         c->loc.io_class = &io_file;
     603                        c->loc.io_class = &_shttpd_io_file;
    599604                        c->loc.flags |= FLAG_W | FLAG_ALWAYS_READY ;
    600605                }
    601606        } else if (c->method == METHOD_DELETE) {
    602607                DBG(("DELETE [%s]", c->uri));
    603                 if (my_remove(path) == 0)
    604                         send_server_error(c, 200, "OK");
     608                if (_shttpd_remove(path) == 0)
     609                        _shttpd_send_server_error(c, 200, "OK");
    605610                else
    606                         send_server_error(c, 500, "DELETE Error");
     611                        _shttpd_send_server_error(c, 500, "DELETE Error");
    607612        } else if (get_path_info(c, path, &st) != 0) {
    608                 send_server_error(c, 404, "Not Found");
     613                _shttpd_send_server_error(c, 404, "Not Found");
    609614        } else if (S_ISDIR(st.st_mode) && path[strlen(path) - 1] != '/') {
    610                 (void) my_snprintf(buf, sizeof(buf),
     615                (void) _shttpd_snprintf(buf, sizeof(buf),
    611616                        "Moved Permanently\r\nLocation: %s/", c->uri);
    612                 send_server_error(c, 301, buf);
     617                _shttpd_send_server_error(c, 301, buf);
    613618        } else if (S_ISDIR(st.st_mode) &&
    614619            find_index_file(c, path, sizeof(path) - 1, &st) == -1 &&
    615620            !IS_TRUE(c->ctx, OPT_DIR_LIST)) {
    616                 send_server_error(c, 403, "Directory Listing Denied");
     621                _shttpd_send_server_error(c, 403, "Directory Listing Denied");
    617622        } else if (S_ISDIR(st.st_mode) && IS_TRUE(c->ctx, OPT_DIR_LIST)) {
    618                 if ((c->loc.chan.dir.path = my_strdup(path)) != NULL)
    619                         get_dir(c);
     623                if ((c->loc.chan.dir.path = _shttpd_strdup(path)) != NULL)
     624                        _shttpd_get_dir(c);
    620625                else
    621                         send_server_error(c, 500, "GET Directory Error");
     626                        _shttpd_send_server_error(c, 500, "GET Directory Error");
    622627        } else if (S_ISDIR(st.st_mode) && !IS_TRUE(c->ctx, OPT_DIR_LIST)) {
    623                 send_server_error(c, 403, "Directory listing denied");
     628                _shttpd_send_server_error(c, 403, "Directory listing denied");
    624629#if !defined(NO_CGI)
    625         } else if (match_extension(path, c->ctx->options[OPT_CGI_EXTENSIONS])) {
     630        } else if (_shttpd_match_extension(path,
     631            c->ctx->options[OPT_CGI_EXTENSIONS])) {
    626632                if (c->method != METHOD_POST && c->method != METHOD_GET) {
    627                         send_server_error(c, 501, "Bad method ");
    628                 } else if ((run_cgi(c, path)) == -1) {
    629                         send_server_error(c, 500, "Cannot exec CGI");
     633                        _shttpd_send_server_error(c, 501, "Bad method ");
     634                } else if ((_shttpd_run_cgi(c, path)) == -1) {
     635                        _shttpd_send_server_error(c, 500, "Cannot exec CGI");
    630636                } else {
    631                         do_cgi(c);
     637                        _shttpd_do_cgi(c);
    632638                }
    633639#endif /* NO_CGI */
    634640#if !defined(NO_SSI)
    635         } else if (match_extension(path, c->ctx->options[OPT_SSI_EXTENSIONS])) {
    636                 if ((c->loc.chan.fd = my_open(path,
     641        } else if (_shttpd_match_extension(path,
     642            c->ctx->options[OPT_SSI_EXTENSIONS])) {
     643                if ((c->loc.chan.fd = _shttpd_open(path,
    637644                    O_RDONLY | O_BINARY, 0644)) == -1) {
    638                         send_server_error(c, 500, "SSI open error");
     645                        _shttpd_send_server_error(c, 500, "SSI open error");
    639646                } else {
    640                         do_ssi(c);
     647                        _shttpd_do_ssi(c);
    641648                }
    642649#endif /* NO_CGI */
    643650        } else if (c->ch.ims.v_time && st.st_mtime <= c->ch.ims.v_time) {
    644                 send_server_error(c, 304, "Not Modified");
    645         } else if ((c->loc.chan.fd = my_open(path,
     651                _shttpd_send_server_error(c, 304, "Not Modified");
     652        } else if ((c->loc.chan.fd = _shttpd_open(path,
    646653            O_RDONLY | O_BINARY, 0644)) != -1) {
    647                 get_file(c, &st);
     654                _shttpd_get_file(c, &st);
    648655        } else {
    649                 send_server_error(c, 500, "Internal Error");
     656                _shttpd_send_server_error(c, 500, "Internal Error");
    650657        }
    651658}
     
    657664
    658665        /* Set the request method */
    659         for (v = known_http_methods; v->ptr != NULL; v++)
     666        for (v = _shttpd_known_http_methods; v->ptr != NULL; v++)
    660667                if (!memcmp(c->rem.io.buf, v->ptr, v->len)) {
    661                         c->method = v - known_http_methods;
     668                        c->method = v - _shttpd_known_http_methods;
    662669                        break;
    663670                }
     
    674681        s = io_data(&c->rem.io);;
    675682        req_len = c->rem.headers_len =
    676             get_headers_len(s, io_data_len(&c->rem.io));
     683            _shttpd_get_headers_len(s, io_data_len(&c->rem.io));
    677684
    678685        if (req_len == 0 && io_space_len(&c->rem.io) == 0) {
    679686                io_clear(&c->rem.io);
    680                 send_server_error(c, 400, "Request is too big");
     687                _shttpd_send_server_error(c, 400, "Request is too big");
    681688        }
    682689
     
    684691                return;
    685692        } else if (req_len < 16) {      /* Minimal: "GET / HTTP/1.0\n\n" */
    686                 send_server_error(c, 400, "Bad request");
     693                _shttpd_send_server_error(c, 400, "Bad request");
    687694        } else if (set_request_method(c)) {
    688                 send_server_error(c, 501, "Method Not Implemented");
    689         } else if ((c->request = my_strndup(s, req_len)) == NULL) {
    690                 send_server_error(c, 500, "Cannot allocate request");
     695                _shttpd_send_server_error(c, 501, "Method Not Implemented");
     696        } else if ((c->request = _shttpd_strndup(s, req_len)) == NULL) {
     697                _shttpd_send_server_error(c, 500, "Cannot allocate request");
    691698        }
    692699
     
    727734        if (sscanf(p, "HTTP/%lu.%lu%n",
    728735            &c->major_version, &c->minor_version, &n) != 2 || p[n] != '\0') {
    729                 send_server_error(c, 400, "Bad HTTP version");
     736                _shttpd_send_server_error(c, 400, "Bad HTTP version");
    730737        } else if (c->major_version > 1 ||
    731738            (c->major_version == 1 && c->minor_version > 1)) {
    732                 send_server_error(c, 505, "HTTP version not supported");
     739                _shttpd_send_server_error(c, 505, "HTTP version not supported");
    733740        } else if (uri_len <= 0) {
    734                 send_server_error(c, 400, "Bad URI");
     741                _shttpd_send_server_error(c, 400, "Bad URI");
    735742        } else if ((c->uri = malloc(uri_len + 1)) == NULL) {
    736                 send_server_error(c, 500, "Cannot allocate URI");
     743                _shttpd_send_server_error(c, 500, "Cannot allocate URI");
    737744        } else {
    738                 my_strlcpy(c->uri, (char *) start, uri_len + 1);
    739                 parse_headers(c->headers,
     745                _shttpd_strlcpy(c->uri, (char *) start, uri_len + 1);
     746                _shttpd_parse_headers(c->headers,
    740747                    (c->request + req_len) - c->headers, &c->ch);
    741748
     
    762769
    763770        sa.len = sizeof(sa.u.sin);
    764         (void) set_non_blocking_mode(sock);
     771        (void) _shttpd_set_non_blocking_mode(sock);
    765772
    766773        if (getpeername(sock, &sa.u.sa, &sa.len)) {
    767                 elog(l, NULL, "add_socket: %s", strerror(errno));
     774                _shttpd_elog(l, NULL, "add_socket: %s", strerror(errno));
    768775#if !defined(NO_SSL)
    769776        } else if (is_ssl && (ssl = SSL_new(ctx->ssl_ctx)) == NULL) {
    770                 elog(l, NULL, "add_socket: SSL_new: %s", strerror(ERRNO));
     777                _shttpd_elog(l, NULL, "add_socket: SSL_new: %s", strerror(ERRNO));
    771778                (void) closesocket(sock);
    772779        } else if (is_ssl && SSL_set_fd(ssl, sock) == 0) {
    773                 elog(l, NULL, "add_socket: SSL_set_fd: %s", strerror(ERRNO));
     780                _shttpd_elog(l, NULL, "add_socket: SSL_set_fd: %s", strerror(ERRNO));
    774781                (void) closesocket(sock);
    775782                SSL_free(ssl);
     
    781788#endif /* NO_SSL */
    782789                (void) closesocket(sock);
    783                 elog(l, NULL, "add_socket: calloc: %s", strerror(ERRNO));
     790                _shttpd_elog(l, NULL, "add_socket: calloc: %s", strerror(ERRNO));
    784791        } else {
    785792                c->rem.conn     = c->loc.conn = c;
     
    787794                c->worker       = worker;
    788795                c->sa           = sa;
    789                 c->birth_time   = current_time;
    790                 c->expire_time  = current_time + EXPIRE_TIME;
     796                c->birth_time   = _shttpd_current_time;
     797                c->expire_time  = _shttpd_current_time + EXPIRE_TIME;
    791798
    792799                (void) getsockname(sock, &sa.u.sa, &sa.len);
    793800                c->loc_port = sa.u.sin.sin_port;
    794801
    795                 set_close_on_exec(sock);
     802                _shttpd_set_close_on_exec(sock);
    796803
    797804                c->loc.io_class = NULL;
    798805       
    799                 c->rem.io_class = &io_socket;
     806                c->rem.io_class = &_shttpd_io_socket;
    800807                c->rem.chan.sock = sock;
    801808
     
    807814#if !defined(NO_SSL)
    808815                if (is_ssl) {
    809                         c->rem.io_class = &io_ssl;
     816                        c->rem.io_class = &_shttpd_io_ssl;
    810817                        c->rem.chan.ssl.sock = sock;
    811818                        c->rem.chan.ssl.ssl = ssl;
    812                         ssl_handshake(&c->rem);
     819                        _shttpd_ssl_handshake(&c->rem);
    813820                }
    814821#endif /* NO_SSL */
     
    852859}
    853860
    854 static void
     861static int
    855862set_ports(struct shttpd_ctx *ctx, const char *p)
    856863{
     
    867874
    868875                if ((sock = shttpd_open_listening_port(port)) == -1) {
    869                         elog(E_FATAL, NULL, "cannot open port %d", port);
     876                        _shttpd_elog(E_LOG, NULL, "cannot open port %d", port);
     877                        goto fail;
     878                } else if (is_ssl && ctx->ssl_ctx == NULL) {
     879                        (void) closesocket(sock);
     880                        _shttpd_elog(E_LOG, NULL, "cannot add SSL socket, "
     881                            "please specify certificate file");
     882                        goto fail;
    870883                } else if ((l = calloc(1, sizeof(*l))) == NULL) {
    871884                        (void) closesocket(sock);
    872                         elog(E_FATAL, NULL, "cannot allocate listener");
    873                 } else if (is_ssl && ctx->ssl_ctx == NULL) {
    874                         (void) closesocket(sock);
    875                         elog(E_FATAL, NULL, "cannot add SSL socket, "
    876                             "please specify certificate file");
     885                        _shttpd_elog(E_LOG, NULL, "cannot allocate listener");
     886                        goto fail;
    877887                } else {
    878888                        l->is_ssl = is_ssl;
     
    883893                }
    884894        }
     895
     896        return (TRUE);
     897fail:
     898        free_list(&ctx->listeners, &listener_destructor);
     899        return (FALSE);
    885900}
    886901
     
    899914
    900915        /* Read from underlying channel */
    901         if( stream->io_class )
    902             n = stream->io_class->read(stream, io_space(&stream->io), len);
    903         else
    904             n = 0;
     916        assert(stream->io_class != NULL);
     917        n = stream->io_class->read(stream, io_space(&stream->io), len);
    905918
    906919        if (n > 0)
     
    909922                n = n;  /* Ignore EINTR and EAGAIN */
    910923        else if (!(stream->flags & FLAG_DONT_CLOSE))
    911                 stop_stream(stream);
     924                _shttpd_stop_stream(stream);
    912925
    913926        DBG(("read_stream (%d %s): read %d/%d/%lu bytes (errno %d)",
     
    925938                assert(stream->io.total <= stream->content_len);
    926939                if (stream->io.total == stream->content_len)
    927                         stop_stream(stream);
    928         }
    929 
    930         stream->conn->expire_time = current_time + EXPIRE_TIME;
     940                        _shttpd_stop_stream(stream);
     941        }
     942
     943        stream->conn->expire_time = _shttpd_current_time + EXPIRE_TIME;
    931944}
    932945
     
    940953
    941954        /* TODO: should be assert on CAN_WRITE flag */
    942         if( to->io_class )
    943             n = to->io_class->write(to, io_data(&from->io), len);
    944         else
    945             n = 0;
    946 
    947         to->conn->expire_time = current_time + EXPIRE_TIME;
     955        n = to->io_class->write(to, io_data(&from->io), len);
     956        to->conn->expire_time = _shttpd_current_time + EXPIRE_TIME;
    948957        DBG(("write_stream (%d %s): written %d/%d bytes (errno %d)",
    949958            to->conn->rem.chan.sock,
     
    955964                n = n;  /* Ignore EINTR and EAGAIN */
    956965        else if (!(to->flags & FLAG_DONT_CLOSE))
    957                 stop_stream(to);
     966                _shttpd_stop_stream(to);
    958967}
    959968
     
    970979
    971980        if (c->request != NULL && c->ctx->access_log != NULL)
    972                 log_access(c->ctx->access_log, c);
     981                _shttpd_log_access(c->ctx->access_log, c);
    973982
    974983        /* In inetd mode, exit if request is finished. */
     
    984993         */
    985994        do_close = (c->ch.connection.v_vec.len >= vec.len &&
    986             !my_strncasecmp(vec.ptr, c->ch.connection.v_vec.ptr, vec.len)) ||
     995            !_shttpd_strncasecmp(vec.ptr,c->ch.connection.v_vec.ptr,vec.len)) ||
    987996            (c->major_version < 1 ||
    988997            (c->major_version >= 1 && c->minor_version < 1));
     
    10031012                (void) memset(&c->ch, 0, sizeof(c->ch));
    10041013                io_clear(&c->loc.io);
    1005                 c->birth_time = current_time;
     1014                c->birth_time = _shttpd_current_time;
    10061015                if (io_data_len(&c->rem.io) > 0)
    10071016                        process_connection(c, 0, 0);
     
    10811090
    10821091        /* Check whether we should close this connection */
    1083         if ((current_time > c->expire_time) ||
     1092        if ((_shttpd_current_time > c->expire_time) ||
    10841093            (c->rem.flags & FLAG_CLOSED) ||
    10851094            ((c->loc.flags & FLAG_CLOSED) && !io_data_len(&c->loc.io)))
     
    11001109#if !defined(_WIN32)
    11011110        if (sock >= (int) FD_SETSIZE) {
    1102                 elog(E_LOG, NULL, "ctx %p: discarding "
     1111                _shttpd_elog(E_LOG, NULL, "ctx %p: discarding "
    11031112                    "socket %d, too busy", ctx, sock);
    11041113                (void) closesocket(sock);
     
    11061115#endif /* !_WIN32 */
    11071116                if (!is_allowed(ctx, sap)) {
    1108                 elog(E_LOG, NULL, "%s is not allowed to connect",
     1117                _shttpd_elog(E_LOG, NULL, "%s is not allowed to connect",
    11091118                    inet_ntoa(sap->u.sin.sin_addr));
    11101119                (void) closesocket(sock);
     
    11421151}
    11431152
    1144 static void
     1153static int
    11451154multiplex_worker_sockets(const struct worker *worker, int *max_fd,
    1146                 fd_set *read_set, fd_set *write_set, int *milliseconds)
     1155                fd_set *read_set, fd_set *write_set)
    11471156{
    11481157        struct llhead   *lp;
    11491158        struct conn     *c;
     1159        int             nowait = FALSE;
    11501160
    11511161        /* Add control socket */
     
    11661176                 */
    11671177                if (io_space_len(&c->loc.io) && (c->loc.flags & FLAG_R) &&
    1168                     c->loc.io_class == &io_cgi)
     1178                    c->loc.io_class == &_shttpd_io_cgi)
    11691179                        add_to_set(c->loc.chan.fd, read_set, max_fd);
    11701180
     
    11741184                 */
    11751185                if (io_data_len(&c->rem.io) && (c->loc.flags & FLAG_W) &&
    1176                     c->loc.io_class == &io_cgi)
     1186                    c->loc.io_class == &_shttpd_io_cgi)
    11771187                        add_to_set(c->loc.chan.fd, write_set, max_fd);
    11781188#endif /* NO_CGI */
     
    11901200                if (io_space_len(&c->loc.io) && (c->loc.flags & FLAG_R) &&
    11911201                    (c->loc.flags & FLAG_ALWAYS_READY))
    1192                         *milliseconds = 0;
     1202                        nowait = TRUE;
    11931203               
    11941204                if (io_data_len(&c->rem.io) && (c->loc.flags & FLAG_W) &&
    11951205                    (c->loc.flags & FLAG_ALWAYS_READY))
    1196                         *milliseconds = 0;
    1197         }
    1198 }
     1206                        nowait = TRUE;
     1207        }
     1208
     1209        return (nowait);
     1210}
     1211
     1212int
     1213shttpd_join(struct shttpd_ctx *ctx,
     1214                fd_set *read_set, fd_set *write_set, int *max_fd)
     1215{
     1216        struct llhead   *lp;
     1217        struct listener *l;
     1218        int             nowait = FALSE;
     1219
     1220        /* Add listening sockets to the read set */
     1221        LL_FOREACH(&ctx->listeners, lp) {
     1222                l = LL_ENTRY(lp, struct listener, link);
     1223                add_to_set(l->sock, read_set, max_fd);
     1224                DBG(("FD_SET(%d) (listening)", l->sock));
     1225        }
     1226
     1227        if (num_workers(ctx) == 1)
     1228                nowait = multiplex_worker_sockets(first_worker(ctx), max_fd,
     1229                    read_set, write_set);
     1230
     1231        return (nowait);
     1232}
     1233
    11991234
    12001235static void
     
    12181253                                break;
    12191254                        default:
    1220                                 elog(E_FATAL, NULL, "ctx %p: ctl cmd %d",
     1255                                _shttpd_elog(E_FATAL, NULL, "ctx %p: ctl cmd %d",
    12211256                                    worker->ctx, cmd);
    12221257                                break;
     
    12261261        LL_FOREACH_SAFE(&worker->connections, lp, tmp) {
    12271262                c = LL_ENTRY(lp, struct conn, link);
    1228                 process_connection(c, FD_ISSET(c->rem.chan.fd, read_set),
     1263                process_connection(c, FD_ISSET(c->rem.chan.sock, read_set),
     1264                    c->loc.io_class != NULL &&
    12291265                    ((c->loc.flags & FLAG_ALWAYS_READY)
    12301266#if !defined(NO_CGI)
    1231                     || (c->loc.io_class == &io_cgi &&
     1267                    || (c->loc.io_class == &_shttpd_io_cgi &&
    12321268                     FD_ISSET(c->loc.chan.fd, read_set))
    12331269#endif /* NO_CGI */
     
    12481284        struct usa      sa;
    12491285
    1250         current_time = time(0);
     1286        _shttpd_current_time = time(0);
    12511287        FD_ZERO(&read_set);
    12521288        FD_ZERO(&write_set);
    12531289
    1254         /* Add listening sockets to the read set */
    1255         LL_FOREACH(&ctx->listeners, lp) {
    1256                 l = LL_ENTRY(lp, struct listener, link);
    1257                 add_to_set(l->sock, &read_set, &max_fd);
    1258                 DBG(("FD_SET(%d) (listening)", l->sock));
    1259         }
    1260 
    1261         if (num_workers(ctx) == 1)
    1262                 multiplex_worker_sockets(first_worker(ctx), &max_fd,
    1263                                 &read_set, &write_set, &milliseconds);
     1290        if (shttpd_join(ctx, &read_set, &write_set, &max_fd))
     1291                milliseconds = 0;
    12641292
    12651293        if (do_select(max_fd, &read_set, &write_set, milliseconds) < 0)
     
    12951323        free_list(&ctx->listeners, listener_destructor);
    12961324#if !defined(NO_SSI)
    1297         free_list(&ctx->ssi_funcs, ssi_func_destructor);
     1325        free_list(&ctx->ssi_funcs, _shttpd_ssi_func_destructor);
    12981326#endif /* !NO_SSI */
    12991327
     
    13481376
    13491377        (void) closesocket(sock);
    1350         (void) set_non_blocking_mode(sp[0]);
    1351         (void) set_non_blocking_mode(sp[1]);
     1378        (void) _shttpd_set_non_blocking_mode(sp[0]);
     1379        (void) _shttpd_set_non_blocking_mode(sp[1]);
    13521380
    13531381#ifndef _WIN32
     
    13611389static int isbyte(int n) { return (n >= 0 && n <= 255); }
    13621390
    1363 static void
     1391static int
    13641392set_inetd(struct shttpd_ctx *ctx, const char *flag)
    13651393{
    13661394        ctx = NULL; /* Unused */
    13671395
    1368         if (is_true(flag)) {
     1396        if (_shttpd_is_true(flag)) {
    13691397                shttpd_set_option(ctx, "ports", NULL);
    13701398                (void) freopen("/dev/null", "a", stderr);
    13711399                add_socket(first_worker(ctx), 0, 0);
    13721400        }
    1373 }
    1374 
    1375 static void
     1401
     1402        return (TRUE);
     1403}
     1404
     1405static int
    13761406set_uid(struct shttpd_ctx *ctx, const char *uid)
    13771407{
     
    13821412#if !defined(_WIN32)
    13831413        if ((pw = getpwnam(uid)) == NULL)
    1384                 elog(E_FATAL, 0, "%s: unknown user [%s]", __func__, uid);
     1414                _shttpd_elog(E_FATAL, 0, "%s: unknown user [%s]", __func__, uid);
    13851415        else if (setgid(pw->pw_gid) == -1)
    1386                 elog(E_FATAL, NULL, "%s: setgid(%s): %s",
     1416                _shttpd_elog(E_FATAL, NULL, "%s: setgid(%s): %s",
    13871417                    __func__, uid, strerror(errno));
    13881418        else if (setuid(pw->pw_uid) == -1)
    1389                 elog(E_FATAL, NULL, "%s: setuid(%s): %s",
     1419                _shttpd_elog(E_FATAL, NULL, "%s: setuid(%s): %s",
    13901420                    __func__, uid, strerror(errno));
    13911421#endif /* !_WIN32 */
    1392 }
    1393 
    1394 static void
     1422        return (TRUE);
     1423}
     1424
     1425static int
    13951426set_acl(struct shttpd_ctx *ctx, const char *s)
    13961427{
     
    13981429        char            flag;
    13991430        int             len, a, b, c, d, n, mask;
    1400         struct llhead   *lp, *tmp;
    14011431
    14021432        /* Delete the old ACLs if any */
    1403         LL_FOREACH_SAFE(&ctx->acl, lp, tmp)
    1404                 free(LL_ENTRY(lp, struct acl, link));
     1433        free_list(&ctx->acl, acl_destructor);
    14051434
    14061435        FOR_EACH_WORD_IN_LIST(s, len) {
     
    14091438
    14101439                if (sscanf(s, "%c%d.%d.%d.%d%n",&flag,&a,&b,&c,&d,&n) != 5) {
    1411                         elog(E_FATAL, NULL, "[%s]: subnet must be "
     1440                        _shttpd_elog(E_FATAL, NULL, "[%s]: subnet must be "
    14121441                            "[+|-]x.x.x.x[/x]", s);
    14131442                } else if (flag != '+' && flag != '-') {
    1414                         elog(E_FATAL, NULL, "flag must be + or -: [%s]", s);
     1443                        _shttpd_elog(E_FATAL, NULL, "flag must be + or -: [%s]", s);
    14151444                } else if (!isbyte(a)||!isbyte(b)||!isbyte(c)||!isbyte(d)) {
    1416                         elog(E_FATAL, NULL, "bad ip address: [%s]", s);
     1445                        _shttpd_elog(E_FATAL, NULL, "bad ip address: [%s]", s);
    14171446                } else  if ((acl = malloc(sizeof(*acl))) == NULL) {
    1418                         elog(E_FATAL, NULL, "%s", "cannot malloc subnet");
     1447                        _shttpd_elog(E_FATAL, NULL, "%s", "cannot malloc subnet");
    14191448                } else if (sscanf(s + n, "/%d", &mask) == 0) {
    14201449                        /* Do nothing, no mask specified */
    14211450                } else if (mask < 0 || mask > 32) {
    1422                         elog(E_FATAL, NULL, "bad subnet mask: %d [%s]", n, s);
     1451                        _shttpd_elog(E_FATAL, NULL, "bad subnet mask: %d [%s]", n, s);
    14231452                }
    14241453
     
    14281457                LL_TAIL(&ctx->acl, &acl->link);
    14291458        }
     1459
     1460        return (TRUE);
    14301461}
    14311462
     
    14341465 * Dynamically load SSL library. Set up ctx->ssl_ctx pointer.
    14351466 */
    1436 static void
     1467static int
    14371468set_ssl(struct shttpd_ctx *ctx, const char *pem)
    14381469{
     
    14401471        void            *lib;
    14411472        struct ssl_func *fp;
     1473        int             retval = FALSE;
    14421474
    14431475        /* Load SSL library dynamically */
    1444         if ((lib = dlopen(SSL_LIB, RTLD_LAZY)) == NULL)
    1445                 elog(E_FATAL, NULL, "set_ssl: cannot load %s", SSL_LIB);
     1476        if ((lib = dlopen(SSL_LIB, RTLD_LAZY)) == NULL) {
     1477                _shttpd_elog(E_LOG, NULL, "set_ssl: cannot load %s", SSL_LIB);
     1478                return (FALSE);
     1479        }
    14461480
    14471481        for (fp = ssl_sw; fp->name != NULL; fp++)
    1448                 if ((fp->ptr.v_void = dlsym(lib, fp->name)) == NULL)
    1449                         elog(E_FATAL, NULL,"set_ssl: cannot find %s", fp->name);
     1482                if ((fp->ptr.v_void = dlsym(lib, fp->name)) == NULL) {
     1483                        _shttpd_elog(E_LOG, NULL,"set_ssl: cannot find %s", fp->name);
     1484                        return (FALSE);
     1485                }
    14501486
    14511487        /* Initialize SSL crap */
     
    14531489
    14541490        if ((CTX = SSL_CTX_new(SSLv23_server_method())) == NULL)
    1455                 elog(E_FATAL, NULL, "SSL_CTX_new error");
     1491                _shttpd_elog(E_LOG, NULL, "SSL_CTX_new error");
    14561492        else if (SSL_CTX_use_certificate_file(CTX, pem, SSL_FILETYPE_PEM) == 0)
    1457                 elog(E_FATAL, NULL, "cannot open %s", pem);
     1493                _shttpd_elog(E_LOG, NULL, "cannot open %s", pem);
    14581494        else if (SSL_CTX_use_PrivateKey_file(CTX, pem, SSL_FILETYPE_PEM) == 0)
    1459                 elog(E_FATAL, NULL, "cannot open %s", pem);
     1495                _shttpd_elog(E_LOG, NULL, "cannot open %s", pem);
     1496        else
     1497                retval = TRUE;
     1498
    14601499        ctx->ssl_ctx = CTX;
     1500
     1501        return (retval);
    14611502}
    14621503#endif /* NO_SSL */
    14631504
    1464 static void
     1505static int
    14651506open_log_file(FILE **fpp, const char *path)
    14661507{
     1508        int     retval = TRUE;
     1509
    14671510        if (*fpp != NULL)
    14681511                (void) fclose(*fpp);
     
    14711514                *fpp = NULL;
    14721515        } else if ((*fpp = fopen(path, "a")) == NULL) {
    1473                 elog(E_FATAL, NULL, "cannot open log file %s: %s",
     1516                _shttpd_elog(E_LOG, NULL, "cannot open log file %s: %s",
    14741517                    path, strerror(errno));
    1475         }
    1476 }
    1477 
    1478 static void set_alog(struct shttpd_ctx *ctx, const char *path) {
    1479         open_log_file(&ctx->access_log, path);
    1480 }
    1481 
    1482 static void set_elog(struct shttpd_ctx *ctx, const char *path) {
    1483         open_log_file(&ctx->error_log, path);
     1518                retval = FALSE;
     1519        }
     1520
     1521        return (retval);
     1522}
     1523
     1524static int set_alog(struct shttpd_ctx *ctx, const char *path) {
     1525        return (open_log_file(&ctx->access_log, path));
     1526}
     1527
     1528static int set_elog(struct shttpd_ctx *ctx, const char *path) {
     1529        return (open_log_file(&ctx->error_log, path));
    14841530}
    14851531
    14861532static void show_cfg_page(struct shttpd_arg *arg);
    14871533
    1488 static void
     1534static int
    14891535set_cfg_uri(struct shttpd_ctx *ctx, const char *uri)
    14901536{
     
    14931539        if (uri != NULL)
    14941540                shttpd_register_uri(ctx, uri, &show_cfg_page, ctx);
     1541
     1542        return (TRUE);
    14951543}
    14961544
     
    15011549
    15021550        if ((worker = calloc(1, sizeof(*worker))) == NULL)
    1503                 elog(E_FATAL, NULL, "Cannot allocate worker");
     1551                _shttpd_elog(E_FATAL, NULL, "Cannot allocate worker");
    15041552        LL_INIT(&worker->connections);
    15051553        worker->ctx = ctx;
     
    15201568        FD_ZERO(&write_set);
    15211569
    1522         multiplex_worker_sockets(worker, &max_fd,
    1523                         &read_set, &write_set, &milliseconds);
     1570        if (multiplex_worker_sockets(worker, &max_fd, &read_set, &write_set))
     1571                milliseconds = 0;
    15241572
    15251573        if (do_select(max_fd, &read_set, &write_set, milliseconds) < 0)
     
    15411589}
    15421590
    1543 static void
     1591static int
    15441592set_workers(struct shttpd_ctx *ctx, const char *value)
    15451593{
     
    15711619                }
    15721620        }
     1621
     1622        return (TRUE);
    15731623}
    15741624#endif /* NO_THREADS */
     
    15791629        const char      *description;   /* Description                  */
    15801630        const char      *default_value; /* Default option value         */
    1581         void (*setter)(struct shttpd_ctx *, const char *);
     1631        int (*setter)(struct shttpd_ctx *, const char *);
    15821632} known_options[] = {
    15831633        {OPT_ROOT, "root", "\tWeb root directory", ".", NULL},
     
    16031653#ifdef _WIN32
    16041654        {OPT_SERVICE, "service", "Manage WinNNT service (install"
    1605             "|uninstall)", NULL, set_nt_service},
     1655            "|uninstall)", NULL, _shttpd_set_nt_service},
    16061656        {OPT_HIDE, "systray", "Hide console, show icon on systray",
    1607                 "no", set_systray},
     1657                "no", _shttpd_set_systray},
    16081658#else
    16091659        {OPT_INETD, "inetd", "Inetd mode", "no", set_inetd},
     
    16301680                        return (known_options + i);
    16311681
    1632         elog(E_FATAL, NULL, "no such option: [%s]", opt_name);
     1682        _shttpd_elog(E_FATAL, NULL, "no such option: [%s]", opt_name);
    16331683
    16341684        /* UNREACHABLE */
     
    16361686}
    16371687
    1638 void
     1688int
    16391689shttpd_set_option(struct shttpd_ctx *ctx, const char *opt, const char *val)
    16401690{
    16411691        const struct opt        *o = find_opt(opt);
     1692        int                     retval = TRUE;
    16421693
    16431694        /* Call option setter first, so it can use both new and old values */
    16441695        if (o->setter != NULL)
    1645                 o->setter(ctx, val);
     1696                retval = o->setter(ctx, val);
    16461697
    16471698        /* Free old value if any */
     
    16501701       
    16511702        /* Set new option value */
    1652         ctx->options[o->index] = val ? my_strdup(val) : NULL;
     1703        ctx->options[o->index] = val ? _shttpd_strdup(val) : NULL;
     1704
     1705        return (retval);
    16531706}
    16541707
     
    17021755 */
    17031756void
    1704 usage(const char *prog)
     1757_shttpd_usage(const char *prog)
    17051758{
    17061759        const struct opt        *o;
     
    17321785        if (ctx->options[o->index] != NULL)
    17331786                free(ctx->options[o->index]);
    1734         ctx->options[o->index] = my_strdup(value);
     1787        ctx->options[o->index] = _shttpd_strdup(value);
    17351788}
    17361789
     
    17471800        for (i = 1; argv[i] != NULL && argv[i][0] == '-'; i += 2)
    17481801                if (argv[i + 1] == NULL)
    1749                         usage(argv[0]);
     1802                        _shttpd_usage(argv[0]);
    17501803
    17511804        if (argv[i] != NULL && argv[i + 1] != NULL) {
    17521805                /* More than one non-option arguments are given w*/
    1753                 usage(argv[0]);
     1806                _shttpd_usage(argv[0]);
    17541807        } else if (argv[i] != NULL) {
    17551808                /* Just one non-option argument is given, this is config file */
     
    17581811                /* No config file specified. Look for one where shttpd lives */
    17591812                if ((p = strrchr(argv[0], DIRSEP)) != 0) {
    1760                         my_snprintf(path, sizeof(path), "%.*s%s",
     1813                        _shttpd_snprintf(path, sizeof(path), "%.*s%s",
    17611814                            p - argv[0] + 1, argv[0], config_file);
    17621815                        config_file = path;
     
    17681821        /* If config file was set in command line and open failed, exit */
    17691822        if (fp == NULL && argv[i] != NULL)
    1770                 elog(E_FATAL, NULL, "cannot open config file %s: %s",
     1823                _shttpd_elog(E_FATAL, NULL, "cannot open config file %s: %s",
    17711824                    config_file, strerror(errno));
    17721825
    17731826        if (fp != NULL) {
    17741827
    1775                 elog(E_LOG, NULL, "Loading config file %s", config_file);
     1828                _shttpd_elog(E_LOG, NULL, "Loading config file %s", config_file);
    17761829
    17771830                /* Loop over the lines in config file */
     
    17851838
    17861839                        if (sscanf(line, "%s %[^\n#]", opt, val) != 2)
    1787                                 elog(E_FATAL, NULL, "line %d in %s is invalid",
     1840                                _shttpd_elog(E_FATAL, NULL, "line %d in %s is invalid",
    17881841                                    line_no, config_file);
    17891842
     
    18071860
    18081861        if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
    1809                 elog(E_FATAL, NULL, "cannot allocate shttpd context");
     1862                _shttpd_elog(E_FATAL, NULL, "cannot allocate shttpd context");
    18101863
    18111864        LL_INIT(&ctx->registered_uris);
     
    18191872        for (o = known_options; o->name != NULL; o++)
    18201873                ctx->options[o->index] = o->default_value ?
    1821                         my_strdup(o->default_value) : NULL;
     1874                        _shttpd_strdup(o->default_value) : NULL;
    18221875
    18231876        /* Second and third passes: config file and argv */
     
    18281881        for (o = known_options; o->name != NULL; o++)
    18291882                if (o->setter && ctx->options[o->index] != NULL)
    1830                         o->setter(ctx, ctx->options[o->index]);
    1831 
    1832         current_time = time(NULL);
    1833         tm = localtime(&current_time);
    1834         tz_offset = 0;
     1883                        if (o->setter(ctx, ctx->options[o->index]) == FALSE) {
     1884                                shttpd_fini(ctx);
     1885                                return (NULL);
     1886                        }
     1887
     1888        _shttpd_current_time = time(NULL);
     1889        tm = localtime(&_shttpd_current_time);
     1890        _shttpd_tz_offset = 0;
    18351891
    18361892        if (num_workers(ctx) == 1)
Note: See TracChangeset for help on using the changeset viewer.