📄 proc.c
字号:
new->out = attr->parent_out; if (attr->errchk) { if (attr->currdir) { if (access(attr->currdir, X_OK) == -1) { /* chdir() in child wouldn't have worked */ return errno; } } if (attr->cmdtype == APR_PROGRAM || attr->cmdtype == APR_PROGRAM_ENV || *progname == '/') { /* for both of these values of cmdtype, caller must pass * full path, so it is easy to check; * caller can choose to pass full path for other * values of cmdtype */ if (access(progname, R_OK|X_OK) == -1) { /* exec*() in child wouldn't have worked */ return errno; } } else { /* todo: search PATH for progname then try to access it */ } } if ((new->pid = fork()) < 0) { return errno; } else if (new->pid == 0) { int status; /* child process */ /* * If we do exec cleanup before the dup2() calls to set up pipes * on 0-2, we accidentally close the pipes used by programs like * mod_cgid. * * If we do exec cleanup after the dup2() calls, cleanup can accidentally * close our pipes which replaced any files which previously had * descriptors 0-2. * * The solution is to kill the cleanup for the pipes, then do * exec cleanup, then do the dup2() calls. */ if (attr->child_in) { apr_pool_cleanup_kill(apr_file_pool_get(attr->child_in), attr->child_in, apr_unix_file_cleanup); } if (attr->child_out) { apr_pool_cleanup_kill(apr_file_pool_get(attr->child_out), attr->child_out, apr_unix_file_cleanup); } if (attr->child_err) { apr_pool_cleanup_kill(apr_file_pool_get(attr->child_err), attr->child_err, apr_unix_file_cleanup); } apr_pool_cleanup_for_exec(); if (attr->child_in) { apr_file_close(attr->parent_in); dup2(attr->child_in->filedes, STDIN_FILENO); apr_file_close(attr->child_in); } if (attr->child_out) { apr_file_close(attr->parent_out); dup2(attr->child_out->filedes, STDOUT_FILENO); apr_file_close(attr->child_out); } if (attr->child_err) { apr_file_close(attr->parent_err); dup2(attr->child_err->filedes, STDERR_FILENO); apr_file_close(attr->child_err); } apr_signal(SIGCHLD, SIG_DFL); /* not sure if this is needed or not */ if (attr->currdir != NULL) { if (chdir(attr->currdir) == -1) { if (attr->errfn) { attr->errfn(pool, errno, "change of working directory failed"); } exit(-1); /* We have big problems, the child should exit. */ } } /* Only try to switch if we are running as root */ if (attr->gid != -1 && !geteuid()) { if ((status = setgid(attr->gid))) { if (attr->errfn) { attr->errfn(pool, errno, "setting of group failed"); } exit(-1); /* We have big problems, the child should exit. */ } } if (attr->uid != -1 && !geteuid()) { if ((status = setuid(attr->uid))) { if (attr->errfn) { attr->errfn(pool, errno, "setting of user failed"); } exit(-1); /* We have big problems, the child should exit. */ } } if ((status = limit_proc(attr)) != APR_SUCCESS) { if (attr->errfn) { attr->errfn(pool, errno, "setting of resource limits failed"); } exit(-1); /* We have big problems, the child should exit. */ } if (attr->cmdtype == APR_SHELLCMD || attr->cmdtype == APR_SHELLCMD_ENV) { int onearg_len = 0; const char *newargs[4]; newargs[0] = SHELL_PATH; newargs[1] = "-c"; i = 0; while (args[i]) { onearg_len += strlen(args[i]); onearg_len++; /* for space delimiter */ i++; } switch(i) { case 0: /* bad parameters; we're doomed */ break; case 1: /* no args, or caller already built a single string from * progname and args */ newargs[2] = args[0]; break; default: { char *ch, *onearg; ch = onearg = apr_palloc(pool, onearg_len); i = 0; while (args[i]) { size_t len = strlen(args[i]); memcpy(ch, args[i], len); ch += len; *ch = ' '; ++ch; ++i; } --ch; /* back up to trailing blank */ *ch = '\0'; newargs[2] = onearg; } } newargs[3] = NULL; if (attr->detached) { apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); } if (attr->cmdtype == APR_SHELLCMD) { execve(SHELL_PATH, (char * const *) newargs, (char * const *)env); } else { execv(SHELL_PATH, (char * const *)newargs); } } else if (attr->cmdtype == APR_PROGRAM) { if (attr->detached) { apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); } execve(progname, (char * const *)args, (char * const *)env); } else if (attr->cmdtype == APR_PROGRAM_ENV) { if (attr->detached) { apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); } execv(progname, (char * const *)args); } else { /* APR_PROGRAM_PATH */ if (attr->detached) { apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); } execvp(progname, (char * const *)args); } if (attr->errfn) { char *desc; desc = apr_psprintf(pool, "exec of '%s' failed", progname); attr->errfn(pool, errno, desc); } exit(-1); /* if we get here, there is a problem, so exit with an * error code. */ } /* Parent process */ if (attr->child_in) { apr_file_close(attr->child_in); } if (attr->child_out) { apr_file_close(attr->child_out); } if (attr->child_err) { apr_file_close(attr->child_err); } return APR_SUCCESS;}APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, int *exitcode, apr_exit_why_e *exitwhy, apr_wait_how_e waithow, apr_pool_t *p){ proc->pid = -1; return apr_proc_wait(proc, exitcode, exitwhy, waithow);}APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, int *exitcode, apr_exit_why_e *exitwhy, apr_wait_how_e waithow){ pid_t pstatus; int waitpid_options = WUNTRACED; int exit_int; int ignore; apr_exit_why_e ignorewhy; if (exitcode == NULL) { exitcode = &ignore; } if (exitwhy == NULL) { exitwhy = &ignorewhy; } if (waithow != APR_WAIT) { waitpid_options |= WNOHANG; } do { pstatus = waitpid(proc->pid, &exit_int, waitpid_options); } while (pstatus < 0 && errno == EINTR); if (pstatus > 0) { proc->pid = pstatus; if (WIFEXITED(exit_int)) { *exitwhy = APR_PROC_EXIT; *exitcode = WEXITSTATUS(exit_int); } else if (WIFSIGNALED(exit_int)) { *exitwhy = APR_PROC_SIGNAL;#ifdef WCOREDUMP if (WCOREDUMP(exit_int)) { *exitwhy |= APR_PROC_SIGNAL_CORE; }#endif *exitcode = WTERMSIG(exit_int); } else { /* unexpected condition */ return APR_EGENERAL; } return APR_CHILD_DONE; } else if (pstatus == 0) { return APR_CHILD_NOTDONE; } return errno;}APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, apr_int32_t what, struct rlimit *limit){ switch(what) { case APR_LIMIT_CPU:#ifdef RLIMIT_CPU attr->limit_cpu = limit; break;#else return APR_ENOTIMPL;#endif case APR_LIMIT_MEM:#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS) attr->limit_mem = limit; break;#else return APR_ENOTIMPL;#endif case APR_LIMIT_NPROC:#ifdef RLIMIT_NPROC attr->limit_nproc = limit; break;#else return APR_ENOTIMPL;#endif case APR_LIMIT_NOFILE:#ifdef RLIMIT_NOFILE attr->limit_nofile = limit; break;#else return APR_ENOTIMPL;#endif } return APR_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -