diff options
author | Stefan Fritsch <sf@sfritsch.de> | 2011-12-27 19:42:03 +0100 |
---|---|---|
committer | Stefan Fritsch <sf@sfritsch.de> | 2011-12-27 19:42:03 +0100 |
commit | 80db94fff6a9620fb469ee911347ed973e3f7735 (patch) | |
tree | 35ccde4018b7e6b84103e5e85dc1085ef9e7d6c2 /os | |
download | apache2-80db94fff6a9620fb469ee911347ed973e3f7735.tar.gz |
Upstream tarball 2.2.3upstream/2.2.3
Diffstat (limited to 'os')
42 files changed, 3900 insertions, 0 deletions
diff --git a/os/.indent.pro b/os/.indent.pro new file mode 100644 index 00000000..a9fbe9f9 --- /dev/null +++ b/os/.indent.pro @@ -0,0 +1,54 @@ +-i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1 +-TBUFF +-TFILE +-TTRANS +-TUINT4 +-T_trans +-Tallow_options_t +-Tapache_sfio +-Tarray_header +-Tbool_int +-Tbuf_area +-Tbuff_struct +-Tbuffy +-Tcmd_how +-Tcmd_parms +-Tcommand_rec +-Tcommand_struct +-Tconn_rec +-Tcore_dir_config +-Tcore_server_config +-Tdir_maker_func +-Tevent +-Tglobals_s +-Thandler_func +-Thandler_rec +-Tjoblist_s +-Tlisten_rec +-Tmerger_func +-Tmode_t +-Tmodule +-Tmodule_struct +-Tmutex +-Tn_long +-Tother_child_rec +-Toverrides_t +-Tparent_score +-Tpid_t +-Tpiped_log +-Tpool +-Trequest_rec +-Trequire_line +-Trlim_t +-Tscoreboard +-Tsemaphore +-Tserver_addr_rec +-Tserver_rec +-Tserver_rec_chain +-Tshort_score +-Ttable +-Ttable_entry +-Tthread +-Tu_wide_int +-Tvtime_t +-Twide_int diff --git a/os/Makefile.in b/os/Makefile.in new file mode 100644 index 00000000..9b35d491 --- /dev/null +++ b/os/Makefile.in @@ -0,0 +1,4 @@ + +SUBDIRS = $(OS_DIR) + +include $(top_builddir)/build/rules.mk diff --git a/os/beos/Makefile.in b/os/beos/Makefile.in new file mode 100644 index 00000000..66272ecc --- /dev/null +++ b/os/beos/Makefile.in @@ -0,0 +1,5 @@ + +LTLIBRARY_NAME = libos.la +LTLIBRARY_SOURCES = os.c beosd.c + +include $(top_srcdir)/build/ltlib.mk diff --git a/os/beos/beosd.c b/os/beos/beosd.c new file mode 100644 index 00000000..8be35c05 --- /dev/null +++ b/os/beos/beosd.c @@ -0,0 +1,166 @@ +/* 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. + */ + +#include <unistd.h> +#include "httpd.h" +#include "http_config.h" +#include "http_main.h" +#include "http_log.h" +#include "beosd.h" +#include "mpm_common.h" + +beosd_config_rec beosd_config; + +/* Set group privileges. + * + * Note that until we get the multi-user situation sorted on beos, + * this is just a no-op to allow common configuration files! + */ + +#if B_BEOS_VERSION < 0x0460 +static int set_group_privs(void) +{ + /* no-op */ + return 0; +} +#endif + + +int beosd_setup_child(void) +{ + /* TODO: revisit the whole issue of users/groups for BeOS as + * R5 and below doesn't really have much concept of them. + */ + + return 0; +} + + +AP_DECLARE(const char *) beosd_set_user(cmd_parms *cmd, + void *dummy, const char *arg) +{ + /* no-op */ + return NULL; +} + +AP_DECLARE(const char *) beosd_set_group(cmd_parms *cmd, + void *dummy, const char *arg) +{ + /* no-op */ + return NULL; +} + +void beosd_pre_config(void) +{ + /* Until the multi-user situation on BeOS is fixed, + simply have a no-op here to allow for common conf files + */ +} + +AP_DECLARE(apr_status_t) beosd_accept(void **accepted, ap_listen_rec *lr, + apr_pool_t *ptrans) +{ + apr_socket_t *csd; + apr_status_t status; + int sockdes; + + status = apr_socket_accept(&csd, lr->sd, ptrans); + if (status == APR_SUCCESS) { + *accepted = csd; + apr_os_sock_get(&sockdes, csd); + if (sockdes >= FD_SETSIZE) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, + "new file descriptor %d is too large; you probably need " + "to rebuild Apache with a larger FD_SETSIZE " + "(currently %d)", + sockdes, FD_SETSIZE); + apr_socket_close(csd); + return APR_EINTR; + } + return status; + } + + if (APR_STATUS_IS_EINTR(status)) { + return status; + } + /* Our old behaviour here was to continue after accept() + * errors. But this leads us into lots of troubles + * because most of the errors are quite fatal. For + * example, EMFILE can be caused by slow descriptor + * leaks (say in a 3rd party module, or libc). It's + * foolish for us to continue after an EMFILE. We also + * seem to tickle kernel bugs on some platforms which + * lead to never-ending loops here. So it seems best + * to just exit in most cases. + */ + switch (status) { +#ifdef EPROTO + /* EPROTO on certain older kernels really means + * ECONNABORTED, so we need to ignore it for them. + * See discussion in new-httpd archives nh.9701 + * search for EPROTO. + * + * Also see nh.9603, search for EPROTO: + * There is potentially a bug in Solaris 2.x x<6, + * and other boxes that implement tcp sockets in + * userland (i.e. on top of STREAMS). On these + * systems, EPROTO can actually result in a fatal + * loop. See PR#981 for example. It's hard to + * handle both uses of EPROTO. + */ + case EPROTO: +#endif +#ifdef ECONNABORTED + case ECONNABORTED: +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: +#endif +#ifdef EHOSTUNREACH + case EHOSTUNREACH: +#endif +#ifdef ENETUNREACH + case ENETUNREACH: +#endif + break; +#ifdef ENETDOWN + case ENETDOWN: + /* + * When the network layer has been shut down, there + * is not much use in simply exiting: the parent + * would simply re-create us (and we'd fail again). + * Use the CHILDFATAL code to tear the server down. + * @@@ Martin's idea for possible improvement: + * A different approach would be to define + * a new APEXIT_NETDOWN exit code, the reception + * of which would make the parent shutdown all + * children, then idle-loop until it detected that + * the network is up again, and restart the children. + * Ben Hyde noted that temporary ENETDOWN situations + * occur in mobile IP. + */ + ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, + "apr_socket_accept: giving up."); + return APR_EGENERAL; +#endif /*ENETDOWN*/ + + default: + ap_log_error(APLOG_MARK, APLOG_ERR, status, ap_server_conf, + "apr_socket_accept: (client socket)"); + return APR_EGENERAL; + } + return status; +} diff --git a/os/beos/beosd.h b/os/beos/beosd.h new file mode 100644 index 00000000..7c75e0a2 --- /dev/null +++ b/os/beos/beosd.h @@ -0,0 +1,68 @@ +/* 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. + */ + +/** + * @file beosd.h + * @brief common stuff that beos MPMs will want + * + * @addtogroup APACHE_OS_BEOS + * @{ + */ + +#ifndef BEOSD_H +#define BEOSD_H + +#include "httpd.h" +#include "ap_listen.h" + +/* Default user name and group name. These may be specified as numbers by + * placing a # before a number */ + +#ifndef DEFAULT_USER +#define DEFAULT_USER "#-1" +#endif +#ifndef DEFAULT_GROUP +#define DEFAULT_GROUP "#" +#endif + +typedef struct { + char *user_name; + uid_t user_id; + gid_t group_id; +} beosd_config_rec; +extern beosd_config_rec beosd_config; + +void beosd_detach(void); +int beosd_setup_child(void); +void beosd_pre_config(void); +AP_DECLARE(const char *) beosd_set_user (cmd_parms *cmd, void *dummy, + const char *arg); +AP_DECLARE(const char *) beosd_set_group(cmd_parms *cmd, void *dummy, + const char *arg); +AP_DECLARE(apr_status_t) beosd_accept(void **accepted, ap_listen_rec *lr, + apr_pool_t *ptrans); + +#define beosd_killpg(x, y) (kill (-(x), (y))) +#define ap_os_killpg(x, y) (kill (-(x), (y))) + +#define BEOS_DAEMON_COMMANDS \ +AP_INIT_TAKE1("User", beosd_set_user, NULL, RSRC_CONF, \ + "Effective user id for this server (NO-OP)"), \ +AP_INIT_TAKE1("Group", beosd_set_group, NULL, RSRC_CONF, \ + "Effective group id for this server (NO-OP)") + +#endif /* BEOSD_H */ +/** @} */ diff --git a/os/beos/config.m4 b/os/beos/config.m4 new file mode 100644 index 00000000..4fe95b75 --- /dev/null +++ b/os/beos/config.m4 @@ -0,0 +1,3 @@ +if test "$OS" = "beos" ; then + APR_ADDTO(CFLAGS,-DBEOS) +fi diff --git a/os/beos/os.c b/os/beos/os.c new file mode 100644 index 00000000..5c535d6e --- /dev/null +++ b/os/beos/os.c @@ -0,0 +1,37 @@ +/* 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 "ap_config.h" +#include "os.h" +#include "httpd.h" +#include "apr_thread_proc.h" +#include "ap_mpm.h" /* needed for definition of + * ap_os_create_privileged_process */ + +AP_DECLARE(apr_status_t) ap_os_create_privileged_process( + const request_rec *r, + apr_proc_t *newproc, const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, apr_pool_t *p) +{ + return apr_proc_create(newproc, progname, args, env, attr, p); +} diff --git a/os/beos/os.h b/os/beos/os.h new file mode 100644 index 00000000..e1b0a63d --- /dev/null +++ b/os/beos/os.h @@ -0,0 +1,42 @@ +/* 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. + */ + +/** + * @file beos/os.h + * @brief This file in included in all Apache source code. It contains definitions + * of facilities available on _this_ operating system (HAVE_* macros), + * and prototypes of OS specific functions defined in os.c or os-inline.c + * + * @defgroup APACHE_OS_BEOS beos + * @ingroup APACHE_OS + * @{ + */ + +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#include "ap_config.h" + +#ifndef PLATFORM +# ifdef BONE_VERSION +# define PLATFORM "BeOS BONE" +# else +# define PLATFORM "BeOS R5" +# endif +#endif + +#endif /* !APACHE_OS_H */ +/** @} */ diff --git a/os/bs2000/ebcdic.c b/os/bs2000/ebcdic.c new file mode 100644 index 00000000..dd5ef54f --- /dev/null +++ b/os/bs2000/ebcdic.c @@ -0,0 +1,210 @@ +/* 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. + */ + +#include "ap_config.h" +#if APR_CHARSET_EBCDIC +#include "ebcdic.h" +/* + Initial Port for Apache-1.3 by <Martin.Kraemer Mch.SNI.De> + +"BS2000 OSD" is a POSIX on a main frame. It is made by Siemens AG, Germany. +Within the POSIX subsystem, the same character set was chosen as in +"native BS2000", namely EBCDIC. + +EBCDIC Table. (Yes, in EBCDIC, the letters 'a'..'z' are not contiguous!) +This apr_table_t is bijective, i.e. there are no ambigous or duplicate characters +00 00 01 02 03 85 09 86 7f 87 8d 8e 0b 0c 0d 0e 0f *................* +10 10 11 12 13 8f 0a 08 97 18 19 9c 9d 1c 1d 1e 1f *................* +20 80 81 82 83 84 92 17 1b 88 89 8a 8b 8c 05 06 07 *................* +30 90 91 16 93 94 95 96 04 98 99 9a 9b 14 15 9e 1a *................* +40 20 a0 e2 e4 e0 e1 e3 e5 e7 f1 60 2e 3c 28 2b 7c * .........`.<(+|* +50 26 e9 ea eb e8 ed ee ef ec df 21 24 2a 29 3b 9f *&.........!$*);.* +60 2d 2f c2 c4 c0 c1 c3 c5 c7 d1 5e 2c 25 5f 3e 3f *-/........^,%_>?* +70 f8 c9 ca cb c8 cd ce cf cc a8 3a 23 40 27 3d 22 *..........:#@'="* +80 d8 61 62 63 64 65 66 67 68 69 ab bb f0 fd fe b1 *.abcdefghi......* +90 b0 6a 6b 6c 6d 6e 6f 70 71 72 aa ba e6 b8 c6 a4 *.jklmnopqr......* +a0 b5 af 73 74 75 76 77 78 79 7a a1 bf d0 dd de ae *..stuvwxyz......* +b0 a2 a3 a5 b7 a9 a7 b6 bc bd be ac 5b 5c 5d b4 d7 *...........[\]..* +c0 f9 41 42 43 44 45 46 47 48 49 ad f4 f6 f2 f3 f5 *.ABCDEFGHI......* +d0 a6 4a 4b 4c 4d 4e 4f 50 51 52 b9 fb fc db fa ff *.JKLMNOPQR......* +e0 d9 f7 53 54 55 56 57 58 59 5a b2 d4 d6 d2 d3 d5 *..STUVWXYZ......* +f0 30 31 32 33 34 35 36 37 38 39 b3 7b dc 7d da 7e *0123456789.{.}.~* +*/ + +/* The bijective ebcdic-to-ascii table: */ +const unsigned char os_toascii_strictly[256] = { +/*00*/ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f, + 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*................*/ +/*10*/ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97, + 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /*................*/ +/*20*/ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /*................*/ +/*30*/ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, + 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /*................*/ +/*40*/ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5, + 0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* .........`.<(+|*/ +/*50*/ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, + 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f, /*&.........!$*);.*/ +/*60*/ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5, + 0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /*-/........^,%_>?*/ +/*70*/ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, + 0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /*..........:#@'="*/ +/*80*/ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /*.abcdefghi......*/ +/*90*/ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /*.jklmnopqr......*/ +/*a0*/ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae, /*..stuvwxyz......*/ +/*b0*/ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, + 0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7, /*...........[\]..*/ +/*c0*/ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /*.ABCDEFGHI......*/ +/*d0*/ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff, /*.JKLMNOPQR......*/ +/*e0*/ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /*..STUVWXYZ......*/ +/*f0*/ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e /*0123456789.{.}.~*/ +}; + +/* This apr_table_t is (almost) identical to the previous one. The only difference + * is the fact that it maps every EBCDIC *except 0x0A* to its ASCII + * equivalent. The reason for this apr_table_t is simple: Throughout the + * server, protocol strings are used in the form + * "Content-Type: text/plain\015\012". Now all the characters in the string + * are stored as EBCDIC, only the semantics of \012 is completely + * different from LF (look it up in the apr_table_t above). \015 happens to be + * mapped to \015 anyway, so there's no special case for it. + * + * In THIS table, EBCDIC-\012 is mapped to ASCII-\012. + * This apr_table_t is therefore used wherever an EBCDIC to ASCII conversion is + * needed in the server. + */ +/* ebcdic-to-ascii with \012 mapped to ASCII-\n */ +const unsigned char os_toascii[256] = { +/*00*/ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f, + 0x87, 0x8d, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*................*/ +/*10*/ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97, + 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /*................*/ +/*20*/ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /*................*/ +/*30*/ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, + 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /*................*/ +/*40*/ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5, + 0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* .........`.<(+|*/ +/*50*/ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, + 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f, /*&.........!$*);.*/ +/*60*/ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5, + 0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /*-/........^,%_>?*/ +/*70*/ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, + 0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /*..........:#@'="*/ +/*80*/ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /*.abcdefghi......*/ +/*90*/ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /*.jklmnopqr......*/ +/*a0*/ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae, /*..stuvwxyz......*/ +/*b0*/ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, + 0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7, /*...........[\]..*/ +/*c0*/ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /*.ABCDEFGHI......*/ +/*d0*/ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff, /*.JKLMNOPQR......*/ +/*e0*/ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /*..STUVWXYZ......*/ +/*f0*/ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e /*0123456789.{.}.~*/ +}; + +/* The ascii-to-ebcdic table: +00 00 01 02 03 37 2d 2e 2f 16 05 15 0b 0c 0d 0e 0f *................* +10 10 11 12 13 3c 3d 32 26 18 19 3f 27 1c 1d 1e 1f *................* +20 40 5a 7f 7b 5b 6c 50 7d 4d 5d 5c 4e 6b 60 4b 61 * !"#$%&'()*+,-./ +30 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 7a 5e 4c 7e 6e 6f *0123456789:;<=>?* +40 7c c1 c2 c3 c4 c5 c6 c7 c8 c9 d1 d2 d3 d4 d5 d6 *@ABCDEFGHIJKLMNO* +50 d7 d8 d9 e2 e3 e4 e5 e6 e7 e8 e9 bb bc bd 6a 6d *PQRSTUVWXYZ[\]^_* +60 4a 81 82 83 84 85 86 87 88 89 91 92 93 94 95 96 *`abcdefghijklmno* +70 97 98 99 a2 a3 a4 a5 a6 a7 a8 a9 fb 4f fd ff 07 *pqrstuvwxyz{|}~.* +80 20 21 22 23 24 04 06 08 28 29 2a 2b 2c 09 0a 14 *................* +90 30 31 25 33 34 35 36 17 38 39 3a 3b 1a 1b 3e 5f *................* +a0 41 aa b0 b1 9f b2 d0 b5 79 b4 9a 8a ba ca af a1 *................* +b0 90 8f ea fa be a0 b6 b3 9d da 9b 8b b7 b8 b9 ab *................* +c0 64 65 62 66 63 67 9e 68 74 71 72 73 78 75 76 77 *................* +d0 ac 69 ed ee eb ef ec bf 80 e0 fe dd fc ad ae 59 *................* +e0 44 45 42 46 43 47 9c 48 54 51 52 53 58 55 56 57 *................* +f0 8c 49 cd ce cb cf cc e1 70 c0 de db dc 8d 8e df *................* +*/ +const unsigned char os_toebcdic[256] = { +/*00*/ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, + 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*................*/ +/*10*/ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, + 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, /*................*/ +/*20*/ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, + 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, /* !"#$%&'()*+,-./ */ +/*30*/ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, /*0123456789:;<=>?*/ +/*40*/ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, /*@ABCDEFGHIJKLMNO*/ +/*50*/ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + 0xe7, 0xe8, 0xe9, 0xbb, 0xbc, 0xbd, 0x6a, 0x6d, /*PQRSTUVWXYZ[\]^_*/ +/*60*/ 0x4a, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /*`abcdefghijklmno*/ +/*70*/ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, + 0xa7, 0xa8, 0xa9, 0xfb, 0x4f, 0xfd, 0xff, 0x07, /*pqrstuvwxyz{|}~.*/ +/*80*/ 0x20, 0x21, 0x22, 0x23, 0x24, 0x04, 0x06, 0x08, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x14, /*................*/ +/*90*/ 0x30, 0x31, 0x25, 0x33, 0x34, 0x35, 0x36, 0x17, + 0x38, 0x39, 0x3a, 0x3b, 0x1a, 0x1b, 0x3e, 0x5f, /*................*/ +/*a0*/ 0x41, 0xaa, 0xb0, 0xb1, 0x9f, 0xb2, 0xd0, 0xb5, + 0x79, 0xb4, 0x9a, 0x8a, 0xba, 0xca, 0xaf, 0xa1, /*................*/ +/*b0*/ 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3, + 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab, /*................*/ +/*c0*/ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68, + 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /*................*/ +/*d0*/ 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf, + 0x80, 0xe0, 0xfe, 0xdd, 0xfc, 0xad, 0xae, 0x59, /*................*/ +/*e0*/ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48, + 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /*................*/ +/*f0*/ 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1, + 0x70, 0xc0, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf /*................*/ +}; + +/* Translate a memory block from EBCDIC (host charset) to ASCII (net charset) + * dest and srce may be identical, or separate memory blocks, but + * should not overlap. + */ +void +ebcdic2ascii(unsigned char *dest, const unsigned char *srce, size_t count) +{ + while (count-- != 0) { + *dest++ = os_toascii[*srce++]; + } +} +void +ebcdic2ascii_strictly(unsigned char *dest, const unsigned char *srce, size_t count) +{ + while (count-- != 0) { + *dest++ = os_toascii_strictly[*srce++]; + } +} +void +ascii2ebcdic(unsigned char *dest, const unsigned char *srce, size_t count) +{ + while (count-- != 0) { + *dest++ = os_toebcdic[*srce++]; + } +} +#endif /*APR_CHARSET_EBCDIC*/ diff --git a/os/bs2000/ebcdic.h b/os/bs2000/ebcdic.h new file mode 100644 index 00000000..e48b859d --- /dev/null +++ b/os/bs2000/ebcdic.h @@ -0,0 +1,33 @@ +/* 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. + */ + +/** + * @file bs2000/ebcdic.h + * @brief EBCDIC/ASCII converson function declarations + * + * @addtogroup APACHE_OS_BS2000 + * @{ + */ + +#include <sys/types.h> + +extern const unsigned char os_toascii[256]; +extern const unsigned char os_toebcdic[256]; +void ebcdic2ascii(unsigned char *dest, const unsigned char *srce, size_t count); +void ebcdic2ascii_strictly(unsigned char *dest, const unsigned char *srce, size_t count); +void ascii2ebcdic(unsigned char *dest, const unsigned char *srce, size_t count); +/** @} */ + diff --git a/os/bs2000/os.c b/os/bs2000/os.c new file mode 100644 index 00000000..ab691242 --- /dev/null +++ b/os/bs2000/os.c @@ -0,0 +1,143 @@ +/* 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. + */ + +#ifdef _OSD_POSIX + +#include "os.h" + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include "apr_lib.h" + +#define USER_LEN 8 + +typedef enum +{ + bs2_unknown, /* not initialized yet. */ + bs2_noFORK, /* no fork() because -X flag was specified */ + bs2_FORK, /* only fork() because uid != 0 */ + bs2_UFORK /* Normally, ufork() is used to switch identities. */ +} bs2_ForkType; + +static bs2_ForkType forktype = bs2_unknown; + + +static void ap_str_toupper(char *str) +{ + while (*str) { + *str = apr_toupper(*str); + ++str; + } +} + +/* Determine the method for forking off a child in such a way as to + * set both the POSIX and BS2000 user id's to the unprivileged user. + */ +static bs2_ForkType os_forktype(int one_process) +{ + /* have we checked the OS version before? If yes return the previous + * result - the OS release isn't going to change suddenly! + */ + if (forktype == bs2_unknown) { + /* not initialized yet */ + + /* No fork if the one_process option was set */ + if (one_process) { + forktype = bs2_noFORK; + } + /* If the user is unprivileged, use the normal fork() only. */ + else if (getuid() != 0) { + forktype = bs2_FORK; + } + else + forktype = bs2_UFORK; + } + return forktype; +} + + + +/* This routine complements the setuid() call: it causes the BS2000 job + * environment to be switched to the target user's user id. + * That is important if CGI scripts try to execute native BS2000 commands. + */ +int os_init_job_environment(server_rec *server, const char *user_name, int one_process) +{ + bs2_ForkType type = os_forktype(one_process); + + /* We can be sure that no change to uid==0 is possible because of + * the checks in http_core.c:set_user() + */ + + if (one_process) { + + type = forktype = bs2_noFORK; + + ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, + "The debug mode of Apache should only " + "be started by an unprivileged user!"); + return 0; + } + + return 0; +} + +/* BS2000 requires a "special" version of fork() before a setuid() call */ +pid_t os_fork(const char *user) +{ + pid_t pid; + char username[USER_LEN+1]; + + switch (os_forktype(0)) { + + case bs2_FORK: + pid = fork(); + break; + + case bs2_UFORK: + apr_cpystrn(username, user, sizeof username); + + /* Make user name all upper case - for some versions of ufork() */ + ap_str_toupper(username); + + pid = ufork(username); + if (pid == -1 && errno == EPERM) { + ap_log_error(APLOG_MARK, APLOG_EMERG, errno, + NULL, "ufork: Possible mis-configuration " + "for user %s - Aborting.", user); + exit(1); + } + break; + + default: + pid = 0; + break; + } + + return pid; +} + +#else /* _OSD_POSIX */ +void bs2000_os_is_not_here() +{ +} +#endif /* _OSD_POSIX */ diff --git a/os/bs2000/os.h b/os/bs2000/os.h new file mode 100644 index 00000000..3b64c6ef --- /dev/null +++ b/os/bs2000/os.h @@ -0,0 +1,40 @@ +/* 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. + */ + +/** + * @file bs2000/os.h + * @brief This file in included in all Apache source code. It contains definitions + * of facilities available on _this_ operating system (HAVE_* macros), + * and prototypes of OS specific functions defined in os.c or os-inline.c + * + * @defgroup APACHE_OS_BS2000 bs2000 + * @ingroup APACHE_OS + * @{ + */ + +#ifndef APACHE_OS_BS2000_H +#define APACHE_OS_BS2000_H + +#define PLATFORM "BS2000" + +#include "../unix/os.h" + +/* Other ap_os_ routines not used by this platform */ + +extern pid_t os_fork(const char *user); + +#endif /* APACHE_OS_BS2000_H */ +/** @} */ diff --git a/os/config.m4 b/os/config.m4 new file mode 100644 index 00000000..336f360d --- /dev/null +++ b/os/config.m4 @@ -0,0 +1,26 @@ +AC_MSG_CHECKING(for target platform) + +case $host in +*beos*) + OS="beos" + OS_DIR=$OS + ;; +*pc-os2-emx*) + OS="os2" + OS_DIR=$OS + ;; +bs2000*) + OS="unix" + OS_DIR=$OS + ;; +*cygwin*) + OS="cygwin" + OS_DIR="unix" + ;; +*) + OS="unix" + OS_DIR=$OS;; +esac + +AC_MSG_RESULT($OS) +APACHE_FAST_OUTPUT(os/${OS_DIR}/Makefile) diff --git a/os/netware/Apache.def b/os/netware/Apache.def new file mode 100644 index 00000000..6d8bf9f4 --- /dev/null +++ b/os/netware/Apache.def @@ -0,0 +1,5 @@ +MODULE APRLIB.NLM +MODULE LIBC.NLM +MODULE WS2_32.NLM +EXPORT @HTTPD.IMP +IMPORT GetCurrentAddressSpace diff --git a/os/netware/apache.xdc b/os/netware/apache.xdc Binary files differnew file mode 100644 index 00000000..12a7f6ba --- /dev/null +++ b/os/netware/apache.xdc diff --git a/os/netware/modules.c b/os/netware/modules.c new file mode 100644 index 00000000..8bbd190d --- /dev/null +++ b/os/netware/modules.c @@ -0,0 +1,105 @@ +/* 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. + */ + +/* modules.c --- major modules compiled into Apache for NetWare. + * Only insert an entry for a module if it must be compiled into + * the core server + */ + +#define CORE_PRIVATE +#include "httpd.h" +#include "http_config.h" + +extern module core_module; +extern module mpm_netware_module; +extern module http_module; +extern module so_module; +extern module mime_module; +extern module authz_host_module; +extern module negotiation_module; +extern module include_module; +extern module dir_module; +extern module alias_module; +extern module env_module; +extern module log_config_module; +extern module setenvif_module; +#ifdef USE_WINSOCK +extern module nwssl_module; +#endif +extern module netware_module; + +module *ap_prelinked_modules[] = { + &core_module, + &mpm_netware_module, + &http_module, + &so_module, + &mime_module, + &authz_host_module, + &negotiation_module, + &include_module, + &dir_module, + &alias_module, + &env_module, + &log_config_module, + &setenvif_module, +#ifdef USE_WINSOCK + &nwssl_module, +#endif + &netware_module, + NULL +}; + +ap_module_symbol_t ap_prelinked_module_symbols[] = { + {"core_module", &core_module}, + {"mpm_netware_module", &mpm_netware_module}, + {"http_module", &http_module}, + {"so_module", &so_module}, + {"mime_module", &mime_module}, + {"authz_host_module", &authz_host_module}, + {"negotiation_module", &negotiation_module}, + {"include_module", &include_module}, + {"dir_module", &dir_module}, + {"alias_module", &alias_module}, + {"env_module", &env_module}, + {"log_config_module", &log_config_module}, + {"setenvif_module", &setenvif_module}, +#ifdef USE_WINSOCK + {"nwssl_module", &nwssl_module}, +#endif + {"netware_module", &netware_module}, + {NULL, NULL} +}; + +module *ap_preloaded_modules[] = { + &core_module, + &mpm_netware_module, + &http_module, + &so_module, + &mime_module, + &authz_host_module, + &negotiation_module, + &include_module, + &dir_module, + &alias_module, + &env_module, + &log_config_module, + &setenvif_module, +#ifdef USE_WINSOCK + &nwssl_module, +#endif + &netware_module, + NULL +}; diff --git a/os/netware/os.h b/os/netware/os.h new file mode 100644 index 00000000..71af7790 --- /dev/null +++ b/os/netware/os.h @@ -0,0 +1,52 @@ +/* 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. + */ + +/** + * @file netware/os.h + * @brief This file in included in all Apache source code. It contains definitions + * of facilities available on _this_ operating system (HAVE_* macros), + * and prototypes of OS specific functions defined in os.c or os-inline.c + * + * @defgroup APACHE_OS_NETWARE netware + * @ingroup APACHE_OS + * @{ + */ + +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#ifndef PLATFORM +#define PLATFORM "NETWARE" +#endif + +#include <screen.h> + +AP_DECLARE_DATA extern int hold_screen_on_exit; /* Indicates whether the screen should be held open on exit*/ + +#define CASE_BLIND_FILESYSTEM +#define NO_WRITEV + +#define APACHE_MPM_DIR "server/mpm/netware" /* generated on unix */ + +#define getpid NXThreadGetId + +/* Hold the screen open if there is an exit code and the hold_screen_on_exit flag >= 0 or the + hold_screen_on_exit > 0. If the hold_screen_on_exit flag is < 0 then close the screen no + matter what the exit code is. */ +#define exit(s) {if((s||hold_screen_on_exit)&&(hold_screen_on_exit>=0)){pressanykey();}apr_terminate();exit(s);} + +#endif /* ! APACHE_OS_H */ +/** @} */ diff --git a/os/netware/pre_nw.h b/os/netware/pre_nw.h new file mode 100644 index 00000000..f4ce6f53 --- /dev/null +++ b/os/netware/pre_nw.h @@ -0,0 +1,76 @@ +/* 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. + */ + +/** + * @file pre_nw.h + * @brief Definitions for Netware systems + * + * @addtogroup APACHE_OS_NETWARE + * @{ + */ + +#ifndef __pre_nw__ +#define __pre_nw__ + +#include <stdint.h> + +#ifndef __GNUC__ +#pragma precompile_target "precomp.mch" +#endif + +#define NETWARE + +#define N_PLAT_NLM + +/* hint for MSL C++ that we're on NetWare platform */ +#define __NETWARE__ + +/* the FAR keyword has no meaning in a 32-bit environment + but is used in the SDK headers so we take it out */ +#define FAR +#define far + +/* no-op for Codewarrior C compiler; a functions are cdecl + by default */ +#define cdecl + +/* if we have wchar_t enabled in C++, predefine this type to avoid + a conflict in Novell's header files */ +#ifndef __GNUC__ +#if (__option(cplusplus) && __option(wchar_type)) +#define _WCHAR_T +#endif +#endif + +/* C9X defintion used by MSL C++ library */ +#define DECIMAL_DIG 17 + +/* some code may want to use the MS convention for long long */ +#ifndef __int64 +#define __int64 long long +#endif + +/* Don't use the DBM rewrite map for mod_rewrite */ +#define NO_DBM_REWRITEMAP + +/* Allow MOD_AUTH_DBM to use APR */ +#define AP_AUTH_DBM_USE_APR + +/* Restrict the number of nested includes */ +#define AP_MAX_INCLUDE_DEPTH 48 + +#endif +/** @} */ diff --git a/os/netware/util_nw.c b/os/netware/util_nw.c new file mode 100644 index 00000000..c5b964c8 --- /dev/null +++ b/os/netware/util_nw.c @@ -0,0 +1,105 @@ +/* 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. + */ + +#include "httpd.h" +#include "http_log.h" + +#include <netware.h> +#include <nks\netware.h> + +int nlmUnloadSignaled(int wait); +event_handle_t eh; +Warn_t ref; +Report_t dum; + +AP_DECLARE(apr_status_t) ap_os_create_privileged_process( + const request_rec *r, + apr_proc_t *newproc, const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, apr_pool_t *p) +{ + return apr_proc_create(newproc, progname, args, env, attr, p); +} + +int _NonAppCheckUnload( void ) +{ + return nlmUnloadSignaled(1); +} + +// down server event callback +void ap_down_server_cb(void *, void *) +{ + nlmUnloadSignaled(0); + return; +} + +// Required place holder event callback +void ap_dummy_cb(void *, void *) +{ + return; +} + +// destroy callback resources +void ap_cb_destroy(void *) +{ + // cleanup down event notification + UnRegisterEventNotification(eh); + NX_UNWRAP_INTERFACE(ref); + NX_UNWRAP_INTERFACE(dum); +} + +int _NonAppStart +( + void *NLMHandle, + void *errorScreen, + const char *cmdLine, + const char *loadDirPath, + size_t uninitializedDataLength, + void *NLMFileHandle, + int (*readRoutineP)( int conn, void *fileHandle, size_t offset, + size_t nbytes, size_t *bytesRead, void *buffer ), + size_t customDataOffset, + size_t customDataSize, + int messageCount, + const char **messages +) +{ +#pragma unused(cmdLine) +#pragma unused(loadDirPath) +#pragma unused(uninitializedDataLength) +#pragma unused(NLMFileHandle) +#pragma unused(readRoutineP) +#pragma unused(customDataOffset) +#pragma unused(customDataSize) +#pragma unused(messageCount) +#pragma unused(messages) + + // register for down server event + rtag_t rt = AllocateResourceTag(NLMHandle, "Apache2 Down Server Callback", + EventSignature); + + NX_WRAP_INTERFACE((void *)ap_down_server_cb, 2, (void **)&ref); + NX_WRAP_INTERFACE((void *)ap_dummy_cb, 2, (void **)&dum); + eh = RegisterForEventNotification(rt, EVENT_DOWN_SERVER, + EVENT_PRIORITY_APPLICATION, + ref, dum, NULL); + + // clean-up + NXVmRegisterExitHandler(ap_cb_destroy, NULL); + +} + diff --git a/os/os2/Makefile.in b/os/os2/Makefile.in new file mode 100644 index 00000000..fba49727 --- /dev/null +++ b/os/os2/Makefile.in @@ -0,0 +1,5 @@ + +LTLIBRARY_NAME = libos.la +LTLIBRARY_SOURCES = util_os2.c + +include $(top_srcdir)/build/ltlib.mk diff --git a/os/os2/config.m4 b/os/os2/config.m4 new file mode 100644 index 00000000..b62d214e --- /dev/null +++ b/os/os2/config.m4 @@ -0,0 +1,3 @@ +if test "$OS" = "os2" ; then + APR_ADDTO(CFLAGS, [-DOS2 -O2]) +fi diff --git a/os/os2/core.mk b/os/os2/core.mk new file mode 100644 index 00000000..639417e8 --- /dev/null +++ b/os/os2/core.mk @@ -0,0 +1,7 @@ +# Some rules for making a shared core dll on OS/2 + +os2core: httpd.dll $(CORE_IMPLIB) + $(LIBTOOL) --mode=link gcc -Zstack 512 $(LDFLAGS) $(EXTRA_LDFLAGS) -o httpd $(CORE_IMPLIB) + +httpd.dll: $(PROGRAM_DEPENDENCIES) $(CORE_IMPLIB) + $(LINK) -Zdll $(EXTRA_LDFLAGS) -s -o $@ server/exports.lo modules.lo $(PROGRAM_DEPENDENCIES) $(AP_LIBS) server/ApacheCoreOS2.def diff --git a/os/os2/core_header.def b/os/os2/core_header.def new file mode 100644 index 00000000..ec3703a6 --- /dev/null +++ b/os/os2/core_header.def @@ -0,0 +1,19 @@ +LIBRARY httpd INITINSTANCE +DESCRIPTION "Apache Server Core" +DATA NONSHARED + +EXPORTS + "main" + +; One for mod_dav from socket library + "_swaps" + +; And some more for mod_unique_id + "gethostname" + "gethostbyname" + "_swapl" + "h_errno" + "inet_ntoa" + +; mod_proxy needs this one + "inet_addr" diff --git a/os/os2/os.h b/os/os2/os.h new file mode 100644 index 00000000..085dacf0 --- /dev/null +++ b/os/os2/os.h @@ -0,0 +1,39 @@ +/* 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. + */ + +/** + * @file os2/os.h + * @brief This file in included in all Apache source code. It contains definitions + * of facilities available on _this_ operating system (HAVE_* macros), + * and prototypes of OS specific functions defined in os.c or os-inline.c + * + * @defgroup APACHE_OS_OS2 os2 + * @ingroup APACHE_OS + * @{ + */ + +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "OS/2" + +/* going away shortly... */ +#define HAVE_DRIVE_LETTERS +#define HAVE_UNC_PATHS +#define CASE_BLIND_FILESYSTEM + +#endif /* ! APACHE_OS_H */ +/** @} */ diff --git a/os/os2/util_os2.c b/os/os2/util_os2.c new file mode 100644 index 00000000..9156fb39 --- /dev/null +++ b/os/os2/util_os2.c @@ -0,0 +1,39 @@ +/* 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. + */ + +#define INCL_DOS +#define INCL_DOSERRORS +#include <os2.h> +#include "ap_config.h" +#include "httpd.h" +#include "http_log.h" +#include "os.h" +#include <sys/time.h> +#include <sys/signal.h> +#include <ctype.h> +#include <string.h> +#include "apr_strings.h" + + +AP_DECLARE(apr_status_t) ap_os_create_privileged_process( + const request_rec *r, + apr_proc_t *newproc, const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, apr_pool_t *p) +{ + return apr_proc_create(newproc, progname, args, env, attr, p); +} diff --git a/os/tpf/TPFExport b/os/tpf/TPFExport new file mode 100644 index 00000000..449ebf2f --- /dev/null +++ b/os/tpf/TPFExport @@ -0,0 +1,7 @@ +#!/bin/sh +echo " Setting TPF/c89 environment variables" +export _C89_CCMODE=1 +# replace the following with the location of your TPF include files +export _C89_INCDIRS="/u/tpf41/currentmaint/include /u/tpf41/currentmaint/include/oco" +export TPF=YES +echo "Done" diff --git a/os/tpf/ebcdic.c b/os/tpf/ebcdic.c new file mode 100644 index 00000000..00e1edf7 --- /dev/null +++ b/os/tpf/ebcdic.c @@ -0,0 +1,179 @@ +/* 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. + */ + +#include "ap_config.h" +#if APR_CHARSET_EBCDIC +#include "ebcdic.h" +/* +This code does basic character mapping for IBM's TPF operating system. +It is a modified version of <Martin.Kraemer@Mch.SNI.De>'s code for +the BS2000 (apache/src/os/bs2000/ebcdic.c). +*/ + +/* +Bijective EBCDIC (character set IBM-1047) to US-ASCII table: +This apr_table_t is bijective - there are no ambigous or duplicate characters. +*/ +const unsigned char os_toascii_strictly[256] = { + 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f, /* 00-0f: */ + 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */ + 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97, /* 10-1f: */ + 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b, /* 20-2f: */ + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /* ................ */ + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30-3f: */ + 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /* ................ */ + 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5, /* 40-4f: */ + 0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* ...........<(+| */ + 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, /* 50-5f: */ + 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e, /* &.........!$*);^ */ + 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5, /* 60-6f: */ + 0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /* -/.........,%_>? */ + 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, /* 70-7f: */ + 0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /* .........`:#@'=" */ + 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80-8f: */ + 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /* .abcdefghi...... */ + 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, /* 90-9f: */ + 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /* .jklmnopqr...... */ + 0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* a0-af: */ + 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae, /* .~stuvwxyz...[.. */ + 0xac, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, /* b0-bf: */ + 0xbd, 0xbe, 0xdd, 0xa8, 0xaf, 0x5d, 0xb4, 0xd7, /* .............].. */ + 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* c0-cf: */ + 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /* {ABCDEFGHI...... */ + 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* d0-df: */ + 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff, /* }JKLMNOPQR...... */ + 0x5c, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* e0-ef: */ + 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /* \.STUVWXYZ...... */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* f0-ff: */ + 0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f /* 0123456789...... */ +}; + +/* +Server EBCDIC (character set IBM-1047) to US-ASCII table: +This apr_table_t is a copy of the os_toascii_strictly bijective apr_table_t above. +The only change is that hex 0a (\012 octal) is mapped to hex 0a +(ASCII's line feed) instead of hex 8e. This is done because throughout +Apache, protocol string definitions hardcode the linefeed as \012 (octal): +"Content-Type: text/plain\015\012". Without this kludge all protocol +string definitions would need to be changed from ...\012 to ...\025. +*/ +const unsigned char os_toascii[256] = { + 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f, /* 00-0f: */ + 0x87, 0x8d, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */ + 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97, /* 10-1f: */ + 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b, /* 20-2f: */ + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /* ................ */ + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30-3f: */ + 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /* ................ */ + 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5, /* 40-4f: */ + 0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* ...........<(+| */ + 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, /* 50-5f: */ + 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e, /* &.........!$*);^ */ + 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5, /* 60-6f: */ + 0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /* -/.........,%_>? */ + 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, /* 70-7f: */ + 0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /* .........`:#@'=" */ + 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80-8f: */ + 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /* .abcdefghi...... */ + 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, /* 90-9f: */ + 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /* .jklmnopqr...... */ + 0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* a0-af: */ + 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae, /* .~stuvwxyz...[.. */ + 0xac, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, /* b0-bf: */ + 0xbd, 0xbe, 0xdd, 0xa8, 0xaf, 0x5d, 0xb4, 0xd7, /* .............].. */ + 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* c0-cf: */ + 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /* {ABCDEFGHI...... */ + 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* d0-df: */ + 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff, /* }JKLMNOPQR...... */ + 0x5c, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* e0-ef: */ + 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /* \.STUVWXYZ...... */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* f0-ff: */ + 0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f /* 0123456789...... */ +}; + +/* +The US-ASCII to EBCDIC (character set IBM-1047) table: +This apr_table_t is bijective (no ambiguous or duplicate characters) +*/ +const unsigned char os_toebcdic[256] = { + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, /* 00-0f: */ + 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* ................ */ + 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, /* 10-1f: */ + 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, /* ................ */ + 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, /* 20-2f: */ + 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, /* !"#$%&'()*+,-./ */ + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 30-3f: */ + 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, /* 0123456789:;<=>? */ + 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 40-4f: */ + 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, /* @ABCDEFGHIJKLMNO */ + 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, /* 50-5f: */ + 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d, /* PQRSTUVWXYZ[\]^_ */ + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60-6f: */ + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* `abcdefghijklmno */ + 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, /* 70-7f: */ + 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07, /* pqrstuvwxyz{|}~. */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x04, 0x06, 0x08, /* 80-8f: */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x14, /* ................ */ + 0x30, 0x31, 0x25, 0x33, 0x34, 0x35, 0x36, 0x17, /* 90-9f: */ + 0x38, 0x39, 0x3a, 0x3b, 0x1a, 0x1b, 0x3e, 0xff, /* ................ */ + 0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5, /* a0-af: */ + 0xbb, 0xb4, 0x9a, 0x8a, 0xb0, 0xca, 0xaf, 0xbc, /* ................ */ + 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3, /* b0-bf: */ + 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab, /* ................ */ + 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68, /* c0-cf: */ + 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* ................ */ + 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf, /* d0-df: */ + 0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xba, 0xae, 0x59, /* ................ */ + 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48, /* e0-ef: */ + 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* ................ */ + 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1, /* f0-ff: */ + 0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf /* ................ */ +}; + +/* Translate a memory block from EBCDIC (host charset) to ASCII (net charset) + * dest and srce may be identical, or separate memory blocks, but + * should not overlap. + */ +void +ebcdic2ascii(void *dest, const void *srce, size_t count) +{ + unsigned char *udest = dest; + const unsigned char *usrce = srce; + while (count-- != 0) { + *udest++ = os_toascii[*usrce++]; + } +} +void +ebcdic2ascii_strictly(unsigned char *dest, const unsigned char *srce, size_t count) +{ + while (count-- != 0) { + *dest++ = os_toascii_strictly[*srce++]; + } +} +void +ascii2ebcdic(void *dest, const void *srce, size_t count) +{ + unsigned char *udest = dest; + const unsigned char *usrce = srce; + + while (count-- != 0) { + *udest++ = os_toebcdic[*usrce++]; + } +} +#endif /*APR_CHARSET_EBCDIC*/ + diff --git a/os/tpf/ebcdic.h b/os/tpf/ebcdic.h new file mode 100644 index 00000000..85a0c334 --- /dev/null +++ b/os/tpf/ebcdic.h @@ -0,0 +1,32 @@ +/* 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. + */ + +/** + * @file tpf/ebcdic.h + * @brief EBCDIC/ASCII converson function declarations + * + * @addtogroup APACHE_OS_TPF + * @{ + */ + +#include <sys/types.h> + +extern const unsigned char os_toascii[256]; +extern const unsigned char os_toebcdic[256]; +void ebcdic2ascii(void *dest, const void *srce, size_t count); +void ebcdic2ascii_strictly(unsigned char *dest, const unsigned char *srce, size_t count); +void ascii2ebcdic(void *dest, const void *srce, size_t count); +/** @} */ diff --git a/os/tpf/os.c b/os/tpf/os.c new file mode 100644 index 00000000..30a0c4cd --- /dev/null +++ b/os/tpf/os.c @@ -0,0 +1,132 @@ +/* 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" + +static FILE *sock_fp; + +#ifndef __PIPE_ +int pipe(int fildes[2]) +{ + errno = ENOSYS; + return(-1); +} +#endif + +/* 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); +} + + +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; + + fflush(stdin); + if (dup2(fileno(sock_fp), STDIN_FILENO) == -1) + ap_log_error(APLOG_MARK, APLOG_CRIT, errno, s, + "unable to replace stdin with sock device driver"); + fflush(stdout); + if (dup2(fileno(sock_fp), STDOUT_FILENO) == -1) + ap_log_error(APLOG_MARK, APLOG_CRIT, errno, s, + "unable to replace stdout with sock device driver"); + input_parms.generation = ap_my_generation; + input_parms.scoreboard_heap = ap_scoreboard_image; + + 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; + 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 = "-x"; + return tpf_fork(&fork_input); +} + +int os_check_server(char *server) { +#ifndef USE_TPF_DAEMON + int rv; + int *current_acn; + if((rv = inetd_getServerStatus(server)) == INETD_SERVER_STATUS_INACTIVE) + return 1; + else { + current_acn = (int *)cinfc_fast(CINFC_CMMACNUM); + if(ecbp2()->ce2acn != *current_acn) + return 1; + } +#endif + return 0; +} + +AP_DECLARE(apr_status_t) ap_os_create_privileged_process( + const request_rec *r, + apr_proc_t *newproc, const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, apr_pool_t *p) +{ + return apr_proc_create(newproc, progname, args, env, attr, p); +} diff --git a/os/tpf/os.h b/os/tpf/os.h new file mode 100644 index 00000000..1c1ddc57 --- /dev/null +++ b/os/tpf/os.h @@ -0,0 +1,93 @@ +/* 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. + */ + +/** + * @file tpf/os.h + * @brief This file in included in all Apache source code. It contains definitions + * of facilities available on _this_ operating system (HAVE_* macros), + * and prototypes of OS specific functions defined in os.c or os-inline.c + * + * @defgroup APACHE_OS_TPF tpf + * @ingroup APACHE_OS + * @{ + */ + +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "TPF" + +#ifdef errno +#undef errno +#endif + +#include "apr.h" +#include "ap_config.h" +#include <strings.h> +#ifndef __strings_h + +#define FD_SETSIZE 2048 + +typedef long fd_mask; + +#define NBBY 8 /* number of bits in a byte */ +#define NFDBITS (sizeof(fd_mask) * NBBY) +#define howmany(x, y) (((x)+((y)-1))/(y)) + +typedef struct fd_set { + fd_mask fds_bits [howmany(FD_SETSIZE, NFDBITS)]; +} fd_set; + +#define FD_CLR(n, p)((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p)((p)->fds_bits[(n)/NFDBITS] & (1 <<((n) % NFDBITS))) +#define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p))) +#endif + +#ifdef FD_SET +#undef FD_SET +#define FD_SET(n, p) (0) +#endif + +#include <i$netd.h> +struct apache_input { + INETD_SERVER_INPUT inetd_server; + void *scoreboard_heap; /* scoreboard system heap address */ + int scoreboard_fd; /* scoreboard file descriptor */ + int slot; /* child number */ + int generation; /* server generation number */ + int listeners[10]; + time_t restart_time; +}; + +typedef struct apache_input APACHE_TPF_INPUT; + +extern int tpf_child; + +struct server_rec; +pid_t os_fork(struct server_rec *s, int slot); +int os_check_server(char *server); + +extern char *ap_server_argv0; +extern int scoreboard_fd; +#include <signal.h> +#ifndef SIGPIPE +#define SIGPIPE 14 +#endif +#ifdef NSIG +#undef NSIG +#endif +#endif /*! APACHE_OS_H*/ +/** @} */ diff --git a/os/tpf/samples/linkdll.jcl b/os/tpf/samples/linkdll.jcl new file mode 100644 index 00000000..16524bf3 --- /dev/null +++ b/os/tpf/samples/linkdll.jcl @@ -0,0 +1,121 @@ +//APACH JOB MSGLEVEL=(1,1),CLASS=A,MSGCLASS=A +/*ROUTE PRINT XXXXXX.XXXXXX +/*ROUTE PUNCH XXXXXX.XXXXXX +/*NOTIFY XXXXXX.XXXXXX +//CCLE JCLLIB ORDER=(SYS1.CBC.SCBCPRC,SYS1.CEE.SCEEPROC) +//PRELINK EXEC EDCPL,COND.LKED=(0,NE), +// PPARM='OMVS,DLLNAME(pppp)', +// LREGSIZ='2048K', +// LPARM='AMODE=31,RMODE=ANY,LIST,XREF' +//PLKED.SYSLIB DD DISP=SHR,DSN=FSE0000.DEVP.STUB.OB +// DD DISP=SHR,DSN=FSE0000.DEVP.CLIB.OB +// DD DISP=SHR,DSN=ACP.CLIB.RLSE46.WEB +// DD DISP=SHR,DSN=ACP.STUB.RLSE46.WEB +// DD DISP=SHR,DSN=ACP.CLIB.RLSE40 +// DD DISP=SHR,DSN=ACP.STUB.RLSE40 +//PLKED.SYSDEFSD DD DSN=APA0000.DEVP.IMPORTS.DSD(ppppvv),DISP=SHR +//PLKED.DSD DD DSN=APA0000.DEVP.IMPORTS.DSD,DISP=SHR +//PLKED.OBJLIB DD DISP=SHR,DSN=FSE0000.DEVP.TEST.OB +// DD DISP=SHR,DSN=ACP.OBJ.RLSE46.WEB +// DD DISP=SHR,DSN=ACP.OBJ.INTG98.NBS +// DD DISP=SHR,DSN=ACP.MAIN.SYST.OBBSS +// DD DISP=SHR,DSN=ACP.DF.MAIN.SYST.OBBSS +// DD DISP=SHR,DSN=ACP.OBJ.RLSE40.BSS +//PLKED.OBJ1 DD PATH='/usr/local/apache/src/ap/ap_cpystrn.o' +//PLKED.OBJ2 DD PATH='/usr/local/apache/src/ap/ap_execve.o' +//PLKED.OBJ3 DD PATH='/usr/local/apache/src/ap/ap_signal.o' +//PLKED.OBJ4 DD PATH='/usr/local/apache/src/ap/ap_slack.o' +//PLKED.OBJ5 DD PATH='/usr/local/apache/src/ap/ap_snprintf.o' +//PLKED.OBJ6 DD PATH='/usr/local/apache/src/ap/ap_strings.o' +//PLKED.OBJ7 DD PATH='/usr/local/apache/src/os/tpf/ebcdic.o' +//PLKED.OBJ8 DD PATH='/usr/local/apache/src/os/tpf/os.o' +//PLKED.OBJ9 DD PATH='/usr/local/apache/src/os/tpf/os-inline.o' +//PLKED.OBJ10 DD PATH='/usr/local/apache/src/regex/regcomp.o' +//PLKED.OBJ11 DD PATH='/usr/local/apache/src/regex/regerror.o' +//PLKED.OBJ12 DD PATH='/usr/local/apache/src/regex/regexec.o' +//PLKED.OBJ13 DD PATH='/usr/local/apache/src/regex/regfree.o' +//PLKED.OBJ14 DD PATH='/usr/local/apache/src/main/alloc.o' +//PLKED.OBJ15 DD PATH='/usr/local/apache/src/main/buff.o' +//PLKED.OBJ16 DD PATH='/usr/local/apache/src/main/fnmatch.o' +//PLKED.OBJ17 DD PATH='/usr/local/apache/src/main/http_config.o' +//PLKED.OBJ18 DD PATH='/usr/local/apache/src/main/http_core.o' +//PLKED.OBJ19 DD PATH='/usr/local/apache/src/main/http_log.o' +//PLKED.OBJ20 DD PATH='/usr/local/apache/src/main/http_main.o' +//PLKED.OBJ21 DD PATH='/usr/local/apache/src/main/http_protocol.o' +//PLKED.OBJ22 DD PATH='/usr/local/apache/src/main/http_request.o' +//PLKED.OBJ23 DD PATH='/usr/local/apache/src/main/http_vhost.o' +//PLKED.OBJ24 DD PATH='/usr/local/apache/src/main/md5c.o' +//PLKED.OBJ25 DD PATH='/usr/local/apache/src/main/rfc1413.o' +//PLKED.OBJ26 DD PATH='/usr/local/apache/src/main/util.o' +//PLKED.OBJ27 DD PATH='/usr/local/apache/src/main/util_date.o' +//PLKED.OBJ28 DD PATH='/usr/local/apache/src/main/util_md5.o' +//PLKED.OBJ29 DD PATH='/usr/local/apache/src/main/util_script.o' +//PLKED.OBJ30 DD PATH='/usr/local/apache/src/main/util_uri.o' +//PLKED.OBJ31 DD PATH='/usr/local/apache/src/modules.o' +//PLKED.OBJ32 DD PATH='/usr/local/apache/src/buildmark.o' +//PLKED.OBJ33 DD PATH='/usr/local/apache/src/modules/standard/mod_auto\ +// index.o' +//PLKED.OBJ34 DD PATH='/usr/local/apache/src/modules/standard/mod_dir.\ +// o' +//PLKED.OBJ35 DD PATH='/usr/local/apache/src/modules/standard/mod_mime\ +// .o' +//PLKED.OBJ36 DD PATH='/usr/local/apache/src/modules/standard/mod_sete\ +// nvif.o' +//PLKED.OBJ37 DD PATH='/usr/local/apache/src/modules/standard/mod_alia\ +// s.o' +//PLKED.OBJ38 DD PATH='/usr/local/apache/src/modules/standard/mod_acce\ +// ss.o' +//PLKED.OBJ39 DD PATH='/usr/local/apache/src/modules/standard/mod_user\ +// dir.o' +//PLKED.OBJ40 DD PATH='/usr/local/apache/src/modules/standard/mod_spel\ +// ing.o' +//PLKED.OBJ41 DD PATH='/usr/local/apache/src/modules/standard/mod_nego\ +// tiation.o' +//PLKED.SYSIN DD * + ORDER @@DLMHDR + INCLUDE OBJLIB(CSTRTD40) + INCLUDE OBJ1 + INCLUDE OBJ2 + INCLUDE OBJ3 + INCLUDE OBJ4 + INCLUDE OBJ5 + INCLUDE OBJ6 + INCLUDE OBJ7 + INCLUDE OBJ8 + INCLUDE OBJ9 + INCLUDE OBJ10 + INCLUDE OBJ11 + INCLUDE OBJ12 + INCLUDE OBJ13 + INCLUDE OBJ14 + INCLUDE OBJ15 + INCLUDE OBJ16 + INCLUDE OBJ17 + INCLUDE OBJ18 + INCLUDE OBJ19 + INCLUDE OBJ20 + INCLUDE OBJ21 + INCLUDE OBJ22 + INCLUDE OBJ23 + INCLUDE OBJ24 + INCLUDE OBJ25 + INCLUDE OBJ26 + INCLUDE OBJ27 + INCLUDE OBJ28 + INCLUDE OBJ29 + INCLUDE OBJ30 + INCLUDE OBJ31 + INCLUDE OBJ32 + INCLUDE OBJ33 + INCLUDE OBJ34 + INCLUDE OBJ35 + INCLUDE OBJ36 + INCLUDE OBJ37 + INCLUDE OBJ38 + INCLUDE OBJ39 + INCLUDE OBJ40 + INCLUDE OBJ41 +/* +//*** WARNING *** NEVER change .LK to .OB in SYSLMOD!!! +//LKED.SYSLMOD DD DISP=OLD,DSN=xxxxxx.xxxx(ppppvv) +// diff --git a/os/tpf/samples/loadset.jcl b/os/tpf/samples/loadset.jcl new file mode 100644 index 00000000..405af828 --- /dev/null +++ b/os/tpf/samples/loadset.jcl @@ -0,0 +1,58 @@ +//OLDRWEB JOB MSGLEVEL=1,CLASS=A,MSGCLASS=S +//JOBCAT DD DSN=ICFCAT.ESAWK2,DISP=SHR +/*ROUTE PRINT xxxxxx.xxxxxxx +/*ROUTE PUNCH xxxxxx.xxxxxxx +//TLDR EXEC PGM=TPFLDRCA,REGION=8M, +// PARM='OLDR,SYS=ACP,CLMSIZE=8000000' +//STEPLIB DD DSN=ACP.LINK.RLSE46.WEB,DISP=SHR +// DD DSN=ACP.LINK.RLSE40.BSS,DISP=SHR +// DD DSN=VIS0000.DEVP.TEST.LK,DISP=SHR +// DD DSN=SYS1.CEE.SCEERUN,DISP=SHR +//SALTB DD DSN=ACP.SALTBL.RLSE46.WEB,DISP=SHR +// DD DSN=ACP.SALTBL.INTG46.WEB,DISP=SHR +//OBJLIB DD DSN=FSE0000.DEVP.TEST.OB,DISP=SHR +// DD DSN=APA0000.DEVP.TEST.OB,DISP=SHR +// DD DSN=ACP.DRVE.TEST.OB,DISP=SHR +// DD DSN=ACP.OBJ.RLSE46.WEB,DISP=SHR +// DD DSN=ACP.OBJ.INTG36.DRV,DISP=SHR +// DD DSN=ACP.OBJ.INTG46.WEB,DISP=SHR +// DD DSN=ACP.OBJ.INTG40.BSS,DISP=SHR +//LOADMOD DD DSN=FSE0000.DEVP.TEST.LK,DISP=SHR +// DD DSN=APA0000.DEVP.TEST.LK,DISP=SHR +// DD DSN=CWEISS.LINK,DISP=SHR +// DD DSN=ACP.DRVE.TEST.LK,DISP=SHR +// DD DSN=ACP.LINK.RLSE46.WEB,DISP=SHR +// DD DSN=ACP.LINK.INTG98.NBS,DISP=SHR +// DD DSN=ACP.LINK.INTG46.WEB,DISP=SHR +// DD DSN=ACP.LINK.INTG36.DRV,DISP=SHR +// DD DSN=ACP.LINK.INTG40.BSS,DISP=SHR +//LOADSUM DD DSN=&&LOADSUM,DISP=(NEW,PASS),UNIT=SYSDA, +// LRECL=133,SPACE=(TRK,(10,10)),RECFM=FBA +//CPRTEMP DD UNIT=SYSDA, +// DSN=&&CPRTEMP,SPACE=(TRK,(100,20)), +// DCB=(RECFM=FB,BLKSIZE=4095,LRECL=4095), +// DISP=(NEW,DELETE) +//PROGTEMP DD UNIT=SYSDA, +// DSN=&&PRTEMP,SPACE=(TRK,(100,20)), +// DCB=(RECFM=FB,BLKSIZE=4095,LRECL=4095), +// DISP=(NEW,DELETE) +//OUTPUT DD DSN=&&VRDROUT,DISP=(NEW,PASS),UNIT=SYSDA, +// DCB=(RECFM=F,BLKSIZE=4095,LRECL=4095) +//SYSUDUMP DD DUMMY +//SYSABEND DD DUMMY +//SYSOUT DD SYSOUT=A +//SYSPRINT DD SYSOUT=A +//PRINTER DD SYSOUT=A +//CEEDUMP DD SYSOUT=A +//SYSIN DD * +SYSID=BSS +PATVERS=NONE +SALVERS=40 +LOADER LOADSET lllllll +LOADER CALL PROG ppppvv +/* +//TRANSMIT EXEC PGM=IKJEFT01, +// PARM='TRANSMIT xxxxxx.xxxxxx DDNAME(SYSTSIN) NOLOG NONOTIFY SEQ' +//SYSTSIN DD UNIT=SYSDA, +// DSN=&&VRDROUT,DISP=(OLD,DELETE) +//SYSTSPRT DD DUMMY diff --git a/os/unix/Makefile.in b/os/unix/Makefile.in new file mode 100644 index 00000000..eddb2c26 --- /dev/null +++ b/os/unix/Makefile.in @@ -0,0 +1,5 @@ + +LTLIBRARY_NAME = libos.la +LTLIBRARY_SOURCES = unixd.c + +include $(top_srcdir)/build/ltlib.mk diff --git a/os/unix/config.m4 b/os/unix/config.m4 new file mode 100644 index 00000000..dacbf6b5 --- /dev/null +++ b/os/unix/config.m4 @@ -0,0 +1,7 @@ +if test "$OS" = "unix" ; then + APACHE_TYPE_RLIM_T + + AC_CHECK_HEADERS(sys/time.h sys/resource.h sys/sem.h sys/ipc.h) + + AC_CHECK_FUNCS(setsid killpg) +fi diff --git a/os/unix/os.h b/os/unix/os.h new file mode 100644 index 00000000..029b1113 --- /dev/null +++ b/os/unix/os.h @@ -0,0 +1,48 @@ +/* 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. + */ + +/** + * @file unix/os.h + * @brief This file in included in all Apache source code. It contains definitions + * of facilities available on _this_ operating system (HAVE_* macros), + * and prototypes of OS specific functions defined in os.c or os-inline.c + * + * @defgroup APACHE_OS_UNIX unix + * @ingroup APACHE_OS + * @{ + */ + +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#include "apr.h" +#include "ap_config.h" + +#ifndef PLATFORM +#define PLATFORM "Unix" +#endif + +/* On platforms where AP_NEED_SET_MUTEX_PERMS is defined, modules + * should call unixd_set_*_mutex_perms on mutexes created in the + * parent process. */ +#define AP_NEED_SET_MUTEX_PERMS 1 + +#ifdef _OSD_POSIX +pid_t os_fork(const char *user); +#endif + +#endif /* !APACHE_OS_H */ +/** @} */ diff --git a/os/unix/unixd.c b/os/unix/unixd.c new file mode 100644 index 00000000..ae140093 --- /dev/null +++ b/os/unix/unixd.c @@ -0,0 +1,718 @@ +/* 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. + */ + +#include "ap_config.h" +#define CORE_PRIVATE +#include "httpd.h" +#include "http_config.h" +#include "http_main.h" +#include "http_log.h" +#include "unixd.h" +#include "mpm_common.h" +#include "os.h" +#include "ap_mpm.h" +#include "apr_thread_proc.h" +#include "apr_strings.h" +#include "apr_portable.h" +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +/* XXX */ +#include <sys/stat.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_GRP_H +#include <grp.h> +#endif +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#ifdef HAVE_SYS_SEM_H +#include <sys/sem.h> +#endif +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif + +unixd_config_rec unixd_config; + +/* Set group privileges. + * + * Note that we use the username as set in the config files, rather than + * the lookup of to uid --- the same uid may have multiple passwd entries, + * with different sets of groups for each. + */ + +static int set_group_privs(void) +{ + if (!geteuid()) { + const char *name; + + /* Get username if passed as a uid */ + + if (unixd_config.user_name[0] == '#') { + struct passwd *ent; + uid_t uid = atoi(&unixd_config.user_name[1]); + + if ((ent = getpwuid(uid)) == NULL) { + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "getpwuid: couldn't determine user name from uid %u, " + "you probably need to modify the User directive", + (unsigned)uid); + return -1; + } + + name = ent->pw_name; + } + else + name = unixd_config.user_name; + +#if !defined(OS2) && !defined(TPF) + /* OS/2 and TPF don't support groups. */ + + /* + * Set the GID before initgroups(), since on some platforms + * setgid() is known to zap the group list. + */ + if (setgid(unixd_config.group_id) == -1) { + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "setgid: unable to set group id to Group %u", + (unsigned)unixd_config.group_id); + return -1; + } + + /* Reset `groups' attributes. */ + + if (initgroups(name, unixd_config.group_id) == -1) { + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "initgroups: unable to set groups for User %s " + "and Group %u", name, (unsigned)unixd_config.group_id); + return -1; + } +#endif /* !defined(OS2) && !defined(TPF) */ + } + return 0; +} + + +AP_DECLARE(int) unixd_setup_child(void) +{ + if (set_group_privs()) { + return -1; + } +#ifdef MPE + /* Only try to switch if we're running as MANAGER.SYS */ + if (geteuid() == 1 && unixd_config.user_id > 1) { + GETPRIVMODE(); + if (setuid(unixd_config.user_id) == -1) { + GETUSERMODE(); + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "setuid: unable to change to uid: %ld", + (long) unixd_config.user_id); + exit(1); + } + GETUSERMODE(); + } +#else + /* Only try to switch if we're running as root */ + if (!geteuid() && ( +#ifdef _OSD_POSIX + os_init_job_environment(NULL, unixd_config.user_name, ap_exists_config_define("DEBUG")) != 0 || +#endif + setuid(unixd_config.user_id) == -1)) { + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "setuid: unable to change to uid: %ld", + (long) unixd_config.user_id); + return -1; + } +#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) + /* this applies to Linux 2.4+ */ +#ifdef AP_MPM_WANT_SET_COREDUMPDIR + if (ap_coredumpdir_configured) { + if (prctl(PR_SET_DUMPABLE, 1)) { + ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL, + "set dumpable failed - this child will not coredump" + " after software errors"); + } + } +#endif +#endif +#endif + return 0; +} + + +AP_DECLARE(const char *) unixd_set_user(cmd_parms *cmd, void *dummy, + const char *arg) +{ + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err != NULL) { + return err; + } + + unixd_config.user_name = arg; + unixd_config.user_id = ap_uname2id(arg); +#if !defined (BIG_SECURITY_HOLE) && !defined (OS2) + if (unixd_config.user_id == 0) { + return "Error:\tApache has not been designed to serve pages while\n" + "\trunning as root. There are known race conditions that\n" + "\twill allow any local user to read any file on the system.\n" + "\tIf you still desire to serve pages as root then\n" + "\tadd -DBIG_SECURITY_HOLE to the CFLAGS env variable\n" + "\tand then rebuild the server.\n" + "\tIt is strongly suggested that you instead modify the User\n" + "\tdirective in your httpd.conf file to list a non-root\n" + "\tuser.\n"; + } +#endif + + return NULL; +} + +AP_DECLARE(const char *) unixd_set_group(cmd_parms *cmd, void *dummy, + const char *arg) +{ + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err != NULL) { + return err; + } + + unixd_config.group_id = ap_gname2id(arg); + + return NULL; +} + +AP_DECLARE(void) unixd_pre_config(apr_pool_t *ptemp) +{ + apr_finfo_t wrapper; + + unixd_config.user_name = DEFAULT_USER; + unixd_config.user_id = ap_uname2id(DEFAULT_USER); + unixd_config.group_id = ap_gname2id(DEFAULT_GROUP); + + /* Check for suexec */ + unixd_config.suexec_enabled = 0; + if ((apr_stat(&wrapper, SUEXEC_BIN, + APR_FINFO_NORM, ptemp)) != APR_SUCCESS) { + return; + } + + if ((wrapper.protection & APR_USETID) && wrapper.user == 0) { + unixd_config.suexec_enabled = 1; + } +} + + +AP_DECLARE(void) unixd_set_rlimit(cmd_parms *cmd, struct rlimit **plimit, + const char *arg, const char * arg2, int type) +{ +#if (defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC) || defined(RLIMIT_AS)) && APR_HAVE_STRUCT_RLIMIT && APR_HAVE_GETRLIMIT + char *str; + struct rlimit *limit; + /* If your platform doesn't define rlim_t then typedef it in ap_config.h */ + rlim_t cur = 0; + rlim_t max = 0; + + *plimit = (struct rlimit *)apr_pcalloc(cmd->pool, sizeof(**plimit)); + limit = *plimit; + if ((getrlimit(type, limit)) != 0) { + *plimit = NULL; + ap_log_error(APLOG_MARK, APLOG_ERR, errno, cmd->server, + "%s: getrlimit failed", cmd->cmd->name); + return; + } + + if ((str = ap_getword_conf(cmd->pool, &arg))) { + if (!strcasecmp(str, "max")) { + cur = limit->rlim_max; + } + else { + cur = atol(str); + } + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server, + "Invalid parameters for %s", cmd->cmd->name); + return; + } + + if (arg2 && (str = ap_getword_conf(cmd->pool, &arg2))) { + max = atol(str); + } + + /* if we aren't running as root, cannot increase max */ + if (geteuid()) { + limit->rlim_cur = cur; + if (max) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server, + "Must be uid 0 to raise maximum %s", cmd->cmd->name); + } + } + else { + if (cur) { + limit->rlim_cur = cur; + } + if (max) { + limit->rlim_max = max; + } + } +#else + + ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server, + "Platform does not support rlimit for %s", cmd->cmd->name); +#endif +} + +APR_HOOK_STRUCT( + APR_HOOK_LINK(get_suexec_identity) +) + +AP_IMPLEMENT_HOOK_RUN_FIRST(ap_unix_identity_t *, get_suexec_identity, + (const request_rec *r), (r), NULL) + +static apr_status_t ap_unix_create_privileged_process( + apr_proc_t *newproc, const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, ap_unix_identity_t *ugid, + apr_pool_t *p) +{ + int i = 0; + const char **newargs; + char *newprogname; + char *execuser, *execgroup; + const char *argv0; + + if (!unixd_config.suexec_enabled) { + return apr_proc_create(newproc, progname, args, env, attr, p); + } + + argv0 = ap_strrchr_c(progname, '/'); + /* Allow suexec's "/" check to succeed */ + if (argv0 != NULL) { + argv0++; + } + else { + argv0 = progname; + } + + + if (ugid->userdir) { + execuser = apr_psprintf(p, "~%ld", (long) ugid->uid); + } + else { + execuser = apr_psprintf(p, "%ld", (long) ugid->uid); + } + execgroup = apr_psprintf(p, "%ld", (long) ugid->gid); + + if (!execuser || !execgroup) { + return APR_ENOMEM; + } + + i = 0; + if (args) { + while (args[i]) { + i++; + } + } + /* allocate space for 4 new args, the input args, and a null terminator */ + newargs = apr_palloc(p, sizeof(char *) * (i + 4)); + newprogname = SUEXEC_BIN; + newargs[0] = SUEXEC_BIN; + newargs[1] = execuser; + newargs[2] = execgroup; + newargs[3] = apr_pstrdup(p, argv0); + + /* + ** using a shell to execute suexec makes no sense thus + ** we force everything to be APR_PROGRAM, and never + ** APR_SHELLCMD + */ + if(apr_procattr_cmdtype_set(attr, APR_PROGRAM) != APR_SUCCESS) { + return APR_EGENERAL; + } + + i = 1; + do { + newargs[i + 3] = args[i]; + } while (args[i++]); + + return apr_proc_create(newproc, newprogname, newargs, env, attr, p); +} + +AP_DECLARE(apr_status_t) ap_os_create_privileged_process( + const request_rec *r, + apr_proc_t *newproc, const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, apr_pool_t *p) +{ + ap_unix_identity_t *ugid = ap_run_get_suexec_identity(r); + + if (ugid == NULL) { + return apr_proc_create(newproc, progname, args, env, attr, p); + } + + return ap_unix_create_privileged_process(newproc, progname, args, env, + attr, ugid, p); +} + +/* XXX move to APR and externalize (but implement differently :) ) */ +static apr_lockmech_e proc_mutex_mech(apr_proc_mutex_t *pmutex) +{ + const char *mechname = apr_proc_mutex_name(pmutex); + + if (!strcmp(mechname, "sysvsem")) { + return APR_LOCK_SYSVSEM; + } + else if (!strcmp(mechname, "flock")) { + return APR_LOCK_FLOCK; + } + return APR_LOCK_DEFAULT; +} + +AP_DECLARE(apr_status_t) unixd_set_proc_mutex_perms(apr_proc_mutex_t *pmutex) +{ + if (!geteuid()) { + apr_lockmech_e mech = proc_mutex_mech(pmutex); + + switch(mech) { +#if APR_HAS_SYSVSEM_SERIALIZE + case APR_LOCK_SYSVSEM: + { + apr_os_proc_mutex_t ospmutex; +#if !APR_HAVE_UNION_SEMUN + union semun { + long val; + struct semid_ds *buf; + unsigned short *array; + }; +#endif + union semun ick; + struct semid_ds buf; + + apr_os_proc_mutex_get(&ospmutex, pmutex); + buf.sem_perm.uid = unixd_config.user_id; + buf.sem_perm.gid = unixd_config.group_id; + buf.sem_perm.mode = 0600; + ick.buf = &buf; + if (semctl(ospmutex.crossproc, 0, IPC_SET, ick) < 0) { + return errno; + } + } + break; +#endif +#if APR_HAS_FLOCK_SERIALIZE + case APR_LOCK_FLOCK: + { + const char *lockfile = apr_proc_mutex_lockfile(pmutex); + + if (lockfile) { + if (chown(lockfile, unixd_config.user_id, + -1 /* no gid change */) < 0) { + return errno; + } + } + } + break; +#endif + default: + /* do nothing */ + break; + } + } + return APR_SUCCESS; +} + +AP_DECLARE(apr_status_t) unixd_set_global_mutex_perms(apr_global_mutex_t *gmutex) +{ +#if !APR_PROC_MUTEX_IS_GLOBAL + apr_os_global_mutex_t osgmutex; + apr_os_global_mutex_get(&osgmutex, gmutex); + return unixd_set_proc_mutex_perms(osgmutex.proc_mutex); +#else /* APR_PROC_MUTEX_IS_GLOBAL */ + /* In this case, apr_proc_mutex_t and apr_global_mutex_t are the same. */ + return unixd_set_proc_mutex_perms(gmutex); +#endif /* APR_PROC_MUTEX_IS_GLOBAL */ +} + +AP_DECLARE(apr_status_t) unixd_accept(void **accepted, ap_listen_rec *lr, + apr_pool_t *ptrans) +{ + apr_socket_t *csd; + apr_status_t status; +#ifdef _OSD_POSIX + int sockdes; +#endif + + *accepted = NULL; + status = apr_socket_accept(&csd, lr->sd, ptrans); + if (status == APR_SUCCESS) { + *accepted = csd; +#ifdef _OSD_POSIX + apr_os_sock_get(&sockdes, csd); + if (sockdes >= FD_SETSIZE) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, + "new file descriptor %d is too large; you probably need " + "to rebuild Apache with a larger FD_SETSIZE " + "(currently %d)", + sockdes, FD_SETSIZE); + apr_socket_close(csd); + return APR_EINTR; + } +#endif + return APR_SUCCESS; + } + + if (APR_STATUS_IS_EINTR(status)) { + return status; + } + /* Our old behaviour here was to continue after accept() + * errors. But this leads us into lots of troubles + * because most of the errors are quite fatal. For + * example, EMFILE can be caused by slow descriptor + * leaks (say in a 3rd party module, or libc). It's + * foolish for us to continue after an EMFILE. We also + * seem to tickle kernel bugs on some platforms which + * lead to never-ending loops here. So it seems best + * to just exit in most cases. + */ + switch (status) { +#if defined(HPUX11) && defined(ENOBUFS) + /* On HPUX 11.x, the 'ENOBUFS, No buffer space available' + * error occurs because the accept() cannot complete. + * You will not see ENOBUFS with 10.20 because the kernel + * hides any occurrence from being returned to user space. + * ENOBUFS with 11.x's TCP/IP stack is possible, and could + * occur intermittently. As a work-around, we are going to + * ignore ENOBUFS. + */ + case ENOBUFS: +#endif + +#ifdef EPROTO + /* EPROTO on certain older kernels really means + * ECONNABORTED, so we need to ignore it for them. + * See discussion in new-httpd archives nh.9701 + * search for EPROTO. + * + * Also see nh.9603, search for EPROTO: + * There is potentially a bug in Solaris 2.x x<6, + * and other boxes that implement tcp sockets in + * userland (i.e. on top of STREAMS). On these + * systems, EPROTO can actually result in a fatal + * loop. See PR#981 for example. It's hard to + * handle both uses of EPROTO. + */ + case EPROTO: +#endif +#ifdef ECONNABORTED + case ECONNABORTED: +#endif + /* Linux generates the rest of these, other tcp + * stacks (i.e. bsd) tend to hide them behind + * getsockopt() interfaces. They occur when + * the net goes sour or the client disconnects + * after the three-way handshake has been done + * in the kernel but before userland has picked + * up the socket. + */ +#ifdef ECONNRESET + case ECONNRESET: +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: +#endif +#ifdef EHOSTUNREACH + case EHOSTUNREACH: +#endif +#ifdef ENETUNREACH + case ENETUNREACH: +#endif + /* EAGAIN/EWOULDBLOCK can be returned on BSD-derived + * TCP stacks when the connection is aborted before + * we call connect, but only because our listener + * sockets are non-blocking (AP_NONBLOCK_WHEN_MULTI_LISTEN) + */ +#ifdef EAGAIN + case EAGAIN: +#endif +#ifdef EWOULDBLOCK +#if !defined(EAGAIN) || EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: +#endif +#endif + break; +#ifdef ENETDOWN + case ENETDOWN: + /* + * When the network layer has been shut down, there + * is not much use in simply exiting: the parent + * would simply re-create us (and we'd fail again). + * Use the CHILDFATAL code to tear the server down. + * @@@ Martin's idea for possible improvement: + * A different approach would be to define + * a new APEXIT_NETDOWN exit code, the reception + * of which would make the parent shutdown all + * children, then idle-loop until it detected that + * the network is up again, and restart the children. + * Ben Hyde noted that temporary ENETDOWN situations + * occur in mobile IP. + */ + ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, + "apr_socket_accept: giving up."); + return APR_EGENERAL; +#endif /*ENETDOWN*/ + +#ifdef TPF + case EINACT: + ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, + "offload device inactive"); + return APR_EGENERAL; + break; + default: + ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, + "select/accept error (%d)", status); + return APR_EGENERAL; +#else + default: + ap_log_error(APLOG_MARK, APLOG_ERR, status, ap_server_conf, + "apr_socket_accept: (client socket)"); + return APR_EGENERAL; +#endif + } + return status; +} + + +#ifdef _OSD_POSIX + +#include "apr_lib.h" + +#define USER_LEN 8 + +typedef enum +{ + bs2_unknown, /* not initialized yet. */ + bs2_noFORK, /* no fork() because -X flag was specified */ + bs2_FORK, /* only fork() because uid != 0 */ + bs2_UFORK /* Normally, ufork() is used to switch identities. */ +} bs2_ForkType; + +static bs2_ForkType forktype = bs2_unknown; + + +static void ap_str_toupper(char *str) +{ + while (*str) { + *str = apr_toupper(*str); + ++str; + } +} + +/* Determine the method for forking off a child in such a way as to + * set both the POSIX and BS2000 user id's to the unprivileged user. + */ +static bs2_ForkType os_forktype(int one_process) +{ + /* have we checked the OS version before? If yes return the previous + * result - the OS release isn't going to change suddenly! + */ + if (forktype == bs2_unknown) { + /* not initialized yet */ + + /* No fork if the one_process option was set */ + if (one_process) { + forktype = bs2_noFORK; + } + /* If the user is unprivileged, use the normal fork() only. */ + else if (getuid() != 0) { + forktype = bs2_FORK; + } + else + forktype = bs2_UFORK; + } + return forktype; +} + + + +/* This routine complements the setuid() call: it causes the BS2000 job + * environment to be switched to the target user's user id. + * That is important if CGI scripts try to execute native BS2000 commands. + */ +int os_init_job_environment(server_rec *server, const char *user_name, int one_process) +{ + bs2_ForkType type = os_forktype(one_process); + + /* We can be sure that no change to uid==0 is possible because of + * the checks in http_core.c:set_user() + */ + + if (one_process) { + + type = forktype = bs2_noFORK; + + ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, + "The debug mode of Apache should only " + "be started by an unprivileged user!"); + return 0; + } + + return 0; +} + +/* BS2000 requires a "special" version of fork() before a setuid() call */ +pid_t os_fork(const char *user) +{ + pid_t pid; + char username[USER_LEN+1]; + + switch (os_forktype(0)) { + + case bs2_FORK: + pid = fork(); + break; + + case bs2_UFORK: + apr_cpystrn(username, user, sizeof username); + + /* Make user name all upper case - for some versions of ufork() */ + ap_str_toupper(username); + + pid = ufork(username); + if (pid == -1 && errno == EPERM) { + ap_log_error(APLOG_MARK, APLOG_EMERG, errno, + NULL, "ufork: Possible mis-configuration " + "for user %s - Aborting.", user); + exit(1); + } + break; + + default: + pid = 0; + break; + } + + return pid; +} + +#endif /* _OSD_POSIX */ + diff --git a/os/unix/unixd.h b/os/unix/unixd.h new file mode 100644 index 00000000..8f781dcc --- /dev/null +++ b/os/unix/unixd.h @@ -0,0 +1,117 @@ +/* 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. + */ + +/** + * @file unixd.h + * @brief common stuff that unix MPMs will want + * + * @addtogroup APACHE_OS_UNIX + * @{ + */ + +#ifndef UNIXD_H +#define UNIXD_H + +#include "httpd.h" +#include "http_config.h" +#include "ap_listen.h" +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#include "apr_hooks.h" +#include "apr_thread_proc.h" +#include "apr_proc_mutex.h" +#include "apr_global_mutex.h" + +#include <pwd.h> +#include <grp.h> +#ifdef APR_HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_IPC_H +#include <sys/ipc.h> +#endif + +typedef struct { + uid_t uid; + gid_t gid; + int userdir; +} ap_unix_identity_t; + +AP_DECLARE_HOOK(ap_unix_identity_t *, get_suexec_identity,(const request_rec *r)) + + +/* Default user name and group name. These may be specified as numbers by + * placing a # before a number */ + +#ifndef DEFAULT_USER +#define DEFAULT_USER "#-1" +#endif +#ifndef DEFAULT_GROUP +#define DEFAULT_GROUP "#-1" +#endif + +typedef struct { + const char *user_name; + uid_t user_id; + gid_t group_id; + int suexec_enabled; +} unixd_config_rec; +AP_DECLARE_DATA extern unixd_config_rec unixd_config; + +AP_DECLARE(int) unixd_setup_child(void); +AP_DECLARE(void) unixd_pre_config(apr_pool_t *ptemp); +AP_DECLARE(const char *) unixd_set_user(cmd_parms *cmd, void *dummy, + const char *arg); +AP_DECLARE(const char *) unixd_set_group(cmd_parms *cmd, void *dummy, + const char *arg); +#if defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC) || defined(RLIMIT_AS) +AP_DECLARE(void) unixd_set_rlimit(cmd_parms *cmd, struct rlimit **plimit, + const char *arg, const char * arg2, int type); +#endif + +/** + * One of the functions to set mutex permissions should be called in + * the parent process on platforms that switch identity when the + * server is started as root. + * If the child init logic is performed before switching identity + * (e.g., MPM setup for an accept mutex), it should only be called + * for SysV semaphores. Otherwise, it is safe to call it for all + * mutex types. + */ +AP_DECLARE(apr_status_t) unixd_set_proc_mutex_perms(apr_proc_mutex_t *pmutex); +AP_DECLARE(apr_status_t) unixd_set_global_mutex_perms(apr_global_mutex_t *gmutex); +AP_DECLARE(apr_status_t) unixd_accept(void **accepted, ap_listen_rec *lr, apr_pool_t *ptrans); + +#ifdef HAVE_KILLPG +#define unixd_killpg(x, y) (killpg ((x), (y))) +#define ap_os_killpg(x, y) (killpg ((x), (y))) +#else /* HAVE_KILLPG */ +#define unixd_killpg(x, y) (kill (-(x), (y))) +#define ap_os_killpg(x, y) (kill (-(x), (y))) +#endif /* HAVE_KILLPG */ + +#define UNIX_DAEMON_COMMANDS \ +AP_INIT_TAKE1("User", unixd_set_user, NULL, RSRC_CONF, \ + "Effective user id for this server"), \ +AP_INIT_TAKE1("Group", unixd_set_group, NULL, RSRC_CONF, \ + "Effective group id for this server") + +#endif +/** @} */ diff --git a/os/win32/BaseAddr.ref b/os/win32/BaseAddr.ref new file mode 100644 index 00000000..d0d1e041 --- /dev/null +++ b/os/win32/BaseAddr.ref @@ -0,0 +1,75 @@ +; os/win32/BaseAddr.ref contains the central repository +; of all module base addresses +; to avoid relocation + +; WARNING: Update this file by reviewing the image size +; of the debug-generated dll files; release images +; should fit in the larger debug-sized space. + +; module name base-address max-size + +libhttpd.dll 0x6FF00000 0x000A0000 +mod_auth_basic.so 0x6FEF0000 0x00010000 +mod_auth_digest.so 0x6FED0000 0x00020000 +mod_cern_meta.so 0x6FEC0000 0x00010000 +mod_expires.so 0x6FEB0000 0x00010000 +mod_headers.so 0x6FEA0000 0x00010000 +mod_info.so 0x6FE90000 0x00010000 +mod_rewrite.so 0x6FE70000 0x00020000 +mod_speling.so 0x6FE60000 0x00010000 +mod_status.so 0x6FE50000 0x00010000 +mod_usertrack.so 0x6FE40000 0x00010000 +mod_file_cache.so 0x6FE20000 0x00020000 +mod_unique_id.so 0x6FE00000 0x00010000 +mod_vhost_alias.so 0x6FDF0000 0x00010000 +mod_mime_magic.so 0x6FDE0000 0x00010000 +mod_dav.so 0x6FDC0000 0x00020000 +mod_dav_fs.so 0x6FDB0000 0x00010000 +mod_proxy_connect.so 0x6FD90000 0x00010000 +mod_proxy_ftp.so 0x6FD80000 0x00010000 +mod_proxy_http.so 0x6FD70000 0x00010000 +mod_ssl.so 0x6FD00000 0x00070000 +mod_actions.so 0x6FCE0000 0x00010000 +mod_alias.so 0x6FCD0000 0x00010000 +mod_asis.so 0x6FCC0000 0x00010000 +mod_autoindex.so 0x6FCA0000 0x00010000 +mod_cgi.so 0x6FC90000 0x00010000 +mod_dir.so 0x6FC80000 0x00010000 +mod_env.so 0x6FC70000 0x00010000 +mod_imagemap.so 0x6FC60000 0x00010000 +mod_include.so 0x6FC50000 0x00010000 +mod_isapi.so 0x6FC40000 0x00010000 +mod_log_config.so 0x6FC30000 0x00010000 +mod_mime.so 0x6FC20000 0x00010000 +mod_negotiation.so 0x6FC10000 0x00010000 +mod_setenvif.so 0x6FC00000 0x00010000 +mod_userdir.so 0x6FBF0000 0x00010000 +mod_cache.so 0x6FBE0000 0x00010000 +mod_disk_cache.so 0x6FBD0000 0x00010000 +mod_mem_cache.so 0x6FBC0000 0x00010000 +mod_deflate.so 0x6FBA0000 0x00020000 +mod_ext_filter.so 0x6FB90000 0x00010000 +mod_charset_lite.so 0x6FB80000 0x00010000 +mod_authn_anon.so 0x6FB70000 0x00010000 +mod_authn_dbm.so 0x6FB60000 0x00010000 +mod_authn_default.so 0x6FB50000 0x00010000 +mod_authn_file.so 0x6FB40000 0x00010000 +mod_authz_dbm.so 0x6FB30000 0x00010000 +mod_authz_default.so 0x6FB20000 0x00010000 +mod_authz_groupfile.so 0x6FB10000 0x00010000 +mod_authz_host.so 0x6FB00000 0x00010000 +mod_authz_user.so 0x6FAF0000 0x00010000 +mod_logio.so 0x6FAE0000 0x00010000 +mod_ldap.so 0x6FAD0000 0x00010000 +mod_authnz_ldap.so 0x6FAC0000 0x00010000 +mod_ident.so 0x6FAB0000 0x00010000 +mod_proxy_ajp.so 0x6FAA0000 0x00010000 +mod_proxy_balancer.so 0x6FA90000 0x00010000 +mod_log_forensic.so 0x6FA80000 0x00010000 +mod_version.so 0x6FA70000 0x00010000 +mod_bucketeer.so 0x6FA60000 0x00010000 +mod_dumpio.so 0x6FA50000 0x00010000 +mod_echo.so 0x6FA40000 0x00010000 +mod_authn_dbd.so 0x6FA30000 0x00010000 +mod_dbd.so 0x6FA20000 0x00010000 +mod_proxy.so 0x6FA00000 0x00010000 diff --git a/os/win32/ap_regkey.c b/os/win32/ap_regkey.c new file mode 100644 index 00000000..ea5a56d3 --- /dev/null +++ b/os/win32/ap_regkey.c @@ -0,0 +1,644 @@ +/* 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. + */ + +#ifdef WIN32 + +#include "apr.h" +#include "arch/win32/apr_arch_file_io.h" +#include "arch/win32/apr_arch_misc.h" +#include "ap_regkey.h" + +struct ap_regkey_t { + apr_pool_t *pool; + HKEY hkey; +}; + + +AP_DECLARE(const ap_regkey_t *) ap_regkey_const(int i) +{ + static struct ap_regkey_t ap_regkey_consts[7] = + { + {NULL, HKEY_CLASSES_ROOT}, + {NULL, HKEY_CURRENT_CONFIG}, + {NULL, HKEY_CURRENT_USER}, + {NULL, HKEY_LOCAL_MACHINE}, + {NULL, HKEY_USERS}, + {NULL, HKEY_PERFORMANCE_DATA}, + {NULL, HKEY_DYN_DATA} + }; + return ap_regkey_consts + i; +} + + +apr_status_t regkey_cleanup(void *key) +{ + ap_regkey_t *regkey = key; + + if (regkey->hkey && regkey->hkey != INVALID_HANDLE_VALUE) { + RegCloseKey(regkey->hkey); + regkey->hkey = INVALID_HANDLE_VALUE; + } + return APR_SUCCESS; +} + + +AP_DECLARE(apr_status_t) ap_regkey_open(ap_regkey_t **newkey, + const ap_regkey_t *parentkey, + const char *keyname, + apr_int32_t flags, + apr_pool_t *pool) +{ + DWORD access = KEY_QUERY_VALUE; + DWORD exists; + HKEY hkey; + LONG rc; + + if (flags & APR_READ) + access |= KEY_READ; + if (flags & APR_WRITE) + access |= KEY_WRITE; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_size_t keylen = strlen(keyname) + 1; + apr_size_t wkeylen = 256; + apr_wchar_t wkeyname[256]; + apr_status_t rv = apr_conv_utf8_to_ucs2(keyname, &keylen, wkeyname, &wkeylen); + if (rv != APR_SUCCESS) + return rv; + else if (keylen) + return APR_ENAMETOOLONG; + + if (flags & APR_CREATE) + rc = RegCreateKeyExW(parentkey->hkey, wkeyname, 0, NULL, 0, + access, NULL, &hkey, &exists); + else + rc = RegOpenKeyExW(parentkey->hkey, wkeyname, 0, access, &hkey); + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + if (flags & APR_CREATE) + rc = RegCreateKeyEx(parentkey->hkey, keyname, 0, NULL, 0, + access, NULL, &hkey, &exists); + else + rc = RegOpenKeyEx(parentkey->hkey, keyname, 0, access, &hkey); + } +#endif + if (rc != ERROR_SUCCESS) { + return APR_FROM_OS_ERROR(rc); + } + if ((flags & APR_EXCL) && (exists == REG_OPENED_EXISTING_KEY)) { + RegCloseKey(hkey); + return APR_EEXIST; + } + + *newkey = apr_palloc(pool, sizeof(**newkey)); + (*newkey)->pool = pool; + (*newkey)->hkey = hkey; + apr_pool_cleanup_register((*newkey)->pool, (void *)(*newkey), + regkey_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + + +AP_DECLARE(apr_status_t) ap_regkey_close(ap_regkey_t *regkey) +{ + apr_status_t stat; + if ((stat = regkey_cleanup(regkey)) == APR_SUCCESS) { + apr_pool_cleanup_kill(regkey->pool, regkey, regkey_cleanup); + } + return stat; +} + + +AP_DECLARE(apr_status_t) ap_regkey_remove(const ap_regkey_t *parent, + const char *keyname, + apr_pool_t *pool) +{ + LONG rc; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_size_t keylen = strlen(keyname) + 1; + apr_size_t wkeylen = 256; + apr_wchar_t wkeyname[256]; + apr_status_t rv = apr_conv_utf8_to_ucs2(keyname, &keylen, wkeyname, &wkeylen); + if (rv != APR_SUCCESS) + return rv; + else if (keylen) + return APR_ENAMETOOLONG; + rc = RegDeleteKeyW(parent->hkey, wkeyname); + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + /* We need to determine if subkeys exist on Win9x, to provide + * consistent behavior with NT, which returns access denied + * if subkeys exist when attempting to delete a key. + */ + DWORD subkeys; + HKEY hkey; + rc = RegOpenKeyEx(parent->hkey, keyname, 0, KEY_READ, &hkey); + if (rc != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rc); + rc = RegQueryInfoKey(hkey, NULL, NULL, NULL, &subkeys, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + RegCloseKey(hkey); + if (rc != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rc); + else if (subkeys) + return APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED); + rc = RegDeleteKey(parent->hkey, keyname); + } +#endif + if (rc != ERROR_SUCCESS) { + return APR_FROM_OS_ERROR(rc); + } + return APR_SUCCESS; +} + + +AP_DECLARE(apr_status_t) ap_regkey_value_get(char **result, + ap_regkey_t *key, + const char *valuename, + apr_pool_t *pool) +{ + /* Retrieve a registry string value, and explode any envvars + * that the system has configured (e.g. %SystemRoot%/someapp.exe) + */ + LONG rc; + DWORD type; + apr_size_t size = 0; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_size_t valuelen = strlen(valuename) + 1; + apr_size_t wvallen = 256; + apr_wchar_t wvalname[256]; + apr_wchar_t *wvalue; + apr_status_t rv; + rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen); + if (rv != APR_SUCCESS) + return rv; + else if (valuelen) + return APR_ENAMETOOLONG; + /* Read to NULL buffer to determine value size */ + rc = RegQueryValueExW(key->hkey, wvalname, 0, &type, NULL, (DWORD *)&size); + if (rc != ERROR_SUCCESS) { + return APR_FROM_OS_ERROR(rc); + } + if ((size < 2) || (type != REG_SZ && type != REG_EXPAND_SZ)) { + return APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER); + } + + wvalue = apr_palloc(pool, size); + /* Read value based on size query above */ + rc = RegQueryValueExW(key->hkey, wvalname, 0, &type, + (LPBYTE)wvalue, (DWORD *)&size); + if (rc != ERROR_SUCCESS) { + return APR_FROM_OS_ERROR(rc); + } + if (type == REG_EXPAND_SZ) { + apr_wchar_t zbuf[1]; + size = ExpandEnvironmentStringsW(wvalue, zbuf, 0); + if (size) { + apr_wchar_t *tmp = wvalue; + /* The size returned by ExpandEnvironmentStringsW is wchars */ + wvalue = apr_palloc(pool, size * 2); + size = ExpandEnvironmentStringsW(tmp, wvalue, (DWORD)size); + } + } + else { + /* count wchars from RegQueryValueExW, rather than bytes */ + size /= 2; + } + /* ###: deliberately overallocate all but the trailing null. + * We could precalculate the exact buffer here instead, the question + * is a matter of storage v.s. cpu cycles. + */ + valuelen = (size - 1) * 3 + 1; + *result = apr_palloc(pool, valuelen); + rv = apr_conv_ucs2_to_utf8(wvalue, &size, *result, &valuelen); + if (rv != APR_SUCCESS) + return rv; + else if (size) + return APR_ENAMETOOLONG; + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + /* Read to NULL buffer to determine value size */ + rc = RegQueryValueEx(key->hkey, valuename, 0, &type, NULL, (DWORD *)&size); + if (rc != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rc); + + if ((size < 1) || (type != REG_SZ && type != REG_EXPAND_SZ)) { + return APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER); + } + + *result = apr_palloc(pool, size); + /* Read value based on size query above */ + rc = RegQueryValueEx(key->hkey, valuename, 0, &type, *result, (DWORD *)&size); + if (rc != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rc); + + if (type == REG_EXPAND_SZ) { + /* Advise ExpandEnvironmentStrings that we have a zero char + * buffer to force computation of the required length. + */ + char zbuf[1]; + size = ExpandEnvironmentStrings(*result, zbuf, 0); + if (size) { + char *tmp = *result; + *result = apr_palloc(pool, size); + size = ExpandEnvironmentStrings(tmp, *result, (DWORD)size); + } + } + } +#endif + return APR_SUCCESS; +} + + +AP_DECLARE(apr_status_t) ap_regkey_value_set(ap_regkey_t *key, + const char *valuename, + const char *value, + apr_int32_t flags, + apr_pool_t *pool) +{ + /* Retrieve a registry string value, and explode any envvars + * that the system has configured (e.g. %SystemRoot%/someapp.exe) + */ + LONG rc; + apr_size_t size = strlen(value) + 1; + DWORD type = (flags & AP_REGKEY_EXPAND) ? REG_EXPAND_SZ : REG_SZ; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_size_t alloclen; + apr_size_t valuelen = strlen(valuename) + 1; + apr_size_t wvallen = 256; + apr_wchar_t wvalname[256]; + apr_wchar_t *wvalue; + apr_status_t rv; + rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen); + if (rv != APR_SUCCESS) + return rv; + else if (valuelen) + return APR_ENAMETOOLONG; + + wvallen = alloclen = size; + wvalue = apr_palloc(pool, alloclen * 2); + rv = apr_conv_utf8_to_ucs2(value, &size, wvalue, &wvallen); + if (rv != APR_SUCCESS) + return rv; + else if (size) + return APR_ENAMETOOLONG; + + /* The size is the number of wchars consumed by apr_conv_utf8_to_ucs2 + * converted to bytes; the trailing L'\0' continues to be counted. + */ + size = (alloclen - wvallen) * 2; + rc = RegSetValueExW(key->hkey, wvalname, 0, type, + (LPBYTE)wvalue, (DWORD)size); + if (rc != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rc); + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + rc = RegSetValueEx(key->hkey, valuename, 0, type, value, (DWORD)size); + if (rc != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rc); + } +#endif + return APR_SUCCESS; +} + + +AP_DECLARE(apr_status_t) ap_regkey_value_raw_get(void **result, + apr_size_t *resultsize, + apr_int32_t *resulttype, + ap_regkey_t *key, + const char *valuename, + apr_pool_t *pool) +{ + /* Retrieve a registry string value, and explode any envvars + * that the system has configured (e.g. %SystemRoot%/someapp.exe) + */ + LONG rc; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_size_t valuelen = strlen(valuename) + 1; + apr_size_t wvallen = 256; + apr_wchar_t wvalname[256]; + apr_status_t rv; + rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen); + if (rv != APR_SUCCESS) + return rv; + else if (valuelen) + return APR_ENAMETOOLONG; + /* Read to NULL buffer to determine value size */ + rc = RegQueryValueExW(key->hkey, wvalname, 0, resulttype, + NULL, (LPDWORD)resultsize); + if (rc != ERROR_SUCCESS) { + return APR_FROM_OS_ERROR(rc); + } + + /* Read value based on size query above */ + *result = apr_palloc(pool, *resultsize); + rc = RegQueryValueExW(key->hkey, wvalname, 0, resulttype, + (LPBYTE)*result, (LPDWORD)resultsize); + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + /* Read to NULL buffer to determine value size */ + rc = RegQueryValueEx(key->hkey, valuename, 0, resulttype, + NULL, (LPDWORD)resultsize); + if (rc != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rc); + + /* Read value based on size query above */ + *result = apr_palloc(pool, *resultsize); + rc = RegQueryValueEx(key->hkey, valuename, 0, resulttype, + (LPBYTE)*result, (LPDWORD)resultsize); + if (rc != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rc); + } +#endif + if (rc != ERROR_SUCCESS) { + return APR_FROM_OS_ERROR(rc); + } + + return APR_SUCCESS; +} + + +AP_DECLARE(apr_status_t) ap_regkey_value_raw_set(ap_regkey_t *key, + const char *valuename, + const void *value, + apr_size_t valuesize, + apr_int32_t valuetype, + apr_pool_t *pool) +{ + LONG rc; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_size_t valuelen = strlen(valuename) + 1; + apr_size_t wvallen = 256; + apr_wchar_t wvalname[256]; + apr_status_t rv; + rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen); + if (rv != APR_SUCCESS) + return rv; + else if (valuelen) + return APR_ENAMETOOLONG; + + rc = RegSetValueExW(key->hkey, wvalname, 0, valuetype, + (LPBYTE)value, (DWORD)valuesize); + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + rc = RegSetValueEx(key->hkey, valuename, 0, valuetype, + (LPBYTE)value, (DWORD)valuesize); + } +#endif + if (rc != ERROR_SUCCESS) { + return APR_FROM_OS_ERROR(rc); + } + return APR_SUCCESS; +} + + +AP_DECLARE(apr_status_t) ap_regkey_value_array_get(apr_array_header_t **result, + ap_regkey_t *key, + const char *valuename, + apr_pool_t *pool) +{ + /* Retrieve a registry string value, and explode any envvars + * that the system has configured (e.g. %SystemRoot%/someapp.exe) + */ + apr_status_t rv; + void *value; + char *buf; + char *tmp; + DWORD type; + apr_size_t size = 0; + + rv = ap_regkey_value_raw_get(&value, &size, &type, key, valuename, pool); + if (rv != APR_SUCCESS) { + return rv; + } + else if (type != REG_MULTI_SZ) { + return APR_EINVAL; + } + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_size_t alloclen; + apr_size_t valuelen = strlen(valuename) + 1; + apr_size_t wvallen = 256; + apr_wchar_t *wvalue = (apr_wchar_t *)value; + + /* ###: deliberately overallocate plus two extra nulls. + * We could precalculate the exact buffer here instead, the question + * is a matter of storage v.s. cpu cycles. + */ + size /= 2; + alloclen = valuelen = size * 3 + 2; + buf = apr_palloc(pool, valuelen); + rv = apr_conv_ucs2_to_utf8(value, &size, buf, &valuelen); + if (rv != APR_SUCCESS) + return rv; + else if (size) + return APR_ENAMETOOLONG; + buf[(alloclen - valuelen)] = '\0'; + buf[(alloclen - valuelen) + 1] = '\0'; + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + /* Small possiblity the array is either unterminated + * or single NULL terminated. Avert. + */ + buf = (char *)value; + if (size < 2 || buf[size - 1] != '\0' || buf[size - 2] != '\0') { + buf = apr_palloc(pool, size + 2); + memcpy(buf, value, size); + buf[size + 1] = '\0'; + buf[size] = '\0'; + } + } +#endif + + size = 0; /* Element Count */ + for (tmp = buf; *tmp; ++tmp) { + ++size; + while (*tmp) { + ++tmp; + } + } + + *result = apr_array_make(pool, (int)size, sizeof(char *)); + for (tmp = buf; *tmp; ++tmp) { + char **newelem = (char **) apr_array_push(*result); + *newelem = tmp; + while (*tmp) { + ++tmp; + } + } + + return APR_SUCCESS; +} + + +AP_DECLARE(apr_status_t) ap_regkey_value_array_set(ap_regkey_t *key, + const char *valuename, + int nelts, + const char * const * elts, + apr_pool_t *pool) +{ + /* Retrieve a registry string value, and explode any envvars + * that the system has configured (e.g. %SystemRoot%/someapp.exe) + */ + int i; + const void *value; + apr_size_t bufsize; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_status_t rv; + apr_wchar_t *buf; + apr_wchar_t *tmp; + apr_size_t bufrem; + + bufsize = 1; /* For trailing second null */ + for (i = 0; i < nelts; ++i) { + bufsize += strlen(elts[i]) + 1; + } + if (!nelts) { + ++bufsize; + } + + bufrem = bufsize; + buf = apr_palloc(pool, bufsize * 2); + tmp = buf; + for (i = 0; i < nelts; ++i) { + apr_size_t eltsize = strlen(elts[i]) + 1; + apr_size_t size = eltsize; + rv = apr_conv_utf8_to_ucs2(elts[i], &size, tmp, &bufrem); + if (rv != APR_SUCCESS) + return rv; + else if (size) + return APR_ENAMETOOLONG; + tmp += eltsize; + } + if (!nelts) { + --bufrem; + (*tmp++) = L'\0'; + } + --bufrem; + *tmp = L'\0'; /* Trailing second null */ + + bufsize = (bufsize - bufrem) * 2; + value = (void*)buf; + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + char *buf; + char *tmp; + + bufsize = 1; /* For trailing second null */ + for (i = 0; i < nelts; ++i) { + bufsize += strlen(elts[i]) + 1; + } + if (!nelts) { + ++bufsize; + } + buf = apr_palloc(pool, bufsize); + tmp = buf; + for (i = 0; i < nelts; ++i) { + apr_size_t len = strlen(elts[i]) + 1; + memcpy(tmp, elts[i], len); + tmp += len; + } + if (!nelts) { + (*tmp++) = '\0'; + } + *tmp = '\0'; /* Trailing second null */ + value = buf; + } +#endif + return ap_regkey_value_raw_set(key, valuename, value, + bufsize, REG_MULTI_SZ, pool); +} + + +AP_DECLARE(apr_status_t) ap_regkey_value_remove(const ap_regkey_t *key, + const char *valuename, + apr_pool_t *pool) +{ + LONG rc; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_size_t valuelen = strlen(valuename) + 1; + apr_size_t wvallen = 256; + apr_wchar_t wvalname[256]; + apr_status_t rv = apr_conv_utf8_to_ucs2(valuename, &valuelen, wvalname, &wvallen); + if (rv != APR_SUCCESS) + return rv; + else if (valuelen) + return APR_ENAMETOOLONG; + rc = RegDeleteValueW(key->hkey, wvalname); + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + rc = RegDeleteValue(key->hkey, valuename); + } +#endif + if (rc != ERROR_SUCCESS) { + return APR_FROM_OS_ERROR(rc); + } + return APR_SUCCESS; +} + +#endif /* defined WIN32 */ diff --git a/os/win32/modules.c b/os/win32/modules.c new file mode 100644 index 00000000..911142ad --- /dev/null +++ b/os/win32/modules.c @@ -0,0 +1,57 @@ +/* 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. + */ + +/* modules.c --- major modules compiled into Apache for Win32. + * Only insert an entry for a module if it must be compiled into + * the core server + */ + +#define CORE_PRIVATE +#include "httpd.h" +#include "http_config.h" + +extern module core_module; +extern module win32_module; +extern module mpm_winnt_module; +extern module http_module; +extern module so_module; + +AP_DECLARE_DATA module *ap_prelinked_modules[] = { + &core_module, + &win32_module, + &mpm_winnt_module, + &http_module, + &so_module, + NULL +}; + +ap_module_symbol_t ap_prelinked_module_symbols[] = { + {"core_module", &core_module}, + {"win32_module", &win32_module}, + {"mpm_winnt_module", &mpm_winnt_module}, + {"http_module", &http_module}, + {"so_module", &so_module}, + {NULL, NULL} +}; + +AP_DECLARE_DATA module *ap_preloaded_modules[] = { + &core_module, + &win32_module, + &mpm_winnt_module, + &http_module, + &so_module, + NULL +}; diff --git a/os/win32/os.h b/os/win32/os.h new file mode 100644 index 00000000..ff7dc008 --- /dev/null +++ b/os/win32/os.h @@ -0,0 +1,135 @@ +/* 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. + */ + +/** + * @file win32/os.h + * @brief This file in included in all Apache source code. It contains definitions + * of facilities available on _this_ operating system (HAVE_* macros), + * and prototypes of OS specific functions defined in os.c or os-inline.c + * + * @defgroup APACHE_OS_WIN32 win32 + * @ingroup APACHE_OS + * @{ + */ + +#ifdef WIN32 + +#ifndef AP_OS_H +#define AP_OS_H +/* Delegate windows include to the apr.h header, if USER or GDI declarations + * are required (for a window rather than console application), include + * windows.h prior to any other Apache header files. + */ +#include "apr_pools.h" + +#include <io.h> +#include <fcntl.h> + +#define PLATFORM "Win32" + +/* going away shortly... */ +#define HAVE_DRIVE_LETTERS +#define HAVE_UNC_PATHS +#define CASE_BLIND_FILESYSTEM + +#define APACHE_MPM_DIR "server/mpm/winnt" /* generated on unix */ + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* BIG RED WARNING: exit() is mapped to allow us to capture the exit + * status. This header must only be included from modules linked into + * the ApacheCore.dll - since it's a horrible behavior to exit() from + * any module outside the main() block, and we -will- assume it's a + * fatal error. + */ + +AP_DECLARE_DATA extern int ap_real_exit_code; + +#define exit(status) ((exit)((ap_real_exit_code==2) \ + ? (ap_real_exit_code = (status)) \ + : ((ap_real_exit_code = 0), (status)))) + +#ifdef AP_DECLARE_EXPORT + +/* Defined in util_win32.c and available only to the core module for + * win32 MPM design. + */ + +AP_DECLARE(apr_status_t) ap_os_proc_filepath(char **binpath, apr_pool_t *p); + +typedef enum { + AP_DLL_WINBASEAPI = 0, // kernel32 From WinBase.h + AP_DLL_WINADVAPI = 1, // advapi32 From WinBase.h + AP_DLL_WINSOCKAPI = 2, // mswsock From WinSock.h + AP_DLL_WINSOCK2API = 3, // ws2_32 From WinSock2.h + AP_DLL_defined = 4 // must define as last idx_ + 1 +} ap_dlltoken_e; + +FARPROC ap_load_dll_func(ap_dlltoken_e fnLib, char* fnName, int ordinal); + +PSECURITY_ATTRIBUTES GetNullACL(); +void CleanNullACL(void *sa); + +DWORD wait_for_many_objects(DWORD nCount, CONST HANDLE *lpHandles, + DWORD dwSeconds); + +int set_listeners_noninheritable(apr_pool_t *p); + + +#define AP_DECLARE_LATE_DLL_FUNC(lib, rettype, calltype, fn, ord, args, names) \ + typedef rettype (calltype *ap_winapi_fpt_##fn) args; \ + static ap_winapi_fpt_##fn ap_winapi_pfn_##fn = NULL; \ + __inline rettype ap_winapi_##fn args \ + { if (!ap_winapi_pfn_##fn) \ + ap_winapi_pfn_##fn = (ap_winapi_fpt_##fn) ap_load_dll_func(lib, #fn, ord); \ + return (*(ap_winapi_pfn_##fn)) names; }; \ + +/* Win2K kernel only */ +AP_DECLARE_LATE_DLL_FUNC(AP_DLL_WINADVAPI, BOOL, WINAPI, ChangeServiceConfig2A, 0, ( + SC_HANDLE hService, + DWORD dwInfoLevel, + LPVOID lpInfo), + (hService, dwInfoLevel, lpInfo)); +#undef ChangeServiceConfig2 +#define ChangeServiceConfig2 ap_winapi_ChangeServiceConfig2A + +/* WinNT kernel only */ +AP_DECLARE_LATE_DLL_FUNC(AP_DLL_WINBASEAPI, BOOL, WINAPI, CancelIo, 0, ( + IN HANDLE hFile), + (hFile)); +#undef CancelIo +#define CancelIo ap_winapi_CancelIo + +/* Win9x kernel only */ +AP_DECLARE_LATE_DLL_FUNC(AP_DLL_WINBASEAPI, DWORD, WINAPI, RegisterServiceProcess, 0, ( + DWORD dwProcessId, + DWORD dwType), + (dwProcessId, dwType)); +#define RegisterServiceProcess ap_winapi_RegisterServiceProcess + +#endif /* def AP_DECLARE_EXPORT */ + +#ifdef __cplusplus +} +#endif + +#endif /* ndef AP_OS_H */ +#endif /* def WIN32 */ +/** @} */ diff --git a/os/win32/util_win32.c b/os/win32/util_win32.c new file mode 100644 index 00000000..a0bb7fd7 --- /dev/null +++ b/os/win32/util_win32.c @@ -0,0 +1,186 @@ +/* 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. + */ + +#include "apr_strings.h" +#include "arch/win32/apr_arch_file_io.h" +#include "arch/win32/apr_arch_misc.h" + +#include "httpd.h" +#include "http_log.h" + +#include <stdarg.h> +#include <time.h> +#include <stdlib.h> + + +AP_DECLARE(apr_status_t) ap_os_proc_filepath(char **binpath, apr_pool_t *p) +{ + apr_wchar_t wbinpath[APR_PATH_MAX]; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_size_t binlen; + apr_size_t wbinlen; + apr_status_t rv; + if (!GetModuleFileNameW(NULL, wbinpath, sizeof(wbinpath) + / sizeof(apr_wchar_t))) { + return apr_get_os_error(); + } + wbinlen = wcslen(wbinpath) + 1; + binlen = (wbinlen - 1) * 3 + 1; + *binpath = apr_palloc(p, binlen); + rv = apr_conv_ucs2_to_utf8(wbinpath, &wbinlen, *binpath, &binlen); + if (rv != APR_SUCCESS) + return rv; + else if (wbinlen) + return APR_ENAMETOOLONG; + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + /* share the same scratch buffer */ + char *pathbuf = (char*) wbinpath; + if (!GetModuleFileName(NULL, pathbuf, sizeof(wbinpath))) { + return apr_get_os_error(); + } + *binpath = apr_pstrdup(p, pathbuf); + } +#endif + return APR_SUCCESS; +} + + +AP_DECLARE(apr_status_t) ap_os_create_privileged_process( + const request_rec *r, + apr_proc_t *newproc, const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, apr_pool_t *p) +{ + return apr_proc_create(newproc, progname, args, env, attr, p); +} + + +/* This code is stolen from misc/win32/misc.c and apr_private.h + * This helper code resolves late bound entry points + * missing from one or more releases of the Win32 API... + * but it sure would be nice if we didn't duplicate this code + * from the APR ;-) + */ +static const char* const lateDllName[DLL_defined] = { + "kernel32", "advapi32", "mswsock", "ws2_32" }; +static HMODULE lateDllHandle[DLL_defined] = { + NULL, NULL, NULL, NULL }; + + +FARPROC ap_load_dll_func(ap_dlltoken_e fnLib, char* fnName, int ordinal) +{ + if (!lateDllHandle[fnLib]) { + lateDllHandle[fnLib] = LoadLibrary(lateDllName[fnLib]); + if (!lateDllHandle[fnLib]) + return NULL; + } + if (ordinal) + return GetProcAddress(lateDllHandle[fnLib], (char *) ordinal); + else + return GetProcAddress(lateDllHandle[fnLib], fnName); +} + + +/* To share the semaphores with other processes, we need a NULL ACL + * Code from MS KB Q106387 + */ +PSECURITY_ATTRIBUTES GetNullACL() +{ + PSECURITY_DESCRIPTOR pSD; + PSECURITY_ATTRIBUTES sa; + + sa = (PSECURITY_ATTRIBUTES) LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES)); + sa->nLength = sizeof(sizeof(SECURITY_ATTRIBUTES)); + + pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + sa->lpSecurityDescriptor = pSD; + + if (pSD == NULL || sa == NULL) { + return NULL; + } + apr_set_os_error(0); + if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION) + || apr_get_os_error()) { + LocalFree( pSD ); + LocalFree( sa ); + return NULL; + } + if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE) + || apr_get_os_error()) { + LocalFree( pSD ); + LocalFree( sa ); + return NULL; + } + + sa->bInheritHandle = FALSE; + return sa; +} + + +void CleanNullACL(void *sa) +{ + if (sa) { + LocalFree(((PSECURITY_ATTRIBUTES)sa)->lpSecurityDescriptor); + LocalFree(sa); + } +} + + +/* + * The Win32 call WaitForMultipleObjects will only allow you to wait for + * a maximum of MAXIMUM_WAIT_OBJECTS (current 64). Since the threading + * model in the multithreaded version of apache wants to use this call, + * we are restricted to a maximum of 64 threads. This is a simplistic + * routine that will increase this size. + */ +DWORD wait_for_many_objects(DWORD nCount, CONST HANDLE *lpHandles, + DWORD dwSeconds) +{ + time_t tStopTime; + DWORD dwRet = WAIT_TIMEOUT; + DWORD dwIndex=0; + BOOL bFirst = TRUE; + + tStopTime = time(NULL) + dwSeconds; + + do { + if (!bFirst) + Sleep(1000); + else + bFirst = FALSE; + + for (dwIndex = 0; dwIndex * MAXIMUM_WAIT_OBJECTS < nCount; dwIndex++) { + dwRet = WaitForMultipleObjects( + min(MAXIMUM_WAIT_OBJECTS, nCount - (dwIndex * MAXIMUM_WAIT_OBJECTS)), + lpHandles + (dwIndex * MAXIMUM_WAIT_OBJECTS), + 0, 0); + + if (dwRet != WAIT_TIMEOUT) { + break; + } + } + } while((time(NULL) < tStopTime) && (dwRet == WAIT_TIMEOUT)); + + return dwRet; +} |