Blame agen5/agCgi.c

Packit Service 96b5d3
Packit Service 96b5d3
/**
Packit Service 96b5d3
 * @file agCgi.c
Packit Service 96b5d3
 *
Packit Service 96b5d3
 *  This is a CGI wrapper for AutoGen.  It will take POST-method
Packit Service 96b5d3
 *  name-value pairs and emit AutoGen definitions to a spawned
Packit Service 96b5d3
 *  AutoGen process.
Packit Service 96b5d3
 *
Packit Service 96b5d3
 *  This file is part of AutoGen.
Packit Service 96b5d3
 *  AutoGen Copyright (C) 1992-2016 by Bruce Korb - all rights reserved
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * AutoGen is free software: you can redistribute it and/or modify it
Packit Service 96b5d3
 * under the terms of the GNU General Public License as published by the
Packit Service 96b5d3
 * Free Software Foundation, either version 3 of the License, or
Packit Service 96b5d3
 * (at your option) any later version.
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * AutoGen is distributed in the hope that it will be useful, but
Packit Service 96b5d3
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 96b5d3
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Packit Service 96b5d3
 * See the GNU General Public License for more details.
Packit Service 96b5d3
 *
Packit Service 96b5d3
 * You should have received a copy of the GNU General Public License along
Packit Service 96b5d3
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 96b5d3
 */
Packit Service 96b5d3
Packit Service 96b5d3
typedef struct {
Packit Service 96b5d3
    char const * name;
Packit Service 96b5d3
    char *       cgi_val;
Packit Service 96b5d3
} name_map_t;
Packit Service 96b5d3
Packit Service 96b5d3
#define ENV_TABLE \
Packit Service 96b5d3
    _ET_(REQUEST_METHOD) \
Packit Service 96b5d3
    _ET_(QUERY_STRING) \
Packit Service 96b5d3
    _ET_(CONTENT_LENGTH) \
Packit Service 96b5d3
\
Packit Service 96b5d3
    _ET_(AUTH_TYPE) \
Packit Service 96b5d3
    _ET_(CONTENT_TYPE) \
Packit Service 96b5d3
    _ET_(GATEWAY_INTERFACE) \
Packit Service 96b5d3
    _ET_(HTTP_ACCEPT) \
Packit Service 96b5d3
    _ET_(HTTP_REFERER) \
Packit Service 96b5d3
    _ET_(HTTP_USER_AGENT) \
Packit Service 96b5d3
    _ET_(PATH_INFO) \
Packit Service 96b5d3
    _ET_(PATH_TRANSLATED) \
Packit Service 96b5d3
    _ET_(REMOTE_ADDR) \
Packit Service 96b5d3
    _ET_(REMOTE_HOST) \
Packit Service 96b5d3
    _ET_(REMOTE_IDENT) \
Packit Service 96b5d3
    _ET_(REMOTE_USER) \
Packit Service 96b5d3
    _ET_(SCRIPT_NAME) \
Packit Service 96b5d3
    _ET_(SERVER_NAME) \
Packit Service 96b5d3
    _ET_(SERVER_PORT) \
Packit Service 96b5d3
    _ET_(SERVER_PROTOCOL) \
Packit Service 96b5d3
    _ET_(SERVER_SOFTWARE)
Packit Service 96b5d3
Packit Service 96b5d3
static name_map_t name_val_map[] = {
Packit Service 96b5d3
#define _ET_(n) { #n, NULL },
Packit Service 96b5d3
    ENV_TABLE
Packit Service 96b5d3
#undef _ET_
Packit Service 96b5d3
    { NULL, NULL }
Packit Service 96b5d3
};
Packit Service 96b5d3
Packit Service 96b5d3
typedef enum {
Packit Service 96b5d3
#define _ET_(n) n ## _IDX,
Packit Service 96b5d3
    ENV_TABLE
Packit Service 96b5d3
#undef _ET_
Packit Service 96b5d3
    NAME_CT
Packit Service 96b5d3
} name_idx_t;
Packit Service 96b5d3
Packit Service 96b5d3
#define cgi_method name_val_map[ REQUEST_METHOD_IDX ].cgi_val
Packit Service 96b5d3
#define cgi_query  name_val_map[ QUERY_STRING_IDX   ].cgi_val
Packit Service 96b5d3
#define cgi_len    name_val_map[ CONTENT_LENGTH_IDX ].cgi_val
Packit Service 96b5d3
Packit Service 96b5d3
 static inline char *
Packit Service 96b5d3
parse_input(char * src, int len)
Packit Service 96b5d3
{
Packit Service 96b5d3
    size_t rsz = (len * 4) + PARSE_INPUT_AG_DEF_STR_LEN;
Packit Service 96b5d3
    char * res = AGALOC(rsz, "CGI Defs");
Packit Service 96b5d3
Packit Service 96b5d3
    memcpy(res, PARSE_INPUT_AG_DEF_STR, PARSE_INPUT_AG_DEF_STR_LEN);
Packit Service 96b5d3
    (void)cgi_run_fsm(src, len, res + PARSE_INPUT_AG_DEF_STR_LEN, len * 2);
Packit Service 96b5d3
    assert(rsz > strlen(res));
Packit Service 96b5d3
    return AGREALOC(res, strlen(res)+1, "CGI input");
Packit Service 96b5d3
}
Packit Service 96b5d3
Packit Service 96b5d3
LOCAL void
Packit Service 96b5d3
load_cgi(void)
Packit Service 96b5d3
{
Packit Service 96b5d3
    /*
Packit Service 96b5d3
     *  Redirect stderr to a file.  If it gets used, we must trap it
Packit Service 96b5d3
     *  and emit the content-type: preamble before actually emitting it.
Packit Service 96b5d3
     *  First, tho, do a simple stderr->stdout redirection just in case
Packit Service 96b5d3
     *  we stumble before we're done with this.
Packit Service 96b5d3
     */
Packit Service 96b5d3
    dup2(STDOUT_FILENO, STDERR_FILENO);
Packit Service 96b5d3
    {
Packit Service 96b5d3
        FILE * fp = fdopen(STDERR_FILENO, "w" FOPEN_BINARY_FLAG);
Packit Service 96b5d3
        (void)fp;
Packit Service 96b5d3
    }
Packit Service 96b5d3
    {
Packit Service 96b5d3
        int tmpfd;
Packit Service 96b5d3
        oops_pfx = CGI_ERR_MSG_FMT;
Packit Service 96b5d3
        AGDUPSTR(cgi_stderr, CGI_TEMP_ERR_FILE_STR, "stderr file");
Packit Service 96b5d3
        tmpfd = mkstemp(cgi_stderr);
Packit Service 96b5d3
        if (tmpfd < 0)
Packit Service 96b5d3
            AG_ABEND(aprf(MKSTEMP_FAIL_FMT, cgi_stderr));
Packit Service 96b5d3
        dup2(tmpfd, STDERR_FILENO);
Packit Service 96b5d3
        close(tmpfd);
Packit Service 96b5d3
    }
Packit Service 96b5d3
Packit Service 96b5d3
    /*
Packit Service 96b5d3
     *  Pull the CGI-relevant environment variables.  Anything we don't find
Packit Service 96b5d3
     *  gets an empty string default.
Packit Service 96b5d3
     */
Packit Service 96b5d3
    {
Packit Service 96b5d3
        name_map_t * nm_map = name_val_map;
Packit Service 96b5d3
        name_idx_t   ix     = (name_idx_t)0;
Packit Service 96b5d3
Packit Service 96b5d3
        do  {
Packit Service 96b5d3
            nm_map->cgi_val = getenv(nm_map->name);
Packit Service 96b5d3
            if (nm_map->cgi_val == NULL)
Packit Service 96b5d3
                nm_map->cgi_val = (char *)zNil;
Packit Service 96b5d3
        } while (nm_map++, ++ix < NAME_CT);
Packit Service 96b5d3
    }
Packit Service 96b5d3
Packit Service 96b5d3
    base_ctx = (scan_ctx_t *)AGALOC(sizeof(scan_ctx_t), "CGI ctx");
Packit Service 96b5d3
    memset(VOIDP(base_ctx), 0, sizeof(scan_ctx_t));
Packit Service 96b5d3
Packit Service 96b5d3
    {
Packit Service 96b5d3
        size_t len = strtoul(cgi_len, NULL, 0);
Packit Service 96b5d3
        char * text;
Packit Service 96b5d3
Packit Service 96b5d3
        if (strcasecmp(cgi_method, "POST") == 0) {
Packit Service 96b5d3
            if (len == 0)
Packit Service 96b5d3
                AG_ABEND(LOAD_CGI_NO_DATA_MSG);
Packit Service 96b5d3
Packit Service 96b5d3
            text  = AGALOC(len + 1, "CGI POST");
Packit Service 96b5d3
            if (fread(text, (size_t)1, len, stdin) != len)
Packit Service 96b5d3
                AG_CANT(LOAD_CGI_READ_NAME, LOAD_CGI_READ_WHAT);
Packit Service 96b5d3
Packit Service 96b5d3
            text[ len ] = NUL;
Packit Service 96b5d3
Packit Service 96b5d3
            base_ctx->scx_data = parse_input(text, (int)len);
Packit Service 96b5d3
            AGFREE(text);
Packit Service 96b5d3
Packit Service 96b5d3
        } else if (strcasecmp(cgi_method, LOAD_CGI_GET_NAME) == 0) {
Packit Service 96b5d3
            if (len == 0)
Packit Service 96b5d3
                len = strlen(cgi_query);
Packit Service 96b5d3
            base_ctx->scx_data = parse_input(cgi_query, (int)len);
Packit Service 96b5d3
Packit Service 96b5d3
        } else {
Packit Service 96b5d3
            AG_ABEND(aprf(LOAD_CGI_INVAL_REQ_FMT, cgi_method));
Packit Service 96b5d3
            /* NOTREACHED */
Packit Service 96b5d3
#ifdef  WARNING_WATCH
Packit Service 96b5d3
            text = NULL;
Packit Service 96b5d3
#endif
Packit Service 96b5d3
        }
Packit Service 96b5d3
    }
Packit Service 96b5d3
Packit Service 96b5d3
    base_ctx->scx_line  = 1;
Packit Service 96b5d3
    base_ctx->scx_fname = LOAD_CGI_DEFS_MARKER;
Packit Service 96b5d3
    base_ctx->scx_scan  = base_ctx->scx_data;
Packit Service 96b5d3
}
Packit Service 96b5d3
Packit Service 96b5d3
/*
Packit Service 96b5d3
 * Local Variables:
Packit Service 96b5d3
 * mode: C
Packit Service 96b5d3
 * c-file-style: "stroustrup"
Packit Service 96b5d3
 * indent-tabs-mode: nil
Packit Service 96b5d3
 * End:
Packit Service 96b5d3
 * end of agen5/agCgi.c */