diff options
author | Roy T. Fielding <fielding@apache.org> | 1999-08-24 08:46:03 +0200 |
---|---|---|
committer | Roy T. Fielding <fielding@apache.org> | 1999-08-24 08:46:03 +0200 |
commit | 6f96ad52275b5b35226cdb2ce66b3832e9dfb605 (patch) | |
tree | 8892afb8b2e31b3d6e7c9bca839afe51b4e11c40 /os | |
parent | Apache 1.3.9 baseline for the Apache 2.0 repository. (diff) | |
download | apache2-6f96ad52275b5b35226cdb2ce66b3832e9dfb605.tar.xz apache2-6f96ad52275b5b35226cdb2ce66b3832e9dfb605.zip |
Apache 1.3.9 baseline for the Apache 2.0 repository.
Obtained from: Apache 1.3.9 (minus unused files), tag APACHE_1_3_9
Submitted by: Apache Group
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@83750 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'os')
-rw-r--r-- | os/.indent.pro | 54 | ||||
-rw-r--r-- | os/bs2000/.cvsignore | 1 | ||||
-rw-r--r-- | os/bs2000/bs2login.c | 297 | ||||
-rw-r--r-- | os/bs2000/ebcdic.c | 252 | ||||
-rw-r--r-- | os/bs2000/ebcdic.h | 8 | ||||
-rw-r--r-- | os/bs2000/os-inline.c | 31 | ||||
-rw-r--r-- | os/bs2000/os.c | 103 | ||||
-rw-r--r-- | os/bs2000/os.h | 51 | ||||
-rw-r--r-- | os/os2/.cvsignore | 1 | ||||
-rw-r--r-- | os/os2/os-inline.c | 34 | ||||
-rw-r--r-- | os/os2/os.h | 52 | ||||
-rw-r--r-- | os/os2/util_os2.c | 96 | ||||
-rw-r--r-- | os/tpf/TPFExport | 7 | ||||
-rw-r--r-- | os/tpf/ebcdic.c | 221 | ||||
-rw-r--r-- | os/tpf/ebcdic.h | 8 | ||||
-rw-r--r-- | os/tpf/os-inline.c | 31 | ||||
-rw-r--r-- | os/tpf/os.c | 414 | ||||
-rw-r--r-- | os/tpf/os.h | 108 | ||||
-rw-r--r-- | os/tpf/samples/linkdll.jcl | 121 | ||||
-rw-r--r-- | os/tpf/samples/loadset.jcl | 58 | ||||
-rw-r--r-- | os/unix/.cvsignore | 1 | ||||
-rw-r--r-- | os/unix/os-inline.c | 31 | ||||
-rw-r--r-- | os/unix/os.h | 147 | ||||
-rw-r--r-- | os/win32/.cvsignore | 27 | ||||
-rw-r--r-- | os/win32/MakeModuleMak.cpp | 59 | ||||
-rw-r--r-- | os/win32/Module.mak.tmpl | 230 | ||||
-rw-r--r-- | os/win32/mod_isapi.c | 569 | ||||
-rw-r--r-- | os/win32/modules.c | 72 | ||||
-rw-r--r-- | os/win32/os.h | 126 | ||||
-rw-r--r-- | os/win32/util_win32.c | 677 |
30 files changed, 3887 insertions, 0 deletions
diff --git a/os/.indent.pro b/os/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /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/bs2000/.cvsignore b/os/bs2000/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/os/bs2000/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/os/bs2000/bs2login.c b/os/bs2000/bs2login.c new file mode 100644 index 0000000000..32eb1aecb0 --- /dev/null +++ b/os/bs2000/bs2login.c @@ -0,0 +1,297 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +#ifdef _OSD_POSIX +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include <ctype.h> +#include <sys/utsname.h> + +#define ACCT_LEN 8 +#define USER_LEN 8 + +static const char *bs2000_account = NULL; +typedef enum +{ + bs2_unknown, /* not initialized yet. */ + bs2_noFORK, /* no fork() because -X flag was specified */ + bs2_FORK, /* only fork() because uid != 0 */ + bs2_FORK_RINI, /* prior to A17, regular fork() and _rini() was used. */ + bs2_RFORK_RINI, /* for A17, use of _rfork() and _rini() was required */ + bs2_UFORK /* As of A18, the new ufork() is used. */ +} bs2_ForkType; + +static bs2_ForkType forktype = bs2_unknown; + + +static void ap_pad(char *dest, size_t size, char ch) +{ + int i = strlen(dest); /* Leave space for trailing '\0' */ + + while (i < size-1) + dest[i++] = ch; + + dest[size-1] = '\0'; /* Guarantee for trailing '\0' */ +} + +static void ap_str_toupper(char *str) +{ + while (*str) { + *str = ap_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(void) +{ + struct utsname os_version; + + /* 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) { + return forktype; + } + + /* If the user is unprivileged, use the normal fork() only. */ + if (getuid() != 0) { + return forktype = bs2_FORK; + } + + if (uname(&os_version) < 0) + { + ap_log_error(APLOG_MARK, APLOG_ALERT, NULL, + "uname() failed - aborting."); + exit(APEXIT_CHILDFATAL); + } + + /* + * Old BS2000/OSD versions (before XPG4 SPEC1170) don't work with Apache. + * Anyway, simply return a fork(). + */ + if (strcmp(os_version.release, "01.0A") == 0 || + strcmp(os_version.release, "02.0A") == 0 || + strcmp(os_version.release, "02.1A") == 0) + { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL, + "Error: unsupported OS version. " + "You may encounter problems."); + forktype = bs2_FORK; + } + + /* The following versions are special: + * OS versions before A17 needs regular fork() and _rini(). + * A17 requires _rfork() and _rini(), + * and later versions need ufork(). + */ + else if (strcmp(os_version.release, "01.1A") == 0 || + strcmp(os_version.release, "03.0A") == 0 || + strcmp(os_version.release, "03.1A") == 0 || + strcmp(os_version.release, "04.0A") == 0) + { + if (strcmp (os_version.version, "A18") >= 0) + forktype = bs2_UFORK; + + else if (strcmp (os_version.version, "A17") < 0) + forktype = bs2_FORK_RINI; + + else + forktype = bs2_RFORK_RINI; + } + + /* All later OS versions will hopefully use ufork() only ;-) */ + else + forktype = bs2_UFORK; + + return forktype; +} + + + +/* This routine is called by http_core for the BS2000Account directive */ +/* It stores the account name for later use */ +const char *os_set_account(pool *p, const char *account) +{ + char account_temp[ACCT_LEN+1]; + + ap_cpystrn(account_temp, account, sizeof account_temp); + + /* Make account all upper case */ + ap_str_toupper(account_temp); + + /* Pad to length 8 */ + ap_pad(account_temp, sizeof account_temp, ' '); + + bs2000_account = ap_pstrdup(p, account_temp); + return NULL; +} + +/* 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) +{ + _rini_struct inittask; + char username[USER_LEN+1]; + int save_errno; + bs2_ForkType type = os_forktype(); + + /* We can be sure that no change to uid==0 is possible because of + * the checks in http_core.c:set_user() + */ + + /* The _rini() function works only after a prior _rfork(). + * In the case of one_process, it would fail. + */ + if (one_process) { + + type = forktype = bs2_noFORK; + + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server, + "The debug mode of Apache should only " + "be started by an unprivileged user!"); + return 0; + } + + /* If no _rini() is required, then return quickly. */ + if (type != bs2_RFORK_RINI && type != bs2_FORK_RINI) + return 0; + + /* An Account is required for _rini() */ + if (bs2000_account == NULL) + { + ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server, + "No BS2000Account configured - cannot switch to User %s", + user_name); + exit(APEXIT_CHILDFATAL); + } + + ap_cpystrn(username, user_name, sizeof username); + + /* Make user name all upper case */ + ap_str_toupper(username); + + /* Pad to length 8 */ + ap_pad(username, sizeof username, ' '); + + inittask.username = username; + inittask.account = bs2000_account; + inittask.processor_name = " "; + + /* Switch to the new logon user (setuid() and setgid() are done later) */ + /* Only the super user can switch identities. */ + if (_rini(&inittask) != 0) { + + ap_log_error(APLOG_MARK, APLOG_ALERT, server, + "_rini: BS2000 auth failed for user \"%s\" acct \"%s\"", + inittask.username, inittask.account); + + exit(APEXIT_CHILDFATAL); + } + + return 0; +} + +/* BS2000 requires a "special" version of fork() before a setuid()/_rini() call */ +pid_t os_fork(const char *user) +{ + pid_t pid; + char username[USER_LEN+1]; + + switch (os_forktype()) { + case bs2_FORK: + case bs2_FORK_RINI: + pid = fork(); + break; + + case bs2_RFORK_RINI: + pid = _rfork(); + break; + + case bs2_UFORK: + ap_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, + NULL, "ufork: Possible mis-configuration " + "for user %s - Aborting.", user); + exit(1); + } + break; + + default: + pid = 0; + break; + } + + return pid; +} + +#else /* _OSD_POSIX */ +void bs2login_is_not_here() +{ +} +#endif /* _OSD_POSIX */ diff --git a/os/bs2000/ebcdic.c b/os/bs2000/ebcdic.c new file mode 100644 index 0000000000..0303fc6dbb --- /dev/null +++ b/os/bs2000/ebcdic.c @@ -0,0 +1,252 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + + +#ifdef CHARSET_EBCDIC +#include "ap_config.h" +#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 table 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 table 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 table 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 table 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 table 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 /*CHARSET_EBCDIC*/ diff --git a/os/bs2000/ebcdic.h b/os/bs2000/ebcdic.h new file mode 100644 index 0000000000..267f9786df --- /dev/null +++ b/os/bs2000/ebcdic.h @@ -0,0 +1,8 @@ +#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-inline.c b/os/bs2000/os-inline.c new file mode 100644 index 0000000000..e58917af36 --- /dev/null +++ b/os/bs2000/os-inline.c @@ -0,0 +1,31 @@ +/* + * This file contains functions which can be inlined if the compiler + * has an "inline" modifier. Because of this, this file is both a + * header file and a compilable module. + * + * Only inlineable functions should be defined in here. They must all + * include the INLINE modifier. + * + * If the compiler supports inline, this file will be #included as a + * header file from os.h to create all the inline function + * definitions. INLINE will be defined to whatever is required on + * function definitions to make them inline declarations. + * + * If the compiler does not support inline, this file will be compiled + * as a normal C file into libos.a (along with os.c). In this case + * INLINE will _not_ be set so we can use this to test if we are + * compiling this source file. + */ + +#ifndef INLINE +#define INLINE + +/* Anything required only when compiling */ +#include "ap_config.h" + +#endif + +INLINE int ap_os_is_path_absolute(const char *file) +{ + return (file && file[0] == '/' ? 1 : 0); +} diff --git a/os/bs2000/os.c b/os/bs2000/os.c new file mode 100644 index 0000000000..c33810a2f0 --- /dev/null +++ b/os/bs2000/os.c @@ -0,0 +1,103 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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" + +/* Check the Content-Type to decide if conversion is needed */ +int ap_checkconv(struct request_rec *r) +{ + int convert_to_ascii; + const char *type; + + /* To make serving of "raw ASCII text" files easy (they serve faster + * since they don't have to be converted from EBCDIC), a new + * "magic" type prefix was invented: text/x-ascii-{plain,html,...} + * If we detect one of these content types here, we simply correct + * the type to the real text/{plain,html,...} type. Otherwise, we + * set a flag that translation is required later on. + */ + + type = (r->content_type == NULL) ? ap_default_type(r) : r->content_type; + + /* If no content type is set then treat it as (ebcdic) text/plain */ + convert_to_ascii = (type == NULL); + + /* Conversion is applied to text/ files only, if ever. */ + if (type && (strncasecmp(type, "text/", 5) == 0 || + strncasecmp(type, "message/", 8) == 0)) { + if (strncasecmp(type, ASCIITEXT_MAGIC_TYPE_PREFIX, + sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0) + r->content_type = ap_pstrcat(r->pool, "text/", + type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1, + NULL); + else + /* translate EBCDIC to ASCII */ + convert_to_ascii = 1; + } + /* Enable conversion if it's a text document */ + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert_to_ascii); + + return convert_to_ascii; +} + diff --git a/os/bs2000/os.h b/os/bs2000/os.h new file mode 100644 index 0000000000..1ede0813f2 --- /dev/null +++ b/os/bs2000/os.h @@ -0,0 +1,51 @@ +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "BS2000" + +/* + * 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 + */ + +#if !defined(INLINE) && defined(USE_GNU_INLINE) +/* Compiler supports inline, so include the inlineable functions as + * part of the header + */ +#define INLINE extern ap_inline + +INLINE int ap_os_is_path_absolute(const char *file); + +#include "os-inline.c" +#endif + +#ifndef INLINE +/* Compiler does not support inline, so prototype the inlineable functions + * as normal + */ +extern int ap_os_is_path_absolute(const char *file); +#endif + +/* Other ap_os_ routines not used by this platform */ + +#define ap_os_is_filename_valid(f) (1) +#define ap_os_kill(pid, sig) kill(pid, sig) + +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +typedef struct { + char *username; + char *account; + char *processor_name; +} _rini_struct; + +extern int _rini(_rini_struct *); +#endif /* !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) */ + +/* Sorry if this is ugly, but the include order doesn't allow me + * to use request_rec here... */ +struct request_rec; +extern int ap_checkconv(struct request_rec *r); +extern pid_t os_fork(const char *user); + +#endif /*! APACHE_OS_H*/ diff --git a/os/os2/.cvsignore b/os/os2/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/os/os2/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/os/os2/os-inline.c b/os/os2/os-inline.c new file mode 100644 index 0000000000..e3ff9f2fb8 --- /dev/null +++ b/os/os2/os-inline.c @@ -0,0 +1,34 @@ +/* + * This file contains functions which can be inlined if the compiler + * has an "inline" modifier. Because of this, this file is both a + * header file and a compilable module. + * + * Only inlineable functions should be defined in here. They must all + * include the INLINE modifier. + * + * If the compiler supports inline, this file will be #included as a + * header file from os.h to create all the inline function + * definitions. INLINE will be defined to whatever is required on + * function definitions to make them inline declarations. + * + * If the compiler does not support inline, this file will be compiled + * as a normal C file into libos.a (along with os.c). In this case + * INLINE will _not_ be set so we can use this to test if we are + * compiling this source file. + */ + +#ifndef INLINE +#define INLINE + +/* Anything required only when compiling */ +#include "ap_config.h" + +#endif + +INLINE int ap_os_is_path_absolute(const char *file) +{ + /* For now, just do the same check that http_request.c and mod_alias.c + * do. + */ + return file && (file[0] == '/' || file[1] == ':'); +} diff --git a/os/os2/os.h b/os/os2/os.h new file mode 100644 index 0000000000..d717f1f8ca --- /dev/null +++ b/os/os2/os.h @@ -0,0 +1,52 @@ +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "OS/2" +#define HAVE_CANONICAL_FILENAME +#define HAVE_DRIVE_LETTERS + +/* + * 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 + */ + +#if defined(__GNUC__) && !defined(INLINE) +/* Compiler supports inline, so include the inlineable functions as + * part of the header + */ +#define INLINE extern __inline__ + +INLINE int ap_os_is_path_absolute(const char *file); + +#include "os-inline.c" +#endif + +#ifndef INLINE +/* Compiler does not support inline, so prototype the inlineable functions + * as normal + */ +extern int ap_os_is_path_absolute(const char *file); +#endif + +/* FIXME: the following should be implemented on this platform */ +#define ap_os_is_filename_valid(f) (1) + +/* Use a specialized kill() function */ +int ap_os_kill(int pid, int sig); + +/* Maps an OS error code to an error message */ +char *ap_os_error_message(int err); + +/* OS/2 doesn't have symlinks so S_ISLNK is always false */ +#define S_ISLNK(m) 0 + +/* Dynamic loading functions */ +#define ap_os_dso_handle_t unsigned long +void ap_os_dso_init(void); +ap_os_dso_handle_t ap_os_dso_load(const char *); +void ap_os_dso_unload(ap_os_dso_handle_t); +void * ap_os_dso_sym(ap_os_dso_handle_t, const char *); +const char *ap_os_dso_error(void); + +#endif /* ! APACHE_OS_H */ diff --git a/os/os2/util_os2.c b/os/os2/util_os2.c new file mode 100644 index 0000000000..820ea61800 --- /dev/null +++ b/os/os2/util_os2.c @@ -0,0 +1,96 @@ +#define INCL_DOS +#define INCL_DOSERRORS +#include <os2.h> +#include "httpd.h" +#include "http_log.h" + + +API_EXPORT(char *)ap_os_canonical_filename(pool *pPool, const char *szFile) +{ + char buf[HUGE_STRING_LEN]; + char buf2[HUGE_STRING_LEN]; + int rc, len; + char *pos; + +/* Remove trailing slash unless it's a root directory */ + strcpy(buf, szFile); + len = strlen(buf); + + if (len > 3 && buf[len-1] == '/') + buf[--len] = 0; + + rc = DosQueryPathInfo(buf, FIL_QUERYFULLNAME, buf2, HUGE_STRING_LEN); + + if (rc) { + if ( rc != ERROR_INVALID_NAME ) { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL, "OS/2 error %d for file %s", rc, szFile); + return ap_pstrdup(pPool, ""); + } else { + return ap_pstrdup(pPool, szFile); + } + } + + strlwr(buf2); + +/* Switch backslashes to forward */ + for (pos=buf2; *pos; pos++) + if (*pos == '\\') + *pos = '/'; + + return ap_pstrdup(pPool, buf2); +} + + + +int ap_os_kill(pid_t pid, int sig) +{ +/* SIGTERM's don't work too well in OS/2 (only affects other EMX programs). + CGIs may not be, esp. REXX scripts, so use a native call instead */ + + int rc; + + if ( sig == SIGTERM ) { + rc = DosSendSignalException( pid, XCPT_SIGNAL_BREAK ); + + if ( rc ) { + errno = ESRCH; + rc = -1; + } + } else { + rc = kill(pid, sig); + } + + return rc; +} + + + +char *ap_os_error_message(int err) +{ + static char result[200]; + char message[HUGE_STRING_LEN]; + ULONG len; + char *pos; + int c; + + if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err, "OSO001.MSG", &len) == 0) { + len--; + message[len] = 0; + pos = result; + + if (len >= sizeof(result)) + len = sizeof(result-1); + + for (c=0; c<len; c++) { + while (isspace(message[c]) && isspace(message[c+1])) /* skip multiple whitespace */ + c++; + *(pos++) = isspace(message[c]) ? ' ' : message[c]; + } + + *pos = 0; + } else { + sprintf(result, "OS/2 error %d", err); + } + + return result; +} diff --git a/os/tpf/TPFExport b/os/tpf/TPFExport new file mode 100644 index 0000000000..449ebf2f93 --- /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 0000000000..be029f4259 --- /dev/null +++ b/os/tpf/ebcdic.c @@ -0,0 +1,221 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + + +#ifdef CHARSET_EBCDIC +#include "ap_config.h" +#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 table 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 table is a copy of the os_toascii_strictly bijective table 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 table 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 /*CHARSET_EBCDIC*/ + diff --git a/os/tpf/ebcdic.h b/os/tpf/ebcdic.h new file mode 100644 index 0000000000..e9c4120e1a --- /dev/null +++ b/os/tpf/ebcdic.h @@ -0,0 +1,8 @@ +#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-inline.c b/os/tpf/os-inline.c new file mode 100644 index 0000000000..e58917af36 --- /dev/null +++ b/os/tpf/os-inline.c @@ -0,0 +1,31 @@ +/* + * This file contains functions which can be inlined if the compiler + * has an "inline" modifier. Because of this, this file is both a + * header file and a compilable module. + * + * Only inlineable functions should be defined in here. They must all + * include the INLINE modifier. + * + * If the compiler supports inline, this file will be #included as a + * header file from os.h to create all the inline function + * definitions. INLINE will be defined to whatever is required on + * function definitions to make them inline declarations. + * + * If the compiler does not support inline, this file will be compiled + * as a normal C file into libos.a (along with os.c). In this case + * INLINE will _not_ be set so we can use this to test if we are + * compiling this source file. + */ + +#ifndef INLINE +#define INLINE + +/* Anything required only when compiling */ +#include "ap_config.h" + +#endif + +INLINE int ap_os_is_path_absolute(const char *file) +{ + return (file && file[0] == '/' ? 1 : 0); +} diff --git a/os/tpf/os.c b/os/tpf/os.c new file mode 100644 index 0000000000..e4682324cd --- /dev/null +++ b/os/tpf/os.c @@ -0,0 +1,414 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * This file will include OS specific functions which are not inlineable. + * Any inlineable functions should be defined in os-inline.c instead. + */ + +#include "httpd.h" +#include "http_core.h" +#include "os.h" +#include "scoreboard.h" +#include "http_log.h" +#include "http_conf_globals.h" + +static FILE *sock_fp; + +/* Check the Content-Type to decide if conversion is needed */ +int ap_checkconv(struct request_rec *r) +{ + int convert_to_ascii; + const char *type; + + /* To make serving of "raw ASCII text" files easy (they serve faster + * since they don't have to be converted from EBCDIC), a new + * "magic" type prefix was invented: text/x-ascii-{plain,html,...} + * If we detect one of these content types here, we simply correct + * the type to the real text/{plain,html,...} type. Otherwise, we + * set a flag that translation is required later on. + */ + + type = (r->content_type == NULL) ? ap_default_type(r) : r->content_type; + + /* If no content type is set then treat it as (ebcdic) text/plain */ + convert_to_ascii = (type == NULL); + + /* Conversion is applied to text/ files only, if ever. */ + if (type && (strncasecmp(type, "text/", 5) == 0 || + strncasecmp(type, "message/", 8) == 0)) { + if (strncasecmp(type, ASCIITEXT_MAGIC_TYPE_PREFIX, + sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0){ + r->content_type = ap_pstrcat(r->pool, "text/", + type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1, NULL); + if (r->method_number == M_PUT) + ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, 0); + } + + else + /* translate EBCDIC to ASCII */ + convert_to_ascii = 1; + } + else{ + if (r->method_number == M_PUT) + ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, 0); + /* don't translate non-text files to EBCDIC */ + } + /* Enable conversion if it's a text document */ + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert_to_ascii); + + return convert_to_ascii; +} + +int tpf_select(int maxfds, fd_set *reads, fd_set *writes, fd_set *excepts, struct timeval *tv) +{ +/* We're going to force our way through select. We're only interested reads and TPF allows + 2billion+ socket descriptors for we don't want an fd_set that big. Just assume that maxfds-1 + contains the socket descriptor we're interested in. If it's 0, leave it alone. */ + + int sockets[1]; + int no_reads = 0; + int no_writes = 0; + int no_excepts = 0; + int timeout = 0; + int rv; + + if(maxfds) { + if(tv) + timeout = tv->tv_sec * 1000 + tv->tv_usec; + sockets[0] = maxfds-1; + no_reads++; + } + else + sockets[0] = 0; + + ap_check_signals(); + rv = select(sockets, no_reads, no_writes, no_excepts, timeout); + ap_check_signals(); + + return rv; + +} + +int tpf_accept(int sockfd, struct sockaddr *peer, int *paddrlen) +{ + int socks[1]; + int rv; + + ap_check_signals(); + socks[0] = sockfd; + rv = select(socks, 1, 0, 0, 1000); + errno = sock_errno(); + if(rv>0) { + ap_check_signals(); + rv = accept(sockfd, peer, paddrlen); + errno = sock_errno(); + } + return rv; +} + +/* the getpass function is not usable on TPF */ +char *getpass(const char* prompt) +{ + errno = EIO; + return((char *)NULL); +} + +#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); +} + + + +int ap_tpf_spawn_child(pool *p, int (*func) (void *, child_info *), + void *data, enum kill_conditions kill_how, + int *pipe_in, int *pipe_out, int *pipe_err, + int out_fds[], int in_fds[], int err_fds[]) + +{ + + int i, temp_out, temp_in, temp_err, save_errno, pid, result=0; + int fd_flags_out, fd_flags_in, fd_flags_err; + struct tpf_fork_input fork_input; + TPF_FORK_CHILD *cld = (TPF_FORK_CHILD *) data; + array_header *env_arr = ap_table_elts ((array_header *) cld->subprocess_env); + table_entry *elts = (table_entry *) env_arr->elts; + + + + if (func) { + if (result=func(data, NULL)) { + return 0; /* error from child function */ + } + } + + if (pipe_out) { + fd_flags_out = fcntl(out_fds[0], F_GETFD); + fcntl(out_fds[0], F_SETFD, FD_CLOEXEC); + temp_out = dup(STDOUT_FILENO); + fcntl(temp_out, F_SETFD, FD_CLOEXEC); + dup2(out_fds[1], STDOUT_FILENO); + } + + + if (pipe_in) { + fd_flags_in = fcntl(in_fds[1], F_GETFD); + fcntl(in_fds[1], F_SETFD, FD_CLOEXEC); + temp_in = dup(STDIN_FILENO); + fcntl(temp_in, F_SETFD, FD_CLOEXEC); + dup2(in_fds[0], STDIN_FILENO); + } + + if (pipe_err) { + fd_flags_err = fcntl(err_fds[0], F_GETFD); + fcntl(err_fds[0], F_SETFD, FD_CLOEXEC); + temp_err = dup(STDERR_FILENO); + fcntl(temp_err, F_SETFD, FD_CLOEXEC); + dup2(err_fds[1], STDERR_FILENO); + } + + if (cld->subprocess_env) { + for (i = 0; i < env_arr->nelts; ++i) { + if (!elts[i].key) + continue; + setenv (elts[i].key, elts[i].val, 1); + } + } + + fork_input.program = (const char*) cld->filename; + fork_input.prog_type = cld->prog_type; + fork_input.istream = TPF_FORK_IS_BALANCE; + fork_input.ebw_data_length = 0; + fork_input.ebw_data = NULL; + fork_input.parm_data = NULL; + + + if ((pid = tpf_fork(&fork_input)) < 0) { + save_errno = errno; + if (pipe_out) { + close(out_fds[0]); + } + if (pipe_in) { + close(in_fds[1]); + } + if (pipe_err) { + close(err_fds[0]); + } + errno = save_errno; + pid = 0; + } + + if (cld->subprocess_env) { + for (i = 0; i < env_arr->nelts; ++i) { + if (!elts[i].key) + continue; + unsetenv (elts[i].key); + } + } + + if (pipe_out) { + close(out_fds[1]); + dup2(temp_out, STDOUT_FILENO); + close(temp_out); + fcntl(out_fds[0], F_SETFD, fd_flags_out); + } + + if (pipe_in) { + close(in_fds[0]); + dup2(temp_in, STDIN_FILENO); + close(temp_in); + fcntl(in_fds[1], F_SETFD, fd_flags_in); + } + + + if (pipe_err) { + close(err_fds[1]); + dup2(temp_err, STDERR_FILENO); + close(temp_err); + fcntl(err_fds[0], F_SETFD, fd_flags_err); + } + + + if (pid) { + + ap_note_subprocess(p, pid, kill_how); + + if (pipe_out) { + *pipe_out = out_fds[0]; + } + if (pipe_in) { + *pipe_in = in_fds[1]; + } + if (pipe_err) { + *pipe_err = err_fds[0]; + } + } + + return pid; + +} + +pid_t os_fork(server_rec *s, int slot) +{ + struct tpf_fork_input fork_input; + APACHE_TPF_INPUT input_parms; + int count; + listen_rec *lr; + + fflush(stdin); + if (dup2(fileno(sock_fp), STDIN_FILENO) == -1) + ap_log_error(APLOG_MARK, APLOG_CRIT, 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, s, + "unable to replace stdout with sock device driver"); + input_parms.generation = ap_my_generation; +#ifdef SCOREBOARD_FILE + input_parms.scoreboard_fd = scoreboard_fd; +#else /* must be USE_TPF_SCOREBOARD or USE_SHMGET_SCOREBOARD */ + input_parms.scoreboard_heap = ap_scoreboard_image; +#endif + + lr = ap_listeners; + count = 0; + do { + input_parms.listeners[count] = lr->fd; + lr = lr->next; + count++; + } while(lr != ap_listeners); + + input_parms.slot = slot; + input_parms.restart_time = ap_restart_time; + 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; +} + +void os_note_additional_cleanups(pool *p, int sd) { + char sockfilename[50]; + /* write the socket to file so that TPF socket device driver will close socket in case + we happen to abend. */ + sprintf(sockfilename, "/dev/tpf.socket.file/%.8X", sd); + sock_fp = fopen(sockfilename, "r+"); + ap_note_cleanups_for_file(p, sock_fp); /* arrange to close on exec or restart */ + fcntl(sd,F_SETFD,FD_CLOEXEC); +} + +void os_tpf_child(APACHE_TPF_INPUT *input_parms) { + tpf_child = 1; + ap_my_generation = input_parms->generation; + ap_restart_time = input_parms->restart_time; +} + + diff --git a/os/tpf/os.h b/os/tpf/os.h new file mode 100644 index 0000000000..ff65322902 --- /dev/null +++ b/os/tpf/os.h @@ -0,0 +1,108 @@ +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "TPF" + +#ifdef errno +#undef errno +#endif + +/* + * 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 + */ + +#include "ap_config.h" + +#if !defined(INLINE) && defined(USE_GNU_INLINE) +/* Compiler supports inline, so include the inlineable functions as + * part of the header + */ +#define INLINE extern ap_inline +#include "os-inline.c" +#endif + +#ifndef INLINE +/* Compiler does not support inline, so prototype the inlineable functions + * as normal + */ +extern int ap_os_is_path_absolute(const char *f); +#endif + +/* Other ap_os_ routines not used by this platform */ + +#define ap_os_is_filename_valid(f) (1) +#define ap_os_kill(pid, sig) kill(pid, sig) + +/* Sorry if this is ugly, but the include order doesn't allow me + * to use request_rec here... */ +struct request_rec; +extern int ap_checkconv(struct request_rec *r); + +#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 + +#define RESOURCE_KEY ((void*) 0xC1C2C1C3) + +/* TPF doesn't have, or need, tzset (it is used in mod_expires.c) */ +#define tzset() + +#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; + +typedef struct tpf_fork_child { + char *filename; + enum { FORK_NAME = 1, FORK_FILE = 2 } prog_type; + void *subprocess_env; +}TPF_FORK_CHILD; + +int tpf_accept(int sockfd, struct sockaddr *peer, int *paddrlen); +extern int tpf_child; + +struct server_rec; +pid_t os_fork(struct server_rec *s, int slot); +int os_check_server(char *server); +char *getpass(const char *prompt); +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 0000000000..6bcd17c6b0 --- /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 0000000000..c0134d4cb8 --- /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/.cvsignore b/os/unix/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/os/unix/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/os/unix/os-inline.c b/os/unix/os-inline.c new file mode 100644 index 0000000000..54ff49a639 --- /dev/null +++ b/os/unix/os-inline.c @@ -0,0 +1,31 @@ +/* + * This file contains functions which can be inlined if the compiler + * has an "inline" modifier. Because of this, this file is both a + * header file and a compilable module. + * + * Only inlineable functions should be defined in here. They must all + * include the INLINE modifier. + * + * If the compiler supports inline, this file will be #included as a + * header file from os.h to create all the inline function + * definitions. INLINE will be defined to whatever is required on + * function definitions to make them inline declarations. + * + * If the compiler does not support inline, this file will be compiled + * as a normal C file into libos.a (along with os.c). In this case + * INLINE will _not_ be set so we can use this to test if we are + * compiling this source file. + */ + +#ifndef INLINE +#define INLINE + +/* Anything required only when compiling */ +#include "ap_config.h" + +#endif + +INLINE int ap_os_is_path_absolute(const char *file) +{ + return file[0] == '/'; +} diff --git a/os/unix/os.h b/os/unix/os.h new file mode 100644 index 0000000000..6689dfae5c --- /dev/null +++ b/os/unix/os.h @@ -0,0 +1,147 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#include "ap_config.h" + +#ifndef PLATFORM +#define PLATFORM "Unix" +#endif + +/* + * 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 + */ + +#if !defined(INLINE) && defined(USE_GNU_INLINE) +/* Compiler supports inline, so include the inlineable functions as + * part of the header + */ +#define INLINE extern ap_inline + +INLINE int ap_os_is_path_absolute(const char *file); + +#include "os-inline.c" + +#else + +/* Compiler does not support inline, so prototype the inlineable functions + * as normal + */ +extern int ap_os_is_path_absolute(const char *file); +#endif + +/* Other ap_os_ routines not used by this platform */ + +#define ap_os_is_filename_valid(f) (1) +#define ap_os_kill(pid, sig) kill(pid, sig) + +/* + * Abstraction layer for loading + * Apache modules under run-time via + * dynamic shared object (DSO) mechanism + */ + +#ifdef HAVE_DL_H +#include <dl.h> +#endif + +/* + * Do not use native AIX DSO support + */ +#ifdef AIX +#undef HAVE_DLFCN_H +#endif + +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#else +void *dlopen(const char *, int); +int dlclose(void *); +void *dlsym(void *, const char *); +const char *dlerror(void); +#endif + +/* probably on an older system that doesn't support RTLD_NOW or RTLD_LAZY. + * The below define is a lie since we are really doing RTLD_LAZY since the + * system doesn't support RTLD_NOW. + */ +#ifndef RTLD_NOW +#define RTLD_NOW 1 +#endif + +#ifndef RTLD_GLOBAL +#define RTLD_GLOBAL 0 +#endif + +#if (defined(__FreeBSD__) ||\ + defined(__OpenBSD__) ||\ + defined(__NetBSD__) ) && !defined(__ELF__) +#define DLSYM_NEEDS_UNDERSCORE +#endif + +#define ap_os_dso_handle_t void * +void ap_os_dso_init(void); +void * ap_os_dso_load(const char *); +void ap_os_dso_unload(void *); +void * ap_os_dso_sym(void *, const char *); +const char *ap_os_dso_error(void); + +#endif /* !APACHE_OS_H */ diff --git a/os/win32/.cvsignore b/os/win32/.cvsignore new file mode 100644 index 0000000000..17564450e9 --- /dev/null +++ b/os/win32/.cvsignore @@ -0,0 +1,27 @@ +*.mdp +*.ncb +*.opt +*.plg +*.dsw +ApacheModuleAuthAnonD +ApacheModuleAuthAnonR +ApacheModuleCERNMetaD +ApacheModuleCERNMetaR +ApacheModuleDigestD +ApacheModuleDigestR +ApacheModuleExpiresD +ApacheModuleExpiresR +ApacheModuleHeadersD +ApacheModuleHeadersR +ApacheModuleInfoD +ApacheModuleInfoR +ApacheModuleRewriteD +ApacheModuleRewriteR +ApacheModuleSpelingD +ApacheModuleSpelingR +ApacheModuleStatusD +ApacheModuleStatusR +ApacheModuleUserTrackD +ApacheModuleUserTrackR +ApacheOSR +ApacheOSD diff --git a/os/win32/MakeModuleMak.cpp b/os/win32/MakeModuleMak.cpp new file mode 100644 index 0000000000..9ab9f27221 --- /dev/null +++ b/os/win32/MakeModuleMak.cpp @@ -0,0 +1,59 @@ +#include <fstream.h> +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +void MakeMake(const char *szModule,const char *szSource) + { + ifstream ifs("Module.mak.tmpl",ios::nocreate); + assert(ifs.good()); + + char buf[1024]; + sprintf(buf,"%s.mak",szModule); + ofstream ofs(buf,ios::trunc); + for( ; ; ) + { + ifs.getline(buf,sizeof buf); + if(ifs.eof()) + break; + for(char *s=buf ; *s ; ) + { + char *p=strchr(s,'%'); + if(!p) + { + ofs << s << '\n'; + break; + } + if(!strncmp(p,"%Module%",8)) + { + ofs.write(s,p-s); + ofs << szModule; + s=p+8; + } + else if(!strncmp(p,"%Source%",8)) + { + ofs.write(s,p-s); + ofs << szSource; + s=p+8; + } + else + { + ofs.write(s,p-s+1); + s=p+1; + } + } + } + } + +void main(int argc,char **argv) + { + if(argc < 2 || (argc%2) != 1) + { + cerr << argv[0] << " [<module name> <source file>]+\n"; + exit(1); + } + for(int n=1 ; n < argc ; n+=2) + MakeMake(argv[n],argv[n+1]); + } + diff --git a/os/win32/Module.mak.tmpl b/os/win32/Module.mak.tmpl new file mode 100644 index 0000000000..162456f064 --- /dev/null +++ b/os/win32/Module.mak.tmpl @@ -0,0 +1,230 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +!IF "$(CFG)" == "" +CFG=%Module% - Win32 Debug +!MESSAGE No configuration specified. Defaulting to %Module% - Win32\ + Debug. +!ENDIF + +!IF "$(CFG)" != "%Module% - Win32 Release" && "$(CFG)" !=\ + "%Module% - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "%Module%.mak"\ + CFG="%Module% - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "%Module% - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "%Module% - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "%Module% - Win32 Debug" +MTL=mktyplib.exe +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "%Module% - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "%Module%R" +# PROP Intermediate_Dir "%Module%R" +# PROP Target_Dir "" +OUTDIR=.\%Module%R +INTDIR=.\%Module%R + +ALL : "$(OUTDIR)\%Module%.dll" + +CLEAN : + -@erase "$(INTDIR)\%Source%.obj" + -@erase "$(OUTDIR)\%Module%.dll" + -@erase "$(OUTDIR)\%Module%.exp" + -@erase "$(OUTDIR)\%Module%.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\regex" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\regex" /D "WIN32" /D "NDEBUG" /D\ + "_WINDOWS" /Fp"$(INTDIR)/%Module%.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\%Module%R/ +CPP_SBRS=.\. +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/%Module%.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 ..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +LINK32_FLAGS=..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib\ + uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll\ + /incremental:no /pdb:"$(OUTDIR)/%Module%.pdb" /machine:I386\ + /out:"$(OUTDIR)/%Module%.dll"\ + /implib:"$(OUTDIR)/%Module%.lib" +LINK32_OBJS= \ + "$(INTDIR)\%Source%.obj" + +"$(OUTDIR)\%Module%.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "%Module% - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "%Module%D" +# PROP Intermediate_Dir "%Module%D" +# PROP Target_Dir "" +OUTDIR=.\%Module%D +INTDIR=.\%Module%D + +ALL : "$(OUTDIR)\%Module%.dll" + +CLEAN : + -@erase "$(INTDIR)\%Source%.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\%Module%.dll" + -@erase "$(OUTDIR)\%Module%.exp" + -@erase "$(OUTDIR)\%Module%.ilk" + -@erase "$(OUTDIR)\%Module%.lib" + -@erase "$(OUTDIR)\%Module%.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\regex" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\regex" /D "WIN32" /D "_DEBUG"\ + /D "_WINDOWS" /Fp"$(INTDIR)/%Module%.pch" /YX /Fo"$(INTDIR)/"\ + /Fd"$(INTDIR)/" /c +CPP_OBJS=.\%Module%D/ +CPP_SBRS=.\. +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/%Module%.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 ..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +LINK32_FLAGS=..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib\ + uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll\ + /incremental:yes /pdb:"$(OUTDIR)/%Module%.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)/%Module%.dll"\ + /implib:"$(OUTDIR)/%Module%.lib" +LINK32_OBJS= \ + "$(INTDIR)\%Source%.obj" + +"$(OUTDIR)\%Module%.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "%Module% - Win32 Release" +# Name "%Module% - Win32 Debug" + +!IF "$(CFG)" == "%Module% - Win32 Release" + +!ELSEIF "$(CFG)" == "%Module% - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=\work\apache\src\%Source%.c +DEP_CPP_MOD_A=\ + "..\alloc.h"\ + "..\buff.h"\ + "..\conf.h"\ + "..\http_config.h"\ + "..\http_core.h"\ + "..\http_log.h"\ + "..\http_request.h"\ + "..\httpd.h"\ + "..\regex\regex.h"\ + "..\ap_mmn.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"\sys\stat.h"\ + {$(INCLUDE)}"\sys\types.h"\ + +NODEP_CPP_MOD_A=\ + "..\sfio.h"\ + + +"$(INTDIR)\%Source%.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/os/win32/mod_isapi.c b/os/win32/mod_isapi.c new file mode 100644 index 0000000000..fa002708ba --- /dev/null +++ b/os/win32/mod_isapi.c @@ -0,0 +1,569 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * mod_isapi.c - Internet Server Application (ISA) module for Apache + * by Alexei Kosut <akosut@apache.org> + * + * This module implements Microsoft's ISAPI, allowing Apache (when running + * under Windows) to load Internet Server Applications (ISAPI extensions). + * It implements all of the ISAPI 2.0 specification, except for the + * "Microsoft-only" extensions dealing with asynchronous I/O. All ISAPI + * extensions that use only synchronous I/O and are compatible with the + * ISAPI 2.0 specification should work (most ISAPI 1.0 extensions should + * function as well). + * + * To load, simply place the ISA in a location in the document tree. + * Then add an "AddHandler isapi-isa dll" into your config file. + * You should now be able to load ISAPI DLLs just be reffering to their + * URLs. Make sure the ExecCGI option is active in the directory + * the ISA is in. + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_request.h" +#include "http_log.h" +#include "util_script.h" + +/* We use the exact same header file as the original */ +#include <HttpExt.h> + +/* Seems IIS does not enforce the requirement for \r\n termination on HSE_REQ_SEND_RESPONSE_HEADER, + define this to conform */ +#define RELAX_HEADER_RULE + +module isapi_module; + +/* Our "Connection ID" structure */ + +typedef struct { + LPEXTENSION_CONTROL_BLOCK ecb; + request_rec *r; + int status; +} isapi_cid; + +/* Declare the ISAPI functions */ + +BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, + LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer); +BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes, + DWORD dwReserved); +BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize); +BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, + LPVOID lpvBuffer, LPDWORD lpdwSize, + LPDWORD lpdwDataType); + +/* + The optimiser blows it totally here. What happens is that autos are addressed relative to the + stack pointer, which, of course, moves around. The optimiser seems to lose track of it somewhere + between setting isapi_entry and calling through it. We work around the problem by forcing it to + use frame pointers. +*/ +#pragma optimize("y",off) + +int isapi_handler (request_rec *r) { + LPEXTENSION_CONTROL_BLOCK ecb = + ap_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK)); + HSE_VERSION_INFO *pVer = ap_pcalloc(r->pool, sizeof(HSE_VERSION_INFO)); + + HINSTANCE isapi_handle; + BOOL (*isapi_version)(HSE_VERSION_INFO *); /* entry point 1 */ + DWORD (*isapi_entry)(LPEXTENSION_CONTROL_BLOCK); /* entry point 2 */ + BOOL (*isapi_term)(DWORD); /* optional entry point 3 */ + + isapi_cid *cid = ap_pcalloc(r->pool, sizeof(isapi_cid)); + table *e = r->subprocess_env; + int retval; + + /* Use similar restrictions as CGIs */ + + if (!(ap_allow_options(r) & OPT_EXECCGI)) + return FORBIDDEN; + + if (r->finfo.st_mode == 0) + return NOT_FOUND; + + if (S_ISDIR(r->finfo.st_mode)) + return FORBIDDEN; + + /* Load the module */ + + if (!(isapi_handle = LoadLibraryEx(r->filename, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH))) { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, + "Could not load DLL: %s", r->filename); + return SERVER_ERROR; + } + + if (!(isapi_version = + (void *)(GetProcAddress(isapi_handle, "GetExtensionVersion")))) { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, + "DLL could not load GetExtensionVersion(): %s", r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + if (!(isapi_entry = + (void *)(GetProcAddress(isapi_handle, "HttpExtensionProc")))) { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, + "DLL could not load HttpExtensionProc(): %s", r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + isapi_term = (void *)(GetProcAddress(isapi_handle, "TerminateExtension")); + + /* Run GetExtensionVersion() */ + + if ((*isapi_version)(pVer) != TRUE) { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, + "ISAPI GetExtensionVersion() failed: %s", r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + /* Set up variables */ + ap_add_common_vars(r); + ap_add_cgi_vars(r); + + /* Set up connection ID */ + ecb->ConnID = (HCONN)cid; + cid->ecb = ecb; + cid->r = r; + cid->status = 0; + + ecb->cbSize = sizeof(struct _EXTENSION_CONTROL_BLOCK); + ecb->dwVersion = MAKELONG(0, 2); + ecb->dwHttpStatusCode = 0; + strcpy(ecb->lpszLogData, ""); + ecb->lpszMethod = r->method; + ecb->lpszQueryString = ap_table_get(e, "QUERY_STRING"); + ecb->lpszPathInfo = ap_table_get(e, "PATH_INFO"); + ecb->lpszPathTranslated = ap_table_get(e, "PATH_TRANSLATED"); + ecb->lpszContentType = ap_table_get(e, "CONTENT_TYPE"); + + /* Set up client input */ + if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return retval; + } + + if (ap_should_client_block(r)) { + /* Unlike IIS, which limits this to 48k, we read the whole + * sucker in. I suppose this could be bad for memory if someone + * uploaded the complete works of Shakespeare. Well, WebSite + * does the same thing. + */ + long to_read = atol(ap_table_get(e, "CONTENT_LENGTH")); + long read; + + /* Actually, let's cap it at 48k, until we figure out what + * to do with this... we don't want a Content-Length: 1000000000 + * taking out the machine. + */ + + if (to_read > 49152) { + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return HTTP_REQUEST_ENTITY_TOO_LARGE; + } + + ecb->lpbData = ap_pcalloc(r->pool, 1 + to_read); + + if ((read = ap_get_client_block(r, ecb->lpbData, to_read)) < 0) { + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + /* Although its not to spec, IIS seems to null-terminate + * its lpdData string. So we will too. To make sure + * cbAvailable matches cbTotalBytes, we'll up the latter + * and equalize them. + */ + ecb->cbAvailable = ecb->cbTotalBytes = read + 1; + ecb->lpbData[read] = '\0'; + } + else { + ecb->cbTotalBytes = 0; + ecb->cbAvailable = 0; + ecb->lpbData = NULL; + } + + /* Set up the callbacks */ + + ecb->GetServerVariable = &GetServerVariable; + ecb->WriteClient = &WriteClient; + ecb->ReadClient = &ReadClient; + ecb->ServerSupportFunction = &ServerSupportFunction; + + /* All right... try and load the sucker */ + retval = (*isapi_entry)(ecb); + + /* Set the status (for logging) */ + if (ecb->dwHttpStatusCode) + r->status = ecb->dwHttpStatusCode; + + /* Check for a log message - and log it */ + if (ecb->lpszLogData && strcmp(ecb->lpszLogData, "")) + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "%s: %s", ecb->lpszLogData, r->filename); + + /* All done with the DLL... get rid of it */ + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + + switch(retval) { + case HSE_STATUS_SUCCESS: + case HSE_STATUS_SUCCESS_AND_KEEP_CONN: + /* Ignore the keepalive stuff; Apache handles it just fine without + * the ISA's "advice". + */ + + if (cid->status) /* We have a special status to return */ + return cid->status; + + return OK; + case HSE_STATUS_PENDING: /* We don't support this */ + ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); + case HSE_STATUS_ERROR: + default: + return SERVER_ERROR; + } + +} +#pragma optimize("",on) + +BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, + LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer) { + request_rec *r = ((isapi_cid *)hConn)->r; + table *e = r->subprocess_env; + const char *result; + + /* Mostly, we just grab it from the environment, but there are + * a couple of special cases + */ + + if (!strcasecmp(lpszVariableName, "UNMAPPED_REMOTE_USER")) { + /* We don't support NT users, so this is always the same as + * REMOTE_USER + */ + result = ap_table_get(e, "REMOTE_USER"); + } + else if (!strcasecmp(lpszVariableName, "SERVER_PORT_SECURE")) { + /* Apache doesn't support secure requests inherently, so + * we have no way of knowing. We'll be conservative, and say + * all requests are insecure. + */ + result = "0"; + } + else if (!strcasecmp(lpszVariableName, "URL")) { + result = r->uri; + } + else { + result = ap_table_get(e, lpszVariableName); + } + + if (result) { + if (strlen(result) > *lpdwSizeofBuffer) { + *lpdwSizeofBuffer = strlen(result); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + strncpy(lpvBuffer, result, *lpdwSizeofBuffer); + return TRUE; + } + + /* Didn't find it */ + SetLastError(ERROR_INVALID_INDEX); + return FALSE; +} + +BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes, + DWORD dwReserved) { + request_rec *r = ((isapi_cid *)ConnID)->r; + int writ; /* written, actually, but why shouldn't I make up words? */ + + /* We only support synchronous writing */ + if (dwReserved && dwReserved != HSE_IO_SYNC) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if ((writ = ap_rwrite(Buffer, *lpwdwBytes, r)) == EOF) { + SetLastError(ERROR); /* XXX: Find the right error code */ + return FALSE; + } + + *lpwdwBytes = writ; + return TRUE; +} + +BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize) { + /* Doesn't need to do anything; we've read all the data already */ + return TRUE; +} + +/* XXX: There is an O(n^2) attack possible here. */ +BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, + LPVOID lpvBuffer, LPDWORD lpdwSize, + LPDWORD lpdwDataType) { + isapi_cid *cid = (isapi_cid *)hConn; + request_rec *subreq, *r = cid->r; + char *data; + + switch (dwHSERequest) { + case HSE_REQ_SEND_URL_REDIRECT_RESP: + /* Set the status to be returned when the HttpExtensionProc() + * is done. + */ + ap_table_set (r->headers_out, "Location", lpvBuffer); + cid->status = cid->r->status = cid->ecb->dwHttpStatusCode = REDIRECT; + return TRUE; + + case HSE_REQ_SEND_URL: + /* Read any additional input */ + + if (r->remaining > 0) { + char argsbuffer[HUGE_STRING_LEN]; + + while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)); + } + + /* Reset the method to GET */ + r->method = ap_pstrdup(r->pool, "GET"); + r->method_number = M_GET; + + /* Don't let anyone think there's still data */ + ap_table_unset(r->headers_in, "Content-Length"); + + ap_internal_redirect((char *)lpvBuffer, r); + return TRUE; + + case HSE_REQ_SEND_RESPONSE_HEADER: + r->status_line = lpvBuffer ? lpvBuffer : ap_pstrdup(r->pool, "200 OK"); + sscanf(r->status_line, "%d", &r->status); + cid->ecb->dwHttpStatusCode = r->status; + + /* Now fill in the HTTP headers, and the rest of it. Ick. + * lpdwDataType contains a string that has headers (in MIME + * format), a blank like, then (possibly) data. We need + * to parse it. + * + * Easy case first: + */ + if (!lpdwDataType) { + ap_send_http_header(r); + return TRUE; + } + + /* Make a copy - don't disturb the original */ + data = ap_pstrdup(r->pool, (char *)lpdwDataType); + + /* We *should* break before this while loop ends */ + while (*data) { + char *value, *lf = strchr(data, '\n'); + int p; + +#ifdef RELAX_HEADER_RULE + if (lf) + *lf = '\0'; +#else + if (!lf) { /* Huh? Invalid data, I think */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "ISA sent invalid headers: %s", r->filename); + SetLastError(ERROR); /* XXX: Find right error */ + return FALSE; + } + + /* Get rid of \n and \r */ + *lf = '\0'; +#endif + p = strlen(data); + if (p > 0 && data[p-1] == '\r') data[p-1] = '\0'; + + /* End of headers */ + if (*data == '\0') { +#ifdef RELAX_HEADER_RULE + if (lf) +#endif + data = lf + 1; /* Reset data */ + break; + } + + if (!(value = strchr(data, ':'))) { + SetLastError(ERROR); /* XXX: Find right error */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "ISA sent invalid headers", r->filename); + return FALSE; + } + + *value++ = '\0'; + while (*value && ap_isspace(*value)) ++value; + + /* Check all the special-case headers. Similar to what + * ap_scan_script_header_err() does (see that function for + * more detail) + */ + + if (!strcasecmp(data, "Content-Type")) { + char *tmp; + /* Nuke trailing whitespace */ + + char *endp = value + strlen(value) - 1; + while (endp > value && ap_isspace(*endp)) *endp-- = '\0'; + + tmp = ap_pstrdup (r->pool, value); + ap_str_tolower(tmp); + r->content_type = tmp; + } + else if (!strcasecmp(data, "Content-Length")) { + ap_table_set(r->headers_out, data, value); + } + else if (!strcasecmp(data, "Transfer-Encoding")) { + ap_table_set(r->headers_out, data, value); + } + else if (!strcasecmp(data, "Set-Cookie")) { + ap_table_add(r->err_headers_out, data, value); + } + else { + ap_table_merge(r->err_headers_out, data, value); + } + + /* Reset data */ +#ifdef RELAX_HEADER_RULE + if (!lf) { + data += p; + break; + } +#endif + data = lf + 1; + } + + /* All the headers should be set now */ + + ap_send_http_header(r); + + /* Any data left should now be sent directly */ + ap_rputs(data, r); + + return TRUE; + + case HSE_REQ_MAP_URL_TO_PATH: + /* Map a URL to a filename */ + subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, (char *)lpvBuffer, + *lpdwSize), r); + + GetFullPathName(subreq->filename, *lpdwSize - 1, (char *)lpvBuffer, NULL); + + /* IIS puts a trailing slash on directories, Apache doesn't */ + + if (S_ISDIR (subreq->finfo.st_mode)) { + int l = strlen((char *)lpvBuffer); + + ((char *)lpvBuffer)[l] = '\\'; + ((char *)lpvBuffer)[l + 1] = '\0'; + } + + return TRUE; + + case HSE_REQ_DONE_WITH_SESSION: + /* Do nothing... since we don't support async I/O, they'll + * return from HttpExtensionProc soon + */ + return TRUE; + + /* We don't support all this async I/O, Microsoft-specific stuff */ + case HSE_REQ_IO_COMPLETION: + case HSE_REQ_TRANSMIT_FILE: + ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +} + +handler_rec isapi_handlers[] = { +{ "isapi-isa", isapi_handler }, +{ NULL} +}; + +module isapi_module = { + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + NULL, /* server config */ + NULL, /* merge server config */ + NULL, /* command table */ + isapi_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* logger */ + NULL /* header parser */ +}; diff --git a/os/win32/modules.c b/os/win32/modules.c new file mode 100644 index 0000000000..d55d3d832c --- /dev/null +++ b/os/win32/modules.c @@ -0,0 +1,72 @@ +/* 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 + */ + +#include "httpd.h" +#include "http_config.h" + +extern module core_module; +extern module so_module; +extern module mime_module; +extern module access_module; +extern module auth_module; +extern module negotiation_module; +extern module includes_module; +extern module autoindex_module; +extern module dir_module; +extern module cgi_module; +extern module userdir_module; +extern module alias_module; +extern module env_module; +extern module config_log_module; +extern module asis_module; +extern module imap_module; +extern module action_module; +extern module setenvif_module; +extern module isapi_module; + +module *ap_prelinked_modules[] = { + &core_module, + &so_module, + &mime_module, + &access_module, + &auth_module, + &negotiation_module, + &includes_module, + &autoindex_module, + &dir_module, + &cgi_module, + &userdir_module, + &alias_module, + &env_module, + &config_log_module, + &asis_module, + &imap_module, + &action_module, + &setenvif_module, + &isapi_module, + NULL +}; +module *ap_preloaded_modules[] = { + &core_module, + &so_module, + &mime_module, + &access_module, + &auth_module, + &negotiation_module, + &includes_module, + &autoindex_module, + &dir_module, + &cgi_module, + &userdir_module, + &alias_module, + &env_module, + &config_log_module, + &asis_module, + &imap_module, + &action_module, + &setenvif_module, + &isapi_module, + NULL +}; diff --git a/os/win32/os.h b/os/win32/os.h new file mode 100644 index 0000000000..80ffd7e65e --- /dev/null +++ b/os/win32/os.h @@ -0,0 +1,126 @@ +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "Win32" + +/* + * 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 + */ + +/* temporarily replace crypt */ +/* char *crypt(const char *pw, const char *salt); */ +#define crypt(buf,salt) (buf) + +/* Although DIR_TYPE is dirent (see nt/readdir.h) we need direct.h for + chdir() */ +#include <direct.h> + +#define STATUS +/*#define WIN32_LEAN_AND_MEAN Now defined in project files */ +#ifndef STRICT + #define STRICT +#endif +#define CASE_BLIND_FILESYSTEM +#define NO_WRITEV +#define NO_SETSID +#define NO_USE_SIGACTION +#define NO_TIMES +#define NO_GETTIMEOFDAY +//#define NEED_PROCESS_H although we do, this is specially handled in ap_config.h +#define USE_LONGJMP +#define HAVE_MMAP +#define USE_MMAP_SCOREBOARD +#define MULTITHREAD +#define HAVE_CANONICAL_FILENAME +#define HAVE_DRIVE_LETTERS +typedef int uid_t; +typedef int gid_t; +typedef int pid_t; +typedef int mode_t; +typedef char * caddr_t; + +/* +Define export types. API_EXPORT_NONSTD is a nasty hack to avoid having to declare +every configuration function as __stdcall. +*/ + +#ifdef SHARED_MODULE +# define API_VAR_EXPORT __declspec(dllimport) +# define API_EXPORT(type) __declspec(dllimport) type __stdcall +# define API_EXPORT_NONSTD(type) __declspec(dllimport) type +#else +# define API_VAR_EXPORT __declspec(dllexport) +# define API_EXPORT(type) __declspec(dllexport) type __stdcall +# define API_EXPORT_NONSTD(type) __declspec(dllexport) type +#endif +#define MODULE_VAR_EXPORT __declspec(dllexport) + +#define strcasecmp(s1, s2) stricmp(s1, s2) +#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n) +#define lstat(x, y) stat(x, y) +#define S_ISLNK(m) (0) +#define S_ISREG(m) ((m & _S_IFREG) == _S_IFREG) +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR) +#endif +#ifndef S_ISREG +#define S_ISREG(m) (((m)&(S_IFREG)) == (S_IFREG)) +#endif +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#define JMP_BUF jmp_buf +#define sleep(t) Sleep(t*1000) +#define O_CREAT _O_CREAT +#define O_RDWR _O_RDWR +#define SIGPIPE 17 +/* Seems Windows is not a subgenius */ +#define NO_SLACK +#include <stddef.h> + +#define NO_OTHER_CHILD +#define NO_RELIABLE_PIPED_LOGS + +__inline int ap_os_is_path_absolute(const char *file) +{ + /* For now, just do the same check that http_request.c and mod_alias.c + * do. + */ + return file[0] == '/' || file[1] == ':'; +} + +#define stat(f,ps) os_stat(f,ps) +API_EXPORT(int) os_stat(const char *szPath,struct stat *pStat); + +API_EXPORT(int) os_strftime(char *s, size_t max, const char *format, const struct tm *tm); + +#define _spawnv(mode,cmdname,argv) os_spawnv(mode,cmdname,argv) +#define spawnv(mode,cmdname,argv) os_spawnv(mode,cmdname,argv) +API_EXPORT(int) os_spawnv(int mode,const char *cmdname,const char *const *argv); +#define _spawnve(mode,cmdname,argv,envp) os_spawnve(mode,cmdname,argv,envp) +#define spawnve(mode,cmdname,argv,envp) os_spawnve(mode,cmdname,argv,envp) +API_EXPORT(int) os_spawnve(int mode,const char *cmdname,const char *const *argv,const char *const *envp); +#define _spawnle os_spawnle +#define spawnle os_spawnle +API_EXPORT(int) os_spawnle(int mode,const char *cmdname,...); + +/* OS-dependent filename routines in util_win32.c */ + +API_EXPORT(int) ap_os_is_filename_valid(const char *file); + +/* Abstractions for dealing with shared object files (DLLs on Win32). + * These are used by mod_so.c + */ +#define ap_os_dso_handle_t HINSTANCE +#define ap_os_dso_init() +#define ap_os_dso_load(l) LoadLibraryEx(l, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) +#define ap_os_dso_unload(l) FreeLibrary(l) +#define ap_os_dso_sym(h,s) GetProcAddress(h,s) +#define ap_os_dso_error() "" /* for now */ + +/* Other ap_os_ routines not used by this platform */ +#define ap_os_kill(pid, sig) kill(pid, sig) + +#endif /* ! APACHE_OS_H */ diff --git a/os/win32/util_win32.c b/os/win32/util_win32.c new file mode 100644 index 0000000000..348e0f9e2a --- /dev/null +++ b/os/win32/util_win32.c @@ -0,0 +1,677 @@ +#include <windows.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <time.h> +#include <stdlib.h> + +#include "httpd.h" +#include "http_log.h" + +/* Returns TRUE if the input string is a string + * of one or more '.' characters. + */ +static BOOL OnlyDots(char *pString) +{ + char *c; + + if (*pString == '\0') + return FALSE; + + for (c = pString;*c;c++) + if (*c != '.') + return FALSE; + + return TRUE; +} + +/* Accepts as input a pathname, and tries to match it to an + * existing path and return the pathname in the case that + * is present on the existing path. This routine also + * converts alias names to long names. + */ +API_EXPORT(char *) ap_os_systemcase_filename(pool *pPool, + const char *szFile) +{ + char buf[HUGE_STRING_LEN]; + char *pInputName; + char *p, *q; + BOOL bDone = FALSE; + BOOL bFileExists = TRUE; + HANDLE hFind; + WIN32_FIND_DATA wfd; + + if (!szFile || strlen(szFile) == 0 || strlen(szFile) >= sizeof(buf)) + return ap_pstrdup(pPool, ""); + + buf[0] = '\0'; + pInputName = ap_pstrdup(pPool, szFile); + + /* First convert all slashes to \ so Win32 calls work OK */ + for (p = pInputName; *p; p++) { + if (*p == '/') + *p = '\\'; + } + + p = pInputName; + /* If there is drive information, copy it over. */ + if (pInputName[1] == ':') { + buf[0] = tolower(*p++); + buf[1] = *p++; + buf[2] = '\0'; + + /* If all we have is a drive letter, then we are done */ + if (strlen(pInputName) == 2) + bDone = TRUE; + } + + q = p; + if (*p == '\\') { + p++; + if (*p == '\\') /* Possible UNC name */ + { + p++; + /* Get past the machine name. FindFirstFile */ + /* will not find a machine name only */ + p = strchr(p, '\\'); + if (p) + { + p++; + /* Get past the share name. FindFirstFile */ + /* will not find a \\machine\share name only */ + p = strchr(p, '\\'); + if (p) { + strncat(buf,q,p-q); + q = p; + p++; + } + } + + if (!p) + p = q; + } + } + + p = strchr(p, '\\'); + + while (!bDone) { + if (p) + *p = '\0'; + + if (strchr(q, '*') || strchr(q, '?')) + bFileExists = FALSE; + + /* If the path exists so far, call FindFirstFile + * again. However, if this portion of the path contains + * only '.' charaters, skip the call to FindFirstFile + * since it will convert '.' and '..' to actual names. + * Note: in the call to OnlyDots, we may have to skip + * a leading slash. + */ + if (bFileExists && !OnlyDots((*q == '.' ? q : q+1))) { + hFind = FindFirstFile(pInputName, &wfd); + + if (hFind == INVALID_HANDLE_VALUE) { + bFileExists = FALSE; + } + else { + FindClose(hFind); + + if (*q == '\\') + strcat(buf,"\\"); + strcat(buf, wfd.cFileName); + } + } + + if (!bFileExists || OnlyDots((*q == '.' ? q : q+1))) { + strcat(buf, q); + } + + if (p) { + q = p; + *p++ = '\\'; + p = strchr(p, '\\'); + } + else { + bDone = TRUE; + } + } + + /* First convert all slashes to / so server code handles it ok */ + for (p = buf; *p; p++) { + if (*p == '\\') + *p = '/'; + } + + return ap_pstrdup(pPool, buf); +} + + +/* Perform canonicalization with the exception that the + * input case is preserved. + */ +API_EXPORT(char *) ap_os_case_canonical_filename(pool *pPool, + const char *szFile) +{ + char *pNewStr; + char *s; + char *p; + char *q; + + if (szFile == NULL || strlen(szFile) == 0) + return ap_pstrdup(pPool, ""); + + pNewStr = ap_pstrdup(pPool, szFile); + + /* Change all '\' characters to '/' characters. + * While doing this, remove any trailing '.'. + * Also, blow away any directories with 3 or + * more '.' + */ + for (p = pNewStr,s = pNewStr; *s; s++,p++) { + if (*s == '\\' || *s == '/') { + + q = p; + while (p > pNewStr && *(p-1) == '.') + p--; + + if (p == pNewStr && q-p <= 2 && *p == '.') + p = q; + else if (p > pNewStr && p < q && *(p-1) == '/') { + if (q-p > 2) + p--; + else + p = q; + } + + *p = '/'; + } + else { + *p = *s; + } + } + *p = '\0'; + + /* Blow away any final trailing '.' since on Win32 + * foo.bat == foo.bat. == foo.bat... etc. + * Also blow away any trailing spaces since + * "filename" == "filename " + */ + q = p; + while (p > pNewStr && (*(p-1) == '.' || *(p-1) == ' ')) + p--; + if ((p > pNewStr) || + (p == pNewStr && q-p > 2)) + *p = '\0'; + + + /* One more security issue to deal with. Win32 allows + * you to create long filenames. However, alias filenames + * are always created so that the filename will + * conform to 8.3 rules. According to the Microsoft + * Developer's network CD (1/98) + * "Automatically generated aliases are composed of the + * first six characters of the filename plus ~n + * (where n is a number) and the first three characters + * after the last period." + * Here, we attempt to detect and decode these names. + */ + p = strchr(pNewStr, '~'); + if (p != NULL) { + char *pConvertedName, *pQstr, *pPstr; + char buf[HUGE_STRING_LEN]; + /* We potentially have a short name. Call + * ap_os_systemcase_filename to examine the filesystem + * and possibly extract the long name. + */ + pConvertedName = ap_os_systemcase_filename(pPool, pNewStr); + + /* Since we want to preserve the incoming case as much + * as we can, compare for differences in the string and + * only substitute in the path names that changed. + */ + if (stricmp(pNewStr, pConvertedName)) { + buf[0] = '\0'; + + q = pQstr = pConvertedName; + p = pPstr = pNewStr; + do { + q = strchr(q,'/'); + p = strchr(p,'/'); + + if (p != NULL) { + *q = '\0'; + *p = '\0'; + } + + if (stricmp(pQstr, pPstr)) + strcat(buf, pQstr); /* Converted name */ + else + strcat(buf, pPstr); /* Original name */ + + + if (p != NULL) { + pQstr = q; + pPstr = p; + *q++ = '/'; + *p++ = '/'; + } + + } while (p != NULL); + + pNewStr = ap_pstrdup(pPool, buf); + } + } + + + return pNewStr; +} + +/* Perform complete canonicalization. + */ +API_EXPORT(char *) ap_os_canonical_filename(pool *pPool, const char *szFile) +{ + char *pNewName; + pNewName = ap_os_case_canonical_filename(pPool, szFile); + strlwr(pNewName); + return pNewName; +} + +/* Win95 doesn't like trailing /s. NT and Unix don't mind. This works + * around the problem. + * Errr... except if it is UNC and we are referring to the root of + * the UNC, we MUST have a trailing \ and we can't use /s. Jeez. + * Not sure if this refers to all UNCs or just roots, + * but I'm going to fix it for all cases for now. (Ben) + */ + +#undef stat +API_EXPORT(int) os_stat(const char *szPath, struct stat *pStat) +{ + int n; + + if (strlen(szPath) == 0) { + return -1; + } + + if (szPath[0] == '/' && szPath[1] == '/') { + char buf[_MAX_PATH]; + char *s; + int nSlashes = 0; + + ap_assert(strlen(szPath) < _MAX_PATH); + strcpy(buf, szPath); + for (s = buf; *s; ++s) { + if (*s == '/') { + *s = '\\'; + ++nSlashes; + } + } + /* then we need to add one more to get \\machine\share\ */ + if (nSlashes == 3) { + *s++ = '\\'; + } + *s = '\0'; + return stat(buf, pStat); + } + + /* + * Below removes the trailing /, however, do not remove + * it in the case of 'x:/' or stat will fail + */ + n = strlen(szPath); + if ((szPath[n - 1] == '\\' || szPath[n - 1] == '/') && + !(n == 3 && szPath[1] == ':')) { + char buf[_MAX_PATH]; + + ap_assert(n < _MAX_PATH); + strcpy(buf, szPath); + buf[n - 1] = '\0'; + + return stat(buf, pStat); + } + return stat(szPath, pStat); +} + +/* Fix two really crap problems with Win32 spawn[lv]e*: + * + * 1. Win32 doesn't deal with spaces in argv. + * 2. Win95 doesn't like / in cmdname. + */ + +#undef _spawnv +API_EXPORT(int) os_spawnv(int mode, const char *cmdname, + const char *const *argv) +{ + int n; + char **aszArgs; + const char *szArg; + char *szCmd; + char *s; + + szCmd = _alloca(strlen(cmdname)+1); + strcpy(szCmd, cmdname); + for (s = szCmd; *s; ++s) { + if (*s == '/') { + *s = '\\'; + } + } + + for (n = 0; argv[n]; ++n) + ; + + aszArgs = _alloca((n + 1) * sizeof(const char *)); + + for (n = 0; szArg = argv[n]; ++n) { + if (strchr(szArg, ' ')) { + int l = strlen(szArg); + + aszArgs[n] = _alloca(l + 2 + 1); + aszArgs[n][0] = '"'; + strcpy(&aszArgs[n][1], szArg); + aszArgs[n][l + 1] = '"'; + aszArgs[n][l + 2] = '\0'; + } + else { + aszArgs[n] = (char *)szArg; + } + } + + aszArgs[n] = NULL; + + return _spawnv(mode, szCmd, aszArgs); +} + +#undef _spawnve +API_EXPORT(int) os_spawnve(int mode, const char *cmdname, + const char *const *argv, const char *const *envp) +{ + int n; + char **aszArgs; + const char *szArg; + char *szCmd; + char *s; + + szCmd = _alloca(strlen(cmdname)+1); + strcpy(szCmd, cmdname); + for (s = szCmd; *s; ++s) { + if (*s == '/') { + *s = '\\'; + } + } + + for (n = 0; argv[n]; ++n) + ; + + aszArgs = _alloca((n + 1)*sizeof(const char *)); + + for (n = 0; szArg = argv[n]; ++n){ + if (strchr(szArg, ' ')) { + int l = strlen(szArg); + + aszArgs[n] = _alloca(l + 2 + 1); + aszArgs[n][0] = '"'; + strcpy(&aszArgs[n][1], szArg); + aszArgs[n][l + 1] = '"'; + aszArgs[n][l + 2] = '\0'; + } + else { + aszArgs[n] = (char *)szArg; + } + } + + aszArgs[n] = NULL; + + return _spawnve(mode, szCmd, aszArgs, envp); +} + +API_EXPORT(int) os_spawnle(int mode, const char *cmdname, ...) +{ + int n; + va_list vlist; + char **aszArgs; + const char *szArg; + const char *const *aszEnv; + char *szCmd; + char *s; + + szCmd = _alloca(strlen(cmdname)+1); + strcpy(szCmd, cmdname); + for (s = szCmd; *s; ++s) { + if (*s == '/') { + *s = '\\'; + } + } + + va_start(vlist, cmdname); + for (n = 0; va_arg(vlist, const char *); ++n) + ; + va_end(vlist); + + aszArgs = _alloca((n + 1) * sizeof(const char *)); + + va_start(vlist, cmdname); + for (n = 0; szArg = va_arg(vlist, const char *); ++n) { + if (strchr(szArg, ' ')) { + int l = strlen(szArg); + + aszArgs[n] = _alloca(l + 2 + 1); + aszArgs[n][0] = '"'; + strcpy(&aszArgs[n][1], szArg); + aszArgs[n][l + 1] = '"'; + aszArgs[n][l + 2] = '\0'; + } + else { + aszArgs[n] = (char *)szArg; + } + } + + aszArgs[n] = NULL; + + aszEnv = va_arg(vlist, const char *const *); + va_end(vlist); + + return _spawnve(mode, szCmd, aszArgs, aszEnv); +} + +#undef strftime + +/* Partial replacement for strftime. This adds certain expandos to the + * Windows version + */ + +API_EXPORT(int) os_strftime(char *s, size_t max, const char *format, + const struct tm *tm) { + /* If the new format string is bigger than max, the result string probably + * won't fit anyway. When %-expandos are added, made sure the padding below + * is enough. + */ + char *new_format = (char *) _alloca(max + 11); + size_t i, j, format_length = strlen(format); + int return_value; + int length_written; + + for (i = 0, j = 0; (i < format_length && j < max);) { + if (format[i] != '%') { + new_format[j++] = format[i++]; + continue; + } + switch (format[i+1]) { + case 'D': + /* Is this locale dependent? Shouldn't be... + Also note the year 2000 exposure here */ + memcpy(new_format + j, "%m/%d/%y", 8); + i += 2; + j += 8; + break; + case 'r': + memcpy(new_format + j, "%I:%M:%S %p", 11); + i += 2; + j += 11; + break; + case 'T': + memcpy(new_format + j, "%H:%M:%S", 8); + i += 2; + j += 8; + break; + case 'e': + length_written = ap_snprintf(new_format + j, max - j, "%2d", + tm->tm_mday); + j = (length_written == -1) ? max : (j + length_written); + i += 2; + break; + default: + /* We know we can advance two characters forward here. */ + new_format[j++] = format[i++]; + new_format[j++] = format[i++]; + } + } + if (j >= max) { + *s = '\0'; /* Defensive programming, okay since output is undefined */ + return_value = 0; + } else { + new_format[j] = '\0'; + return_value = strftime(s, max, new_format, tm); + } + return return_value; +} + +/* + * ap_os_is_filename_valid is given a filename, and returns 0 if the filename + * is not valid for use on this system. On Windows, this means it fails any + * of the tests below. Otherwise returns 1. + * + * Test for filename validity on Win32. This is of tests come in part from + * the MSDN article at "Technical Articles, Windows Platform, Base Services, + * Guidelines, Making Room for Long Filenames" although the information + * in MSDN about filename testing is incomplete or conflicting. There is a + * similar set of tests in "Technical Articles, Windows Platform, Base Services, + * Guidelines, Moving Unix Applications to Windows NT". + * + * The tests are: + * + * 1) total path length greater than MAX_PATH + * + * 2) anything using the octets 0-31 or characters " < > | : + * (these are reserved for Windows use in filenames. In addition + * each file system has its own additional characters that are + * invalid. See KB article Q100108 for more details). + * + * 3) anything ending in "." (no matter how many) + * (filename doc, doc. and doc... all refer to the same file) + * + * 4) any segment in which the basename (before first period) matches + * one of the DOS device names + * (the list comes from KB article Q100108 although some people + * reports that additional names such as "COM5" are also special + * devices). + * + * If the path fails ANY of these tests, the result must be to deny access. + */ + +API_EXPORT(int) ap_os_is_filename_valid(const char *file) +{ + const char *segstart; + unsigned int seglength; + const char *pos; + static const char * const invalid_characters = "?\"<>*|:"; + static const char * const invalid_filenames[] = { + "CON", "AUX", "COM1", "COM2", "COM3", + "COM4", "LPT1", "LPT2", "LPT3", "PRN", "NUL", NULL + }; + + /* Test 1 */ + if (strlen(file) > MAX_PATH) { + /* Path too long for Windows. Note that this test is not valid + * if the path starts with //?/ or \\?\. */ + return 0; + } + + pos = file; + + /* Skip any leading non-path components. This can be either a + * drive letter such as C:, or a UNC path such as \\SERVER\SHARE\. + * We continue and check the rest of the path based on the rules above. + * This means we could eliminate valid filenames from servers which + * are not running NT (such as Samba). + */ + + if (pos[0] && pos[1] == ':') { + /* Skip leading drive letter */ + pos += 2; + } + else { + if ((pos[0] == '\\' || pos[0] == '/') && + (pos[1] == '\\' || pos[1] == '/')) { + /* Is a UNC, so skip the server name and share name */ + pos += 2; + while (*pos && *pos != '/' && *pos != '\\') + pos++; + if (!*pos) { + /* No share name */ + return 0; + } + pos++; /* Move to start of share name */ + while (*pos && *pos != '/' && *pos != '\\') + pos++; + if (!*pos) { + /* No path information */ + return 0; + } + } + } + + while (*pos) { + unsigned int idx; + unsigned int baselength; + + while (*pos == '/' || *pos == '\\') { + pos++; + } + if (*pos == '\0') { + break; + } + segstart = pos; /* start of segment */ + while (*pos && *pos != '/' && *pos != '\\') { + pos++; + } + seglength = pos - segstart; + /* + * Now we have a segment of the path, starting at position "segstart" + * and length "seglength" + */ + + /* Test 2 */ + for (idx = 0; idx < seglength; idx++) { + if ((segstart[idx] > 0 && segstart[idx] < 32) || + strchr(invalid_characters, segstart[idx])) { + return 0; + } + } + + /* Test 3 */ + if (segstart[seglength-1] == '.') { + return 0; + } + + /* Test 4 */ + for (baselength = 0; baselength < seglength; baselength++) { + if (segstart[baselength] == '.') { + break; + } + } + + /* baselength is the number of characters in the base path of + * the segment (which could be the same as the whole segment length, + * if it does not include any dot characters). */ + if (baselength == 3 || baselength == 4) { + for (idx = 0; invalid_filenames[idx]; idx++) { + if (strlen(invalid_filenames[idx]) == baselength && + !strnicmp(invalid_filenames[idx], segstart, baselength)) { + return 0; + } + } + } + } + + return 1; +} |