process.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:6k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** process.c
  3. **
  4. ** Copyright (c) 1994-1997 Peter Eriksson <pen@signum.se>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <unistd.h>
  20. #include <wait.h>
  21. #include <errno.h>
  22. #include <signal.h>
  23. #include <syslog.h>
  24. #include <string.h>
  25. #include <sys/time.h>
  26. #include <sys/resource.h>
  27. #include <stdlib.h>
  28. #include "phttpd.h"
  29. int proc_run(char *path,
  30.      uid_t uid, gid_t gid, char *cgi_newroot,
  31.      rlim_t niceval, rlim_t vmem, rlim_t fd_max, rlim_t maxcputime,
  32.      int stdin_fd, int stdout_fd, int stderr_fd,
  33.      char **argv, char **envp,
  34.      char *wdir, char *cgi_basedir)
  35. {
  36.     pid_t pid;
  37.     int i, s;
  38.     char *rpath = NULL;
  39.     char *err, *err2;
  40.     struct rlimit rlp;
  41.     if (debug > 4)
  42. fprintf(stderr,
  43. "proc_run("%s", uid=%d, gid=%d, stdin=%d, stdout=%d, stderr=%d, ..., wdir=%s, cgi_basedir=%s)n",
  44. path, (int) uid, (int) gid, stdin_fd, stdout_fd, stderr_fd,
  45. wdir ? wdir : "<null>", cgi_basedir ? cgi_basedir : "<null>" );
  46.     
  47.     /* Create subprocess */
  48.     pid = fork1();
  49.     if (pid == 0)
  50.     {
  51. /* Close all open file descriptors */
  52. for (i = 0; i < max_fds; i++)
  53.     if (i != stdin_fd &&
  54. i != stdout_fd &&
  55. i != stderr_fd)
  56. s_close(i);
  57. s = 3;
  58. /* Make sure stdin, stdout and stderr don't interfere */
  59. if (stdin_fd >= s)
  60.     s = stdin_fd+1;
  61. if (stdout_fd >= s)
  62.     s = stdout_fd+1;
  63. if (stderr_fd >= s+1)
  64.     s = stderr_fd;
  65. /* Stdin_Fd at Stdout_Fd or Stderr_Fd? Relocate out of way */
  66. if (stdin_fd == 1 || stdin_fd == 2)
  67. {
  68.     s_dup2(stdin_fd, ++s);
  69.     s_close(stdin_fd);
  70.     stdin_fd = s;
  71. }
  72. /* Stdout_Fd at Stdin_Fd or Stderr_Fd?, Relocate out of way */
  73. if (stdout_fd == 0 || stdout_fd == 2)
  74. {
  75.     s_dup2(stdout_fd, ++s);
  76.     s_close(stdout_fd);
  77.     stdout_fd = s;
  78. }
  79. /* Stderr_Fd at Stdin_Fd or Stdout_Fd?, Relocate out of way */
  80. if (stderr_fd == 0 || stderr_fd == 1)
  81. {
  82.     s_dup2(stderr_fd, ++s);
  83.     s_close(stderr_fd);
  84.     stderr_fd = s;
  85. }
  86. /* Move Stdin_Fd to fd #0 */
  87. if (stdin_fd > 0)
  88. {
  89.     s_dup2(stdin_fd, 0);
  90.     s_close(stdin_fd);
  91. }
  92. /* Move Stdout_Fd to fd #1 */
  93. if (stdout_fd != -1 && stdout_fd != 1)
  94. {
  95.     s_dup2(stdout_fd, 1);
  96.     s_close(stdout_fd);
  97. }
  98. /* Move Stderr_Fd to fd #2 */
  99. if (stderr_fd != -1 && stderr_fd != 2)
  100. {
  101.     s_dup2(stderr_fd, 2);
  102.     s_close(stderr_fd);
  103. }
  104. /* in case we have vmem limit ...*/
  105. if ( vmem != 0 ) 
  106. {
  107.     rlp.rlim_cur=vmem;
  108.     rlp.rlim_max=vmem;
  109.     setrlimit(RLIMIT_VMEM,&rlp);
  110. }
  111. /* and do we have a fd_max ? */
  112. if ( fd_max != 0 )
  113. {
  114.     rlp.rlim_cur=fd_max;
  115.     rlp.rlim_max=fd_max;
  116.     setrlimit(RLIMIT_NOFILE,&rlp);
  117. }
  118. /* and do we have CPU-time-limit ? */
  119. if ( maxcputime != 0 )
  120. {
  121.     rlp.rlim_cur=maxcputime;
  122.     rlp.rlim_max=maxcputime;
  123.     setrlimit(RLIMIT_CPU,&rlp);
  124.     signal(SIGXCPU,exit); /* set abort on SIGXCPU :-) */
  125. }
  126. /* in case we have nicevalue, set it ! */
  127. if ( niceval != 0 )
  128.     s_nice(niceval);
  129. /* In case we have a newroot ... */
  130. if ( cgi_newroot != NULL )
  131. {
  132.     s_chdir(cgi_newroot);
  133.             seteuid(0);
  134.     if ( s_chroot(cgi_newroot) == -1 )
  135.     {
  136. err = "chroot()";
  137. goto Fail;
  138.     }
  139.     if ( cgi_basedir == NULL )
  140.     {
  141.       if ( rkmultimode || softvirtserver ) rpath=strchr(path,'/');
  142.       else rpath=path;
  143.       if ( softvirtserver && rkmultimode && rpath!=NULL ) rpath=strchr(rpath+1,'/');
  144.     }
  145.     else
  146.       rpath=path;
  147. }
  148. else /* we do not have chroot */
  149.   { 
  150.   if (wdir)
  151.   {
  152.     s_chdir(wdir);
  153.             if ( path[0] != '/' )
  154. rpath=path+strlen(wdir)+1;
  155.     else
  156. rpath=path;
  157.           }
  158.   else
  159.     rpath=path;
  160.          } 
  161. /* Fix the user and group id's for the process */
  162. if ((uid != -1 || gid != -1) && getuid() == 0)
  163. {
  164.     if (uid == -1)
  165. uid = geteuid();
  166.     if (gid == -1)
  167. gid = getegid();
  168.     
  169.     seteuid(0);
  170.     setegid(getgid());
  171.     
  172.     if (gid != -1)
  173.     {
  174. s = setgid(gid);
  175. if (s < 0)
  176. {
  177.     err = "setgid()";
  178.     goto Fail;
  179. }
  180.     }
  181.     
  182.     if (uid != -1)
  183.     {
  184. s = setuid(uid);
  185. if (s < 0)
  186. {
  187.     err = "setuid()";
  188.     goto Fail;
  189. }
  190.     }
  191. }
  192. s_execve(rpath, argv, envp);
  193. err = "s_execve()";
  194.       Fail:
  195. err2 = strerror(errno);
  196. s_write(2, "proc_run("", 10);
  197. s_write(2, rpath, strlen(rpath));
  198. s_write(2, "") failed: ", 11);
  199. s_write(2, err, strlen(err));
  200. s_write(2, ": ", 2);
  201. s_write(2, err2, strlen(err2));
  202. s_write(2, "rn", 2);
  203. _exit(1);
  204.     }
  205.     
  206.     return pid;
  207. }
  208. /* Returns 0 = normal exit(), 1 = Died because of a  Signal, 2 = Unknown */
  209. int proc_wait(pid_t pid, int *code)
  210. {
  211.     int status;
  212.     if (debug > 4)
  213. fprintf(stderr, "proc_wait(): Before s_waitpid()n");
  214.     
  215.   Again:
  216.     s_waitpid(pid, &status, 0);
  217.     if (debug > 1)
  218. fprintf(stderr,
  219. "Process %d exited, status = %dn",
  220. (int) pid,
  221. status);
  222.     
  223.     if (WIFEXITED(status))
  224.     {
  225. /* Process called exit() */
  226. *code = WEXITSTATUS(status);
  227. return PROC_EXIT;
  228.     }
  229.     
  230.     else if (WIFSIGNALED(status))
  231.     {
  232. /* Process died with a Signal */
  233. *code = WTERMSIG(status);
  234. return PROC_SIGNAL;
  235.     }
  236.     else if (WIFSTOPPED(status) ||
  237.      WIFCONTINUED(status))
  238.     {
  239. goto Again;
  240.     }
  241.     /* Unknown termination reason */
  242.     return PROC_OTHER;
  243. }