Annotation of embedaddon/libpdel/http/test/main.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (c) 2001-2002 Packet Design, LLC.
                      4:  * All rights reserved.
                      5:  * 
                      6:  * Subject to the following obligations and disclaimer of warranty,
                      7:  * use and redistribution of this software, in source or object code
                      8:  * forms, with or without modifications are expressly permitted by
                      9:  * Packet Design; provided, however, that:
                     10:  * 
                     11:  *    (i)  Any and all reproductions of the source or object code
                     12:  *         must include the copyright notice above and the following
                     13:  *         disclaimer of warranties; and
                     14:  *    (ii) No rights are granted, in any manner or form, to use
                     15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
                     16:  *         on advertising, endorsements, or otherwise except as such
                     17:  *         appears in the above copyright notice or in the software.
                     18:  * 
                     19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
                     20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
                     21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
                     22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
                     23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
                     24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
                     25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
                     26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
                     27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
                     28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
                     29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
                     30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
                     31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
                     32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
                     33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
                     35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
                     36:  * THE POSSIBILITY OF SUCH DAMAGE.
                     37:  *
                     38:  * Author: Archie Cobbs <archie@freebsd.org>
                     39:  */
                     40: 
                     41: #include <sys/stat.h>
                     42: #include <sys/param.h>
                     43: 
                     44: #include <stdio.h>
                     45: #include <stdlib.h>
                     46: #include <signal.h>
                     47: #include <stdarg.h>
                     48: #include <string.h>
                     49: #include <unistd.h>
                     50: #include <errno.h>
                     51: #include <assert.h>
                     52: #include <netdb.h>
                     53: #include <err.h>
                     54: #include <regex.h>
                     55: #include <pthread.h>
                     56: 
                     57: #include <netinet/in_systm.h>
                     58: #include <netinet/in.h>
                     59: #include <arpa/inet.h>
                     60: 
                     61: #include <openssl/ssl.h>
                     62: 
                     63: #include <pdel/structs/structs.h>
                     64: #include <pdel/structs/type/array.h>
                     65: 
                     66: #include <pdel/tmpl/tmpl.h>
                     67: #include <pdel/util/typed_mem.h>
                     68: #include <pdel/util/pevent.h>
                     69: 
                     70: #include <pdel/http/http_defs.h>
                     71: #include <pdel/http/http_server.h>
                     72: #include <pdel/http/http_servlet.h>
                     73: #include <pdel/http/servlet/tmpl.h>
                     74: #include <pdel/http/servlet/file.h>
                     75: #include <pdel/http/servlet/basicauth.h>
                     76: #include <pdel/http/servlet/redirect.h>
                     77: #include <pdel/http/servlet/cookieauth.h>
                     78: 
                     79: #define DEMO_MEM_TYPE          "demo"
                     80: #define DEMO_COOKIE_NAME       "demo_cookie"
                     81: #define TMPL_MEM_TYPE          "tmpl"
                     82: #define NUM_IN_CACHE           2
                     83: #define CACHE_TIMEOUT_SECS     10
                     84: #define NUM_CACHE_LOOP         10
                     85: #define PATH_KERNEL            "/kernel"
                     86: 
                     87: #ifndef MIN
                     88: #define MIN(a, b)      ((a) > (b) ? (a) : (b))
                     89: #endif
                     90: 
                     91: /*
                     92:  * Servlets
                     93:  */
                     94: static struct  http_servlet *demo_servlet_create(void);
                     95: static struct  http_servlet *cgi_servlet_create(void);
                     96: static struct  http_servlet *getkernel_servlet_create(void);
                     97: 
                     98: /*
                     99:  * Internal functions
                    100:  */
                    101: 
                    102: static http_logger_t           demo_logger;
                    103: 
                    104: static tmpl_handler_t          demo_tmpl_handler;
                    105: static tmpl_errfmtr_t          demo_tmpl_errfmtr;
                    106: 
                    107: static http_servlet_basicauth_t        demo_basicauth;
                    108: 
                    109: static http_servlet_cookieauth_reqd_t  demo_auth_reqd;
                    110: 
                    111: static void    demo_file_upload(struct http_request *req,
                    112:                        struct http_response *resp, FILE *op);
                    113: static int     demo_client(struct pevent_ctx *ctx, int nurls,
                    114:                        char **urls, int count);
                    115: 
                    116: /* SSL typed_mem(3) wrappers */
                    117: static void    *ssl_malloc(size_t size);
                    118: static void    *ssl_realloc(void *mem, size_t size);
                    119: static void    ssl_free(void *mem);
                    120: 
                    121: static void    usage(void);
                    122: 
                    123: /*
                    124:  * Internal variables
                    125:  */
                    126: 
                    127: /* SSL info */
                    128: static const struct http_server_ssl ssl_info = {
                    129:        "demo.crt",                     /* SSL x509 certificate file */
                    130:        "demo.key",                     /* SSL RSA private key file */
                    131:        NULL                            /* no password for private key needed */
                    132: };
                    133: 
                    134: static const   char *redirect_url;
                    135: static const   struct in_addr zero_ip;
                    136: static pid_t   main_pid;
                    137: 
                    138: static const   u_char demo_id[] = { 'd', 'e', 'm', 'o' };
                    139: 
                    140: static const   char *vhost = NULL;
                    141: static const   struct http_server_ssl *ssl = NULL;
                    142: static int     port = 0;
                    143: 
                    144: static struct  http_servlet *cookieauth_servlet;
                    145: 
                    146: /* Info for "demo.tmpl" template servlet */
                    147: static struct http_servlet_tmpl_info tmpl_servlet_info = {
                    148:        "demo.tmpl",                    /* pathname of template file */
                    149:        NULL,                           /* guess the mime type for me */
                    150:        NULL,                           /* guess the mime encoding for me */
                    151:        demo_logger,                    /* error logging routine */
                    152:        {                               /* info required by tmpl library */
                    153:                TMPL_SKIP_NL_WHITE,             /* flags for tmpl_execute() */
                    154:                TMPL_MEM_TYPE,                  /* tmpl string typed mem type */
                    155:                demo_tmpl_handler,              /* handler for custom @funcs */
                    156:                demo_tmpl_errfmtr,              /* handler for errors */
                    157:                NULL,                           /* opaque user cookie */
                    158:        }
                    159: };
                    160: 
                    161: /* Info for "logon.tmpl" template servlet */
                    162: static struct http_servlet_tmpl_info logon_servlet_info = {
                    163:        "logon.tmpl",                   /* pathname of template file */
                    164:        NULL,                           /* guess the mime type for me */
                    165:        NULL,                           /* guess the mime encoding for me */
                    166:        demo_logger,                    /* error logging routine */
                    167:        {                               /* info required by tmpl library */
                    168:                TMPL_SKIP_NL_WHITE,             /* flags for tmpl_execute() */
                    169:                TMPL_MEM_TYPE,                  /* tmpl string typed mem type */
                    170:                demo_tmpl_handler,              /* handler for custom @funcs */
                    171:                demo_tmpl_errfmtr,              /* handler for errors */
                    172:                NULL,                           /* opaque user cookie */
                    173:        }
                    174: };
                    175: 
                    176: /* Info for "vhost.tmpl" template servlet */
                    177: static struct http_servlet_tmpl_info vhost_servlet_info = {
                    178:        "vhost.tmpl",                   /* pathname of template file */
                    179:        NULL,                           /* guess the mime type for me */
                    180:        NULL,                           /* guess the mime encoding for me */
                    181:        demo_logger,                    /* error logging routine */
                    182:        {                               /* info required by tmpl library */
                    183:                TMPL_SKIP_NL_WHITE,             /* flags for tmpl_execute() */
                    184:                TMPL_MEM_TYPE,                  /* tmpl string typed mem type */
                    185:                demo_tmpl_handler,              /* handler for custom @funcs */
                    186:                demo_tmpl_errfmtr,              /* handler for errors */
                    187:                NULL,                           /* opaque user cookie */
                    188:        }
                    189: };
                    190: 
                    191: /* Info for BIND docs file servlet */
                    192: static struct http_servlet_file_info bind_servlet_info = {
                    193:        "/usr/share/doc/bind/html",     /* document root for this servlet */
                    194:        0,                              /* don't allow escape from docroot */
                    195:        NULL,                           /* derive filename from URL */
                    196:        "/file",                        /* URL prefix to strip from pathname */
                    197:        NULL,                           /* guess the mime type for me */
                    198:        NULL,                           /* guess the mime encoding for me */
                    199:        demo_logger,                    /* error logging routine */
                    200:        NULL,                           /* don't hide any files */
                    201:        { }                             /* don't support templates */
                    202: };
                    203: 
                    204: /*
                    205:  * Start a HTTP server.
                    206:  */
                    207: int
                    208: main(int argc, char **argv)
                    209: {
                    210:        struct pevent_ctx *ctx;
                    211:        char hostname[255] = { '\0' };
                    212:        struct http_servlet *servlet;
                    213:        struct http_server *server;
                    214:        int do_client = 0;
                    215:        sigset_t sigs;
                    216:        int count = 1;
                    217:        int sig;
                    218:        int ret;
                    219:        int ch;
                    220: 
                    221:        /* Parse command line arguments */
                    222:        while ((ch = getopt(argc, argv, "sp:c:r:h:v:")) != -1) {
                    223:                switch (ch) {
                    224:                case 'c':
                    225:                        count = atoi(optarg);
                    226:                        break;
                    227:                case 'h':
                    228:                        snprintf(hostname, sizeof(hostname), "%s", optarg);
                    229:                        break;
                    230:                case 's':
                    231:                        ssl = &ssl_info;
                    232:                        break;
                    233:                case 'p':
                    234:                        port = atoi(optarg);
                    235:                        break;
                    236:                case 'r':
                    237:                        redirect_url = optarg;
                    238:                        break;
                    239:                case 'v':
                    240:                        vhost = optarg;
                    241:                        break;
                    242:                default:
                    243:                        usage();
                    244:                }
                    245:        }
                    246:        argc -= optind;
                    247:        argv += optind;
                    248:        switch (argc) {
                    249:        default:
                    250:                do_client = 1;
                    251:                break;
                    252:        case 0:
                    253:                break;
                    254:        }
                    255:        if (port == 0)
                    256:                port = (ssl != NULL) ? 443 : 80;
                    257:        if (*hostname == '\0') {
                    258:                if (gethostname(hostname, sizeof(hostname)) == -1)
                    259:                        err(1, "gethostname");
                    260:                hostname[sizeof(hostname) - 1] = '\0';
                    261:        }
                    262: 
                    263:        /* Make OpenSSL use our malloc/free wrappers */
                    264:        if (ssl != NULL) {
                    265:                ret = CRYPTO_set_mem_functions(ssl_malloc,
                    266:                    ssl_realloc, ssl_free);
                    267:                assert(ret);
                    268:                ret = CRYPTO_set_locked_mem_functions(ssl_malloc, ssl_free);
                    269:                assert(ret);
                    270:        }
                    271:        main_pid = getpid();
                    272: 
                    273:        /* Enable typed memory */
                    274:        if (typed_mem_enable() == -1)
                    275:                err(1, "typed_mem_enable");
                    276: 
                    277:        /* Block SIGPIPE */
                    278:        (void)signal(SIGPIPE, SIG_IGN);
                    279: 
                    280:        /* Get event context */
                    281:        if ((ctx = pevent_ctx_create("demo_server.ctx", NULL)) == NULL)
                    282:                err(1, "pevent_ctx_create");
                    283: 
                    284:        /* If client mode, do that */
                    285:        if (do_client) {
                    286:                demo_client(ctx, argc, argv, count);
                    287:                goto shutdown;
                    288:        }
                    289: 
                    290:        /* Start HTTP server */
                    291:        printf("demo_server: starting http server on port %d, SSL %sabled\n",
                    292:            port, ssl ? "en" : "dis");
                    293:        if ((server = http_server_start(ctx, zero_ip,
                    294:            port, ssl, "Demo/1.0", demo_logger)) == NULL)
                    295:                err(1, "http_server_start");
                    296: 
                    297:        /* Register default virtual host servlet if vhost defined */
                    298:        if (vhost != NULL) {
                    299:                /* Register "vhost.tmpl" servlet */
                    300:                if ((servlet = http_servlet_tmpl_create(
                    301:                    &vhost_servlet_info)) == NULL)
                    302:                        err(1, "http_servlet_tmpl_create");
                    303:                if (http_server_register_servlet(server,
                    304:                    servlet, NULL, "^/", 0) == -1)
                    305:                        err(1, "http_server_register_servlet");
                    306:        }
                    307: 
                    308:        /* Register redirect servlet */
                    309:        if (redirect_url != NULL) {
                    310:                if ((servlet = http_servlet_redirect_create(redirect_url,
                    311:                    HTTP_SERVLET_REDIRECT_NO_APPEND)) == NULL)
                    312:                        err(1, "redirect_servlet_create");
                    313:                if (http_server_register_servlet(server,
                    314:                    servlet, vhost, "^/redirect", 0) == -1)
                    315:                        err(1, "http_server_register_servlet");
                    316:        }
                    317: 
                    318:        /* Register cookie auth servlet */
                    319:        {
                    320:                char logurl[128];
                    321: 
                    322:                if ((ssl && port == 443) || (!ssl && port == 80)) {
                    323:                        snprintf(logurl, sizeof(logurl),
                    324:                            "http%s://%s/logon", ssl ? "s" : "", hostname);
                    325:                } else {
                    326:                        snprintf(logurl, sizeof(logurl),
                    327:                            "http%s://%s:%u/logon", ssl ? "s" : "",
                    328:                            hostname, port);
                    329:                }
                    330:                if ((cookieauth_servlet = http_servlet_cookieauth_create(
                    331:                    logurl, HTTP_SERVLET_REDIRECT_APPEND_URL,
                    332:                    demo_auth_reqd, NULL, NULL, "demo.key", demo_id,
                    333:                    sizeof(demo_id), DEMO_COOKIE_NAME)) == NULL)
                    334:                        err(1, "http_servlet_cookieauth_create");
                    335:                if (http_server_register_servlet(server,
                    336:                    cookieauth_servlet, vhost, "^/.*", -20) == -1)
                    337:                        err(1, "http_server_register_servlet");
                    338:        }
                    339: 
                    340:        /* Register logon page */
                    341:        if ((servlet = http_servlet_tmpl_create(&logon_servlet_info)) == NULL)
                    342:                err(1, "http_servlet_tmpl_create");
                    343:        if (http_server_register_servlet(server,
                    344:            servlet, vhost, "^/logon$", 0) == -1)
                    345:                err(1, "http_server_register_servlet");
                    346: 
                    347:        /* Register demo servlet */
                    348:        if ((servlet = demo_servlet_create()) == NULL)
                    349:                err(1, "demo_servlet_create");
                    350:        if (http_server_register_servlet(server,
                    351:            servlet, vhost, "^/$", 0) == -1)
                    352:                err(1, "http_server_register_servlet");
                    353: 
                    354:        /* Register "demo.tmpl" servlet */
                    355:        if ((servlet = http_servlet_tmpl_create(&tmpl_servlet_info)) == NULL)
                    356:                err(1, "http_servlet_tmpl_create");
                    357:        if (http_server_register_servlet(server,
                    358:            servlet, vhost, "^/tmpl$", 0) == -1)
                    359:                err(1, "http_server_register_servlet");
                    360: 
                    361:        /* Register authorization servlet */
                    362:        if ((servlet = http_servlet_basicauth_create(
                    363:            demo_basicauth, NULL, NULL)) == NULL)
                    364:                err(1, "http_servlet_basicauth_create");
                    365:        if (http_server_register_servlet(server,
                    366:            servlet, vhost, "^/[^l].*$", -10) == -1)
                    367:                err(1, "http_server_register_servlet");
                    368: 
                    369:        /* Register BIND docs servlet */
                    370:        if ((servlet = http_servlet_file_create(&bind_servlet_info)) == NULL)
                    371:                err(1, "http_servlet_file_create");
                    372:        if (http_server_register_servlet(server,
                    373:            servlet, vhost, "^/file", 0) == -1)
                    374:                err(1, "http_server_register_servlet");
                    375: 
                    376:        /* Register CGI servlet, at two different URLs */
                    377:        if ((servlet = cgi_servlet_create()) == NULL)
                    378:                err(1, "cgi_servlet_create");
                    379:        if (http_server_register_servlet(server,
                    380:            servlet, vhost, "^/cgi/get$", 0) == -1)
                    381:                err(1, "http_server_register_servlet");
                    382:        if ((servlet = cgi_servlet_create()) == NULL)
                    383:                err(1, "cgi_servlet_create");
                    384:        if (http_server_register_servlet(server,
                    385:            servlet, vhost, "^/cgi/post$", 0) == -1)
                    386:                err(1, "http_server_register_servlet");
                    387: 
                    388:        /* Register kernel servlet */
                    389:        if ((servlet = getkernel_servlet_create()) == NULL)
                    390:                err(1, "getkernel_servlet_create");
                    391:        if (http_server_register_servlet(server,
                    392:            servlet, vhost, "^/kernel", 0) == -1)
                    393:                err(1, "http_server_register_servlet");
                    394: 
                    395:        /* Wait for interrupt */
                    396:        sigemptyset(&sigs);
                    397:        sigaddset(&sigs, SIGINT);
                    398:        sigaddset(&sigs, SIGTERM);
                    399:        if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1)
                    400:                err(1, "sigprocmask");
                    401:        if (sigwait(&sigs, &sig) == -1)
                    402:                err(1, "sigwait");
                    403: 
                    404:        /* Shut down server */
                    405:        printf("Rec'd signal %d, shutting down http server...\n", sig);
                    406:        http_server_stop(&server);
                    407: 
                    408: shutdown:
                    409:        /* Destroy event context */
                    410:        pevent_ctx_destroy(&ctx);
                    411:        usleep(100000);
                    412: 
                    413:        /* Done */
                    414:        printf("Done. Displaying unfreed memory...\n");
                    415: 
                    416:        /* Show memory usage */
                    417:        typed_mem_dump(stdout);
                    418:        return (0);
                    419: }
                    420: 
                    421: /***********************************************************************
                    422:                        SUPPORT ROUTINES
                    423: ***********************************************************************/
                    424: 
                    425: /*
                    426:  * Do client loop
                    427:  */
                    428: static int
                    429: demo_client(struct pevent_ctx *ctx, int nurls, char **urls, int count)
                    430: {
                    431:        struct http_client *client;
                    432:        struct hostent *hent;
                    433:        struct in_addr ip;
                    434:        char buf[256];
                    435:        regex_t reg;
                    436:        int i, j;
                    437:        int r;
                    438: 
                    439:        /* Compile URL pattern */
                    440:        if ((r = regcomp(&reg,
                    441:            "^(http|https)://([-.[:alnum:]]+)(:[[:digit:]]+)?(/.*)?$",
                    442:            REG_EXTENDED)) != 0) {
                    443:                regerror(r, &reg, buf, sizeof(buf));
                    444:                errx(1, "invalid URL pattern: %s", buf);
                    445:        }
                    446: 
                    447:        /* Create client */
                    448:        if ((client = http_client_create(ctx, "DemoClient/1.0",
                    449:            5, 3, 7, demo_logger)) == NULL)
                    450:                err(1, "http_client_create");
                    451: 
                    452:        printf("Fetching %d URLs %d times...\n", nurls, count);
                    453:        for (i = 0; i < count; i++) {
                    454:            for (j = 0; j < nurls; j++) {
                    455:                const char *const url = urls[j];
                    456:                struct http_client_connection *cc;
                    457:                struct http_request *req;
                    458:                struct http_response *resp;
                    459:                regmatch_t match[5];
                    460:                char host[256];
                    461:                char path[256];
                    462:                int https = 0;
                    463:                int port;
                    464: 
                    465:                /* Parse URL */
                    466:                if ((r = regexec(&reg, url, sizeof(match) / sizeof(*match),
                    467:                    match, 0)) != 0) {
                    468:                        regerror(r, &reg, buf, sizeof(buf));
                    469:                        errx(1, "invalid URL \"%s\": %s", url, buf);
                    470:                }
                    471:                if (match[1].rm_eo - match[1].rm_so == 4)
                    472:                        port = 80;
                    473:                else {
                    474:                        port = 443;
                    475:                        https = 1;
                    476:                }
                    477:                if (match[3].rm_so != match[3].rm_eo) {
                    478:                        strncpy(buf, url + match[3].rm_so, sizeof(buf) - 1);
                    479:                        buf[sizeof(buf) - 1] = '\0';
                    480:                        if ((port = strtoul(buf + 1, NULL, 10)) == 0)
                    481:                                errx(1, "invalid port");
                    482:                }
                    483:                memset(&host, 0, sizeof(host));
                    484:                strncpy(host, url + match[2].rm_so,
                    485:                    MIN(sizeof(host) - 1, (match[2].rm_eo - match[2].rm_so)));
                    486:                if (match[4].rm_so != match[4].rm_eo) {
                    487:                        memset(&path, 0, sizeof(path));
                    488:                        strncpy(path, url + match[4].rm_so,
                    489:                            MIN(sizeof(path) - 1, (match[4].rm_eo
                    490:                              - match[4].rm_so)));
                    491:                } else
                    492:                        strcpy(path, "/");
                    493:                if (!inet_aton(host, &ip)) {
                    494:                        if ((hent = gethostbyname(host)) == NULL)
                    495:                                err(1, "%s: %s", host, hstrerror(h_errno));
                    496:                        ip = *((struct in_addr **)hent->h_addr_list)[0];
                    497:                }
                    498:                printf("\nFetching %s://%s:%d%s\n", https ? "https" : "http",
                    499:                    host, port, path);
                    500: 
                    501:                /* Create/get client connection */
                    502:                if ((cc = http_client_connect(client, ip, port, https)) == NULL)
                    503:                        err(1, "http_client_connect");
                    504: 
                    505:                /* Set up request */
                    506:                req = http_client_get_request(cc);
                    507:                if (http_request_set_method(req, "GET") == -1)
                    508:                        err(1, "http_request_set_method");
                    509:                if (http_request_set_path(req, path) == -1)
                    510:                        err(1, "%s(%s)", "http_request_set_path", path);
                    511:                if (http_request_set_header(req, 0,
                    512:                    HTTP_HEADER_HOST, "%s:%u", host, port) == -1)
                    513:                        err(1, "http_request_set_header");
                    514: 
                    515:                /* Send request */
                    516:                if ((resp = http_client_get_response(cc)) == NULL)
                    517:                        printf("Error: %s\n", http_client_get_reason(cc));
                    518:                else {
                    519:                        FILE *fp;
                    520:                        int ch;
                    521:                        int lnum;
                    522: 
                    523:                        printf("********** RESPONSE (first 20 lines): %d %s\n",
                    524:                            http_response_get_code(resp),
                    525:                            http_response_get_header(resp, HDR_REPLY_REASON));
                    526:                        if ((fp = http_response_get_input(resp)) == NULL)
                    527:                                err(1, "http_response_get_input");
                    528:                        for (lnum = 0; (ch = getc(fp)) != EOF; ) {
                    529:                                putchar(ch);
                    530:                                if (ch == '\n') {
                    531:                                        if (++lnum == 20)
                    532:                                                break;
                    533:                                }
                    534:                        }
                    535:                        printf("*********************************\n\n\n");
                    536:                }
                    537: 
                    538:                /* Release client connection */
                    539:                http_client_close(&cc);
                    540: 
                    541:                /* Pause */
                    542:                sleep(1);
                    543:            }
                    544:        }
                    545: 
                    546:        /* Release client */
                    547:        if (http_client_destroy(&client) == -1)
                    548:                err(1, "http_client_free");
                    549:        regfree(&reg);
                    550:        return (0);
                    551: }
                    552: 
                    553: /*
                    554:  * Demo CGI file upload handler
                    555:  */
                    556: static void
                    557: demo_file_upload(struct http_request *req, struct http_response *resp, FILE *fp)
                    558: {
                    559:        static const char *hr = "-----------------------------------------\n";
                    560:        struct mime_multipart *mp;
                    561:        u_int count;
                    562:        int i;
                    563: 
                    564:        /* Read multipart MIME */
                    565:        if ((mp = http_request_read_mime_multipart(req)) == NULL) {
                    566:                http_response_send_error(resp,
                    567:                    HTTP_STATUS_INTERNAL_SERVER_ERROR,
                    568:                    "Can't read multi-part MIME input: %s", strerror(errno));
                    569:                return;
                    570:        }
                    571: 
                    572:        /* Display parts */
                    573:        count = http_mime_multipart_get_count(mp);
                    574:        fprintf(fp, "Read %d parts:\n\n", count);
                    575:        fprintf(fp, "%s", hr);
                    576:        for (i = 0; i < count; i++) {
                    577:                struct mime_part *const part
                    578:                    = http_mime_multipart_get_part(mp, i);
                    579:                u_char *const data = http_mime_part_get_data(part);
                    580:                const u_int dlen = http_mime_part_get_length(part);
                    581:                const char *const cd = http_mime_part_get_header(part,
                    582:                    HTTP_HEADER_CONTENT_DISPOSITION);
                    583: 
                    584:                fprintf(fp, "PART #%u: %u bytes\n%s: %s\n%s",
                    585:                    i + 1, dlen, HTTP_HEADER_CONTENT_DISPOSITION,
                    586:                    cd == NULL ? "<< NONE >>" : cd, hr);
                    587:                fwrite(data, 1, dlen, fp);
                    588:                fprintf(fp, "\n%s", hr);
                    589:        }
                    590: 
                    591:        /* Free multipart data */
                    592:        http_mime_multipart_free(&mp);
                    593: }
                    594: 
                    595: /*
                    596:  * Exit after printing usage string
                    597:  */
                    598: static void
                    599: usage(void)
                    600: {
                    601:        (void)fprintf(stderr,
                    602:           "Usage: demo_server [-s] [-p port] [-c count]\n"
                    603:           "\t[-r redirect url] [-h hostname] [-v virtual-host] [url ...]\n");
                    604:        exit(1);
                    605: }
                    606: 
                    607: /***********************************************************************
                    608:                        HTTP CALLBACKS
                    609: ***********************************************************************/
                    610: 
                    611: /*
                    612:  * Logger for the HTTP server.
                    613:  */
                    614: static void
                    615: demo_logger(int sev, const char *fmt, ...)
                    616: {
                    617:        static char buf[512];
                    618:        va_list args;
                    619: 
                    620:        snprintf(buf, sizeof(buf), "http_server: %s", fmt);
                    621:        va_start(args, fmt);
                    622:        vfprintf(stderr, buf, args);
                    623:        fprintf(stderr, "\n");
                    624:        va_end(args);
                    625: }
                    626: 
                    627: /***********************************************************************
                    628:                        AUTHORIZOR SERVLETS
                    629: ***********************************************************************/
                    630: 
                    631: static int
                    632: demo_auth_reqd(void *arg, struct http_request *req)
                    633: {
                    634:        const char *path = http_request_get_path(req);
                    635: 
                    636:        return (strcmp(path, "/logon") != 0);
                    637: }
                    638: 
                    639: static const char *
                    640: demo_basicauth(void *arg, struct http_request *req,
                    641:        const char *username, const char *password)
                    642: {
                    643:        if (strcmp(username, "demo") != 0 || strcmp(password, "demo") != 0)
                    644:                return ("HTTP Server Demo");
                    645:        return (NULL);
                    646: }
                    647: 
                    648: /***********************************************************************
                    649:                        DEMO SERVLET
                    650: ***********************************************************************/
                    651: 
                    652: static http_servlet_run_t      demo_servlet_run;
                    653: static http_servlet_destroy_t  demo_servlet_destroy;
                    654: 
                    655: /*
                    656:  * Demo servlet
                    657:  */
                    658: static struct http_servlet *
                    659: demo_servlet_create(void)
                    660: {
                    661:        struct http_servlet *servlet;
                    662: 
                    663:        if ((servlet = MALLOC(DEMO_MEM_TYPE, sizeof(*servlet))) == NULL)
                    664:                return (NULL);
                    665:        memset(servlet, 0, sizeof(*servlet));
                    666:        servlet->run = demo_servlet_run;
                    667:        servlet->destroy = demo_servlet_destroy;
                    668:        return (servlet);
                    669: }
                    670: 
                    671: static int
                    672: demo_servlet_run(struct http_servlet *servlet,
                    673:        struct http_request *req, struct http_response *resp)
                    674: {
                    675:        const time_t now = time(NULL);
                    676:        char buf[32];
                    677:        FILE *fp;
                    678:        char *u;
                    679: 
                    680:        /* Get output stream */
                    681:        if ((fp = http_response_get_output(resp, 1)) == NULL) {
                    682:                http_response_send_error(resp,
                    683:                    HTTP_STATUS_INTERNAL_SERVER_ERROR,
                    684:                    "Can't get output stream");
                    685:                return (1);
                    686:        }
                    687: 
                    688:        /* Set content type */
                    689:        http_response_set_header(resp, 0,
                    690:            HTTP_HEADER_CONTENT_TYPE, "text/html");
                    691: 
                    692:        /* Tell browser not to cache me */
                    693:         http_response_set_header(resp, 1, HTTP_HEADER_PRAGMA, "no-cache");
                    694:        http_response_set_header(resp, 0,
                    695:            HTTP_HEADER_CACHE_CONTROL, "no-cache");
                    696: 
                    697:        /* Send some output */
                    698:        fprintf(fp, "<html><head><title>Demo Servlet</title></head>\n");
                    699:        fprintf(fp, "<body bgcolor=\"#ffffff\">\n");
                    700:        fprintf(fp, "<h3>Demo Servlet in C</h3>\n");
                    701:        fprintf(fp, "This servlet is implemented directly in C code.\n");
                    702:        fprintf(fp, "See http_servlet(3) for details.\n<br>\n");
                    703:        fprintf(fp, "<p>The time is <code>%s</code>\n", ctime_r(&now, buf));
                    704:        if ((u = http_servlet_cookieauth_user("demo.key", demo_id,
                    705:            sizeof(demo_id), DEMO_COOKIE_NAME, req, TYPED_MEM_TEMP)) == NULL) {
                    706:                if (errno == EACCES)
                    707:                        u = STRDUP(TYPED_MEM_TEMP, "(nobody)");
                    708:        }
                    709:        if (u != NULL) {
                    710:                fprintf(fp, "<p>You are logged on as <b>%s</b>.", u);
                    711:                FREE(TYPED_MEM_TEMP, u);
                    712:        } else
                    713:                fprintf(fp, "<p><b>Error with user: %s</b>.", strerror(errno));
                    714:        fprintf(fp, "<p>Click <a href=\"tmpl\">HERE</a>"
                    715:            " for tmpl servlet demo (login as <b>demo</b>"
                    716:            " password <b>demo</b>)\n");
                    717:        fprintf(fp, "</body></html>\n");
                    718:        fclose(fp);
                    719:        return (1);
                    720: }
                    721: 
                    722: static void
                    723: demo_servlet_destroy(struct http_servlet *servlet)
                    724: {
                    725:        FREE(DEMO_MEM_TYPE, servlet);
                    726: }
                    727: 
                    728: /***********************************************************************
                    729:                        KERNEL SERVLET
                    730: ***********************************************************************/
                    731: 
                    732: static http_servlet_run_t      getkernel_servlet_run;
                    733: static http_servlet_destroy_t  getkernel_servlet_destroy;
                    734: 
                    735: /*
                    736:  * Kernel servlet
                    737:  */
                    738: static struct http_servlet *
                    739: getkernel_servlet_create(void)
                    740: {
                    741:        struct http_servlet *servlet;
                    742: 
                    743:        if ((servlet = MALLOC(DEMO_MEM_TYPE, sizeof(*servlet))) == NULL)
                    744:                return (NULL);
                    745:        memset(servlet, 0, sizeof(*servlet));
                    746:        servlet->run = getkernel_servlet_run;
                    747:        servlet->destroy = getkernel_servlet_destroy;
                    748:        return (servlet);
                    749: }
                    750: 
                    751: static int
                    752: getkernel_servlet_run(struct http_servlet *servlet,
                    753:        struct http_request *req, struct http_response *resp)
                    754: {
                    755:        struct stat sb;
                    756:        time_t timestamp;
                    757:        char date[64];
                    758:        struct tm tm;
                    759: 
                    760:        /* Make this "web page" not cachable */
                    761:        http_response_set_header(resp, 1, HTTP_HEADER_PRAGMA, "no-cache");
                    762:        http_response_set_header(resp, 0,
                    763:            HTTP_HEADER_CACHE_CONTROL, "no-cache");
                    764: 
                    765:        /* Get timestamp of kernel file */
                    766:        if (stat(PATH_KERNEL, &sb) != -1)
                    767:                timestamp = sb.st_mtime;
                    768:        else
                    769:                timestamp = time(NULL); /* ok because servlet will fail too */
                    770: 
                    771:        /* Set MIME type */
                    772:        http_response_set_header(resp, 0, HTTP_HEADER_CONTENT_TYPE,
                    773:            "application/octet-stream");
                    774: 
                    775:        /* Set filename (via Content-Disposition) based on date */
                    776:        strftime(date, sizeof(date), "%Y-%m-%d", localtime_r(&timestamp, &tm));
                    777:        http_response_set_header(resp, 0, HTTP_HEADER_CONTENT_DISPOSITION,
                    778:            "application/octet-stream; filename=\"kernel-%s\"", date);
                    779: 
                    780:        /* Piggy-back off of file servlet routine */
                    781:        http_servlet_file_serve(PATH_KERNEL, demo_logger, req, resp);
                    782:        return (1);
                    783: }
                    784: 
                    785: static void
                    786: getkernel_servlet_destroy(struct http_servlet *servlet)
                    787: {
                    788:        FREE(DEMO_MEM_TYPE, servlet);
                    789: }
                    790: 
                    791: /***********************************************************************
                    792:                            CGI SERVLET
                    793: ***********************************************************************/
                    794: 
                    795: static http_servlet_run_t      cgi_servlet_run;
                    796: static http_servlet_destroy_t  cgi_servlet_destroy;
                    797: 
                    798: /*
                    799:  * Demo CGI
                    800:  */
                    801: static struct http_servlet *
                    802: cgi_servlet_create(void)
                    803: {
                    804:        struct http_servlet *servlet;
                    805: 
                    806:        if ((servlet = MALLOC(DEMO_MEM_TYPE, sizeof(*servlet))) == NULL)
                    807:                return (NULL);
                    808:        memset(servlet, 0, sizeof(*servlet));
                    809:        servlet->run = cgi_servlet_run;
                    810:        servlet->destroy = cgi_servlet_destroy;
                    811:        return (servlet);
                    812: }
                    813: 
                    814: static int
                    815: cgi_servlet_run(struct http_servlet *servlet,
                    816:        struct http_request *req, struct http_response *resp)
                    817: {
                    818:        FILE *fp;
                    819:        int i;
                    820: 
                    821:        /* Set no cache */
                    822:        http_response_set_header(resp, 1, "Pragma", "no-cache");
                    823:        http_response_set_header(resp, 0, "Cache-Control", "no-cache");
                    824: 
                    825:        /* Set MIME type */
                    826:        http_response_set_header(resp, 0,
                    827:            HTTP_HEADER_CONTENT_TYPE, "text/plain; charset=iso-8859-1");
                    828: 
                    829:        /* Get output stream */
                    830:        if ((fp = http_response_get_output(resp, 0)) == NULL) {
                    831:                http_response_send_error(resp,
                    832:                    HTTP_STATUS_INTERNAL_SERVER_ERROR,
                    833:                    "Can't get output stream");
                    834:                return (1);
                    835:        }
                    836: 
                    837:        /* For POST, read and decode input */
                    838:        if (strcmp(http_request_get_method(req), "POST") == 0) {
                    839:                const char *hval;
                    840:                const char *s;
                    841:                int nval;
                    842: 
                    843:                /* Check type of encoding */
                    844:                if ((hval = http_request_get_header(req,
                    845:                    HTTP_HEADER_CONTENT_TYPE)) == NULL) {
                    846:                        http_response_send_error(resp,
                    847:                            HTTP_STATUS_INTERNAL_SERVER_ERROR,
                    848:                            "Missing %s header", HTTP_HEADER_CONTENT_TYPE);
                    849:                        return (1);
                    850:                }
                    851: 
                    852:                /* Special case form file upload */
                    853:                if ((s = strchr(hval, ';')) != NULL
                    854:                    && strncasecmp(hval,
                    855:                      HTTP_CTYPE_MULTIPART_FORMDATA, s - hval) == 0) {
                    856:                        demo_file_upload(req, resp, fp);
                    857:                        return (1);
                    858:                }
                    859: 
                    860:                /* Must be POST form data */
                    861:                if (strcasecmp(hval, HTTP_CTYPE_FORM_URLENCODED) != 0) {
                    862:                        http_response_send_error(resp,
                    863:                            HTTP_STATUS_INTERNAL_SERVER_ERROR,
                    864:                            "Weird content-type \"%s\"", hval);
                    865:                        return (1);
                    866:                }
                    867: 
                    868:                /* Read POST form data */
                    869:                if ((nval = http_request_read_url_encoded_values(req)) == -1) {
                    870:                        http_response_send_error(resp,
                    871:                            HTTP_STATUS_INTERNAL_SERVER_ERROR,
                    872:                            "Can't read POST input");
                    873:                        return (1);
                    874:                }
                    875:                fprintf(fp, "Read %d values from input\n", nval);
                    876:        }
                    877: 
                    878:        /* Get fields and display them */
                    879:        for (i = 1; 1; i++) {
                    880:                const char *value;
                    881:                char fname[32];
                    882: 
                    883:                snprintf(fname, sizeof(fname), "field%d", i);
                    884:                fprintf(fp, "FIELD \"%s\": ", fname);
                    885:                if ((value = http_request_get_value(req, fname, 0)) == NULL) {
                    886:                        fprintf(fp, "<< NOT FOUND >>\n");
                    887:                        break;
                    888:                } else
                    889:                        fprintf(fp, "value=\"%s\"\n", value);
                    890:        }
                    891:        return (1);
                    892: }
                    893: 
                    894: static void
                    895: cgi_servlet_destroy(struct http_servlet *servlet)
                    896: {
                    897:        FREE(DEMO_MEM_TYPE, servlet);
                    898: }
                    899: 
                    900: /***********************************************************************
                    901:                        TMPL USER FUNCTIONS
                    902: ***********************************************************************/
                    903: 
                    904: static tmpl_handler_t  authname_handler;
                    905: static tmpl_handler_t  authorize_handler;
                    906: static tmpl_handler_t  date_handler;
                    907: static tmpl_handler_t  get_header_handler;
                    908: static tmpl_handler_t  get_port_handler;
                    909: static tmpl_handler_t  get_ssl_handler;
                    910: static tmpl_handler_t  query_handler;
                    911: static tmpl_handler_t  query_string_handler;
                    912: static tmpl_handler_t  redirect_handler;
                    913: static tmpl_handler_t  remote_ip_handler;
                    914: static tmpl_handler_t  remote_port_handler;
                    915: static tmpl_handler_t  shutdown_handler;
                    916: static tmpl_handler_t  sleep_handler;
                    917: static tmpl_handler_t  vhost_handler;
                    918: 
                    919: static const struct tmpl_func demo_tmpl_funcs[] = {
                    920:        { "authname",           0, 0,   authname_handler        },
                    921:        { "authorize",          0, 2,   authorize_handler       },
                    922:        { "date",               0, 0,   date_handler            },
                    923:        { "get_header",         1, 1,   get_header_handler      },
                    924:        { "get_port",           0, 0,   get_port_handler        },
                    925:        { "get_ssl",            0, 0,   get_ssl_handler         },
                    926:        { "query",              1, 1,   query_handler           },
                    927:        { "query_string",       0, 0,   query_string_handler    },
                    928:        { "redirect",           0, 0,   redirect_handler        },
                    929:        { "remote_ip",          0, 0,   remote_ip_handler       },
                    930:        { "remote_port",        0, 0,   remote_port_handler     },
                    931:        { "shutdown",           0, 0,   shutdown_handler        },
                    932:        { "sleep",              1, 1,   sleep_handler           },
                    933:        { "vhost",              0, 0,   vhost_handler           },
                    934: };
                    935: 
                    936: static char *
                    937: demo_tmpl_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                    938: {
                    939:        return (tmpl_list_handler(ctx, demo_tmpl_funcs,
                    940:            sizeof(demo_tmpl_funcs) / sizeof(*demo_tmpl_funcs),
                    941:            errmsgp, ac, av));
                    942: }
                    943: 
                    944: static char *
                    945: remote_ip_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                    946: {
                    947:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
                    948:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                    949: 
                    950:        return (STRDUP(mtype,
                    951:            inet_ntoa(http_request_get_remote_ip(targ->req))));
                    952: }
                    953: 
                    954: static char *
                    955: remote_port_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                    956: {
                    957:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
                    958:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                    959:        char buf[32];
                    960: 
                    961:        snprintf(buf, sizeof(buf), "%u",
                    962:            http_request_get_remote_port(targ->req));
                    963:        return (STRDUP(mtype, buf));
                    964: }
                    965: 
                    966: static char *
                    967: redirect_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                    968: {
                    969:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                    970: 
                    971:        return (STRDUP(mtype, redirect_url ? redirect_url : ""));
                    972: }
                    973: 
                    974: static char *
                    975: date_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                    976: {
                    977:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                    978:        const time_t now = time(NULL);
                    979:        char buf[32];
                    980: 
                    981:        return (STRDUP(mtype, ctime_r(&now, buf)));
                    982: }
                    983: 
                    984: static char *
                    985: sleep_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                    986: {
                    987:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
                    988:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                    989: 
                    990:        http_response_send_headers(targ->resp, 1);
                    991:        sleep(atoi(av[1]));
                    992:        return (STRDUP(mtype, ""));
                    993: }
                    994: 
                    995: static char *
                    996: authorize_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                    997: {
                    998:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
                    999:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1000: 
                   1001:        /* Login */
                   1002:        if (ac > 2 && *av[2] != '\0') {
                   1003:                const u_long expiry = strtoul(av[2], NULL, 10);
                   1004: 
                   1005:                if (http_servlet_cookieauth_login(targ->resp,
                   1006:                    "demo.key", av[1], 3600, expiry ? time(NULL) + expiry : 0,
                   1007:                    expiry == 0, demo_id, sizeof(demo_id), DEMO_COOKIE_NAME,
                   1008:                    "/", NULL, 0) == -1)
                   1009:                        return (NULL);
                   1010:                return (STRDUP(mtype, ""));
                   1011:        }
                   1012: 
                   1013:        /* Logout */
                   1014:        if (http_servlet_cookieauth_logout(DEMO_COOKIE_NAME,
                   1015:            "/", NULL, targ->resp) == -1)
                   1016:                return (NULL);
                   1017:        return (STRDUP(mtype, ""));
                   1018: }
                   1019: 
                   1020: static char *
                   1021: authname_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                   1022: {
                   1023:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
                   1024:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1025:        char *name;
                   1026: 
                   1027:        if ((name = http_servlet_cookieauth_user("demo.key", demo_id,
                   1028:            sizeof(demo_id), DEMO_COOKIE_NAME, targ->req, mtype)) == NULL) {
                   1029:                if (errno == EACCES)
                   1030:                        name = STRDUP(mtype, "");
                   1031:        }
                   1032:        if (name == NULL)
                   1033:                return (NULL);
                   1034:        return (name);
                   1035: }
                   1036: 
                   1037: static char *
                   1038: query_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                   1039: {
                   1040:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
                   1041:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1042:        const char *value;
                   1043: 
                   1044:        if ((value = http_request_get_value(targ->req, av[1], 0)) == NULL)
                   1045:                value = "";
                   1046:        return (STRDUP(mtype, value));
                   1047: }
                   1048: 
                   1049: static char *
                   1050: query_string_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                   1051: {
                   1052:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
                   1053:        const char *eqs = http_request_get_query_string(targ->req);
                   1054:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1055:        char *dqs;
                   1056: 
                   1057:        /* URL-decode query string */
                   1058:        if ((dqs = MALLOC(mtype, strlen(eqs) + 1)) == NULL)
                   1059:                return (NULL);
                   1060:        http_request_url_decode(eqs, dqs);
                   1061: 
                   1062:        /* Return it */
                   1063:        return (dqs);
                   1064: }
                   1065: 
                   1066: static char *
                   1067: get_header_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                   1068: {
                   1069:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
                   1070:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1071:        const char *value;
                   1072: 
                   1073:        if ((value = http_request_get_header(targ->req, av[1])) == NULL)
                   1074:                value = "";
                   1075:        return (STRDUP(mtype, value));
                   1076: }
                   1077: 
                   1078: static char *
                   1079: get_port_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                   1080: {
                   1081:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1082:        char buf[32];
                   1083: 
                   1084:        snprintf(buf, sizeof(buf), "%u", port);
                   1085:        return (STRDUP(mtype, buf));
                   1086: }
                   1087: 
                   1088: static char *
                   1089: get_ssl_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                   1090: {
                   1091:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1092: 
                   1093:        return (STRDUP(mtype, ssl != NULL ? "1" : "0"));
                   1094: }
                   1095: 
                   1096: static char *
                   1097: vhost_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                   1098: {
                   1099:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1100: 
                   1101:        return (STRDUP(mtype, vhost == NULL ? "" : vhost));
                   1102: }
                   1103: 
                   1104: static char *
                   1105: shutdown_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
                   1106: {
                   1107:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1108: 
                   1109:        kill(main_pid, SIGTERM);
                   1110:        return (STRDUP(mtype, ""));
                   1111: }
                   1112: 
                   1113: /*
                   1114:  * Error formatter for templates.
                   1115:  */
                   1116: static char *
                   1117: demo_tmpl_errfmtr(struct tmpl_ctx *ctx, const char *errmsg)
                   1118: {
                   1119:        static const char fmt[] =
                   1120:            "<font color=\"#ff0000\"><strong>Error: %s</strong></font>";
                   1121:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
                   1122:        char *string;
                   1123:        int slen;
                   1124: 
                   1125:        slen = sizeof(fmt) + strlen(errmsg);
                   1126:        if ((string = MALLOC(mtype, slen)) == NULL)
                   1127:                return (NULL);
                   1128:        snprintf(string, slen, fmt, errmsg);
                   1129:        return (string);
                   1130: }
                   1131: 
                   1132: /***********************************************************************
                   1133:                        SSL MEMORY WRAPPERS
                   1134: ***********************************************************************/
                   1135: 
                   1136: /*
                   1137:  * OpenSSL malloc() wrappers
                   1138:  */
                   1139: static void
                   1140: *ssl_malloc(size_t size)
                   1141: {
                   1142:        return (MALLOC("OpenSSL", size));
                   1143: }
                   1144: 
                   1145: static void
                   1146: *ssl_realloc(void *mem, size_t size)
                   1147: {
                   1148:        return (REALLOC("OpenSSL", mem, size));
                   1149: }
                   1150: 
                   1151: static void
                   1152: ssl_free(void *mem)
                   1153: {
                   1154:        return (FREE("OpenSSL", mem));
                   1155: }
                   1156: 

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