Skip to content
Snippets Groups Projects
thttpd_cgi.c 29.6 KiB
Newer Older

  if (hc->method == METHOD_GET || hc->method == METHOD_POST)
    {
#ifdef CONFIG_THTTPD_CGILIMIT
      if (hc->hs->cgi_count >= CONFIG_THTTPD_CGILIMIT)
        {
          httpd_send_err(hc, 503, httpd_err503title, "", httpd_err503form,
                         hc->encodedurl);
          goto errout_with_sem;
        }
#endif
      ++hc->hs->cgi_count;
      httpd_clear_ndelay(hc->conn_fd);

      /* Start the child task.  We use a trampoline task here so that we can
       * safely muck with the file descriptors before actually started the CGI
       * task.
       */

      snprintf(arg, 16, "%p", hc); /* task_create doesn't handle binary arguments. */
      argv[0] = arg;

#ifndef CONFIG_CUSTOM_STACK
      child = task_create("CGI child", CONFIG_THTTPD_CGI_PRIORITY,
                          CONFIG_THTTPD_CGI_STACKSIZE,
                          (main_t)cgi_child, (const char **)argv);
#else
      child = task_create("CGI child", CONFIG_THTTPD_CGI_PRIORITY,
                          (main_t)cgi_child, (const char **)argv);
#endif
      if (child < 0)
        {
          ndbg("task_create: %d\n", errno);
          INTERNALERROR("task_create");
          httpd_send_err(hc, 500, err500title, "", err500form, hc->encodedurl);
          goto errout_with_sem;
        }

      ndbg("Started CGI task %d for file '%s'\n", child, hc->expnfilename);

      /* Wait for the CGI threads to become initialized */

      cgi_semtake();

      hc->bytes_sent    = CONFIG_THTTPD_CGI_BYTECOUNT;
      hc->should_linger = false;
    }
  else
    {
      NOTIMPLEMENTED("CGI");
      httpd_send_err(hc, 501, err501title, "", err501form, httpd_method_str(hc->method));
      goto errout_with_sem;
    }

  /* Successfully started */

  retval = OK;

errout_with_sem:
  sem_destroy(&g_cgisem);
  return retval;
}

#if CONFIG_THTTPD_CGI_TIMELIMIT > 0
static void cgi_kill(ClientData client_data, struct timeval *nowP)
{
  pid_t pid = (pid_t)client_data.i;

  /* task_delete() is a very evil API.  It can leave memory stranded! */

  nlldbg("Killing CGI child: %d\n", pid);
  if (task_delete(pid) != 0)
    {
      nlldbg("task_delete() failed: %d\n", errno);
    }
}
#endif

#endif /* CONFIG_THTTPD && CONFIG_THTTPD_CGI_PATTERN */