⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http-cgi.c

📁 Serveez是一个服务器框架
💻 C
📖 第 1 页 / 共 2 页
字号:
 * cgi file (including the path). This MUST be freed afterwards. */char *http_pre_exec (svz_socket_t *sock,   /* socket structure */	       svz_envblock_t *envp, /* environment block to be filled */	       char *file,           /* plain executable name */	       char *request,        /* original http request */	       int type)             /* POST or GET ? */{  char *cgidir;  char *cgifile;  char *p;  http_config_t *cfg = sock->cfg;  /* change into the CGI directory temporarily */  if (chdir (cfg->cgidir) == -1)    {      svz_log (LOG_ERROR, "cgi: chdir: %s\n", SYS_ERROR);#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "cgi: cannot change dir: %s\n", cfg->cgidir);#endif      return NULL;    }  /* get the current directory  */  cgidir = svz_getcwd ();    /* put the directory and file together */  cgifile = svz_malloc (strlen (cgidir) + strlen (file) + 1);  sprintf (cgifile, "%s%s", cgidir, file);  svz_free (cgidir);  /* create the environment block for the CGI script */  http_create_cgi_envp (sock, envp, file, type);  /* put the QUERY_STRING into the env variables if necessary */  if (type == GET_METHOD)    {      p = request;      while (*p != '?' && *p != 0)	p++;      svz_envblock_add (envp, "QUERY_STRING=%s", *p ? p + 1 : "");    }  return cgifile;}/* * Write an initial HTTP response header to the socket SOCK * right after the the actual CGI script has been invoked. */inthttp_cgi_accepted (svz_socket_t *sock){  http_socket_t *http = sock->data;  http->response = 202;  return svz_sock_printf (sock, HTTP_OK			  "Date: %s\r\n"			  "Server: %s/%s\r\n"			  "Connection: close\r\n",			  http_asc_date (time (NULL)),			  svz_library, svz_version);}/* * This routine generates some standard cgi associations. */#define DEFAULT_CGIAPP "default"voidhttp_gen_cgi_apps (http_config_t *cfg){  char *p;  /* create the cgi association hash table if necessary */  if (cfg->cgiapps == NULL)    cfg->cgiapps = svz_hash_create (4);  /* the associations need to be in the hash to be executed at all */  if ((p = svz_hash_put (cfg->cgiapps, "exe", svz_strdup (DEFAULT_CGIAPP)))       != NULL)    svz_free (p);  if ((p = svz_hash_put (cfg->cgiapps, "com", svz_strdup (DEFAULT_CGIAPP)))      != NULL)    svz_free (p);  if ((p = svz_hash_put (cfg->cgiapps, "bat", svz_strdup (DEFAULT_CGIAPP)))      != NULL)    svz_free (p);}/* * Invoke a cgi script. In Unices we fork() us and in Win32 we * CreateProcess(). */inthttp_cgi_exec (svz_socket_t *sock, /* the socket structure */	       HANDLE in,      /* here the cgi reads from or NULL if GET */	       HANDLE out,     /* here the cgi writes to */	       char *file,     /* cgi script file */	       char *request,  /* original request (needed for GET) */	       int type)       /* request type (POST or GET) */{  HANDLE pid;    /* the pid from fork() or the process handle in Win32 */  char *cgifile; /* path including the name of the cgi script */  http_socket_t *http;  svz_envblock_t *envp;#ifdef __MINGW32__  http_config_t *cfg = sock->cfg;  STARTUPINFO StartupInfo;         /* store here the inherited handles */  PROCESS_INFORMATION ProcessInfo; /* where we get the process handle from */  char *savedir;                   /* save the original directory */  char *suffix, *p;  char *cgiapp;#else  char *argv[2];  struct stat buf;  int retries;#endif  /* Assign local CGI disconnection routine. */  sock->disconnected_socket = http_cgi_disconnect;#ifdef __MINGW32__  /*    * Clean the StartupInfo, use the stdio handles, and store the   * pipe handles there if necessary (depends on type).   */  memset (&StartupInfo, 0, sizeof (StartupInfo));  StartupInfo.cb = sizeof (StartupInfo);  StartupInfo.dwFlags = STARTF_USESTDHANDLES;  StartupInfo.hStdOutput = out;  /* StartupInfo.hStdError = out; */  if (type == POST_METHOD)    StartupInfo.hStdInput = in;  /* reserve buffer space for the environment block */  envp = svz_envblock_create ();  /* save the current directory */  savedir = svz_getcwd ();  if ((cgifile = http_pre_exec (sock, envp, file, request, type)) == NULL)    {      svz_sock_printf (sock, HTTP_INTERNAL_ERROR "\r\n");      http_error_response (sock, 500);      sock->userflags |= HTTP_FLAG_DONE;      chdir (savedir);      svz_envblock_destroy (envp);      svz_free (savedir);      return -1;    }  /* find a cgi interpreter if possible */  p = cgifile + strlen (cgifile) - 1;  while (p != cgifile && *p != '.')    p--;  suffix = p + 1;  if ((p = svz_hash_get (cfg->cgiapps, svz_tolower (suffix))) != NULL)    {      if (strcmp (p, DEFAULT_CGIAPP))	{	  cgiapp = svz_malloc (strlen (cgifile) + strlen (p) + 2);	  sprintf (cgiapp, "%s %s", p, cgifile);	  svz_free (cgifile);	  cgifile = cgiapp;	}    }  /* not a valid file extension */  else    {      /* find an appropriate system association */      cgiapp = svz_malloc (MAX_PATH);      if (FindExecutable (cgifile, NULL, cgiapp) <= (HINSTANCE) 32)	svz_log (LOG_ERROR, "FindExecutable: %s\n", SYS_ERROR);#if ENABLE_DEBUG      /* if this is enabled you could learn about the system */      else	svz_log (LOG_DEBUG, "FindExecutable: %s\n", cgiapp);#endif      svz_free (cgiapp);      /* print some error message */      svz_sock_printf (sock, HTTP_ACCESS_DENIED "\r\n");      http_error_response (sock, 403);      sock->userflags |= HTTP_FLAG_DONE;      chdir (savedir);      svz_free (cgifile);      svz_envblock_destroy (envp);      svz_free (savedir);      return -1;    }  /* send http header response */  if (http_cgi_accepted (sock) == -1)    {      sock->userflags |= HTTP_FLAG_DONE;      chdir (savedir);      svz_free (cgifile);      svz_envblock_destroy (envp);      svz_free (savedir);      return -1;    }  /* create the process here */  if (!CreateProcess (NULL,                    /* ApplicationName */		      cgifile,                 /* CommandLine */		      NULL,                    /* ProcessAttributes */		      NULL,                    /* ThreadAttributes */		      TRUE,                    /* InheritHandles */		      DETACHED_PROCESS,        /* CreationFlags */		      svz_envblock_get (envp), /* Environment */		      NULL,                    /* CurrentDirectory */		      &StartupInfo, &ProcessInfo))    {      svz_log (LOG_ERROR, "cgi: CreateProcess: %s\n", SYS_ERROR);#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "cgi: cannot execute: %s\n", cgifile);#endif      svz_sock_printf (sock, "\r\n");      sock->userflags |= HTTP_FLAG_DONE;      chdir (savedir);      svz_free (cgifile);      svz_envblock_destroy (envp);      svz_free (savedir);      return -1;    }    /* reenter the actual directory and free reserved space */  chdir (savedir);  svz_free (cgifile);  svz_envblock_destroy (envp);  svz_free (savedir);  pid = ProcessInfo.hProcess;#ifdef ENABLE_DEBUG  svz_log (LOG_DEBUG, "http: cgi %s got pid 0x%08X\n", 	   file + 1, ProcessInfo.dwProcessId);#endif#else /* not __MINGW32__ */  retries = 3; retry:  /* fork us here */  if ((pid = fork ()) == 0)    {      /* ------ child process here ------ */      /* create environment block */      envp = svz_envblock_create ();      if ((cgifile = http_pre_exec (sock, envp, file, request, type)) == NULL)	{	  exit (0);	}      /* make the output blocking */      if (fcntl (out, F_SETFL, ~O_NONBLOCK) == -1)	{	  svz_log (LOG_ERROR, "cgi: fcntl: %s\n", SYS_ERROR);	  exit (0);	}      /* duplicate the receiving pipe descriptor to stdout */      if (dup2 (out, 1) != 1)	{	  svz_log (LOG_ERROR, "cgi: dup2: %s\n", SYS_ERROR);	  exit (0);	}#ifndef ENABLE_DEBUG      /* duplicate stderr to the cgi output */      if (dup2 (out, 2) != 2)	{	  svz_log (LOG_ERROR, "cgi: dup2: %s\n", SYS_ERROR);	  exit (0);	}#endif /* !ENABLE_DEBUG */      /* handle post method */      if (type == POST_METHOD)	{	  /* make the input blocking */	  if (fcntl (in, F_SETFL, ~O_NONBLOCK) == -1)	    {	      svz_log (LOG_ERROR, "cgi: fcntl: %s\n", SYS_ERROR);	      exit (0);	    }	  /* duplicate the sending pipe descriptor to stdin */	  if (dup2 (in, 0) != 0)	    {	      svz_log (LOG_ERROR, "cgi: dup2: %s\n", SYS_ERROR);	      exit (0);	    }	  /* close the old file descriptors */	  if (close (in) < 0)	    svz_log (LOG_ERROR, "cgi: close: %s\n", SYS_ERROR);	}      /* close remaining stdin in get method */      else	{	  close (0);	}      /* close the old file descriptors */      if (close (out) < 0)	svz_log (LOG_ERROR, "cgi: close: %s\n", SYS_ERROR);      /* get the cgi scripts permissions */      if (stat (cgifile, &buf) == -1)	{	  svz_log (LOG_ERROR, "cgi: stat: %s\n", SYS_ERROR);	  exit (0);	}      /* set the appropriate user permissions */      if (setgid (buf.st_gid) == -1)	{	  svz_log (LOG_ERROR, "cgi: setgid: %s\n", SYS_ERROR);	  exit (0);	}      if (setuid (buf.st_uid) == -1)	{	  svz_log (LOG_ERROR, "cgi: setuid: %s\n", SYS_ERROR);	  exit (0);	}      /* create the argv[] and envp[] pointers */      argv[0] = cgifile;      argv[1] = NULL;      /*        * Execute the CGI script itself here. This will overwrite the        * current process.       */      if (execve (cgifile, argv, svz_envblock_get (envp)) == -1)	{	  svz_log (LOG_ERROR, "cgi: execve: %s\n", SYS_ERROR);	  exit (0);	}    }  else if (pid == -1)    {      if (errno == EAGAIN && --retries)	{	  /* sleep (1); */	  goto retry;	}      /* ------ error forking new process ------ */      svz_log (LOG_ERROR, "cgi: fork: %s\n", SYS_ERROR);      svz_sock_printf (sock, HTTP_BAD_REQUEST "\r\n");      http_error_response (sock, 400);      sock->userflags |= HTTP_FLAG_DONE;      return -1;    }  /* ------ still current (parent) process here ------ */#ifdef ENABLE_DEBUG  svz_log (LOG_DEBUG, "http: cgi %s got pid %d\n", file + 1, pid);#endif  /* send http header response */  if (http_cgi_accepted (sock) == -1)    {      sock->userflags |= HTTP_FLAG_DONE;      return -1;    }#endif /* not __MINGW32__ */  /* save the process id */  http = sock->data;  http->pid = pid;  /* close the inherited http data handles */  if (closehandle (out) == -1)    {      svz_log (LOG_ERROR, "cgi: close: %s\n", SYS_ERROR);    }  if (type == POST_METHOD)    {      /* close the reading end of the pipe for the post data */      if (closehandle (in) == -1)	{	  svz_log (LOG_ERROR, "cgi: close: %s\n", SYS_ERROR);	}    }  return 0;}/* * The http GET cgi request response. */inthttp_cgi_get_response (svz_socket_t *sock, char *request, int flags){  HANDLE cgi2s[2];  char *file;  /* check if this is a cgi request at all */  if ((file = http_check_cgi (sock, request)) == HTTP_NO_CGI)    return -2;  if (file == NULL)    {      svz_sock_printf (sock, HTTP_INTERNAL_ERROR "\r\n");      http_error_response (sock, 500);      sock->userflags |= HTTP_FLAG_DONE;      return -1;    }  /* create a pipe for the cgi script process */  if (svz_pipe_create_pair (cgi2s) == -1)    {      svz_sock_printf (sock, HTTP_INTERNAL_ERROR "\r\n");      http_error_response (sock, 500);      sock->userflags |= HTTP_FLAG_DONE;      svz_free (file);      return -1;    }  /* execute the cgi script in FILE */  sock->userflags |= HTTP_FLAG_CGI;  sock->flags |= SOCK_FLAG_RECV_PIPE;  sock->read_socket = http_cgi_read;  sock->pipe_desc[READ] = cgi2s[READ];  svz_fd_cloexec ((int) cgi2s[READ]);  if (http_cgi_exec (sock, INVALID_HANDLE, cgi2s[WRITE], 		     file, request, GET_METHOD))    {      /* some error occurred here */      sock->read_socket = svz_tcp_read_socket;      svz_free (file);      return -1;    }  svz_free (file);  return 0;}/* * The http POST request response. */inthttp_post_response (svz_socket_t *sock, char *request, int flags){  char *file;  char *length;  HANDLE s2cgi[2];  HANDLE cgi2s[2];  http_socket_t *http;  /* get http socket structure */  http = sock->data;  /* is this a valid POST request ? */  file = http_check_cgi (sock, request);  if (file == NULL || file == HTTP_NO_CGI)    {      svz_sock_printf (sock, HTTP_INTERNAL_ERROR "\r\n");      http_error_response (sock, 500);      sock->userflags |= HTTP_FLAG_DONE;      return -1;    }  /* create a pair of pipes for the cgi script process */  if (svz_pipe_create_pair (cgi2s) == -1)    {      svz_sock_printf (sock, HTTP_INTERNAL_ERROR "\r\n");      http_error_response (sock, 500);      sock->userflags |= HTTP_FLAG_DONE;      svz_free (file);      return -1;    }  if (svz_pipe_create_pair (s2cgi) == -1)    {      svz_sock_printf (sock, HTTP_INTERNAL_ERROR "\r\n");      http_error_response (sock, 500);      sock->userflags |= HTTP_FLAG_DONE;      svz_free (file);      return -1;    }  /* get the content length from the header information */  if ((length = http_find_property (http, "Content-length")) == NULL)    {      svz_sock_printf (sock, HTTP_BAD_REQUEST "\r\n");      http_error_response (sock, 411);      sock->userflags |= HTTP_FLAG_DONE;      svz_free (file);      return -1;    }  http->contentlength = svz_atoi (length);  /* prepare everything for the cgi pipe handling */  sock->pipe_desc[WRITE] = s2cgi[WRITE];  sock->pipe_desc[READ] = cgi2s[READ];  svz_fd_cloexec ((int) s2cgi[WRITE]);  svz_fd_cloexec ((int) cgi2s[READ]);  /* execute the cgi script in FILE */  if (http_cgi_exec (sock, s2cgi[READ], cgi2s[WRITE], 		     file, request, POST_METHOD))    {      /* some error occurred here */      sock->read_socket = svz_tcp_read_socket;      sock->write_socket = http_default_write;      svz_free (file);      return -1;    }  sock->write_socket = http_cgi_write;  sock->flags |= SOCK_FLAG_SEND_PIPE;  sock->userflags |= HTTP_FLAG_POST;  svz_free (file);  return 0;}#else /* ENABLE_HTTP_PROTO */int http_cgi_dummy; /* Shut up compiler warnings. */#endif /* not ENABLE_HTTP_PROTO */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -