stoddard    99/10/14 06:51:41

  Modified:    src/modules/standard mod_cgi.c
  Log:
  Still does not work reliably, but it's closer to being right.
  
  Revision  Changes    Path
  1.10      +119 -77   apache-2.0/src/modules/standard/mod_cgi.c
  
  Index: mod_cgi.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_cgi.c,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- mod_cgi.c 1999/10/12 19:19:29     1.9
  +++ mod_cgi.c 1999/10/14 13:51:41     1.10
  @@ -278,37 +278,16 @@
       ap_close(f);
       return ret;
   }
  -
  -/****************************************************************
  - *
  - * Actual CGI handling...
  - */
  -
  -
  -struct cgi_child_stuff {
  -#ifdef TPF
  -    TPF_FORK_CHILD t;
  -#endif
  -    request_rec *r;
  -    int nph;
  -    int debug;
  -    char *argv0;
  -};
  -
  -static ap_status_t cgi_child(struct cgi_child_stuff *child_stuff,
  -                      BUFF **script_out, BUFF **script_in, BUFF **script_err)
  +static ap_status_t run_cgi_child(BUFF **script_out, BUFF **script_in, BUFF 
**script_err, 
  +                                 char *command, char *const argv[], 
request_rec *r, ap_context_t *p)
   {
  -    struct cgi_child_stuff *cld = child_stuff;
  -    request_rec *r = cld->r;
  -    char err_string[MAX_STRING_LEN];
  -    char *argv0 = cld->argv0;
  -    char **args = NULL;
       char **env;
  -    ap_context_t *child_context;
       ap_procattr_t *procattr;
       ap_proc_t *procnew;
       ap_os_proc_t fred;
       ap_status_t rc = APR_SUCCESS;
  +    ap_file_t *file;
  +    ap_iol *iol;
   
   #ifdef DEBUG_CGI
   #ifdef OS2
  @@ -322,8 +301,6 @@
   
       ap_block_alarms();
   
  -    child_context = r->main ? r->main->pool : r->pool;
  -
       RAISE_SIGSTOP(CGI_CHILD);
   #ifdef DEBUG_CGI
       fprintf(dbg, "Attempting to exec %s as %sCGI child (argv0 = %s)\n",
  @@ -331,7 +308,7 @@
   #endif
   
       ap_add_cgi_vars(r);
  -    env = ap_create_environment(child_context, r->subprocess_env);
  +    env = ap_create_environment(p, r->subprocess_env);
   
   #ifdef DEBUG_CGI
       fprintf(dbg, "Environment: \n");
  @@ -339,21 +316,17 @@
        fprintf(dbg, "'%s'\n", env[i]);
   #endif
   
  -    if (!cld->debug)
  -     ap_error_log2stderr(r->server);
  -
       /* Transumute ourselves into the script.
        * NB only ISINDEX scripts get decoded arguments.
        */
  -
       ap_cleanup_for_exec();
   
  -    if ((ap_createprocattr_init(&procattr, child_context) != APR_SUCCESS) ||
  +    if ((ap_createprocattr_init(&procattr, p) != APR_SUCCESS) ||
           (ap_setprocattr_io(procattr,
                              script_in  ? 1 : 0,
                              script_out ? 1 : 0,
                              script_err ? 1 : 0)            != APR_SUCCESS) ||
  -        (ap_setprocattr_dir(procattr,  ap_make_dirstr_parent(r->pool, 
r->filename)) != APR_SUCCESS) ||
  +        (ap_setprocattr_dir(procattr, ap_make_dirstr_parent(r->pool, 
r->filename))        != APR_SUCCESS) ||
           (ap_setprocattr_cmdtype(procattr, APR_PROGRAM)    != APR_SUCCESS)) {
           /* Something bad happened, tell the world. */
        ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  @@ -361,20 +334,7 @@
           rc = !APR_SUCCESS;
       }
       else {
  -
  -        rc = ap_tokenize_to_argv(child_context, argv0, &args);
  -        if (rc != APR_SUCCESS) {
  -            ap_snprintf(err_string, sizeof(err_string),
  -                        "argv[] allocation failed, reason: %s (errno = 
%d)\n",
  -                        strerror(errno), errno);
  -            write(STDERR_FILENO, err_string, strlen(err_string));
  -            ap_unblock_alarms();
  -
  -            exit(0);
  -        }
  -
  -        rc = ap_create_process(&procnew, r->filename, args,
  -                               env, procattr, child_context);
  +        rc = ap_create_process(&procnew, command, argv, env, procattr, p);
       
           if (rc != APR_SUCCESS) {
               /* Bad things happened. Everyone should have cleaned up. */
  @@ -388,37 +348,121 @@
                *       to make use of ap_proc_t instead of pid.
                */
               ap_get_os_proc(&fred, procnew);
  -            ap_note_subprocess(child_context, fred, kill_after_timeout);
  +            ap_note_subprocess(p, fred, kill_after_timeout);
   #endif
               if (script_in) {
  -                *script_in = ap_bcreate(child_context, B_WR);
  +                ap_get_childout(&file, procnew);
  +                iol = ap_create_file_iol(file);
  +                if (!iol)
  +                    return APR_EBADF;
  +                *script_in = ap_bcreate(p, B_RD);
  +                ap_bpush_iol(*script_in, iol);
               }
   
               if (script_out) {
  -                *script_out = ap_bcreate(child_context, B_RD);
  +                ap_get_childin(&file, procnew);
  +                iol = ap_create_file_iol(file);
  +                if (!iol)
  +                    return APR_EBADF;
  +                *script_out = ap_bcreate(p, B_WR);
  +                ap_bpush_iol(*script_out, iol);
               }
   
               if (script_err) {
  -                *script_err = ap_bcreate(child_context, B_RD);
  +                ap_get_childerr(&file, procnew);
  +                iol = ap_create_file_iol(file);
  +                if (!iol)
  +                    return APR_EBADF;
  +                *script_err = ap_bcreate(p, B_RD);
  +                ap_bpush_iol(*script_err, iol);
               }
           }
       }
       ap_unblock_alarms();
       return (rc);
   }
  +static ap_status_t build_argv_list(char **argv, request_rec *r, ap_context_t 
*p) 
  +{
  +    int numwords, x, idx;
  +    char *w;
  +    const char *args = r->args;
  +
  +    if (!args || !args[0] || strchr(args, '=')) {
  +       *argv = NULL;
  +    }
  +    else {
  +        /* count the number of keywords */
  +        for (x = 0, numwords = 1; args[x]; x++) {
  +            if (args[x] == '+') {
  +                ++numwords;
  +            }
  +        }
  +        if (numwords > APACHE_ARG_MAX) {
  +            numwords = APACHE_ARG_MAX;       /* Truncate args to prevent 
overrun */
  +        }
  +        argv = (char **) ap_palloc(p, numwords * sizeof(char *));
  +
  +        for (x = 0; x < numwords; x++) {
  +            w = ap_getword_nulls(p, &args, '+');
  +            ap_unescape_url(w);
  +            argv[idx++] = ap_escape_shell_cmd(p, w);
  +        }
  +        argv[idx] = NULL;
  +    }
  +
  +    return APR_SUCCESS;
  +}
  +
  +static ap_status_t build_command_line(char **c, request_rec *r, ap_context_t 
*p) 
  +{
  +#ifdef WIN32
  +    char *quoted_filename = NULL;
  +    char *interpreter = NULL;
  +    file_type_e fileType;
  +
  +    *c = NULL;
  +    fileType = ap_get_win32_interpreter(r, &interpreter);
  +
  +    if (fileType == eFileTypeUNKNOWN) {
  +        ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
  +                      "%s is not executable; ensure interpreted scripts have 
"
  +                      "\"#!\" first line", 
  +                      r->filename);
  +        return APR_EBADF;
  +    }
  +
  +    /*
  +     * Build the command string to pass to ap_create_process()
  +     */
  +    quoted_filename = ap_pstrcat(p, "\"", r->filename, "\"", NULL);
  +    if (interpreter && *interpreter) {
  +        *c = ap_pstrcat(p, interpreter, " ", quoted_filename, " ", NULL);
  +    }
  +    else {
  +        *c = ap_pstrcat(p, quoted_filename, " ", NULL);
  +    }
  +#else
  +    *c = ap_pstrcat(p, r->filename, NULL);
  +#endif
  +    return APR_SUCCESS;
  +}
   
   static int cgi_handler(request_rec *r)
   {
       int retval, nph, dbpos = 0;
       char *argv0, *dbuf = NULL;
  +    char *command;
  +    char *argv;
  +
       BUFF *script_out, *script_in, *script_err;
       char argsbuffer[HUGE_STRING_LEN];
       int is_included = !strcmp(r->protocol, "INCLUDED");
       void *sconf = r->server->module_config;
  +    ap_context_t *p;
       cgi_server_conf *conf =
       (cgi_server_conf *) ap_get_module_config(sconf, &cgi_module);
   
  -    struct cgi_child_stuff cld;
  +    p = r->main ? r->main->pool : r->pool;
   
       if (r->method_number == M_OPTIONS) {
        /* 99 out of 100 CGI scripts, this is all they support */
  @@ -465,32 +509,33 @@
        return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
                               "attempt to invoke directory as script");
   
  +/*
  +    if (!ap_suexec_enabled) {
  +     if (!ap_can_exec(&r->finfo))
  +         return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
  +                                "file permissions deny server execution");
  +    }
  +
  +*/
       if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
        return retval;
   
       ap_add_common_vars(r);
  -    cld.argv0 = argv0;
  -    cld.r = r;
  -    cld.nph = nph;
  -    cld.debug = conf->logname ? 1 : 0;
  -#ifdef TPF
  -    cld.t.filename = r->filename;
  -    cld.t.subprocess_env = r->subprocess_env;
  -    cld.t.prog_type = FORK_FILE;
  -#endif   /* TPF */
  -
  -#ifdef CHARSET_EBCDIC
  -    /* XXX:@@@ Is the generated/included output ALWAYS in text/ebcdic 
format? */
  -    /* Or must we check the Content-Type first? */
  -    ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1);
  -#endif /*CHARSET_EBCDIC*/
   
  -    /*
  -     * we spawn out of r->main if it's there so that we can avoid
  -     * waiting for free_proc_chain to cleanup in the middle of an
  -     * SSI request -djg
  -     */
  -    if (cgi_child(&cld, &script_out, &script_in, &script_err) != 
APR_SUCCESS) {
  +    /* build the command line */
  +    if (build_command_line(&command, r, p) != APR_SUCCESS) {
  +        ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  +                      "couldn't spawn child process: %s", r->filename);
  +        return HTTP_INTERNAL_SERVER_ERROR;
  +    }
  +    /* build the argument list */
  +    else if (build_argv_list(&argv, r, p) != APR_SUCCESS) {
  +        ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  +                      "couldn't spawn child process: %s", r->filename);
  +        return HTTP_INTERNAL_SERVER_ERROR;
  +    }
  +    /* run the script in its own process */
  +    else if (run_cgi_child(&script_out, &script_in, &script_err, command, 
&argv, r, p) != APR_SUCCESS) {
           ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
                         "couldn't spawn child process: %s", r->filename);
           return HTTP_INTERNAL_SERVER_ERROR;
  @@ -499,7 +544,6 @@
       /* Transfer any put/post args, CERN style...
        * Note that we already ignore SIGPIPE in the core server.
        */
  -
       if (ap_should_client_block(r)) {
        int dbsize, len_read;
   
  @@ -528,9 +572,7 @@
                break;
            }
        }
  -
        ap_bflush(script_out);
  -
       }
   
       ap_bclose(script_out);
  
  
  

Reply via email to