📄 os.c
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * This file will include OS specific functions which are not inlineable. * Any inlineable functions should be defined in os-inline.c instead. */#include "httpd.h"#include "http_core.h"#include "os.h"#include "scoreboard.h"#include "http_log.h"#include "http_conf_globals.h"#ifdef TPF41#ifdef __PIPE_#include <ipc.h>#include <shm.h>static TPF_FD_LIST *tpf_fds = NULL;#endif /* __PIPE_ */#else#include <sys/ipc.h> #include <sys/shm.h>static TPF_FD_LIST *tpf_fds = NULL;#endif /* TPF41 */void *tpf_shm_static_ptr = NULL;unsigned short zinet_model;char *argv_ptr = NULL;static FILE *sock_fp;static int sock_sd;int tpf_select(int maxfds, fd_set *reads, fd_set *writes, fd_set *excepts, struct timeval *tv){/* We're going to force our way through select. We're only interested reads and TPF allows 2billion+ socket descriptors for we don't want an fd_set that big. Just assume that maxfds-1 contains the socket descriptor we're interested in. If it's 0, leave it alone. */ int sockets[1]; int no_reads = 0; int no_writes = 0; int no_excepts = 0; int timeout_seconds = 0; int timeout_millisec = 0; int rv = 0; if(maxfds) { if(tv) timeout_millisec = tv->tv_sec * 1000 + tv->tv_usec; sockets[0] = maxfds-1; no_reads++; } else sockets[0] = 0; ap_check_signals(); if ((no_reads + no_writes + no_excepts == 0) && (tv) && (tv->tv_sec + tv->tv_usec != 0)) { /* TPF's select immediately returns if the sum of no_reads, no_writes, and no_excepts is zero. The following code makes TPF's select work a little closer to everyone else's select: */#ifdef TPF_HAVE_SAWNC struct ev0bk evnblock;#endif /* event processing uses seconds, select uses milliseconds */ timeout_seconds = tv->tv_sec; if (tv->tv_usec) { timeout_seconds++; /* round up to seconds (like TPF's select does) */ } if (timeout_seconds > 0) { /* paranoid check for valid timeout */#ifdef TPF_HAVE_SAWNC evnblock.evnpstinf.evnbkc1 = 1; /* nbr of posts needed */ evntc(&evnblock, EVENT_CNT, 'N', timeout_seconds, EVNTC_1052); tpf_sawnc(&evnblock, EVENT_CNT);#else sleep(timeout_seconds);#endif } } else { if (timeout_millisec < 0) { /* paranoid check for valid timeout */ timeout_millisec = 0; } if (timeout_millisec != 0) timeout_millisec += 1000; rv = select(sockets, no_reads, no_writes, no_excepts, timeout_millisec); } ap_check_signals(); return rv;}int tpf_accept(int sockfd, struct sockaddr *peer, int *paddrlen){ extern pid_t tpf_parent_pid; int socks[1]; int rv; socks[0] = sockfd; rv = select(socks, 1, 0, 0, 1 * 1000); ap_check_signals(); if ((rv == 0) && (errno == 0)) { /* select timed out */ errno = EINTR; /* make errno look like accept was interruped */ /* now's a good time to make sure our parent didn't abnormally exit */ if (getppid() == 1) { /* our parent is gone... close the socket so Apache can restart (it shouldn't still be open but we're taking no chances) */ closesocket(sockfd); ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, NULL, "child %d closing the socket because getppid()" " returned 1 instead of parent pid %d", getpid(), tpf_parent_pid); errno = 0; } return -1; } /* paranoid check for rv == 0 and errno != 0, should never happen */ if (rv == 0) { rv = -1; } if(rv>0) { rv = accept(sockfd, peer, paddrlen); errno = sock_errno(); } return rv;} /* the getpass function is not usable on TPF */char *getpass(const char* prompt){ errno = EIO; return((char *)NULL);}/* fork and exec functions are not defined on TPF due to the implementation of tpf_fork() */ pid_t fork(void){ errno = ENOSYS; return(-1);}int execl(const char *path, const char *arg0, ...){ errno = ENOSYS; return(-1);}int execle(const char *path, const char *arg0, ...){ errno = ENOSYS; return(-1);}int execve(const char *path, char *const argv[], char *const envp[]){ errno = ENOSYS; return(-1);}int execvp(const char *file, char *const argv[]){ errno = ENOSYS; return(-1);}int ap_tpf_spawn_child(pool *p, int (*func) (void *, child_info *), void *data, enum kill_conditions kill_how, int *pipe_in, int *pipe_out, int *pipe_err, int out_fds[], int in_fds[], int err_fds[]){ int i, temp_out=0, temp_in=0, temp_err=0, save_errno, pid, result=0; int fd_flags_out=0, fd_flags_in=0, fd_flags_err=0; struct tpf_fork_input fork_input; TPF_FORK_CHILD *cld = (TPF_FORK_CHILD *) data;#ifdef TPF_FORK_EXTENDED#define WHITE " \t\n"#define MAXARGC 49 char *arguments; char *args[MAXARGC + 1]; char **envp = NULL; pool *subpool = NULL;#include "util_script.h"#else array_header *env_arr = ap_table_elts ((array_header *) cld->subprocess_env); table_entry *elts = (table_entry *) env_arr->elts;#endif /* TPF_FORK_EXTENDED */ if (func) { if ((result=func(data, NULL))) { return 0; /* error from child function */ } } if (pipe_out) { fd_flags_out = fcntl(out_fds[0], F_GETFD); fcntl(out_fds[0], F_SETFD, FD_CLOEXEC); temp_out = dup(STDOUT_FILENO); fcntl(temp_out, F_SETFD, FD_CLOEXEC); dup2(out_fds[1], STDOUT_FILENO); } if (pipe_in) { fd_flags_in = fcntl(in_fds[1], F_GETFD); fcntl(in_fds[1], F_SETFD, FD_CLOEXEC); temp_in = dup(STDIN_FILENO); fcntl(temp_in, F_SETFD, FD_CLOEXEC); dup2(in_fds[0], STDIN_FILENO); } if (pipe_err) { fd_flags_err = fcntl(err_fds[0], F_GETFD); fcntl(err_fds[0], F_SETFD, FD_CLOEXEC); temp_err = dup(STDERR_FILENO); fcntl(temp_err, F_SETFD, FD_CLOEXEC); dup2(err_fds[1], STDERR_FILENO); }/* set up environment variables for the tpf_fork */ if (cld->subprocess_env) {#ifdef TPF_FORK_EXTENDED /* with extended tpf_fork( ) we pass the pointer to a list of pointers */ /* that point to "key=value" strings for each env variable */ subpool = ap_make_sub_pool(p); envp = ap_create_environment(subpool, cld->subprocess_env);#else /* without extended tpf_fork( ) we setenv( ) each env variable */ /* so the child inherits them */ for (i = 0; i < env_arr->nelts; ++i) { if (!elts[i].key) continue; setenv (elts[i].key, elts[i].val, 1); }#endif /* TPF_FORK_EXTENDED */ } fork_input.program = (const char*) cld->filename; fork_input.prog_type = cld->prog_type; fork_input.istream = TPF_FORK_IS_BALANCE; fork_input.ebw_data_length = 0; fork_input.ebw_data = NULL; fork_input.parm_data = NULL;#ifdef TPF_FORK_EXTENDED /* use a copy of cld->filename because strtok is destructive */ arguments = ap_pstrdup(p, cld->filename); args[0] = strtok(arguments, WHITE); for (i = 0; i < MAXARGC && args[i] ; i++) { args[i + 1] = strtok(NULL, WHITE); } args[MAXARGC] = NULL; if ((pid = tpf_fork(&fork_input, (const char **)args, (const char **)envp)) < 0) {#else if ((pid = tpf_fork(&fork_input)) < 0) {#endif /* TPF_FORK_EXTENDED */ save_errno = errno; if (pipe_out) { close(out_fds[0]); } if (pipe_in) { close(in_fds[1]); } if (pipe_err) { close(err_fds[0]); } errno = save_errno; pid = 0; }#ifdef TPF_FORK_EXTENDED if (subpool) { ap_destroy_pool(subpool); }#else if (cld->subprocess_env) { for (i = 0; i < env_arr->nelts; ++i) { if (!elts[i].key) continue; unsetenv (elts[i].key); } }#endif /* TPF_FORK_EXTENDED */ if (pipe_out) { close(out_fds[1]); dup2(temp_out, STDOUT_FILENO); close(temp_out); fcntl(out_fds[0], F_SETFD, fd_flags_out); } if (pipe_in) { close(in_fds[0]); dup2(temp_in, STDIN_FILENO); close(temp_in); fcntl(in_fds[1], F_SETFD, fd_flags_in); } if (pipe_err) { close(err_fds[1]); dup2(temp_err, STDERR_FILENO); close(temp_err); fcntl(err_fds[0], F_SETFD, fd_flags_err); } if (pid) { ap_note_subprocess(p, pid, kill_how); if (pipe_out) { *pipe_out = out_fds[0]; } if (pipe_in) { *pipe_in = in_fds[1]; } if (pipe_err) { *pipe_err = err_fds[0]; } } return pid;}pid_t os_fork(server_rec *s, int slot){ struct tpf_fork_input fork_input; APACHE_TPF_INPUT input_parms; int count; listen_rec *lr; input_parms.generation = ap_my_generation;#ifdef USE_SHMGET_SCOREBOARD input_parms.scoreboard_heap = ap_scoreboard_image;#endif lr = ap_listeners; count = 0; do { input_parms.listeners[count] = lr->fd; lr = lr->next; count++; } while(lr != ap_listeners); input_parms.slot = slot; input_parms.restart_time = ap_restart_time; input_parms.shm_static_ptr = tpf_shm_static_ptr; input_parms.tpf_fds = tpf_fds; fork_input.ebw_data = &input_parms; fork_input.program = ap_server_argv0; fork_input.prog_type = TPF_FORK_NAME; fork_input.istream = TPF_FORK_IS_BALANCE; fork_input.ebw_data_length = sizeof(input_parms); fork_input.parm_data = argv_ptr;#ifdef TPF_FORK_EXTENDED return tpf_fork(&fork_input, NULL, NULL);#else return tpf_fork(&fork_input);#endif /* TPF_FORK_EXTENDED */}void ap_tpf_zinet_checks(int standalone, const char *servername, server_rec *s) { INETD_IDCT_ENTRY_PTR idct; /* explicitly disallow "ServerType inetd" on TPF */ if (!standalone) { ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s, TPF_SERVERTYPE_MSG); exit(1); /* abort start-up of server */ } /* figure out zinet model for our server from the idct slot */ idct = inetd_getServer(servername); if (idct) { zinet_model = idct->model; free(idct); } else { ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s, TPF_UNABLE_TO_DETERMINE_ZINET_MODEL, servername); exit(1); /* abort start-up of server */ } /* check for valid zinet models */ if (zinet_model != INETD_IDCF_MODEL_DAEMON && zinet_model != INETD_IDCF_MODEL_NOLISTEN) { ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s, TPF_STANDALONE_CONFLICT_MSG); exit(1); /* abort start-up of server */ }#ifdef TPF_NOLISTEN_WARNING/* nag about switching to DAEMON model */ if (zinet_model == INETD_IDCF_MODEL_NOLISTEN) { ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, s, TPF_NOLISTEN_WARNING); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -