From 815b8d89cd172079185b9c7e86dd455300b8f07a Mon Sep 17 00:00:00 2001 From: No Author Date: Fri, 22 May 1998 00:24:06 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'APACHE_1_3b7'. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/tags/1.3@81346 13f79535-47bb-0310-9956-ffa450edef68 --- APACHE_1_3b7/.cvsignore | 3 + APACHE_1_3b7/ABOUT_APACHE | 234 + APACHE_1_3b7/Announcement | 69 + APACHE_1_3b7/CHANGES | 173 + APACHE_1_3b7/INSTALL | 396 ++ APACHE_1_3b7/KEYS | 325 + APACHE_1_3b7/LICENSE | 59 + APACHE_1_3b7/Makefile.tmpl | 471 ++ APACHE_1_3b7/README | 63 + APACHE_1_3b7/README.NT | 231 + APACHE_1_3b7/README.configure | 268 + APACHE_1_3b7/RULES.CVS | 13 + APACHE_1_3b7/STATUS | 387 ++ APACHE_1_3b7/cgi-bin/printenv | 7 + APACHE_1_3b7/cgi-bin/test-cgi | 31 + APACHE_1_3b7/conf/.cvsignore | 4 + APACHE_1_3b7/conf/access.conf-dist | 70 + APACHE_1_3b7/conf/access.conf-dist-win | 75 + APACHE_1_3b7/conf/highperformance.conf-dist | 51 + APACHE_1_3b7/conf/httpd.conf-dist | 246 + APACHE_1_3b7/conf/httpd.conf-dist-win | 216 + APACHE_1_3b7/conf/magic | 365 ++ APACHE_1_3b7/conf/mime.types | 104 + APACHE_1_3b7/conf/srm.conf-dist | 233 + APACHE_1_3b7/conf/srm.conf-dist-win | 241 + APACHE_1_3b7/configure | 979 +++ APACHE_1_3b7/htdocs/.cvsignore | 1 + APACHE_1_3b7/htdocs/apache_pb.gif | Bin 0 -> 2326 bytes APACHE_1_3b7/htdocs/index.html | 51 + APACHE_1_3b7/htdocs/manual/LICENSE | 59 + APACHE_1_3b7/htdocs/manual/bind.html | 135 + APACHE_1_3b7/htdocs/manual/cgi_path.html | 93 + .../htdocs/manual/content-negotiation.html | 527 ++ APACHE_1_3b7/htdocs/manual/custom-error.html | 177 + APACHE_1_3b7/htdocs/manual/dns-caveats.html | 189 + APACHE_1_3b7/htdocs/manual/dso.html | 384 ++ APACHE_1_3b7/htdocs/manual/ebcdic.html | 497 ++ APACHE_1_3b7/htdocs/manual/env.html | 46 + APACHE_1_3b7/htdocs/manual/expand.pl | 104 + APACHE_1_3b7/htdocs/manual/footer.html | 6 + APACHE_1_3b7/htdocs/manual/handler.html | 167 + APACHE_1_3b7/htdocs/manual/header.html | 6 + .../htdocs/manual/images/custom_errordocs.gif | Bin 0 -> 23291 bytes APACHE_1_3b7/htdocs/manual/images/home.gif | Bin 0 -> 1465 bytes APACHE_1_3b7/htdocs/manual/images/index.gif | Bin 0 -> 1540 bytes .../htdocs/manual/images/mod_rewrite_fig1.fig | 60 + .../htdocs/manual/images/mod_rewrite_fig1.gif | Bin 0 -> 3525 bytes .../htdocs/manual/images/mod_rewrite_fig2.fig | 50 + .../htdocs/manual/images/mod_rewrite_fig2.gif | Bin 0 -> 2553 bytes APACHE_1_3b7/htdocs/manual/images/sub.gif | Bin 0 -> 6083 bytes APACHE_1_3b7/htdocs/manual/index.html | 61 + APACHE_1_3b7/htdocs/manual/install.html | 262 + APACHE_1_3b7/htdocs/manual/invoking.html | 137 + APACHE_1_3b7/htdocs/manual/keepalive.html | 103 + APACHE_1_3b7/htdocs/manual/location.html | 68 + APACHE_1_3b7/htdocs/manual/man-template.html | 108 + APACHE_1_3b7/htdocs/manual/misc/API.html | 1151 ++++ APACHE_1_3b7/htdocs/manual/misc/FAQ.html | 2306 +++++++ .../htdocs/manual/misc/HTTP_Features.tsv | 142 + .../htdocs/manual/misc/client_block_api.html | 87 + .../htdocs/manual/misc/compat_notes.html | 117 + .../htdocs/manual/misc/custom_errordocs.html | 394 ++ .../htdocs/manual/misc/descriptors.html | 155 + .../htdocs/manual/misc/fin_wait_2.html | 324 + APACHE_1_3b7/htdocs/manual/misc/footer.html | 8 + APACHE_1_3b7/htdocs/manual/misc/header.html | 6 + APACHE_1_3b7/htdocs/manual/misc/howto.html | 164 + APACHE_1_3b7/htdocs/manual/misc/index.html | 138 + .../manual/misc/known_client_problems.html | 250 + APACHE_1_3b7/htdocs/manual/misc/nopgp.html | 90 + .../htdocs/manual/misc/perf-bsd44.html | 238 + APACHE_1_3b7/htdocs/manual/misc/perf-dec.html | 283 + APACHE_1_3b7/htdocs/manual/misc/perf-hp.html | 118 + .../htdocs/manual/misc/perf-tuning.html | 871 +++ APACHE_1_3b7/htdocs/manual/misc/perf.html | 176 + .../htdocs/manual/misc/security_tips.html | 229 + APACHE_1_3b7/htdocs/manual/misc/vif-info.html | 399 ++ .../htdocs/manual/misc/windoz_keepalive.html | 50 + APACHE_1_3b7/htdocs/manual/mod/core.html | 2910 +++++++++ .../htdocs/manual/mod/directive-dict.html | 262 + .../htdocs/manual/mod/directives.html | 210 + APACHE_1_3b7/htdocs/manual/mod/footer.html | 8 + APACHE_1_3b7/htdocs/manual/mod/header.html | 6 + APACHE_1_3b7/htdocs/manual/mod/index.html | 120 + .../htdocs/manual/mod/mod_access.html | 310 + .../htdocs/manual/mod/mod_actions.html | 125 + APACHE_1_3b7/htdocs/manual/mod/mod_alias.html | 387 ++ APACHE_1_3b7/htdocs/manual/mod/mod_asis.html | 68 + APACHE_1_3b7/htdocs/manual/mod/mod_auth.html | 201 + .../htdocs/manual/mod/mod_auth_anon.html | 363 ++ .../htdocs/manual/mod/mod_auth_db.html | 220 + .../htdocs/manual/mod/mod_auth_dbm.html | 210 + .../htdocs/manual/mod/mod_autoindex.html | 606 ++ .../htdocs/manual/mod/mod_browser.html | 120 + .../htdocs/manual/mod/mod_cern_meta.html | 143 + APACHE_1_3b7/htdocs/manual/mod/mod_cgi.html | 211 + .../htdocs/manual/mod/mod_cookies.html | 59 + .../htdocs/manual/mod/mod_digest.html | 80 + APACHE_1_3b7/htdocs/manual/mod/mod_dir.html | 103 + APACHE_1_3b7/htdocs/manual/mod/mod_dld.html | 108 + APACHE_1_3b7/htdocs/manual/mod/mod_dll.html | 151 + APACHE_1_3b7/htdocs/manual/mod/mod_env.html | 137 + .../htdocs/manual/mod/mod_example.html | 167 + .../htdocs/manual/mod/mod_expires.html | 322 + .../htdocs/manual/mod/mod_headers.html | 121 + APACHE_1_3b7/htdocs/manual/mod/mod_imap.html | 329 + .../htdocs/manual/mod/mod_include.html | 420 ++ APACHE_1_3b7/htdocs/manual/mod/mod_info.html | 113 + APACHE_1_3b7/htdocs/manual/mod/mod_isapi.html | 73 + .../htdocs/manual/mod/mod_log_agent.html | 76 + .../htdocs/manual/mod/mod_log_common.html | 116 + .../htdocs/manual/mod/mod_log_config.html | 376 ++ .../htdocs/manual/mod/mod_log_referer.html | 115 + APACHE_1_3b7/htdocs/manual/mod/mod_mime.html | 365 ++ .../htdocs/manual/mod/mod_mime_magic.html | 275 + .../htdocs/manual/mod/mod_mmap_static.html | 142 + .../htdocs/manual/mod/mod_negotiation.html | 177 + APACHE_1_3b7/htdocs/manual/mod/mod_proxy.html | 1008 +++ .../htdocs/manual/mod/mod_rewrite.html | 1818 ++++++ .../htdocs/manual/mod/mod_setenvif.html | 371 ++ APACHE_1_3b7/htdocs/manual/mod/mod_so.html | 164 + .../htdocs/manual/mod/mod_speling.html | 107 + .../htdocs/manual/mod/mod_status.html | 109 + .../htdocs/manual/mod/mod_unique_id.html | 180 + .../htdocs/manual/mod/mod_userdir.html | 123 + .../htdocs/manual/mod/mod_usertrack.html | 116 + APACHE_1_3b7/htdocs/manual/multilogs.html | 134 + .../htdocs/manual/new_features_1_0.html | 131 + .../htdocs/manual/new_features_1_1.html | 228 + .../htdocs/manual/new_features_1_2.html | 210 + .../htdocs/manual/new_features_1_3.html | 583 ++ APACHE_1_3b7/htdocs/manual/process-model.html | 68 + APACHE_1_3b7/htdocs/manual/sections.html | 141 + APACHE_1_3b7/htdocs/manual/sourcereorg.html | 298 + APACHE_1_3b7/htdocs/manual/stopping.html | 174 + APACHE_1_3b7/htdocs/manual/suexec.html | 540 ++ APACHE_1_3b7/htdocs/manual/unixware.html | 62 + .../htdocs/manual/upgrading_to_1_3.html | 245 + .../htdocs/manual/vhosts/details.html | 372 ++ .../htdocs/manual/vhosts/details_1_2.html | 396 ++ .../htdocs/manual/vhosts/examples.html | 512 ++ .../htdocs/manual/vhosts/fd-limits.html | 59 + APACHE_1_3b7/htdocs/manual/vhosts/footer.html | 8 + APACHE_1_3b7/htdocs/manual/vhosts/header.html | 6 + APACHE_1_3b7/htdocs/manual/vhosts/host.html | 172 + APACHE_1_3b7/htdocs/manual/vhosts/index.html | 64 + .../htdocs/manual/vhosts/ip-based.html | 140 + .../htdocs/manual/vhosts/name-based.html | 146 + .../htdocs/manual/vhosts/vhosts-in-depth.html | 396 ++ .../htdocs/manual/vhosts/virtual-host.html | 207 + APACHE_1_3b7/htdocs/manual/windows.html | 372 ++ APACHE_1_3b7/icons/README | 161 + APACHE_1_3b7/icons/a.gif | Bin 0 -> 246 bytes APACHE_1_3b7/icons/alert.black.gif | Bin 0 -> 242 bytes APACHE_1_3b7/icons/alert.red.gif | Bin 0 -> 247 bytes APACHE_1_3b7/icons/apache_pb.gif | Bin 0 -> 2326 bytes APACHE_1_3b7/icons/back.gif | Bin 0 -> 216 bytes APACHE_1_3b7/icons/ball.gray.gif | Bin 0 -> 233 bytes APACHE_1_3b7/icons/ball.red.gif | Bin 0 -> 205 bytes APACHE_1_3b7/icons/binary.gif | Bin 0 -> 246 bytes APACHE_1_3b7/icons/binhex.gif | Bin 0 -> 246 bytes APACHE_1_3b7/icons/blank.gif | Bin 0 -> 148 bytes APACHE_1_3b7/icons/bomb.gif | Bin 0 -> 308 bytes APACHE_1_3b7/icons/box1.gif | Bin 0 -> 251 bytes APACHE_1_3b7/icons/box2.gif | Bin 0 -> 268 bytes APACHE_1_3b7/icons/broken.gif | Bin 0 -> 247 bytes APACHE_1_3b7/icons/burst.gif | Bin 0 -> 235 bytes APACHE_1_3b7/icons/c.gif | Bin 0 -> 242 bytes APACHE_1_3b7/icons/comp.blue.gif | Bin 0 -> 251 bytes APACHE_1_3b7/icons/comp.gray.gif | Bin 0 -> 246 bytes APACHE_1_3b7/icons/compressed.gif | Bin 0 -> 1038 bytes APACHE_1_3b7/icons/continued.gif | Bin 0 -> 214 bytes APACHE_1_3b7/icons/dir.gif | Bin 0 -> 225 bytes APACHE_1_3b7/icons/down.gif | Bin 0 -> 163 bytes APACHE_1_3b7/icons/dvi.gif | Bin 0 -> 238 bytes APACHE_1_3b7/icons/f.gif | Bin 0 -> 236 bytes APACHE_1_3b7/icons/folder.gif | Bin 0 -> 225 bytes APACHE_1_3b7/icons/folder.open.gif | Bin 0 -> 242 bytes APACHE_1_3b7/icons/folder.sec.gif | Bin 0 -> 243 bytes APACHE_1_3b7/icons/forward.gif | Bin 0 -> 219 bytes APACHE_1_3b7/icons/generic.gif | Bin 0 -> 221 bytes APACHE_1_3b7/icons/generic.red.gif | Bin 0 -> 220 bytes APACHE_1_3b7/icons/generic.sec.gif | Bin 0 -> 249 bytes APACHE_1_3b7/icons/hand.right.gif | Bin 0 -> 217 bytes APACHE_1_3b7/icons/hand.up.gif | Bin 0 -> 223 bytes APACHE_1_3b7/icons/icon.sheet.gif | Bin 0 -> 11977 bytes APACHE_1_3b7/icons/image1.gif | Bin 0 -> 274 bytes APACHE_1_3b7/icons/image2.gif | Bin 0 -> 309 bytes APACHE_1_3b7/icons/image3.gif | Bin 0 -> 286 bytes APACHE_1_3b7/icons/index.gif | Bin 0 -> 268 bytes APACHE_1_3b7/icons/layout.gif | Bin 0 -> 276 bytes APACHE_1_3b7/icons/left.gif | Bin 0 -> 172 bytes APACHE_1_3b7/icons/link.gif | Bin 0 -> 249 bytes APACHE_1_3b7/icons/movie.gif | Bin 0 -> 243 bytes APACHE_1_3b7/icons/p.gif | Bin 0 -> 237 bytes APACHE_1_3b7/icons/patch.gif | Bin 0 -> 251 bytes APACHE_1_3b7/icons/pdf.gif | Bin 0 -> 249 bytes APACHE_1_3b7/icons/pie0.gif | Bin 0 -> 188 bytes APACHE_1_3b7/icons/pie1.gif | Bin 0 -> 198 bytes APACHE_1_3b7/icons/pie2.gif | Bin 0 -> 198 bytes APACHE_1_3b7/icons/pie3.gif | Bin 0 -> 191 bytes APACHE_1_3b7/icons/pie4.gif | Bin 0 -> 193 bytes APACHE_1_3b7/icons/pie5.gif | Bin 0 -> 189 bytes APACHE_1_3b7/icons/pie6.gif | Bin 0 -> 186 bytes APACHE_1_3b7/icons/pie7.gif | Bin 0 -> 185 bytes APACHE_1_3b7/icons/pie8.gif | Bin 0 -> 173 bytes APACHE_1_3b7/icons/portal.gif | Bin 0 -> 254 bytes APACHE_1_3b7/icons/ps.gif | Bin 0 -> 244 bytes APACHE_1_3b7/icons/quill.gif | Bin 0 -> 267 bytes APACHE_1_3b7/icons/right.gif | Bin 0 -> 172 bytes APACHE_1_3b7/icons/screw1.gif | Bin 0 -> 258 bytes APACHE_1_3b7/icons/screw2.gif | Bin 0 -> 263 bytes APACHE_1_3b7/icons/script.gif | Bin 0 -> 242 bytes APACHE_1_3b7/icons/sound1.gif | Bin 0 -> 248 bytes APACHE_1_3b7/icons/sound2.gif | Bin 0 -> 221 bytes APACHE_1_3b7/icons/sphere1.gif | Bin 0 -> 285 bytes APACHE_1_3b7/icons/sphere2.gif | Bin 0 -> 264 bytes APACHE_1_3b7/icons/tar.gif | Bin 0 -> 219 bytes APACHE_1_3b7/icons/tex.gif | Bin 0 -> 251 bytes APACHE_1_3b7/icons/text.gif | Bin 0 -> 229 bytes APACHE_1_3b7/icons/transfer.gif | Bin 0 -> 242 bytes APACHE_1_3b7/icons/unknown.gif | Bin 0 -> 245 bytes APACHE_1_3b7/icons/up.gif | Bin 0 -> 164 bytes APACHE_1_3b7/icons/uu.gif | Bin 0 -> 236 bytes APACHE_1_3b7/icons/uuencoded.gif | Bin 0 -> 236 bytes APACHE_1_3b7/icons/world1.gif | Bin 0 -> 228 bytes APACHE_1_3b7/icons/world2.gif | Bin 0 -> 261 bytes APACHE_1_3b7/logs/.cvsignore | 1 + APACHE_1_3b7/src/.cvsignore | 21 + APACHE_1_3b7/src/.gdbinit | 15 + APACHE_1_3b7/src/Apache.dsp | 101 + APACHE_1_3b7/src/Apache.mak | 170 + APACHE_1_3b7/src/ApacheCore.def | 1 + APACHE_1_3b7/src/ApacheCore.dsp | 413 ++ APACHE_1_3b7/src/ApacheCore.mak | 2728 ++++++++ APACHE_1_3b7/src/CHANGES | 4598 ++++++++++++++ APACHE_1_3b7/src/Configuration.tmpl | 376 ++ APACHE_1_3b7/src/Configure | 1769 ++++++ APACHE_1_3b7/src/INDENT | 140 + APACHE_1_3b7/src/INSTALL | 169 + APACHE_1_3b7/src/Makefile.nt | 140 + APACHE_1_3b7/src/Makefile.tmpl | 114 + APACHE_1_3b7/src/PORTING | 377 ++ APACHE_1_3b7/src/README | 147 + APACHE_1_3b7/src/README.EBCDIC | 148 + APACHE_1_3b7/src/ap/.cvsignore | 2 + APACHE_1_3b7/src/ap/.indent.pro | 54 + APACHE_1_3b7/src/ap/Makefile.tmpl | 59 + APACHE_1_3b7/src/ap/ap.dsp | 106 + APACHE_1_3b7/src/ap/ap.mak | 241 + APACHE_1_3b7/src/ap/ap_cpystrn.c | 93 + APACHE_1_3b7/src/ap/ap_execve.c | 340 + APACHE_1_3b7/src/ap/ap_fnmatch.c | 213 + APACHE_1_3b7/src/ap/ap_md5c.c | 392 ++ APACHE_1_3b7/src/ap/ap_signal.c | 83 + APACHE_1_3b7/src/ap/ap_slack.c | 116 + APACHE_1_3b7/src/ap/ap_snprintf.c | 1021 +++ APACHE_1_3b7/src/ap/ap_strings.c | 108 + APACHE_1_3b7/src/buildmark.c | 70 + APACHE_1_3b7/src/helpers/CutRule | 8 + APACHE_1_3b7/src/helpers/GuessOS | 263 + APACHE_1_3b7/src/helpers/MakeLint | 31 + APACHE_1_3b7/src/helpers/PrintPath | 51 + APACHE_1_3b7/src/helpers/PrintPathOS2 | 33 + APACHE_1_3b7/src/helpers/TestCompile | 138 + APACHE_1_3b7/src/helpers/dummy.c | 12 + APACHE_1_3b7/src/helpers/find-dbm-lib | 43 + APACHE_1_3b7/src/helpers/fmn.sh | 46 + APACHE_1_3b7/src/helpers/fp2rp | 13 + APACHE_1_3b7/src/helpers/install.sh | 96 + APACHE_1_3b7/src/helpers/mfhead | 8 + APACHE_1_3b7/src/helpers/mkdir.sh | 31 + APACHE_1_3b7/src/helpers/mkshadow.sh | 83 + APACHE_1_3b7/src/helpers/ppl.sh | 51 + APACHE_1_3b7/src/include/.cvsignore | 1 + APACHE_1_3b7/src/include/.indent.pro | 54 + APACHE_1_3b7/src/include/alloc.h | 332 + APACHE_1_3b7/src/include/ap.h | 169 + APACHE_1_3b7/src/include/ap_compat.h | 410 ++ APACHE_1_3b7/src/include/ap_config.h | 1170 ++++ APACHE_1_3b7/src/include/buff.h | 236 + APACHE_1_3b7/src/include/compat.h | 410 ++ APACHE_1_3b7/src/include/conf.h | 1170 ++++ APACHE_1_3b7/src/include/explain.h | 44 + APACHE_1_3b7/src/include/fnmatch.h | 62 + APACHE_1_3b7/src/include/hsregex.h | 81 + APACHE_1_3b7/src/include/http_conf_globals.h | 118 + APACHE_1_3b7/src/include/http_config.h | 392 ++ APACHE_1_3b7/src/include/http_core.h | 261 + APACHE_1_3b7/src/include/http_log.h | 147 + APACHE_1_3b7/src/include/http_main.h | 174 + APACHE_1_3b7/src/include/http_protocol.h | 216 + APACHE_1_3b7/src/include/http_request.h | 114 + APACHE_1_3b7/src/include/http_vhost.h | 95 + APACHE_1_3b7/src/include/httpd.h | 1042 +++ APACHE_1_3b7/src/include/md5.h | 116 + APACHE_1_3b7/src/include/multithread.h | 65 + APACHE_1_3b7/src/include/rfc1413.h | 71 + APACHE_1_3b7/src/include/scoreboard.h | 173 + APACHE_1_3b7/src/include/util_date.h | 85 + APACHE_1_3b7/src/include/util_md5.h | 75 + APACHE_1_3b7/src/include/util_script.h | 89 + APACHE_1_3b7/src/include/util_uri.h | 127 + APACHE_1_3b7/src/main/.cvsignore | 13 + APACHE_1_3b7/src/main/.indent.pro | 54 + APACHE_1_3b7/src/main/Makefile.tmpl | 141 + APACHE_1_3b7/src/main/alloc.c | 2314 +++++++ APACHE_1_3b7/src/main/buff.c | 1563 +++++ APACHE_1_3b7/src/main/fnmatch.c | 213 + APACHE_1_3b7/src/main/gen_test_char.c | 62 + APACHE_1_3b7/src/main/gen_test_char.dsp | 105 + APACHE_1_3b7/src/main/gen_test_char.mak | 236 + APACHE_1_3b7/src/main/gen_uri_delims.c | 31 + APACHE_1_3b7/src/main/gen_uri_delims.dsp | 105 + APACHE_1_3b7/src/main/gen_uri_delims.mak | 204 + APACHE_1_3b7/src/main/http_config.c | 1604 +++++ APACHE_1_3b7/src/main/http_core.c | 2269 +++++++ APACHE_1_3b7/src/main/http_log.c | 673 ++ APACHE_1_3b7/src/main/http_main.c | 5618 +++++++++++++++++ APACHE_1_3b7/src/main/http_protocol.c | 2183 +++++++ APACHE_1_3b7/src/main/http_request.c | 1326 ++++ APACHE_1_3b7/src/main/http_vhost.c | 917 +++ APACHE_1_3b7/src/main/md5c.c | 392 ++ APACHE_1_3b7/src/main/rfc1413.c | 239 + APACHE_1_3b7/src/main/util.c | 1742 +++++ APACHE_1_3b7/src/main/util_date.c | 321 + APACHE_1_3b7/src/main/util_md5.c | 196 + APACHE_1_3b7/src/main/util_script.c | 994 +++ APACHE_1_3b7/src/main/util_uri.c | 583 ++ APACHE_1_3b7/src/modules/.cvsignore | 1 + APACHE_1_3b7/src/modules/README | 36 + APACHE_1_3b7/src/modules/example/.cvsignore | 3 + APACHE_1_3b7/src/modules/example/.indent.pro | 54 + .../src/modules/example/Makefile.tmpl | 12 + APACHE_1_3b7/src/modules/example/README | 53 + .../src/modules/example/mod_example.c | 1141 ++++ .../src/modules/experimental/.cvsignore | 3 + .../src/modules/experimental/.indent.pro | 54 + .../src/modules/experimental/Makefile.tmpl | 12 + .../modules/experimental/mod_mmap_static.c | 390 ++ APACHE_1_3b7/src/modules/extra/.cvsignore | 3 + APACHE_1_3b7/src/modules/extra/.indent.pro | 54 + APACHE_1_3b7/src/modules/extra/Makefile.tmpl | 6 + APACHE_1_3b7/src/modules/proxy/.cvsignore | 10 + APACHE_1_3b7/src/modules/proxy/.indent.pro | 55 + .../src/modules/proxy/ApacheModuleProxy.dsp | 133 + .../src/modules/proxy/ApacheModuleProxy.mak | 557 ++ .../src/modules/proxy/Makefile.libdir | 4 + APACHE_1_3b7/src/modules/proxy/Makefile.tmpl | 91 + APACHE_1_3b7/src/modules/proxy/mod_proxy.c | 811 +++ APACHE_1_3b7/src/modules/proxy/mod_proxy.h | 298 + APACHE_1_3b7/src/modules/proxy/proxy_cache.c | 980 +++ .../src/modules/proxy/proxy_connect.c | 264 + APACHE_1_3b7/src/modules/proxy/proxy_ftp.c | 1135 ++++ APACHE_1_3b7/src/modules/proxy/proxy_http.c | 469 ++ APACHE_1_3b7/src/modules/proxy/proxy_util.c | 1228 ++++ APACHE_1_3b7/src/modules/standard/.cvsignore | 3 + APACHE_1_3b7/src/modules/standard/.indent.pro | 54 + .../src/modules/standard/Makefile.tmpl | 183 + .../src/modules/standard/mod_access.c | 410 ++ .../src/modules/standard/mod_actions.c | 235 + APACHE_1_3b7/src/modules/standard/mod_alias.c | 418 ++ APACHE_1_3b7/src/modules/standard/mod_asis.c | 145 + APACHE_1_3b7/src/modules/standard/mod_auth.c | 319 + .../src/modules/standard/mod_auth_anon.c | 315 + .../src/modules/standard/mod_auth_db.c | 324 + .../src/modules/standard/mod_auth_db.module | 20 + .../src/modules/standard/mod_auth_dbm.c | 326 + .../src/modules/standard/mod_autoindex.c | 1201 ++++ .../src/modules/standard/mod_cern_meta.c | 387 ++ APACHE_1_3b7/src/modules/standard/mod_cgi.c | 593 ++ .../src/modules/standard/mod_digest.c | 387 ++ APACHE_1_3b7/src/modules/standard/mod_dir.c | 246 + APACHE_1_3b7/src/modules/standard/mod_env.c | 274 + .../src/modules/standard/mod_expires.c | 507 ++ .../src/modules/standard/mod_headers.c | 265 + APACHE_1_3b7/src/modules/standard/mod_imap.c | 916 +++ .../src/modules/standard/mod_include.c | 2414 +++++++ APACHE_1_3b7/src/modules/standard/mod_info.c | 694 ++ .../src/modules/standard/mod_log_agent.c | 188 + .../src/modules/standard/mod_log_config.c | 1031 +++ .../src/modules/standard/mod_log_referer.c | 228 + APACHE_1_3b7/src/modules/standard/mod_mime.c | 351 + .../src/modules/standard/mod_mime_magic.c | 2474 ++++++++ .../src/modules/standard/mod_negotiation.c | 2302 +++++++ .../src/modules/standard/mod_rewrite.c | 3923 ++++++++++++ .../src/modules/standard/mod_rewrite.h | 473 ++ .../src/modules/standard/mod_setenvif.c | 402 ++ APACHE_1_3b7/src/modules/standard/mod_so.c | 350 + .../src/modules/standard/mod_speling.c | 451 ++ .../src/modules/standard/mod_status.c | 709 +++ .../src/modules/standard/mod_unique_id.c | 357 ++ .../src/modules/standard/mod_userdir.c | 349 + .../src/modules/standard/mod_usertrack.c | 350 + APACHE_1_3b7/src/modules/test/.cvsignore | 3 + APACHE_1_3b7/src/modules/test/.indent.pro | 54 + APACHE_1_3b7/src/modules/test/Makefile.tmpl | 18 + APACHE_1_3b7/src/modules/test/README | 3 + APACHE_1_3b7/src/modules/test/mod_rndchunk.c | 179 + .../src/modules/test/mod_test_util_uri.c | 353 ++ APACHE_1_3b7/src/os/.indent.pro | 54 + APACHE_1_3b7/src/os/bs2000/.cvsignore | 1 + APACHE_1_3b7/src/os/bs2000/Makefile.tmpl | 42 + APACHE_1_3b7/src/os/bs2000/bs2login.c | 190 + APACHE_1_3b7/src/os/bs2000/ebcdic.c | 253 + APACHE_1_3b7/src/os/bs2000/ebcdic.h | 8 + APACHE_1_3b7/src/os/bs2000/os-inline.c | 31 + APACHE_1_3b7/src/os/bs2000/os.c | 98 + APACHE_1_3b7/src/os/bs2000/os.h | 34 + APACHE_1_3b7/src/os/emx/.cvsignore | 1 + APACHE_1_3b7/src/os/emx/Makefile.tmpl | 49 + APACHE_1_3b7/src/os/emx/os-inline.c | 34 + APACHE_1_3b7/src/os/emx/os.c | 6 + APACHE_1_3b7/src/os/emx/os.h | 30 + APACHE_1_3b7/src/os/os2/.cvsignore | 1 + APACHE_1_3b7/src/os/os2/Makefile.tmpl | 49 + APACHE_1_3b7/src/os/os2/os-inline.c | 34 + APACHE_1_3b7/src/os/os2/os.c | 6 + APACHE_1_3b7/src/os/os2/os.h | 30 + APACHE_1_3b7/src/os/unix/.cvsignore | 1 + APACHE_1_3b7/src/os/unix/Makefile.tmpl | 43 + APACHE_1_3b7/src/os/unix/os-aix-dso.c | 668 ++ APACHE_1_3b7/src/os/unix/os-inline.c | 31 + APACHE_1_3b7/src/os/unix/os.c | 85 + APACHE_1_3b7/src/os/unix/os.h | 132 + APACHE_1_3b7/src/os/win32/.cvsignore | 27 + .../src/os/win32/ApacheModuleAuthAnon.dsp | 113 + .../src/os/win32/ApacheModuleAuthAnon.mak | 239 + .../src/os/win32/ApacheModuleCERNMeta.dsp | 113 + .../src/os/win32/ApacheModuleCERNMeta.mak | 237 + .../src/os/win32/ApacheModuleDigest.dsp | 113 + .../src/os/win32/ApacheModuleDigest.mak | 240 + .../src/os/win32/ApacheModuleExpires.dsp | 113 + .../src/os/win32/ApacheModuleExpires.mak | 232 + .../src/os/win32/ApacheModuleHeaders.dsp | 113 + .../src/os/win32/ApacheModuleHeaders.mak | 230 + .../src/os/win32/ApacheModuleInfo.dsp | 112 + .../src/os/win32/ApacheModuleInfo.mak | 210 + .../src/os/win32/ApacheModuleRewrite.dsp | 117 + .../src/os/win32/ApacheModuleRewrite.mak | 248 + .../src/os/win32/ApacheModuleSpeling.dsp | 113 + .../src/os/win32/ApacheModuleSpeling.mak | 234 + .../src/os/win32/ApacheModuleStatus.dsp | 113 + .../src/os/win32/ApacheModuleStatus.mak | 242 + .../src/os/win32/ApacheModuleUserTrack.dsp | 113 + .../src/os/win32/ApacheModuleUserTrack.mak | 233 + APACHE_1_3b7/src/os/win32/ApacheOS.dsp | 86 + APACHE_1_3b7/src/os/win32/ApacheOS.mak | 164 + APACHE_1_3b7/src/os/win32/MakeModuleMak.cpp | 59 + APACHE_1_3b7/src/os/win32/MakeModuleMak.mak | 195 + APACHE_1_3b7/src/os/win32/Module.mak.tmpl | 229 + APACHE_1_3b7/src/os/win32/getopt.c | 170 + APACHE_1_3b7/src/os/win32/getopt.h | 10 + .../src/os/win32/installer/README.TXT | 6 + .../src/os/win32/installer/apache.iwz | 842 +++ .../os/win32/installer/installdll/install.c | 543 ++ .../os/win32/installer/installdll/install.def | 6 + .../os/win32/installer/installdll/install.dsp | 103 + .../os/win32/installer/installdll/install.mak | 184 + .../installer/installdll/test/resource.h | 23 + .../os/win32/installer/installdll/test/test.c | 154 + .../win32/installer/installdll/test/test.def | 2 + .../win32/installer/installdll/test/test.dsp | 121 + .../os/win32/installer/installdll/test/test.h | 4 + .../win32/installer/installdll/test/test.ico | Bin 0 -> 766 bytes .../win32/installer/installdll/test/test.mak | 240 + .../win32/installer/installdll/test/test.rc | 137 + APACHE_1_3b7/src/os/win32/main_win32.c | 16 + APACHE_1_3b7/src/os/win32/mod_dll.c | 190 + APACHE_1_3b7/src/os/win32/mod_isapi.c | 566 ++ APACHE_1_3b7/src/os/win32/modules.c | 71 + APACHE_1_3b7/src/os/win32/multithread.c | 258 + APACHE_1_3b7/src/os/win32/os.c | 7 + APACHE_1_3b7/src/os/win32/os.h | 115 + APACHE_1_3b7/src/os/win32/passwd.c | 16 + APACHE_1_3b7/src/os/win32/passwd.h | 8 + APACHE_1_3b7/src/os/win32/readdir.c | 80 + APACHE_1_3b7/src/os/win32/readdir.h | 36 + APACHE_1_3b7/src/os/win32/registry.c | 395 ++ APACHE_1_3b7/src/os/win32/registry.h | 6 + APACHE_1_3b7/src/os/win32/service.c | 316 + APACHE_1_3b7/src/os/win32/service.h | 13 + APACHE_1_3b7/src/os/win32/util_win32.c | 281 + APACHE_1_3b7/src/regex/.cvsignore | 6 + APACHE_1_3b7/src/regex/COPYRIGHT | 20 + APACHE_1_3b7/src/regex/Makefile.tmpl | 143 + APACHE_1_3b7/src/regex/README | 32 + APACHE_1_3b7/src/regex/WHATSNEW | 92 + APACHE_1_3b7/src/regex/cclass.h | 31 + APACHE_1_3b7/src/regex/cname.h | 102 + APACHE_1_3b7/src/regex/debug.c | 242 + APACHE_1_3b7/src/regex/engine.c | 1019 +++ APACHE_1_3b7/src/regex/engine.ih | 35 + APACHE_1_3b7/src/regex/main.c | 510 ++ APACHE_1_3b7/src/regex/mkh | 75 + APACHE_1_3b7/src/regex/regcomp.c | 1546 +++++ APACHE_1_3b7/src/regex/regcomp.ih | 48 + APACHE_1_3b7/src/regex/regerror.c | 124 + APACHE_1_3b7/src/regex/regerror.ih | 12 + APACHE_1_3b7/src/regex/regex.3 | 502 ++ APACHE_1_3b7/src/regex/regex.7 | 233 + APACHE_1_3b7/src/regex/regex.dsp | 114 + APACHE_1_3b7/src/regex/regex.mak | 266 + APACHE_1_3b7/src/regex/regex2.h | 138 + APACHE_1_3b7/src/regex/regexec.c | 140 + APACHE_1_3b7/src/regex/regfree.c | 37 + APACHE_1_3b7/src/regex/split.c | 316 + APACHE_1_3b7/src/regex/tests | 475 ++ APACHE_1_3b7/src/regex/utils.h | 22 + APACHE_1_3b7/src/support/.cvsignore | 11 + APACHE_1_3b7/src/support/.indent.pro | 54 + APACHE_1_3b7/src/support/Makefile.tmpl | 71 + APACHE_1_3b7/src/support/ab.1 | 114 + APACHE_1_3b7/src/support/ab.8 | 114 + APACHE_1_3b7/src/support/ab.c | 689 ++ APACHE_1_3b7/src/support/apachectl | 209 + APACHE_1_3b7/src/support/apachectl.1 | 122 + APACHE_1_3b7/src/support/apachectl.8 | 122 + APACHE_1_3b7/src/support/apxs.8 | 398 ++ APACHE_1_3b7/src/support/apxs.pl | 599 ++ APACHE_1_3b7/src/support/dbmmanage | 189 + APACHE_1_3b7/src/support/dbmmanage.1 | 119 + APACHE_1_3b7/src/support/htdigest.1 | 97 + APACHE_1_3b7/src/support/htdigest.c | 207 + APACHE_1_3b7/src/support/htpasswd.1 | 98 + APACHE_1_3b7/src/support/htpasswd.c | 224 + APACHE_1_3b7/src/support/httpd.8 | 190 + APACHE_1_3b7/src/support/httpd.exp | 346 + APACHE_1_3b7/src/support/log_server_status | 115 + APACHE_1_3b7/src/support/logresolve.8 | 87 + APACHE_1_3b7/src/support/logresolve.c | 344 + APACHE_1_3b7/src/support/logresolve.pl | 264 + APACHE_1_3b7/src/support/phf_abuse_log.cgi | 21 + APACHE_1_3b7/src/support/rotatelogs.8 | 83 + APACHE_1_3b7/src/support/rotatelogs.c | 82 + APACHE_1_3b7/src/support/split-logfile | 103 + APACHE_1_3b7/src/support/suexec.8 | 70 + APACHE_1_3b7/src/support/suexec.c | 520 ++ APACHE_1_3b7/src/support/suexec.h | 142 + APACHE_1_3b7/src/test/.cvsignore | 11 + APACHE_1_3b7/src/test/.indent.pro | 54 + APACHE_1_3b7/src/test/README | 3 + APACHE_1_3b7/src/test/check_chunked | 42 + APACHE_1_3b7/src/test/cls.c | 166 + APACHE_1_3b7/src/test/rename/Makefile | 21 + APACHE_1_3b7/src/test/rename/README | 59 + APACHE_1_3b7/src/test/rename/apapi.h | 259 + APACHE_1_3b7/src/test/rename/apapi.h.mk | 82 + APACHE_1_3b7/src/test/rename/apapi_compat.h | 525 ++ .../src/test/rename/apapi_compat.h.mk | 90 + APACHE_1_3b7/src/test/rename/compat.h | 393 ++ APACHE_1_3b7/src/test/rename/compat.h.mk | 59 + APACHE_1_3b7/src/test/rename/csubst/Makefile | 34 + APACHE_1_3b7/src/test/rename/csubst/csubst.c | 131 + APACHE_1_3b7/src/test/rename/csubst/lexer.c | 2235 +++++++ APACHE_1_3b7/src/test/rename/csubst/lexer.l | 226 + APACHE_1_3b7/src/test/rename/csubst/tokens.h | 41 + APACHE_1_3b7/src/test/rename/csubst/util.c | 137 + APACHE_1_3b7/src/test/rename/csubst/util.h | 11 + APACHE_1_3b7/src/test/rename/rename.cf | 400 ++ .../src/test/rename/rename.cf.clean-api | 456 ++ APACHE_1_3b7/src/test/rename/rename.cf.update | 55 + APACHE_1_3b7/src/test/rename/rename.pl | 89 + APACHE_1_3b7/src/test/tcpdumpscii.txt | 50 + APACHE_1_3b7/src/test/test-writev.c | 85 + APACHE_1_3b7/src/test/test_date.c | 180 + APACHE_1_3b7/src/test/test_select.c | 30 + APACHE_1_3b7/src/test/time-sem.c | 572 ++ APACHE_1_3b7/src/test/vhtest/README | 53 + APACHE_1_3b7/src/test/vhtest/bin/test1 | 29 + APACHE_1_3b7/src/test/vhtest/bin/test1d | 29 + APACHE_1_3b7/src/test/vhtest/bin/test2 | 45 + APACHE_1_3b7/src/test/vhtest/bin/test2d | 45 + APACHE_1_3b7/src/test/vhtest/bin/test3 | 18 + APACHE_1_3b7/src/test/vhtest/bin/test4 | 13 + APACHE_1_3b7/src/test/vhtest/bin/test5 | 31 + APACHE_1_3b7/src/test/vhtest/bin/test6 | 0 APACHE_1_3b7/src/test/vhtest/bin/vhget | 74 + APACHE_1_3b7/src/test/vhtest/conf/common.conf | 24 + APACHE_1_3b7/src/test/vhtest/conf/mime.types | 103 + APACHE_1_3b7/src/test/vhtest/conf/test1.conf | 28 + APACHE_1_3b7/src/test/vhtest/conf/test1d.conf | 33 + APACHE_1_3b7/src/test/vhtest/conf/test2.conf | 35 + APACHE_1_3b7/src/test/vhtest/conf/test2d.conf | 45 + APACHE_1_3b7/src/test/vhtest/conf/test3.conf | 34 + APACHE_1_3b7/src/test/vhtest/conf/test4.conf | 18 + APACHE_1_3b7/src/test/vhtest/conf/test5.conf | 44 + APACHE_1_3b7/src/test/vhtest/conf/test6.conf | 42 + .../test/vhtest/docroot/default1/vhost.txt | 1 + .../test/vhtest/docroot/default2/vhost.txt | 1 + .../test/vhtest/docroot/default3/vhost.txt | 1 + .../src/test/vhtest/docroot/main/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost1/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost2/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost3/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost4/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost5/vhost.txt | 1 + APACHE_1_3b7/src/test/vhtest/logs/.cvsignore | 1 + APACHE_1_3b7/src/test/vhtest/runtest | 42 + APACHE_1_3b7/src/test/zb.c | 567 ++ 600 files changed, 147308 insertions(+) create mode 100644 APACHE_1_3b7/.cvsignore create mode 100644 APACHE_1_3b7/ABOUT_APACHE create mode 100644 APACHE_1_3b7/Announcement create mode 100644 APACHE_1_3b7/CHANGES create mode 100644 APACHE_1_3b7/INSTALL create mode 100644 APACHE_1_3b7/KEYS create mode 100644 APACHE_1_3b7/LICENSE create mode 100644 APACHE_1_3b7/Makefile.tmpl create mode 100644 APACHE_1_3b7/README create mode 100644 APACHE_1_3b7/README.NT create mode 100644 APACHE_1_3b7/README.configure create mode 100644 APACHE_1_3b7/RULES.CVS create mode 100644 APACHE_1_3b7/STATUS create mode 100644 APACHE_1_3b7/cgi-bin/printenv create mode 100644 APACHE_1_3b7/cgi-bin/test-cgi create mode 100644 APACHE_1_3b7/conf/.cvsignore create mode 100644 APACHE_1_3b7/conf/access.conf-dist create mode 100644 APACHE_1_3b7/conf/access.conf-dist-win create mode 100644 APACHE_1_3b7/conf/highperformance.conf-dist create mode 100644 APACHE_1_3b7/conf/httpd.conf-dist create mode 100644 APACHE_1_3b7/conf/httpd.conf-dist-win create mode 100644 APACHE_1_3b7/conf/magic create mode 100644 APACHE_1_3b7/conf/mime.types create mode 100644 APACHE_1_3b7/conf/srm.conf-dist create mode 100644 APACHE_1_3b7/conf/srm.conf-dist-win create mode 100755 APACHE_1_3b7/configure create mode 100644 APACHE_1_3b7/htdocs/.cvsignore create mode 100644 APACHE_1_3b7/htdocs/apache_pb.gif create mode 100644 APACHE_1_3b7/htdocs/index.html create mode 100644 APACHE_1_3b7/htdocs/manual/LICENSE create mode 100644 APACHE_1_3b7/htdocs/manual/bind.html create mode 100644 APACHE_1_3b7/htdocs/manual/cgi_path.html create mode 100644 APACHE_1_3b7/htdocs/manual/content-negotiation.html create mode 100644 APACHE_1_3b7/htdocs/manual/custom-error.html create mode 100644 APACHE_1_3b7/htdocs/manual/dns-caveats.html create mode 100644 APACHE_1_3b7/htdocs/manual/dso.html create mode 100644 APACHE_1_3b7/htdocs/manual/ebcdic.html create mode 100644 APACHE_1_3b7/htdocs/manual/env.html create mode 100755 APACHE_1_3b7/htdocs/manual/expand.pl create mode 100644 APACHE_1_3b7/htdocs/manual/footer.html create mode 100644 APACHE_1_3b7/htdocs/manual/handler.html create mode 100644 APACHE_1_3b7/htdocs/manual/header.html create mode 100644 APACHE_1_3b7/htdocs/manual/images/custom_errordocs.gif create mode 100644 APACHE_1_3b7/htdocs/manual/images/home.gif create mode 100644 APACHE_1_3b7/htdocs/manual/images/index.gif create mode 100644 APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig1.fig create mode 100644 APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig1.gif create mode 100644 APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig2.fig create mode 100644 APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig2.gif create mode 100644 APACHE_1_3b7/htdocs/manual/images/sub.gif create mode 100644 APACHE_1_3b7/htdocs/manual/index.html create mode 100644 APACHE_1_3b7/htdocs/manual/install.html create mode 100644 APACHE_1_3b7/htdocs/manual/invoking.html create mode 100644 APACHE_1_3b7/htdocs/manual/keepalive.html create mode 100644 APACHE_1_3b7/htdocs/manual/location.html create mode 100644 APACHE_1_3b7/htdocs/manual/man-template.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/API.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/FAQ.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/HTTP_Features.tsv create mode 100644 APACHE_1_3b7/htdocs/manual/misc/client_block_api.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/compat_notes.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/custom_errordocs.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/descriptors.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/fin_wait_2.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/footer.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/header.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/howto.html create mode 100755 APACHE_1_3b7/htdocs/manual/misc/index.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/known_client_problems.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/nopgp.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/perf-bsd44.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/perf-dec.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/perf-hp.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/perf-tuning.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/perf.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/security_tips.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/vif-info.html create mode 100644 APACHE_1_3b7/htdocs/manual/misc/windoz_keepalive.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/core.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/directive-dict.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/directives.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/footer.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/header.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/index.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_access.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_actions.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_alias.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_asis.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_auth.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_auth_anon.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_auth_db.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_auth_dbm.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_autoindex.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_browser.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_cern_meta.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_cgi.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_cookies.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_digest.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_dir.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_dld.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_dll.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_env.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_example.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_expires.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_headers.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_imap.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_include.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_info.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_isapi.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_log_agent.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_log_common.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_log_config.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_log_referer.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_mime.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_mime_magic.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_mmap_static.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_negotiation.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_proxy.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_rewrite.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_setenvif.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_so.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_speling.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_status.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_unique_id.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_userdir.html create mode 100644 APACHE_1_3b7/htdocs/manual/mod/mod_usertrack.html create mode 100644 APACHE_1_3b7/htdocs/manual/multilogs.html create mode 100644 APACHE_1_3b7/htdocs/manual/new_features_1_0.html create mode 100644 APACHE_1_3b7/htdocs/manual/new_features_1_1.html create mode 100644 APACHE_1_3b7/htdocs/manual/new_features_1_2.html create mode 100644 APACHE_1_3b7/htdocs/manual/new_features_1_3.html create mode 100644 APACHE_1_3b7/htdocs/manual/process-model.html create mode 100644 APACHE_1_3b7/htdocs/manual/sections.html create mode 100644 APACHE_1_3b7/htdocs/manual/sourcereorg.html create mode 100644 APACHE_1_3b7/htdocs/manual/stopping.html create mode 100644 APACHE_1_3b7/htdocs/manual/suexec.html create mode 100644 APACHE_1_3b7/htdocs/manual/unixware.html create mode 100644 APACHE_1_3b7/htdocs/manual/upgrading_to_1_3.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/details.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/details_1_2.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/examples.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/fd-limits.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/footer.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/header.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/host.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/index.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/ip-based.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/name-based.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/vhosts-in-depth.html create mode 100644 APACHE_1_3b7/htdocs/manual/vhosts/virtual-host.html create mode 100644 APACHE_1_3b7/htdocs/manual/windows.html create mode 100644 APACHE_1_3b7/icons/README create mode 100644 APACHE_1_3b7/icons/a.gif create mode 100644 APACHE_1_3b7/icons/alert.black.gif create mode 100644 APACHE_1_3b7/icons/alert.red.gif create mode 100644 APACHE_1_3b7/icons/apache_pb.gif create mode 100644 APACHE_1_3b7/icons/back.gif create mode 100644 APACHE_1_3b7/icons/ball.gray.gif create mode 100644 APACHE_1_3b7/icons/ball.red.gif create mode 100644 APACHE_1_3b7/icons/binary.gif create mode 100644 APACHE_1_3b7/icons/binhex.gif create mode 100644 APACHE_1_3b7/icons/blank.gif create mode 100644 APACHE_1_3b7/icons/bomb.gif create mode 100644 APACHE_1_3b7/icons/box1.gif create mode 100644 APACHE_1_3b7/icons/box2.gif create mode 100644 APACHE_1_3b7/icons/broken.gif create mode 100644 APACHE_1_3b7/icons/burst.gif create mode 100644 APACHE_1_3b7/icons/c.gif create mode 100644 APACHE_1_3b7/icons/comp.blue.gif create mode 100644 APACHE_1_3b7/icons/comp.gray.gif create mode 100644 APACHE_1_3b7/icons/compressed.gif create mode 100644 APACHE_1_3b7/icons/continued.gif create mode 100644 APACHE_1_3b7/icons/dir.gif create mode 100644 APACHE_1_3b7/icons/down.gif create mode 100644 APACHE_1_3b7/icons/dvi.gif create mode 100644 APACHE_1_3b7/icons/f.gif create mode 100644 APACHE_1_3b7/icons/folder.gif create mode 100644 APACHE_1_3b7/icons/folder.open.gif create mode 100644 APACHE_1_3b7/icons/folder.sec.gif create mode 100644 APACHE_1_3b7/icons/forward.gif create mode 100644 APACHE_1_3b7/icons/generic.gif create mode 100644 APACHE_1_3b7/icons/generic.red.gif create mode 100644 APACHE_1_3b7/icons/generic.sec.gif create mode 100644 APACHE_1_3b7/icons/hand.right.gif create mode 100644 APACHE_1_3b7/icons/hand.up.gif create mode 100644 APACHE_1_3b7/icons/icon.sheet.gif create mode 100644 APACHE_1_3b7/icons/image1.gif create mode 100644 APACHE_1_3b7/icons/image2.gif create mode 100644 APACHE_1_3b7/icons/image3.gif create mode 100644 APACHE_1_3b7/icons/index.gif create mode 100644 APACHE_1_3b7/icons/layout.gif create mode 100644 APACHE_1_3b7/icons/left.gif create mode 100644 APACHE_1_3b7/icons/link.gif create mode 100644 APACHE_1_3b7/icons/movie.gif create mode 100644 APACHE_1_3b7/icons/p.gif create mode 100644 APACHE_1_3b7/icons/patch.gif create mode 100644 APACHE_1_3b7/icons/pdf.gif create mode 100644 APACHE_1_3b7/icons/pie0.gif create mode 100644 APACHE_1_3b7/icons/pie1.gif create mode 100644 APACHE_1_3b7/icons/pie2.gif create mode 100644 APACHE_1_3b7/icons/pie3.gif create mode 100644 APACHE_1_3b7/icons/pie4.gif create mode 100644 APACHE_1_3b7/icons/pie5.gif create mode 100644 APACHE_1_3b7/icons/pie6.gif create mode 100644 APACHE_1_3b7/icons/pie7.gif create mode 100644 APACHE_1_3b7/icons/pie8.gif create mode 100644 APACHE_1_3b7/icons/portal.gif create mode 100644 APACHE_1_3b7/icons/ps.gif create mode 100644 APACHE_1_3b7/icons/quill.gif create mode 100644 APACHE_1_3b7/icons/right.gif create mode 100644 APACHE_1_3b7/icons/screw1.gif create mode 100644 APACHE_1_3b7/icons/screw2.gif create mode 100644 APACHE_1_3b7/icons/script.gif create mode 100644 APACHE_1_3b7/icons/sound1.gif create mode 100644 APACHE_1_3b7/icons/sound2.gif create mode 100644 APACHE_1_3b7/icons/sphere1.gif create mode 100644 APACHE_1_3b7/icons/sphere2.gif create mode 100644 APACHE_1_3b7/icons/tar.gif create mode 100644 APACHE_1_3b7/icons/tex.gif create mode 100644 APACHE_1_3b7/icons/text.gif create mode 100644 APACHE_1_3b7/icons/transfer.gif create mode 100644 APACHE_1_3b7/icons/unknown.gif create mode 100644 APACHE_1_3b7/icons/up.gif create mode 100644 APACHE_1_3b7/icons/uu.gif create mode 100644 APACHE_1_3b7/icons/uuencoded.gif create mode 100644 APACHE_1_3b7/icons/world1.gif create mode 100644 APACHE_1_3b7/icons/world2.gif create mode 100644 APACHE_1_3b7/logs/.cvsignore create mode 100644 APACHE_1_3b7/src/.cvsignore create mode 100644 APACHE_1_3b7/src/.gdbinit create mode 100644 APACHE_1_3b7/src/Apache.dsp create mode 100644 APACHE_1_3b7/src/Apache.mak create mode 100644 APACHE_1_3b7/src/ApacheCore.def create mode 100644 APACHE_1_3b7/src/ApacheCore.dsp create mode 100644 APACHE_1_3b7/src/ApacheCore.mak create mode 100644 APACHE_1_3b7/src/CHANGES create mode 100644 APACHE_1_3b7/src/Configuration.tmpl create mode 100755 APACHE_1_3b7/src/Configure create mode 100644 APACHE_1_3b7/src/INDENT create mode 100644 APACHE_1_3b7/src/INSTALL create mode 100644 APACHE_1_3b7/src/Makefile.nt create mode 100644 APACHE_1_3b7/src/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/PORTING create mode 100644 APACHE_1_3b7/src/README create mode 100644 APACHE_1_3b7/src/README.EBCDIC create mode 100644 APACHE_1_3b7/src/ap/.cvsignore create mode 100644 APACHE_1_3b7/src/ap/.indent.pro create mode 100644 APACHE_1_3b7/src/ap/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/ap/ap.dsp create mode 100644 APACHE_1_3b7/src/ap/ap.mak create mode 100644 APACHE_1_3b7/src/ap/ap_cpystrn.c create mode 100644 APACHE_1_3b7/src/ap/ap_execve.c create mode 100644 APACHE_1_3b7/src/ap/ap_fnmatch.c create mode 100644 APACHE_1_3b7/src/ap/ap_md5c.c create mode 100644 APACHE_1_3b7/src/ap/ap_signal.c create mode 100644 APACHE_1_3b7/src/ap/ap_slack.c create mode 100644 APACHE_1_3b7/src/ap/ap_snprintf.c create mode 100644 APACHE_1_3b7/src/ap/ap_strings.c create mode 100644 APACHE_1_3b7/src/buildmark.c create mode 100755 APACHE_1_3b7/src/helpers/CutRule create mode 100755 APACHE_1_3b7/src/helpers/GuessOS create mode 100644 APACHE_1_3b7/src/helpers/MakeLint create mode 100755 APACHE_1_3b7/src/helpers/PrintPath create mode 100644 APACHE_1_3b7/src/helpers/PrintPathOS2 create mode 100755 APACHE_1_3b7/src/helpers/TestCompile create mode 100644 APACHE_1_3b7/src/helpers/dummy.c create mode 100644 APACHE_1_3b7/src/helpers/find-dbm-lib create mode 100755 APACHE_1_3b7/src/helpers/fmn.sh create mode 100755 APACHE_1_3b7/src/helpers/fp2rp create mode 100755 APACHE_1_3b7/src/helpers/install.sh create mode 100755 APACHE_1_3b7/src/helpers/mfhead create mode 100755 APACHE_1_3b7/src/helpers/mkdir.sh create mode 100755 APACHE_1_3b7/src/helpers/mkshadow.sh create mode 100755 APACHE_1_3b7/src/helpers/ppl.sh create mode 100644 APACHE_1_3b7/src/include/.cvsignore create mode 100644 APACHE_1_3b7/src/include/.indent.pro create mode 100644 APACHE_1_3b7/src/include/alloc.h create mode 100644 APACHE_1_3b7/src/include/ap.h create mode 100644 APACHE_1_3b7/src/include/ap_compat.h create mode 100644 APACHE_1_3b7/src/include/ap_config.h create mode 100644 APACHE_1_3b7/src/include/buff.h create mode 100644 APACHE_1_3b7/src/include/compat.h create mode 100644 APACHE_1_3b7/src/include/conf.h create mode 100644 APACHE_1_3b7/src/include/explain.h create mode 100644 APACHE_1_3b7/src/include/fnmatch.h create mode 100644 APACHE_1_3b7/src/include/hsregex.h create mode 100644 APACHE_1_3b7/src/include/http_conf_globals.h create mode 100644 APACHE_1_3b7/src/include/http_config.h create mode 100644 APACHE_1_3b7/src/include/http_core.h create mode 100644 APACHE_1_3b7/src/include/http_log.h create mode 100644 APACHE_1_3b7/src/include/http_main.h create mode 100644 APACHE_1_3b7/src/include/http_protocol.h create mode 100644 APACHE_1_3b7/src/include/http_request.h create mode 100644 APACHE_1_3b7/src/include/http_vhost.h create mode 100644 APACHE_1_3b7/src/include/httpd.h create mode 100644 APACHE_1_3b7/src/include/md5.h create mode 100644 APACHE_1_3b7/src/include/multithread.h create mode 100644 APACHE_1_3b7/src/include/rfc1413.h create mode 100644 APACHE_1_3b7/src/include/scoreboard.h create mode 100644 APACHE_1_3b7/src/include/util_date.h create mode 100644 APACHE_1_3b7/src/include/util_md5.h create mode 100644 APACHE_1_3b7/src/include/util_script.h create mode 100644 APACHE_1_3b7/src/include/util_uri.h create mode 100644 APACHE_1_3b7/src/main/.cvsignore create mode 100644 APACHE_1_3b7/src/main/.indent.pro create mode 100644 APACHE_1_3b7/src/main/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/main/alloc.c create mode 100644 APACHE_1_3b7/src/main/buff.c create mode 100644 APACHE_1_3b7/src/main/fnmatch.c create mode 100644 APACHE_1_3b7/src/main/gen_test_char.c create mode 100644 APACHE_1_3b7/src/main/gen_test_char.dsp create mode 100644 APACHE_1_3b7/src/main/gen_test_char.mak create mode 100644 APACHE_1_3b7/src/main/gen_uri_delims.c create mode 100644 APACHE_1_3b7/src/main/gen_uri_delims.dsp create mode 100644 APACHE_1_3b7/src/main/gen_uri_delims.mak create mode 100644 APACHE_1_3b7/src/main/http_config.c create mode 100644 APACHE_1_3b7/src/main/http_core.c create mode 100644 APACHE_1_3b7/src/main/http_log.c create mode 100644 APACHE_1_3b7/src/main/http_main.c create mode 100644 APACHE_1_3b7/src/main/http_protocol.c create mode 100644 APACHE_1_3b7/src/main/http_request.c create mode 100644 APACHE_1_3b7/src/main/http_vhost.c create mode 100644 APACHE_1_3b7/src/main/md5c.c create mode 100644 APACHE_1_3b7/src/main/rfc1413.c create mode 100644 APACHE_1_3b7/src/main/util.c create mode 100644 APACHE_1_3b7/src/main/util_date.c create mode 100644 APACHE_1_3b7/src/main/util_md5.c create mode 100644 APACHE_1_3b7/src/main/util_script.c create mode 100644 APACHE_1_3b7/src/main/util_uri.c create mode 100644 APACHE_1_3b7/src/modules/.cvsignore create mode 100644 APACHE_1_3b7/src/modules/README create mode 100644 APACHE_1_3b7/src/modules/example/.cvsignore create mode 100644 APACHE_1_3b7/src/modules/example/.indent.pro create mode 100644 APACHE_1_3b7/src/modules/example/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/modules/example/README create mode 100644 APACHE_1_3b7/src/modules/example/mod_example.c create mode 100644 APACHE_1_3b7/src/modules/experimental/.cvsignore create mode 100644 APACHE_1_3b7/src/modules/experimental/.indent.pro create mode 100644 APACHE_1_3b7/src/modules/experimental/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/modules/experimental/mod_mmap_static.c create mode 100644 APACHE_1_3b7/src/modules/extra/.cvsignore create mode 100644 APACHE_1_3b7/src/modules/extra/.indent.pro create mode 100644 APACHE_1_3b7/src/modules/extra/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/modules/proxy/.cvsignore create mode 100644 APACHE_1_3b7/src/modules/proxy/.indent.pro create mode 100644 APACHE_1_3b7/src/modules/proxy/ApacheModuleProxy.dsp create mode 100644 APACHE_1_3b7/src/modules/proxy/ApacheModuleProxy.mak create mode 100644 APACHE_1_3b7/src/modules/proxy/Makefile.libdir create mode 100644 APACHE_1_3b7/src/modules/proxy/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/modules/proxy/mod_proxy.c create mode 100644 APACHE_1_3b7/src/modules/proxy/mod_proxy.h create mode 100644 APACHE_1_3b7/src/modules/proxy/proxy_cache.c create mode 100644 APACHE_1_3b7/src/modules/proxy/proxy_connect.c create mode 100644 APACHE_1_3b7/src/modules/proxy/proxy_ftp.c create mode 100644 APACHE_1_3b7/src/modules/proxy/proxy_http.c create mode 100644 APACHE_1_3b7/src/modules/proxy/proxy_util.c create mode 100644 APACHE_1_3b7/src/modules/standard/.cvsignore create mode 100644 APACHE_1_3b7/src/modules/standard/.indent.pro create mode 100644 APACHE_1_3b7/src/modules/standard/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/modules/standard/mod_access.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_actions.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_alias.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_asis.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_auth.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_auth_anon.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_auth_db.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_auth_db.module create mode 100644 APACHE_1_3b7/src/modules/standard/mod_auth_dbm.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_autoindex.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_cern_meta.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_cgi.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_digest.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_dir.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_env.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_expires.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_headers.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_imap.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_include.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_info.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_log_agent.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_log_config.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_log_referer.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_mime.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_mime_magic.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_negotiation.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_rewrite.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_rewrite.h create mode 100644 APACHE_1_3b7/src/modules/standard/mod_setenvif.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_so.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_speling.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_status.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_unique_id.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_userdir.c create mode 100644 APACHE_1_3b7/src/modules/standard/mod_usertrack.c create mode 100644 APACHE_1_3b7/src/modules/test/.cvsignore create mode 100644 APACHE_1_3b7/src/modules/test/.indent.pro create mode 100644 APACHE_1_3b7/src/modules/test/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/modules/test/README create mode 100644 APACHE_1_3b7/src/modules/test/mod_rndchunk.c create mode 100644 APACHE_1_3b7/src/modules/test/mod_test_util_uri.c create mode 100644 APACHE_1_3b7/src/os/.indent.pro create mode 100644 APACHE_1_3b7/src/os/bs2000/.cvsignore create mode 100644 APACHE_1_3b7/src/os/bs2000/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/os/bs2000/bs2login.c create mode 100644 APACHE_1_3b7/src/os/bs2000/ebcdic.c create mode 100644 APACHE_1_3b7/src/os/bs2000/ebcdic.h create mode 100644 APACHE_1_3b7/src/os/bs2000/os-inline.c create mode 100644 APACHE_1_3b7/src/os/bs2000/os.c create mode 100644 APACHE_1_3b7/src/os/bs2000/os.h create mode 100644 APACHE_1_3b7/src/os/emx/.cvsignore create mode 100644 APACHE_1_3b7/src/os/emx/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/os/emx/os-inline.c create mode 100644 APACHE_1_3b7/src/os/emx/os.c create mode 100644 APACHE_1_3b7/src/os/emx/os.h create mode 100644 APACHE_1_3b7/src/os/os2/.cvsignore create mode 100644 APACHE_1_3b7/src/os/os2/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/os/os2/os-inline.c create mode 100644 APACHE_1_3b7/src/os/os2/os.c create mode 100644 APACHE_1_3b7/src/os/os2/os.h create mode 100644 APACHE_1_3b7/src/os/unix/.cvsignore create mode 100644 APACHE_1_3b7/src/os/unix/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/os/unix/os-aix-dso.c create mode 100644 APACHE_1_3b7/src/os/unix/os-inline.c create mode 100644 APACHE_1_3b7/src/os/unix/os.c create mode 100644 APACHE_1_3b7/src/os/unix/os.h create mode 100644 APACHE_1_3b7/src/os/win32/.cvsignore create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleAuthAnon.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleAuthAnon.mak create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleCERNMeta.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleCERNMeta.mak create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleDigest.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleDigest.mak create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleExpires.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleExpires.mak create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleHeaders.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleHeaders.mak create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleInfo.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleInfo.mak create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleRewrite.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleRewrite.mak create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleSpeling.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleSpeling.mak create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleStatus.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleStatus.mak create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleUserTrack.dsp create mode 100644 APACHE_1_3b7/src/os/win32/ApacheModuleUserTrack.mak create mode 100755 APACHE_1_3b7/src/os/win32/ApacheOS.dsp create mode 100755 APACHE_1_3b7/src/os/win32/ApacheOS.mak create mode 100644 APACHE_1_3b7/src/os/win32/MakeModuleMak.cpp create mode 100644 APACHE_1_3b7/src/os/win32/MakeModuleMak.mak create mode 100644 APACHE_1_3b7/src/os/win32/Module.mak.tmpl create mode 100644 APACHE_1_3b7/src/os/win32/getopt.c create mode 100644 APACHE_1_3b7/src/os/win32/getopt.h create mode 100644 APACHE_1_3b7/src/os/win32/installer/README.TXT create mode 100644 APACHE_1_3b7/src/os/win32/installer/apache.iwz create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/install.c create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/install.def create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/install.dsp create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/install.mak create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/test/resource.h create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/test/test.c create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/test/test.def create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/test/test.dsp create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/test/test.h create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/test/test.ico create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/test/test.mak create mode 100644 APACHE_1_3b7/src/os/win32/installer/installdll/test/test.rc create mode 100644 APACHE_1_3b7/src/os/win32/main_win32.c create mode 100644 APACHE_1_3b7/src/os/win32/mod_dll.c create mode 100644 APACHE_1_3b7/src/os/win32/mod_isapi.c create mode 100644 APACHE_1_3b7/src/os/win32/modules.c create mode 100644 APACHE_1_3b7/src/os/win32/multithread.c create mode 100755 APACHE_1_3b7/src/os/win32/os.c create mode 100755 APACHE_1_3b7/src/os/win32/os.h create mode 100644 APACHE_1_3b7/src/os/win32/passwd.c create mode 100644 APACHE_1_3b7/src/os/win32/passwd.h create mode 100644 APACHE_1_3b7/src/os/win32/readdir.c create mode 100644 APACHE_1_3b7/src/os/win32/readdir.h create mode 100755 APACHE_1_3b7/src/os/win32/registry.c create mode 100755 APACHE_1_3b7/src/os/win32/registry.h create mode 100644 APACHE_1_3b7/src/os/win32/service.c create mode 100644 APACHE_1_3b7/src/os/win32/service.h create mode 100644 APACHE_1_3b7/src/os/win32/util_win32.c create mode 100644 APACHE_1_3b7/src/regex/.cvsignore create mode 100644 APACHE_1_3b7/src/regex/COPYRIGHT create mode 100644 APACHE_1_3b7/src/regex/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/regex/README create mode 100644 APACHE_1_3b7/src/regex/WHATSNEW create mode 100644 APACHE_1_3b7/src/regex/cclass.h create mode 100644 APACHE_1_3b7/src/regex/cname.h create mode 100644 APACHE_1_3b7/src/regex/debug.c create mode 100644 APACHE_1_3b7/src/regex/engine.c create mode 100644 APACHE_1_3b7/src/regex/engine.ih create mode 100644 APACHE_1_3b7/src/regex/main.c create mode 100644 APACHE_1_3b7/src/regex/mkh create mode 100644 APACHE_1_3b7/src/regex/regcomp.c create mode 100644 APACHE_1_3b7/src/regex/regcomp.ih create mode 100644 APACHE_1_3b7/src/regex/regerror.c create mode 100644 APACHE_1_3b7/src/regex/regerror.ih create mode 100644 APACHE_1_3b7/src/regex/regex.3 create mode 100644 APACHE_1_3b7/src/regex/regex.7 create mode 100644 APACHE_1_3b7/src/regex/regex.dsp create mode 100644 APACHE_1_3b7/src/regex/regex.mak create mode 100644 APACHE_1_3b7/src/regex/regex2.h create mode 100644 APACHE_1_3b7/src/regex/regexec.c create mode 100644 APACHE_1_3b7/src/regex/regfree.c create mode 100644 APACHE_1_3b7/src/regex/split.c create mode 100644 APACHE_1_3b7/src/regex/tests create mode 100644 APACHE_1_3b7/src/regex/utils.h create mode 100644 APACHE_1_3b7/src/support/.cvsignore create mode 100644 APACHE_1_3b7/src/support/.indent.pro create mode 100644 APACHE_1_3b7/src/support/Makefile.tmpl create mode 100644 APACHE_1_3b7/src/support/ab.1 create mode 100644 APACHE_1_3b7/src/support/ab.8 create mode 100644 APACHE_1_3b7/src/support/ab.c create mode 100755 APACHE_1_3b7/src/support/apachectl create mode 100644 APACHE_1_3b7/src/support/apachectl.1 create mode 100644 APACHE_1_3b7/src/support/apachectl.8 create mode 100644 APACHE_1_3b7/src/support/apxs.8 create mode 100644 APACHE_1_3b7/src/support/apxs.pl create mode 100644 APACHE_1_3b7/src/support/dbmmanage create mode 100644 APACHE_1_3b7/src/support/dbmmanage.1 create mode 100644 APACHE_1_3b7/src/support/htdigest.1 create mode 100644 APACHE_1_3b7/src/support/htdigest.c create mode 100644 APACHE_1_3b7/src/support/htpasswd.1 create mode 100644 APACHE_1_3b7/src/support/htpasswd.c create mode 100644 APACHE_1_3b7/src/support/httpd.8 create mode 100644 APACHE_1_3b7/src/support/httpd.exp create mode 100755 APACHE_1_3b7/src/support/log_server_status create mode 100644 APACHE_1_3b7/src/support/logresolve.8 create mode 100644 APACHE_1_3b7/src/support/logresolve.c create mode 100644 APACHE_1_3b7/src/support/logresolve.pl create mode 100755 APACHE_1_3b7/src/support/phf_abuse_log.cgi create mode 100644 APACHE_1_3b7/src/support/rotatelogs.8 create mode 100644 APACHE_1_3b7/src/support/rotatelogs.c create mode 100644 APACHE_1_3b7/src/support/split-logfile create mode 100644 APACHE_1_3b7/src/support/suexec.8 create mode 100644 APACHE_1_3b7/src/support/suexec.c create mode 100644 APACHE_1_3b7/src/support/suexec.h create mode 100644 APACHE_1_3b7/src/test/.cvsignore create mode 100644 APACHE_1_3b7/src/test/.indent.pro create mode 100644 APACHE_1_3b7/src/test/README create mode 100755 APACHE_1_3b7/src/test/check_chunked create mode 100644 APACHE_1_3b7/src/test/cls.c create mode 100644 APACHE_1_3b7/src/test/rename/Makefile create mode 100644 APACHE_1_3b7/src/test/rename/README create mode 100644 APACHE_1_3b7/src/test/rename/apapi.h create mode 100755 APACHE_1_3b7/src/test/rename/apapi.h.mk create mode 100644 APACHE_1_3b7/src/test/rename/apapi_compat.h create mode 100755 APACHE_1_3b7/src/test/rename/apapi_compat.h.mk create mode 100644 APACHE_1_3b7/src/test/rename/compat.h create mode 100755 APACHE_1_3b7/src/test/rename/compat.h.mk create mode 100644 APACHE_1_3b7/src/test/rename/csubst/Makefile create mode 100644 APACHE_1_3b7/src/test/rename/csubst/csubst.c create mode 100644 APACHE_1_3b7/src/test/rename/csubst/lexer.c create mode 100644 APACHE_1_3b7/src/test/rename/csubst/lexer.l create mode 100644 APACHE_1_3b7/src/test/rename/csubst/tokens.h create mode 100644 APACHE_1_3b7/src/test/rename/csubst/util.c create mode 100644 APACHE_1_3b7/src/test/rename/csubst/util.h create mode 100644 APACHE_1_3b7/src/test/rename/rename.cf create mode 100644 APACHE_1_3b7/src/test/rename/rename.cf.clean-api create mode 100755 APACHE_1_3b7/src/test/rename/rename.cf.update create mode 100755 APACHE_1_3b7/src/test/rename/rename.pl create mode 100644 APACHE_1_3b7/src/test/tcpdumpscii.txt create mode 100644 APACHE_1_3b7/src/test/test-writev.c create mode 100644 APACHE_1_3b7/src/test/test_date.c create mode 100644 APACHE_1_3b7/src/test/test_select.c create mode 100644 APACHE_1_3b7/src/test/time-sem.c create mode 100644 APACHE_1_3b7/src/test/vhtest/README create mode 100644 APACHE_1_3b7/src/test/vhtest/bin/test1 create mode 100644 APACHE_1_3b7/src/test/vhtest/bin/test1d create mode 100644 APACHE_1_3b7/src/test/vhtest/bin/test2 create mode 100644 APACHE_1_3b7/src/test/vhtest/bin/test2d create mode 100644 APACHE_1_3b7/src/test/vhtest/bin/test3 create mode 100644 APACHE_1_3b7/src/test/vhtest/bin/test4 create mode 100644 APACHE_1_3b7/src/test/vhtest/bin/test5 create mode 100644 APACHE_1_3b7/src/test/vhtest/bin/test6 create mode 100755 APACHE_1_3b7/src/test/vhtest/bin/vhget create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/common.conf create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/mime.types create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/test1.conf create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/test1d.conf create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/test2.conf create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/test2d.conf create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/test3.conf create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/test4.conf create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/test5.conf create mode 100644 APACHE_1_3b7/src/test/vhtest/conf/test6.conf create mode 100644 APACHE_1_3b7/src/test/vhtest/docroot/default1/vhost.txt create mode 100644 APACHE_1_3b7/src/test/vhtest/docroot/default2/vhost.txt create mode 100644 APACHE_1_3b7/src/test/vhtest/docroot/default3/vhost.txt create mode 100644 APACHE_1_3b7/src/test/vhtest/docroot/main/vhost.txt create mode 100644 APACHE_1_3b7/src/test/vhtest/docroot/vhost1/vhost.txt create mode 100644 APACHE_1_3b7/src/test/vhtest/docroot/vhost2/vhost.txt create mode 100644 APACHE_1_3b7/src/test/vhtest/docroot/vhost3/vhost.txt create mode 100644 APACHE_1_3b7/src/test/vhtest/docroot/vhost4/vhost.txt create mode 100644 APACHE_1_3b7/src/test/vhtest/docroot/vhost5/vhost.txt create mode 100644 APACHE_1_3b7/src/test/vhtest/logs/.cvsignore create mode 100755 APACHE_1_3b7/src/test/vhtest/runtest create mode 100644 APACHE_1_3b7/src/test/zb.c diff --git a/APACHE_1_3b7/.cvsignore b/APACHE_1_3b7/.cvsignore new file mode 100644 index 0000000000..b332a41791 --- /dev/null +++ b/APACHE_1_3b7/.cvsignore @@ -0,0 +1,3 @@ +Makefile +Makefile.* +src.* diff --git a/APACHE_1_3b7/ABOUT_APACHE b/APACHE_1_3b7/ABOUT_APACHE new file mode 100644 index 0000000000..880b67f56d --- /dev/null +++ b/APACHE_1_3b7/ABOUT_APACHE @@ -0,0 +1,234 @@ + + The Apache HTTP Server Project + + http://www.apache.org/ + + April 1998 + +The Apache Project is a collaborative software development effort aimed +at creating a robust, commercial-grade, featureful, and freely-available +source code implementation of an HTTP (Web) server. The project is +jointly managed by a group of volunteers located around the world, using +the Internet and the Web to communicate, plan, and develop the server and +its related documentation. These volunteers are known as the Apache Group. +In addition, hundreds of users have contributed ideas, code, and +documentation to the project. This file is intended to briefly describe +the history of the Apache Group, recognize the many contributors, and +explain how you can join the fun too. + +In February of 1995, the most popular server software on the Web was the +public domain HTTP daemon developed by Rob McCool at the National Center +for Supercomputing Applications, University of Illinois, Urbana-Champaign. +However, development of that httpd had stalled after Rob left NCSA in +mid-1994, and many webmasters had developed their own extensions and bug +fixes that were in need of a common distribution. A small group of these +webmasters, contacted via private e-mail, gathered together for the purpose +of coordinating their changes (in the form of "patches"). Brian Behlendorf +and Cliff Skolnick put together a mailing list, shared information space, +and logins for the core developers on a machine in the California Bay Area, +with bandwidth and diskspace donated by HotWired and Organic Online. +By the end of February, eight core contributors formed the foundation +of the original Apache Group: + + Brian Behlendorf Roy T. Fielding Rob Hartill + David Robinson Cliff Skolnick Randy Terbush + Robert S. Thau Andrew Wilson + +with additional contributions from + + Eric Hagberg Frank Peters Nicolas Pioch + +Using NCSA httpd 1.3 as a base, we added all of the published bug fixes +and worthwhile enhancements we could find, tested the result on our own +servers, and made the first official public release (0.6.2) of the Apache +server in April 1995. By coincidence, NCSA restarted their own development +during the same period, and Brandon Long and Beth Frank of the NCSA Server +Development Team joined the list in March as honorary members so that the +two projects could share ideas and fixes. + +The early Apache server was a big hit, but we all knew that the codebase +needed a general overhaul and redesign. During May-June 1995, while +Rob Hartill and the rest of the group focused on implementing new features +for 0.7.x (like pre-forked child processes) and supporting the rapidly growing +Apache user community, Robert Thau designed a new server architecture +(code-named Shambhala) which included a modular structure and API for better +extensibility, pool-based memory allocation, and an adaptive pre-forking +process model. The group switched to this new server base in July and added +the features from 0.7.x, resulting in Apache 0.8.8 (and its brethren) +in August. + +After extensive beta testing, many ports to obscure platforms, a new set +of documentation (by David Robinson), and the addition of many features +in the form of our standard modules, Apache 1.0 was released on +December 1, 1995. + +Less than a year after the group was formed, the Apache server passed +NCSA's httpd as the #1 server on the Internet. + + ============================================================================ + +Current Apache Group in alphabetical order as of 23 April 1998: + + Brian Behlendorf Organic Online, California + Ken Coar MeepZor Consulting, New England, USA + Mark J. Cox C2Net Europe, UK + Ralf S. Engelschall Munich, Germany. + Dean Gaudet Transmeta Corporation, California + Rob Hartill Internet Movie DB, UK + Jim Jagielski jaguNET ISP, Maryland + Alexei Kosut Stanford University, California + Martin Kraemer Munich, Germany + Ben Laurie Freelance Consultant, UK + Doug MacEachern Freelance Consultant, Summer Seasons, Earth + Aram W. Mirzadeh Qosina Corporation, New York + Sameer Parekh C2Net, California + Marc Slemko Canada + Cliff Skolnick Freelance, California + Paul Sutton C2Net Europe, UK + Randy Terbush Zyzzyva ISP, Nebraska + Dirk-Willem van Gulik Freelance Consultant, Italy + +Apache Emeritae (old group members now off doing other things) + + Roy T. Fielding UC Irvine, California + Chuck Murcko The Topsail Group, Pennsylvania + David Robinson Cambridge University, UK + Robert S. Thau MIT, Massachusetts + Andrew Wilson Freelance Consultant, UK + +Other major contributors + + Rob McCool (original author of the NCSA httpd), + Brandon Long and Beth Frank (NCSA Server Development Team, post-1.3), + Paul Richards (convinced the group to use remote CVS after 1.0), + Kevin Hughes (creator of all those nifty icons), + Henry Spencer (author of the regex library), Garey Smiley (OS/2 port), + Howard Fear (mod_include), Florent Guillaume (language negotiation), + Ambarish Malpani (NT port), Ben Hyde (multi-platform build tests). + +Many 3rd-party modules, frequently used and recommended, are also +freely-available and linked from the related projects page: +, and their authors frequently +contribute ideas, patches, and testing. In particular, Doug MacEachern +(mod_perl) and Rasmus Lerdorf (mod_php). + +Hundreds of people have made individual contributions to the Apache +project. Patch contributors are listed in the src/CHANGES file. +Frequent contributors have included Lars Eilebrecht, Petr Lampa, Tom Tromey, +James H. Cloos Jr., Ed Korthof, Nathan Neulinger, Jason S. Clary, +Jason A. Dour, Michael Douglass, Tony Sanders, Brian Tao, Michael Smith, +Adam Sussman, Nathan Schrenk, Matthew Gray, and John Heidemann. + + ============================================================================ + +How to become involved in the Apache project + +There are several levels of contributing. If you just want to send +in an occasional suggestion/fix, then you can just use the bug reporting +form at . You can also subscribe +to the announcements mailing list (apache-announce@apache.org) which we +use to broadcast information about new releases, bugfixes, and upcoming +events. There's a lot of information about the development process (much +of it in serious need of updating) to be found at . + +If you'd like to become an active contributor to the Apache project (the +group of volunteers who vote on changes to the distributed server), then +you need to start by subscribing to the new-httpd@apache.org mailing list. +One warning though: traffic is high, 1000 to 1500 messages/month. +To subscribe to the list, send "subscribe new-httpd" in the body of +a message to . We recommend reading the list for +a while before trying to jump in to development. + + NOTE: The developer mailing list (new-httpd@apache.org) is not + a user support forum; it is for people actively working on development + of the server code and documentation, and for planning future + directions. If you have user/configuration questions, send them + to the USENET newsgroup "comp.infosystems.www.servers.unix". + +There is a core group of contributors (informally called the "core") +which was formed from the project founders and is augmented from time +to time when core members nominate outstanding contributors and the +rest of the core members agree. The core group focus is more on +"business" issues and limited-circulation things like security problems +than on mainstream code development. The term "The Apache Group" +technically refers to this core of project contributors. + +The Apache project is a meritocracy -- the more work you have done, the more +you are allowed to do. The group founders set the original rules, but +they can be changed by vote of the active members. There is a group +of people who have logins on our server (hyperreal.com) and access to the +CVS repository. Everyone has access to the CVS snapshots. Changes to +the code are proposed on the mailing list and usually voted on by active +members -- three +1 (yes votes) and no -1 (no votes, or vetoes) are needed +to commit a code change during a release cycle; docs are usually committed +first and then changed as needed, with conflicts resolved by majority vote. + +Our primary method of communication is our mailing list. Approximately 40 +messages a day flow over the list, and are typically very conversational in +tone. We discuss new features to add, bug fixes, user problems, developments +in the web server community, release dates, etc. The actual code development +takes place on the developers' local machines, with proposed changes +communicated using a patch (output of a unified "diff -u oldfile newfile" +command), and committed to the source repository by one of the core +developers using remote CVS. Anyone on the mailing list can vote on a +particular issue, but we only count those made by active members or people +who are known to be experts on that part of the server. Vetoes must be +accompanied by a convincing explanation. + +New members of the Apache Group are added when a frequent contributor is +nominated by one member and unanimously approved by the voting members. +In most cases, this "new" member has been actively contributing to the +group's work for over six months, so it's usually an easy decision. + +The above describes our past and current (as of April 1998) guidelines, +which will probably change over time as the membership of the group +changes and our development/coordination tools improve. + + ============================================================================ + +Why Apache Is Free + +Apache exists to provide a robust and commercial-grade reference +implementation of the HTTP protocol. It must remain a platform upon which +individuals and institutions can build reliable systems, both for +experimental purposes and for mission-critical purposes. We believe the +tools of online publishing should be in the hands of everyone, and +software companies should make their money providing value-added services +such as specialized modules and support, amongst other things. We realize +that it is often seen as an economic advantage for one company to "own" a +market - in the software industry that means to control tightly a +particular conduit such that all others must pay. This is typically done +by "owning" the protocols through which companies conduct business, at the +expense of all those other companies. To the extent that the protocols of +the World Wide Web remain "unowned" by a single company, the Web will +remain a level playing field for companies large and small. Thus, +"ownership" of the protocol must be prevented, and the existence of a +robust reference implementation of the protocol, available absolutely for +free to all companies, is a tremendously good thing. + +Furthermore, Apache is an organic entity; those who benefit from it +by using it often contribute back to it by providing feature enhancements, +bug fixes, and support for others in public newsgroups. The amount of +effort expended by any particular individual is usually fairly light, but +the resulting product is made very strong. This kind of community can +only happen with freeware -- when someone pays for software, they usually +aren't willing to fix its bugs. One can argue, then, that Apache's +strength comes from the fact that it's free, and if it were made "not +free" it would suffer tremendously, even if that money were spent on a +real development team. + +We want to see Apache used very widely -- by large companies, small +companies, research institutions, schools, individuals, in the intranet +environment, everywhere -- even though this may mean that companies who +could afford commercial software, and would pay for it without blinking, +might get a "free ride" by using Apache. We would even be happy if some +commercial software companies completely dropped their own HTTP server +development plans and used Apache as a base, with the proper attributions +as described in the LICENSE file. + +Thanks for using Apache! + + ============================================================================ +Roy Fielding, June 1997 + +If you are interested in other WWW history, see diff --git a/APACHE_1_3b7/Announcement b/APACHE_1_3b7/Announcement new file mode 100644 index 0000000000..e32bd5e026 --- /dev/null +++ b/APACHE_1_3b7/Announcement @@ -0,0 +1,69 @@ + + Apache 1.3 Beta 7 Released + ========================== + + The Apache Group is pleased to announce the release of the 1.3b7 version + of Apache, the latest beta release of the Apache HTTP server. 1.3b7 is + a second release candidate for Apache 1.3.0. + + This version is stable under UNIX but remains beta-level under Win32. No + new features are expected between 1.3b7 and 1.3.0, so please give this + version a good thrashing in order to provide as much feedback as possible + to the Apache Group before the release of 1.3.0. + + To grab the latest Apache distribution, check out + http://www.apache.org/dist/ + and the huge list of available "International Mirror Sites" at + http://www.apache.org/mirrors/ + + For a full list of specific code changes see src/CHANGES. + + For an overview of new features in 1.2 please read the CHANGES file + in the distribution and the "New Features with Apache 1.3" document at + http://www.apache.org/docs/new_features_1_3.html + + Major changes with this beta: + HTTP: fixes for 400 and 408 error codes. + WIN32: Child process spawning now uses native Win32 API. + This should address many problems people have had + on Win32 - it also forced us to modify the + related child_spawn calls in the Apache API. + Other various stability fixes. + Extensive overhaul of the way UNCs are handled. + Various mod_rewrite fixes. + Various makefile cleanups. + Various APACI changes. + Various DSO cleanups, better support for AIX, OpenBSD, NetBSD + Server's OS family now reported in Server: strings. + PORT: added support for NCR MP/RAS 3.0 + Security: we now make sure all config files opened by Apache are not + special devices. + Added "-s" command line option to dump out vhost settings. + + Contributing code to this beta: + Ralf S. Engelschall + Ed Korthof + Rick Ohnemus + Brian Behlendorf + Bob Beck + Ben Laurie + Bill Stoddard + Ernst Kloppenburg + John Withers + Jim Patterson + Jim Jagielski + Martin Kraemer + Dean Gaudet + Paul Eggert + Lars Eilebrecht + Ronald.Tschalaer@psi.ch + Kari Likovuori + Michael Anderson's + Roy Fielding + David MacKenzie + Francisco Tomei + Jens Schleusener + Jeff Earickson + Marc Slemko + diff --git a/APACHE_1_3b7/CHANGES b/APACHE_1_3b7/CHANGES new file mode 100644 index 0000000000..d0df24721c --- /dev/null +++ b/APACHE_1_3b7/CHANGES @@ -0,0 +1,173 @@ + OVERVIEW OF NEW FEATURES IN APACHE 1.3 + +New features with this release, as extensions of the Apache functionality +For more information, see the documentation included with this release +(htdocs/manual/) or http://www.apache.org/docs/ + +The Apache license has been modified slightly for this version; the +change simply prohibits derived products from claiming themselves to +be "Apache." + +In addition to a number of bug fixes and internal performance +enhancements, Apache 1.3 has the following specific new user +features: + + *) Support for Windows NT/95 + Apache now supports the Windows NT and Windows 95 operating + systems, as well as the Unix systems supported in previous + releases. Although the Windows version of Apache may not be + perform as well as on the Unix systems for which Apache was + originally written, the ability to run on Windows gives Apache the + ability to run on a large number of web servers it was not + previously able to. + + *) Regular Expression support for Alias and Redirect + New AliasMatch, ScriptAliasMatch, and RedirectMatch directives + allow for the use of regular expression matching. Additionally, + new , , and sections + provide a new syntax for regular expression sectioning. + + *) New "Magic" MIME-typing module + A new module, the optional mod_mime_magic, has been added. It uses + "magic numbers" and other hints from a file's contents to figure + out what the contents are. It then uses this information to set + the file's media type, if it cannot be determined by the file's + extension. + + *) Directory indexing modules split + The mod_dir module has been split in two, with mod_dir handling + directory index files, and mod_autoindex creating directory + listings. + + *) Support for Directory Icon Sizing + The mod_autoindex module provides listings of directory contents + when appropriate. If the FancyIndexing option is enabled, each + file in the list is preceded by an icon representing the content + type. In earlier versions of Apache, the HTML IMG tags for these + icons weren't sized, so the browser had to wait until the images + were loaded before it could lay out the page. With 1.3, the + IndexOptions directive has two new keywords which allow you to + control whether pre-sized IMG tags are used. This can + substantially speed up the display of large directory listings. + + *) AccessFileName Enhancement + The directive can now take more than one + filename. This lets sites serving pages from network file systems + and more than one Apache web server, configure access based on the + server through which shared pages are being served. + + *) HostNameLookups now defaults to "Off" + The HostNameLookups directive now defaults to "Off". This means + that, unless explicitly turned on, the server will not resolve IP + addresses into names. This was done to spare the Internet from + unnecessary DNS traffic. + + *) New child_init function for module API + A new phase for Apache's API is called once per "heavy-weight + process," before any requests are handled. This allows the module + to set up anything that need to be done once per processes. For + example, connections to databases. + + *) New child_exit function for module API + A new phase for Apache's API is called prior to termination of + a server child, e.g. when max_requests_per_child is reached. + This allow for modules to tear down anything that need to be done + once per processes. For example, connections to databases. + + *) Totally overhauled mod_rewrite: + First the last officially available release of mod_rewrite (3.0.9) was + integrated into the Apache source repository. Additionally to the fact + that this fixed some bugs, mod_rewrite now is no longer developed and + maintained _externally_ by the original author Ralf S. Engelschall. + Instead he has officially joined the Apache Group and gifted the + complete sources to it (removed the shared copyright), so further + development takes place directly at the Apache Groups source + repository. No more version synchronizations are needed in the future. + Additionally the rewriting engine was both enhanced and cleaned up by + introducing a generic way to interpolate backreferences. The noticeable + effect is that one now can use backreferences at nearly any string + construction point (RewriteRule subst string, RewriteCond test string, + ENV flag key/value, etc.) to access the parts of RewriteRule and + RewriteCond patterns via $N and %N. + + *) Simple transport and i/o hooks in place + It is possible to re-define the standalone_main function + (with -DSTANDALONE_MAIN) so modules may plugin support for + transport protocols other than tcp, e.g. DCE RPC + A new slot in the BUFF structure `t_handle' is provided to + store the plugin's transport related structures. + Support for sfio can be enabled with -DB_SFIO, which allows + modules to re-define lowest-level reads and writes so i/o + may travel through something other than a tcp socket. + In addition, sfio support allows plugin modules to manipulate + the output of all modules, e.g. parsing the output of CGI programs. + + *) New dbmmanage script + A new Perl5 version of dbmmanage allows modification of + various databases, Berkeley DB, ndbm and gdbm. Security has + been tightened such that passwords will no longer be echoed to + the terminal, the seed for srand is more random and `add' will not + overwrite and existing user, use the new `update' command + instead. New commands include the `check' command to check a + users' password and the `import' command to convert existing + password text-files or dbm files exported with `view'. + + *) New API function: is_initial_req() + The function returns true only for the initial call during a + given HTTP request. If the request is a sub-request or + internal redirect, the function will return false. + + *) Apache now ported to a mainframe machine with EBCDIC charset + This new port makes apache-1.3 compile and run on a + Siemens Nixdorf mainframe running under the BS2000-OSD + operating system in the POSIX subsystem. The server is capable + of serving either "binary-ASCII" or EBCDIC coded HTML text + documents. See the file README.EBCDIC in the src directory; + it also explains which modules still need porting (most are ready). + + *) Apache Autoconf-style Interface (APACI) + Until Apache 1.3 there was no real out-of-the-box batch-capable build + and installation procedure for the complete Apache package. This is now + provided by a top-level "configure" script and a corresponding + top-level "Makefile.tmpl" file. The goal is to provide a GNU + Autoconf-style frontend which is capable to both drive the old + src/Configure stuff in batch and additionally installs the package + with a GNU-conforming directory layout. Any options from the old + configuration scheme are available plus a lot of new options for + flexibly customizing Apache. + + *) Dynamic Shared Object (DSO) support + The support for loading Apache modules under runtime from DSO files was + greatly enhanced: First, mod_so was cleaned up and the src/Configure + script was extended to setup the totally platform-dependend commands to + build DSO files on all major Unix platforms which support the pragmatic + dlopen() interface (Linux, FreeBSD, Solaris, SunOS, IRIX, OSF1, + UnixWare). The two popular platforms HP/UX and AIX are not supported + because they both use a very special proprietary interface. Second the + modules mod_proxy and mod_mime were unbundled to be able to use them + independend from each other. Finally the Makefile generation stuff in + src/Configure was overhauled to support building shared objects as + clean as building static objects. Additionally the new APACI (see + below) provides a powerful mechanism for out-of-the-box enabling, + building, installing and activating those DSO-based modules. + + *) APache eXtenSion (APXS) support tool + Now that Apache provides full support for loading modules under runtime + from dynamic shared object (DSO) files, a new support tool "apxs" was + created which provides off-source building, installing and activating + of those DSO-based modules. It completely hides the platform-dependend + DSO-build commands from the user and provides an easy way to build + modules outside the Apache source tree. To achieve this APACI installs + the Apache C header files together with the "apxs" tool. + + *) THE BIG SYMBOL RENAMING + To avoid symbol clashes with third-party code compiled into the server, + the general prefix `ap_' was globally applied to the following classes + of symbols in the Apache source tree: Apache provided general functions + (e.g., ap_cpystrn), public API functions (e.g., palloc, bgets) and + private functions which can't be made static (because of cross-object + usage) but should be (e.g., new_connection). For backward source + compatibility with Apache 1.2 a new header file named compat.h was + created which provides defines for the old symbol names and should be + used by third-party module authors. + diff --git a/APACHE_1_3b7/INSTALL b/APACHE_1_3b7/INSTALL new file mode 100644 index 0000000000..2021d3acb5 --- /dev/null +++ b/APACHE_1_3b7/INSTALL @@ -0,0 +1,396 @@ + + A P A C H E I N S T A L L A T I O N + + NOTE: Windows users please read the documents README.NT and + http://www.apache.org/docs/windows.html, (or the + htdocs/manual/windows.html file included with Apache). + The following applies only to Unix users. + + Introduction + ============ + + Like all good things, there are two ways to configure, compile, and install + Apache. You can go for the 3-minute installation process using the APACI + process described below; or, you can opt for the same mechanism used in + previous versions of Apache, as described in the file 'src/INSTALL'. Each + mechanism has its benefits and drawbacks - APACI is newer and a little more + raw, but it gets you up and running the least amount of time, whereas the + "Configuration.tmpl" mechanism may be more familiar and give you some more + flexibility to the power user. We'd be very interested in your comments and + feedback regarding each approach. + + + Installing the Apache 1.3 HTTP server with APACI + ================================================ + + 1. Overview for the impatient + -------------------------- + + $ ./configure --prefix=PREFIX + $ make + $ make install + $ PREFIX/sbin/apachectl start + + 2. Requirements + ------------ + + The following requirements exist for building Apache: + + o Disk Space: + + Make sure you have approximately 12 MB of temporary free disk space + available. After installation Apache occupies approximately 3 MB of + disk space (the actual required disk space depends on the amount of + compiled in third party modules, etc). + + o ANSI-C Compiler: + + Make sure you have an ANSI-C compiler installed. The GNU C compiler + (GCC) from the Free Software Foundation (FSF) is recommended (version + 2.7.2 is fine). If you don't have GCC then at least make sure your + vendors compiler is ANSI compliant. You can find the homepage of GNU + at http://www.gnu.ai.mit.edu/ and the GCC distribution under + http://www.gnu.ai.mit.edu/order/ftp.html . + + o Perl 5 Interpreter [OPTIONAL]: + + For some of the support scripts like `apxs' or `dbmmanage' (which are + written in Perl) the Perl 5 interpreter is required (versions 5.003 + and 5.004 are fine). If no such interpreter is found by APACI's + `configure' script this is no harm. Of course, you still can build + and install Apache 1.3. Only those support scripts cannot be used. If + you have multiple Perl interpreters installed (perhaps a Perl 4 from + the vendor and a Perl 5 from your own), then it is recommended to use + the --with-perl option (see below) to make sure the correct one is + selected by APACI. + + o Dynamic Shared Object (DSO) support [OPTIONAL]: + + To provide maximum flexibility Apache now is able to load modules + under runtime via the DSO mechanism by using the pragmatic + dlopen()/dlsym() system calls. These system calls are not available + under all operating systems therefore you cannot use the DSO mechanism + on all platforms. And Apache currently has only limited built-in + knowledge on how to compile shared objects because this is heavily + platform-dependend. The current state is this: + + o Out-of-the-box supported platforms are: + - Linux - IRIX + - FreeBSD - HPUX + - OpenBSD - OSF1 + - NetBSD - UnixWare + - SunOS - AIX + - Solaris + + o Entirely unsupported platforms are: + - Ultrix + + If your system is not on these lists but has the dlopen-style + interface, you either have to provide the appropriate compiler and + linker flags (see CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT + below) manually or at least make sure a Perl 5 interpreter is + installed from which Apache can guess the options. + + For more in-depth information about DSO support in Apache 1.3 please + read the document htdocs/manual/dso.html carefully. Especially the + section entitled "Advantages & Disadvantages" because using the DSO + mechanism can have strange side-effects if you are not carefully. BE + WARNED! + + 3. Configuring the source tree + --------------------------- + + NOTE: Although we'll often advice you to read the src/Configuration.tmpl + file parts to better understand the various options in this + section, there is _AT NO TIME_ any need to _EDIT_ this file. The + _COMPLETE_ configuration takes place via command line arguments and + loal shell variables for the ./configure script. The + src/Configuration.tmpl file is just a _READ-ONLY_ resource, here. + + Introduction: + + The next step is to configure the Apache source tree for your particular + platform and personal requirements. The most important setup here is the + location prefix where Apache is to be installed later, because Apache has + to be configured for this location to work correctly. But there are a lot + of other options available for your pleasure. + + For a short impression of what possibilities you have, here is a typical + example which compiles Apache for the installation tree /sw/pkg/apache + with a particular compiler and flags plus the two additional modules + mod_rewrite and mod_proxy for later loading through the DSO mechanism: + + $ CC="pgcc" OPTIM="-O2" \ + ./configure --prefix=/sw/pkg/apache \ + --enable-module=rewrite --enable-shared=rewrite \ + --enable-module=proxy --enable-shared=proxy + + The complete reference of all configuration possibilities follows. For + more real-life configuration examples please check out the file + README.configure. + + Reference: + + $ [CC=...] [CFLAGS_SHLIB=...] + [OPTIM=...] [LD_SHLIB=...] + [CFLAGS=...] [LDFLAGS_SHLIB=...] + [INCLUDES=...] [LDFLAGS_SHLIB_EXPORT=...] + [LDFLAGS=...] [RANLIB=...] + [LIBS=...] + ./configure [--quiet] [--prefix=DIR] [--enable-rule=NAME] + [--verbose] [--exec-prefix=PREFIX] [--disable-rule=NAME] + [--shadow] [--bindir=EPREFIX] [--add-module=FILE] + [--help] [--sbindir=DIR] [--activate-module=FILE] + [--layout] [--libexecdir=DIR] [--enable-module=NAME] + [--mandir=DIR] [--disable-module=NAME] + [--sysconfdir=DIR] [--enable-shared=NAME] + [--datadir=DIR] [--disable-shared=NAME] + [--includedir=DIR] + [--localstatedir=DIR] [--enable-suexec] + [--runtimedir=DIR] [--suexec-caller=UID] + [--logfiledir=DIR] [--suexec-userdir=DIR] + [--proxycachedir=DIR] [--suexec-uidmin=UID] + [--compat] [--suexec-gidmin=GID] + [--suexec-safepath=PATH] + + [--with-perl=FILE] + [--without-support] + + Use the CC, OPTIM, CFLAGS, INCLUDES, LDFLAGS, LIBS, CFLAGS_SHLIB, + LD_SHLIB, LDFLAGS_SHLIB, LDFLAGS_SHLIB_EXPORT and RANLIB environment + variables to override the corresponding default entries in the + src/Configuration.tmpl file (see there for more information about their + usage). + + Note: The syntax ``KEY=VALUE ./configure ...'' (one single line!) is + the GNU Autoconf compatible way of specifying defines and can + be used with Bourne shell compatible shells only (sh, bash, + ksh). If you use a different type of shell either use ``env + KEY=VALUE ./configure ...'' when the `env' command is available + on your system or use ``setenv KEY VALUE; ./configure ...'' if + you use one of the C-shell variants (csh, tcsh). + + Note: The above parameter names are the canonical ones used in + Autoconf-style interfaces. But because src/Configuration.tmpl + uses the prefix EXTRA_ for some variables (e.g. EXTRA_CFLAGS) + these variants are accepted for backward-compatibility reasons, + too. But please use the canonical Autoconf-style names and + don't rely on this. + + Use the --prefix=PREFIX and --exec-prefix=EPREFIX options to configure + Apache to use a particular installation prefix. The default is + PREFIX=/usr/local/apache and EPREFIX=PREFIX. + + Use the --bindir=DIR, --sbindir=DIR, --libexecdir=DIR, --mandir=DIR, + --sysconfdir=DIR, --datadir=DIR, --includedir=DIR, --localstatedir=DIR, + --runtimedir=DIR, --logfiledir=DIR and proxycachedir=DIR option to change + the paths for particular subdirectories of the installation tree. + Defaults are bindir=EPREFIX/bin, sbindir=EPREFIX/sbin, + libexecdir=EPREFIX/libexec, mandir=PREFIX/man, sysconfdir=PREFIX/etc, + datadir=PREFIX/share, includedir=PREFIX/include, + localstatedir=PREFIX/var, runtimedir=PREFIX/var/run, + logfiledir=PREFIX/var/log and proxycachedir=PREFIX/var/proxy. + + Use the --compat option to install Apache into a installation tree which + has a similar layout than the one used with Apache 1.2. + + Use the --layout option to check the final installation path layout while + fiddling with the options above. + + Use the --enable-rule=NAME and --disable-rule=NAME options to enable or + disable a particular Rule from the Apache src/Configuration.tmpl file. The + defaults (yes=enabled, no=disabled) can either be seen when running + `./configure --help' or manually looked up in the src/Configuration.tmpl + file. + + Use the --add-module=FILE option to copy a module source file to the + Apache src/modules/extra/ directory and on-the-fly add an entry for it in + the configuration file. FILE has to be a valid path to a C source file + outside the Apache source tree, for instance /path/to/mod_foo.c. The added + module this is way is automatically activated and enabled. Use this option + to automatically include a simple third-party module to the Apache build + process. + + Use the --activate-module=FILE option to on-the-fly add an entry for an + existing module source file in the configuration file. FILE has to be a + valid path under src/modules/ of the Apache source tree, i.e. it already + has to be copied to this location before. The module is automatically + enabled. Use this option to automatically include a complex third-party + module to the Apache build process where, for instance a module like + mod_perl or mod_php3 consisting of more than one file which are created by + a third-party configuration scheme. + + Use the --enable-module=NAME and --disable-module=NAME options to enable + or disable a particular already distributed module from the Apache + src/Configuration.tmpl file. The correct module names (no `mod_' prefix!) + and defaults (yes=enabled, no=disabled) can be seen when running + `./configure --help'. There are two special NAME variants: "all" for + enabling or disabling all modules and "most" for enabling or disabling + only these modules which are useable on all platforms (currently this is + "all" minus the modules auth_db, log_agent, log_referer, example, so and + mmap_static). + + Use the --enable-shared=NAME and --disable-shared=NAME options to enable + or disable the shared object support for a particular module from the + Apache src/Configuration.tmpl file. The defaults (yes=enabled, + no=disabled) can be seen when running `./configure --help'. There are two + special NAME variants: "max" for enabling or disabling all modules except + the bootstrapping "so" module and "remain" for enabling or disabling only + these modules which are still not enabled. + + Note 1: The --enable-shared option DOES NOT AUTOMATICALLY enable the + module because there are variants like `--enable-shared=all' + which should not imply `--enable-module=all'. + + Note 2: Per default the DSO mechanism is globally disabled, i.e. no + modules are build as shared objects. + + Note 3: The usage of any --enable-shared option automatically implies + a --enable-module=so option because the bootstrapping module + mod_so is always needed for DSO support. + + Note 4: When you later want to extend your Apache installation via + third-party modules through the DSO+APXS mechanism make sure + that you at least compile with mod_so included, even when no + distributed modules are build as shared objects. This can be + achieved by explicitly using --enable-module=so. + + Use the --with-perl=FILE option to select a particular Perl interpreter + executable to be used with Apache. Per default APACI tries to find it + automatically. But if multiple Perl instances exist on your system you + have to select the correct one manually. + + Use the --without-support option to explicitly disable the build and + installation of support tools from the src/support/ area. This can be + useful when you have compilation problems with one or more of these not + programs on your platform or if you just don't need them. + + Use the --enable-suexec option to enable the suEXEC feature by building + and installing the "suexec" support program. Use --suexec-caller=UID to + set the allowed caller user id, the --suexec-userdir=DIR to set the user + subdirectory, the --suexec-uidmin=UID/--suexec-gidmin=GID to set the + minimal allowed UID/GID and --suexec-safepath=PATH to set the safe shell + PATH for the suEXEC feature. At least one --suexec-xxxxx option has + to be provided together with --enable-suexec option to let APACI accept + your request for using the suEXEC feature. + + CAUTION: FOR DETAILS ABOUT THE SUEXEC FEATURE WE HIGHLY RECOMMEND YOU TO + FIRST READ THE DOCUMENT htdocs/manual/suexec.html BEFORE USING + THE ABOVE OPTIONS. + + USING THE SUEXEC FEATURE PROPERLY CAN REDUCE CONSIDERABLY THE + SECURITY RISKS INVOLVED WITH ALLOWING USERS TO DEVELOP AND RUN + PRIVATE CGI OR SSI PROGRAMS. HOWEVER, IF SUEXEC IS IMPROPERLY + CONFIGURED, IT CAN CAUSE ANY NUMBER OF PROBLEMS AND POSSIBLY + CREATE NEW HOLES IN YOUR COMPUTER'S SECURITY. IF YOU AREN'T + FAMILIAR WITH MANAGING SETUID ROOT PROGRAMS AND THE SECURITY + ISSUES THEY PRESENT, WE HIGHLY RECOMMEND THAT YOU NOT CONSIDER + USING SUEXEC AND KEEP AWAY FROM THESE OPTIONS! + + Use the --shadow option to let APACI create a shadow source tree of the + sources for building. This is useful when you want to build for different + platforms in parallel (usually through a NFS, AFS or DFS mounted + filesystem). + + Use the --quiet option to disable all configuration verbose messages. + + Use the --verbose option to enable additional verbose messages. + + 4. Building the package + -------------------- + + Now you can build the various parts which form the Apache package by + simply running the command + + $ make + + Please be patient here, this takes approximately 2 minutes to complete + under a Pentium-166/FreeBSD-2.2 system, dependend on the amount of + modules you have enabled. + + 5. Installing the package + ---------------------- + + Now its time to install the package under the configured installation + PREFIX (see --prefix option above) by running: + + $ make install + + For the paranoid hackers under us: The above command really installs under + prefix _only_, i.e. no other stuff from your system is touched. Even if + you upgrade an existing installation your configuration files in + PREFIX/etc/ are preserved. + + Note for package authors: + + To simplify rolling a package tarball from the installed files APACI + provides a way to override the installation root for the install step. + Additionally you can get rid of the user message at the end of the + installation process by using the `install-quiet' target. Example: + + $ make install-quiet root=/tmp/apache-root + + 6. Testing the package + ------------------- + + Now you can fire up your Apache HTTP server by immediately running + + $ PREFIX/sbin/apachectl start + + and then you should be able to request your first document via URL + http://localhost/. Then stop the server again by running: + + $ PREFIX/sbin/apachectl stop + + 7. Customizing the package + ----------------------- + + Finally you can customize your Apache HTTP server by editing the + configuration files under PREFIX/etc/. + + $ vi PREFIX/etc/httpd.conf + $ vi PREFIX/etc/access.conf + $ vi PREFIX/etc/srm.conf + + Have a look at the Apache manual under http://localhost/manual/ or + http://www.apache.org/docs/ for a complete reference of available + configuration directives. + + 9. Set your system time properly! + ------------------------------ + + Proper operation of a public web server requires accurate time + keeping, since elements of the HTTP protocol are expressed as the time + of day. So, it's time to investigate setting up NTP or some other + time synchronization system on your Unix box, or whatever the + equivalent on NT would be. + + 8. Contacts + -------- + + o If you want to be informed about new code releases, bug fixes, + security fixes, general news and information about the Apache server + subscribe to the apache-announce mailing list as described under + http://www.apache.org/announcelist.html + + o If you want freely available support for running Apache please join the + Apache user community by subscribing at least to the following USENET + newsgroup: + comp.infosystems.www.servers.unix + + o If you want commercial support for running Apache please contact + one of the companies and contractors which are listed at + http://www.apache.org/info/support.cgi + + o If you have a concrete bug report for Apache please go to the + Apache Group Bug Database and submit your report: + http://www.apache.org/bug_report.html + + o If you want to participate in actively developing Apache please + subscribe to the `new-httpd' mailing list as described at + http://dev.apache.org/mailing-lists + + Thanks for running Apache. + The Apache Group + http://www.apache.org/ + diff --git a/APACHE_1_3b7/KEYS b/APACHE_1_3b7/KEYS new file mode 100644 index 0000000000..b8bb3873b2 --- /dev/null +++ b/APACHE_1_3b7/KEYS @@ -0,0 +1,325 @@ +This file contains the PGP keys of various Apache developers. +Please don't use them for email unless you have to. Their main +purpose is code signing. + +Apache users: pgp < KEYS +Apache developers: pgp -kxa and append it to this file. + + +Type Bits/KeyID Date User ID +pub 1024/2719AF35 1995/05/13 Ben Laurie + Ben Laurie + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAi+0jQEAAAEEAK7oX0FeNncaHfa1v+V7SMUviAm8qB8orWG0zvja4ZtSrHVg +/PMwppUh44t5ERA9lltRBdHu30+YSh8a1dYt1XOD83nknzj9rhtpFAPqyywlLVhN +VY3PVLyMbULw27aEAGc+StFqrDoUQ0+j9QU/YH/IyVN9rBaJyhsIDEUnGa81AAUR +tB5CZW4gTGF1cmllIDxiZW5AYWxncm91cC5jby51az6JARUDBRAyb2Doc3AsNzyk +Yh0BARa6CACUBnsP9Vb+T/PvNYKVQBIODz+90tz5GozWwCVfPVSaRd8Dz+oF1sFs +YCz/KuxqBhL5PkiCuSMfOVlPA5nirjoktMF/af5saZqhPr5rvr67Z1OzZnVDvWe4 +DhFrn8EoLrY5YNJhUwfINnZqyKaQu8TW6p4caLkTCW0KM+4ztTe74xRG9NeE+K0+ +0RMpAF3jEY36LGRjq6miazt2bVZQDTl6CuWE+gAaFlX2ojV7e1xdxVvpBIEc34MP +g9ORJ0evx1QilMt1VyGcS/pe4IQgjdJqjU/4fzqFZkT2nntQMbV9kQyNe2+qfqP7 +giTryIanmBAfd3oOCTsRz2VKPfdhCqCRiQB1AwUQMRdzEEyr2GZv4ALJAQEuhAL6 +A8I84BR+87uNAHD0ZJkTM73WdyMEGvAKBvrZK/g0VLYj0NtgkSuRJfrXnGkuh27I +ZrjfL952Q/mXgMtHhJHJ9YfenGFWSEDHnolNzKOzTQJpE01IZ3nWv7ezA9N1LZVC +iQCVAgUQMROrdRsIDEUnGa81AQEUNgQAlvyjt534RDQd2AYGoZriaFzjaL7dTCRH +4b1zxuWBNWf3pI4W0iwU02Q5rEWEmY5DLl6/ie+vcQKOWSqXVgnM/s6EARdKEN56 +d6PzkwszgfEybDYrcAxReJcTCcV8ItJer/iqpBLgtaxyUpI77NvKcDGHp6BgYpnv +1lNkH0FISK+JAJUDBRAwtzlWdGx7qH+PTVkBARFWA/99NTCMihlOZS7LmHDVic/q +H1K1DVdMcv0iL39+7Pq4+AA/ET8dWIgcjaIreSqAZTpjwU1pMPaWgecDD1rEMCYX +R+JoofLJ24BLcSlpXJ/gWMifYNxqdDeMRkw/aW/kaXQJWIz+oDYNuOyi5VvB6faF +6Lm7P5cw1mX0I5rYc3woh7QoQmVuIExhdXJpZSA8YmVuQGdvbnpvLmJlbi5hbGdy +b3VwLmNvLnVrPokAlQIFEDEXgCUbCAxFJxmvNQEBiL8D/3MLjfHGvuByqP1VFQrF +QeMNd2aIQuC7ys3lkDvrLkkPJQANua0/MdDaZk6F5pCGcTmmmaJOjcOcCheD7FU5 +w9zxkQGR3Swr3opFHSr/CkEl83jRy3oq1MFydWoGajQjIr/c23X8zr+XntPyO6VX +q5He4RrTiXeAEFBzz+J+R+EQ +=zh1u +-----END PGP PUBLIC KEY BLOCK----- + + +Type bits/keyID Date User ID +pub 1024/A99F75DD 1997/01/24 Ken A L Coar + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.2 + +mQCNAzLpIyUAAAEEAN9KC8CxTeozPYJjsnhFpJ14d4Hhf2M6OTgqPQFRHOswM/3j +B7IW0s+HwVyQ5/SjIlo+8ur9X7yaj1FS2GQmKD1x9LKeHRAoosBIs33okRtoeDRy +ufTaTyQTwLklxClWm3JEef4xZioun1mtWbpz0yVEOCSZcRvtnJrNPMCpn3XdAAUR +tB1LZW4gQSBMIENvYXIgPENvYXJAREVDVVMuT3JnPokAlQMFEDNLrGCazTzAqZ91 +3QEBzwEEAMqamgAftJ8X39dH+slXVZhXAkUDfUNPkDyy7Yd8R+UTCdXXZMRrVSc3 +3nGsd7sycFot+TQ4RWK8g1o/eY0LzgT+hSxsI80BabdnX2hCP8Yq6aqBw9XfHRQU ++zUHA5h150dX9vEUp+Rb8UKPvkqTNz58Cv1HFAHboZ55KMJ+oeTk +=arlJ +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 768/A0BB71C1 1997/06/03 Jim Jagielski + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3 + +mQBtAzOUkNMAAAEDANZdTUJQPwrFI9526Qf+DEWL8dXgfhWW8o6CzewdcCoHYEpu +9CiOMD3f9bgo1VozOPceGzCu/9FF2hMLUvVsTAZkzC3rre5TtPo/vOf5HJ+ac9M7 +aqxW+gRu2/90oLtxwQAFEbQfSmltIEphZ2llbHNraSA8amltQGphZ3VORVQuY29t +PokAdQMFEDOUkNRu2/90oLtxwQEB8iEC/i9Qo55TlT8bRpcqeM3lzNDqzU9cqKRf +9X8pGJIVE5m2JPm99qPLs8RPeepLChi8ZZ+2hSfb7ldQhvVLgNqQqLpsjGtJjJOU +C+MrKDeSk2WAicg6Uo0FWCsEHxrssw139A== +=pwim +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 2048/DD919C31 1996/12/24 sameer@c2.net + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQENAzK/QZIAAAEIALrsEjuGlt6wkHy8fx2wPSkH7paAqJHDCbO1W/GMVs41BsH1 +xpyBi9lOtUXHsDC8Obx/TES4/xVPSsFKPQLa9Q/OsxjXmEPBvQ5PZdOXJ5zmRMI1 +1cfUp2s8w6i+IS68IWRKdPMshGWFGar1YUPM1UpVME7U+uGD3wgdC4DrVJHzS5Eh +gEDyQ9FPb+8CpsRO3AvUPzsZGG8Iy/9GiLzmaJG34zZ5fv5X7sr89xiWJ21ehk+X +ePO9kvq+nzfOCCK6a3GZD4g3KJX/Pm3oKeaXeL8WSCCPzpNbtRJk3ofeN7Zm1K0L +yChPiyui+OO063/WASv52bxUIlmzbX82a92RnDEABRG0DXNhbWVlckBjMi5uZXSJ +ARUDBRAyv0GTbX82a92RnDEBAfqVB/9GSzADIVqY0faFOLN6+E3qqg3hPRLBvjgC +5cvTlwT7W64zI+aiSZuN+xAXq+3lnKtmzn45F3hD7gBxRPJbSKsObn2zU4UcqW/o +qoiYEnO9EhoBomwPUbVy8C00CWvDLfeF4L5r+2oXgilTsCojSaWJX0QoPCwRQao1 +YwZ6CqAA78vdbBNkmA0WrPsVqwd3ijgFapcX671AqiT+pDbvK646I6uGPXJzN3ZU +vFuDim9D2uNk9CfvPhKGscr4qqP40TnNn5fjSsmrFyFxYsdwo7I4TFpnsEPOw226 +GU+TR7zdwnByP72AxPEBJ/F22LwNyreuph+fRpWCnCf+9gVW9Heh +=jS5Z +-----END PGP PUBLIC KEY BLOCK----- + + =========================== +Rob Hartill + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.2 + +mQCNAzG6VfMAAAEEAOvtvphFG/D02vGLENBl5OVPgEJgP9E1xhUgKTZnJstv30kD +h1IqeIBkEAy5bpKapCbvvxukyQErhB0efTi2v5yTAlz5pVjgWM5Sa8CyTXJmXPHH +EuOfy1DqaiQSmZ6KWX0ygw3gKDZMiNMf06UURLLYtRlGKSYY3WVj2u2UCmS9AAUR +tB5Sb2JlcnQgSGFydGlsbCA8cm9iaEBpbWRiLmNvbT6JAJUDBRAx5eIAZWPa7ZQK +ZL0BAU2XBACXfopMzC8kW3KEqq+N9W9fkGNgy//8XqQ77FmfPQPbO4X7Zn3cyO46 +MxvPP+92zSyN3dyj/xWZYoRLwll+ync9d4KUFwKw45DALAvz1CKHMOpQPD7dIWdE +9poJQrcbKeOqLcGZTu/hY90gWBUZ++9umR8X8lyh/WEgcUolfgYHew== +=upYh +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1024/631B5749 1996/06/21 Randy Terbush + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3 + +mQCNAzHLBS8AAAEEANGFXb9o0NPVfVjSLvQh1j3fN6cMeVNA5BGUJ6HZGP/NDxTE +i8hwejJqakkU4ux/g6Kqckrx3h8WR7OXZZ+R8CsA0bg9Sr42ndEQCUISgArg+lXZ +gRUniARPPA7tamTSq8v1mnxqy9s26Ht2rAG2D6IiK/7v0JlezKirDeBjG1dJAAUR +tCFSYW5keSBUZXJidXNoIDxyYW5keUB6eXp6eXZhLmNvbT6JAJUDBRAxywUwqKsN +4GMbV0kBAegnA/sH63WyfwMFmn3nWe8T/5IXO/QkMYoMGLS1i7IxMY9O8BVvKQM+ +oxEcJdFAG7zPZkpgKzTBxmExz5hMZ9hwJ42XhrslWoP7JVvADJcdthrUAYW9W+jx +GcDYAW3qW5DpKsQchfvXq9QOBDxP+Kbbe2B8xGEyGUhLkacISFTrIhhQSg== +=8P8s +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1024/49A563D9 1997/02/24 Mark Cox + Mark Cox + Mark Cox + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAzMRY/IAAAEEAOloTOU0f4w7FDRMM6kA/6XazXxJ/HH8dsmb6E7RuYfVlXsd +kCwxUBOkyW+AYhkHbYUwnB5qBoFUyLrbLGuwKHW1KnAwgbeZLTH5nqQLpA0RLGVZ +v3tzImKUdyyxBphZWC4IeEgUbl9cc+piOsEJ8QzF7gnqwWo/Ku6tTP1JpWPZAAUR +tBdNYXJrIENveCA8bWFya0Bhd2UuY29tPokAlQMFEDQvYTHurUz9SaVj2QEB/hMD +/ix6pAa+4ZgFQNRAc7fC+I4uGWvXoI8N8wtgiJi//8Kc1vjtvTylLPKVBDsy1ihs +bVOjD3NUEkH95TNI3QhVeCwJPl2e3GgFl253hj8Jai9snHj75pXjQXq0NxQ/JRSr +EAqrFM7+yRLPs7zDwsMoc2Ox5emq4joVa3syZUEwW7LxtBZNYXJrIENveCA8bWNv +eEBjMi5uZXQ+iQCVAwUQNHKlBO6tTP1JpWPZAQEA8QP9HSjVMLohfOVO0tHcLRDB +eDfnRnBxgTeF7P2u8qB+eOeLqBzHNmE/gROWuZXOpkxeCqT0GG3oXqmSEmVOtDsJ +K92sKvtTdJOAGq95UQI3t1Ix6iNHkVJfo11RkJyU2iL6XFR1953nS33xKGdbU6v7 +5KVCu3JTe1kDEDOyMVDdRmW0GU1hcmsgQ294IDxtYXJrQHVrd2ViLmNvbT6JAJUD +BRAzEWPy7q1M/UmlY9kBAfN5A/43SdANs/NZ6ouyxAvKEWSPDnNkHI3rSPynbn7o +kSrtFeCQ3Vwe0B0fkszBEAZ9zbnx/s/1LKnriUfyzhdZhJfkZfxgDwy6s6smagYW +smz/LFaeDzG3Ej20VSe6ghseqcPscJL06PUg13LJC4LFlgYcCDEeGl81Nm37fe0x +IUhlNA== +=k8vP +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1024/2F90A69D 1997/02/24 Paul Sutton + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAzMRsB0AAAEEAKj2XYYEGcZhT69x4gskQ3xz+KMTLn7gKSqqcyyeinJ0ZjLl +6AJjb1/68nGsF+IIY+IJS+5smq8do1qpC3UZcmw423Sg8F71GeqDO4HZXOAOieVy +rpVs6S5TaXlJOcrC7zZCx+iql97+xJFjUGkkS7j/jIkx1AajzMNkSr0vkKadAAUR +tBxQYXVsIFN1dHRvbiA8cGF1bEB1a3dlYi5jb20+iQCVAwUQMxGwHcNkSr0vkKad +AQGrigP9F43zbiOigYel+JCMiB0HK/UdqSrf3xWxHIKWKNhQNjhnyeF+jKQwFld6 +7KQYsqZIpHsWLWmSk0AmKQOUIw+DxclDxBL2dT4p+CjgTgIAcbvPpahWkBAw/E+c +EGTiYbe+Y3sHJhhP+d0TOLmsETG9tpi7gFZ6FfNcWPxFMdxGrf4= +=0jQW +-----END PGP PUBLIC KEY BLOCK----- + +Type bits/keyID Date User ID +pub 1024/BA20321D 1997/06/05 Chuck Murcko + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.2 + +mQCNAzOW7moAAAEEAMYZlNOxWCjLR/PosadbG+xsrB2unid2LiYoakTFiDIBaZjx +bu6hNmVZPYfKOXQcqrCu0EY3uVLP/L89bST5pfIZOzz8GTm33zrETgfzpXYyFdbX +eZ5vc6aa3+7zmI7h/aU567P9ruB2C/RBLl1A59wmPRRVvjEIAkI4bAO6IDIdAAUR +tCBDaHVjayBNdXJja28gPGNodWNrQHRvcHNhaWwub3JnPg== +=vUdL +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1024/26BB437D 1997/04/28 Ralf S. Engelschall + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAzNko/QAAAEEANZ2kpN/oMkz4tqzxvKPZws/XwsD0Y+E5/y7P2DIw4uHS/4N +syQbgkdrZhPBlXDv68DQioHXWsb904qyr7iZB1LC5ItK9MgqlK+Z2mvPqsGbHM8J ++oYib8kf2zJ6HvrYrP7NYB0tN9YYum2ICtx+hIi6aKGXdB1ATA5erwYmu0N9AAUR +tClSYWxmIFMuIEVuZ2Vsc2NoYWxsIDxyc2VAZW5nZWxzY2hhbGwuY29tPokAlQMF +EDNko/QOXq8GJrtDfQEBKVoD/2K/+4pcwhxok+FkuLwC5Pnuh/1oeOYHiKYwx0Z3 +p09RLvDtNldr6VD+aL9JltxdPTARzZ8M50UqoF9jMr25GifheFYhilww41OVZA3e +cLXlLgda1+t0vWs3Eg/i2b0arQQDaIq7PeRdjdEDgwnG4xBaqaAqfgxwOXJ+LPWF +hiXZ +=K7lL +-----END PGP PUBLIC KEY BLOCK----- + +Type bits/keyID Date User ID +pub 1024/45B91DF1 1996/03/02 Doug MacEachern + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.2 + +mQCNAzE4lesAAAEEAKJYS1vL2iB3owwiZdCxp3JyvSNaC7h1p2jQXcJvY10gqyZm +VffDwFoSvJM1JdCx3o1mb3JpZ2OTV4SrDDkzcSpTXelgyh7k9O3HB7oG6pHTML9g +Dq9ZKydShMIvIJos7KuLWoM/eeeejtkv7r/gWsGHAyKbT8fs3r7nlmxFuR3xAAUX +tB9Eb3VnIE1hY0VhY2hlcm4gPGRvdWdtQG9zZi5vcmc+ +=yaR9 +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1023/163751F5 1997/08/18 Dean Gaudet + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3a + +mQCNAzP30QgAAAED/1k8hPKsJj8Il/TfhP1JIRGwnXuzfQ/etv+MZJMzeNeKa8OX +Kw0d4e1S/KdJ+AZwWQp3ZMDoX2ghZ79X4DDDLEAc/Fmy0Gg8t89CP+xJk7b4EHjk +F7HX69BRJp3On4aRTXRND3WviqEmn5ppzbBkTenF9WWudLRbqrc4NnoWN1H1AAUR +tCBEZWFuIEdhdWRldCA8ZGdhdWRldEBhcmN0aWMub3JnPokAlQMFEDP30Qm3ODZ6 +FjdR9QEB9VQD/0+zumFj1zzYZ1+bS9Az36gijDUb8rlEVf/lBShx4VEvha8fsRRy +vkwnmJyupYvGtrSIYAwB0VK+GZPZa7XfZvUCM83AZY9vGpE0LwW2Vcz9kWZdJ0t+ +B7zJElmBUrmj9aW6ICmSNbOBwVo1Y7hg6lPSFFMOOECFpT1WuTXXYpNA +=KWcF +-----END PGP PUBLIC KEY BLOCK----- + + +Type bits/keyID Date User ID +pub 768/8F394E3D 1995/08/08 Martin Kraemer + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6 + +mQBtAzAnjA8AAAEDAKlpkRzZ7c4yDdVnW9fMHMXrMJ8gQ+UIzr1xt2+y7Sv71Nv9 +GfUuTeCWdOoynFUXvvBjyCuEIZ426s9UfrnWv94VppoS8sjFgLYkRIAhZiDMHYp0 +j8i1/f82KtdYjzlOPQAFEbQqTWFydGluIEtyYWVtZXIgPE1hcnRpbi5LcmFlbWVy +QE1jaC5TTkkuRGU+ +=hcsR +-----END PGP PUBLIC KEY BLOCK----- + + +Type Bits/KeyID Date User ID +pub 1024/EC140B81 1997/04/10 Dirk-Willem van Gulik + Dirk-Willem van Gulik + Dirk-Willem van Gulik + Dirk-Willem van Gulik + Dirk-Willem van Gulik + Dirk-Willem van Gulik + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3i + +mQCNAzNNOsMAAAEEAJmwazRhNJB4mQkvp0rrxLkeOAxR9fGBXgJNa6HHdLv7YHwx +mwMorHYDCAMypO1yuznNTaMVT1z3cS+yqhOkTVxwNI1mxW6Zts1kOJB9pWuU33sk +sUuCkLHXMgyvP9cms6gcYgB5g3UP6M/aQ4T017+Gk/7crlH87DGmPZbsFAuBAAUR +tCxEaXJrLVdpbGxlbSB2YW4gR3VsaWsgPGRpcmt4QHdlYndlYXZpbmcub3JnPokA +lQMFEDRZ5+0xpj2W7BQLgQEB/KAD/1xniFNLHp+jxIVrEL6HcI06QZUYPvRuarWq +3aI2gdeXej59Ry96MOo2MU3MsuQ+wW+6gEJAuyCp2jyYfzF/8winNcFWc738s/hX +fRYCJe4bvtMcnhBV7GAlTgyw00fcrnaJaQ811+QwKnZvXXWb+QuoXC4ddTon25w4 +XHLjtDZHtCxEaXJrLVdpbGxlbSB2YW4gR3VsaWsgPERpcmsudmFuR3VsaWtAanJj +Lml0PokAlQMFEDNNOsMxpj2W7BQLgQEBzW8EAItAEaeuIzPIVlKOk1LnHlYc4FyW +aiNJC2+rRmftYu2bIp/JFuXu3xC0U0byyHu0p+Y1pcAnt2YrqmYUfM0d2cx1b4+L +8RQR4SGKhq9jWKS3icfKoyMnGiD2CeI8/Xx8V6b8Xg0QqsdlS0kz//qGCDWMz0vi +oxzasVEvFjqAse03tCtEaXJrLVdpbGxlbSB2YW4gR3VsaWsgPGRpcmt4QHdlYndl +YXZpbmcubmw+iQCVAwUQNFnn1DGmPZbsFAuBAQE0vAP/aOb/rXsE256tpi0+CRp6 +cd9b1oBmw894UK+Cf4DeNHWehPWJog4y0eNFUcAMdLIdubDzc6Kfxw5QyJt2EAXr +05XuJ2DJdG24S/aPzGq+6VzL7Nq7pylXuhrACTgeesaceEpUd/NeOCOyzNR7i8qM +zbGFtU7fH1ipfJjN6fXLo5K0JERpcmstV2lsbGVtIHZhbiBHdWxpayA8ZGlya3hA +ZGRzLm5sPokAlQMFEDRZ58Expj2W7BQLgQEBGRwD/jdUjCJXFcAbjx3Y2pWUkR7C +hwJTohM2TvhFp80Ffbhh1xT961XGuHL5l41fRAIg9FEHjQKNVfXeisLH68Qh73cF +5xuNE6c1x1VSqfDLl9fXZ6TA35qt0G599T67jmVai4F/LjHWDI1O6UvPRuZE3O7m +eRaCfbPLAJ1ztFujtS3btClEaXJrLVdpbGxlbSB2YW4gR3VsaWsgPGRpcmt4QGJp +Z2Zvb3QuY29tPokAlQMFEDRZ56Qxpj2W7BQLgQEBvOED/1LhhPP5OkeCCEMVnmyZ +jZexzv6XOH2I5qH0iuozsI987sSK+zfv8O0wEBwjUOQqBuzlvjKImYQ/oqR89egQ +AinPc4z1b3kgeGyqrmtea6ScmpKufcWUBbhH0qsXF41eU3ArKY4kB9znV+/PacCe +VrOD8roFaxIDZ2nW9FS0mriOtC5EaXJrLVdpbGxlbSB2YW4gR3VsaWsgPGRpcmt4 +QHRlY2hub2xvZ2lzdC5jb20+iQCVAwUQNFnnjTGmPZbsFAuBAQEaHwP/Q2Rs6MIu +z8all/xildFOPfRAX73InwBeInr1O4UU4l6yWRvuLkg+m6O8eJSHo21SNZBCu9gM +FoQsd0jVOitUr8+w2WkypBlJo5wl1nCw/1sLU4AxtBb0jyADvJzxFCeje/FkxEvs +6Y3eLxpJRBylbg6KFOsmSY46DyGc49B6cZo= +=xUw/ +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits KeyID Created Expires Algorithm Use +sec+ 1024 0xF08E012A 1998-02-19 ---------- DSS Sign & Encrypt +sub 2048 0xD8F8125A 1998-02-19 ---------- Diffie-Hellman +uid Dean Gaudet +uid Dean Gaudet +uid Dean Gaudet + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPfreeware 5.0i for non-commercial use + +mQGiBDTsCJkRBADJmDUiJL0xUaxg0yw7+VqqFUL6sjWxZeZ7kQZs4dyN3R1ilBUG +KmOXE6qSfb6Pi0qEmgCz1K7g1KaglMRrpANY4h1CjziEVmTH5s3ocxe77w2uaou1 +gHJERIqQuC4/z0DwFqq61ZVf5dUQTD8OmfOwG4pFs51Si9WS03ueVEFQFwCg/9Z2 +j6UzCLyUABpWeV1v4m0w82kEAK96GyKDcT20TymKJnMKuwya+ZwqrULH3Sdi2Mwi +1GOH7aomG2fK4D2yxWx5xTiYhmYNnRoopgu/Kv5a4x43tOKS3zeADMnHIw9dMSn9 +4Kba8vfKbZnlOgt9veV+iWZv7N2aS2z7w/i53Y6LAlV1hAIMvGJ3zLfmShZs0LDI +Ya18A/wNcdJazUk9mLGIoycCYOk5YhWL9sCaCBdmdfDPu++rLnqROSWkmfYkOTt+ +pG9SPnvv3XrX/SEwM8gYfpbZwrFDJFI9W63lc9hdSosFD+8xiRl6h2gKRwWvc1Ry +xIt3+gUrZxovNxBOv98BoSf/j3lkldU+ZjDGlCplRHSndxlN/bQgRGVhbiBHYXVk +ZXQgPGRnYXVkZXRAYXJjdGljLm9yZz6JAEsEEBECAAsFAjTsCJkECwMBAgAKCRB9 +bb/R8I4BKqqzAKDc/4H9iOXJxVE0yCEHeTQ2gAHfhgCg7VSq7eNhiJhBgblQav/R +XOhaHj20JkRlYW4gR2F1ZGV0IDxkZ2F1ZGV0LWRqZzIwQGFyY3RpYy5vcmc+iQBL +BBARAgALBQI07AjSBAsDAQIACgkQfW2/0fCOASoWOACfb+8OVvy6FCqN2MxdCqp6 +gffNbYgAoOxlTa4NjCUUO9dfLFFYpDfGrRy7tCBEZWFuIEdhdWRldCA8ZGdhdWRl +dEBhcGFjaGUub3JnPokASwQQEQIACwUCNOwI/gQLAwECAAoJEH1tv9HwjgEqiC8A +oJDu1HTuGOfChFSJJ31XvV8tnlo5AKCFceck4veIMP8pDC0f5UBGGC3mZLkCDQQ0 +7AiZEAgA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AH +xstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8 +dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0 +neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6Md +GGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1m +pF1Bn5x8vYlLIhkmuquiXsNV6TILOwACAggAhb3cBmR67H4+9Rj4FeTwJ8kflX6I +pp2AeXXZiffiPVBv5cGzGn2RkGPAZqbp2AkrCb4TrJH//1GPdR8VmPeEGsm6u0uT +0M404l/4IW1FFQ4JBpTENPn4NYBHkKBNkPcls/ip0lSjlmLGVQVOtDOaFD7n44xV +hT4WpptCripg/5kymDmK9c8hv6rPUvNoVrDdWR4//MCvNAZvGq2bZGdFTyd5Tn6D +AmwbvL/UwgiDnm95qBBfCZtmGkkFaoOePtBevWFaviFZM2pErPRcjY8A/1cZsycj +JPMFYqBKGDIk76ulDSjU0Q8dqhCEDf0o2oQEg6msjDtetVFEDw9yJe0AGIkAPwMF +GDTsCJl9bb/R8I4BKhECBKgAoNRtRaRMdYNwajSO7056eKazCGSDAKDShamaRjAe +ThQ1KefmJKyzfcosZQ== +=25Cv +-----END PGP PUBLIC KEY BLOCK----- diff --git a/APACHE_1_3b7/LICENSE b/APACHE_1_3b7/LICENSE new file mode 100644 index 0000000000..edb90e071f --- /dev/null +++ b/APACHE_1_3b7/LICENSE @@ -0,0 +1,59 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + + + diff --git a/APACHE_1_3b7/Makefile.tmpl b/APACHE_1_3b7/Makefile.tmpl new file mode 100644 index 0000000000..11151410ee --- /dev/null +++ b/APACHE_1_3b7/Makefile.tmpl @@ -0,0 +1,471 @@ +## ==================================================================== +## Copyright (c) 1998 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 . +## + +## +## Makefile -- Apache Autoconf-style Interface (APACI) +## top-level control Makefile for out-of-the-box +## build and installation procedure. +## +## Written by Ralf S. Engelschall +## + +## ================================================================== +## Options +## ================================================================== + +# safe environment +SHELL = /bin/sh + +# paths to the source tree parts +TOP = @TOP@ +SRC = @SRC@ +MKF = @MKF@ +AUX = @AUX@ + +# build tools +CP = cp +LN = ln +RM = rm -f +TAR = tar +UMASK = umask +MKDIR = $(TOP)/$(AUX)/mkdir.sh +INSTALL = $(TOP)/$(AUX)/install.sh -c +INSTALL_PROGRAM = $(INSTALL) -s -m 755 +INSTALL_SCRIPT = $(INSTALL) -m 755 +INSTALL_DATA = $(INSTALL) -m 644 +PERL = @PERL@ + +# installation root +# (overrideable by package maintainers for +# rolling packages without bristling the system) +root = + +# installation paths +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +mandir = @mandir@ +sysconfdir = @sysconfdir@ +datadir = @datadir@ +includedir = @includedir@ +localstatedir = @localstatedir@ +runtimedir = @runtimedir@ +logfiledir = @logfiledir@ +proxycachedir = @proxycachedir@ + +libexecdir_relative = @libexecdir_relative@ + +# suexec details (optional) +suexec = @suexec@ +suexec_caller = @suexec_caller@ +suexec_userdir = @suexec_userdir@ +suexec_uidmin = @suexec_uidmin@ +suexec_gidmin = @suexec_gidmin@ +suexec_safepath = @suexec_safepath@ + +# usage of src/support stuff +build-support = @build_support@ +install-support = @install_support@ +clean-support = @clean_support@ +distclean-support = @distclean_support@ + +# forwarding arguments +MFWD = root=$(root) + +## ================================================================== +## Targets +## ================================================================== + +# default target +all: build + +## ------------------------------------------------------------------ +## Build Target +## ------------------------------------------------------------------ + +# build the package +build: + @echo "===> $(SRC)" + @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) build-std $(build-support) + @touch $(TOP)/$(SRC)/.apaci.build.ok + @echo "<=== $(SRC)" + +# build the standard stuff +build-std: + @cd $(TOP)/$(SRC); $(MAKE) $(MFLAGS) SDP=$(SRC)/ all + +# build the additional support stuff +build-support: + @echo "===> $(SRC)/support"; \ + cd $(TOP)/$(SRC)/support; $(MAKE) $(MFLAGS) all; \ + if [ ".$(suexec)" = .1 ]; then \ + $(MAKE) $(MFLAGS) \ + EXTRA_CFLAGS='\ + -DHTTPD_USER=\"$(suexec_caller)\" \ + -DUID_MIN=$(suexec_uidmin) \ + -DGID_MIN=$(suexec_gidmin) \ + -DUSERDIR_SUFFIX=\"$(suexec_userdir)\" \ + -DLOG_EXEC=\"$(logfiledir)/suexec_log\" \ + -DDOC_ROOT=\"$(datadir)/htdocs\" \ + -DSAFE_PATH=\"$(suexec_safepath)\" \ + ' \ + suexec; \ + fi; \ + echo "<=== $(SRC)/support" + +## ------------------------------------------------------------------ +## Installation Targets +## ------------------------------------------------------------------ + +# the install target for installing the complete Apache +# package. This is implemented by running subtargets for the +# separate parts of the installation process. +install: + @if [ ! -f $(TOP)/$(SRC)/.apaci.build.ok ]; then \ + $(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) build; \ + fi + @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) \ + install-mktree install-programs $(install-support) \ + install-include install-data install-config + -@$(RM) $(SRC)/.apaci.install.tmp + -@$(RM) $(SRC)/.apaci.install.conf + -@if [ ".$(QUIET)" != .1 ]; then \ + echo "+--------------------------------------------------------+"; \ + echo "| You now have successfully built and installed the |"; \ + echo "| Apache 1.3 HTTP server. To verify that Apache actually |"; \ + echo "| works correctly you now should first check the |"; \ + echo "| (initially created or preserved) configuration files |"; \ + echo "| |"; \ + echo "| $(sysconfdir)/{httpd,access,srm}.conf"; \ + echo "| |"; \ + echo "| and then you should be able to immediately fire up |"; \ + echo "| Apache the first time by running: |"; \ + echo "| |"; \ + echo "| $(sbindir)/apachectl start"; \ + echo "| |"; \ + echo "| Thanks for using Apache. The Apache Group |"; \ + echo "| http://www.apache.org/ |"; \ + echo "+--------------------------------------------------------+"; \ + fi + +# the non-verbose variant for package maintainers +install-quiet: + @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) QUIET=1 install + +# create the installation tree +install-mktree: + @echo "===> [mktree: Creating Apache installation tree]" + $(MKDIR) $(root)$(bindir) + $(MKDIR) $(root)$(sbindir) + $(MKDIR) $(root)$(libexecdir) + $(MKDIR) $(root)$(mandir)/man1 + $(MKDIR) $(root)$(mandir)/man8 + $(MKDIR) $(root)$(sysconfdir) + $(MKDIR) $(root)$(datadir)/htdocs + $(MKDIR) $(root)$(datadir)/icons + $(MKDIR) $(root)$(datadir)/cgi-bin + $(MKDIR) $(root)$(includedir) + $(MKDIR) $(root)$(runtimedir) + $(MKDIR) $(root)$(logfiledir) + $(MKDIR) $(root)$(proxycachedir) + @echo "<=== [mktree]" + +# install the server program and optionally corresponding +# shared object files. +install-programs: + @echo "===> [programs: Installing Apache httpd program and shared objects]" + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/httpd $(root)$(sbindir)/httpd + -@if [ ".`grep 'SUBTARGET=target_shared' $(TOP)/$(SRC)/Makefile`" != . ]; then \ + echo "$(INSTALL_PROGRAM) $(TOP)/$(SRC)/libhttpd.ep $(root)$(libexecdir)/libhttpd.ep"; \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/libhttpd.ep $(root)$(libexecdir)/libhttpd.ep; \ + echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/libhttpd.so $(root)$(libexecdir)/libhttpd.so"; \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/libhttpd.so $(root)$(libexecdir)/libhttpd.so; \ + SHLIB_SUFFIX_LIST="`grep '^SHLIB_SUFFIX_LIST=' $(TOP)/$(SRC)/Makefile | sed -e 's:^.*=::'`"; \ + if [ ".$${SHLIB_SUFFIX_LIST}" != . ]; then \ + echo "$(RM) $(libexecdir)/libhttpd.so.*"; \ + $(RM) $(libexecdir)/libhttpd.so.*; \ + for suffix in $${SHLIB_SUFFIX_LIST} ""; do \ + [ ".$${suffix}" = . ] && continue; \ + echo "$(LN) $(root)$(libexecdir)/libhttpd.so $(root)$(libexecdir)/libhttpd.so.$${suffix}"; \ + $(LN) $(root)$(libexecdir)/libhttpd.so $(root)$(libexecdir)/libhttpd.so.$${suffix}; \ + done; \ + fi; \ + fi + $(INSTALL_DATA) $(TOP)/$(SRC)/support/httpd.8 $(root)$(mandir)/man8/httpd.8 + -@$(RM) $(SRC)/.apaci.install.conf; touch $(SRC)/.apaci.install.conf + -@if [ ".`grep '^[ ]*SharedModule' $(TOP)/$(SRC)/Configuration.apaci`" != . ]; then \ + for mod in `egrep '^[ ]*SharedModule' $(TOP)/$(SRC)/Configuration.apaci |\ + sed -e 's/^[ ]*SharedModule[ ]*//'`; do \ + file=`echo $${mod} | sed -e 's;^.*/\([^/]*\);\1;'`; \ + echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/$${mod} $(root)$(libexecdir)/$${file}"; \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/$${mod} $(root)$(libexecdir)/$${file}; \ + name=`$(TOP)/$(AUX)/fmn.sh $(TOP)/$(SRC)/$${mod}`; \ + echo dummy | awk '{ printf("LoadModule %-18s %s\n", modname, modpath); }' \ + modname="$${name}" modpath="$(libexecdir_relative)$${file}" >>$(SRC)/.apaci.install.conf; \ + done; \ + echo "" >>$(SRC)/.apaci.install.conf; \ + echo "# Reconstruction of the complete module list from all available modules" >>$(SRC)/.apaci.install.conf; \ + echo "# (static and shared ones) to achieve correct module execution order." >>$(SRC)/.apaci.install.conf; \ + echo "# [WHENEVER YOU CHANGE THE LOADMODULE SECTION ABOVE UPDATE THIS, TOO]" >>$(SRC)/.apaci.install.conf; \ + echo "ClearModuleList" >>$(SRC)/.apaci.install.conf; \ + egrep "^[ ]*(Add|Shared)Module" $(SRC)/Configuration.apaci |\ + sed -e 's:SharedModule:AddModule:' \ + -e 's:modules/[^/]*/::' \ + -e 's:[ ]lib: mod_:' \ + -e 's:\.[soa]*$$:.c:' >>$(SRC)/.apaci.install.conf; \ + fi + @echo "<=== [programs]" + +# install the support programs and scripts +install-support: + @echo "===> [support: Installing Apache support programs and scripts]" + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/ab $(root)$(sbindir)/ab + $(INSTALL_DATA) $(TOP)/$(SRC)/support/ab.1 $(root)$(mandir)/man1/ab.1 + @echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/apachectl[*] $(root)$(sbindir)/apachectl"; \ + sed -e 's;PIDFILE=.*;PIDFILE=$(runtimedir)/httpd.pid;' \ + -e 's;HTTPD=.*;HTTPD=$(sbindir)/httpd;' \ + < $(TOP)/$(SRC)/support/apachectl > $(TOP)/$(SRC)/.apaci.install.tmp && \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sbindir)/apachectl + $(INSTALL_DATA) $(TOP)/$(SRC)/support/apachectl.1 $(root)$(mandir)/man1/apachectl.1 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/htpasswd $(root)$(bindir)/htpasswd + $(INSTALL_DATA) $(TOP)/$(SRC)/support/htpasswd.1 $(root)$(mandir)/man1/htpasswd.1 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/htdigest $(root)$(bindir)/htdigest + $(INSTALL_DATA) $(TOP)/$(SRC)/support/htdigest.1 $(root)$(mandir)/man1/htdigest.1 + @echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/dbmmanage[*] $(root)$(bindir)/dbmmanage"; \ + sed -e 's;^#!/.*;#!$(PERL);' \ + < $(TOP)/$(SRC)/support/dbmmanage > $(TOP)/$(SRC)/.apaci.install.tmp && \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(bindir)/dbmmanage + $(INSTALL_DATA) $(TOP)/$(SRC)/support/dbmmanage.1 $(root)$(mandir)/man1/dbmmanage.1 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/logresolve $(root)$(sbindir)/logresolve + $(INSTALL_DATA) $(TOP)/$(SRC)/support/logresolve.8 $(root)$(mandir)/man8/logresolve.8 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/rotatelogs $(root)$(sbindir)/rotatelogs + $(INSTALL_DATA) $(TOP)/$(SRC)/support/rotatelogs.8 $(root)$(mandir)/man8/rotatelogs.8 + @echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/apxs[*] $(root)$(sbindir)/apxs"; \ + sed -e 's;^#!/.*;#!$(PERL);' \ + -e 's;\@prefix\@;$(prefix);' \ + -e 's;\@sbindir\@;$(sbindir);' \ + -e 's;\@libexecdir\@;$(libexecdir);' \ + -e 's;\@includedir\@;$(includedir);' \ + -e 's;\@sysconfdir\@;$(sysconfdir);' \ + < $(TOP)/$(SRC)/support/apxs > $(TOP)/$(SRC)/.apaci.install.tmp && \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sbindir)/apxs + $(INSTALL_DATA) $(TOP)/$(SRC)/support/apxs.8 $(root)$(mandir)/man8/apxs.8 + -@if [ ".$(suexec)" = .1 ]; then \ + echo "$(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/suexec $(root)$(sbindir)/suexec"; \ + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/suexec $(root)$(sbindir)/suexec; \ + echo "chown root $(sbindir)/suexec"; \ + chown root $(sbindir)/suexec; \ + echo "chmod 4711 $(sbindir)/suexec"; \ + chmod 4711 $(sbindir)/suexec; \ + echo "$(INSTALL_DATA) $(TOP)/$(SRC)/support/suexec.8 $(root)$(mandir)/man8/suexec.8"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/support/suexec.8 $(root)$(mandir)/man8/suexec.8; \ + fi + @echo "<=== [support]" + +# install the Apache C header files +install-include: + @echo "===> [include: Installing Apache C header files]" + $(UMASK) 022; $(CP) $(TOP)/$(SRC)/include/*.h $(root)$(includedir)/ + @osdir=`grep '^OSDIR=' $(TOP)/$(SRC)/Makefile.config | sed -e 's:^OSDIR=.*/os:os:'`; \ + echo "$(UMASK) 022; $(CP) $(TOP)/$(SRC)/$${osdir}/os.h $(includedir)/"; \ + $(UMASK) 022; $(CP) $(TOP)/$(SRC)/$${osdir}/os.h $(root)$(includedir)/ + @echo "<=== [include]" + +# create an initial document root containing the Apache manual, +# icons and distributed CGI scripts. +install-data: + @echo "===> [data: Installing initial data files]" + -@if [ -f $(root)$(datadir)/htdocs/index.html ]; then \ + echo "[PRESERVING EXISTING DATA SUBDIR: $(root)$(datadir)/htdocs/]"; \ + else \ + echo "Copying tree $(TOP)/htdocs/ -> $(root)$(datadir)/htdocs/"; \ + (cd $(TOP)/htdocs/ && $(TAR) cf - *) |\ + (cd $(root)$(datadir)/htdocs/ && $(TAR) xf -); \ + find $(root)$(datadir)/htdocs/ -type d -exec chmod a+rx {} \; ; \ + find $(root)$(datadir)/htdocs/ -type f -exec chmod a+r {} \; ; \ + fi + -@if [ -f $(root)$(datadir)/cgi-bin/printenv ]; then \ + echo "[PRESERVING EXISTING DATA SUBDIR: $(root)$(datadir)/cgi-bin/]"; \ + else \ + echo "Copying tree $(TOP)/cgi-bin/ -> $(root)$(datadir)/cgi-bin/"; \ + (cd $(TOP)/cgi-bin/ && $(TAR) cf - *) |\ + (cd $(root)$(datadir)/cgi-bin/ && $(TAR) xf -); \ + find $(root)$(datadir)/cgi-bin/ -type d -exec chmod a+rx {} \; ; \ + find $(root)$(datadir)/cgi-bin/ -type f -exec chmod a+r {} \; ; \ + fi + @echo "Copying tree $(TOP)/icons/ -> $(root)$(datadir)/icons/"; \ + (cd $(TOP)/icons/ && $(TAR) cf - *) |\ + (cd $(root)$(datadir)/icons/ && $(TAR) xf -); \ + find $(root)$(datadir)/icons/ -type d -exec chmod a+rx {} \; ;\ + find $(root)$(datadir)/icons/ -type f -exec chmod a+r {} \; + @echo "<=== [data]" + +# create the initial configuration by providing default files +# and initial config files while preserving existing ones. +install-config: + @echo "===> [config: Installing Apache configuration files]" + -@for conf in httpd.conf access.conf srm.conf; do \ + (echo "##"; \ + echo "## $${conf} -- Apache HTTP server configuration file"; \ + echo "##"; \ + echo ""; \ + cat $(TOP)/conf/$${conf}-dist ) |\ + sed -e '/# LoadModule/r $(TOP)/$(SRC)/.apaci.install.conf' \ + -e 's;@@ServerRoot@@/htdocs;$(datadir)/htdocs;' \ + -e 's;@@ServerRoot@@/htdocs;$(datadir)/htdocs;' \ + -e 's;@@ServerRoot@@/icons;$(datadir)/icons;' \ + -e 's;@@ServerRoot@@/cgi-bin;$(datadir)/cgi-bin;' \ + -e 's;@@ServerRoot@@/proxy;$(proxycachedir);' \ + -e 's;@@ServerRoot@@;$(prefix);' \ + -e 's;logs/accept.lock;$(runtimedir)/httpd.lock;' \ + -e 's;logs/apache_runtime_status;$(runtimedir)/httpd.scoreboard;' \ + -e 's;logs/httpd.pid;$(runtimedir)/httpd.pid;' \ + -e 's;logs/access_log;$(logfiledir)/access_log;' \ + -e 's;logs/error_log;$(logfiledir)/error_log;' \ + -e 's;logs/referer_log;$(logfiledir)/referer_log;' \ + -e 's;logs/agent_log;$(logfiledir)/agent_log;' \ + -e 's;conf/magic;$(sysconfdir)/magic;' \ + > $(TOP)/$(SRC)/.apaci.install.tmp && \ + echo "$(INSTALL_DATA) $(TOP)/conf/$${conf}-dist[*] $(root)$(sysconfdir)/$${conf}.default"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sysconfdir)/$${conf}.default; \ + if [ ! -f "$(root)$(sysconfdir)/$${conf}" ]; then \ + echo "$(INSTALL_DATA) $(TOP)/conf/$${conf}-dist[*] $(root)$(sysconfdir)/$${conf}"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sysconfdir)/$${conf}; \ + else \ + echo "[PRESERVING EXISTING CONFIG FILE: $(root)$(sysconfdir)/$${conf}]"; \ + fi; \ + done + -@for conf in mime.types magic; do \ + echo "$(INSTALL_DATA) $(TOP)/conf/$${conf} $(root)$(sysconfdir)/$${conf}.default"; \ + $(INSTALL_DATA) $(TOP)/conf/$${conf} $(root)$(sysconfdir)/$${conf}.default; \ + if [ ! -f "$(root)$(sysconfdir)/$${conf}" ]; then \ + echo "$(INSTALL_DATA) $(TOP)/conf/$${conf} $(root)$(sysconfdir)/$${conf}"; \ + $(INSTALL_DATA) $(TOP)/conf/$${conf} $(root)$(sysconfdir)/$${conf}; \ + else \ + echo "[PRESERVING EXISTING CONFIG FILE: $(root)$(sysconfdir)/$${conf}]"; \ + fi; \ + done + @echo "<=== [config]" + + +## ------------------------------------------------------------------ +## Cleanup Targets +## ------------------------------------------------------------------ + +# cleanup the source tree by removing anything which was +# created by the build target +clean: + @echo "===> $(SRC)" + @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) clean-std $(clean-support) + @echo "<=== $(SRC)" + @$(RM) $(TOP)/$(SRC)/.apaci.build.ok + +# clean the standard stuff +clean-std: + @cd $(TOP)/$(SRC); $(MAKE) $(MFLAGS) SDP=$(SRC)/ clean + +# clean additional support stuff +clean-support: + @echo "===> $(SRC)/support"; \ + cd $(TOP)/$(SRC)/support; $(MAKE) $(MFLAGS) clean; \ + if [ ".$(suexec)" = .1 ]; then \ + echo "$(RM) suexec"; \ + $(RM) suexec; \ + fi; \ + echo "<=== $(SRC)/support" + +# cleanup the source tree by removing anything which was +# created by the configure step and the build target. +# When --shadow is used we just remove the complete shadow tree. +distclean: + @if [ ".$(SRC)" = .src ]; then \ + $(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) distclean-normal; \ + else \ + $(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) distclean-shadow; \ + fi + +distclean-normal: + @echo "===> $(SRC)" + @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) distclean-std $(distclean-support) + @echo "<=== $(SRC)" + -$(RM) $(SRC)/Configuration.apaci + -$(RM) $(SRC)/apaci + @$(RM) $(SRC)/.apaci.build.ok + -$(RM) Makefile + +# clean the standard stuff +distclean-std: + @cd $(TOP)/$(SRC); $(MAKE) $(MFLAGS) SDP=$(SRC)/ distclean + +distclean-support: + @echo "===> $(SRC)/support"; \ + cd $(TOP)/$(SRC)/support; $(MAKE) $(MFLAGS) distclean; \ + if [ ".$(suexec)" = .1 ]; then \ + echo "$(RM) suexec"; \ + $(RM) suexec; \ + fi; \ + echo "<=== $(SRC)/support" + +distclean-shadow: + $(RM) -r $(SRC) + $(RM) $(MKF) + -@if [ ".`ls $(TOP)/src.* 2>/dev/null`" = . ]; then \ + echo "$(RM) Makefile"; \ + $(RM) Makefile; \ + fi + diff --git a/APACHE_1_3b7/README b/APACHE_1_3b7/README new file mode 100644 index 0000000000..604b8dff9c --- /dev/null +++ b/APACHE_1_3b7/README @@ -0,0 +1,63 @@ + + Apache + Version 1.3 (and up) + + What is it? + ----------- + + Apache is an HTTP server designed as a plug-in replacement for + the NCSA server version 1.3 (or 1.4). It fixes numerous bugs in + the NCSA server and includes many frequently requested new + features, and has an API which allows it to be extended to meet + users' needs more easily. + + The Latest Version + ------------------ + + Details of the latest version can be found on the Apache HTTP + server project page under http://www.apache.org/. + + Documentation + ------------- + + The documentation available as of the date of this release is + also included, in HTML format, in the htdocs/manual/ directory. + For the most up-to-date documentation can be found on + http://www.apache.org/docs/. + + Installation + ------------ + + From Apache version 1.3 and up you have two possibilities to + build and install the Apache package: The old commonly known + but manual way from Apache 1.2 and below and the new + out-of-the-box way through the new Apache Autoconf-style + Interface (APACI). For detailed instructions see the file + INSTALL in this directory. + + Licensing + --------- + + Please see the file called LICENSE. + + Acknowledgments + ---------------- + + We wish to acknowledge the following copyrighted works that + make up portions of the Apache software: + + Portions of this software were developed at the National Center + for Supercomputing Applications (NCSA) at the University of + Illinois at Urbana-Champaign. + + This software contains code derived from the RSA Data Security + Inc. MD5 Message-Digest Algorithm, including various + modifications by Spyglass Inc., Carnegie Mellon University, and + Bell Communications Research, Inc (Bellcore). + + This package contains software written and copyrighted by Henry + Spencer. Please see the file called src/regex/COPYRIGHT. + + The NT port was started with code provided to the Apache Group + by Ambarish Malpani of ValiCert, Inc. (http://www.valicert.com/). + diff --git a/APACHE_1_3b7/README.NT b/APACHE_1_3b7/README.NT new file mode 100644 index 0000000000..0b5447b91e --- /dev/null +++ b/APACHE_1_3b7/README.NT @@ -0,0 +1,231 @@ + Apache for Windows + Version 1.3 (and up) + +What is it? +----------- + +Apache is an HTTP server, originally designed for Unix systems. This +is the first release of Apache for Windows systems. Like the Unix +version, it includes many frequently requested new features, and has +an API which allows it to be extended to meet users' needs more +easily. It also allows ISAPI extensions. + +Documentation +------------- + +The documentation available as of the date of this release is also +included, in HTML format, in the htdocs/manual/ directory. For the +most up-to-date documentation, visit us on the WWW, at +http://www.apache.org/. For Windows specific information, see +http://www.apache.org/docs/windows.html. + +WARNING +------- + +Apache on NT has not yet been optimized for performance. Apache still +performs best, and is most reliable on Unix platforms. Over time we +will improve NT performance. Folks doing comparative reviews of +webserver performance are asked to compare against Apache on a Unix +platform such as Solaris, FreeBSD, or Linux. + +Changes for the Windows version +------------------------------- + +1. It is multithreaded + +2. It can run as a service (run apache -i to install the service) + or as a regular program (run apache -s to avoid waiting for + the program to hook up to the Service Manager). On Windows 95 + it runs as a regular program. + +3. There is only ever one child process for handling requests. + However for fault tolerance, if this process dies, another one + takes its place. Also after dealing with a certain number of + requests, each process voluntarily exits, to clean up any resources + it might have forgotten to free up. + +By default Apache uses the directory \Apache for the ServerRoot ON THE +DRIVE WHERE THE EXECUTABLE EXISTS. This can be changed with the -d +command line argument. + +There are a couple of new directives: + +ThreadsPerChild - Number of threads to use to handle requests +ExcessRequestsPerChild - Number of additional requests a server responds + to, after it decides to exit (this is not + currently used) + +Compilation +----------- + +If you have downloaded the source code you will need to compile +it. This requires Microsoft Visual C++ version 5.0 or higher. + +To compile Apache, run the command + + nmake -f Makefile.nt _apacher + +in the src directory. To install Apache to the \Apache directory, run + + nmake -f Makefile.nt installr + +To specify a different install directory, use + + nmake -f Makefile.nt installr INSTDIR=c:\mydir + +You can also build and install debug versions of Apache, with the +targets "_apached" and "installd". + +Make sure that before you run "nmake" that you've run VCVARS32.BAT +so that your environment is configured to run nmake from the command +line. + +To build Apache within MSVC, you will need to build the following +projects in this order. Make sure that you build the same +configuration (i.e. Debug or Release) for all of the various projects. + + regex/Makefile.dsp + ap/ap.dsp + os/win32/ApacheOS.dsp + src/ApacheCore.dsp + src/Apache.dsp + +Additional modules can also be built using project files in the os/win32 +directory. + +Installing a Binary Release +--------------------------- + +Since this file is installed as part of the install process, you have +probably already figured out how to install the binary. But for +reference, here are the instructions: + +Run the Apache distribution file. This will ask for a location to +install Apache into (the default is \Program Files\Apache +Group\Apache), for a start menu name (default is Apache Web Server) +and for a choice of installations. The Typical installation installs +everything except the source code. The Minimum installations does not +install the manuals either. Choose Custom install if you want to +install the source code. + +After installation is completed, there are three new items on the +start menu. On NT you should run the "Install Apache as Service" +program, then start Apache as a normal service. On Windows 95 or if +you do not want to run Apache as a service, click on the "Apache +Server" option. This will start Apache running in a console window, +where it will print its version number, then wait to start serving +requests. The third start menu option accessing the manual, if it was +installed. If it was not installed, you can access the Apache manual +at the URL http://www.apache.org/. + +Once Apache is running (either in a console window, or as a service), +if you have not edited the configuration files, it will be listening +on port 80, so you can connect to it at this URL: + + http://localhost/ + +To configure Apache, go into the directory where you installed it and +edit the "httpd.conf" file in the "conf" directory. + +Running Apache +-------------- + +Apache can run as either a service (NT only) or a regular executable. + +To run as an executable, simply run apache.exe from the command +line. This will print the version number, then wait to serve +requests. If the server root is a directory other than \Apache, use +the -d option to give the correct server root, or store it in the +registry (see below). + +To stop Apache, press Control-C to stop it running. Note +that there may be a delay between typing the command line and Apache +being ready to accept requests as it checks the service manager. Use +the -s option to prevent this delay. + +When Apache starts it will look at the registry key + + HKEY_LOCAL_MACHINE\Software\Apache Group\Apache\1.3 beta\ServerRoot + +to find the server root, unless specified by the -d command line +flag. The correct server root is stored in this key by the binary +installation, or when Apache is run with the -i option. + +To install Apache as a service on NT and set the server root registry +key, run + + apache -i -d serverroot + +This will store the value of "serverroot" into the Apache ServerRoot +registry key, as above. Note that this can be used on both Windows NT +and Windows 95, however it will not install a service on 95. + +On NT you can now start the Apache service within the service manager +(Control Panel, Services), and set it to start automatically at boot +time if required. You can also stop Apache from the manager. + +To remove the Apache service, run + + apache -u + +Uninstalling Apache +------------------- + +If you installed a binary release, you can uninstall Apache using the +normal method of removing programs (Start menu, Control Panel, +Add/Remove Programs). You may have to remove the directory manually +because of the configuration files. + +If you installed a source release, you should delete the directory +where you installed Apache. You might also want to delete the registry +key, as given above. + +Known Problems +-------------- + +- The User directive is not supported. If you run apache as a service, + you can change the user it runs as by going to + Control Panel->Services->Startup + +- suexec doesn't work + +- RFC 1413 not yet ported + +- If you have a very busy server, when a server child process exits, + any connections made to that child process that have not yet been + accepted by it are aborted. + +- Problem with very long running cgi scripts (their output is garbled?) + +- regex does not generate *.ih headers. + +- Multithreadng is not properly abstracted + +- htpasswd passwords are stored in plain text because Windows lacks a + crypt() function + +Licensing +--------- + +Please see the file called LICENSE. + +Acknowledgments +---------------- + +We wish to acknowledge the following copyrighted works that make up +portions of the Apache software: + +Portions of this software were developed at the National Center for +Supercomputing Applications at the University of Illinois at +Urbana-Champaign. + +This software contains code derived from the RSA Data Security Inc. MD5 +Message-Digest Algorithm, including various modifications by Spyglass Inc., +Carnegie Mellon University, and Bell Communications Research, Inc. +(Bellcore). + +This package contains software written and copyrighted by Henry Spencer. +Please see the file called src/regex/COPYRIGHT. + +The NT port was started with code provided to the Apache Group +by Ambarish Malpani of ValiCert, Inc. (www.valicert.com). diff --git a/APACHE_1_3b7/README.configure b/APACHE_1_3b7/README.configure new file mode 100644 index 0000000000..7a1b743f81 --- /dev/null +++ b/APACHE_1_3b7/README.configure @@ -0,0 +1,268 @@ + + A P A C H E C O N F I G U R A T I O N + + Apache 1.3 Autoconf-style Interface (APACI) + =========================================== + + APACI is an Autoconf-style interface for the Unix side of the Apache 1.3 + HTTP server source distribution. It is actually not GNU Autoconf-based, i.e. + the GNU Autoconf package itself is not used. Instead APACI just provides a + similar batch configuration interface and a corresponding out-of-the-box + build and installation procedure. + + The basic goal is to provide the following commonly known and expected + procedure for out-of-the-box building and installing a package like Apache: + + $ gunzip plus corresponding Makefile. and then + performs the complete build process inside this shadow tree. + + Dynamic Shared Object (DSO) support + ----------------------------------- + + Apache 1.3 supports building modules as shared objects on all major Unix + platforms (see section "Supported Platforms" in document + htdocs/manual/dso.html for details). APACI has a nice way of enabling the + building of DSO-based modules and automatically installing them: + + $ ./configure --prefix=/path/to/apache \ + --enable-module=rewrite \ + --enable-shared=rewrite + $ make + $ make install + + This builds and installs Apache with the default configuration except that + it adds the mod_rewrite module and automatically builds and installs it as a + DSO, so it is optionally available for loading under runtime. To make your + life even more easy APACI additionally inserts a corresponding `LoadModule' + line into the httpd.conf file in the installation phase. + + APACI also supports a variant of the --enable-shared option: + + $ ./configure --prefix=/path/to/apache \ + --enable-shared=max + $ make + $ make install + + This enables shared object building for the maximum of modules, i.e. all + enabled modules (--enable-module or the default set) except for mod_so + itself (the bootstrapping module for DSO support). So, to build a + full-powered Apache with maximum flexibility by building and installing most + of the modules, you can use: + + $ ./configure --prefix=/path/to/apache \ + --enable-module=most \ + --enable-shared=max + $ make + $ make install + + This first enables most of the modules (all modules except some problematic + ones like mod_auth_db which needs third party libraries not available on + every platform or mod_log_agent and mod_log_referer which are deprecated) + and then enables DSO support for all of them. This way you get all these + modules installed and you then can decide under runtime (via the + `LoadModule') directives which ones are actually used. Especially a very + useful for vendor package maintainers to provide a flexible Apache package. + + On-the-fly added additional/private module + ------------------------------------------ + + For Apache there are a lot of modules flying around on the net which solve + particular problems. For a good reference see the Apache Module Registory at + http://modules.apache.org/ and the Apache Group's contribution directory at + http://www.apache.org/dist/contrib/modules/. These modules usually come in a + file named mod_foo.c. APACI supports adding these sources on-the-fly to the + build process: + + $ ./configure --prefix=/path/to/apache \ + --add-module=/path/to/mod_foo.c + $ make + $ make install + + This automatically copies mod_foo.c to src/modules/extra/, activates it in + the configuration and builds Apache with it. A very useful way is to combine + this with the DSO support: + + $ ./configure --prefix=/path/to/apache \ + --add-module=/path/to/mod_foo.c \ + --enable-shared=foo + $ make + $ make install + + This builds and installs Apache with the default set of modules, but + additionally builds mod_foo as a DSO and adds a `LoadModule' line to the + httpd.conf file to activate it for loading under runtime. + + Apache and mod_perl + ------------------- + + The Apache/Perl integration project (http://perl.apache.org/) from Doug + MacEachern is a very powerful approach to integrate + a Perl 5 interpreter into the Apache HTTP server both for running Perl + programs and for programming Apache modules in Perl. The distribution + mod_perl-1.XX.tar.gz can be found on http://perl.apache.org/src/. Here is + how you can install Apache with mod_perl: + + $ cd mod_perl-1.11 + $ perl Makefile.PL + ReadLine support enabled + Configure mod_perl with ../apache-1.3/src ? [y] y + Shall I build httpd in ../apache-1.3/src for you? [y] y + : + $ cd ../apache-1.3 + $ LIBS='`perl $(SRCDIR)/modules/perl/ldopts`' \ + ./configure --prefix=/path/to/apache \ + --activate-module=src/modules/perl/libperl.a + $ make + $ make install + + This automatically builds and installs Apache 1.3 with mod_perl. After + additionally installing the Perl side of mod_perl via + + $ cd ../mod_perl-1.11 + $ perl Makefile.PL NO_HTTPD=1 + $ make all install + + you can fire up Apache with mod_perl enabled. + + Apache and PHP + -------------- + + The PHP language (http://www.php.net) is an HTML-embedded scripting language + which can be directly integrated into the Apache HTTP server for powerful HTML + scripting. The package can be found at http://www.php.net/download-php.php3. + + 1. How you can install Apache with a statically linked PHP: + + $ cd apache-1.3 + $ ./configure --prefix=/path/to/apache + $ cd ../php-3.0 + $ ./configure --with-apache=../apache-1.3 + $ make + $ make install + $ cd ../apache-1.3 + $ ./configure --prefix=/path/to/apache \ + --activate-module=src/modules/php3/libphp3.a + $ make + $ make install + + 2. How you can install Apache with a dynamically linked PHP: + + $ cd apache-1.3 + $ ./configure --prefix=/path/to/apache + $ cd ../php-3.0 + $ ./configure --with-shared-apache=../apache-1.3 + $ make + $ make install + $ cd ../apache-1.3 + $ ./configure --prefix=/path/to/apache \ + --activate-module=src/modules/php3/libphp3.a \ + --enable-shared=php3 + $ make + $ make install + diff --git a/APACHE_1_3b7/RULES.CVS b/APACHE_1_3b7/RULES.CVS new file mode 100644 index 0000000000..7ecbbffd4c --- /dev/null +++ b/APACHE_1_3b7/RULES.CVS @@ -0,0 +1,13 @@ +1. Don't commit several unrelated changes in one go. Each change should be +committed separately (that is, it can affect multiple files, but it should all +be part of a single change). + +2. When committing, make sure that the CVS log message explains what the +patches do and why. + +3. Don't edit CHANGES files unless there is a change which is visible to a user +of Apache. CVS logs provide a detailed history of all changes (if people follow +rule 2), so there is no need to duplicate it in CHANGES. + +4. Don't change src/Configuration.tmpl to your local configuration. Copy it to +Configuration (which is _not_ version controlled) and change that. diff --git a/APACHE_1_3b7/STATUS b/APACHE_1_3b7/STATUS new file mode 100644 index 0000000000..78b5b1a28c --- /dev/null +++ b/APACHE_1_3b7/STATUS @@ -0,0 +1,387 @@ +Apache 1.3 STATUS: + +Release: + + 1.3.0: Shoot for May 19, 1998 Release! + Brian to be RM, Jim will do announcements + + 1.3b7: 1.3.0 release candidate for May 13th + + 2.0 : In pre-alpha development, see apache-2.0 repository + +FINAL RELEASE SHOWSTOPPERS: + +WIN32 1.3 FINAL RELEASE SHOWSTOPPERS: + + * SECURITY: numerous uses of strcpy and strcat have potential + for buffer overflow, someone should rewrite or verify + they're safe + + * CGI: chdir() needs to be reinstated for CGI. + + * Child process: eliminate spawn_child() and spawn_child_err() which + are unsafe in mod_rewrite.c + + * Win95: when authentication is required for directory /foobar/, direct + access to /foobar/bletch is permitted. PR #2145 + +Documentation that needs writing: + + * Documentation for: + 1) htdocs/manual/sourcereorg.html and other files should mention + new mod_so capabilities. + 2) windows.html should be cleaned up. + + * Need a document explaining mod_rewrite/"UseCanonicalName off" based + virtualhosting. (If it exists already I can't find it easily.) + +Available Patches: + + * Wilfredo Sanchez's port to Rhapsody 5.1 for 1.2.6 - forward port to + 1.3? + <199804182347.QAA05438@scv2.apple.com> + + * Ralf's "configure generates config.status": + A tiny addition for the APACI configure script to provide an easy way + (like GNU Autoconf) to re-create the configuration + See: http://www.engelschall.com/sw/apache/ [configstatus] + Status (for 1.3.1-dev): Ralf +1, Martin +1 + + * Ralf's "...": + This patch adds a useful ... section to the core + module very similar to the existing ... sections. + The intent is to provide _LOGICAL_ conditions based on arbitrary defined + parameters. The parameters are specified on the "httpd" command line via + -D options. + See: http://www.engelschall.com/sw/apache/ [ifdefine] + Status (for 1.3.1-dev): Ralf +1 + + * Ralf's "substitute some more configuration parameters": + This patch lets APACI's configure script determine more configuration + parameters (Group, Port, ServerAdmin, ServerName) via some intelligent + tests to remove some of the classical hurdles for new users when setting + up Apache. + See: http://www.engelschall.com/sw/apache/ [substconfparam] + Status (for 1.3.1-dev): Ralf +1 + + * Ralf's "command line option to do a config syntax check only": + This patch adds a -t option to httpd which forces Apache to parse and + check its configuration files but exit immediately after this step. It + is useful for checking the syntax of the config files before doing a + restart of a running server, especially from within cron jobs. There you + must avoid a server going down just because of recently introduced + syntax error in one of the config files. + See: http://www.engelschall.com/sw/apache/ [configcheckoption] + Status (for 1.3.1-dev): Ralf +1 + + * Ralf's "linking DSO modules against possible libraries from $(LIBS)": + This patch is a first step for a more powerful and less restrictive DSO + mechanism: We allow DSO modules to be linked against other DSO libraries + when the system permits it. + See: http://www.engelschall.com/sw/apache/ [libshlib] + Status (for 1.3.1-dev): Ralf +1 + +In progress: + + * Ken's IndexFormat enhancement to mod_autoindex to allow + CustomLog-like tailoring of directory listing formats + +Needs patch: + + * get_path_info bug; ap_get_remote_host should be ap_vformatter instead. + See: + + * uri issues + - RFC2068 requires a server to recognize its own IP addr(s) in dot + notation, we do this fine if the user follows the dns-caveats + documentation... we should handle it in the case the user doesn't ever + supply a dot-notation address. + + * Amdalh UTS 2.1.2 + Message-Id: <9801211635.ZM7239@ihgp1.ih.lucent.com> + Message-Id: <199801220935.BAA13813@tiber.cisco.com> + Jim: Sounded like the version of the OS that required + the patches were WAY old and would bugger the newer + versions... Not sure if we want to do that. + + * Problems dealing with .-rooted domain names such as "twinlark." versus + "twinlark.arctic.org.". See the thread containing + Message-ID: <19980203211817.06723@deejai.mch.sni.de> for more details. + In particular this affects the correctness of the proxy and the + vhost mechanism. + + * PR#1799: we need to add a "default" or "none" handler to deal with + filenames such as foo.map.gif which aren't image maps, and shouldn't + be considered such. See discussion in + + + <34ED6E5A.29555AB8@Golux.Com> + <34EECEB1.5AD015CF@Golux.Com> + (feb98 archives) + Jim: I thought that we decided "default", although Ken + thought it ugly + Ken: I just don't like using "Add" when reverting something; not a -1 + + * proxy_*_canon routines use r->proxyreq incorrectly. See + + + * LynxOS has system-level conf.h file + Seems that Lynx has a system level conf.h file that ours overrules, + so it doesn't compile correctly. To accomodate, we would need to + rename our conf.h to something "safe". Possible choices: + + apconf.h : + applatforms.h : + apdefaults.h : + apdefines.h : + +Open issues: + + * Someone other than Dean has to do a security/correctness review on + psprintf(), bprintf(), and ap_snprintf(). In particular these routines + do lots of fun pointer manipulations and such and possibly have overflow + errors. The respective flush_funcs also need to be exercised. + o Jim's looked over the ap_snprintf() stuff (the changes that Dean + did to make thread-safe) and they look fine. + o Laura La Gassa's looked over ap_vformatter & other related code + o Martin did a "source review" as well. + o Could still use 1 or 2 more sets of eyeballs. + + * Paul would like to see a 'gdbm' option because he uses + it a lot. + + * Maybe a http_paths.h file? See + + +1: Brian, Paul, Ralf, Martin + +0: Jim (not for 1.3.0) + + * Release builds: Should we provide Configuration or not? + Should we 'make all suexec' in src/support? + +1: Brian, Jim, Ken +1 (possible suexec path issue, though) + + * root's environment is inherited by the Apache server. Jim & Ken + think we should recommend using 'env' to build the + appropriate environment. Marc and Alexei don't see any + big deal. Martin says that not every "env" has a -u flag. + + * Marc's socket options like source routing (kill them?) + Marc, Martin say Yes + + * Ken's PR#1053: an error when accessing a negotiated document + explicitly names the variant selected. Should it do so, or should + the original URI be referenced? + + * Proposed API Changes: + + - r->content_language is for backwards compatibility... with modules + that may not link any longer without some minor editing. The new + field is r->content_languages. Heck it's not even mentioned in + apache-devsite/mmn.txt when we got content_languages (note the s!). + The proposal is to remove r->content_language: + Status: Paul +1, Ralf +1, Ken +1 + + - child_exit() is redundant, it can be implemented via cleanups. It is + not "symmetric" in the sense that there is no exit API method to go + along with the init() API method. There is no need for an exit + method, there are already modules using cleanups to perform this (see + mod_mmap_static, and mod_php3 for example). The proposal is to + remove the child_exit() method and document cleanups as the method of + handling this need. + Status: Rasmus +1, Paul +1, Jim +1, + Martin +1, Ralf +1, Ken +1 + + * Should we re-enable nagle now that we're non-buffering CGIs? See + various messages from Marc in March 98. + +Win32 specific issues: + + In progress: + + * Ben's ASP work... All agree it sounds cool. + + * DDA's adding a tray application to the Windoze version for ease of + status/management. + <01BCDB29.2C04DEB0@caravan.individual.com> + <01BCDB2A.F8C09010@caravan.individual.com> + Status: Ken +1, Sameer +1, Martin +1, Ben +1 (as long as + we get a single executable) + Paul: No like Win95 specific stuff + Ken: What's W95-specific about it? + + Help: + + * SECURITY: check if the magic con/aux/nul/etc names do anything + really bad + + * chdir() for CGI scripts and mod_include #exec needs to be + re-implemented now that CreateProcess is being used. + + * process/thread model + - need dynamic thread creation/destruction, similar to + Unix process model + - can't use WaitForMultipleObjects in the same way we + do now, since that has a limit of 64(!) objects. Grr. + PR#1665 + + * some errors printed by CGIs to stderr don't end up making it + to the server log unless an extra debugging message is added + after they run? (PR#1725 indicates this may not be just Win32) + + * handle bugs that make it pop up errors on console, ie. segv + equiv? Can we do this? Need to make it robust. + + * install + - make installshield work + - config in cvs tree? + - install docs, etc.? + - location for install + + * the mutex should be critical-regions, since the current design + is creating a mess of SO calls that are unnecessary + + * we don't mmap on NT. Use TransmitFile? + + * CGIs + - docs on how they work w/scripts + - use registry to find interpreter? + - WTF is the buffering coming from? + - we don't have a way to make non-blocking files on NT! + + * performance + + * documentation: + - running the server without admin + - how CGIs work + - update README.NT + - short/long name handling + - better status page on current state of NT for users + + * http_main.c hell + - split into two files? + + * who should run the service? Who exactly is the "system account"? + + docs say: + + Localsystem is a very privileged account locally, so you shouldn't run + any shareware applications there. However, it has no network privileges + and cannot leave the machine via any NT-secured mechanism, including + file system, named pipes, DCOM, or secure RPC. + + and: + + A service that runs in the context of the LocalSystem account + inherits the security context of the SCM. It is not associated with + any logged-on user account and does not have credentials (domain + name, user name, and password) to be used for verification. This + has several implications: [... removed ...] + + + That _really_ sucks. Can we recommend running Apache as some + other user? + + + * need a crypt() of some sort. + - sources are easy; problem is export restrictions on DES + - if we don't do DES, can do md5 + + * modules that need to be made to work on win32 + - mod_example isn't multithreadreded + - mod_unique_id (needs mt changes) + - mod_auth_db.c (do we want to even try this? We should have some + db of some sort... what else can we pick from under win32?) + - mod_auth_dbm.c + - mod_info.c (PR re exporting symbols for it...) + - mod_log_agent.c + - mod_log_referer.c + - mod_mime_magic.c (needs access to mod_mime API stage...) + + * do something to disable bogus warnings + + * rfc1413.c has static storage which won't work multithreaded + + * mod_include --> exec cgi, exec cmd, etc. don't work right. + Looks like a code path that isn't run anywhere else that has + something not quite right... A PR or two on it. + + * signal type handling + - how to rotate logs from command line? + + * Currently if you double click on the conf files or the + log files you get a useless dialog offering the set of all + execuables, usually after a very long pause. Ought + to stuff .conf in the registry mapping it to text. + + * apparently either "BrowserMatch" or the "nokeepalive" variable + cause instability - see PR#1729. + +Delayed until after 1.3.0, unless someone happens to get to it: + + * Arnt Gulbrandsen 03 Apr 1998 21:28:17 +0200 + mod_usertrack.c patch: + The patch provides per-domain cookies (which I use to share user-ids + among the *.troll.no web servers) and configurable cookie names. It + also marginally increases the efficiency of Apache when the server + runs with DNS lookups turned off. + + Update: Dean found one part of the patch unacceptable, Arnt is in + the process of updating it. + + * TZ should not be dealt with specially any longer now that we have + "PassEnv". See + + Jim: IMO it's too late in the game for this... I'm + sure this would cause some strange bug reports as + people's cgi-scripts no longer work correctly + ("It worked just fine before I upgraded to 1.3.0") + unless we warn people in big nasty letters to add + PassEnv TZ to their config files "just in case" + and hope they do it :) + + * proxy module doesn't load on Win95. Why? Good question. + PR#1462. + + * In ap_bclose() there's no test that (fb->fd != -1) -- so it's + possible that it'll do something completely bogus when it's + used for read-only things. - Dean Gaudet + + * ap_pcfg_openfile doesn't use pfopen() to open the file. Consider + .htaccess parsing, if a timeout occurs the file may not be closed. I + can't imagine that a timeout would be set during this stage... but it'd + probably be good to just clean this up. - Dean Gaudet + + * Okay, so our negotiation strategy needs a bit of refinement. See + . + In general, we need to go through and clean up the negotiation + module to make it compliant with the final HTTP/1.1 draft, and at the + very least we should make it more copacetic to the idea of transferring + gzipped variants of files when both variants exist on the server. + + * Roy's HTTP/1.1 Wishlist items: + 1) New status codes? + 2) Expect + 3) byte range error handling + 4) update the Accept-Encoding parser to allow q-values + 5) would be nice if the proxy used Via and Max-Forwards, even as HTTP/1.0 + + * #ifdef __EMX__ --> #ifdef OS2. + + * use of spawnvp in uncompress_child in mod_mime_magic - doesn't + use the new child_info structure, is this still safe? Needs to be + looked at. + + * suexec doesn't understand argv parameters; e.g. + + + + fails even when "ls" is in the same directory because suexec is trying + to stat a file called "ls -l". A patch for this is available at + + http://www.xnet.com/~emarshal/suexec.diff + + and it's not bad except that it doesn't handle programs with spaces in + the filename (think win32, or samba-mounted filesystems). There are + several PR's to this and I don't see for security reasons why we can't + accomodate it, though it does add complexity to suexec.c. + PR #1120 + Brian: +1 diff --git a/APACHE_1_3b7/cgi-bin/printenv b/APACHE_1_3b7/cgi-bin/printenv new file mode 100644 index 0000000000..7d389e0ac5 --- /dev/null +++ b/APACHE_1_3b7/cgi-bin/printenv @@ -0,0 +1,7 @@ +#!/usr/local/bin/perl + +print "Content-type: text/html\n\n"; +while (($key, $val) = each %ENV) { + print "$key = $val
\n"; +} + diff --git a/APACHE_1_3b7/cgi-bin/test-cgi b/APACHE_1_3b7/cgi-bin/test-cgi new file mode 100644 index 0000000000..a85631e3aa --- /dev/null +++ b/APACHE_1_3b7/cgi-bin/test-cgi @@ -0,0 +1,31 @@ +#!/bin/sh + +# disable filename globbing +set -f + +echo Content-type: text/plain +echo + +echo CGI/1.0 test script report: +echo + +echo argc is $#. argv is "$*". +echo + +echo SERVER_SOFTWARE = $SERVER_SOFTWARE +echo SERVER_NAME = $SERVER_NAME +echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE +echo SERVER_PROTOCOL = $SERVER_PROTOCOL +echo SERVER_PORT = $SERVER_PORT +echo REQUEST_METHOD = $REQUEST_METHOD +echo HTTP_ACCEPT = "$HTTP_ACCEPT" +echo PATH_INFO = "$PATH_INFO" +echo PATH_TRANSLATED = "$PATH_TRANSLATED" +echo SCRIPT_NAME = "$SCRIPT_NAME" +echo QUERY_STRING = "$QUERY_STRING" +echo REMOTE_HOST = $REMOTE_HOST +echo REMOTE_ADDR = $REMOTE_ADDR +echo REMOTE_USER = $REMOTE_USER +echo AUTH_TYPE = $AUTH_TYPE +echo CONTENT_TYPE = $CONTENT_TYPE +echo CONTENT_LENGTH = $CONTENT_LENGTH diff --git a/APACHE_1_3b7/conf/.cvsignore b/APACHE_1_3b7/conf/.cvsignore new file mode 100644 index 0000000000..39efabf64d --- /dev/null +++ b/APACHE_1_3b7/conf/.cvsignore @@ -0,0 +1,4 @@ +access.conf +httpd.conf +srm.conf +highperformance.conf diff --git a/APACHE_1_3b7/conf/access.conf-dist b/APACHE_1_3b7/conf/access.conf-dist new file mode 100644 index 0000000000..65a7f18ff3 --- /dev/null +++ b/APACHE_1_3b7/conf/access.conf-dist @@ -0,0 +1,70 @@ +# access.conf: Global access configuration +# Online docs at http://www.apache.org/ + +# This file defines server settings which affect which types of services +# are allowed, and in what circumstances. + +# Each directory to which Apache has access, can be configured with respect +# to which services and features are allowed and/or disabled in that +# directory (and its subdirectories). + +# Originally by Rob McCool + +# This should be changed to whatever you set DocumentRoot to. + + + +# This may also be "None", "All", or any combination of "Indexes", +# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews". + +# Note that "MultiViews" must be named *explicitly* --- "Options All" +# doesn't give it to you (or at least, not yet). + +Options Indexes FollowSymLinks + +# This controls which options the .htaccess files in directories can +# override. Can also be "All", or any combination of "Options", "FileInfo", +# "AuthConfig", and "Limit" + +AllowOverride None + +# Controls who can get stuff from this server. + +order allow,deny +allow from all + + + +# @@ServerRoot@@/cgi-bin should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. + + +AllowOverride None +Options None + + +# Allow server status reports, with the URL of http://servername/server-status +# Change the ".your_domain.com" to match your domain to enable. + +# +#SetHandler server-status + +#order deny,allow +#deny from all +#allow from .your_domain.com +# + +# There have been reports of people trying to abuse an old bug from pre-1.1 +# days. This bug involved a CGI script distributed as a part of Apache. +# By uncommenting these lines you can redirect these attacks to a logging +# script on phf.apache.org. Or, you can record them yourself, using the script +# support/phf_abuse_log.cgi. + +# +#deny from all +#ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi +# + +# You may place any other directories or locations you wish to have +# access information for after this one. + diff --git a/APACHE_1_3b7/conf/access.conf-dist-win b/APACHE_1_3b7/conf/access.conf-dist-win new file mode 100644 index 0000000000..3c05e10a51 --- /dev/null +++ b/APACHE_1_3b7/conf/access.conf-dist-win @@ -0,0 +1,75 @@ +# access.conf: Global access configuration +# Online docs at http://www.apache.org/ + +# This file defines server settings which affect which types of services +# are allowed, and in what circumstances. + +# Each directory to which Apache has access, can be configured with respect +# to which services and features are allowed and/or disabled in that +# directory (and its subdirectories). + +# Note: Where filenames are specified, you must use forward slashes +# instead of backslashes. e.g. "c:/apache" instead of "c:\apache". If +# the drive letter is ommited, the drive where Apache.exe is located +# will be assumed + +# Originally by Rob McCool + +# This should be changed to whatever you set DocumentRoot to. + + + +# This may also be "None", "All", or any combination of "Indexes", +# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews". + +# Note that "MultiViews" must be named *explicitly* --- "Options All" +# doesn't give it to you (or at least, not yet). + +Options Indexes FollowSymLinks + +# This controls which options the .htaccess files in directories can +# override. Can also be "All", or any combination of "Options", "FileInfo", +# "AuthConfig", and "Limit" + +AllowOverride None + +# Controls who can get stuff from this server. + +order allow,deny +allow from all + + + +# /apache/cgi-bin should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. + + +AllowOverride None +Options None + + +# Allow server status reports, with the URL of http://servername/server-status +# Change the ".your_domain.com" to match your domain to enable. + +# +#SetHandler server-status + +#order deny,allow +#deny from all +#allow from .your_domain.com +# + +# There have been reports of people trying to abuse an old bug from pre-1.1 +# days. This bug involved a CGI script distributed as a part of Apache. +# By uncommenting these lines you can redirect these attacks to a logging +# script on phf.apache.org. Or, you can record them yourself, using the script +# support/phf_abuse_log.cgi. + +# +#deny from all +#ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi +# + +# You may place any other directories or locations you wish to have +# access information for after this one. + diff --git a/APACHE_1_3b7/conf/highperformance.conf-dist b/APACHE_1_3b7/conf/highperformance.conf-dist new file mode 100644 index 0000000000..4c03fba528 --- /dev/null +++ b/APACHE_1_3b7/conf/highperformance.conf-dist @@ -0,0 +1,51 @@ +# Ha, you're reading this config file looking for the easy way out! +# "how do I make my apache server go really really fast??" +# Well you could start by reading the htdocs/manual/misc/perf-tuning.html +# page. But, we'll give you a head start. +# +# This config file is small, it is probably not what you'd expect on a +# full featured internet webserver with multiple users. But it's +# probably a good starting point for any folks interested in testing +# performance. +# +# To run this config you'll need to use something like: +# httpd -f @@ServerRoot@@/conf/highperformance.conf + +Port 80 +ServerRoot @@ServerRoot@@ +DocumentRoot @@ServerRoot@@/htdocs +MaxClients 150 +StartServers 5 +MinSpareServers 5 +MaxSpareServers 10 +MaxRequestsPerChild 10000000 + +# this is a True Config File +# see http://www.apache.org/info/three-config-files.html +ResourceConfig /dev/null +AccessConfig /dev/null + +# it's always nice to know the server has started +ErrorLog logs/error_log + +# Some benchmarks require logging, which is a good requirement. Uncomment +# this if you need logging. +#TransferLog logs/access_log + +# Disable symlink protection and htaccess files, they chew far too much. + + AllowOverride none + Options FollowSymLinks + # If this was a real internet server you'd probably want to + # uncomment these: + #order deny,allow + #deny from all + + +# If this was a real internet server you'd probably want to uncomment this: +# +# order allow,deny +# allow from all +# + +# OK that's enough hints. Read the documentation if you want more. diff --git a/APACHE_1_3b7/conf/httpd.conf-dist b/APACHE_1_3b7/conf/httpd.conf-dist new file mode 100644 index 0000000000..de8d9992a1 --- /dev/null +++ b/APACHE_1_3b7/conf/httpd.conf-dist @@ -0,0 +1,246 @@ +# This is the main server configuration file. See URL http://www.apache.org/ +# for instructions. + +# Do NOT simply read the instructions in here without understanding +# what they do, if you are unsure consult the online docs. You have been +# warned. + +# Originally by Rob McCool + +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Please read the file README.DSO in the Apache 1.3 distribution for more +# details about the DSO mechanism and run `httpd -l' for the list of already +# built-in (statically linked and thus always available) modules in your httpd +# binary. +# +# Example: +# LoadModule foo_module libexec/mod_foo.so + +# ServerType is either inetd, or standalone. + +ServerType standalone + +# If you are running from inetd, go to "ServerAdmin". + +# Port: The port the standalone listens to. For ports < 1023, you will +# need httpd to be run as root initially. + +Port 80 + +# HostnameLookups: Log the names of clients or just their IP numbers +# e.g. www.apache.org (on) or 204.62.129.132 (off) +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on. + +HostnameLookups off + +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. + +# User/Group: The name (or #number) of the user/group to run httpd as. +# On SCO (ODT 3) use User nouser and Group nogroup +# On HPUX you may not be able to use shared memory as nobody, and the +# suggested workaround is to create a user www and use that user. +# NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET) +# when the value of (unsigned)Group is above 60000; +# don't use Group #-1 on these systems! + +User nobody +Group #-1 + +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. + +ServerAdmin you@your.address + +# ServerRoot: The directory the server's config, error, and log files +# are kept in. +# NOTE! If you intend to place this on a NFS (or otherwise network) +# mounted filesystem then please read the LockFile documentation, +# you will save yourself a lot of trouble. + +ServerRoot @@ServerRoot@@ + +# BindAddress: You can support virtual hosts with this option. This option +# is used to tell the server which IP address to listen to. It can either +# contain "*", an IP address, or a fully qualified Internet domain name. +# See also the VirtualHost directive. + +#BindAddress * + +# ErrorLog: The location of the error log file. If this does not start +# with /, ServerRoot is prepended to it. + +ErrorLog logs/error_log + +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. + +LogLevel warn + +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). + +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %b" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# The location of the access logfile (Common Logfile Format). +# If this does not start with /, ServerRoot is prepended to it. + +CustomLog logs/access_log common + +# If you would like to have an agent and referer logfile uncomment the +# following directives. + +#CustomLog logs/referer_log referer +#CustomLog logs/agent_log agent + +# If you prefer a single logfile with access, agent and referer information +# (Combined Logfile Format) you can use the following directive. + +#CustomLog logs/access_log combined + +# PidFile: The file the server should log its pid to +PidFile logs/httpd.pid + +# ScoreBoardFile: File used to store internal server process information. +# Not all architectures require this. But if yours does (you'll know because +# this file is created when you run Apache) then you *must* ensure that +# no two invocations of Apache share the same scoreboard file. +ScoreBoardFile logs/apache_runtime_status + +# The LockFile directive sets the path to the lockfile used when Apache +# is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or +# USE_FLOCK_SERIALIZED_ACCEPT. This directive should normally be left at +# its default value. The main reason for changing it is if the logs +# directory is NFS mounted, since the lockfile MUST BE STORED ON A LOCAL +# DISK. The PID of the main server process is automatically appended to +# the filename. +# +#LockFile logs/accept.lock + +# ServerName allows you to set a host name which is sent back to clients for +# your server if it's different than the one the program would get (i.e. use +# "www" instead of the host's real name). +# +# Note: You cannot just invent host names and hope they work. The name you +# define here must be a valid DNS name for your host. If you don't understand +# this, ask your network administrator. + +#ServerName new.host.name + +# UseCanonicalName: (new for 1.3) With this setting turned on, whenever +# Apache needs to construct a self-referencing URL (a url that refers back +# to the server the response is coming from) it will use ServerName and +# Port to form a "canonical" name. With this setting off, Apache will +# use the hostname:port that the client supplied, when possible. This +# also affects SERVER_NAME and SERVER_PORT in CGIs. +UseCanonicalName on + +# CacheNegotiatedDocs: By default, Apache sends Pragma: no-cache with each +# document that was negotiated on the basis of content. This asks proxy +# servers not to cache the document. Uncommenting the following line disables +# this behavior, and proxies will be allowed to cache the documents. + +#CacheNegotiatedDocs + +# Timeout: The number of seconds before receives and sends time out + +Timeout 300 + +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. + +KeepAlive On + +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We reccomend you leave this number high, for maximum performance. + +MaxKeepAliveRequests 100 + +# KeepAliveTimeout: Number of seconds to wait for the next request + +KeepAliveTimeout 15 + +# Server-pool size regulation. Rather than making you guess how many +# server processes you need, Apache dynamically adapts to the load it +# sees --- that is, it tries to maintain enough server processes to +# handle the current load, plus a few spare servers to handle transient +# load spikes (e.g., multiple simultaneous requests from a single +# Netscape browser). + +# It does this by periodically checking how many servers are waiting +# for a request. If there are fewer than MinSpareServers, it creates +# a new spare. If there are more than MaxSpareServers, some of the +# spares die off. These values are probably OK for most sites --- + +MinSpareServers 5 +MaxSpareServers 10 + +# Number of servers to start --- should be a reasonable ballpark figure. + +StartServers 5 + +# Limit on total number of servers running, i.e., limit on the number +# of clients who can simultaneously connect --- if this limit is ever +# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW. +# It is intended mainly as a brake to keep a runaway server from taking +# Unix with it as it spirals down... + +MaxClients 150 + +# MaxRequestsPerChild: the number of requests each child process is +# allowed to process before the child dies. +# The child will exit so as to avoid problems after prolonged use when +# Apache (and maybe the libraries it uses) leak. On most systems, this +# isn't really needed, but a few (such as Solaris) do have notable leaks +# in the libraries. + +MaxRequestsPerChild 30 + +# Proxy Server directives. Uncomment the following line to +# enable the proxy server: + +#ProxyRequests On + +# To enable the cache as well, edit and uncomment the following lines: + +#CacheRoot @@ServerRoot@@/proxy +#CacheSize 5 +#CacheGcInterval 4 +#CacheMaxExpire 24 +#CacheLastModifiedFactor 0.1 +#CacheDefaultExpire 1 +#NoCache a_domain.com another_domain.edu joes.garage_sale.com + +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the VirtualHost command + +#Listen 3000 +#Listen 12.34.56.78:80 + +# VirtualHost: Allows the daemon to respond to requests for more than one +# server address, if your server machine is configured to accept IP packets +# for multiple addresses. This can be accomplished with the ifconfig +# alias flag, or through kernel patches like VIF. + +# Any httpd.conf or srm.conf directive may go into a VirtualHost command. +# See also the BindAddress entry. + +# +#ServerAdmin webmaster@host.some_domain.com +#DocumentRoot /www/docs/host.some_domain.com +#ServerName host.some_domain.com +#ErrorLog logs/host.some_domain.com-error_log +#TransferLog logs/host.some_domain.com-access_log +# + + diff --git a/APACHE_1_3b7/conf/httpd.conf-dist-win b/APACHE_1_3b7/conf/httpd.conf-dist-win new file mode 100644 index 0000000000..eea26d1058 --- /dev/null +++ b/APACHE_1_3b7/conf/httpd.conf-dist-win @@ -0,0 +1,216 @@ +# This is the main server configuration file. See URL http://www.apache.org/ +# for instructions. + +# Do NOT simply read the instructions in here without understanding +# what they do, if you are unsure consult the online docs. You have been +# warned. + +# Note: Where filenames are specified, you must use forward slashes +# instead of backslashes. e.g. "c:/apache" instead of "c:\apache". If +# the drive letter is ommited, the drive where Apache.exe is located +# will be assumed + +# Originally by Rob McCool + +# ServerType must be standalone. + +ServerType standalone + +# +# The following lists extra modules that can be uncommented to be loaded +# to enable extra functionality. See the manual +# (http://www.apache.org/docs/mod/) for details on the functionality +# of each module. +# +#LoadModule anon_auth_module modules/ApacheModuleAuthAnon.dll +#LoadModule cern_meta_module modules/ApacheModuleCERNMeta.dll +#LoadModule digest_module modules/ApacheModuleDigest.dll +#LoadModule expires_module modules/ApacheModuleExpires.dll +#LoadModule headers_module modules/ApacheModuleHeaders.dll +#LoadModule proxy_module modules/ApacheModuleProxy.dll +#LoadModule rewrite_module modules/ApacheModuleRewrite.dll +#LoadModule speling_module modules/ApacheModuleSpeling.dll +#LoadModule status_module modules/ApacheModuleStatus.dll +#LoadModule usertrack_module modules/ApacheModuleUserTrack.dll + + +# Port: The port the standalone listens to. + +Port 80 + +# HostnameLookups: Log the names of clients or just their IP numbers +# e.g. www.apache.org (on) or 204.62.129.132 (off) +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on. +HostnameLookups off + +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. + +# User/Group: The name (or #number) of the user/group to run httpd as. +User nobody +Group #-1 + +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. + +ServerAdmin you@your.address + +# ServerRoot: The directory the server's config, error, and log files +# are kept in + +ServerRoot "@@ServerRoot@@" + +# BindAddress: You can support virtual hosts with this option. This option +# is used to tell the server which IP address to listen to. It can either +# contain "*", an IP address, or a fully qualified Internet domain name. +# See also the VirtualHost directive. + +#BindAddress * + +# ErrorLog: The location of the error log file. If this does not start +# with /, ServerRoot is prepended to it. + +ErrorLog logs/error.log + +# LogLevel: Control the number of messages logged to the error.log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. + +LogLevel warn + +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). + +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %b" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# The location of the access logfile (Common Logfile Format). +# If this does not start with /, ServerRoot is prepended to it. + +CustomLog logs/access.log common + +# If you would like to have an agent and referer logfile uncomment the +# following directives. + +#CustomLog logs/referer.log referer +#CustomLog logs/agent.log agent + +# If you prefer a single logfile with access, agent and referer information +# (Combined Logfile Format) you can use the following directive. + +#CustomLog logs/access.log combined + +# PidFile: The file the server should log its pid to +PidFile logs/httpd.pid + +# ScoreBoardFile: File used to store internal server process information. +# Not all architectures require this. But if yours does (you'll know because +# this file is created when you run Apache) then you *must* ensure that +# no two invocations of Apache share the same scoreboard file. +ScoreBoardFile logs/apache_status + +# ServerName allows you to set a host name which is sent back to clients for +# your server if it's different than the one the program would get (i.e. use +# "www" instead of the host's real name). +# +# Note: You cannot just invent host names and hope they work. The name you +# define here must be a valid DNS name for your host. If you don't understand +# this, ask your network administrator. + +#ServerName new.host.name + +# UseCanonicalName: (new for 1.3) With this setting turned on, whenever +# Apache needs to construct a self-referencing URL (a url that refers back +# to the server the response is coming from) it will use ServerName and +# Port to form a "canonical" name. With this setting off, Apache will +# use the hostname:port that the client supplied, when possible. This +# also affects SERVER_NAME and SERVER_PORT in CGIs. +UseCanonicalName on + +# CacheNegotiatedDocs: By default, Apache sends Pragma: no-cache with each +# document that was negotiated on the basis of content. This asks proxy +# servers not to cache the document. Uncommenting the following line disables +# this behavior, and proxies will be allowed to cache the documents. + +#CacheNegotiatedDocs + +# Timeout: The number of seconds before receives and sends time out + +Timeout 300 + +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. + +KeepAlive On + +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We reccomend you leave this number high, for maximum performance. + +MaxKeepAliveRequests 100 + +# KeepAliveTimeout: Number of seconds to wait for the next request + +KeepAliveTimeout 15 + +# Apache always creates one child process to handle requests. If it +# dies another child process is created automatically. Within the +# child process multiple threads handle incoming requests. The next two +# directives determine the behaviour of the threads and processes. + +# Don't force a server to exit after it has served some number of requests. +# If you do want server's to exit after they have run for a long time (to +# help the system clean up after the process), please set this to a pretty +# large number - like 10,000. What this will do, is, each child server will +# exit after serving 10,000 requests, and another server will take its place. + +MaxRequestsPerChild 0 + +# Number of concurrent threads at a time (set the value to more or less +# depending on the responsiveness you want and the resources you wish +# this server to consume). + +ThreadsPerChild 50 + + +# Proxy Server directives. Uncomment the following line to +# enable the proxy server: + +#ProxyRequests On + +# To enable the cache as well, edit and uncomment the following lines: + +#CacheRoot /usr/local/apache/proxy +#CacheSize 5 +#CacheGcInterval 4 +#CacheMaxExpire 24 +#CacheLastModifiedFactor 0.1 +#CacheDefaultExpire 1 +#NoCache a_domain.com another_domain.edu joes.garage_sale.com + +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the VirtualHost command + +#Listen 3000 +#Listen 12.34.56.78:80 + +# VirtualHost: Allows the daemon to respond to requests for more than one +# server address, if your server machine is configured to accept IP packets +# for multiple addresses. This can be accomplished with the ifconfig +# alias flag, or through kernel patches like VIF. + +# Any httpd.conf or srm.conf directive may go into a VirtualHost command. +# See also the BindAddress entry. + +# +#ServerAdmin webmaster@host.some_domain.com +#DocumentRoot /www/docs/host.some_domain.com +#ServerName host.some_domain.com +#ErrorLog logs/host.some_domain.com-error.log +#TransferLog logs/host.some_domain.com-access.log +# + + diff --git a/APACHE_1_3b7/conf/magic b/APACHE_1_3b7/conf/magic new file mode 100644 index 0000000000..48806019ee --- /dev/null +++ b/APACHE_1_3b7/conf/magic @@ -0,0 +1,365 @@ +# Magic data for mod_mime_magic Apache module (originally for file(1) command) +# The module is described in htdocs/manual/mod/mod_mime_magic.html +# +# The format is 4-5 columns: +# Column #1: byte number to begin checking from, ">" indicates continuation +# Column #2: type of data to match +# Column #3: contents of data to match +# Column #4: MIME type of result +# Column #5: MIME encoding of result (optional) + +#------------------------------------------------------------------------------ +# Localstuff: file(1) magic for locally observed files +# Add any locally observed files here. + +#------------------------------------------------------------------------------ +# end local stuff +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Java + +0 short 0xcafe +>2 short 0xbabe application/java + +#------------------------------------------------------------------------------ +# audio: file(1) magic for sound formats +# +# from Jan Nicolai Langfeldt , +# + +# Sun/NeXT audio data +0 string .snd +>12 belong 1 audio/basic +>12 belong 2 audio/basic +>12 belong 3 audio/basic +>12 belong 4 audio/basic +>12 belong 5 audio/basic +>12 belong 6 audio/basic +>12 belong 7 audio/basic + +>12 belong 23 audio/x-adpcm + +# DEC systems (e.g. DECstation 5000) use a variant of the Sun/NeXT format +# that uses little-endian encoding and has a different magic number +# (0x0064732E in little-endian encoding). +0 lelong 0x0064732E +>12 lelong 1 audio/x-dec-basic +>12 lelong 2 audio/x-dec-basic +>12 lelong 3 audio/x-dec-basic +>12 lelong 4 audio/x-dec-basic +>12 lelong 5 audio/x-dec-basic +>12 lelong 6 audio/x-dec-basic +>12 lelong 7 audio/x-dec-basic +# compressed (G.721 ADPCM) +>12 lelong 23 audio/x-dec-adpcm + +# Bytes 0-3 of AIFF, AIFF-C, & 8SVX audio files are "FORM" +# AIFF audio data +8 string AIFF audio/x-aiff +# AIFF-C audio data +8 string AIFC audio/x-aiff +# IFF/8SVX audio data +8 string 8SVX audio/x-aiff + +# Creative Labs AUDIO stuff +# Standard MIDI data +0 string MThd audio/unknown +#>9 byte >0 (format %d) +#>11 byte >1 using %d channels +# Creative Music (CMF) data +0 string CTMF audio/unknown +# SoundBlaster instrument data +0 string SBI audio/unknown +# Creative Labs voice data +0 string Creative\ Voice\ File audio/unknown +## is this next line right? it came this way... +#>19 byte 0x1A +#>23 byte >0 - version %d +#>22 byte >0 \b.%d + +# [GRR 950115: is this also Creative Labs? Guessing that first line +# should be string instead of unknown-endian long...] +#0 long 0x4e54524b MultiTrack sound data +#0 string NTRK MultiTrack sound data +#>4 long x - version %ld + +# Microsoft WAVE format (*.wav) +# [GRR 950115: probably all of the shorts and longs should be leshort/lelong] +# Microsoft RIFF +0 string RIFF audio/unknown +# - WAVE format +>8 string WAVE audio/x-wav + +#------------------------------------------------------------------------------ +# c-lang: file(1) magic for C programs or various scripts +# + +# XPM icons (Greg Roelofs, newt@uchicago.edu) +# ideally should go into "images", but entries below would tag XPM as C source +0 string /*\ XPM image/x-xbm 7bit + +# this first will upset you if you're a PL/1 shop... (are there any left?) +# in which case rm it; ascmagic will catch real C programs +# C or REXX program text +0 string /* text/plain +# C++ program text +0 string // text/plain + +#------------------------------------------------------------------------------ +# compress: file(1) magic for pure-compression formats (no archives) +# +# compress, gzip, pack, compact, huf, squeeze, crunch, freeze, yabba, whap, etc. +# +# Formats for various forms of compressed data +# Formats for "compress" proper have been moved into "compress.c", +# because it tries to uncompress it to figure out what's inside. + +# standard unix compress +0 string \037\235 application/octet-stream x-compress + +# gzip (GNU zip, not to be confused with [Info-ZIP/PKWARE] zip archiver) +0 string \037\213 application/octet-stream x-gzip + +# According to gzip.h, this is the correct byte order for packed data. +0 string \037\036 application/octet-stream +# +# This magic number is byte-order-independent. +# +0 short 017437 application/octet-stream + +# XXX - why *two* entries for "compacted data", one of which is +# byte-order independent, and one of which is byte-order dependent? +# +# compacted data +0 short 0x1fff application/octet-stream +0 string \377\037 application/octet-stream +# huf output +0 short 0145405 application/octet-stream + +# Squeeze and Crunch... +# These numbers were gleaned from the Unix versions of the programs to +# handle these formats. Note that I can only uncrunch, not crunch, and +# I didn't have a crunched file handy, so the crunch number is untested. +# Keith Waclena +#0 leshort 0x76FF squeezed data (CP/M, DOS) +#0 leshort 0x76FE crunched data (CP/M, DOS) + +# Freeze +#0 string \037\237 Frozen file 2.1 +#0 string \037\236 Frozen file 1.0 (or gzip 0.5) + +# lzh? +#0 string \037\240 LZH compressed data + +#------------------------------------------------------------------------------ +# frame: file(1) magic for FrameMaker files +# +# This stuff came on a FrameMaker demo tape, most of which is +# copyright, but this file is "published" as witness the following: +# +0 string \ +# +0 string \14 byte 12 (OS/2 1.x format) +#>14 byte 64 (OS/2 2.x format) +#>14 byte 40 (Windows 3.x format) +#0 string IC icon +#0 string PI pointer +#0 string CI color icon +#0 string CP color pointer +#0 string BA bitmap array + + +#------------------------------------------------------------------------------ +# lisp: file(1) magic for lisp programs +# +# various lisp types, from Daniel Quinlan (quinlan@yggdrasil.com) +0 string ;; text/plain 8bit +# Emacs 18 - this is always correct, but not very magical. +0 string \012( application/x-elc +# Emacs 19 +0 string ;ELC\023\000\000\000 application/x-elc + +#------------------------------------------------------------------------------ +# mail.news: file(1) magic for mail and news +# +# There are tests to ascmagic.c to cope with mail and news. +0 string Relay-Version: message/rfc822 7bit +0 string #!\ rnews message/rfc822 7bit +0 string N#!\ rnews message/rfc822 7bit +0 string Forward\ to message/rfc822 7bit +0 string Pipe\ to message/rfc822 7bit +0 string Return-Path: message/rfc822 7bit +0 string Path: message/news 8bit +0 string Xref: message/news 8bit +0 string From: message/rfc822 7bit +0 string Article message/news 8bit +#------------------------------------------------------------------------------ +# msword: file(1) magic for MS Word files +# +# Contributor claims: +# Reversed-engineered MS Word magic numbers +# + +0 string \376\067\0\043 application/msword +0 string \320\317\021\340\241\261 application/msword +0 string \333\245-\0\0\0 application/msword + + + +#------------------------------------------------------------------------------ +# printer: file(1) magic for printer-formatted files +# + +# PostScript +0 string %! application/postscript +0 string \004%! application/postscript + +# Acrobat +# (due to clamen@cs.cmu.edu) +0 string %PDF- application/pdf + +#------------------------------------------------------------------------------ +# sc: file(1) magic for "sc" spreadsheet +# +38 string Spreadsheet application/x-sc + +#------------------------------------------------------------------------------ +# tex: file(1) magic for TeX files +# +# XXX - needs byte-endian stuff (big-endian and little-endian DVI?) +# +# From + +# Although we may know the offset of certain text fields in TeX DVI +# and font files, we can't use them reliably because they are not +# zero terminated. [but we do anyway, christos] +0 string \367\002 application/x-dvi +#0 string \367\203 TeX generic font data +#0 string \367\131 TeX packed font data +#0 string \367\312 TeX virtual font data +#0 string This\ is\ TeX, TeX transcript text +#0 string This\ is\ METAFONT, METAFONT transcript text + +# There is no way to detect TeX Font Metric (*.tfm) files without +# breaking them apart and reading the data. The following patterns +# match most *.tfm files generated by METAFONT or afm2tfm. +#2 string \000\021 TeX font metric data +#2 string \000\022 TeX font metric data +#>34 string >\0 (%s) + +# Texinfo and GNU Info, from Daniel Quinlan (quinlan@yggdrasil.com) +#0 string \\input\ texinfo Texinfo source text +#0 string This\ is\ Info\ file GNU Info text + +# correct TeX magic for Linux (and maybe more) +# from Peter Tobias (tobias@server.et-inf.fho-emden.de) +# +0 leshort 0x02f7 application/x-dvi + +# RTF - Rich Text Format +0 string {\\rtf application/rtf + +#------------------------------------------------------------------------------ +# animation: file(1) magic for animation/movie formats +# +# animation formats, originally from vax@ccwf.cc.utexas.edu (VaX#n8) +# MPEG file +0 string \000\000\001\263 video/mpeg +# +# The contributor claims: +# I couldn't find a real magic number for these, however, this +# -appears- to work. Note that it might catch other files, too, +# so BE CAREFUL! +# +# Note that title and author appear in the two 20-byte chunks +# at decimal offsets 2 and 22, respectively, but they are XOR'ed with +# 255 (hex FF)! DL format SUCKS BIG ROCKS. +# +# DL file version 1 , medium format (160x100, 4 images/screen) +0 byte 1 video/unknown +0 byte 2 video/unknown + diff --git a/APACHE_1_3b7/conf/mime.types b/APACHE_1_3b7/conf/mime.types new file mode 100644 index 0000000000..8b9bbdfd13 --- /dev/null +++ b/APACHE_1_3b7/conf/mime.types @@ -0,0 +1,104 @@ +# This file controls what MIME types are sent to the client for the +# given file extensions. Sending the correct MIME type to the client +# is important so they know how to handle the content of the file. +# Extra types can either be added here or by using an AddType directive +# in your config files. + +# MIME type Extension +application/activemessage +application/andrew-inset +application/applefile +application/atomicmail +application/dca-rft +application/dec-dx +application/mac-binhex40 hqx +application/mac-compactpro cpt +application/macwriteii +application/msword doc +application/news-message-id +application/news-transmission +application/octet-stream bin dms lha lzh exe class +application/oda oda +application/pdf pdf +application/postscript ai eps ps +application/powerpoint ppt +application/remote-printing +application/rtf rtf +application/slate +application/wita +application/wordperfect5.1 +application/x-bcpio bcpio +application/x-cdlink vcd +application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-director dcr dir dxr +application/x-dvi dvi +application/x-gtar gtar +application/x-gzip +application/x-hdf hdf +application/x-koan skp skd skt skm +application/x-latex latex +application/x-mif mif +application/x-netcdf nc cdf +application/x-sh sh +application/x-shar shar +application/x-stuffit sit +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-texinfo texinfo texi +application/x-troff t tr roff +application/x-troff-man man +application/x-troff-me me +application/x-troff-ms ms +application/x-ustar ustar +application/x-wais-source src +application/zip zip +audio/basic au snd +audio/midi mid midi kar +audio/mpeg mpga mp2 mp3 +audio/x-aiff aif aiff aifc +audio/x-pn-realaudio ram +audio/x-pn-realaudio-plugin rpm +audio/x-realaudio ra +audio/x-wav wav +chemical/x-pdb pdb xyz +image/gif gif +image/ief ief +image/jpeg jpeg jpg jpe +image/png png +image/tiff tiff tif +image/x-cmu-raster ras +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +message/external-body +message/news +message/partial +message/rfc822 +multipart/alternative +multipart/appledouble +multipart/digest +multipart/mixed +multipart/parallel +text/css css +text/html html htm +text/plain txt +text/richtext rtx +text/tab-separated-values tsv +text/x-setext etx +text/x-sgml sgml sgm +video/mpeg mpeg mpg mpe +video/quicktime qt mov +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice +x-world/x-vrml wrl vrml diff --git a/APACHE_1_3b7/conf/srm.conf-dist b/APACHE_1_3b7/conf/srm.conf-dist new file mode 100644 index 0000000000..53dbeb7e7d --- /dev/null +++ b/APACHE_1_3b7/conf/srm.conf-dist @@ -0,0 +1,233 @@ +# With this document, you define the name space that users see of your http +# server. This file also defines server settings which affect how requests are +# serviced, and how results should be formatted. + +# See the tutorials at http://www.apache.org/ for +# more information. + +# Originally by Rob McCool; Adapted for Apache + + +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. + +DocumentRoot @@ServerRoot@@/htdocs + +# UserDir: The name of the directory which is appended onto a user's home +# directory if a ~user request is recieved. + +UserDir public_html + +# DirectoryIndex: Name of the file or files to use as a pre-written HTML +# directory index. Separate multiple entries with spaces. + +DirectoryIndex index.html + +# FancyIndexing is whether you want fancy directory indexing or standard + +FancyIndexing on + +# AddIcon tells the server which icon to show for different files or filename +# extensions + +AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip + +AddIconByType (TXT,/icons/text.gif) text/* +AddIconByType (IMG,/icons/image2.gif) image/* +AddIconByType (SND,/icons/sound2.gif) audio/* +AddIconByType (VID,/icons/movie.gif) video/* + +AddIcon /icons/binary.gif .bin .exe +AddIcon /icons/binhex.gif .hqx +AddIcon /icons/tar.gif .tar +AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv +AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip +AddIcon /icons/a.gif .ps .ai .eps +AddIcon /icons/layout.gif .html .shtml .htm .pdf +AddIcon /icons/text.gif .txt +AddIcon /icons/c.gif .c +AddIcon /icons/p.gif .pl .py +AddIcon /icons/f.gif .for +AddIcon /icons/dvi.gif .dvi +AddIcon /icons/uuencoded.gif .uu +AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl +AddIcon /icons/tex.gif .tex +AddIcon /icons/bomb.gif core + +AddIcon /icons/back.gif .. +AddIcon /icons/hand.right.gif README +AddIcon /icons/folder.gif ^^DIRECTORY^^ +AddIcon /icons/blank.gif ^^BLANKICON^^ + +# DefaultIcon is which icon to show for files which do not have an icon +# explicitly set. + +DefaultIcon /icons/unknown.gif + +# AddDescription allows you to place a short description after a file in +# server-generated indexes. +# Format: AddDescription "description" filename + +# ReadmeName is the name of the README file the server will look for by +# default. Format: ReadmeName name +# +# The server will first look for name.html, include it if found, and it will +# then look for name and include it as plaintext if found. +# +# HeaderName is the name of a file which should be prepended to +# directory indexes. + +ReadmeName README +HeaderName HEADER + +# IndexIgnore is a set of filenames which directory indexing should ignore +# Format: IndexIgnore name1 name2... + +IndexIgnore .??* *~ *# HEADER* README* RCS + +# AccessFileName: The name of the file to look for in each directory +# for access control information. + +AccessFileName .htaccess + +# DefaultType is the default MIME type for documents which the server +# cannot find the type of from filename extensions. + +DefaultType text/plain + +# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress +# information on the fly. Note: Not all browsers support this. + +AddEncoding x-compress Z +AddEncoding x-gzip gz + +# AddLanguage allows you to specify the language of a document. You can +# then use content negotiation to give a browser a file in a language +# it can understand. Note that the suffix does not have to be the same +# as the language keyword --- those with documents in Polish (whose +# net-standard language code is pl) may wish to use "AddLanguage pl .po" +# to avoid the ambiguity with the common suffix for perl scripts. + +AddLanguage en .en +AddLanguage fr .fr +AddLanguage de .de +AddLanguage da .da +AddLanguage el .el +AddLanguage it .it + +# LanguagePriority allows you to give precedence to some languages +# in case of a tie during content negotiation. +# Just list the languages in decreasing order of preference. + +LanguagePriority en fr de + +# Redirect allows you to tell clients about documents which used to exist in +# your server's namespace, but do not anymore. This allows you to tell the +# clients where to look for the relocated document. +# Format: Redirect fakename url + + +# Aliases: Add here as many aliases as you need (with no limit). The format is +# Alias fakename realname + +# Note that if you include a trailing / on fakename then the server will +# require it to be present in the URL. So "/icons" isn't aliased in this +# example. + +Alias /icons/ @@ServerRoot@@/icons/ + +# ScriptAlias: This controls which directories contain server scripts. +# Format: ScriptAlias fakename realname + +#ScriptAlias /cgi-bin/ @@ServerRoot@@/cgi-bin/ + +# If you want to use server side includes, or CGI outside +# ScriptAliased directories, uncomment the following lines. + +# AddType allows you to tweak mime.types without actually editing it, or to +# make certain files to be certain types. +# Format: AddType type/subtype ext1 + +# For example, the PHP3 module (not part of the Apache distribution) +# will typically use: +#AddType application/x-httpd-php3 .phtml +#AddType application/x-httpd-php3-source .phps + +# AddHandler allows you to map certain file extensions to "handlers", +# actions unrelated to filetype. These can be either built into the server +# or added with the Action command (see below) +# Format: AddHandler action-name ext1 + +# To use CGI scripts: +#AddHandler cgi-script .cgi + +# To use server-parsed HTML files +#AddType text/html .shtml +#AddHandler server-parsed .shtml + +# Uncomment the following line to enable Apache's send-asis HTTP file +# feature +#AddHandler send-as-is asis + +# If you wish to use server-parsed imagemap files, use +#AddHandler imap-file map + +# To enable type maps, you might want to use +#AddHandler type-map var + +# Action lets you define media types that will execute a script whenever +# a matching file is called. This eliminates the need for repeated URL +# pathnames for oft-used CGI file processors. +# Format: Action media/type /cgi-script/location +# Format: Action handler-name /cgi-script/location + +# MetaDir: specifies the name of the directory in which Apache can find +# meta information files. These files contain additional HTTP headers +# to include when sending the document + +#MetaDir .web + +# MetaSuffix: specifies the file name suffix for the file containing the +# meta information. + +#MetaSuffix .meta + +# Customizable error response (Apache style) +# these come in three flavors +# +# 1) plain text +#ErrorDocument 500 "The server made a boo boo. +# n.b. the (") marks it as text, it does not get output +# +# 2) local redirects +#ErrorDocument 404 /missing.html +# to redirect to local url /missing.html +#ErrorDocument 404 /cgi-bin/missing_handler.pl +# n.b. can redirect to a script or a document using server-side-includes. +# +# 3) external redirects +#ErrorDocument 402 http://some.other_server.com/subscription_info.html +# + +# mod_mime_magic allows the server to use various hints from the file itself +# to determine its type. +#MimeMagicFile conf/magic + +# The following directives disable keepalives and HTTP header flushes. +# The first directive disables it for Netscape 2.x and browsers which +# spoof it. There are known problems with these. +# The second directive is for Microsoft Internet Explorer 4.0b2 +# which has a broken HTTP/1.1 implementation and does not properly +# support keepalive when it is used on 301 or 302 (redirect) responses. + +BrowserMatch "Mozilla/2" nokeepalive +BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + +# The following directive disables HTTP/1.1 responses to browsers which +# are in violation of the HTTP/1.0 spec by not being able to grok a +# basic 1.1 response. + +BrowserMatch "RealPlayer 4\.0" force-response-1.0 +BrowserMatch "Java/1\.0" force-response-1.0 +BrowserMatch "JDK/1\.0" force-response-1.0 diff --git a/APACHE_1_3b7/conf/srm.conf-dist-win b/APACHE_1_3b7/conf/srm.conf-dist-win new file mode 100644 index 0000000000..aef87913d5 --- /dev/null +++ b/APACHE_1_3b7/conf/srm.conf-dist-win @@ -0,0 +1,241 @@ +# With this document, you define the name space that users see of your http +# server. This file also defines server settings which affect how requests are +# serviced, and how results should be formatted. + +# See the tutorials at http://www.apache.org/ for +# more information. + +# Originally by Rob McCool; Adapted for Apache + +# Note: Where filenames are specified, you must use forward slashes +# instead of backslashes. e.g. "c:/apache" instead of "c:\apache". If +# the drive letter is ommited, the drive where Apache.exe is located +# will be assumed. + +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. + +DocumentRoot "@@ServerRoot@@/htdocs" + +# UserDir: The name of the directory which is appended onto a user's home +# directory if a ~user request is recieved. +# +# Under Win32, we do not currently try to determine the home directory of +# a Windows login, so one of the forms such as the below needs to be +# used. See the manual for details. +# +#UserDir "/@@ServerRoot@@/users/" + +# DirectoryIndex: Name of the file or files to use as a pre-written HTML +# directory index. Separate multiple entries with spaces. + +DirectoryIndex index.html + +# FancyIndexing is whether you want fancy directory indexing or standard + +FancyIndexing on + +# AddIcon tells the server which icon to show for different files or filename +# extensions + +AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip + +AddIconByType (TXT,/icons/text.gif) text/* +AddIconByType (IMG,/icons/image2.gif) image/* +AddIconByType (SND,/icons/sound2.gif) audio/* +AddIconByType (VID,/icons/movie.gif) video/* + +AddIcon /icons/binary.gif .bin .exe +AddIcon /icons/binhex.gif .hqx +AddIcon /icons/tar.gif .tar +AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv +AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip +AddIcon /icons/a.gif .ps .ai .eps +AddIcon /icons/layout.gif .html .shtml .htm .pdf +AddIcon /icons/text.gif .txt +AddIcon /icons/c.gif .c +AddIcon /icons/p.gif .pl .py +AddIcon /icons/f.gif .for +AddIcon /icons/dvi.gif .dvi +AddIcon /icons/uuencoded.gif .uu +AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl +AddIcon /icons/tex.gif .tex +AddIcon /icons/bomb.gif core + +AddIcon /icons/back.gif .. +AddIcon /icons/hand.right.gif README +AddIcon /icons/folder.gif ^^DIRECTORY^^ +AddIcon /icons/blank.gif ^^BLANKICON^^ + +# DefaultIcon is which icon to show for files which do not have an icon +# explicitly set. + +DefaultIcon /icons/unknown.gif + +# AddDescription allows you to place a short description after a file in +# server-generated indexes. +# Format: AddDescription "description" filename + +# ReadmeName is the name of the README file the server will look for by +# default. Format: ReadmeName name +# +# The server will first look for name.html, include it if found, and it will +# then look for name and include it as plaintext if found. +# +# HeaderName is the name of a file which should be prepended to +# directory indexes. + +ReadmeName README +HeaderName HEADER + +# IndexIgnore is a set of filenames which directory indexing should ignore +# Format: IndexIgnore name1 name2... + +IndexIgnore .??* *~ *# HEADER* README* RCS + +# AccessFileName: The name of the file to look for in each directory +# for access control information. + +AccessFileName .htaccess + +# DefaultType is the default MIME type for documents which the server +# cannot find the type of from filename extensions. + +DefaultType text/plain + +# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress +# information on the fly. Note: Not all browsers support this. + +AddEncoding x-compress Z +AddEncoding x-gzip gz + +# AddLanguage allows you to specify the language of a document. You can +# then use content negotiation to give a browser a file in a language +# it can understand. Note that the suffix does not have to be the same +# as the language keyword --- those with documents in Polish (whose +# net-standard language code is pl) may wish to use "AddLanguage pl .po" +# to avoid the ambiguity with the common suffix for perl scripts. + +AddLanguage en .en +AddLanguage fr .fr +AddLanguage de .de +AddLanguage da .da +AddLanguage el .el +AddLanguage it .it + +# LanguagePriority allows you to give precedence to some languages +# in case of a tie during content negotiation. +# Just list the languages in decreasing order of preference. + +LanguagePriority en fr de + +# Redirect allows you to tell clients about documents which used to exist in +# your server's namespace, but do not anymore. This allows you to tell the +# clients where to look for the relocated document. +# Format: Redirect fakename url + + +# Aliases: Add here as many aliases as you need (with no limit). The format is +# Alias fakename realname + +# Note that if you include a trailing / on fakename then the server will +# require it to be present in the URL. So "/icons" isn't aliased in this +# example. + +Alias /icons/ /apache/icons/ + +# ScriptAlias: This controls which directories contain server scripts. +# Format: ScriptAlias fakename realname + +#ScriptAlias /cgi-bin/ /apache/cgi-bin/ + +# If you want to use server side includes, or CGI outside +# ScriptAliased directories, uncomment the following lines. + +# AddType allows you to tweak mime.types without actually editing it, or to +# make certain files to be certain types. +# Format: AddType type/subtype ext1 + +# For example, the PHP3 module (not part of the Apache distribution) +# will typically use: +#AddType application/x-httpd-php3 .phtml +#AddType application/x-httpd-php3-source .phps + +# AddHandler allows you to map certain file extensions to "handlers", +# actions unrelated to filetype. These can be either built into the server +# or added with the Action command (see below) +# Format: AddHandler action-name ext1 + +# To use CGI scripts: +#AddHandler cgi-script .cgi + +# To use server-parsed HTML files +#AddType text/html .shtml +#AddHandler server-parsed .shtml + +# Uncomment the following line to enable Apache's send-asis HTTP file +# feature +#AddHandler send-as-is asis + +# If you wish to use server-parsed imagemap files, use +#AddHandler imap-file map + +# To enable type maps, you might want to use +#AddHandler type-map var + +# Action lets you define media types that will execute a script whenever +# a matching file is called. This eliminates the need for repeated URL +# pathnames for oft-used CGI file processors. +# Format: Action media/type /cgi-script/location +# Format: Action handler-name /cgi-script/location + +# MetaDir: specifies the name of the directory in which Apache can find +# meta information files. These files contain additional HTTP headers +# to include when sending the document + +#MetaDir .web + +# MetaSuffix: specifies the file name suffix for the file containing the +# meta information. + +#MetaSuffix .meta + +# Customizable error response (Apache style) +# these come in three flavors +# +# 1) plain text +#ErrorDocument 500 "The server made a boo boo. +# n.b. the (") marks it as text, it does not get output +# +# 2) local redirects +#ErrorDocument 404 /missing.html +# to redirect to local url /missing.html +#ErrorDocument 404 /cgi-bin/missing_handler.pl +# n.b. can redirect to a script or a document using server-side-includes. +# +# 3) external redirects +#ErrorDocument 402 http://some.other_server.com/subscription_info.html +# + +# mod_mime_magic allows the server to use various hints from the file itself +# to determine its type. +#MimeMagicFile conf/magic + +# The following directives disable keepalives and HTTP header flushes. +# The first directive disables it for Netscape 2.x and browsers which +# spoof it. There are known problems with these. +# The second directive is for Microsoft Internet Explorer 4.0b2 +# which has a broken HTTP/1.1 implementation and does not properly +# support keepalive when it is used on 301 or 302 (redirect) responses. + +BrowserMatch "Mozilla/2" nokeepalive +BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + +# The following directive disables HTTP/1.1 responses to browsers which +# are in violation of the HTTP/1.0 spec by not being able to grok a +# basic 1.1 response. + +BrowserMatch "RealPlayer 4\.0" force-response-1.0 +BrowserMatch "Java/1\.0" force-response-1.0 +BrowserMatch "JDK/1\.0" force-response-1.0 diff --git a/APACHE_1_3b7/configure b/APACHE_1_3b7/configure new file mode 100755 index 0000000000..2e836b1912 --- /dev/null +++ b/APACHE_1_3b7/configure @@ -0,0 +1,979 @@ +#!/bin/sh +## ==================================================================== +## Copyright (c) 1998 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 . +## + +## +## configure -- Apache Autoconf-style Interface (APACI) +## +## Written by Ralf S. Engelschall +## + +# default input separator chars: +DIFS=' +' + +## +## the paths to the Apache source tree +## + +top=. +mkf=Makefile +src=src +aux=src/helpers +sedsubst=src/.apaci.sedsubst +addconf=src/.apaci.addconf + +## +## pre-determine runtime modes +## + +quiet=no +verbose=no +case "$*" in + --help|*--help|*--help* ) quiet=yes ;; + --quiet|*--quiet|*--quiet* ) quiet=yes ;; + --verbose|*--verbose|*--verbose*|-v|*-v|*-v* ) verbose=yes ;; + * ) ;; +esac + +## +## display version information +## + +if [ ".$quiet" = .no ]; then + APV=`cat $src/include/httpd.h |\ + grep "#define SERVER_BASEVERSION" |\ + sed -e 's/^[^"]*"//' -e 's/".*$//' -e 's/^Apache\///'` + echo "Configuring for Apache, Version $APV" +fi + +## +## important hint for the first-time users +## + +if [ $# -eq 0 ]; then + echo " + Warning: Configuring Apache with default settings." + echo " + This is probably not what you really want." + echo " + Please read the README.configure and INSTALL files" + echo " + first or at least run '$0 --help' for" + echo " + a compact summary of available options." +fi + +## +## determine optional Perl interpreter +## + +PERL=no-perl-on-this-system +OIFS="$IFS" IFS=':' +for dir in $PATH; do + OIFS2="$IFS" IFS="$DIFS" + for exe in perl5 perl miniperl; do + if test -f "$dir/$exe"; then + if test -x "$dir/$exe"; then + PERL="$dir/$exe" + break 2 + fi + fi + done + IFS="$OIFS2" +done +IFS="$OIFS" +PERL="`echo $PERL | sed -e 's://:/:'`" + +## +## determine default parameters +## + +# default paths +prefix='/usr/local/apache' +exec_prefix='$prefix' +bindir='$exec_prefix/bin' +sbindir='$exec_prefix/sbin' +libexecdir='$exec_prefix/libexec' +mandir='$prefix/man' +sysconfdir='$prefix/etc' +datadir='$prefix/share' +includedir='$prefix/include' +localstatedir='$prefix/var' +runtimedir='$localstatedir/run' +logfiledir='$localstatedir/log' +proxycachedir='$localstatedir/proxy' + +# customization flags for +# automatic "apache" suffix +customized_sysconfdir=0 +customized_datadir=0 +customized_localstatedir=0 +customized_includedir=0 + +# check and debug +layout=0 + +# suexec defaults +suexec=0 +suexec_ok=0 +suexec_caller=www +suexec_userdir=public_html +suexec_uidmin=100 +suexec_gidmin=100 +suexec_safepath="/usr/local/bin:/usr/bin:/bin" + +# with support tools +support=1 + +# determine rules +rules="" +rulelist="" +OIFS="$IFS" IFS=' +' +for rule in `grep '^Rule' $src/Configuration.tmpl`; do + rule=`echo "$rule" | sed -e 's/^Rule[ ]*//'` + name=`echo "$rule" | sed -e 's/=.*$//'` + namelow=`echo "$name" | tr "A-Z" "a-z"` + arg=`echo "$rule" | sed -e 's/^.*=//'` + eval "rule_$namelow=$arg" + rules="$rules:$namelow" + rulelist="$rulelist:$name=$arg" +done +IFS="$OIFS" +rules=`echo $rules | sed -e 's/^://'` + +# determine modules +rm -f $addconf 2>/dev/null +touch $addconf +modules="" +modulelist="" +OIFS="$IFS" IFS=' +' +for module in `egrep '^[# ]*(Add|Shared)Module' $src/Configuration.tmpl`; do + add=yes + share=no + if [ ".`echo $module | grep '^#'`" != . ]; then + add=no + fi + if [ ".`echo $module | grep 'SharedModule'`" != . ]; then + share=yes + fi + module=`echo "$module" |\ + sed -e 's%^.*/\(.*\)$%\1%' \ + -e 's/\.[oa]$//' \ + -e 's/^mod_//' \ + -e 's/^lib//'` + eval "module_$module=$add" + eval "shared_$module=$share" + modules="${modules}:$module" + modulelist="${modulelist}:$module=$add" + if [ ".$share" = .yes ]; then + modulelist="${modulelist}*" + fi +done +IFS="$OIFS" +modules=`echo $modules | sed -e 's/^://'` + +# backward compatibility from old src/Configuration.tmpl +# parameter names to the canonical Autoconf-style shell +# variable names. +OIFS="$IFS" IFS="$DIFS" +for var in CFLAGS LDFLAGS LIBS INCLUDES; do + eval "val=\$EXTRA_$var" + if [ ".$val" != . ]; then + eval "$var=\$val" + eval "EXTRA_$var=\"\"; export EXTRA_$var" + echo " + Hint: please use $var instead of EXTRA_$var next time" + fi +done +IFS="$OIFS" + +## +## parse argument line options +## + +apc_prev="" +OIFS1="$IFS" IFS="$DIFS" +for apc_option +do + # if previous option needs an argument, assign it. + if [ ".$apc_prev" != . ]; then + eval "$apc_prev=\$apc_option" + apc_prev="" + continue + fi + # split out arguments + case "$apc_option" in + -*=*) apc_optarg=`echo "$apc_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) apc_optarg= ;; + esac + + # accept only the most important GNU Autoconf-style options + case "$apc_option" in + --quiet | --silent) + quiet=yes + ;; + --verbose | -v) + verbose=yes + ;; + --shadow) + # determine GNU platform triple + gnutriple=`$aux/GuessOS | awk '{ printf("%s",$1); }' | sed -e 's:/:-:g'` + # create Makefile wrapper (the first time only) + if [ ".`ls $top/src.* 2>/dev/null`" = . ]; then + if [ .$quiet = .no ]; then + echo " + creating Makefile (shadow wrapper)" + fi + echo "##" > Makefile + echo "## Apache Makefile (shadow wrapper)" >> Makefile + echo "##" >> Makefile + echo "" >> Makefile + echo "GNUTRIPLE=\`$aux/GuessOS | awk '{ printf(\"%s\",\$\$1); }' | sed -e 's:/:-:g'\`" >> Makefile + echo "" >> Makefile + echo "all build install install-quiet clean distclean:" >> Makefile + echo " @\$(MAKE) -f Makefile.\$(GNUTRIPLE) \$(MFLAGS) \$@" >> Makefile + echo "" >> Makefile + fi + # set shadow paths + shadowmkf="Makefile.$gnutriple" + shadowsrc="src.$gnutriple" + shadowaux="src.$gnutriple/helpers" + shadowsedsubst="src.$gnutriple/.apaci.sedsubst" + shadowaddconf="src.$gnutriple/.apaci.addconf" + # (re)create shadow tree + if [ .$quiet = .no ]; then + echo " + create shadow tree ($shadowsrc)" + fi + rm -rf $shadowsrc + $aux/mkshadow.sh $src $shadowsrc + # delegate us to the shadow paths + mkf=$shadowmkf + src=$shadowsrc + aux=$shadowaux + sedsubst=$shadowsedsubst + rm -f $addconf 2>/dev/null + addconf=$shadowaddconf + rm -f $addconf 2>/dev/null + touch $addconf + ;; + --help | -h | -help ) + echo "Usage: configure [options]" + echo "Options: [defaults in brackets after descriptions]" + echo "General options:" + echo " --quiet, --silent do not print messages" + echo " --verbose, -v print even more messages" + echo " --shadow switch to a shadow tree for building" + echo "" + echo "Stand-alone options:" + echo " --help, -h print this message" + echo " --layout print installation layout (check and debug)" + echo "" + echo "Installation layout options:" + echo " --prefix=PREFIX install architecture-independent files in PREFIX" + echo " --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX" + echo " --bindir=DIR install user executables in DIR [EPREFIX/bin]" + echo " --sbindir=DIR install sysadmin executables in DIR [EPREFIX/sbin]" + echo " --libexecdir=DIR install program executables in DIR [EPREFIX/libexec]" + echo " --mandir=DIR install manual pages in DIR [PREFIX/man]" + echo " --sysconfdir=DIR install configuration files in DIR [PREFIX/etc]" + echo " --datadir=DIR install read-only data files in DIR [PREFIX/share]" + echo " --includedir=DIR install includes files in DIR [PREFIX/include]" + echo " --localstatedir=DIR install modifiable data files in DIR [PREFIX/var]" + echo " --runtimedir=DIR install runtime data in DIR [PREFIX/var/run]" + echo " --logfiledir=DIR install logfile data in DIR [PREFIX/var/log]" + echo " --proxycachedir=DIR install proxy cache data in DIR [PREFIX/var/proxy]" + echo " --compat install with old Apache 1.2 installation paths" + echo "" + echo "Configuration options:" + echo " --enable-rule=NAME enable a particular Rule named 'NAME'" + echo " --disable-rule=NAME disable a particular Rule named 'NAME'" + $aux/ppl.sh $rulelist + echo " --add-module=FILE on-the-fly copy & activate a third-party Module source" + echo " --activate-module=FILE on-the-fly activate existing third-party Module source" + echo " --enable-module=NAME enable a particular Module named 'NAME'" + echo " --disable-module=NAME disable a particular Module named 'NAME'" + $aux/ppl.sh $modulelist + echo " --enable-shared=NAME enable build of Module named 'NAME' as a shared object" + echo " --disable-shared=NAME disable build of Module named 'NAME' as a shared object" + echo " --with-perl=FILE set the path to the optional Perl interpreter to use" + echo " --without-support disable the build and installation of support tools" + echo "" + echo "suEXEC options:" + echo " --enable-suexec enable the suEXEC feature" + echo " --suexec-caller=NAME set the suEXEC username of the allowed caller [$suexec_caller]" + echo " --suexec-userdir=DIR set the suEXEC user subdirectory [$suexec_userdir]" + echo " --suexec-uidmin=UID set the suEXEC minimal allowed UID [$suexec_uidmin]" + echo " --suexec-gidmin=GID set the suEXEC minimal allowed GID [$suexec_gidmin]" + echo " --suexec-safepath=PATH set the suEXEC safe PATH [$suexec_safepath]" + echo "" + exit 0 + ;; + --layout) + layout=1 + ;; + --prefix=*) + prefix="$apc_optarg" + ;; + --exec-prefix=*) + exec_prefix="$apc_optarg" + ;; + --bindir=*) + bindir="$apc_optarg" + ;; + --sbindir=*) + sbindir="$apc_optarg" + ;; + --libexecdir=*) + libexecdir="$apc_optarg" + ;; + --mandir=*) + mandir="$apc_optarg" + ;; + --sysconfdir=*) + sysconfdir="$apc_optarg" + customized_sysconfdir=1 + ;; + --datadir=*) + datadir="$apc_optarg" + customized_datadir=1 + ;; + --includedir=*) + includedir="$apc_optarg" + customized_includedir=1 + ;; + --localstatedir=*) + localstatedir="$apc_optarg" + customized_localstatedir=1 + ;; + --runtimedir=*) + runtimedir="$apc_optarg" + ;; + --logfiledir=*) + logfiledir="$apc_optarg" + ;; + --proxycachedir=*) + proxycachedir="$apc_optarg" + ;; + --compat) + exec_prefix='$prefix' + bindir='$exec_prefix/bin' + sbindir='$exec_prefix/bin' + libexecdir='$exec_prefix/libexec' + mandir='$prefix/man' + sysconfdir='$prefix/conf' + datadir='$prefix' + includedir='$prefix/include' + localstatedir='$prefix' + runtimedir='$localstatedir/logs' + logfiledir='$localstatedir/logs' + proxycachedir='$localstatedir/proxy' + customized_sysconfdir=1 + customized_datadir=1 + customized_localstatedir=1 + customized_includedir=1 + ;; + --add-module=*) + file="$apc_optarg" + case $file in + *.c ) ;; + * ) echo "configure:Error: Module source $file is not a C source file" 1>&2 + exit 1 + ;; + esac + if [ ! -f $file ]; then + echo "configure:Error: Module source $file not found" 1>&2 + exit 1 + fi + modfilec=`echo $file | sed -e 's;^.*/;;'` + modfileo=`echo $file | sed -e 's;^.*/;;' -e 's;\.c$;.o;'` + if [ ".$file" != ".$src/modules/extra/$modfilec" ]; then + cp $file $src/modules/extra/$modfilec + fi + echo "" >>$addconf + echo "## On-the-fly added module" >>$addconf + echo "## (configure --add-module=$file)" >>$addconf + echo "AddModule modules/extra/$modfileo" >>$addconf + module=`echo "$modfileo" |\ + sed -e 's%^.*/\(.*\)$%\1%' \ + -e 's/\.[^.]*$//' \ + -e 's/^mod_//' \ + -e 's/^lib//'` + eval "module_$module=yes" + eval "shared_$module=no" + modules="${modules}:$module" + modulelist="${modulelist}:$module=yes" + if [ ".$quiet" = .no ]; then + echo " + on-the-fly added and activated $module module (modules/extra/$modfileo)" + fi + ;; + --activate-module=*) + file="$apc_optarg" + case $file in + src/modules/* ) ;; + *) echo "configure:Error: Module source already has to stay below src/modules/ to be activated" 1>&2 + exit 1 + ;; + esac + modfile=`echo $file | sed -e 's;^src/;;'` + echo "" >>$addconf + echo "## On-the-fly activated module" >>$addconf + echo "## (configure --activate-module=$file)" >>$addconf + echo "AddModule $modfile" >>$addconf + module=`echo "$modfile" |\ + sed -e 's%^.*/\(.*\)$%\1%' \ + -e 's/\.[^.]*$//' \ + -e 's/^mod_//' \ + -e 's/^lib//'` + eval "module_$module=yes" + eval "shared_$module=no" + modules="${modules}:$module" + modulelist="${modulelist}:$module=yes" + if [ ".$quiet" = .no ]; then + echo " + activated $module module ($modfile)" + fi + ;; + --enable-*) + apc_feature=`echo $apc_option | sed -e 's/-*enable-//' -e 's/=.*//'` + apc_feature=`echo $apc_feature | sed 's/-/_/g'` + case "$apc_option" in + *=*) ;; + *) apc_optarg=yes ;; + esac + case "$apc_feature" in + rule ) + apc_optarg=`echo "$apc_optarg" | tr "A-Z" "a-z"` + apc_optarg_real=`echo "$apc_optarg" | tr "a-z" "A-Z"` + eval "exists=\$rule_${apc_optarg}" + if [ ".$exists" = . ]; then + echo "configure:Error: No such rule named '${apc_optarg_real}'" 1>&2 + exit 1 + fi + eval "rule_${apc_optarg}=yes" + ;; + module ) + case $apc_optarg in + all ) + OIFS="$IFS" IFS=':' + for module in $modules; do + eval "module_${module}=yes" + done + IFS="$OIFS" + ;; + most ) + OIFS="$IFS" IFS=':' + for module in $modules; do + eval "module_${module}=yes" + done + IFS="$OIFS" + module_auth_db=no # not all platforms have -ldb + module_mmap_static=no # not all platforms have mmap() + module_so=no # not all platforms have dlopen() + module_example=no # only for developers + module_log_agent=no # deprecated + module_log_referer=no # deprecated + ;; + * ) + eval "exists=\$module_${apc_optarg}" + if [ ".$exists" = . ]; then + echo "configure:Error: No such module named '${apc_optarg}'" 1>&2 + exit 1 + fi + eval "module_${apc_optarg}=yes" + ;; + esac + ;; + shared ) + case $apc_optarg in + max ) + OIFS="$IFS" IFS=':' + for module in $modules; do + eval "shared_${module}=yes" + done + IFS="$OIFS" + shared_so=no # because of bootstrapping + ;; + remain ) + OIFS="$IFS" IFS=':' + for module in $modules; do + eval "add=\$module_${module}" + if [ ".$add" = .no ]; then + eval "module_${module}=yes" + eval "shared_${module}=yes" + fi + done + IFS="$OIFS" + shared_so=no + ;; + * ) + eval "exists=\$module_${apc_optarg}" + if [ ".$exists" = . ]; then + echo "configure:Error: No such module named '${apc_optarg}'" 1>&2 + exit 1 + fi + eval "shared_${apc_optarg}=yes" + ;; + esac + ;; + suexec ) + if [ ".`id | grep root`" = . ]; then + echo "configure:Error: suEXEC support needs root priviledges for installation" 1>&2 + exit 1 + fi + suexec=1 + ;; + esac + ;; + --disable-*) + apc_feature=`echo $apc_option | sed -e 's/-*disable-//' -e 's/=.*//'` + apc_feature=`echo $apc_feature| sed 's/-/_/g'` + case "$apc_option" in + *=*) ;; + *) apc_optarg=yes ;; + esac + case "$apc_feature" in + rule ) + apc_optarg=`echo "$apc_optarg" | tr "A-Z" "a-z"` + apc_optarg_real=`echo "$apc_optarg" | tr "a-z" "A-Z"` + eval "exists=\$rule_${apc_optarg}" + if [ ".$exists" = . ]; then + echo "configure:Error: No such rule named '${apc_optarg_real}'" 1>&2 + exit 1 + fi + eval "rule_${apc_optarg}=no" + ;; + module ) + case $apc_optarg in + all ) + OIFS="$IFS" IFS=':' + for module in $modules; do + eval "module_${module}=no" + done + IFS="$OIFS" + ;; + * ) + eval "exists=\$module_${apc_optarg}" + if [ ".$exists" = . ]; then + echo "configure:Error: No such module named '${apc_optarg}'" 1>&2 + exit 1 + fi + eval "module_${apc_optarg}=no" + ;; + esac + ;; + shared ) + case $apc_optarg in + all ) + OIFS="$IFS" IFS=':' + for module in $modules; do + eval "shared_${module}=no" + done + IFS="$OIFS" + ;; + * ) + eval "exists=\$module_${apc_optarg}" + if [ ".$exists" = . ]; then + echo "configure:Error: No such module named '${apc_optarg}'" 1>&2 + exit 1 + fi + eval "shared_${apc_optarg}=no" + ;; + esac + ;; + esac + ;; + --with-perl=*) + PERL="$apc_optarg" + ;; + --without-support) + support=0 + ;; + --suexec-caller=*) + suexec_caller="$apc_optarg" + suexec_ok=1 + ;; + --suexec-userdir=*) + suexec_userdir="$apc_optarg" + suexec_ok=1 + ;; + --suexec-uidmin=*) + suexec_uidmin="$apc_optarg" + suexec_ok=1 + ;; + --suexec-gidmin=*) + suexec_gidmin="$apc_optarg" + suexec_ok=1 + ;; + --suexec-safepath=*) + suexec_safepath="$apc_optarg" + suexec_ok=1 + ;; + * ) + echo "configure:Error: invalid option '$apc_option'" 1>&2 + exit 1 + ;; + esac +done +IFS="$OIFS1" +if [ ".$apc_prev" != . ]; then + echo "configure:Error: missing argument to --`echo $apc_prev | sed 's/_/-/g'`" 1>&2 + exit 1 +fi + +## +## a few errors +## +if [ ".$suexec" = .1 ]; then + if [ ".$suexec_ok" = .0 ]; then + echo "configure:Error: You enabled the suEXEC feature via --enable-suexec but" + echo " without explicitly configuring it via at least one" + echo " --suexec-xxxxx option. Seems like you are still not" + echo " familiar with the suEXEC risks. Please read the INSTALL" + echo " and htdocs/manual/suexec.html documents first." + exit 1 + fi +fi + +## +## a few warnings +## +if [ ".$PERL" = .no-perl-on-this-system ]; then + if [ .$quiet = .no ]; then + echo " + Warning: no Perl interpreter available for support scripts." + echo " + Perhaps you have to select one with --with-perl=FILE." + fi +fi + +## +## expand path variables and make sure +## they do not end with a backslash +## +OIFS="$IFS" IFS="$DIFS" +for var in prefix exec_prefix bindir sbindir \ + libexecdir mandir sysconfdir datadir \ + includedir localstatedir runtimedir \ + logfiledir proxycachedir; do + eval "val=\"\$$var\""; + val=`echo $val | sed -e 's:/*$::'` + eval "$var=\"$val\"" + case $var in + sysconfdir|datadir|localstatedir|includedir ) + eval "val=\$$var" + case $val in + *apache | *apache* ) ;; + * ) eval "customized=\$customized_$var" + if [ ".$customized" = .0 ]; then + eval "$var=\"\$$var/apache\"" + fi + ;; + esac + ;; + esac +done +IFS="$OIFS" + +## +## determine special configurable Makefile targets +## +if [ ".$support" = .1 ]; then + build_support=build-support + install_support=install-support + clean_support=clean-support + distclean_support=distclean-support +else + build_support= + install_support= + clean_support= + distclean_support= +fi + +## +## determine prefix-relative paths for directories +## because Apache supports them for the -d and -f +## options, the LoadModule directive, etc. +## +## [we have to make sure that it ends with a slash +## or we cannot support the case where the relative +## path is just the emtpy one, i.e. ""] +## +runtimedir_relative=`echo $runtimedir | sed -e "s:^$prefix/*::" -e 's:\(.\)$:\1/:'` +logfiledir_relative=`echo $logfiledir | sed -e "s:^$prefix/*::" -e 's:\(.\)$:\1/:'` +sysconfdir_relative=`echo $sysconfdir | sed -e "s:^$prefix/*::" -e 's:\(.\)$:\1/:'` +libexecdir_relative=`echo $libexecdir | sed -e "s:^$prefix/*::" -e 's:\(.\)$:\1/:'` + +## +## check and debug +## +if [ ".$layout" = .1 ]; then + echo "" + echo "Installation paths:" + echo " prefix: $prefix" + echo " exec_prefix: $exec_prefix" + echo " bindir: $bindir" + echo " sbindir: $sbindir" + echo " libexecdir: $libexecdir" + echo " mandir: $mandir" + echo " sysconfdir: $sysconfdir" + echo " datadir: $datadir" + echo " includedir: $includedir" + echo " localstatedir: $localstatedir" + echo " runtimedir: $runtimedir" + echo " logfiledir: $logfiledir" + echo " proxycachedir: $proxycachedir" + echo "" + echo "Compilation paths:" + echo " HTTPD_ROOT: $prefix" + echo " SUEXEC_BIN: $sbindir/suexec" + echo " SHARED_CORE_DIR: $libexecdir" + echo " DEFAULT_PIDLOG: ${runtimedir_relative}httpd.pid" + echo " DEFAULT_SCOREBOARD: ${runtimedir_relative}httpd.scoreboard" + echo " DEFAULT_LOCKFILE: ${runtimedir_relative}httpd.lock" + echo " DEFAULT_XFERLOG: ${logfiledir_relative}access_log" + echo " DEFAULT_ERRORLOG: ${logfiledir_relative}error_log" + echo " TYPES_CONFIG_FILE: ${sysconfdir_relative}mime.types" + echo " SERVER_CONFIG_FILE: ${sysconfdir_relative}httpd.conf" + echo " ACCESS_CONFIG_FILE: ${sysconfdir_relative}access.conf" + echo " RESOURCE_CONFIG_FILE: ${sysconfdir_relative}srm.conf" + echo "" + exit 0 +fi + +## +## create Makefile from Makefile.tmpl +## +if [ .$quiet = .no ]; then + echo "Creating $mkf" +fi +sed $mkf \ +-e "s%@PERL@%$PERL%g" \ +-e "s%@TOP@%$top%g" \ +-e "s%@SRC@%$src%g" \ +-e "s%@MKF@%$mkf%g" \ +-e "s%@AUX@%$aux%g" \ +-e "s%@prefix@%$prefix%g" \ +-e "s%@exec_prefix@%$exec_prefix%g" \ +-e "s%@bindir@%$bindir%g" \ +-e "s%@sbindir@%$sbindir%g" \ +-e "s%@libexecdir@%$libexecdir%g" \ +-e "s%@libexecdir_relative@%$libexecdir_relative%g" \ +-e "s%@mandir@%$mandir%g" \ +-e "s%@sysconfdir@%$sysconfdir%g" \ +-e "s%@datadir@%$datadir%g" \ +-e "s%@localstatedir@%$localstatedir%g" \ +-e "s%@includedir@%$includedir%g" \ +-e "s%@runtimedir@%$runtimedir%g" \ +-e "s%@logfiledir@%$logfiledir%g" \ +-e "s%@proxycachedir@%$proxycachedir%g" \ +-e "s%@suexec@%$suexec%g" \ +-e "s%@suexec_caller@%$suexec_caller%g" \ +-e "s%@suexec_userdir@%$suexec_userdir%g" \ +-e "s%@suexec_uidmin@%$suexec_uidmin%g" \ +-e "s%@suexec_gidmin@%$suexec_gidmin%g" \ +-e "s%@suexec_safepath@%$suexec_safepath%g" \ +-e "s%@build_support@%$build_support%g" \ +-e "s%@install_support@%$install_support%g" \ +-e "s%@clean_support@%$clean_support%g" \ +-e "s%@distclean_support@%$distclean_support%g" + +## +## override default paths in $src/include/httpd.h +## via command line arguments for the compiler +## supplied by a little shell script named $src/apaci +## +echo "#!/bin/sh" >$src/apaci +echo "## USED AS A COMMAND LINE EXPANDER TO OVERRIDE PATHS" >>$src/apaci +echo "## WITHOUT DISTURBING THE KNOWN MAKE BUILD PROCESS DISPLAY" >>$src/apaci +echo "echo '-DHTTPD_ROOT=\"$prefix\"'" >>$src/apaci +echo "echo '-DSUEXEC_BIN=\"$sbindir/suexec\"'" >>$src/apaci +echo "echo '-DSHARED_CORE_DIR=\"$libexecdir\"'" >>$src/apaci +echo "echo '-DDEFAULT_PIDLOG=\"${runtimedir_relative}httpd.pid\"'" >>$src/apaci +echo "echo '-DDEFAULT_SCOREBOARD=\"${runtimedir_relative}httpd.scoreboard\"'" >>$src/apaci +echo "echo '-DDEFAULT_LOCKFILE=\"${runtimedir_relative}httpd.lock\"'" >>$src/apaci +echo "echo '-DDEFAULT_XFERLOG=\"${logfiledir_relative}access_log\"'" >>$src/apaci +echo "echo '-DDEFAULT_ERRORLOG=\"${logfiledir_relative}error_log\"'" >>$src/apaci +echo "echo '-DTYPES_CONFIG_FILE=\"${sysconfdir_relative}mime.types\"'" >>$src/apaci +echo "echo '-DSERVER_CONFIG_FILE=\"${sysconfdir_relative}httpd.conf\"'" >>$src/apaci +echo "echo '-DACCESS_CONFIG_FILE=\"${sysconfdir_relative}access.conf\"'" >>$src/apaci +echo "echo '-DRESOURCE_CONFIG_FILE=\"${sysconfdir_relative}srm.conf\"'" >>$src/apaci +chmod a+x $src/apaci +CFLAGS="$CFLAGS \\\`\$(SRCDIR)/apaci\\\`" + +## +## create $src/Configuration.apaci file +## +if [ .$quiet = .no ]; then + echo "Creating Configuration.apaci in $src" +fi +rm -f $sedsubst 2>/dev/null +touch $sedsubst + +# generate settings from imported environment variables +OIFS="$IFS" IFS="$DIFS" +for var in CC OPTIM CFLAGS CFLAGS_SHLIB LDFLAGS LD_SHLIB LDFLAGS_SHLIB \ + LDFLAGS_SHLIB_EXPORT LIBS INCLUDES RANLIB; do + eval "val=\"\$$var\""; + if [ ".$val" != . ]; then + case $var in + CFLAGS|LDFLAGS|LIBS|INCLUDES) + echo "s%^#*\\(EXTRA_$var=\\).*%\\1$val%g" >>$sedsubst + ;; + *) + echo "s%^#*\\($var=\\).*%\\1$val%g" >>$sedsubst + ;; + esac + eval "$var=\"\"; export $var" + fi +done +IFS="$OIFS" + +# generate rule directives +OIFS="$IFS" IFS=':' +for rule in $rules; do + name="`echo $rule | tr "a-z" "A-Z"`" + eval "val=\$rule_$rule" + echo "s%^\\(Rule $name=\\).*%\\1$val%g" >>$sedsubst + if [ $verbose = yes ]; then + echo " + Rule $name=$val" + fi +done +IFS="$OIFS" + +# consistency checks for shared object support +some_shares=0 +OIFS="$IFS" IFS=':' +for module in $modules; do + eval "share=\$shared_$module" + if [ $share = yes ]; then + some_shares=1 + fi +done +IFS="$OIFS" +if [ $some_shares = 1 ]; then + if [ $module_so = no ]; then + module_so=yes + if [ .$quiet = .no ]; then + echo " + enabling mod_so for DSO support" + fi + fi +fi +if [ ".$shared_so" = .yes ]; then + shared_so=no + echo "configure:Error: Module mod_so cannot be made a DSO itself" 1>&2 + exit 1 +fi + +# generate module directives +OIFS="$IFS" IFS=':' +for module in $modules; do + eval "add=\$module_$module" + if [ $add = yes ]; then + echo "s%^.*\\(AddModule.*$module\\..*\\)%\\1%g" >>$sedsubst + echo "s%^.*\\(SharedModule.*$module\\..*\\)%\\1%g" >>$sedsubst + m="yes [static]" + else + echo "s%^.*\\(AddModule.*$module\\..*\\)%# \\1%g" >>$sedsubst + echo "s%^.*\\(SharedModule.*$module\\..*\\)%# \\1%g" >>$sedsubst + m=no + fi + eval "share=\$shared_$module" + if [ $share = yes ]; then + echo "s%^\\(.*\\)AddModule\\(.*$module\\.\\)[oa]\\(.*\\)%\\1SharedModule\\2so\\3%g" >>$sedsubst + m="yes [shared]" + fi + if [ $verbose = yes ]; then + echo " + Module $module: $m" + fi +done +IFS="$OIFS" + +# split sedsubst into chunks of 50 commands +# to workaround limits in braindead seds +files=`awk <$sedsubst ' + BEGIN { line=0; cnt=0; } + { + if (line % 50 == 0) { + file = sedsubst "." cnt; + printf("%s\n", file); + cnt++; + } + line++; + print $0 >file; + } +' "sedsubst=$sedsubst"` +OIFS="$IFS" IFS="$DIFS" +substcmd="" +for file in $files; do + substcmd="${substcmd} sed -f $file |" +done +substcmd="${substcmd} cat" +IFS="$OIFS" + +# and finally translate the config template +# according to our defined configuration +eval "cat $src/Configuration.tmpl $addconf | $substcmd >$src/Configuration.apaci" + +# cleanup +rm -f $sedsubst $sedsubst.[0-9] 2>/dev/null +rm -f $addconf 2>/dev/null + +## +## create all other Makefiles by running the proprietary +## $src/Configure script with our custom Configuration.apaci file +## +if [ .$quiet = .yes ]; then + (cd $src; ./Configure -file Configuration.apaci >/dev/null); +else + (cd $src; ./Configure -file Configuration.apaci |\ + sed -e '/^Using config file:.*/d' \ + -e "s:Makefile in :Makefile in $src\\/:" \ + -e "s:Makefile\$:Makefile in $src:") +fi + diff --git a/APACHE_1_3b7/htdocs/.cvsignore b/APACHE_1_3b7/htdocs/.cvsignore new file mode 100644 index 0000000000..72e8ffc0db --- /dev/null +++ b/APACHE_1_3b7/htdocs/.cvsignore @@ -0,0 +1 @@ +* diff --git a/APACHE_1_3b7/htdocs/apache_pb.gif b/APACHE_1_3b7/htdocs/apache_pb.gif new file mode 100644 index 0000000000000000000000000000000000000000..3a1c139fc4247ec7e770fdaab961fb3692c953fb GIT binary patch literal 2326 zcmeH``#aS60)Ri?F~*GRoWb@r$c#H_jN6u#)66_>GY!UILM{ophO`}&oUt=FmBNTY z$`ICVA7j^+h#i;OQDc-ga!qS+8Gc0FW4f z)Bt1yAj_Q32!U{ zRIo-qQptb-t7{uBm(~px;>}n!KArWR1^>`Cf~is&A3~v0s8aF}M#nn9GGt0d7v`yb z*>S>eMWL(I627?MNllQ7BkqHq)M=1k z=&Ky&zXVh2hPE6DHG1$Mj#+!@W<|fAeonA2iB#Un#%N(&&W1dtI~9BfQ#)e2X=lF^XcGT}q=AoZ{H^5&_C+Pv zN&hQZTYONvvH2qVcG~jIh^yqZXMG0jauI~J<^%?yjPC{pb>Ylqd7Qgl5*ph^Ulf=T ztUu|ceZK)dM=IDKg~q~CZoH&Cb~-~Z=;&lvYG{6Kc>2z^;Sv327g?kssFZ=dw}0cH zdw$mEtN!A<`J8^&z3 zt~SwiD6S8)Rjrr!Kx<)&vBl1-$xbOvcBi~nxrDC!TBPace;L%k*DDqrZ4t4XvN(& zu%4H=wkn0>)>bWw*7qy^XgxfL8hEr{3=!aT@x^9eDj^ytk&Chl$kO(lBLUN|dQ6Gs zqR_gQC$$$-23%rt``_I(>C3A7dOXT9Z$frk_k~-Ys+P;@AA_2Pg%%8=^ZRrL+?~|f zW&~d`K5oo!G0s}dw|gtsI8gBY`D(2K(S?RiMa{{iIhO(d)G0SJjuwocN&dl=)Ns$! zkAoL^`msv}wXFIo9^Egsd~xDITuw=a{)ty}PeNiaZ{?=q1Ff-;&+#A?LvlJm+3a2z z0EU`idSaEFK|F|qEq^5hpn?C2d=DQ+H3YkO^OBqUex<5bLo z9(N*aTe0*iA?|UPIVvKLCc?9Ag1I16-HvOfbsA#dH4-dk3 zhnz>*3E(FdLU+yVpuPUsliM=aeNjZUS*@XX3Z53T6iR8-2uO=XFwVs0@AhefEv8q zeI*^7gje{cZVN8?oK%ZT=2#U=<_Ih7M^R~)Ja%@QBEHt-Nj+won-qIvXTfK$!wnkr z2MQ*#TaAN%Ohqz*uQYER7$<|Jgd}A|ZL~mb$%8Fh^ z{1s=ft;T@}n?u#1Sd8|0dAq@XlaA<)Sy)vu-xZB|?3vPJ`3#PxQkI=}-aLquKdtW{ zRsg5o;PBjI;EgPh^zTEWZ?enGho=a|_a2#rB5> + + + Test Page for Apache Installation on Web Site + + + +

+ It Worked! The Apache Web Server is Installed on this Web Site! +

+

+ If you can see this page, then the people who own this domain have just + installed the Apache Web server + software successfully. They now have to add content to this directory + and replace this placeholder page, or else point the server at their real + content. +

+
+
+ If you are seeing this page instead of the site you expected, please + contact the administrator of the site involved. + (Try sending mail to <Webmaster@domain>.) + Although this site is + running the Apache software it almost certainly has no other connection + to the Apache Group, so please do not send mail about this site or its + contents to the Apache authors. If you do, your message will be + ignored. +
+
+

+ The Apache + documentation + has been included with this distribution. +

+

+ The Webmaster of this site is free to use the image below on + an Apache-powered Web server. Thanks for using Apache! +

+
+ +
+ + diff --git a/APACHE_1_3b7/htdocs/manual/LICENSE b/APACHE_1_3b7/htdocs/manual/LICENSE new file mode 100644 index 0000000000..edb90e071f --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/LICENSE @@ -0,0 +1,59 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + + + diff --git a/APACHE_1_3b7/htdocs/manual/bind.html b/APACHE_1_3b7/htdocs/manual/bind.html new file mode 100644 index 0000000000..75bacbb253 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/bind.html @@ -0,0 +1,135 @@ + + +Setting which addresses and ports Apache uses + + + + + +

Setting which addresses and ports Apache uses

+ +
+ +When Apache starts, it connects to some port and address on the +local machine and waits for incoming requests. By default, it +listens to all addresses on the machine, and to the port +as specified by the Port directive in the server configuration. +However, it can be told to listen to more the one port, or to listen +to only selected addresses, or a combination. This is often combined +with the Virtual Host feature which determines how Apache +responds to different IP addresses, hostnames and ports.

+ +There are two directives used to restrict or specify which addresses +and ports Apache listens to. + +

    +
  • BindAddress is used to restrict the server to + listening to + a single address, and can be used to permit multiple Apache servers + on the same machine listening to different IP addresses. +
  • Listen can be used to make a single Apache server + listen + to more than one address and/or port. +
+ +

BindAddress

+Syntax: BindAddress [ * | IP-address + | hostname ]
+Default: BindAddress *
+Context: server config
+Status: Core

+ +Makes the server listen to just the specified address. If the argument +is *, the server listens to all addresses. The port listened to +is set with the Port directive. Only one BindAddress +should be used. + +

Listen

+Syntax: Listen [ port | IP-address:port ]
+Default: none
+Context: server config
+Status: Core

+ +Listen can be used instead of BindAddress and +Port. It tells the server to accept incoming requests on the +specified port or address-and-port combination. If the first format is +used, with a port number only, the server listens to the given port on +all interfaces, instead of the port given by the Port +directive. If an IP address is given as well as a port, the server +will listen on the given port and interface.

Multiple Listen +directives may be used to specify a number of addresses and ports to +listen to. The server will respond to requests from any of the listed +addresses and ports.

+ +For example, to make the server accept connections on both port +80 and port 8000, use: +

+   Listen 80
+   Listen 8000
+
+ +To make the server accept connections on two specified +interfaces and port numbers, use +
+   Listen 192.170.2.1:80
+   Listen 192.170.2.5:8000
+
+ +

How this works with Virtual Hosts

+ +BindAddress and Listen do not implement Virtual Hosts. They tell the +main server what addresses and ports to listen to. If no +<VirtualHost> directives are used, the server will behave the +same for all accepted requests. However, <VirtualHost> can be +used to specify a different behavior for one or more of the addresses +and ports. To implement a VirtualHost, the server must first be told +to listen to the address and port to be used. Then a +<VirtualHost> section should be created for a specified address +and port to set the behavior of this virtual host. Note that if the +<VirtualHost> is set for an address and port that the server is +not listening to, it cannot be accessed. + +

See also

+ +See also the documentation on +Virtual Hosts, +BindAddress directive, +Port directive, +DNS Issues +and +<VirtualHost> section. + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/cgi_path.html b/APACHE_1_3b7/htdocs/manual/cgi_path.html new file mode 100644 index 0000000000..2b7bd963b1 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/cgi_path.html @@ -0,0 +1,93 @@ + + +PATH_INFO Changes in the CGI Environment + + + + + +

PATH_INFO Changes in the CGI Environment

+ +
+ +

Overview

+ +

As implemented in Apache 1.1.1 and earlier versions, the method +Apache used to create PATH_INFO in the CGI environment was +counterintuitive, and could result in crashes in certain cases. In +Apache 1.2 and beyond, this behavior has changed. Although this +results in some compatibility problems with certain legacy CGI +applications, the Apache 1.2 behavior is still compatible with the +CGI/1.1 specification, and CGI scripts can be easily modified (see below). + +

The Problem

+ +

Apache 1.1.1 and earlier implemented the PATH_INFO and SCRIPT_NAME +environment variables by looking at the filename, not the URL. While +this resulted in the correct values in many cases, when the filesystem +path was overloaded to contain path information, it could result in +errant behavior. For example, if the following appeared in a config +file: +

+     Alias /cgi-ralph /usr/local/httpd/cgi-bin/user.cgi/ralph
+
+

In this case, user.cgi is the CGI script, the "/ralph" +is information to be passed onto the CGI. If this configuration was in +place, and a request came for "/cgi-ralph/script/", the +code would set PATH_INFO to "/ralph/script", and +SCRIPT_NAME to "/cgi-". Obviously, the latter is +incorrect. In certain cases, this could even cause the server to +crash.

+ +

The Solution

+ +

Apache 1.2 and later now determine SCRIPT_NAME and PATH_INFO by +looking directly at the URL, and determining how much of the URL is +client-modifiable, and setting PATH_INFO to it. To use the above +example, PATH_INFO would be set to "/script", and +SCRIPT_NAME to "/cgi-ralph". This makes sense and results +in no server behavior problems. It also permits the script to be +guaranteed that +"http://$SERVER_NAME:$SERVER_PORT$SCRIPT_NAME$PATH_INFO" +will always be an accessible URL that points to the current script, +something which was not necessarily true with previous versions of +Apache. + +

However, the "/ralph" +information from the Alias directive is lost. This is +unfortunate, but we feel that using the filesystem to pass along this +sort of information is not a recommended method, and a script making +use of it "deserves" not to work. Apache 1.2b3 and later, however, do +provide a workaround. + +

Compatibility with Previous Servers

+ +

It may be necessary for a script that was designed for earlier +versions of Apache or other servers to need the information that the +old PATH_INFO variable provided. For this purpose, Apache 1.2 (1.2b3 +and later) sets an additional variable, FILEPATH_INFO. This +environment variable contains the value that PATH_INFO would have had +with Apache 1.1.1.

+ +

A script that wishes to work with both Apache 1.2 and earlier +versions can simply test for the existence of FILEPATH_INFO, and use +it if available. Otherwise, it can use PATH_INFO. For example, in +Perl, one might use: +

+    $path_info = $ENV{'FILEPATH_INFO'} || $ENV{'PATH_INFO'};
+
+ +

By doing this, a script can work with all servers supporting the +CGI/1.1 specification, including all versions of Apache.

+ + + + + diff --git a/APACHE_1_3b7/htdocs/manual/content-negotiation.html b/APACHE_1_3b7/htdocs/manual/content-negotiation.html new file mode 100644 index 0000000000..3f9d60ecf2 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/content-negotiation.html @@ -0,0 +1,527 @@ + + + +Apache Content Negotiation + + + + + +

Content Negotiation

+ +

+Apache's support for content negotiation has been updated to meet the +HTTP/1.1 specification. It can choose the best representation of a +resource based on the browser-supplied preferences for media type, +languages, character set and encoding. It is also implements a +couple of features to give more intelligent handling of requests from +browsers which send incomplete negotiation information.

+ +Content negotiation is provided by the +mod_negotiation module, +which is compiled in by default. + +


+ +

About Content Negotiation

+ +

+A resource may be available in several different representations. For +example, it might be available in different languages or different +media types, or a combination. One way of selecting the most +appropriate choice is to give the user an index page, and let them +select. However it is often possible for the server to choose +automatically. This works because browsers can send as part of each +request information about what representations they prefer. For +example, a browser could indicate that it would like to see +information in French, if possible, else English will do. Browsers +indicate their preferences by headers in the request. To request only +French representations, the browser would send + +

+  Accept-Language: fr
+
+ +

+Note that this preference will only be applied when there is a choice +of representations and they vary by language. +

+ +As an example of a more complex request, this browser has been +configured to accept French and English, but prefer French, and to +accept various media types, preferring HTML over plain text or other +text types, and preferring GIF or JPEG over other media types, but also +allowing any other media type as a last resort: + +

+  Accept-Language: fr; q=1.0, en; q=0.5
+  Accept: text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6,
+        image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1
+
+ +Apache 1.2 supports 'server driven' content negotiation, as defined in +the HTTP/1.1 specification. It fully supports the Accept, +Accept-Language, Accept-Charset and Accept-Encoding request headers. +

+ +The terms used in content negotiation are: a resource is an +item which can be requested of a server, which might be selected as +the result of a content negotiation algorithm. If a resource is +available in several formats, these are called representations +or variants. The ways in which the variants for a particular +resource vary are called the dimensions of negotiation. + +

Negotiation in Apache

+ +

+In order to negotiate a resource, the server needs to be given +information about each of the variants. This is done in one of two +ways: + +

    +
  • Using a type map (i.e., a *.var file) which + names the files containing the variants explicitly +
  • Or using a 'MultiViews' search, where the server does an implicit + filename pattern match, and chooses from among the results. +
+ +

Using a type-map file

+ +

+A type map is a document which is associated with the handler +named type-map (or, for backwards-compatibility with +older Apache configurations, the mime type +application/x-type-map). Note that to use this feature, +you've got to have a SetHandler some place which defines a +file suffix as type-map; this is best done with a +

+
+  AddHandler type-map var
+
+
+in srm.conf. See comments in the sample config files for +details.

+ +Type map files have an entry for each available variant; these entries +consist of contiguous RFC822-format header lines. Entries for +different variants are separated by blank lines. Blank lines are +illegal within an entry. It is conventional to begin a map file with +an entry for the combined entity as a whole (although this +is not required, and if present will be ignored). An example +map file is: +

+
+  URI: foo
+
+  URI: foo.en.html
+  Content-type: text/html
+  Content-language: en
+
+  URI: foo.fr.de.html
+  Content-type: text/html; charset=iso-8859-2
+  Content-language: fr, de
+
+ +If the variants have different source qualities, that may be indicated +by the "qs" parameter to the media type, as in this picture (available +as jpeg, gif, or ASCII-art): +
+  URI: foo
+
+  URI: foo.jpeg
+  Content-type: image/jpeg; qs=0.8
+
+  URI: foo.gif
+  Content-type: image/gif; qs=0.5
+
+  URI: foo.txt
+  Content-type: text/plain; qs=0.01
+
+
+

+ +qs values can vary between 0.000 and 1.000. Note that any variant with +a qs value of 0.000 will never be chosen. Variants with no 'qs' +parameter value are given a qs factor of 1.0.

+ +The full list of headers recognized is: + +

+
URI: +
uri of the file containing the variant (of the given media + type, encoded with the given content encoding). These are + interpreted as URLs relative to the map file; they must be on + the same server (!), and they must refer to files to which the + client would be granted access if they were to be requested + directly. +
Content-type: +
media type --- charset, level and "qs" parameters may be given. These + are often referred to as MIME types; typical media types are + image/gif, text/plain, or + text/html; level=3. +
Content-language: +
The languages of the variant, specified as an Internet standard + language code (e.g., en for English, + kr for Korean, etc.). +
Content-encoding: +
If the file is compressed, or otherwise encoded, rather than + containing the actual raw data, this says how that was done. + For compressed files (the only case where this generally comes + up), content encoding should be + x-compress, or x-gzip, as appropriate. +
Content-length: +
The size of the file. Clients can ask to receive a given media + type only if the variant isn't too big; specifying a content + length in the map allows the server to compare against these + thresholds without checking the actual file. +
+ +

Multiviews

+ +

+This is a per-directory option, meaning it can be set with an +Options directive within a <Directory>, +<Location> or <Files> +section in access.conf, or (if AllowOverride +is properly set) in .htaccess files. Note that +Options All does not set MultiViews; you +have to ask for it by name. (Fixing this is a one-line change to +http_core.h). + +

+ +The effect of MultiViews is as follows: if the server +receives a request for /some/dir/foo, if +/some/dir has MultiViews enabled, and +/some/dir/foo does not exist, then the server reads the +directory looking for files named foo.*, and effectively fakes up a +type map which names all those files, assigning them the same media +types and content-encodings it would have if the client had asked for +one of them by name. It then chooses the best match to the client's +requirements, and forwards them along. + +

+ +This applies to searches for the file named by the +DirectoryIndex directive, if the server is trying to +index a directory; if the configuration files specify +

+
+  DirectoryIndex index
+
+
then the server will arbitrate between index.html +and index.html3 if both are present. If neither are +present, and index.cgi is there, the server will run it. + +

+ +If one of the files found when reading the directive is a CGI script, +it's not obvious what should happen. The code gives that case +special treatment --- if the request was a POST, or a GET with +QUERY_ARGS or PATH_INFO, the script is given an extremely high quality +rating, and generally invoked; otherwise it is given an extremely low +quality rating, which generally causes one of the other views (if any) +to be retrieved. + +

The Negotiation Algorithm

+ +After Apache has obtained a list of the variants for a given resource, +either from a type-map file or from the filenames in the directory, it +applies a algorithm to decide on the 'best' variant to return, if +any. To do this it calculates a quality value for each variant in each +of the dimensions of variance. It is not necessary to know any of the +details of how negotiation actually takes place in order to use Apache's +content negotiation features. However the rest of this document +explains in detail the algorithm used for those interested.

+ +In some circumstances, Apache can 'fiddle' the quality factor of a +particular dimension to achieve a better result. The ways Apache can +fiddle quality factors is explained in more detail below. + +

Dimensions of Negotiation

+ + +
Dimension +Notes +
Media Type +Browser indicates preferences on Accept: header. Each item +can have an associated quality factor. Variant description can also +have a quality factor. +
Language +Browser indicates preferences on Accept-Language: header. Each +item +can have a quality factor. Variants can be associated with none, one +or more languages. +
Encoding +Browser indicates preference with Accept-Encoding: header. +
Charset +Browser indicates preference with Accept-Charset: header. Variants +can indicate a charset as a parameter of the media type. +
+ +

Apache Negotiation Algorithm

+ +

+Apache uses an algorithm to select the 'best' variant (if any) to +return to the browser. This algorithm is not configurable. It operates +like this: + +

    +
  1. +Firstly, for each dimension of the negotiation, the appropriate +Accept header is checked and a quality assigned to this each +variant. If the Accept header for any dimension means that this +variant is not acceptable, eliminate it. If no variants remain, go +to step 4. + +
  2. Select the 'best' variant by a process of elimination. Each of +the following tests is applied in order. Any variants not selected at +each stage are eliminated. After each test, if only one variant +remains, it is selected as the best match. If more than one variant +remains, move onto the next test. + +
      +
    1. Multiply the quality factor from the Accept header with the + quality-of-source factor for this variant's media type, and select + the variants with the highest value + +
    2. Select the variants with the highest language quality factor + +
    3. Select the variants with the best language match, using either the + order of languages on the LanguagePriority directive (if + present), + else the order of languages on the Accept-Language header. + +
    4. Select the variants with the highest 'level' media parameter + (used to give the version of text/html media types). + +
    5. Select only unencoded variants, if there is a mix of encoded + and non-encoded variants. If either all variants are encoded + or all variants are not encoded, select all. + +
    6. Select only variants with acceptable charset media parameters, + as given on the Accept-Charset header line. Charset ISO-8859-1 + is always acceptable. Variants not associated with a particular + charset are assumed to be in ISO-8859-1. + +
    7. Select the variants with the smallest content length + +
    8. Select the first variant of those remaining (this will be either the +first listed in the type-map file, or the first read from the directory) +and go to stage 3. + +
    + +
  3. The algorithm has now selected one 'best' variant, so return + it as the response. The HTTP response header Vary is set to indicate the + dimensions of negotiation (browsers and caches can use this + information when caching the resource). End. + +
  4. To get here means no variant was selected (because non are acceptable + to the browser). Return a 406 status (meaning "No acceptable representation") + with a response body consisting of an HTML document listing the + available variants. Also set the HTTP Vary header to indicate the + dimensions of variance. + +
+ +

Fiddling with Quality Values

+ +

+Apache sometimes changes the quality values from what would be +expected by a strict interpretation of the algorithm above. This is to +get a better result from the algorithm for browsers which do not send +full or accurate information. Some of the most popular browsers send +Accept header information which would otherwise result in the +selection of the wrong variant in many cases. If a browser +sends full and correct information these fiddles will not +be applied. +

+ +

Media Types and Wildcards

+ +

+The Accept: request header indicates preferences for media types. It +can also include 'wildcard' media types, such as "image/*" or "*/*" +where the * matches any string. So a request including: +

+  Accept: image/*, */*
+
+ +would indicate that any type starting "image/" is acceptable, +as is any other type (so the first "image/*" is redundant). Some +browsers routinely send wildcards in addition to explicit types they +can handle. For example: +
+  Accept: text/html, text/plain, image/gif, image/jpeg, */*
+
+ +The intention of this is to indicate that the explicitly +listed types are preferred, but if a different representation is +available, that is ok too. However under the basic algorithm, as given +above, the */* wildcard has exactly equal preference to all the other +types, so they are not being preferred. The browser should really have +sent a request with a lower quality (preference) value for *.*, such +as: +
+  Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01
+
+ +The explicit types have no quality factor, so they default to a +preference of 1.0 (the highest). The wildcard */* is given +a low preference of 0.01, so other types will only be returned if +no variant matches an explicitly listed type. +

+ +If the Accept: header contains no q factors at all, Apache sets +the q value of "*/*", if present, to 0.01 to emulate the desired +behavior. It also sets the q value of wildcards of the format +"type/*" to 0.02 (so these are preferred over matches against +"*/*". If any media type on the Accept: header contains a q factor, +these special values are not applied, so requests from browsers +which send the correct information to start with work as expected. + +

Variants with no Language

+ +

+If some of the variants for a particular resource have a language +attribute, and some do not, those variants with no language +are given a very low language quality factor of 0.001.

+ +The reason for setting this language quality factor for +variant with no language to a very low value is to allow +for a default variant which can be supplied if none of the +other variants match the browser's language preferences. + +For example, consider the situation with three variants: + +

    +
  • foo.en.html, language en +
  • foo.fr.html, language en +
  • foo.html, no language +
+ +

+The meaning of a variant with no language is that it is +always acceptable to the browser. If the request Accept-Language +header includes either en or fr (or both) one of foo.en.html +or foo.fr.html will be returned. If the browser does not list +either en or fr as acceptable, foo.html will be returned instead. + +

Note on hyperlinks and naming conventions

+ +

+If you are using language negotiation you can choose between +different naming conventions, because files can have more than one +extension, and the order of the extensions is normally irrelevant +(see mod_mime documentation for details). +

+A typical file has a mime-type extension (e.g. html), +maybe an encoding extension (e.g. gz and of course a +language extension (e.g. en) when we have different +language variants of this file. + +

+Examples: +

    +
  • foo.en.html +
  • foo.html.en +
  • foo.en.html.gz +
+ +

+Here some more examples of filenames together with valid and invalid +hyperlinks: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FilenameValid hyperlinkInvalid hyperlink
foo.html.enfoo
+ foo.html
-
foo.en.htmlfoofoo.html
foo.html.en.gzfoo
+ foo.html
foo.gz
+ foo.html.gz
foo.en.html.gzfoofoo.html
+ foo.html.gz
+ foo.gz
foo.gz.html.enfoo
+ foo.gz
+ foo.gz.html
foo.html
foo.html.gz.enfoo
+ foo.html
+ foo.html.gz
foo.gz
+ +

+Looking at the table above you will notice that it is always possible to +use the name without any extensions in an hyperlink (e.g. foo). +The advantage is that you can hide the actual type of a +document rsp. file and can change it later, e.g. from html +to shtml or cgi without changing any +hyperlink references. + +

+If you want to continue to use a mime-type in your hyperlinks (e.g. +foo.html) the language extension (including an encoding extension +if there is one) must be on the right hand side of the mime-type extension +(e.g. foo.html.en). + + +

Note on Caching

+ +

+When a cache stores a document, it associates it with the request URL. +The next time that URL is requested, the cache can use the stored +document, provided it is still within date. But if the resource is +subject to content negotiation at the server, this would result in +only the first requested variant being cached, and subsequent cache +hits could return the wrong response. To prevent this, +Apache normally marks all responses that are returned after content negotiation +as non-cacheable by HTTP/1.0 clients. Apache also supports the HTTP/1.1 +protocol features to allow caching of negotiated responses.

+ +For requests which come from a HTTP/1.0 compliant client (either a +browser or a cache), the directive CacheNegotiatedDocs can be +used to allow caching of responses which were subject to negotiation. +This directive can be given in the server config or virtual host, and +takes no arguments. It has no effect on requests from HTTP/1.1 +clients. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/custom-error.html b/APACHE_1_3b7/htdocs/manual/custom-error.html new file mode 100644 index 0000000000..c76f224e26 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/custom-error.html @@ -0,0 +1,177 @@ + + + +Custom error responses + + + + + +

Custom error responses

+ +
+ +
Purpose + +
Additional functionality. Allows webmasters to configure the response of + Apache to some error or problem. + +

Customizable responses can be defined to be activated in the + event of a server detected error or problem. + +

e.g. if a script crashes and produces a "500 Server Error" + response, then this response can be replaced with either some + friendlier text or by a redirection to another URL (local or + external). +

+ +

Old behavior + +
NCSA httpd 1.3 would return some boring old error/problem message + which would often be meaningless to the user, and would provide no + means of logging the symptoms which caused it.
+ +

+ +

New behavior + +
The server can be asked to; +
    +
  1. Display some other text, instead of the NCSA hard coded messages, or +
  2. redirect to a local URL, or +
  3. redirect to an external URL. +
+ +

Redirecting to another URL can be useful, but only if some information + can be passed which can then be used to explain and/or log the + error/problem + more clearly. + +

To achieve this, Apache will define new CGI-like environment + variables, e.g. + +

+REDIRECT_HTTP_ACCEPT=*/*, image/gif, image/x-xbitmap, image/jpeg
+REDIRECT_HTTP_USER_AGENT=Mozilla/1.1b2 (X11; I; HP-UX A.09.05 9000/712)
+REDIRECT_PATH=.:/bin:/usr/local/bin:/etc
+REDIRECT_QUERY_STRING=
+REDIRECT_REMOTE_ADDR=121.345.78.123
+REDIRECT_REMOTE_HOST=ooh.ahhh.com
+REDIRECT_SERVER_NAME=crash.bang.edu
+REDIRECT_SERVER_PORT=80
+REDIRECT_SERVER_SOFTWARE=Apache/0.8.15
+REDIRECT_URL=/cgi-bin/buggy.pl
+
+ +

note the REDIRECT_ prefix. + +

At least REDIRECT_URL and REDIRECT_QUERY_STRING + will + be passed to the new URL (assuming it's a cgi-script or a cgi-include). + The + other variables will exist only if they existed prior to the + error/problem. + None of these will be set if your ErrorDocument is an + external redirect (i.e., anything starting with a + scheme name + like http:, even if it refers to the same host as the + server).

+ +

Configuration + +
Use of "ErrorDocument" is enabled for .htaccess files when the + "FileInfo" override is + allowed. + +

Here are some examples... + +

+ErrorDocument 500 /cgi-bin/crash-recover
+ErrorDocument 500 "Sorry, our script crashed. Oh dear
+ErrorDocument 500 http://xxx/
+ErrorDocument 404 /Lame_excuses/not_found.html
+ErrorDocument 401 /Subscription/how_to_subscribe.html +
+ +

The syntax is, + +

ErrorDocument +<3-digit-code> action + +

where the action can be, + +

    +
  1. Text to be displayed. Prefix the text with a quote ("). Whatever + follows the quote is displayed. Note: the (") prefix isn't + displayed. + +
  2. An external URL to redirect to. + +
  3. A local URL to redirect to. + +
+
+ +


+ +

Custom error responses and redirects

+ +
+ +
Purpose + +
Apache's behavior to redirected URLs has been modified so that additional + environment variables are available to a script/server-include.

+ +

Old behavior + +
Standard CGI vars were made available to a script which has been + redirected to. No indication of where the redirection came from was + provided. + +

+ +

New behavior +
+ +A new batch of environment variables will be initialized for use by a +script which has been redirected to. Each new variable will have the +prefix REDIRECT_. REDIRECT_ environment +variables are created from the CGI environment variables which existed +prior to the redirect, they are renamed with a REDIRECT_ +prefix, i.e. HTTP_USER_AGENT becomes +REDIRECT_HTTP_USER_AGENT. In addition to these new +variables, Apache will define REDIRECT_URL and +REDIRECT_STATUS to help the script trace its origin. +Both the original URL and the URL being redirected to can be logged in +the access log. + +
+

+If the ErrorDocument specifies a local redirect to a CGI script, the script +should include a "Status:" header field in its output +in order to ensure the propagation all the way back to the client +of the error condition that caused it to be invoked. For instance, a Perl +ErrorDocument script might include the following: +

+
+      :
+    print  "Content-type: text/html\n";
+    printf "Status: %s Condition Intercepted\n", $ENV{"REDIRECT_STATUS"};
+      :
+
+

+If the script is dedicated to handling a particular error condition, such as +404 Not Found, it can use the specific code and +error text instead. +

+ + + + diff --git a/APACHE_1_3b7/htdocs/manual/dns-caveats.html b/APACHE_1_3b7/htdocs/manual/dns-caveats.html new file mode 100644 index 0000000000..cbf8a57a9d --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/dns-caveats.html @@ -0,0 +1,189 @@ + + +Issues Regarding DNS and Apache + + + + + +

Issues Regarding DNS and Apache

+ +

This page could be summarized with the statement: don't require +Apache to use DNS for any parsing of the configuration files. +If Apache has to use DNS to parse the configuration files then your +server may be subject to reliability problems (it might not boot), or +denial and theft of service attacks (including users able to steal hits +from other users). + +

A Simple Example

+ +Consider this configuration snippet: + +
+    <VirtualHost www.abc.dom>
+    ServerAdmin webgirl@abc.dom
+    DocumentRoot /www/abc
+    </VirtualHost>
+
+ +

In order for Apache to function properly it absolutely needs +to have two pieces of information about each virtual host: the +ServerName +and at least one IP address that the server +responds to. This example does not include the IP address, so Apache +must use DNS to find the address of www.abc.dom. If for +some reason DNS is not available at the time your server is parsing its +config file, then this virtual host will not be configured. It +won't be able to respond to any hits to this virtual host (prior to +Apache version 1.2 the server would not even boot). + +

Suppose that www.abc.dom has address 10.0.0.1. Then +consider this configuration snippet: + +

+    <VirtualHost 10.0.0.1>
+    ServerAdmin webgirl@abc.dom
+    DocumentRoot /www/abc
+    </VirtualHost>
+
+ +

Now Apache needs to use reverse DNS to find the ServerName +for this virtualhost. If that reverse lookup fails then it will partially +disable the virtualhost (prior to Apache version 1.2 the server would not +even boot). If the virtual host is name-based then it will effectively +be totally disabled, but if it is IP-based then it will mostly work. +However if Apache should ever have to generate a full URL for the server +which includes the server name then it will fail to generate a valid URL. + +

Here is a snippet that avoids both of these problems. + +

+    <VirtualHost 10.0.0.1>
+    ServerName www.abc.dom
+    ServerAdmin webgirl@abc.dom
+    DocumentRoot /www/abc
+    </VirtualHost>
+
+ +

Denial of Service

+ +

There are (at least) two forms that denial of service can come in. +If you are running a version of Apache prior to version 1.2 then your +server will not even boot if one of the two DNS lookups mentioned above +fails for any of your virtual hosts. In some cases this DNS lookup may +not even be under your control. For example, if abc.dom +is one of your customers and they control their own DNS then they +can force your (pre-1.2) server to fail while booting simply by deleting the +www.abc.dom record. + +

Another form is far more insidious. Consider this configuration +snippet: + +

+    <VirtualHost www.abc.dom>
+    ServerAdmin webgirl@abc.dom
+    DocumentRoot /www/abc
+    </VirtualHost>
+
+ +
+    <VirtualHost www.def.dom>
+    ServerAdmin webguy@def.dom
+    DocumentRoot /www/def
+    </VirtualHost>
+
+ +

Suppose that you've assigned 10.0.0.1 to www.abc.dom and +10.0.0.2 to www.def.dom. Furthermore, suppose that +def.com has control of their own DNS. With this config +you have put def.com into a position where they can steal +all traffic destined to abc.com. To do so, all they have to +do is set www.def.dom to 10.0.0.1. +Since they control their own DNS you can't stop them from pointing the +www.def.com record wherever they wish. + +

Requests coming in to 10.0.0.1 (including all those where users typed +in URLs of the form http://www.abc.dom/whatever) will all be +served by the def.com virtual host. To better understand why +this happens requires a more in-depth discussion of how Apache matches +up incoming requests with the virtual host that will serve it. A rough +document describing this is available. + +

The "main server" Address

+ +

The addition of name-based virtual host +support in Apache 1.1 requires Apache to know the IP address(es) of +the host that httpd is running on. To get this address it uses either +the global ServerName (if present) or calls the C function +gethostname (which should return the same as typing +"hostname" at the command prompt). Then it performs a DNS lookup on +this address. At present there is no way to avoid this lookup. + +

If you fear that this lookup might fail because your DNS server is down +then you can insert the hostname in /etc/hosts (where you +probably already have it so that the machine can boot properly). Then +ensure that your machine is configured to use /etc/hosts +in the event that DNS fails. Depending on what OS you are using this +might be accomplished by editing /etc/resolv.conf, or maybe +/etc/nsswitch.conf. + +

If your server doesn't have to perform DNS for any other reason +then you might be able to get away with running Apache with the +HOSTRESORDER environment variable set to "local". This all +depends on what OS and resolver libraries you are using. It also affects +CGIs unless you use mod_env +to control the environment. It's best to consult the man pages or FAQs +for your OS. + +

Tips to Avoid these problems

+ +
    +
  • use IP addresses in <VirtualHost> +
  • use IP addresses in Listen +
  • use IP addresses in BindAddress +
  • ensure all virtual hosts have an explicit ServerName +
  • create a <VirtualHost _default_:*> server that + has no pages to serve +
+ +

Appendix: Future Directions

+ +

The situation regarding DNS is highly undesirable. For Apache +1.2 we've attempted to make the server at least continue booting +in the event of failed DNS, but it might not be the best we +can do. In any event requiring the use of explicit IP addresses in +configuration files is highly undesirable in today's Internet where renumbering + is a necessity. + +

A possible work around to the theft of service attack described above +would be to perform a reverse DNS lookup on the ip address returned by +the forward lookup and compare the two names. In the event of a mismatch +the virtualhost would be disabled. This would require reverse DNS to be +configured properly (which is something that most admins are familiar with +because of the common use of "double-reverse" DNS lookups by FTP servers +and TCP wrappers). + +

In any event it doesn't seem possible to reliably boot a virtual-hosted +web server when DNS has failed unless IP addresses are used. Partial +solutions such as disabling portions of the configuration might be worse +than not booting at all depending on what the webserver is supposed +to accomplish. + +

As HTTP/1.1 is deployed and browsers and proxies start issuing the +Host header it will become possible to avoid the use of +IP-based virtual hosts entirely. In this event a webserver has no requirement +to do DNS lookups during configuration. But as of March 1997 these +features have not been deployed widely enough to be put into use on +critical webservers. + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/dso.html b/APACHE_1_3b7/htdocs/manual/dso.html new file mode 100644 index 0000000000..0d79f7ee67 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/dso.html @@ -0,0 +1,384 @@ + + +Apache 1.3 Dynamic Shared Object (DSO) support + + + + +

+ + +
+ +

+Apache 1.3
+Dynamic Shared Object (DSO)
+Support +

+ +
Originally written by
+Ralf S. Engelschall <rse@apache.org>, April 1998
+ +
+ +

Background

+ +

On modern Unix derivatives there exists a nifty mechanism usually called +dynamic linking/loading of Dynamic Shared Objects (DSO) which +provides a way to build a piece of program code in a special format for +loading it at run-time into the address space of an executable program. + +

This loading can usually be done in two ways: Automatically by a system +program called ld.so when an executable program is started or +manually from within the executing program via a programmatic system interface +to the Unix loader through the system calls dlopen()/dlsym(). + +

In the first way the DSO's are usually called shared libraries or +DSO libraries and named libfoo.so or +libfoo.so.1.2. They reside in a system directory (usually +/usr/lib) and the link to the executable program is established +at build-time by specifying -lfoo to the linker command. This +hard-codes library references into the executable program file so that at +start-time the Unix loader is able to locate libfoo.so in +/usr/lib, in paths hard-coded via linker-options like +-R or in paths configured via the environment variable +LD_LIBRARY_PATH. It then resolves any (yet unresolved) symbols in +the executable program which are available in the DSO. + +

Symbols in the executable program are usually not referenced by the DSO +(because it's a reusable library of general code) and hence no further +resolving has to be done. The executable program has no need to do anything on +its own to use the symbols from the DSO because the complete resolving is done +by the Unix loader. (In fact, the code to invoke ld.so is part of +the run-time startup code which is linked into every executable program which +has been bound non-static). The advantage of dynamic loading of common library +code is obvious: the library code needs to be stored only once, in a system +library like libc.so, saving disk space for every program. + +

In the second way the DSO's are usually called shared objects or +DSO files and can be named with an arbitrary extension (although the +canonical name is foo.so). These files usually stay inside a +program-specific directory and there is no automatically established link to +the executable program where they are used. Instead the executable program +manually loads the DSO at run-time into its address space via +dlopen(). At this time no resolving of symbols from the DSO for +the executable program is done. But instead the Unix loader automatically +resolves any (yet unresolved) symbols in the DSO from the set of symbols +exported by the executable program and its already loaded DSO libraries +(especially all symbols from the ubiquitous libc.so). This way +the DSO gets knowledge of the executable program's symbol set as if it had +been statically linked with it in the first place. + +

Finally, to take advantage of the DSO's API the executable program has to +resolve particular symbols from the DSO via dlsym() for later use +inside dispatch tables etc. In other words: The executable program has to +manually resolve every symbol it needs to be able to use it. The advantage of +such a mechanism is that optional program parts need not be loaded (and thus +do not spend memory) until they are needed by the program in question. When +required, these program parts can be loaded dynamically to extend the base +program's functionality. + +

Although this DSO mechanism sounds straightforward there is at least one +difficult step here: The resolving of symbols from the executable program for +the DSO when using a DSO to extend a program (the second way). Why? Because +"reverse resolving" DSO symbols from the executable program's symbol set is +against the library design (where the library has no knowledge about the +programs it is used by) and is neither available under all platforms nor +standardized. In practice the executable program's global symbols are often +not re-exported and thus not available for use in a DSO. Finding a way to +force the linker to export all global symbols is the main problem one has to +solve when using DSO for extending a program at run-time. + +

Practical Usage

+ +

The shared library approach is the typical one, because it is what the DSO +mechanism was designed for, hence it is used for nearly all types of libraries +the operating system provides. On the other hand using shared objects for +extending a program is not used by a lot of programs. + +

As of 1998 there are only a few software packages available which use the +DSO mechanism to actually extend their functionality at run-time: Perl 5 (via +its XS mechanism and the DynaLoader module), Netscape Server, etc. Starting +with version 1.3, Apache joined the crew, because Apache already uses a module +concept to extend its functionality and internally uses a dispatch-list-based +approach to link external modules into the Apache core functionality. So, +Apache is really predestined for using DSO to load its modules at run-time. + +

As of Apache 1.3, the configuration system supports two optional features +for taking advantage of the modular DSO approach: compilation of the Apache +core program into a DSO library for shared usage and compilation of the +Apache modules into DSO files for explicit loading at run-time. + +

Implementation

+ +

The DSO support for loading individual Apache modules is based on a module +named mod_so.c which has to be +statically compiled into the Apache core. It is the only module besides +http_core.c which cannot be put into a DSO itself +(bootstrapping!). Practically all other distributed Apache modules then can +then be placed into a DSO by individually enabling the DSO build for them via +configure's --enable-shared option (see top-level +INSTALL file) or by changing the AddModule command +in your src/Configuration into a SharedModule +command (see src/INSTALL file). After a module is compiled into +a DSO named mod_foo.so you can use mod_so's LoadModule command in your +httpd.conf file to load this module at server startup or restart. + +

To simplify this creation of DSO files for Apache modules (especially for +third-party modules) a new support program named apxs (APache +eXtenSion) is available. It can be used to build DSO based modules +outside of the Apache source tree. The idea is simple: When +installing Apache the configure's make install +procedure installs the Apache C header files and puts the platform-dependent +compiler and linker flags for building DSO files into the apxs +program. This way the user can use apxs to compile his Apache +module sources without the Apache distribution source tree and without having +to fiddle with the platform-dependent compiler and linker flags for DSO +support. + +

To place the complete Apache core program into a DSO library (only required +on some of the supported platforms to force the linker to export the apache +core symbols -- a prerequisite for the DSO modularization) the rule +SHARED_CORE has to be enabled via configure's +--enable-rule=SHARED_CORE option (see top-level +INSTALL file) or by changing the Rule command in +your Configuration file to Rule SHARED_CORE=yes (see +src/INSTALL file). The Apache core code is then placed into a DSO +library named libhttpd.so. Because one cannot link a DSO against +static libraries on all platforms, an additional executable program named +libhttpd.ep is created which both binds this static code and +provides a stub for the main() function. Finally the +httpd executable program itself is replaced by a bootstrapping +code which automatically makes sure the Unix loader is able to load and start +libhttpd.ep by providing the LD_LIBRARY_PATH to +libhttpd.so. + +

Supported Platforms

+ +

Apache's src/Configure script currently has only limited but +adequate built-in knowledge on how to compile DSO files, because as already +mentioned this is heavily platform-dependent. Nevertheless all major Unix +platforms are supported. The definitive current state (May 1998) is this: + +

+

    +
  • Out-of-the-box supported platforms:
    +(actually tested versions in parenthesis) + +
    +o  FreeBSD            (2.1.5, 2.2.5, 2.2.6)
    +o  OpenBSD            (2.x)
    +o  NetBSD             (1.3.1)
    +o  Linux              (Debian/1.3.1, RedHat/4.2)
    +o  Solaris            (2.4, 2.5.1, 2.6)
    +o  SunOS              (4.1.3)
    +o  OSF1               (4.0)
    +o  IRIX               (6.2)
    +o  HP/UX              (10.20)
    +o  UnixWare           (2.01, 2.1.2)
    +o  AIX                (3.2, 4.1.5, 4.2, 4.3)
    +o  ReliantUNIX/SINIX  (5.43)
    +o  SVR4               (-)
    +
    + +

    +

  • Explicitly unsupported platforms: + +
    +o  Ultrix             (no dlopen-style interface under this platform)
    +
    + +
+ +

Usage Summary

+ +

To give you an overview of the DSO features of Apache 1.3, here is a short +and concise summary: + +

    + +
  1. Placing the Apache core code (all the stuff which usually forms the +httpd binary) into a DSO libhttpd.so, an executable +program libhttpd.ep and a bootstrapping executable program +httpd (Notice: this is only required on some of the supported +platforms to force the linker to export the Apache core symbols, which in turn +is a prerequisite for the DSO modularization): + +

    +

      +
    • Build and install via configure (preferred): +
      +
      +$ ./configure --prefix=/path/to/install
      +              --enable-rule=SHARED_CORE ...
      +$ make install
      +
      +
      + +
    • Build and install manually: +
      +
      +- Edit src/Configuration:
      +  << Rule SHARED_CORE=default
      +  >> Rule SHARED_CORE=yes
      +  << EXTRA_CFLAGS= 
      +  >> EXTRA_CFLAGS= -DSHARED_CORE_DIR=\"/path/to/install/libexec\"
      +$ make 
      +$ cp src/libhttpd.so* /path/to/install/libexec/
      +$ cp src/libhttpd.ep  /path/to/install/libexec/
      +$ cp src/httpd        /path/to/install/bin/
      +
      +
      +
    + +
  2. Build and install a distributed Apache module, say +mod_foo.c, into its own DSO mod_foo.so: + +

    +

      +
    • Build and install via configure (preferred): +
      +
      +$ ./configure --prefix=/path/to/install
      +        --enable-shared=foo
      +$ make install
      +
      +
      + +
    • Build and install manually: +
      +
      +- Edit src/Configuration:
      +  << AddModule    modules/xxxx/mod_foo.o
      +  >> SharedModule modules/xxxx/mod_foo.so
      +$ make
      +$ cp src/xxxx/mod_foo.so /path/to/install/libexec
      +- Edit /path/to/install/etc/httpd.conf
      +  >> LoadModule foo_module /path/to/install/libexec/mod_foo.so
      +
      +
      +
    + +
  3. Build and install a third-party Apache module, say +mod_foo.c, into its own DSO mod_foo.so + +

    +

      +
    • Build and install via configure (preferred): +
      +
      +$ ./configure --add-module=/path/to/3rdparty/mod_foo.c 
      +        --enable-shared=foo
      +$ make install
      +
      +
      + +
    • Build and install manually: +
      +
      +$ cp /path/to/3rdparty/mod_foo.c /path/to/apache-1.3/src/modules/extra/
      +- Edit src/Configuration:
      +  >> SharedModule modules/extra/mod_foo.so
      +$ make
      +$ cp src/xxxx/mod_foo.so /path/to/install/libexec
      +- Edit /path/to/install/etc/httpd.conf
      +  >> LoadModule foo_module /path/to/install/libexec/mod_foo.so
      +
      +
      +
    + +

    +

  4. Build and install a third-party Apache module, say +mod_foo.c, into its own DSO mod_foo.so outside +of the Apache source tree: + +

    +

      +
    • Build and install via apxs: +
      +
      +$ cd /path/to/3rdparty
      +$ apxs -c mod_foo.c
      +$ apxs -i -a -n foo mod_foo.so
      +
      +
      +
    + +
+ +

Advantages & Disadvantages

+ +

The above DSO based features of Apache 1.3 have the following advantages: + +

    +
  • The server package is more flexible at run-time because the actual server + process can be assembled at run-time via LoadModule + httpd.conf configuration commands instead of + Configuration AddModule commands at build-time. + For instance this way one is able to run different server instances + (standard & SSL version, minimalistic & powered up version + [mod_perl, PHP3], etc.) with only one Apache installation. +

    +

  • The server package can be easily extended with third-party modules even + after installation. This is at least a great benefit for vendor package + maintainers who can create a Apache core package and additional packages + containing extensions like PHP3, mod_perl, mod_fastcgi, etc. +

    +

  • Easier Apache module prototyping because with the DSO/apxs + pair you can both work outside the Apache source tree and only need an + apxs -i command followed by an apachectl + restart to bring a new version of your currently developed module + into the running Apache server. +
+ +

DSO has the following disadvantages: + +

    +
  • The DSO mechanism cannot be used on every platform because not all + operating systems support dynamic loading of code into the address space + of a program. +

    +

  • The server is approximately 20% slower at startup time because of the + symbol resolving overhead the Unix loader now has to do. +

    +

  • The server is approximately 5% slower at execution time under some + platforms because position independent code (PIC) sometimes needs + complicated assembler tricks for relative addressing which are not + necessarily as fast as absolute addressing. +

    +

  • Because DSO modules cannot be linked against other DSO-based libraries + (ld -lfoo) on all platforms (for instance a.out-based + platforms usually don't provide this functionality while ELF-based + platforms do) you cannot use the DSO mechanism for all types of modules. + Or in other words, modules compiled as DSO files are restricted to only + use symbols from the Apache core, from the C library (libc) + and all other dynamic or static libraries used by the Apache core, or + from static library archives (libfoo.a) containing position + independent code. The only chance to use other code is to either make + sure the Apache core itself already contains a reference to it or loading + the code yourself via dlopen(). +

    +

  • Under some platforms (many SVR4 systems) there is no way to force the + linker to export all global symbols for use in DSO's when linking the + Apache httpd executable program. But without the visibility of the Apache + core symbols no standard Apache module could be used as a DSO. The only + chance here is to use the SHARED_CORE feature because this + way the global symbols are forced to be exported. As a consequence the + Apache src/Configure script automatically enforces + SHARED_CORE on these platforms when DSO features are used in + the Configuration file or on the configure command line. +
+ + +
+ + diff --git a/APACHE_1_3b7/htdocs/manual/ebcdic.html b/APACHE_1_3b7/htdocs/manual/ebcdic.html new file mode 100644 index 0000000000..8d97c989e3 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/ebcdic.html @@ -0,0 +1,497 @@ + + + +The Apache EBCDIC Port + + + + + +

Overview of the Apache EBCDIC Port

+ +

+ Version 1.3 of the Apache HTTP Server is the first version which + includes a port to a (non-ASCII) mainframe machine which uses + the EBCDIC character set as its native codeset.
+ (It is the SIEMENS NIXDORF family of mainframes running the + BS2000/OSD + operating system. This mainframe OS nowadays features a + SVR4-derived POSIX subsystem). +

+ +

+ The port was started initially to +

    +
  • prove the feasibility of porting + the Apache HTTP server + to this platform +
  • find a "worthy and capable" successor for the venerable + CERN-3.0 daemon + (which was ported a couple of years ago), and to +
  • prove that Apache's preforking process model can on this platform + easily outperform the accept-fork-serve model used by CERN by a + factor of 5 or more. +
+

+ +

+ This document serves as a rationale to describe some of the design + decisions of the port to this machine. +

+ +

Design Goals

+

+ One objective of the EBCDIC port was to maintain enough backwards + compatibility with the (EBCDIC) CERN server to make the transition to + the new server attractive and easy. This required the addition of + a configurable method to define whether a HTML document was stored + in ASCII (the only format accepted by the old server) or in EBCDIC + (the native document format in the POSIX subsystem, and therefore + the only realistic format in which the other POSIX tools like grep + or sed could operate on the documents). The current solution to + this is a "pseudo-MIME-format" which is intercepted and + interpreted by the Apache server (see below). Future versions + might solve the problem by defining an "ebcdic-handler" for all + documents which must be converted. +

+ +

Technical Solution

+

+ Since all Apache input and output is based upon the BUFF data type + and its methods, the easiest solution was to add the conversion to + the BUFF handling routines. The conversion must be settable at any + time, so a BUFF flag was added which defines whether a BUFF object + has currently enabled conversion or not. This flag is modified at + several points in the HTTP protocol: +

    +
  • set before a request is received (because the + request and the request header lines are always in ASCII + format) + +
  • set/unset when the request body is + received - depending on the content type of the request body + (because the request body may contain ASCII text or a binary file) + +
  • set before a reply header is sent (because the + response header lines are always in ASCII format) + +
  • set/unset when the response body is + sent - depending on the content type of the response body + (because the response body may contain text or a binary file) +
+

+ +

Porting Notes

+

+

    +
  1. + The relevant changes in the source are #ifdef'ed into two + categories: +
    +
    #ifdef CHARSET_EBCDIC +
    Code which is needed for any EBCDIC based machine. This + includes character translations, differences in + contiguity of the two character sets, flags which + indicate which part of the HTTP protocol has to be + converted and which part doesn't etc. +
    #ifdef _OSD_POSIX +
    Code which is needed for the BS2000 SIEMENS NIXDORF + mainframe platform only. This deals with include file + differences and socket implementations topics which are + only required on the BS2000/OSD platform. +
    +

  2. + +
  3. + The possibility to translate between ASCII and EBCDIC at the + socket level (on BS2000 POSIX, there is a socket option which + supports this) was intentionally not chosen, because + the byte stream at the HTTP protocol level consists of a + mixture of protocol related strings and non-protocol related + raw file data. HTTP protocol strings are always encoded in + ASCII (the GET request, any Header: lines, the chunking + information etc.) whereas the file transfer parts (i.e., GIF + images, CGI output etc.) should usually be just "passed through" + by the server. This separation between "protocol string" and + "raw data" is reflected in the server code by functions like + bgets() or rvputs() for strings, and functions like bwrite() + for binary data. A global translation of everything would + therefore be inadequate.
    + (In the case of text files of course, provisions must be made so + that EBCDIC documents are always served in ASCII) +

  4. + +
  5. + This port therefore features a built-in protocol level conversion + for the server-internal strings (which the compiler translated to + EBCDIC strings) and thus for all server-generated documents. + The hard coded ASCII escapes \012 and \015 which are + ubiquitous in the server code are an exception: they are + already the binary encoding of the ASCII \n and \r and must + not be converted to ASCII a second time. This exception is + only relevant for server-generated strings; and external + EBCDIC documents are not expected to contain ASCII newline characters. +

  6. + +
  7. + By examining the call hierarchy for the BUFF management + routines, I added an "ebcdic/ascii conversion layer" which + would be crossed on every puts/write/get/gets, and a + conversion flag which allowed enabling/disabling the + conversions on-the-fly. Usually, a document crosses this + layer twice from its origin source (a file or CGI output) to + its destination (the requesting client): file -> + Apache, and Apache -> client.
    + The server can now read the header + lines of a CGI-script output in EBCDIC format, and then find + out that the remainder of the script's output is in ASCII + (like in the case of the output of a WWW Counter program: the + document body contains a GIF image). All header processing is + done in the native EBCDIC format; the server then determines, + based on the type of document being served, whether the + document body (except for the chunking information, of + course) is in ASCII already or must be converted from EBCDIC. +

  8. + +
  9. + For Text documents (MIME types text/plain, text/html etc.), + an implicit translation to ASCII can be used, or (if the + users prefer to store some documents in raw ASCII form for + faster serving, or because the files reside on a NFS-mounted + directory tree) can be served without conversion. +
    + Example:
    + to serve files with the suffix .ahtml as a raw ASCII text/html + document without implicit conversion (and suffix .ascii + as ASCII text/plain), use the directives:
    +      AddType  text/x-ascii-html  .ahtml
    +      AddType  text/x-ascii-plain .ascii
    +      
    + Similarly, any text/XXXX MIME type can be served as "raw ASCII" by + configuring a MIME type "text/x-ascii-XXXX" for it using AddType. +

  10. + +
  11. + Non-text documents are always served "binary" without conversion. + This seems to be the most sensible choice for, .e.g., GIF/ZIP/AU + file types. This of course requires the user to copy them to the + mainframe host using the "rcp -b" binary switch. +

  12. + +
  13. + Server parsed files are always assumed to be in native (i.e., + EBCDIC) format as used on the machine, and are converted after + processing. +

  14. + +
  15. + For CGI output, the CGI script determines whether a conversion is + needed or not: by setting the appropriate Content-Type, text files + can be converted, or GIF output can be passed through unmodified. + An example for the latter case is the wwwcount program which we ported + as well. +

  16. +
+

+ +

Document Storage Notes

+

Binary Files

+

+ All files with a Content-Type: which does not + start with text/ are regarded as binary files + by the server and are not subject to any conversion. + Examples for binary files are GIF images, gzip-compressed + files and the like. +

+

+ When exchanging binary files between the mainframe host and a + Unix machine or Windows PC, be sure to use the ftp "binary" + (TYPE I) command, or use the + rcp -b command from the mainframe host + (the -b switch is not supported in unix rcp's). +

+ +

Text Documents

+

+ The default assumption of the server is that Text Files + (i.e., all files whose Content-Type: starts with + text/) are stored in the native character + set of the host, EBCDIC. +

+ +

Server Side Included Documents

+

+ SSI documents must currently be stored in EBCDIC only. No + provision is made to convert it from ASCII before processing. +

+ +

Apache Modules' Status

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Module + Status + Notes +
http_core + + + +
mod_access + + + +
mod_actions + ? + +
mod_alias + + + +
mod_asis + ? + +
mod_auth + + + +
mod_auth_anon + + + +
mod_auth_db + ? + with own libdb.a +
mod_auth_dbm + ? + with own libdb.a +
mod_autoindex + + + +
mod_cern_meta + ? + +
mod_cgi + + + +
mod_digest + - + MD5 not ported yet +
mod_dir + + + +
mod_dld + - + no shared libs +
mod_env + + + +
mod_example + - + not tried yet +
mod_expires + + + +
mod_headers + + + +
mod_imap + + + +
mod_include + + + +
mod_info + + + +
mod_log_agent + + + +
mod_log_config + + + +
mod_log_referer + + + +
mod_mime + + + +
mod_mime_magic + - + not tried yet +
mod_negotiation + + + +
mod_proxy + + + +
mod_rewrite + ? + untested +
mod_setenvif + + + +
mod_speling + + + +
mod_status + + + +
mod_unique_id + + + +
mod_userdir + + + +
mod_usertrack + ? + untested +
+ +

Third Party Modules' Status

+ + + + + + + + + + + + + + + + +
Module + Status + Notes +
mod_jserv + - + JAVA still being ported. +
mod_php + - + not ported yet +
mod_put + ? + untested +
mod_session + - + untested +
+ + + + diff --git a/APACHE_1_3b7/htdocs/manual/env.html b/APACHE_1_3b7/htdocs/manual/env.html new file mode 100644 index 0000000000..6235076c4c --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/env.html @@ -0,0 +1,46 @@ + + + +Special Purpose Environment Variables + + + + + +

Special Purpose Environment Variables

+

Interoperability problems have led to the introduction of +mechanisms to modify the way Apache behaves when talking to particular +clients. To make these mechanisms as flexible as possible, they +are invoked by defining environment variables, typically with +BrowserMatch, though +SetEnv and +PassEnv could also be used, for +example.

+ +

nokeepalive

+This disables KeepAlive when set. Because +of problems with Netscape 2.x and KeepAlive, we recommend the following +directive be used: +
+BrowserMatch Mozilla/2 nokeepalive +
+ +

force-response-1.0

+This forces an HTTP/1.0 response when set. It was originally implemented as a +result of a problem with AOL's proxies. Some clients may not behave correctly +when given an HTTP/1.1 response, and this can be used to interoperate with +them. + +

downgrade-1.0

+

This forces the request to be treated as a HTTP/1.0 request even if it +was in a later dialect. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/expand.pl b/APACHE_1_3b7/htdocs/manual/expand.pl new file mode 100755 index 0000000000..79b997fe9f --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/expand.pl @@ -0,0 +1,104 @@ +#!/usr/local/bin/perl5 + +# This is a very simple Perl script to expand server-side includes +# in the directory it is run, and direct subdirectories. It will +# work only on SSI directives of the form +# +# +# +# Filename must be relative to the directory the file appears in. +# +# Nov 30, 1996 - Alexei Kosut + +# ==================================================================== +# Copyright (c) 1996-1998 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. +# +# 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 . + +# Put a list of dirs (except ..) into @dirs + +opendir DIR, "." or die "Could not open directory: $!"; +@dirs = grep !/^\.\.$/, (grep -d, readdir DIR); +closedir DIR; + +foreach $dir (@dirs) { + print "Entering directory $dir\n"; + opendir SUBDIR, "$dir" or die "Could not open subdir $dir: $!"; + foreach $file (grep /\.html$/, readdir SUBDIR) { + print "Expanding file $dir/$file\n"; + rename "$dir/$file", "$dir/${file}.old"; + open READ, "$dir/${file}.old" or die "Couldn't read $dir/$file: $!"; + open WRITE, ">$dir/$file" or die "Couldn't write $dir/$file: $!"; + while ($r = ) { + if ($r =~ //) { + ($pre, $include, $post) = ($`, $1, $'); + print WRITE $pre; + + open INC, "$dir/$include" or + print "Could not include file $dir/$include: $!"; + print WRITE while (); + close INC; + + print WRITE $post; + } + else { + print WRITE $r; + } + } + close READ; + close WRITE; + unlink "$dir/$file.old"; + } + closedir SUBDIR; +} + + diff --git a/APACHE_1_3b7/htdocs/manual/footer.html b/APACHE_1_3b7/htdocs/manual/footer.html new file mode 100644 index 0000000000..c82d24e722 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/footer.html @@ -0,0 +1,6 @@ +


+

+ Apache HTTP Server Version 1.3 +

+ +Index diff --git a/APACHE_1_3b7/htdocs/manual/handler.html b/APACHE_1_3b7/htdocs/manual/handler.html new file mode 100644 index 0000000000..84cd97c06b --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/handler.html @@ -0,0 +1,167 @@ + + + +Apache's Handler Use + + + + + +

Apache's Handler Use

+ +

What is a Handler

+ +

A "handler" is an internal Apache representation of the action to be +performed when a file is called. Generally, files have implicit +handlers, based on the file type. Normally, all files are simply +served by the server, but certain file typed are "handled" +separately. For example, you may use a type of +"application/x-httpd-cgi" to invoke CGI scripts.

+ +

Apache 1.1 adds the additional ability to use handlers +explicitly. Either based on filename extensions or on location, these +handlers are unrelated to file type. This is advantageous both because +it is a more elegant solution, but it also allows for both a type +and a handler to be associated with a file.

+ +

Handlers can either be built into the server or to a module, or +they can be added with the Action directive. The built-in +handlers in the standard distribution are as follows:

+ +
    +
  • send-as-is: + Send file with HTTP headers as is. + (mod_asis) +
  • cgi-script: + Treat the file as a CGI script. + (mod_cgi) +
  • imap-file: + Imagemap rule file. + (mod_imap) +
  • server-info: + Get the server's configuration information + (mod_info) +
  • server-parsed: + Parse for server-side includes + (mod_include) +
  • server-status: + Get the server's status report + (mod_status) +
  • type-map: + Parse as a type map file for content negotiation + (mod_negotiation) +
+ +

+ +

Directives

+ + +
+ +

AddHandler

+ +Syntax: <AddHandler handler-name + extension>
+Context: server config, virtual host, directory, + .htaccess
+Status: Base
+Module: mod_mime + +

AddHandler maps the filename extension extension to the +handler handler-name. For example, to activate CGI scripts +with the file extension ".cgi", you might use: +

+    AddHandler cgi-script cgi
+
+ +

Once that has been put into your srm.conf or httpd.conf file, any +file ending with ".cgi" will be treated as a CGI +program.

+ +
+ +

SetHandler

+ +Syntax: <SetHandler handler-name>
+Context: directory, .htaccess
+Status: Base
+Module: mod_mime + +

When placed into an .htaccess file or a +<Directory> or <Location> section, +this directive forces all matching files to be parsed through the +handler given by handler-name. For example, if you had a +directory you wanted to be parsed entirely as imagemap rule files, +regardless of extension, you might put the following into an +.htaccess file in that directory: +

+    SetHandler imap-file
+
+

Another example: if you wanted to have the server display a status +report whenever a URL of http://servername/status was +called, you might put the following into access.conf: +

+    <Location /status>
+    SetHandler server-status
+    </Location>
+
+ +


+ +

Programmer's Note

+ +

In order to implement the handler features, an addition has been +made to the Apache API that you may wish to +make use of. Specifically, a new record has been added to the +request_rec structure:

+
+    char *handler
+
+

If you wish to have your module engage a handler, you need only to +set r->handler to the name of the handler at any time +prior to the invoke_handler stage of the +request. Handlers are implemented as they were before, albeit using +the handler name instead of a content type. While it is not +necessary, the naming convention for handlers is to use a +dash-separated word, with no slashes, so as to not invade the media +type name-space.

+ + + + + diff --git a/APACHE_1_3b7/htdocs/manual/header.html b/APACHE_1_3b7/htdocs/manual/header.html new file mode 100644 index 0000000000..c0959dc7aa --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/header.html @@ -0,0 +1,6 @@ +
+ [APACHE DOCUMENTATION] +

+ Apache HTTP Server Version 1.3 +

+
diff --git a/APACHE_1_3b7/htdocs/manual/images/custom_errordocs.gif b/APACHE_1_3b7/htdocs/manual/images/custom_errordocs.gif new file mode 100644 index 0000000000000000000000000000000000000000..d566c5d891e5c574267fe715fc10706c5702b790 GIT binary patch literal 23291 zcmbq(Wl$VV7w+PVyM`nLcMC2FL4pK#54N}mx4`0yJ1i31-95OwySoS1Gk!sySv-L!2t{gJ3BioDLsL`yXJ0O0)1{Ox-4`A@tRfY-PCO=AZE*gL9gRbz&MnB z9Qq&JH|ufe>znELIQ!eXH|5Q5eEfC%Kdf)%+i>5IgI)p9*SC2559lj9=#?G%%KrNL zA5hRM2>J?oeH-u_rdKHF^(_Q%2>!nl^M5V;_bmV@Fkg7Ee?VYRa7ZX5EIcAIDmo@M zE)S?=?}zb)E%hI>JG-Cl1Y=Q%I*y#`E0o|P?ggkMS+R6MMs}I7)P&C ztUFkpH=M+7Jd`$Qzf}m!8Sm(Zo%Ig?{cEp*YQX3Ke_WfFC64K?8B*?hxuuUf)0Id$Yvu3H*A^@G zeF~Ta*;W^%2L*}Ng2=LZ~8wWJhbLJF;c9sT7yr0YEr;}bi!=XPniz&@kaAiguXiDmr2`@ zf)pFrz;=csICvt~X6|>m$kfGxkFIn@+*t0$ znYD9dE15i<+qu6&WSSPUC%Kp6bLZ+Lm@{Z0DXXQGM2k8lzNkRWs5&^{PMr(5*t&Qz zqp_?e6N0wiP@ibUYSQSKf1E|c+P~5=VJM}U6xB7mnd*UjSd_nFd2Ce2q%33BKDWnU zn-)U&OqpUd1Y!C6jmPt>hXAIrOXw)iGiVzy#?Nn=1qgF|@xNH8Iv~ubt4+qm9RNRruf@{%jA5#~AbbWfa{+k%- ze#6K0JKv^Cur4>8o$-nC>ab`JN$>Wd&BJaqcX`tu%(|R3hxc3L!$EG6t-yjR_Eg7F zX~Ws$ab-X2(@E{T?bB)Fe)-c`>)qMYc?SyH^F19X2oZ3a^UVwkn^f$;RI`95m8cx1o|4j zL=Kdry~qS(3m~EVxd+l+4q5QEQsB9|iA#LT4pN9WBI+&dWs;eMXr3$}(-HKcnZbWr*Lu&`IlKA4b-ijZ_x$otLL8FtC&o-{C&(d;4$Mw7fn*RH z3oqJXB$t*2X4oUpRTAVTYe2lrC-qG|#v+3&mkP~d@T;j(jD_qDBeB+yc5`*CsTYXC zYH(QY@iHmJjf_U;q3i6>A;~Iti`muUhfH)#3}NdoaTEQp*wkg>0=X%xnzW>aHeT`u z#y;2E4=wY7GM_mikdRx2s7A{8mB@JXhr6X2r0FIG+(nt8F|D3XgP zRxKcdwHH9+i#11!)ioA?g|;^(2ACy6t&DTk(3{d_3MTFOp}Be=(K6eJ65ahHpcB?c zx!Y)o{@u`g`{PZ8FJ`F$%8!LEvfIiKxl$wI;e|ed+p6e@QWLr#i$mJC)ybo!KU?-& z$2@LpGBL}{C4VeUL2qjd<;pA_T-5^dl=F+1wM7?tkLGxH({3B zbMyOck=->8NR(6Hq4@#D0UtWvmpc`Nb?s=+HxF|&AhzP^9eLcfz>jnw_E@c8ge0}@ zzCTB-4*Q}+J6W$lmc`9bHLpAp6?92+AhG$-ZLyOS*QuKC({vb`aO>Lf`G%5KsyGzZ zinZ0gCTxf7;kowjmI$8ElG zKhrB~H9nI|$&^ntSNLOX47rStt{|vP*?uzNns>_hM#KKqqIi#ZKQ`RO>&j<#z%+Dh zS}`?-fm&$Am+>e6uufuG)M%KWDq>0lsd;S-9R?gVRVAE$5m!P=nyHOEXQ9xTLsnhu z;jTwTefF8-wWF7Y{5W62ub_O0l81C6R3-0hrLa6_1SsxOn+58 zrNsd^aSNa`IgvJY5i91Z2EJ3oz>dIBS&*^iV`tjg9;$TlhU5X^O8#2ywM*+6Vur_R z2~%C`zaKIns;f*!7PD`!7Aop%?=m~p4=M~!CqWJD0adKODqhNl0@m^I1N%5zr-irN z#|h!TV>#x$dk=so;a?`{)sBZe@|@^`p?Fw(wS?)Wl7R~=Ypm%3e@loG--!T>v4(C^qLN#bIJ$AJq+**L=K z=on~8vPdLuTi8+OQwAMersOm)vqkA=t?J*@hUD_1ZihAod1wQ)yG%Dc5a ztsXwNnlJr|I5E@SYFDun9PQRquQKk~j-_>EWR12N_FS35Bj{)tg>8a8m-4d8JzRgS z*fcA^hRS(7HVtj;#ctEqxzG65T%#1y5On7JuuTP>EAIOczRuP0dhV!=pDh?|9BCw7 zUp2s1hJS8cW=3VjPPW-IA`9ffo!bkP2wlxvEe>C;IgX}|?0>#AG*%0wqj8v@?wRUMQBmgNYneFk^H2<^sP{iNYAaoFMb8=VpD z-ANW~PHBX5P{2%@0oxPcYYBJrS%3ZzxGi5eh0prJ3x3p^j^Et^*L?$|lXak3{`!Ud zswBc68+|l2gLZNP%y#*^5Ch&Niik-CnUVxM(qmgDf3r?D0UHGVY7F+03U=1~cEA;6 zz7QOs88Ukj?0aBy4hjih2wCwB`75g9e-IL{8M;6bnwT64<->C6)xa&#$|Qkg^FeYo zA^C2Q!emHsBcyZzf<+WiLKs%f7gnnoR__+pm>kyZrd`(Sygbi-55@kQ=vM((*q9wbMi zO{fjH8RA^%43TJz6h>ZaM%}ta-6uyqHby-!M8Py8RXQSF-7K>Abted;&b!^y=&-K_ zFt8q?aY$qE_+tpPVu;*hRB)n|gTld;dhL9uaFzPIInlTs(W7oL^eM57O|i_2v8)fV z#nCbFp`q~xew5O{Gbv#_04B9XELtWhJ88Tqf4sO>{CBMw&ZZayQjaZ-xN%;%V&Aw{ zHDNpo0Gfq~e|8|oEf6!56YDU+-XVSvkk}xS*kh1rl#*yk8qX;$C?e(f@c~HY=0|KF z_nu$oR>Px)2zA02purD^sF*-kmy|dGOGy5gPzFdeNg*xiNUkS^b{(u%knm!SlHpKv)I7~?8PoE7% z&pk}3+(_GShwf-)6c)vB-5Ut@#n|zE!@I~(N(nw^021HF_a-TO?8&Upe1An@3sFq) zDT-bW1pGx!>$`JmL3ZvBO&l3S$6QKZDoRUPOvbZJ-(*N9gk+IwC;qKWClJWkBh99? zM3+v<$h}R}$P4zr$Y3T*V1dab)h$|82mfFPStW2ud;kIAd;vctV};0aP!il;^F3K> zGesCu5<|(Q7@=WJSwxmu*u`1np()aj$;uG!G_5R>Z5~OP^dFEs14yo}KzfdJo)Tj| z74$8~I~HW9*T-|rK+6ZSon#8gG?Q>Cl2Pk_qc+>Ux~QTx#I-f0B5G%jAi8by*w-}t zLf1|=W6Ur-%8Px>HD5~C(9Sc4=E*;%3`(bbgrvzG<)x8jDQFYqG8SP#v!aXhOD&<+ z(2UTa>~HiQVdg+*j}jtt6TNw7f5}`}ku~J8#8(CgUdq9@hocDvh>+#-dw8H&0wZM7 zqaKUWWy<0hi(wRKc~h2o8QNtUkTR8}vOLC=WtpNS%c3I2@*j`sWlQDkgZVaOCDlto zM>*L{9wjctC8M)Crh6s6w^jqLgSr)=M{EEOPjK~aAQse00&XN7bHk10Rmvl%qJ&7e5cs+$eW62*k6Fx9Ue1eoER>YVSGUSn z8P25^%$J7Ntqj(wE+q#aCaWG7>4nvYFV-h7r5O&_TMd`9=rquyR+P+HpJGJcz0%%QqZT8I8c2q*N#lDB3wLRpF5yDC7VD%qnE_#%?Se1!$Bqp^qC51KMCW(`$ z1UpCr-L;$X44Rja8#l!Oqcm`Bp*7K|3OTlp2AdjFTbgyCZo@%#WFh|Sju$tL z1v;(cgmAqQUl7^h&QX)AQ?W3cTBZcsW`?WVJmo!)wZrY3qmFgkQIlJdnzm|MW6;~^ zwAv0*+mBij=a&t$JZbEuN)ad8&hJ}wxT8o@{yw(+eO~?xd-@9??|>KTK-BF(_UZtp zb)dC&V61dtJ$K-ccj5_k5(vea5Vz(^>WxTslCN}rcI0iXS-nEfOWK%EAY8iLJYL;=Y25;8S_2Cje;T_*$a_SEdc<{mzI*jZd1+2`17x4! zWk&$=2D30~a!vpV z;UacvLxpLBPUOSw&%+&QeKjk-xzD{tUL!%JgJtYUD%S9-CnNIYBU3`7u$j{QXpE8^ zuVIbY;X!Nowdc{Xk)elo0L7D05|zH$w6UYsF$wq4qwTRDt-}M>@CssY`z>SR&!bSk zv6Gc?*z-6+Q$MW-s9twSUuhsIZT!(|{7!Zp%Vz8r1MrM7L7+ED#DW1Y{EhVecvAR; zitgA3#^_!+Ic>+73>p+;sE8i3VR?}c%cErqeL7UDg;09h%wn3@8@=qd+aqrjC1S!} zw^yxn$nF`Qs*IGTZH!Z{+|;U=aWyUeVMeJeo$n=Cxh&DiYF4XlCfRdZw;4k>eY$4C z^7rnvzx_~g_>iMDd}!%kICdnoh#A_|sT`Tv`JyQe%vrhgSr0i_hPzFR&dWTx=k$l+ z`4*fxqxa}p7z6Rv6aLY|EwX*0a=m4(Xd~7$80n<=dZQX`b-H0wZZGK#VGEya7TBbh zdU56oy%)g37$xZorIpjRi~0dxBW#M}>((=9n3KsdGe^v`bm>K1ZS&C#OIfQ+a;NhZ zEEu|avmKQy?SR$F_ke0lLBe_c=+z!2@=21b35?T;Ht+FYZBxI{8%&31_RD57^_KcE z>rJfI4Bo9@3eTSF6=@+X1)kRRmeoDT&FXl}cgWSzv25JfOslo5BeAYlwNCFlt=ecV zr|9;MJx^e_EjOHwZoi-HmfLWNSW6mAQ5ap9Kdn1VU-5>?mCHPG(YDtgTW)Q-*LR+7 zIu1{9lrOQ5Z5;^LQ)A7(p006!Xb}3a4I9~bzqgUtI#j~E7{@Xrn-;_IF!w^f^iF^6 z=jo)@oY<0Zr3<+*ATX;qMwq}G;eUWPO`jbg*72Q zW^Kv>G*90V9i4kd-zCU(+7jv;12mj01DD*%R*apWkwIIXv(p|fs8b{v**nD=sM zvbBIF^Ww{w z)mQnmMAnPy@_*N-r-rs0XdnNfV_&_q``3?k*2lUa+CDP?yCA_nXT<(@vhwflYylj7 zj{Bv5_R9sA-64L(wOqv+iNf^x*cG4f4dTx$IG-z%j2occh0ypJ()!Kkzhk17OrZv+dnt-rRig z$+sPZM{j%e8FR}qay>y{59F~O%6b-neHD*=b2@gX_Iv%Z{X|E5&+Yei zPuZQz+R2CCx8KM2rLZ5mGIn)-t~A&_ww&)dEZ?21t#|#sWIkOpe$5;Bb4B^(Id<)_ z?#F#^`AJ{Y^B3&>UWJ#?^^K2FBbKAXRM^V{r?b(2mRi5U3bbxreRk|iZxw}Lo99dU zHn5tr>r1x8gTMFsaF^mNz3b~o=dUZi0054Nrny^4a$)1Z!ofX|l!0Gbiy_2KtEg#k z@$dna3{8N2VuHdK$|zz9)do=DL=VA4p1KS?byBUYn2w&%$yey5n60JKEJ|BPR!Wm) zfu}-pdN#t^9>tKMVwMZC)S(}#KiXST`JA7OF1yag>{-4l{IvTW_0d;1ZTDhuth+ss(gEB6 z$%bIE;Y~|%7L26}c|MX4isWay2uo$F2I7&6!Zi~l{<@pk8xB(`T6+%VE}1LSZ4rfD z!qHY?)6#>5po~RB0nEePWxY(rVuhliDHjmlinTVc^I1Zs1F_a9bJTj#Jg2$k#51z) z&nWY>)h*skI_=^7H93C)U9ht_%S7W%H6+{$!ilM};jNOYI1E;lHq#XZ{;3W+~Lu)=IGAsDzO}rWkdh0a%*regljxZ!U%> zR@nbR`Gm%0h5uL+QB#d0f__@{B|XFl@&e*bbm0i}#ibFJE$qe-pw2?T#b#96#**GB z6c3aEgl-xx6Evt=Vw52eI;mnxt;;gXOM?B`L)WNc_Pm%?W!z_|v;$uywpg%saqS+rUaEf3v8bJL!n`riEL|pDUDdQAg ztWMe#!Y!$yRD>9!eT$+x5S?m;Tn}Aleg?!+p4Hr1V_Zf4vu3w znhSRLE|^_6s?XZdD?ay#yaSuKY)-t_;*ja`Z4`(u0%NjZtib!TF4&8q3SP*VHrabn z6;wLoJ&Csb(+_v(gQ0@MPy>;Zl`@ps-;RaY(ctx|!(1|Hab_@XFF{gk*x3MF+fQi@YHSi0rlJ0@fm;}%>|rX~{9$FL8eu8jxBaMB#z#SA+xv|X)AUfGYpaJ5iXcvCPzGVAimxT}D<_MuaG7gooro{hq&_gfk z08uWbB&;y+Wj1mM(>|dj{(I2N4t5APVx}S;H}B)hc8IXFrh2!2@SR2) zfRJbwnxb!4R6cukLy@&47a9DO4;OoDFSB#Wa%Rj2Q=A@W8_n&DUJ99zLD@$HZ-6;m z>SduQ;VlPRrWY7f96<3+H7w|>5os#D1nuY9OoI`@T;%tLeDkZ}A$toMP8k2vV2>Du zo>1m|j+dDCgcyU7ZUlJ*nE)9f(N3h#*5WHJ*Yq^^2a>@@CU~j<_|93*kmivOxZ9LT zF2D#?qRkPuDAaMcp&V4ey%K5WLx5+ba#Wt`H}04_nZ1Z(WEP4bCN+^}38T>%yCVbs z#VKxWgCcRRPzb_q=w!ISHp*SizVH(bu3Zbw5&#K!k< zYBTDu3x9V8K=hwKO?q=?PiCSKk_c1GU|tmUo0eB%m{xA%=z_Si6b+R`9*Ln&)L`}I z4M~{OF3Y=^;nZ^K?2B)7-eg_1S;fv}X(E46b=d0FcMjrhpe=iin13Dv#U zm~;#9uOb&&n#b z`5)kGI5wJo99;aGcLy>W93sr6DM6Lzy8_%}<-|O|M*Q&qpb4ik~dLk}MTsP5RxO`X`4NsNSe*6p4jq_OeAf+&D57IB^7U%NIkempiuWi^B^v3K7V4q9I zPM4Mki=f$`iA?2A1U!>b3J18c&%!K2b`FPHc$RdcGEw*#zjlsSZ09wTt0XFsl1-Mf z($c|2`vY1R`H4I~69(W5o#7cL$k`rJ`t2wbbIkR&P;$$|dF#899RDq|bpiY^K@tU` z;HsQ;ZrzX4 zZLFCdz!f%}707ocmXz0aKqTKVW8}qOsZ6WCL~mIq(9c8SE@naQzdZ77{#}`@aFa-@ zQgWTHCZBd7b3{7eWh(lAdYJ6(`(U&sKT7TT!)xzrPM66R$Em2MCoVtl@TnUDKoyS) zw6;b_MQY*io1%=uN_%UrV{0tq7`3N*w-)=&+A7zgb)q;!G*-_kbEnS!#8Pw@MO!iG z9XpRRZLml8_=A1Fs`puh3g_9J`{{)0yJS3EZEX6>*jTs@t&{1d(9idJ?{K=~6!~bv zzw%oKip6%a+CkVrl6NDo;VngT{O-2tcGkzMlduZZ@P2l9|7^C)4F!^KoyabA9*H`A zo8Gx%gHN{wh|R>%bMHPr3wYJb4rUT;2TGA~=Zge4{@VtM4XpHSS!}5S@joagw6jIvrgIu+)b%K)0)B3+VwkVss5(_WSOiaw2q_Y1U zMuGg2c6e2QZ^ZBuu`)?Ba3a2LUPOHCxR%lek{d|sTeAX&z70p{q66zD;07C16cDGLb#J-^AztFPHnAZg#{Er*e~=$UoE*V z&u&HF_mCh9zJNHz0F{6MhelK(2~rw2hn=Kf)3m;edx9B;Y}D$wnD=fQ)oOBgnsmI{ zKB~XNs?ZN}50;~^E#TJ4b2SQ`nDMfDFZ*EOZHv{fX9qeumT&he6 zHzhg5tgV$5Yj*kuYU%X%nIY_SVGl?r&S4DFu?f=Wf*^2O4S#y%IuHcZR;EBWj?KmhJ`3iMVE zzoIoHwb4@I_&9|JHY8oBBk@!Gn?drou5?L(T4{b3$rMqKnz16=F|-dsk9-O8MX}F7 zFkk}lbBc3BkjZtBNevGY9XF*vJlt16B>#gRry;$$t79E~Jh5gB>48BzQfQSDepg)( z{a}1DPAoNQl&^FY*gb*KJ#sS9##1x8Ch>#dXQVzc`Yuy=*$s$wu+$V-K zien^3p91f_NJ!}2LF8}PVr0Kmvg%+`U{P!l&?leIXVVO*GMf+>lnQ5nBq5gA!;XNc z?!V+rpRMBPf|$fBW&D(5`=Ww=g=_e;USGH#_>Cla0GRNU4V`_6nUzj29}GRbgA?S9 z_N4Un2RBa-q{Jbj>Y(p&v1d|swB!`N+V=YB?Cqds+>}I4K}keeZS0hcO?Q}% z1OZBL6I@pDX91&g2Qt070szUszTSnB#0ZtSDF~w4Gj5R9x*^8|ryblXo_~vM?*XZ8 zf^I*3#Nx>8HP2+zHjkUcGPLm7x5&xUw6T^>v@nKeS%CbRiD;7+aCJ%}H1`xE<%p~G z1P7tp^wE*iv%xHZIe`zBsE?T$cLArAVA=z6&VL+WBVyqVqcZwGU$b3C!MyCIX>N!? z`9!YS*_QpBdA}ZU58@QzDc^gz0Z~LF;87FFQS!w;xe06AGNBmfQv;bgINfJ_E>W|; zL;M}3;{_XYhi-G7AVpLhh!eGdIT z`141aVHvp~?TPpjp#j@WhH`{s>}v^sd>|D%83d0p?kzyd25E{SdZ?Q4Sv`nyD8_EN zh%UKqBw6rj+PP?^eou#G1<2TlVb%AUx^-k_X#$91odtKMR_=`s<)1V_6t+{Mh?zYI zwpA7@kSldKs^YA>U8%cXMNXJnUW$+D7?1?B@(aFFUBDIOuBxJ`&Y zi1m(y#=ca_as}*t?vk&?p0v%iHp3XI6i9japP8SO>ILe1D!qRTSk2eF;=xrtnB?#xhwpLA->_2TQUuh-Yu(U_NY!4mu93Q z)@fZg(SlCs{lkguqmSk>0z$sL9p>9$xU~M~YOJ_&Ql~BI$D8aSRX1uO$ zld{>@YCeh<%?S)-|E|ok4B;B6_@}K?y(AmOSS`s|q=hWF)7Y~9qa#iPY5zy75z`;) zK-I@$`n=)1?O-lt#ZUW!+MUZ4J31QZ;UPZaiiOkFd3j|o?~15Pa;sE27?@Gz)atXT z+i<1*-Qp2NgFgx;1=oe-ir$+vq#ZSX9a6~9>9J($XcrGM<&%Xmp0qjl zHa|F(Od-}S79;p6HSvwK(@wxIDI@nWXhcH(fQDriqs5L7;a|w)GMJj2w?c3`iBtKzYIVA zlI@q#5pYgb812zjvmO9ZAPs2PY)RraA`^i{27u%-qq&1_X^3#joHXnjpH3@s)U%RQS(XkG36;$e7!{G!3QP@6we;^>m4GS{C^Hf6bKP?5{*GY` zegMaq)`gL$V1J+(`+x)3kp*stkL`z#ZKVPC$WhOPP)}CIj&#R%F<|2zX&;AYBp=0d z4aj9wbxWju5pIJVe8>QD6RGE(l^INbWOfVlazsGrNan!`;_S-qGkv?}TG3T8e}9a=}Th=ENVpfmGg8G;Op0Mo<|}rx;k~ z*wf#=r|=849#O-nV4@Zdp2|In)+hq{B^iy#>~`auBfs;kV1);KC2y)oFD}PprRSiBB86#V~^hz8TiV16ri70ZFE=^@q1bMbJ46An2 z<#&fk3S{!S)$pzs!n3|jqZ?f$EDKbY@vxMzgZofg(G^PJv51I`pWah*FDo-;i>PM{ zv!fdm-Wvc%AZOe2&t;&J&F$`>onYz@GtFsW_HniuO ztg_|6*`NP`n406~aW>i7HqgFoCcUhTyx$3-*umFdh0WV+LOGE5*d5WkIPZ9VRU?=}|W(pSD` zY~abSUhD3NoNeHI+4*7n{;MxLM(i4=3RPgFqA(hQ{18xN0+Akv9gmZ#%n3mVAd7+1 z-DB00XQGiwu+S{*t|XU4i(Vj!Tn<@X9C&|VWV1iavO0iyJZv*13OgDVUIm{KjxHNk z3IA-vI{CY1xN;8$v_QBa5h&kz_X;H`Q(fwgTO zrf>lrWj~vN0A{6+?7{Wc{8eMfYiE7$H&OIqn^$LN$YU#q%;$uxi^t64{bk2GpOElk zMbw<76uzrCrf%Npu@8>%GEUS?9Qy+AG@}X-X?=NvGA>v)PE*GwDqgmp15}&Z$|xaz z{5PLYMBmFq?zd-NzOE6=!6^9gcJZ^DzvBI15ogGYa~fK^m0>MIhTO)=}w z1T&K2&8Fgw*8>v$r7d8(I0TD*{dWa3Yhagcs5l)MBbSjv+Eza2j)>_EQYd%|q%|}W z69Y3PRIf%yF~r+l;r+;yvgN4mNny5eOrU7sL6mB^n?6stDKA8LQi0bb$&3V2x z`pYKd-g2DD8Nn$VVNal=^c5K>EiD5M^j8QBP?Qb;Z8-u0CMJAcJ$zM7J<=Nkw;rRD4WqlKubXYKyJBQ?Y<%MX<=U=q zY;OI>wS`rv2=N5)NT15E001=p0y4MK|1N`q1fTE1NN8j(r4^~9LeTW#0}rR^RMK%| zxM&z>@ey;_m4_vc)mb82JYI?enUmS$Xnx4^_y1qAt#nQPXzJ`#Qw?uGI-2`+eC<2V zf$yQXEN2XITM83cGC@EkFe46x^m`(`Gag7iqnd=$JCO4=u$qYNXNNq| z5BG4Au@<+hqt)StiuJz>g@r2B{)L#oS-y~G}Gj}a&8Fj`|q5fP^RKJptxat zyn2$PZcP)7vaa*$_j%49n!*h*2G4=PPjK0l zF3f*wr1tRs(KJo3-ll!1+uQyPc%<`aiJSWhpD?99TsE; zF-FFQGXyR|25+bbAkhrSBF2nEIq4L$xH~j}w5F8&Qf%ifD~YSg``HK(D)bMdc_&e( zHH1?;%&&<9kdY6NWjc(Tcj+%GTyZ%*ZOAZMTo4dHtt3@6*B_vzd_Q!xQp>_zE#{mQ z9b7__-bkT<9?k4XRP~RW3nE5P< z_$d=ROrRvqWd=?@i4Q-cnB_)BN~LaohYGQ+)_EU}yIEo;cJ-e5z_OSk6O}d?M!e%Y zK1NuU^TWu4rJh8?tgByD!{%mohlFmx_?Eu2Sd}Hs6RG*RSwlQ}qK!%1#3dtNZc=oC zEBV5=`$o3)YEWg)vNVoZ%``-n#*E1T>idW&B(ual@Kch(XNumZk@mWf3N(^cbl`U; z<#Y<5F+M#tv#l^s1&M{rZVg?i^XKE2MD`_0cEFQGe-rpditD5ZMo#QNq_j6cmCuC7 zmzto*4amf@Ht0mQ493|AHTc3z55`i)M*HrtabhXXE)Amyb3yi8ACIMpSXhX1y}#14 z)fZubNI;}}TNaYAq%hq7K#b;9v;%tA`yRnvif1PEhyYh96ARnchX~j{?p8 z!C8@!yUBJt!30vdwH2p%@`rR7B_Vx+(X!v;(`H^;&m01)wJ5+rMM!lhOxi%$1G z;Ij{PMBwzMU;HF>m=<%0Pr~Hl-3Y_)j*GcT6HWe*66R)Rlw(K*bmBV`}bl~42c=DSc*Uf2`}9gdU7J$ zh$wBm*L&h{nL1H7XY!rTxhYa8xHF`G}0{fe5F#X&IW@Fhp2LiyZyuqDgs z|H1k?hhp|%i+N}gVmkw*{ltLJ+N_Ms{wWbuhsn}3aXNxQuQ@l<=%9nanNfM4o7TNk_tw9=_##t3X|e8{vtA|MGklJaO6hEaR__g1Wn`^G)*+ zw$A6!)r~I=jlIHFu1TJH9cZr2`+?;ygC#3_<-|=>H)kHbo@@6I;_CZ0X~m!XGoJ=8 zNuG|^`L=%OpS_WTd(tbwi^Hpa9)z9e5%!LxPjeMR4Xu#2ZKldF!<)$YcAR#0x6^m} z*yudv7+5Es{3BaE^?ZNX^9Oy7LzlmQvuc3H$gOjGl|4>lWM348Y=SWHIAj;Y?Aw0I#82DnoIzO& z$7IsPCT`0wgbgDfT~mf#(mB1iSJo6hFIMS#b9j|m9UbNiw2mf}#~rp>YD9UoSKB%T z*tMsdJ(3U4YNH%|?$_2oTT8RsBtlBS!EB$qPj7^=Sho;SxK_m|`i` zs4-XbetsNAulMn2cYVKa`RuE2{VVLgqH*yd%w@S$ceHj!t2XI3qNeX-0lS&2L$<52 zB#ptXnJ*5BpD%}xPQzEs5GPM3HDOas>F>XABn-!UjDIIede35F?fTt*m+hj(qCYT@ zMz)ld&|3mH;%VZa2lD}vF-Y!px=qczcl-dp+a zIOx+lN|N|&Y|-joBw7Od>=s;pcFY-Y&{>U1XdL6kG>vSj57Q2cJamq%Nd_M;*d8_7 z9(_0C*pIvz&?Kslq)?AWTm-N2VL2zey7EP;@kH1)MkqE$As>RoUCjTQ#&|o05^F_~ z!5AzXzel{Mw~(j@nG}YFnFjdpnT$0W`~_N{(NjfF>wsyT?IZHkqei~W)k|5Z97`Znm3MZ6o2(LdUR9jQ2thTmL4jw#5$Q;}nY zLrgN%6FtE9!uF#Cc1}>Xxt^!xjXRXZA!t@XokB{7$%Ep;kjDDj< z&W|SW)di~c^O@MtEJUd^IjY}mI9>n(?#-esYHe?x6#G$L2A`xqjT+gkGT!76_ha`z zD-CXJ9y#ns31+6~uWCMZJ7Nb(?oBhCi#5w#2Sud);5zKStn>}#JeiK+~$vx(( zH+xDwdJ6FQ^1J8hleyEO84%y+nRs|_slZ0Q0w zw0xT(YZBKub2J-wvO+)Nyi}fSQohg;lMuxPGg|s!PIE9Ny*=6kUffX>mqwAVU(tuk zqSDHu4>;s$5X=lRz#jpcWHN}KDwxHgc)_4RGBB9gEdhuW9MM>aoe=X=DgfCf2o6+I z<6+h=lh`GLnYUEbtyDUTQ=Da4ye8r=ei$U+j%D}=i5&#nXqEinGp`~m1(BrHH3zL| z$4D{+$`tW&Uo5LmOK69hwpv zcDZL;>|vH)WEVFOWmH%Bnwa<#sj^Yp@>$bzIUymB&oG}q6$PeKdB#(9;!!^Iwy`Eq zTxL*BGh99_Q%pNteR@>XyHw5kgvR7qJ#MY<{s zWd33rMkENXTd37}0Evav3`48aWvbnN6w{?PFdsK~JvDGFH&9xY`n_w+D=z00Yy^8Y zhW==z32S@=#&!3`yFS!wd4_9R)#El*Bp=twhxtAi_%=(FRcV3`O)Wp|#oG_Z|9CL` zL>v6wDl*C?y)h9Iq*Zs>XokWcotPRa{t#1#ZgnVC1KXErjJ0YEL9ZDKE9bRpWIt|= z9&Y{pgyH(5?Gt+2f=(kAPwd}R{UV(@h6AHOYDXT5#woqF?ATYbzGAqaXvJ6zBBXlrx#o*$l2$D zm-!95PCsXm-An!JGuTzy(&7B@*J-ioFEpy{pv#NY^gg5nwA`Vx(yaKl;(v}G5%2sE z-bzm1HF(_UYSl)(g2A2I2C-_TDQ)HP>@gdJRfv=KOD5OJK9|}acYG$V7}@xPgokl# z!2+e@c(e$3Dvk|wAK=7j4z@@Ne@Fx$cJ(&Kg^|@B1P+8V+i*4|$_Ylqd-X=T^(*XE zI1coBSamKfH+Vj^QhIeUwsiVG_4*1{7lwDP3^$kyHCd%bg?ZI$rVZm3B_pNvC#NR0 zhDX5j{)sts#zTY#uk-{~mM@0BOHHVChalgk_ViZCt@uq!*+kT(xE-b>G^Khs zrlb^(mRO7~p^f4T+BR8830c*IrdE6Cj0=`jQ>Qk}>(qP>8^4zw4oj^uldVB~Ujqxb zB}Pv>)=k~P&jUf(Paq|2-Wg>)+M_J`EXjbp+;~ky*K74&eMTleR}K$KhDzdmi0tuf33}4MVT{y@2G_-veZA~V3K3; zem+iPhCj*qpQq~AB{wF4T*uYtL%9t zvu!sEi4oR@mVVFEc}c5_l86f(`-|C_i`h>J&Jp(74S|jVOQmg6nV2qR@0ZKpFDfK; zYcno4>WPPznKrF1BV8{|A1=eXSon>+DP{#$1|qn9y)gz?S2V;5V+I$;gjdtSxk8ew z3pU=hHuIC5i6azV*XYZO!fU8qQ*h1Qw)@?_l4~a{t8YG3vhUvChMazlZ4wK22kPnc;

NJBr8l*+>3!pZ>`f<1VQh5z!dWX991Pqv^fncj8Lo^}`!@J!yPhY&c=(sd8HIpRb z>i+~18tvtVj=h{+=4IfsuIpCz>!>+ymbrrWnCiyGVAuNV;#Na)KG}b2zr$WY-t1k* zT!rbL?%HKo&}eMl4()Df?9{esiCS;TsFZcPXVQ+z(U9Y}UG4^?S7U3o5lzMF#<{3F zz+%g5fp%a~mZ*{J?-BkhXKu!*m^ra~Eay?nbIBm^8rqJO1Ki{e^81DLLS5~{AREI8B_a865wN>F+B94`7c-U zfA*Ua|A6oU05CN;6@ZwixX9S(_y`#(IZ0V*d5M{+xyjk-`KdTC(9j@YdMY4FdRhP= z5ODg!Aj>dYTT46p@?vs0_3OK9GCVkF0*aihyv(f0Fj4|@xcd^IMWeO#qLr2PvVpb1 z#Z|`D#RVi%3?RZ#2v98uFgy5BvJNCa0x}p7GFWShpc3`~m|y@ffV@Qu1E^c@j$gHA z6f0W1{)jQ7#*K?ql|p68BP&<1Ox==2YnLu+)DA70GRuU)brU(-yopm2Om*<)F-Vbu zMv7}$Xk^i%C7e=lTzI++@GhRAcktvLlgFgT4+a5biby1=9g~2AUI^@`Xdyy)3X46> z2{*3XxpZxc1et2oM**!~#j+-F!97MkxbEpB<^@3;)g;GNhDnjp7NkyCgB1Y zg|)E+B`rE4;!BZM!sQN2)&NDBiQK(F!V5ytu*Fc=q~J{!OaTxhIc1b%&RZP4L*SKm z-ifCtM~0-=NJ_{c4B2DjJesF-E;#^IN!ur z&N)A9l*R`&DT->Uss^xUUaOdL+$qX2`6NqK%DHN;%-p)^7FleOVhWQv#~uD zrjRU9zak}GH*K01+PIt;%K;^q4NP#s1*c(cBxwji2E&z1VFVgWP0a5GXe9iS7h;Iv zg%pxVG0r$1Gh&7rXOw(0$|akuvKdU23v(!a;?=FJ;0{`=SuyYY2~6f~dK9o)1W~3? zB|5hqypjS%ri#gS#u+#1mf81`Pam6aIE)*8poYvBe~9 zX?H1Z0W9S-yr`y9qUDeU7l}J!?9wD)t?;wnwNZ7iM&4_v6pb>Gz zV=yuN7-M+BubgX-vw_=@paFLyXViV86ii65g!R~4AI0@&EUqo!uL}O>tT%?}R5=P0Pk*I7yAc?1BY&dtxF|=|CiMX=xmU zr7R7mMO^A`pZnY;BRmKRG-wQtj2L0afQJU+B{T~DXxJVd<(4-lTu-9hI~_Hxv`q39 zQbM_a=8rB4QYuYhTI9&)QsRe&^1J{GkmE)rIYYkz9_3!ta-tKLScaa|B8{o*4wsD8 z9m?Et5n{Z|P%oiIekv7TU+CRZA|Zwlmhps;U;+>lLM)XV-u!eEx-Qt2tUoBB91^X!&(9f zVT&DL{~AZY0u~Kn8^a`6o2o(3(D`GYwl4CEjS*}pbMPGG>r zi^Lel9l+pCl0P}*C`)+xI#lOC3wqGMx$}|58YKyx9K1gm}XYG%Z`F|$5Utu-?1 zTHiXT!a&4^n^dlBKDgu2ZgiFJ$n+ube(yCD(le2=@{x2r)eZjF|@Q^KG9S+BI)E%>iEWeGh!-{Qh^#18#AO)7;?WPWsPv zj`VvQ9p^HqcfUU#^qt2%*GB&~(Pf@>a`_s~PP#NNICLQ|3t|`(zxd2Q?sm7&yyQg3 zI>Cc}cazgy;8CAD-1{!{tZUojSob%;Pmc7AuN>ug2fMBf4)3Q|T<%Ms{MNzVc)KsY z>MK9G$}4~Ox6i%j`G)+^3vceyU!CeEN4?LlEq7|mJ5{4bG|mzoO(s_pQ4>FU+(qyA z%f~+F!VmlKHGl4?D?RL^Cw}CK-*e2vyy;r6e&c_RZjWQX>%iZB@-q*5>T}-J(06{} z#eZ{^>z(}S55D#OlP-JA8=vY2AD>spS6f3OnI*k26mJ)oaf+vO(?@y#wtkiOdeJ9( zT<3eM2Ym1cbUr74E;n@{cX&-#dhgbE+XjJ_ka`4Yc%J8YomYG)H-LmEdE-Zd0(f!> z7Ggr7EbM2Hb%mt$oo zE=-scNhpO2LWNZ*Y6!;8L)(p$HiY&(wte8x0 z$Y0R33>CPGJokC9D2m8Hiy1+R!nkp`c7#WGg|C=?@#c)1P>e`;jP8bS$!LsbQ8THYk)xjU%WG%UB8RR*t}kjIH>KrFf3PIF7#PfzPN3%t(ywSdIBOfyrQx zexnN82#^X_KF@TAjL47ew}W4IgGG0YR=0%lmx&3vcupsKGAM#9D1p!Cc`T@ks@H%! zn2eeDff8wpmnU$^XM-3hbuIXjBDirJ>5-fFa^%K=F$sTl$C59Zk*cSPF?f=&=#d2% zlm0&GbT$WhGe}LM-~da>luhXX-MCSQR**ZU3&S>S(!_oysdz5Ad^sp|jCXiJ$&g!T zf+snE)0c88c!D=~gJtQHCV7!yDSd7!d~}I#@V1p}>4MEDi(|=>c}b3YnQdc9mKkZ5 z!zY*&NSN>EfQH9?>Iar>>6Izhk1?Z^PU)0TX)}@-6H1mLOr|5931yl%e>FIn7WtSx zX_QxomVfz^1lXD{n1B!Yf)@Fejt85kc$=&FbaJViys2~Ex0kPpo6%>0vALUr*_f$G zoWi-4Y5AO5cbu#jn84X?$f=lHb(xsSl$vQ0dBy-*W*TT`m7Jz(&WL(U=bY4;{(}zr za`C5?>M4UF2cOJ2evyfgODL1%hFNp`qEY;5*sYt|fr_?8iga~!&JkNKPM zh@HO(g6s*SYDtR%sEq2Ef?3&oY>9pN2&DK}qx<-yDX5=zIgB$ZoLc#!YU!i9hM(v+ zZ4X*~SL%XGilnzV03q6)BWh&e$x+OqWPa9YmH3h%_U?*aoq%VU zaLSgII;o9mejB-g6}m_u%AMXBRvndQP?BSdMht06n)1hVIm&V_dZ9Q-gMpcW8LF!j zYMOwFtGB6;r?{ZFS*syOo4HD=%Brj~I;&Ypt15Yk3dwatxude#ke1r34{56_*>w&X zZWb7VFG`WS3YQ^es+ftYm1ao7;0v0jAzKz{`WcUpn2L{xC+V7*V!D|?SZZK+YG?Ol z^Gc)+TA70wjrb}g`r4H1`fD8(Y<*UqDta38T9R_Au%noN=W^hW(^l?Z5AC| zW^5aavMHOdUkauo`mu!bu#1=>7m{{-wswxDvN@}>9@4Q(iK_nlwTQSE5KmDhli&eI ziwH;S0T!XOO4|uYo3xJrwG=V6nXt5tP_>JYwOWg`P8$GT%LrTR2w4lZ7NHyEcCb79 zp)3og4y&p`+kgJYdz)~zUz-tiYqy+$w~(;6%+R->@VAK&xPnW#g*&#Du(x8%x12DP zl#sS+TdHguqCZQJ|2l+#8?|?<2!m_1l)$;j@VT16xuILPrMtL@Yr3JUwTx?x`UtsF z*0V0lOx{?cDj|f+aJ6^~wYgimOWV6&>$F{Kx`qq9T#L27o3y%%ym`C3#Y?urTfBnX zyj$zF&>Ov*yS&LOwPb6!%DcIF8wtysz1qvW<@>u)tNys?_@+gfmPq-!*eJQD%C9h_ zh+n8P%22kMo4e%8yVnc7y$iO@>%57pz546B`&+pE3%=6pyan991Ps1iOT5ghz<-Ot z-J8G&9K4bsz7c%D`rEx1%(>ypzI_Ru?^}p1E4vyMAxDOW0E@p148qKtz!^Nlb_>A* zyuia7!8LrtJnX28^{*i^E5(!=$^!M@+*+jKnhRqs~d6(}}{mT{yQtBhP!p#z!W^iQOv_Ye8+JN$4%VH zR4m7$tjC{R%65FZ#_PXxT*|Br%GWEzefzoLs*}anrHqWOUuu7OvBLTHwjQ+$mF&kK zjJ`O`$I%vw3&Ik7%zXUJ$BfJ~49&&7#G{IONIjz(FJI&KQ?bAOE)IlxOLrv60ZPYxy(o(pctFYAb z3n<^HXcThNHI%35>@GASQ*xB?beAf z)@8lbhvp=n`I(0zn(Fk{d(GFT8oxgap5n=7Qjo#_4-s{cY?G4=Bz1gPl5dlfx09hRMjo{0+aV6+>^^45(AmQr04icQc>6br;$u96Q zFY_}`>3?$R{s&L&5`X{_KmePb?IZu&vF_*HPVqn=+$b*r0)X)WK<-SR0Rh1Az+LGA z0Pi}Q@VQ&F>4)25R?=cVaGq3h*zwAsc=7Mh*duAOR0h_Abxw zY0vhX&-rNn>}swgnBMc7p7T3D0h^BP*-qTCe)XEZ_k5q{6X5s0{p(HN^igl<5}^CK zAMU}8_*T#O0ATeXAMcP4<7VI8lP>`k!2HZF?3Zus0U#^2k859bX3 z=@2mf=exiAzYXz<(B0jK4ZwkRb{8V4|TW|clp5>Dd z2muy@gbx4$hyo3Xhy#p|kdcy;l$Dm3my3yxn4O-VprN9pq@|{(sHv)}tfHETuZR$g zoRS0x0uu#&X9+ZFcq4-tonu>!TN00GAO7qFngg9sBUT*$DYr&x>PC5lIo5rK8M z5bfGUAOeAp#60~9MzUmtW(24SSjSQTH(90#SU_M-z`1gi+9i6olHWWC+6WQS$Ef~a zMTbZq4NS_ksne%Wqe_hg5vIghM-i=?U_loIW)Tof_&6+NCzEJTLP%LDZLn^qEC{lY z5|_G4IuY@dsL4@;uhN*611FEx)TB!fD_+dFv17$m8Nu~OX{-bZVm%_VEDD-uXq`Sg zQ}w{Y18)#;Udk(AuTRRIj6P17c((1^xO3~a6j@T%-G^DbF8rJ7qvF6_8BWf;x%1}= zd$WVCSU9}b$dw+aUaB_t@8H9WFHC;=_@>r-5^uo1z5Dm)Q3FIM;e-@cXyJtzW~kwY9Cqm8hZN4E*SU4&ooC{S zD5j|5iqyG7q9QEDDC3MY)@UOuE~=*ph&=Y_NG7S|l1w(~0+ zo_zM{=bwNED(Iku7Ha6Bh$gD&qKr1`=%bMOS`m}aW!rkr-_>8GHED(a}D cmTKy$sHUpws;su^>Z`EED(kGYni>cIJO8`nHUIzs literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/htdocs/manual/images/home.gif b/APACHE_1_3b7/htdocs/manual/images/home.gif new file mode 100644 index 0000000000000000000000000000000000000000..11299c1cb7ef6aed8ee4b159d733668de8662f22 GIT binary patch literal 1465 zcmW+#YfO^|6g_P}`hb?UfCU7!Ag=*RMW7WJEwIjlKme;k1}ab&2*DvZXLNHgz%i{n z3mR9Y7$rv8M5m%)l>+jRM?iElgAB@Rn)yW3VbpIQyFYGjZf@>9=j7ZC(Vxqt=^BXf zHG1$6}$N0HhEs1{h#YOn?T0#13OAoUz{88vFO7xf%Wan41F$ zvoRaJcqhiP)8UXvpx2|Nh3elp3tt)yQYqY^Tv(twRYGu5QmA5745xS7sN%vC{1a{s z7U)dSd_*{cTCosH56Iys5@GFHjE+L-f=rMsSmeS?r&Ew%e{enws>#Z~@)j zumIC+#{2h}RD+u0!rk4PIpKyfk1GCY3{@(^k);q8h6kaEb>Y6L*u-j1;`ym>=OC^CNoG6R#aAIEolu&@SI z9v=Ac0S6cyBTka2p5bF0qQfx|3Q>mmvzd7On8E;ZIamZp0a$d3K3w4Ja8uv?CFWrRB8irk+8diujrupK}iE_ zY@kvhGZRJ}+=V#;%wyR63m&$$;pIylg_y*4CvaEMkpMQILV`&FXyJUUgqK*1&`|8& z4XqX(9n`I0u?U_}PU8DO0!mMa1r!Co4}v79^72Aj8b}g!8YPH*Ff8;iKSh|WEf&(C z(cr`h*z&0TZGP~y0-Xco!zw2SazD(^L+%c_8{QP_{DWRay zqPC5P#YK=6AWJE`zSS(Lp2g!qr^CgI6n&x)1_HGAQ2eI7g!#{eSo^<)vRxus?#vc2+eTOvP+lpVZ!Fb7Xp_TZ}$yX4uG^@QEFF zco~b74x4EGT=SW}8s3B1FGN3@i@v=QY0yXi))o{zZvQb?bb3v{QCcKkn~PbjM$u?x|e0@l@=M028tTa{kh%sHFXdxbw5B@+uRf zLbgScD_L2eJ`owZ!g&4K)ATZpTy*VOfl1RSOX@8c7WAxXt?}J{%h}pGk+o6ia{QUz z;^6y7nz0oz_8e)L;bSmo>+=n!&C`_5K9cINoz>#L+btv3(IVtA4pZXeP z!q8hnq9bs->OPIf>C3PZn3}Kuk?}wmQR!vN-Fw$7z)jpE3HFC5=U#FK7LE*K1o zO^7<`VCbX0(zD%WI->b{S@oSgbeEk)Nfv8ob&B(6+z{}>FmH*;fy6SGG!wlpY{R&? zn0xbPdusfD_sLtamKk^=)G&cCj?2j;s*`)?b& z3j5o;9{pY@vT_cz6siQD5uWQ6`Y7wC>hU2@#@F|Lu;Oss%J__+(+aVruBm;cH#rjB L;Md}uqCn_>{mJyz literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/htdocs/manual/images/index.gif b/APACHE_1_3b7/htdocs/manual/images/index.gif new file mode 100644 index 0000000000000000000000000000000000000000..741c8939d77d2423d67beaaef8fe78aed13a94bb GIT binary patch literal 1540 zcma)5X;V`N6g^2EAqfEj3FHAmLln@6kxfB?HbDhZNdqfbC>Xlu)u%~i4fxr zzJ!Ylva@mP7Gz+zw_{`kMmA>_j_13=(h?F02v~kb=lD2<&y`h?98{sgmB3Y7|P-oTat3#t{+%}_+4$c(KApcmUwEFv-z zQkXL`K&NAD41LL%jpJryk+4|17MCw$Vge?%6%BNmEzZkPk^&wNT69%Zpr?mYaBGFx z2vR77uP>64s45aIBGWK5aSpx$Fc>H=$Fpa6{~i-r;BesXj$ONOAr>|uii*(O3=V;B zkzlgJbM#NBV6>%t*;#=sg?S1Xr!ZkcwKbR;r2Po9pC4}Apa6m=PeAfOa$!ON1AG$j zh6_Pp>QtnrqP`vf&K< z549Tm_oKBHeSMS{HZ?gXC;0n=57HGjc5obzg$HCZNX#%0V4HA7EJjceR;|MJ?a*pr zGEpUL#Eu9-{A4CRBah34rzb)~ariJ2p*5Q+h3BJaS2<8dY$GCY-~e<`mz1EY3jO^k zo)4KA%dtsDf&-efGxow99Ss==$;og-*v*@e5pX8JWMan->TKjp;NwTQ2~o8HCKZGb zSX)z@m74b=E)Fd%P{QvCHZy>6NCiy9$taeK5V8SezeUz8IGcF?-Sq!XUSE)3enHNf z1dSzHqB~u$VezHw^t#eUP4gzxutT0fms>j#+^N5MwsCda9aW;A_roSDIF{W-%W4<< zDe9IJ^V^)Fg%gf#8e7NfD){dmk4$i9+ z3Wpe@J|?#JZ;wr)%O>B3Wy1S4sR1nw$0VqiSa>Ith1sm_{3G2ep^>%Z_c_s9RVi!S zmW3Od3te~hF8^LNW7peLq~NGjR8P){yYT3AUrX8U684qS#d-3=r}mfb77*g~{xdST zq0#5G-!BvwPHC{gXqFHg@^6gU`rXBJ9o@8Pk$e;;{PdNFnVP8OfEo>nO1 z7mXPa z8}g=~3>^KF=R+TS?B~`#ta05FyyLE~Qmb1L%RCyJIDg4-`hx}DK{Q5a-=1j&PDfGN zb=%1CzwbBKK5gk7a(b1((%M*>HcMj|M(wyqZj|MUAev?HAi+p?Ve5Gc-)*d>$N*LF OiPzOh=dG1;1pN#BQV7)m literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig1.fig b/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig1.fig new file mode 100644 index 0000000000..7c80fea3f1 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig1.fig @@ -0,0 +1,60 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +0 32 #efefef +0 33 #cfcfef +0 34 #bebebe +2 1 0 4 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 6675 5250 6900 5250 6900 4650 4950 4650 4950 4050 5475 4050 +2 1 0 4 4 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 6900 4050 7650 4050 +2 1 0 4 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9375 4050 9900 4050 9900 4650 7200 4650 7200 5250 7650 5250 +2 1 0 4 9 7 0 0 -1 0.000 0 0 -1 1 0 4 + 1 1 2.00 120.00 240.00 + 9300 5250 9900 5250 9900 6300 6975 6300 +2 1 2 4 0 7 0 0 -1 7.500 1 1 -1 0 0 2 + 3900 2100 3900 1500 +2 1 2 4 0 7 0 0 -1 7.500 1 1 -1 0 0 2 + 3900 7950 3900 7350 +2 1 1 4 9 7 0 0 -1 10.000 0 0 -1 1 0 4 + 1 1 2.00 120.00 240.00 + 5625 6300 2700 6300 2700 7050 3225 7050 +2 1 0 4 9 7 0 0 -1 0.000 0 0 -1 1 0 4 + 1 1 2.00 120.00 240.00 + 5550 3000 2700 3000 2700 5250 3225 5250 +2 1 1 4 9 7 0 0 -1 10.000 0 0 -1 1 0 4 + 1 1 2.00 120.00 240.00 + 9225 2325 9900 2325 9900 3000 6975 3000 +2 1 0 4 9 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4800 5250 5550 5250 +2 4 0 2 9 7 0 0 -1 0.000 0 0 7 0 0 5 + 6900 3300 5700 3300 5700 2700 6900 2700 6900 3300 +2 4 0 2 9 7 0 0 -1 0.000 0 0 7 0 0 5 + 6900 6600 5700 6600 5700 6000 6900 6000 6900 6600 +4 0 0 0 0 0 20 0.0000 4 195 1455 3300 5400 RewriteRule\001 +4 0 0 0 0 1 20 0.0000 4 210 1440 7800 4200 CondPattern\001 +4 0 0 0 0 1 20 0.0000 4 270 1110 5625 4200 TestString\001 +4 0 0 0 0 0 20 0.0000 4 195 1905 3300 4200 RewriteCond \001 +4 0 0 0 0 1 20 0.0000 4 210 1320 7800 5400 Substitution\001 +4 0 0 0 0 1 20 0.0000 4 195 825 5700 5400 Pattern\001 +4 0 0 0 0 0 20 0.0000 4 195 1455 3300 7200 RewriteRule\001 +4 0 0 0 0 0 20 0.0000 4 195 1455 3300 2400 RewriteRule\001 +4 0 0 0 0 1 20 0.0000 4 195 825 5700 7200 Pattern\001 +4 0 0 0 0 1 20 0.0000 4 210 1320 7800 7200 Substitution\001 +4 0 0 0 0 1 20 0.0000 4 210 1320 7800 2400 Substitution\001 +4 0 0 0 0 1 20 0.0000 4 195 825 5700 2400 Pattern\001 +4 0 9 0 0 18 12 0.0000 4 135 645 6000 2925 current\001 +4 0 9 0 0 18 12 0.0000 4 135 375 6075 3150 URL\001 +4 0 9 0 0 18 12 0.0000 4 135 825 5925 6225 rewritten\001 +4 0 9 0 0 18 12 0.0000 4 135 375 6075 6450 URL\001 diff --git a/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig1.gif b/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig1.gif new file mode 100644 index 0000000000000000000000000000000000000000..664ac1e7bb7a186d2c6157878cdadd5bfb7d3466 GIT binary patch literal 3525 zcmV;$4Lb5iNk%v~VXOgx0igf@000000I&Z50RR90EC2ui0IUIl0RRI2oR6u??GK}z zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNI&iDQg3<`(DqVb4KDwoWr^9hYgr_`$T zip^@b+^+Wv4vWX+viXcotJmzd`wfrF=k&V$j?e4&{J#GW7$`VMSZH{Nn5ekO*y#8O z87VnQS!sERnW?$S+3EQS8ma{VAZi*%daBx%y6XB08!J0YTWfoZJJ_1b`?T8&tn?d9 zTx@)doUFXe+}t>uEKSD7VUw$V!fPAKs7Md zyD+KN9Q=3h;kSZ|nq;i_tyjVj)go#8aj#*#l1DDS3)(Z@%69kyPTY9&V!4&)rtBFx zuj2)w`FT#Zid9C@pqy*6bX(4r!i z`&oEWA8EOQzK;7h-_)wNdu5K?Iehubp{JLgo4RDqgZ`)Y*B;$$)*%+$dHscE#A{gb zR-kbH1*IQZjHxyr2lYAeQhMI0XB~uIWhh>7=EXn_fCXlz9*RV4IG20X@n;)YEyjqV zZzf#W#9BIHb|Q;WnUx=P*|kMtQ@s&q*LfQbkywavf%hMh?0vUnUk~7jP?lP5$z_*b zehFrnVvb2>nP#3T29{_Bqvo2uwCQFpaK?GdoOIS==bf|Usb?&FW&>ZKf(}Y(p@H_f zM*u!3is&7TF4|}vkNz-eq;FK(1E!X;q3H^pF7W53V|Z$>}`s%Bqu>#xc1iDTV{;D&&R{HCsu*yp8vByf1Y%|O9+Ux z-3#mecOiw7a5$cc3$nP<;RJq2<6evY1GyoR!%g|+e`u}&=de^Bx#tvsE~n^zl#IIR zpR0~*Af&ghHS4gSF8l0!yl#8wxx0e|zaD&_XPZ1tY z8sBI|GGg#PLSdr?;8?|v9qvbAnbL=N1Qhdf)ZUCxu8f|=>UjiK^T)Xn(x5qHnABbZJemex0KS7O!VPvHiOI4 zbn-}bfu$R3X+v_v206$;FM3iA0kfKH24|KF;HD2d zbRTN!D4cp3&Ii01OhUGDkjTWQh(1H1vfzgU==9q&4^*N+R+E+Z5vDd*iNt1}U>K-G z&pMFgA1Ap;K(B0NDE{eqOAToel@Xoi2I_gEdqydR`rKkX56Xbri1afU4FN$zN+EY@ z@jpEpr3d^;AbtrDV3 z8zUqoPBzGn7d>jJ2p9ykQema15Nyx@3k1VTK|6)@D+(rP1jQ<4rlFAR*%12!%R-@` zrqJvLAX@~_o=LR-!mJNSTPD-g7gL!zm2Ld9`Fd@01J4)Jd^-|4~*ahD_FpK zeC~oD3}HALIKmXJu!YgsV1Wo0zSMGWW%)}=5SMNs8x}F(JPe8wvkS$aP_Z)f`wAE1 zi^ZOhG0|w;2^${+#;(w@F?hTRA2$uhoDeeDh`b3Sr;WrW=5Qo{tO_Lq1Imq^@QRsi z3tW zla!qSrQ;asOrmg^adiU8P@2#pim{RgHdy&pneohVSpnZih{MM+D4kU zC~y|7O4MBX5~l_oW-smO?RJ@lk_OlKKV>uW6Rk7dx3zRr7OtcT<>%jfRx?lveoX$x z=KQBFdZe_y=I0URQ%D|_d92BZYX8EYstA5?*kuPLdhNN{4a+L37O=#vv&?H`#b)ux_e3j_lTMFt< z^_KH9>jUok*W=*KvL^!VYmc(nJUY4n><{pn|a8_Mtg$NqLd{;{RM z{N`_e3BW)9*f&SBU#$xJw>Fs)fcWPqKwyAMAb^pBGN!PAmeYXhLOF;NEuWQuNAQ4# z<2PoLH=vM#zXJiX5-Y+YEX+oNv~nR12PzWyI3ZXzD0nVp(<>ubfmgzUdgFpWGlF&_ zgC`h+sB(cu@PUH>gy7|aNkcY2$bl;u3PZ>^IruX#h=ep)D{q5bH~0;>6@*3Lgsw9< zOVfo2xP@_`g^1>Cd^0@jMl%9uf-2aCkoJZwvuWnShC1kmb_j=fh$Cf)Gyms@e+Y;s zBLiwkhi9mVokEClh=_Bjh%2**b+~SPScrj0iIo_L6S!J;!-JUP{)l0?J7e=UR%jt$ zn1}r50H7!}qWD?$w_{^ydmZ>JG02Ho=!#!xHFsl#jzfzM2#e^lgq`y^wHSdG&@o7J zhocjWyf}>B;E7ToiOeXBLGX;-(2P+aThZt{*Jz5RvW(l9UkK=pDv(^&_&=7|FyV-f z>8OscK#uF^9Pao9?Ff%BGml*$kM#&%_?QLvh>!fJkN*ge0V$9JNst9;kOygg{y2|$ za*P}W01t_J(ROnXnG_F69uygoS#W6?NrswMhZ1R#i}qO zhk~eW$~I857HZtlcxS*^AZ0@>`960DFwZ8FN0e+N$&o|;bdy2F1t>X`KzVFBDF@%i zX%N{*ocC3Kgpw3#ZVA^?Md=dlc9Ix*l~QSyLbW1Fxp-n3Z&In2V(D>M`4v{_lBIZ1 zZs|}?(jEXsC1@FQwqcepqD#`c!5cEh}o9Zv_B#TP1bahF$H$4 zL70&#cwos;;c-kSS5Ad#m|qEXgoSaU$(J5Sl51d^pmv!vQkgfUP8F`AC znin~4JV#Zl*_wQ}8h*zLE7h0!)_5NUk~TF=BJ^@|_f$%Gl;pv75wce`Wu4R+QyF&$ z&{=w;2~Kato!$v`MFM!8$#_o17KP`UHNsCEr+BO8iFncJ253p2huKnMr9p4WmV}8< zdP$yhX`5B4cR{%WnrV8Y*K~Ht9$^Wa26>6auilG?+ni*OG#mS)} zv7sL-q9aP8CHg%cYNDH&qEHp0E9#;z3ZpSvCMYVSEkL6+8k#t&qdUr@Jvt^g>Z3*( zq!TfuMQWr+`U*gbq-nLJa@C?unwwB6rBh0!RcfVIilteqrCZ9SUFxOoR{#JzTehj$ literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig2.fig b/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig2.fig new file mode 100644 index 0000000000..facf410fc9 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig2.fig @@ -0,0 +1,50 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +0 32 #efefef +0 33 #cfcfef +0 34 #bebebe +2 1 2 4 0 7 0 0 -1 10.000 1 1 -1 0 0 2 + 4050 3750 4050 4425 +2 1 0 2 9 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4950 4800 5550 4800 +2 1 0 2 9 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4950 3600 5550 3600 +2 1 0 2 9 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 6600 5700 7725 5700 +2 1 0 2 9 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 6600 5550 6900 5550 6900 5100 4950 5100 4950 2850 5550 2850 +2 1 0 2 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9525 4800 9750 4800 9750 5100 7200 5100 7200 5550 7725 5550 +2 1 0 2 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9450 3000 9750 3000 9750 3225 5100 3225 5100 3450 5550 3450 +2 1 0 2 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9450 3600 9750 3600 9750 3825 5100 3825 5100 4050 5550 4050 +2 1 0 2 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9450 4200 9750 4200 9750 4425 5100 4425 5100 4650 5550 4650 +4 0 0 0 0 0 20 0.0000 4 195 1905 3300 4800 RewriteCond \001 +4 0 0 0 0 1 20 0.0000 4 210 1620 7800 4800 CondPatternN\001 +4 0 0 0 0 0 20 0.0000 4 195 1905 3300 3600 RewriteCond \001 +4 0 0 0 0 1 20 0.0000 4 210 1575 7800 3600 CondPattern2\001 +4 0 0 0 0 1 20 0.0000 4 270 1290 5625 4800 TestStringN\001 +4 0 0 0 0 1 20 0.0000 4 270 1245 5625 3600 TestString2\001 +4 0 0 0 0 0 20 0.0000 4 195 1905 3300 3000 RewriteCond \001 +4 0 0 0 0 1 20 0.0000 4 270 1245 5625 3000 TestString1\001 +4 0 0 0 0 1 20 0.0000 4 210 1575 7800 3000 CondPattern1\001 +4 0 0 0 0 1 20 0.0000 4 210 1320 7800 5700 Substitution\001 +4 0 0 0 0 1 20 0.0000 4 195 825 5700 5700 Pattern\001 +4 0 0 0 0 0 20 0.0000 4 195 1455 3300 5700 RewriteRule\001 diff --git a/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig2.gif b/APACHE_1_3b7/htdocs/manual/images/mod_rewrite_fig2.gif new file mode 100644 index 0000000000000000000000000000000000000000..3ea8cb65a3f9f1682c6b52d3911f52d2434ad38f GIT binary patch literal 2553 zcmV*@J5W=b#yB~Kp0=~-bve892N4)}p(pW%2p5sZht~LD zI1%}hx8|otxH2g-xLK0vxppC@5V~NentIoI(rJ0{2OE+}BP-$wx*=Bz983yn zON(iU%aN>EEQsprz_yI0Q)?}KoO*nQ-CZ_4KxX`yc3=u2d>*X_(0`guqzqd@*%#-LfeXh5BVQWpLp z)QG8|NtFn{$$Q4mA4HAe4t}G#aHU6(6t}s=hq0PVmJMrKq`A|k!e|9O8l4z&!W#`S zjZ$>#(5cRsJn6|i1(K`QjsTk`MM>77$!02Ard6pHsnu+78$i8lc7VuF^ky0)tFtHF zr(QWty35d@Uzmf7Y8_lL2S2v}^FhUV^=(jScxmn>5x6qvpoM!Pb&QqLVZdksM=H$I z>f6||`_!fUG4I*j11X7%v6>pY2xh3(3xa*;o zNYwSdUv1ZB&wdX*)_krZ4vewXW?IWbBeN8I)p6nPzS&B?4Ba$!41htm$T)Y{DsLok!AXXP!Iasb`-s^66)wB?2mFp%M~m zXrkQ3=fOx@uY&%$*{vTrQ0I{>pr{8vB)Ijjp5X8oW+QCNZyu6c=x)f=Sie!59OmW78?Uq0#Q z-A_M>*2j0|B3IR1{j3WUtyZmwDmAPb*OzWZ(KlCd!!olPXD?x<)MZ`WCSOCy2xXtD zBJXyVst}vinMV{8xGT+dtvA`ugw^Np$GNUjU414?N3v`l^XJ|U-Mw}&ZPjtd6m(DJ z6=fj;N4r>Zw<*{1t;9aJ(R|1-mS1mQ3*BsPl^rbC)KrgcT-_5(HI>#v|5g>Q3aoBpX0Y3fE=(`y56f!k?an7cM1Y2Z z>89<%9O0m%5>UCP<%ld{q4w}rZ#fjfi|+vUI%bW2f9l`Je*0g%Phpa(w)!Vrq^ zK;-L{1y9HXM4@nnK~NzJU&sR&!f=MpVu1{4I70`L;D$JSp$#5&cs{ zYT@jNOnhJx6M&^AO3?#^;?n*Uuh<3#lnIMmM8^c;)kQ!3a6w;0P#6_8#t_^LgJ*0~ z8bMIOHp($7bF3p3?TE(>#4(Rt+#?@BK)p8k@sBNFBX(pkNJ5^-eBJ6mA{CheLyiju zkA&n2BzXe>G;%|hOadk^RLM@dsDz>{!Y2<^N+X=|L7_|~AW7-UAgr=&FKA^fYs5%I z`f7x{?4>V%3Cv(F(FvN=r3r6Y#~>n;iOO825u52uAwn~nIGiRmXK2l9zA&5GEP^J# zSxjy@;+s@?7XnT-%uMkmW9qbo!NR!*cxJ^gHB45ja8-zDopYBYWED8c87Y7YLT~j< z!9TkN&v44KJU)w6L;elAvYZ*|nCAo|*E}W(wrLbBv>95q?)j~FcCxUUeXSS_qn!ztLk!=+AD_Zz6^so0i)aBZQiC`j+k z*P9!?-z)_r-R~*Ey)V3Rf27Mu^G49eU|?}Kw+G83*MP`hFtU<|l;kJNfXQBPvXr$L z_+~zF2`O9&Z^NR0`=RE7#d1Vx) zpa1;+r88#{$%0-X#R_fcFCrR+hhDS=8|`QXLORm?n>3~6XX#6$FVmXV9;Z87n?$UQ1dKj$WxKWt%&lC&*2KeJ zg|Jc^3%8wSJbJ~>Es5hsvVku&bMOtThffzVrY3bjZp9qQL0cRG3m7&S2lxLF`)k|Z zf?Q-y{q1!w@@ujE{JG!dHe$z|&Vcqbv=aBY>W)J$AvZ9!qFH%?Ma*N^PF&p0-WiVv zzMQNZfxTa!4%O>=-_E_8*b=)>dpCpizhqA8omJk;HIvg6=s4YH_3mYv&UCJ#46a;f zD6N=H-t{KN>tGW*NzbkI=0cs4Ge);y`zlrYMtkMWtfc2gZs#07qC6*Y8&p!K)?pjTI?meG(PwMLdKh&2SzNe>a{NyWt`OI&=^Pdm> P=u3b4)UW=R3jhE+CPVN4 literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/htdocs/manual/images/sub.gif b/APACHE_1_3b7/htdocs/manual/images/sub.gif new file mode 100644 index 0000000000000000000000000000000000000000..93061c5ad7f011307c4188fbc5d134db19fbc8c0 GIT binary patch literal 6083 zcmaKNc~BGC_xAdZs(b)vW+xP(Py6C*@L zL<}GZDo$WT5k&(CqM{Qwz;y!Z;7)MG`HYh<)bIaaSJ$mu{q8&WoO9o+4h;|S79@R! z{J}RPFdB^*hQ-9hBqt|lW@f5Xs=B(m-rimW01N;Q0DJ%h0EhvI2Ot@MGypOI7)5{) z0dBs~z0wh%oa+5J*>tsZ}wSu(NnA8{$BjzT@^96j2&qa&_AU9Ji7GY`0$k=UASb)7PdXQX7zC&=(8>a1lhm-u{$P{?R0!ZqQWJsE zNm7$LVy5yY3~)IhCV7hfWQ{m&%7d6RFqSz*d{TXUJgDOWaSTwg0C&;`)zq%k%Bj`c zbyMK1rYS#C)27M92On^aV1Nra zO;ZK8$3TY>^ooIi16anXyfp?0DnaT1m>dGX6=cQ(ff3Y+05=tgjG!_TOwNSW3(`hG z?${K9$~YBsV*qymq;fFU*i^4fG2j?MS|t!=0=^NX8bPuV#IpeMZOT<_Ux;B?M~%Trt2>0ZRoql~YTTYy~j@iw9UPU_G0H<%$3@HkEM102u(29VeMj zzL;@pl>fhH^6+!M;~@Zyz;&u_>P`re$xA_=8KzNp<{;BtR`hAAyZ2yr;>xh*nw}!o zoRlYh&9#A$bztGl@RsA(%ba6Rt`OW+0H-Lkz6l7|Tf}tpRO#hO*}25eFRrKU`Ec0t zm;NmY5jPe-YJrVJge_GUX2Fnfy1l%vYT55gmls+^oICyS4_Qyl{**d2+irneD~zsz zE>*ug-PoPiRMA?0r+gCk)O5EMEt11#1o1(a*dnilm|U4e?Z4@3-?n?iTju=Lm$rYu z`|{N5doZyf(ao#r?Vu+4X307Q7&LSC@AJ+MbT4MuScH|IU!O2fK3Wx=w&mTyx$B2Y z94UW?Z)jZn=g#pO=G!HWQPu9@#*IN-m0fr~<41Ec>Cc(Io1ba8c8*c~%;g_vG{+w}i0l%c2xq!;8Q2?GMUE z3Y_a3Mhacey&5Uv^*TQCHtR+x?yUw}D(^~Me({_;kvX@#|CHX_D;Qg>gb*904o1_q9U$yg=efLT zIDRnYO=Cm7Pc60piO#`-tc`c<7{21@t7g#?tld=M2UzCT_AX|ae@9rm(BrN&Im+iE z)*ZpuKIx+HFW7e%d)`}ZcY991=Z%H#R~coI?texmM+q9S}PW$NdaKzfY0E zEV)^bu#;dOrvrpTTciP3$WkFpv^cHFCMPzl-*jW4uH#o3%hrzfIMy`x_Wr#6CDCeg zZa=9Y7yogOU5V?ez8kKV@b#NV<7^)~s6Nk&;MQM?DRNs01r{aso)*eS2!gl;*AzyfdnUpv9ih10gIc&+G(DB2VkPjc42_z!|CpYyvCdNqTXI(hDjNil!_!6V zSaSsv6)IfL?gp^z=BJRbF0;~?E;uzjUZKR>G-z=*lmV2b!ffhiy!8ujl1FZIQT!#C zS*{_t8WTGUqn^}Ef0|Wn8^Wm?w-=cd@s``X%FCe2?~fipMrCeE!Krmkjn%Pwhm zdo;=-FH^2s{m07>>U-^1Jb`x(<8YSf7Ku(^y|b0g#WFvf&kZ!xcYwc-Bv;@aB#H6* z-o6l@kNXo3cQFo1vz_{HkS}C+nQU>$wewDz_9gC7!B6{U`hv1seBG z>#3%m5?-6zXIfHMmt$4ENg)cnuov-@La*A0^UfvhB}k-}f2oP{9#xlY^0Z}M1a$>9 z!PP&VZZN-KzTo^KvZv6-hr{H%fL`oU5@oK=Sr@ z?0@LS{rV4S)K%Wyy}i=Blku&laXl$Bg-iGNgAvcAsyaKzJ2gr1d#0Td#?HFizSOg+ zYer9c0zWdvqK3K7Ql|*zN%i(wtX~n4|AQ zr^V-5qHdjDGw0+{N_CVGVj zph8{N`1M-v!HI}X%Fd>*v|7_}zumLK?i4IjcA?RY?-!rpc^|^77eLS%vO5ZKs8A%;jJKbqiS8rU$=wGe{G`e0jJr%Q2-JddgP13|&AW1WYID zp3~k;{HbuShCF2i<|{l7muW$G)~UBhRKOH0)T^esIKi83J?a%Y?$opln`IJ2&lxgCUAQ5LIgla!NcK$!epjuI{yZVFG?j(U z)nutwzZ;3`)qA_eRToC_vUhDV;B4J%_k^p={kQ76*9<6$yo_q<>b`w59`W+{uiArC z;>w(;0VJ2N0onPApif{4$J)67H!9@0}366FzqTJ zyQpscGULzm&}R*yF|1OvbjCI(B#T@=)@fR!#XI{YG1tc7Ec(R+sNc?PMuQ=D)+$qqv~7f0?O#*9_RjjB2cJ&Ax45yk zrF!q$O|_P9FcRlwK-T?-5d@yX)kxW-oA`Ld`0w$In~a%DP26N0sB91}k$=Y9kh4C< zc#D4QR-%#p(aaWgWV4oXj<>zlKiN^Ovj=cKmKw+&gWWW- z&U&6J8~18!ZdiG4qpiIlJA6S4K9-Fau-$ri)XQ?Z!w?-GOn=KZG010M*16r2(}pqb z6Lwe+$K<&N3`*%Aomc9%zgg_->Qnf^lWtY^>khkgZR&@4Sf)Zintci>7_WCjG)nSVBm*YEG_)uZ-)mOOE#fwVXiu;l9HA10f z4)Jb2Q7+lLg6XkVZ&S`fE_EaO414txNUec5!EiWQI9;KO31Pq8-(e?afOsC}LW8l=>{-{Gjv}M(3HAc@#+Oy1?A);D1J$Euw}T z**HhJ-;X5Nho=f!t_o?y36(1Bf-3T%D$3k$){Fx&f&-)^uuOO$?(l*5ZDuR90ZSy_ zHX=}X6?2a^nP@#AJA4pF6g36_7Yw$=U`!8RX@<_X!Y)G0Y8BIJ71;R@!x>g4@(-pg zFVDN+httjT)#G95>e=#XZajFF7P|U{ZYuS8s->++r%`w&A9!^5PCzTPt~HwA6pFcz zbMHDx_dKjPvwU767dM}WpRcp@Wgk{u|B0c4whq&u80drZXm`}K42Ewb=6l&dX_Y3& z={P5&!3_!a^EQj5@rr?MM`ioV-K8=s-io=$Wp-?MuJQh~F%9jZl6F_l*#5$QKx1{* zfYxs!S4hc)(tvU{c_J7z>85-9z4AX(@F4Ff?4!0%0wHX?SOKiD#EO{2j+eWKCG_na z+8scBAzyz_U1d6C)xayMk&>GX_RojOo%gJF8i<*S8aUb(h}G`@)R=b$z?#@u82rP- z#|&fWwMRavf8EApUDG9*dT*-LQ+D66IxQ)gxcA#m%x@D$g6^+c2SQfq2rIuGyF;vv zZ?7Yp&foVO@{>;EVzB->>@0+5N+CL%KE$Iv(1u!sP<`S=dFWZds)!?c=3H+L6F7kRd z2GP~@XL;-I%W3BA)JEV8^3ffu$ow?&0RvK``z=Sf*1#dH#Yl#6qFXO*wD8smQUK z@rHU)PJgw$TB`{9U5_^Lg6cKw5;^kA!BsniNQWay&LjOXJ>=YUBI%oh;|OsbmhqdO zR3;;BRUoAjvYbSDkVm-r<-kp*$Z|Ddu%gNKZTzlqLWlzI!NytZ;haOzRVI`!^Z8p& zlQ=@7##XvsO6$^YXqVC)kmJ2-3f6}fZ9q?G(c^41@`%Xdx}KAA zr&UM>K+MjPjGssfEmEK(Z#F|uu+atsdUEoZY@{eubOR5f@h~C=@X<%pEH53HBZGzW zEwEpo%V~@Z>iaax_SMvG1$7W(SvvZ*saZuy=ztUb zOAKV8#_w~v#PGA+br{cPdokE_3LEFlu43v}_l?i4FQaw6PHT~%$AzcLwe2I(zG}Al z|HOz&xyH~*Oammhb3`ddg0~W-Y>V1)LW+)%peDN35Lf6)>4pV)N@SGd#C*IZ?Y@2U z#mMvW?ekUWj$HafDSbpu|DfM(A~azF*bU&^c%8Cw)%r`t(SQ(GvulGZ-o-!-IB#`Y zkFvd}c>!mub!4pqZL_n^mtVeul6D$}q|WvwZePt4w8VtFo5yF_t&+t{VNMSjZwJooa(gb`*W1dPA7h+(r#*~*UjjIqj?lw*hdT^mciA9 zu%iOU$NK3%bjP!2MeD;w61@LMI}ZuI{2MO9fRjk@!AhI}D~^|#Fdo{jkzX#FDZNT`!)9vQ8%mdy z+OMQOQo7!s#~tycC&cL(de4*_vpE{wd>#%<7+6Ddi7?%7!Bu zc(HUF@`!vAkJc*D!f`ZXVQ4d;v?!2If;9)QK11>LR%KU0-Uif}Q!A(Ve4_N)bIQ~d zvD<@t&D6o{h1X%)%j_KkhMqV2KOO?Q!XfH0n_;E_QDx9b88j1vU3lrv>Nu`W_si4A zmw(tU2fM`vd@vjDD8WZ7aY~Z?(L*?q-cF*%d)wk_HA5#1k(-^U7u2EG^wdEkM!gnF z(elunDzr`M{FFvpoKC%$MY(6Dc)F2xxod+~eW`R6{e?EK2Qqo(X<|_Ntoe7g|M=`R z{{k~PR1Pm9mTTeV0KZ`-!PoX$tQ_xO+W*fWQlFlsHBfEy zX;0+zY|E&ZYTBO?>Q&oE@7y}Rb<7t>5WNOKs{^GrE3 zT>_i3eX>L0S-PC3J%FrBuvQYBdAZDIFBARwUOa-AayV825WfevBqq-^v|(l0GtIsg z>_-oHv@#F+Uvk=eHhok$`;!ntHMDY~iHTx&V-xLp?fl0^$>h&(6k|gyJ@iEnu{4l{ zPPuaD>+-7Q$~OKc1u0!xaA=5BBo*uXkkx-9$9SbxTBJhvrdn#-E~K>FwrW$9*sr2p zmw2{Y(^hWZ0lj}K8V3JPc(%paQk7m_Ny?6ixDNi2K*KxTfA7je@rM)Nm#{Ks#+vN1 z@Yu*BIhZY#teE3qX8kdI>D*fMv@Y zb}8NBaz1Xr-w^q|c>fT;KB-;RK(cGu>-@=p%_diS$751v8lbU**D`B2|{gCwI~ z=GlHh?7purT9gLavtjO)kLsLvdt2Z2e|V=;yW{aIKZW*P-e3O7GO)nU#zP^$yE5A2 ziT6_Xjp*Bk@jq@`otPN!;Vt{Y|7b576LCxg- + + +Apache 1.3 documentation + + + + + +

Apache 1.3 User's Guide

+ +
+ +

Release Notes

+ + +

Apache Reference Manual

+ + + +

Other Notes

+ + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/install.html b/APACHE_1_3b7/htdocs/manual/install.html new file mode 100644 index 0000000000..ad532557e1 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/install.html @@ -0,0 +1,262 @@ + + + +Compiling and Installing Apache + + + + + + +

Compiling and Installing Apache 1.3

+ +UnixWare users will want to consult build notes +for various UnixWare versions before compiling. + +

Downloading Apache

+ +Information on the latest version of Apache can be found on the Apache +web server at http://www.apache.org/. This will +list the current release, any more recent beta-test release, together +with details of mirror web and anonymous ftp sites. + +

+ +If you downloaded a binary distribution, skip to Installing Apache. Otherwise read the next section +for how to compile the server. + +

Compiling Apache

+ +Compiling Apache consists of three steps: Firstly select which Apache +modules you want to include into the server. Secondly create a +configuration for your operating system. Thirdly compile the +executable. +

+ +All configuration of Apache is performed in the src +directory of the Apache distribution. Change into this directory. + +

    +
  1. + Select modules to compile into Apache in the + Configuration file. Uncomment lines corresponding to + those optional modules you wish to include (among the AddModule lines + at the bottom of the file), or add new lines corresponding to + additional modules you have downloaded or written. (See API.html for preliminary docs on how to + write Apache modules). Advanced users can comment out some of the + default modules if they are sure they will not need them (be careful + though, since many of the default modules are vital for the correct + operation and security of the server). +

    + + You should also read the instructions in the Configuration + file to see if you need to set any of the Rule lines. + + +

  2. + Configure Apache for your operating system. Normally you can just + type run the Configure script as given below. However + if this fails or you have any special requirements (e.g. to include + an additional library required by an optional module) you might need + to edit one or more of the following options in the + Configuration file: + EXTRA_CFLAGS, LIBS, LDFLAGS, INCLUDES. +

    + + Run the Configure script: +

    +
    +    % Configure
    +    Using 'Configuration' as config file
    +     + configured for <whatever> platform
    +     + setting C compiler to <whatever> *
    +     + setting C compiler optimization-level to <whatever> *
    +     + Adding selected modules
    +     + doing sanity check on compiler and options
    +    Creating Makefile in support
    +    Creating Makefile in main
    +    Creating Makefile in os/unix
    +    Creating Makefile in modules/standard
    +   
    +
    + + (*: Depending on Configuration and your system, Configure + make not print these lines. That's OK).

    + + This generates a Makefile for use in stage 3. It also creates a + Makefile in the support directory, for compilation of the optional + support programs. +

    + + (If you want to maintain multiple configurations, you can give a + option to Configure to tell it to read an alternative + Configuration file, such as Configure -file + Configuration.ai). +

    + +

  3. + Type make. +
+ +The modules we place in the Apache distribution are the ones we have +tested and are used regularly by various members of the Apache +development group. Additional modules contributed by members or third +parties with specific needs or functions are available at +<http://www.apache.org/dist/contrib/modules/>. +There are instructions on that page for linking these modules into the +core Apache code. + +

Installing Apache

+ +You will have a binary file called httpd in the +src directory. A binary distribution of Apache will +supply this file.

+ +The next step is to install the program and configure it. Apache is +designed to be configured and run from the same set of directories +where it is compiled. If you want to run it from somewhere else, make +a directory and copy the conf, logs and +icons directories into it. In either case you should +read the security tips +describing how to set the permissions on the server root directory.

+ +The next step is to edit the configuration files for the server. This +consists of setting up various directives in up to three +central configuration files. By default, these files are located in +the conf directory and are called srm.conf, +access.conf and httpd.conf. To help you get +started there are same files in the conf directory of the +distribution, called srm.conf-dist, +access.conf-dist and httpd.conf-dist. Copy +or rename these files to the names without the -dist. +Then edit each of the files. Read the comments in each file carefully. +Failure to setup these files correctly could lead to your server not +working or being insecure. You should also have an additional file in +the conf directory called mime.types. This +file usually does not need editing. + +

+ +First edit httpd.conf. This sets up general attributes +about the server: the port number, the user it runs as, etc. Next +edit the srm.conf file; this sets up the root of the +document tree, special functions like server-parsed HTML or internal +imagemap parsing, etc. Finally, edit the access.conf +file to at least set the base cases of access. + +

+ +In addition to these three files, the server behavior can be configured +on a directory-by-directory basis by using .htaccess +files in directories accessed by the server. + +

Set your system time properly!

+ +Proper operation of a public web server requires accurate time +keeping, since elements of the HTTP protocol are expressed as the time +of day. So, it's time to investigate setting up NTP or some other +time synchronization system on your Unix box, or whatever the +equivalent on NT would be. + +

Starting and Stopping the Server

+ +To start the server, simply run httpd. This will look for +httpd.conf in the location compiled into the code (by +default /usr/local/apache/conf/httpd.conf). If +this file is somewhere else, you can give the real +location with the -f argument. For example: + +
+    /usr/local/apache/httpd -f /usr/local/apache/conf/httpd.conf
+
+ +If all goes well this will return to the command prompt almost +immediately. This indicates that the server is now up and running. If +anything goes wrong during the initialization of the server you will +see an error message on the screen. + +If the server started ok, you can now use your browser to +connect to the server and read the documentation. If you are running +the browser on the same machine as the server and using the default +port of 80, a suitable URL to enter into your browser is + +
+    http://localhost/
+
+ +

+ +Note that when the server starts it will create a number of +child processes to handle the requests. If you started Apache +as the root user, the parent process will continue to run as root +while the children will change to the user as given in the httpd.conf +file. + +

+ +If when you run httpd it complained about being unable to +"bind" to an address, then either some other process is already using +the port you have configured Apache to use, or you are running httpd +as a normal user but trying to use port below 1024 (such as the +default port 80). + +

+ +If the server is not running, read the error message displayed +when you run httpd. You should also check the server +error_log for additional information (with the default configuration, +this will be located in the file error_log in the +logs directory). + +

+ +If you want your server to continue running after a system reboot, you +should add a call to httpd to your system startup files +(typically rc.local or a file in an +rc.N directory). This will start Apache as root. +Before doing this ensure that your server is properly configured +for security and access restrictions. + +

+ +To stop Apache send the parent process a TERM signal. The PID of this +process is written to the file httpd.pid in the +logs directory (unless configured otherwise). Do not +attempt to kill the child processes because they will be renewed by +the parent. A typical command to stop the server is: + +

+    kill -TERM `cat /usr/local/apache/logs/httpd.pid`
+
+ +

+ +For more information about Apache command line options, configuration +and log files, see Starting Apache. For a +reference guide to all Apache directives supported by the distributed +modules, see the Apache directives. + +

Compiling Support Programs

+ +In addition to the main httpd server which is compiled +and configured as above, Apache includes a number of support programs. +These are not compiled by default. The support programs are in the +support directory of the distribution. To compile +the support programs, change into this directory and type +
+    make
+
+ + + + diff --git a/APACHE_1_3b7/htdocs/manual/invoking.html b/APACHE_1_3b7/htdocs/manual/invoking.html new file mode 100644 index 0000000000..df0a4d0445 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/invoking.html @@ -0,0 +1,137 @@ + + + +Starting Apache + + + + + +

Starting Apache

+ +

Invoking Apache

+The httpd program is usually run as a daemon which executes +continuously, handling requests. It is possible to invoke Apache by +the Internet daemon inetd each time a connection to the HTTP +service is made (use the +ServerType directive) +but this is not recommended. + +

Command line options

+The following options are recognized on the httpd command line: +
+
-d serverroot +
Set the initial value for the +ServerRoot variable to +serverroot. This can be overridden by the ServerRoot command in the +configuration file. The default is /usr/local/apache. + +
-f config +
Execute the commands in the file config on startup. If +config does not begin with a /, then it is taken to be a +path relative to the ServerRoot. The +default is conf/httpd.conf. + +
-X +
Run in single-process mode, for internal debugging purposes only; the +daemon does not detach from the terminal or fork any children. Do NOT +use this mode to provide ordinary web service. + +
-v +
Print the version of httpd and its build date, and then exit. + +
-V +
Print the base version of httpd, its sub-version if defined, its +build date, and a list of compile time settings which influence the +behavior and performance of the apache server (e.g., +-DUSE_MMAP_FILES), +then exit. + +
-h +
Give a list of directives together with expected arguments and +places where the directive is valid. (New in Apache 1.2) + +
-l +
Give a list of all modules compiled into the server. + +
-S +
Show the settings as parsed from the config file (currently only +shows a breakdown of the vhost settings). + +
-? +
Print a list of the httpd options, and then exit. +
+ +

Configuration files

+The server will read three files for configuration directives. Any directive +may appear in any of these files. The the names of these files are taken +to be relative to the server root; this is set by the +ServerRoot directive, or the +-d command line flag. + +Conventionally, the files are: +
+
conf/httpd.conf +
Contains directives that control the operation of the server daemon. +The filename may be overridden with the -f command line flag. + +
conf/srm.conf +
Contains directives that control the specification of documents that +the server can provide to clients. The filename may be overridden with +the ResourceConfig directive. + +
conf/access.conf +
Contains directives that control access to documents. +The filename may be overridden with the +AccessConfig directive. +
+However, these conventions need not be adhered to. +

+The server also reads a file containing mime document types; the filename +is set by the TypesConfig +directive, +and is conf/mime.types by default. + +

Log files

+

security warning

+Anyone who can write to the directory where Apache is writing a +log file can almost certainly gain access to the uid that the server is +started as, which is normally root. Do NOT give people write +access to the directory the logs are stored in without being aware of +the consequences; see the security tips +document for details. +

pid file

+On daemon startup, it saves the process id of the parent httpd process to +the file logs/httpd.pid. This filename can be changed with the +PidFile directive. The process-id is for +use by the administrator in restarting and terminating the daemon; +A HUP or USR1 signal causes the daemon to re-read its configuration files and +a TERM signal causes it to die gracefully. For more information +see the Stopping and Restarting page. +

+If the process dies (or is killed) abnormally, then it will be necessary to +kill the children httpd processes. + +

Error log

+The server will log error messages to a log file, logs/error_log +by default. The filename can be set using the +ErrorLog directive; different error logs +can +be set for different virtual hosts. + +

Transfer log

+The server will typically log each request to a transfer file, +logs/access_log by default. The filename can be set using a +TransferLog directive; +different transfer logs can be set for different +virtual hosts. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/keepalive.html b/APACHE_1_3b7/htdocs/manual/keepalive.html new file mode 100644 index 0000000000..31f35327c4 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/keepalive.html @@ -0,0 +1,103 @@ + + +Apache Keep-Alive Support + + + + + +

Apache Keep-Alive Support

+ +
+ +

What is Keep-Alive?

+ +The Keep-Alive extension to HTTP, as defined by the +HTTP/1.1 draft, allows persistent connections. These +long-lived HTTP sessions allow multiple requests to be send over the +same TCP connection, and in some cases have been shown to result in an +almost 50% speedup in latency times for HTML documents with lots of +images. + +

Enabling Keep-Alive Support

+ +Apache 1.1 comes with Keep-Alive support on by default, however there +are some directives you can use to modify Apache's behavior: + +

Note: Apache 1.2 uses a different syntax for the KeepAlive directive.

+ +

KeepAlive

+Syntax: KeepAlive max-requests
+Default: KeepAlive 5
+Context: server config
+Status: Core

+ +This directive enables Keep-Alive support. Set max-requests +to the maximum number of requests you want Apache to entertain per +connection. A limit is imposed to prevent a client from hogging your +server resources. Set this to 0 to disable support. + +

KeepAliveTimeout

+Syntax: KeepAliveTimeout seconds
+Default: KeepAliveTimeout 15
+Context: server config
+Status: Core

+ +The number of seconds Apache will wait for a subsequent request before +closing the connection. Once a request has been received, the timeout +value specified by the Timeout directive +applies. + +

When Keep-Alive Is Used

+ +In order for Keep-Alive support to be used, first the browser must +support it. Many current browsers, including Netscape Navigator 2.0, +and Spyglass Mosaic-based browsers (including Microsoft Internet +Explorer) do. Note, however, that some Windows 95-based browsers misbehave +with Keep-Alive-supporting servers; they may occasionally hang on a +connect. This has been observed with several Windows browsers, and occurs +when connecting to any Keep-Alive server, not just Apache. Netscape 3.0b5 +and later versions are known to work around this problem. + +

However, Keep-Alive support only is active with files where the +length is known beforehand. This means that most CGI scripts, +server-side included files and directory listings will not use +the Keep-Alive protocol. While this should be completely transparent +to the end user, it is something the web-master may want to keep in mind.

+ + + + + diff --git a/APACHE_1_3b7/htdocs/manual/location.html b/APACHE_1_3b7/htdocs/manual/location.html new file mode 100644 index 0000000000..2dddd2ee2c --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/location.html @@ -0,0 +1,68 @@ + + + +Access Control by URL + + + + + +

Access Control by URL

+ +

The <Location> Directive

+ +Syntax: <Location URL prefix>
+Context: server config, virtual host
+Status: core
+ +

The <Location> directive provides for access control by +URL. It is comparable to the <Directory> directive, and +should be matched with a </Location> directive. Directives that +apply to the URL given should be listen +within. <Location> sections are processed in the +order they appear in the configuration file, after the +<Directory> sections and .htaccess files are +read.

+ +

Note that, due to the way HTTP functions, URL prefix +should, save for proxy requests, be of the form /path/, +and should not include the http://servername. It doesn't +necessarily have to protect a directory (it can be an individual +file, or a number of files), and can include wild-cards. In a wild-card +string, `?' matches any single character, and `*' matches any +sequences of characters. + +

This functionality is especially useful when combined with the +SetHandler +directive. For example, to enable status requests, but allow them only +from browsers at foo.com, you might use: + +

+    <Location /status>
+    SetHandler server-status
+    order deny,allow
+    deny from all
+    allow from .foo.com
+    </Location>
+
+ + + + + diff --git a/APACHE_1_3b7/htdocs/manual/man-template.html b/APACHE_1_3b7/htdocs/manual/man-template.html new file mode 100644 index 0000000000..805b0079e9 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/man-template.html @@ -0,0 +1,108 @@ + + + + Apache module mod_foobar + + + + + +

Module mod_foobar

+ +
Add this file as a link in mod/index.html
+ +

+ This module is contained in the mod_foobar.c file, and + is/is not compiled in by default. It provides for + the foobar feature. Any document with the mime type + foo/bar will be processed by this module. +

+ +
Add the magic mime type to the list in +magic_types.html
+ +

Summary

+

+ General module documentation here. +

+ +

Directives

+ + +
Add these directives to the list in +directives.html
+ +
+

ADirective directive

+

+ Syntax: ADirective some args +
+ Default: ADirective default value +
+ Context: context-list +
+ +

context-list is where this directive can appear; +allowed: server config, virtual host, directory, .htaccess
+ + Override: override +
+ +
required if the directive is allowed in .htaccess files; +the AllowOverride option that allows the directive.
+ + Status: status +
+ +
Core if in core apache, Base if in one of the standard +modules, Extension if in an extension module (not compiled in by default) +or Experimental
+ + Module: mod_foobar +
+ Compatibility: compatibility notes + +
+ Describe any compatibility issues, such as "Only available in Apache + 1.2 or later," or "The Apache syntax for this directive is not + compatible with the NCSA directive of the same name." +
+

+ +

+ The ADirective directive does something. +

+ + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/API.html b/APACHE_1_3b7/htdocs/manual/misc/API.html new file mode 100644 index 0000000000..1b59833024 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/API.html @@ -0,0 +1,1151 @@ + + +Apache API notes + + + + +

Apache API notes

+ +These are some notes on the Apache API and the data structures you +have to deal with, etc. They are not yet nearly complete, but +hopefully, they will help you get your bearings. Keep in mind that +the API is still subject to change as we gain experience with it. +(See the TODO file for what might be coming). However, +it will be easy to adapt modules to any changes that are made. +(We have more modules to adapt than you do). +

+ +A few notes on general pedagogical style here. In the interest of +conciseness, all structure declarations here are incomplete --- the +real ones have more slots that I'm not telling you about. For the +most part, these are reserved to one component of the server core or +another, and should be altered by modules with caution. However, in +some cases, they really are things I just haven't gotten around to +yet. Welcome to the bleeding edge.

+ +Finally, here's an outline, to give you some bare idea of what's +coming up, and in what order: + +

+ +

Basic concepts.

+ +We begin with an overview of the basic concepts behind the +API, and how they are manifested in the code. + +

Handlers, Modules, and Requests

+ +Apache breaks down request handling into a series of steps, more or +less the same way the Netscape server API does (although this API has +a few more stages than NetSite does, as hooks for stuff I thought +might be useful in the future). These are: + +
    +
  • URI -> Filename translation +
  • Auth ID checking [is the user who they say they are?] +
  • Auth access checking [is the user authorized here?] +
  • Access checking other than auth +
  • Determining MIME type of the object requested +
  • `Fixups' --- there aren't any of these yet, but the phase is + intended as a hook for possible extensions like + SetEnv, which don't really fit well elsewhere. +
  • Actually sending a response back to the client. +
  • Logging the request +
+ +These phases are handled by looking at each of a succession of +modules, looking to see if each of them has a handler for the +phase, and attempting invoking it if so. The handler can typically do +one of three things: + +
    +
  • Handle the request, and indicate that it has done so + by returning the magic constant OK. +
  • Decline to handle the request, by returning the magic + integer constant DECLINED. In this case, the + server behaves in all respects as if the handler simply hadn't + been there. +
  • Signal an error, by returning one of the HTTP error codes. + This terminates normal handling of the request, although an + ErrorDocument may be invoked to try to mop up, and it will be + logged in any case. +
+ +Most phases are terminated by the first module that handles them; +however, for logging, `fixups', and non-access authentication +checking, all handlers always run (barring an error). Also, the +response phase is unique in that modules may declare multiple handlers +for it, via a dispatch table keyed on the MIME type of the requested +object. Modules may declare a response-phase handler which can handle +any request, by giving it the key */* (i.e., a +wildcard MIME type specification). However, wildcard handlers are +only invoked if the server has already tried and failed to find a more +specific response handler for the MIME type of the requested object +(either none existed, or they all declined).

+ +The handlers themselves are functions of one argument (a +request_rec structure. vide infra), which returns an +integer, as above.

+ +

A brief tour of a module

+ +At this point, we need to explain the structure of a module. Our +candidate will be one of the messier ones, the CGI module --- this +handles both CGI scripts and the ScriptAlias config file +command. It's actually a great deal more complicated than most +modules, but if we're going to have only one example, it might as well +be the one with its fingers in every place.

+ +Let's begin with handlers. In order to handle the CGI scripts, the +module declares a response handler for them. Because of +ScriptAlias, it also has handlers for the name +translation phase (to recognize ScriptAliased URIs), the +type-checking phase (any ScriptAliased request is typed +as a CGI script).

+ +The module needs to maintain some per (virtual) +server information, namely, the ScriptAliases in effect; +the module structure therefore contains pointers to a functions which +builds these structures, and to another which combines two of them (in +case the main server and a virtual server both have +ScriptAliases declared).

+ +Finally, this module contains code to handle the +ScriptAlias command itself. This particular module only +declares one command, but there could be more, so modules have +command tables which declare their commands, and describe +where they are permitted, and how they are to be invoked.

+ +A final note on the declared types of the arguments of some of these +commands: a pool is a pointer to a resource pool +structure; these are used by the server to keep track of the memory +which has been allocated, files opened, etc., either to service a +particular request, or to handle the process of configuring itself. +That way, when the request is over (or, for the configuration pool, +when the server is restarting), the memory can be freed, and the files +closed, en masse, without anyone having to write explicit code to +track them all down and dispose of them. Also, a +cmd_parms structure contains various information about +the config file being read, and other status information, which is +sometimes of use to the function which processes a config-file command +(such as ScriptAlias). + +With no further ado, the module itself: + +

+/* Declarations of handlers. */
+
+int translate_scriptalias (request_rec *);
+int type_scriptalias (request_rec *);
+int cgi_handler (request_rec *);
+
+/* Subsidiary dispatch table for response-phase handlers, by MIME type */
+
+handler_rec cgi_handlers[] = {
+{ "application/x-httpd-cgi", cgi_handler },
+{ NULL }
+};
+
+/* Declarations of routines to manipulate the module's configuration
+ * info.  Note that these are returned, and passed in, as void *'s;
+ * the server core keeps track of them, but it doesn't, and can't,
+ * know their internal structure.
+ */
+
+void *make_cgi_server_config (pool *);
+void *merge_cgi_server_config (pool *, void *, void *);
+
+/* Declarations of routines to handle config-file commands */
+
+extern char *script_alias(cmd_parms *, void *per_dir_config, char *fake,
+                          char *real);
+
+command_rec cgi_cmds[] = {
+{ "ScriptAlias", script_alias, NULL, RSRC_CONF, TAKE2,
+    "a fakename and a realname"},
+{ NULL }
+};
+
+module cgi_module = {
+   STANDARD_MODULE_STUFF,
+   NULL,                     /* initializer */
+   NULL,                     /* dir config creator */
+   NULL,                     /* dir merger --- default is to override */
+   make_cgi_server_config,   /* server config */
+   merge_cgi_server_config,  /* merge server config */
+   cgi_cmds,                 /* command table */
+   cgi_handlers,             /* handlers */
+   translate_scriptalias,    /* filename translation */
+   NULL,                     /* check_user_id */
+   NULL,                     /* check auth */
+   NULL,                     /* check access */
+   type_scriptalias,         /* type_checker */
+   NULL,                     /* fixups */
+   NULL,                     /* logger */
+   NULL                      /* header parser */
+};
+
+ +

How handlers work

+ +The sole argument to handlers is a request_rec structure. +This structure describes a particular request which has been made to +the server, on behalf of a client. In most cases, each connection to +the client generates only one request_rec structure.

+ +

A brief tour of the request_rec

+ +The request_rec contains pointers to a resource pool +which will be cleared when the server is finished handling the +request; to structures containing per-server and per-connection +information, and most importantly, information on the request itself.

+ +The most important such information is a small set of character +strings describing attributes of the object being requested, including +its URI, filename, content-type and content-encoding (these being filled +in by the translation and type-check handlers which handle the +request, respectively).

+ +Other commonly used data items are tables giving the MIME headers on +the client's original request, MIME headers to be sent back with the +response (which modules can add to at will), and environment variables +for any subprocesses which are spawned off in the course of servicing +the request. These tables are manipulated using the +ap_table_get and ap_table_set routines.

+

+ Note that the Content-type header value cannot be + set by module content-handlers using the ap_table_*() + routines. Rather, it is set by pointing the content_type + field in the request_rec structure to an appropriate + string. E.g., +
+  r->content_type = "text/html";
+ 
+
+Finally, there are pointers to two data structures which, in turn, +point to per-module configuration structures. Specifically, these +hold pointers to the data structures which the module has built to +describe the way it has been configured to operate in a given +directory (via .htaccess files or +<Directory> sections), for private data it has +built in the course of servicing the request (so modules' handlers for +one phase can pass `notes' to their handlers for other phases). There +is another such configuration vector in the server_rec +data structure pointed to by the request_rec, which +contains per (virtual) server configuration data.

+ +Here is an abridged declaration, giving the fields most commonly used:

+ +

+struct request_rec {
+
+  pool *pool;
+  conn_rec *connection;
+  server_rec *server;
+
+  /* What object is being requested */
+
+  char *uri;
+  char *filename;
+  char *path_info;
+  char *args;           /* QUERY_ARGS, if any */
+  struct stat finfo;    /* Set by server core;
+                         * st_mode set to zero if no such file */
+
+  char *content_type;
+  char *content_encoding;
+
+  /* MIME header environments, in and out.  Also, an array containing
+   * environment variables to be passed to subprocesses, so people can
+   * write modules to add to that environment.
+   *
+   * The difference between headers_out and err_headers_out is that
+   * the latter are printed even on error, and persist across internal
+   * redirects (so the headers printed for ErrorDocument handlers will
+   * have them).
+   */
+
+  table *headers_in;
+  table *headers_out;
+  table *err_headers_out;
+  table *subprocess_env;
+
+  /* Info about the request itself... */
+
+  int header_only;     /* HEAD request, as opposed to GET */
+  char *protocol;      /* Protocol, as given to us, or HTTP/0.9 */
+  char *method;        /* GET, HEAD, POST, etc. */
+  int method_number;   /* M_GET, M_POST, etc. */
+
+  /* Info for logging */
+
+  char *the_request;
+  int bytes_sent;
+
+  /* A flag which modules can set, to indicate that the data being
+   * returned is volatile, and clients should be told not to cache it.
+   */
+
+  int no_cache;
+
+  /* Various other config info which may change with .htaccess files
+   * These are config vectors, with one void* pointer for each module
+   * (the thing pointed to being the module's business).
+   */
+
+  void *per_dir_config;   /* Options set in config files, etc. */
+  void *request_config;   /* Notes on *this* request */
+
+};
+
+
+ +

Where request_rec structures come from

+ +Most request_rec structures are built by reading an HTTP +request from a client, and filling in the fields. However, there are +a few exceptions: + +
    +
  • If the request is to an imagemap, a type map (i.e., a + *.var file), or a CGI script which returned a + local `Location:', then the resource which the user requested + is going to be ultimately located by some URI other than what + the client originally supplied. In this case, the server does + an internal redirect, constructing a new + request_rec for the new URI, and processing it + almost exactly as if the client had requested the new URI + directly.

    + +

  • If some handler signaled an error, and an + ErrorDocument is in scope, the same internal + redirect machinery comes into play.

    + +

  • Finally, a handler occasionally needs to investigate `what + would happen if' some other request were run. For instance, + the directory indexing module needs to know what MIME type + would be assigned to a request for each directory entry, in + order to figure out what icon to use.

    + + Such handlers can construct a sub-request, using the + functions ap_sub_req_lookup_file and + ap_sub_req_lookup_uri; this constructs a new + request_rec structure and processes it as you + would expect, up to but not including the point of actually + sending a response. (These functions skip over the access + checks if the sub-request is for a file in the same directory + as the original request).

    + + (Server-side includes work by building sub-requests and then + actually invoking the response handler for them, via the + function run_sub_request). +

+ +

Handling requests, declining, and returning error + codes

+ +As discussed above, each handler, when invoked to handle a particular +request_rec, has to return an int to +indicate what happened. That can either be + +
    +
  • OK --- the request was handled successfully. This may or may + not terminate the phase. +
  • DECLINED --- no erroneous condition exists, but the module + declines to handle the phase; the server tries to find another. +
  • an HTTP error code, which aborts handling of the request. +
+ +Note that if the error code returned is REDIRECT, then +the module should put a Location in the request's +headers_out, to indicate where the client should be +redirected to.

+ +

Special considerations for response + handlers

+ +Handlers for most phases do their work by simply setting a few fields +in the request_rec structure (or, in the case of access +checkers, simply by returning the correct error code). However, +response handlers have to actually send a request back to the client.

+ +They should begin by sending an HTTP response header, using the +function ap_send_http_header. (You don't have to do +anything special to skip sending the header for HTTP/0.9 requests; the +function figures out on its own that it shouldn't do anything). If +the request is marked header_only, that's all they should +do; they should return after that, without attempting any further +output.

+ +Otherwise, they should produce a request body which responds to the +client as appropriate. The primitives for this are ap_rputc +and ap_rprintf, for internally generated output, and +ap_send_fd, to copy the contents of some FILE * +straight to the client.

+ +At this point, you should more or less understand the following piece +of code, which is the handler which handles GET requests +which have no more specific handler; it also shows how conditional +GETs can be handled, if it's desirable to do so in a +particular response handler --- ap_set_last_modified checks +against the If-modified-since value supplied by the +client, if any, and returns an appropriate code (which will, if +nonzero, be USE_LOCAL_COPY). No similar considerations apply for +ap_set_content_length, but it returns an error code for +symmetry.

+ +

+int default_handler (request_rec *r)
+{
+    int errstatus;
+    FILE *f;
+
+    if (r->method_number != M_GET) return DECLINED;
+    if (r->finfo.st_mode == 0) return NOT_FOUND;
+
+    if ((errstatus = ap_set_content_length (r, r->finfo.st_size))
+	|| (errstatus = ap_set_last_modified (r, r->finfo.st_mtime)))
+        return errstatus;
+
+    f = fopen (r->filename, "r");
+
+    if (f == NULL) {
+        log_reason("file permissions deny server access",
+                   r->filename, r);
+        return FORBIDDEN;
+    }
+
+    register_timeout ("send", r);
+    ap_send_http_header (r);
+
+    if (!r->header_only) send_fd (f, r);
+    ap_pfclose (r->pool, f);
+    return OK;
+}
+
+ +Finally, if all of this is too much of a challenge, there are a few +ways out of it. First off, as shown above, a response handler which +has not yet produced any output can simply return an error code, in +which case the server will automatically produce an error response. +Secondly, it can punt to some other handler by invoking +ap_internal_redirect, which is how the internal redirection +machinery discussed above is invoked. A response handler which has +internally redirected should always return OK.

+ +(Invoking ap_internal_redirect from handlers which are +not response handlers will lead to serious confusion). + +

Special considerations for authentication + handlers

+ +Stuff that should be discussed here in detail: + +
    +
  • Authentication-phase handlers not invoked unless auth is + configured for the directory. +
  • Common auth configuration stored in the core per-dir + configuration; it has accessors ap_auth_type, + ap_auth_name, and ap_requires. +
  • Common routines, to handle the protocol end of things, at least + for HTTP basic authentication (ap_get_basic_auth_pw, + which sets the connection->user structure field + automatically, and ap_note_basic_auth_failure, which + arranges for the proper WWW-Authenticate: header + to be sent back). +
+ +

Special considerations for logging handlers

+ +When a request has internally redirected, there is the question of +what to log. Apache handles this by bundling the entire chain of +redirects into a list of request_rec structures which are +threaded through the r->prev and r->next +pointers. The request_rec which is passed to the logging +handlers in such cases is the one which was originally built for the +initial request from the client; note that the bytes_sent field will +only be correct in the last request in the chain (the one for which a +response was actually sent). + +

Resource allocation and resource pools

+

+One of the problems of writing and designing a server-pool server is +that of preventing leakage, that is, allocating resources (memory, +open files, etc.), without subsequently releasing them. The resource +pool machinery is designed to make it easy to prevent this from +happening, by allowing resource to be allocated in such a way that +they are automatically released when the server is done with +them. +

+

+The way this works is as follows: the memory which is allocated, file +opened, etc., to deal with a particular request are tied to a +resource pool which is allocated for the request. The pool +is a data structure which itself tracks the resources in question. +

+

+When the request has been processed, the pool is cleared. At +that point, all the memory associated with it is released for reuse, +all files associated with it are closed, and any other clean-up +functions which are associated with the pool are run. When this is +over, we can be confident that all the resource tied to the pool have +been released, and that none of them have leaked. +

+

+Server restarts, and allocation of memory and resources for per-server +configuration, are handled in a similar way. There is a +configuration pool, which keeps track of resources which were +allocated while reading the server configuration files, and handling +the commands therein (for instance, the memory that was allocated for +per-server module configuration, log files and other files that were +opened, and so forth). When the server restarts, and has to reread +the configuration files, the configuration pool is cleared, and so the +memory and file descriptors which were taken up by reading them the +last time are made available for reuse. +

+

+It should be noted that use of the pool machinery isn't generally +obligatory, except for situations like logging handlers, where you +really need to register cleanups to make sure that the log file gets +closed when the server restarts (this is most easily done by using the +function ap_pfopen, which also +arranges for the underlying file descriptor to be closed before any +child processes, such as for CGI scripts, are execed), or +in case you are using the timeout machinery (which isn't yet even +documented here). However, there are two benefits to using it: +resources allocated to a pool never leak (even if you allocate a +scratch string, and just forget about it); also, for memory +allocation, ap_palloc is generally faster than +malloc. +

+

+We begin here by describing how memory is allocated to pools, and then +discuss how other resources are tracked by the resource pool +machinery. +

+

Allocation of memory in pools

+

+Memory is allocated to pools by calling the function +ap_palloc, which takes two arguments, one being a pointer to +a resource pool structure, and the other being the amount of memory to +allocate (in chars). Within handlers for handling +requests, the most common way of getting a resource pool structure is +by looking at the pool slot of the relevant +request_rec; hence the repeated appearance of the +following idiom in module code: +

+
+int my_handler(request_rec *r)
+{
+    struct my_structure *foo;
+    ...
+
+    foo = (foo *)ap_palloc (r->pool, sizeof(my_structure));
+}
+
+

+Note that there is no ap_pfree --- +ap_palloced memory is freed only when the associated +resource pool is cleared. This means that ap_palloc does not +have to do as much accounting as malloc(); all it does in +the typical case is to round up the size, bump a pointer, and do a +range check. +

+

+(It also raises the possibility that heavy use of ap_palloc +could cause a server process to grow excessively large. There are +two ways to deal with this, which are dealt with below; briefly, you +can use malloc, and try to be sure that all of the memory +gets explicitly freed, or you can allocate a sub-pool of +the main pool, allocate your memory in the sub-pool, and clear it out +periodically. The latter technique is discussed in the section on +sub-pools below, and is used in the directory-indexing code, in order +to avoid excessive storage allocation when listing directories with +thousands of files). +

+

Allocating initialized memory

+

+There are functions which allocate initialized memory, and are +frequently useful. The function ap_pcalloc has the same +interface as ap_palloc, but clears out the memory it +allocates before it returns it. The function ap_pstrdup +takes a resource pool and a char * as arguments, and +allocates memory for a copy of the string the pointer points to, +returning a pointer to the copy. Finally ap_pstrcat is a +varargs-style function, which takes a pointer to a resource pool, and +at least two char * arguments, the last of which must be +NULL. It allocates enough memory to fit copies of each +of the strings, as a unit; for instance: +

+
+     ap_pstrcat (r->pool, "foo", "/", "bar", NULL);
+
+

+returns a pointer to 8 bytes worth of memory, initialized to +"foo/bar". +

+

Commonly-used pools in the Apache Web server

+

+A pool is really defined by its lifetime more than anything else. There +are some static pools in http_main which are passed to various +non-http_main functions as arguments at opportune times. Here they are: +

+
+
permanent_pool +
+
+
    +
  • never passed to anything else, this is the ancestor of all pools +
  • +
+
+
pconf +
+
+
    +
  • subpool of permanent_pool +
  • +
  • created at the beginning of a config "cycle"; exists until the + server is terminated or restarts; passed to all config-time + routines, either via cmd->pool, or as the "pool *p" argument on + those which don't take pools +
  • +
  • passed to the module init() functions +
  • +
+
+
ptemp +
+
+
    +
  • sorry I lie, this pool isn't called this currently in 1.3, I + renamed it this in my pthreads development. I'm referring to + the use of ptrans in the parent... contrast this with the later + definition of ptrans in the child. +
  • +
  • subpool of permanent_pool +
  • +
  • created at the beginning of a config "cycle"; exists until the + end of config parsing; passed to config-time routines via + cmd->temp_pool. Somewhat of a "bastard child" because it isn't + available everywhere. Used for temporary scratch space which + may be needed by some config routines but which is deleted at + the end of config. +
  • +
+
+
pchild +
+
+
    +
  • subpool of permanent_pool +
  • +
  • created when a child is spawned (or a thread is created); lives + until that child (thread) is destroyed +
  • +
  • passed to the module child_init functions +
  • +
  • destruction happens right after the child_exit functions are + called... (which may explain why I think child_exit is redundant + and unneeded) +
  • +
+
+
ptrans +
+
+
    +
  • should be a subpool of pchild, but currently is a subpool of + permanent_pool, see above +
  • +
  • cleared by the child before going into the accept() loop to receive + a connection +
  • +
  • used as connection->pool +
  • +
+
+
r->pool +
+
+
    +
  • for the main request this is a subpool of connection->pool; for + subrequests it is a subpool of the parent request's pool. +
  • +
  • exists until the end of the request (i.e., destroy_sub_req, or + in child_main after process_request has finished) +
  • +
  • note that r itself is allocated from r->pool; i.e., + r->pool is + first created and then r is the first thing palloc()d from it +
  • +
+
+
+

+For almost everything folks do, r->pool is the pool to use. But you +can see how other lifetimes, such as pchild, are useful to some +modules... such as modules that need to open a database connection once +per child, and wish to clean it up when the child dies. +

+

+You can also see how some bugs have manifested themself, such as setting +connection->user to a value from r->pool -- in this case +connection exists +for the lifetime of ptrans, which is longer than r->pool (especially if +r->pool is a subrequest!). So the correct thing to do is to allocate +from connection->pool. +

+

+And there was another interesting bug in mod_include/mod_cgi. You'll see +in those that they do this test to decide if they should use r->pool +or r->main->pool. In this case the resource that they are registering +for cleanup is a child process. If it were registered in r->pool, +then the code would wait() for the child when the subrequest finishes. +With mod_include this could be any old #include, and the delay can be up +to 3 seconds... and happened quite frequently. Instead the subprocess +is registered in r->main->pool which causes it to be cleaned up when +the entire request is done -- i.e., after the output has been sent to +the client and logging has happened. +

+

Tracking open files, etc.

+

+As indicated above, resource pools are also used to track other sorts +of resources besides memory. The most common are open files. The +routine which is typically used for this is ap_pfopen, which +takes a resource pool and two strings as arguments; the strings are +the same as the typical arguments to fopen, e.g., +

+
+     ...
+     FILE *f = ap_pfopen (r->pool, r->filename, "r");
+
+     if (f == NULL) { ... } else { ... }
+
+

+There is also a ap_popenf routine, which parallels the +lower-level open system call. Both of these routines +arrange for the file to be closed when the resource pool in question +is cleared. +

+

+Unlike the case for memory, there are functions to close +files allocated with ap_pfopen, and ap_popenf, +namely ap_pfclose and ap_pclosef. (This is +because, on many systems, the number of files which a single process +can have open is quite limited). It is important to use these +functions to close files allocated with ap_pfopen and +ap_popenf, since to do otherwise could cause fatal errors on +systems such as Linux, which react badly if the same +FILE* is closed more than once. +

+

+(Using the close functions is not mandatory, since the +file will eventually be closed regardless, but you should consider it +in cases where your module is opening, or could open, a lot of files). +

+

Other sorts of resources --- cleanup functions

+
+More text goes here. Describe the the cleanup primitives in terms of +which the file stuff is implemented; also, spawn_process. +
+

+Pool cleanups live until clear_pool() is called: clear_pool(a) recursively +calls destroy_pool() on all subpools of a; then calls all the cleanups for a; +then releases all the memory for a. destroy_pool(a) calls clear_pool(a) +and then releases the pool structure itself. i.e. clear_pool(a) doesn't +delete a, it just frees up all the resources and you can start using it +again immediately. +

+

Fine control --- creating and dealing with sub-pools, with a note +on sub-requests

+ +On rare occasions, too-free use of ap_palloc() and the +associated primitives may result in undesirably profligate resource +allocation. You can deal with such a case by creating a +sub-pool, allocating within the sub-pool rather than the main +pool, and clearing or destroying the sub-pool, which releases the +resources which were associated with it. (This really is a +rare situation; the only case in which it comes up in the standard +module set is in case of listing directories, and then only with +very large directories. Unnecessary use of the primitives +discussed here can hair up your code quite a bit, with very little +gain).

+ +The primitive for creating a sub-pool is ap_make_sub_pool, +which takes another pool (the parent pool) as an argument. When the +main pool is cleared, the sub-pool will be destroyed. The sub-pool +may also be cleared or destroyed at any time, by calling the functions +ap_clear_pool and ap_destroy_pool, respectively. +(The difference is that ap_clear_pool frees resources +associated with the pool, while ap_destroy_pool also +deallocates the pool itself. In the former case, you can allocate new +resources within the pool, and clear it again, and so forth; in the +latter case, it is simply gone).

+ +One final note --- sub-requests have their own resource pools, which +are sub-pools of the resource pool for the main request. The polite +way to reclaim the resources associated with a sub request which you +have allocated (using the ap_sub_req_lookup_... functions) +is ap_destroy_sub_req, which frees the resource pool. +Before calling this function, be sure to copy anything that you care +about which might be allocated in the sub-request's resource pool into +someplace a little less volatile (for instance, the filename in its +request_rec structure).

+ +(Again, under most circumstances, you shouldn't feel obliged to call +this function; only 2K of memory or so are allocated for a typical sub +request, and it will be freed anyway when the main request pool is +cleared. It is only when you are allocating many, many sub-requests +for a single main request that you should seriously consider the +ap_destroy... functions). + +

Configuration, commands and the like

+ +One of the design goals for this server was to maintain external +compatibility with the NCSA 1.3 server --- that is, to read the same +configuration files, to process all the directives therein correctly, +and in general to be a drop-in replacement for NCSA. On the other +hand, another design goal was to move as much of the server's +functionality into modules which have as little as possible to do with +the monolithic server core. The only way to reconcile these goals is +to move the handling of most commands from the central server into the +modules.

+ +However, just giving the modules command tables is not enough to +divorce them completely from the server core. The server has to +remember the commands in order to act on them later. That involves +maintaining data which is private to the modules, and which can be +either per-server, or per-directory. Most things are per-directory, +including in particular access control and authorization information, +but also information on how to determine file types from suffixes, +which can be modified by AddType and +DefaultType directives, and so forth. In general, the +governing philosophy is that anything which can be made +configurable by directory should be; per-server information is +generally used in the standard set of modules for information like +Aliases and Redirects which come into play +before the request is tied to a particular place in the underlying +file system.

+ +Another requirement for emulating the NCSA server is being able to +handle the per-directory configuration files, generally called +.htaccess files, though even in the NCSA server they can +contain directives which have nothing at all to do with access +control. Accordingly, after URI -> filename translation, but before +performing any other phase, the server walks down the directory +hierarchy of the underlying filesystem, following the translated +pathname, to read any .htaccess files which might be +present. The information which is read in then has to be +merged with the applicable information from the server's own +config files (either from the <Directory> sections +in access.conf, or from defaults in +srm.conf, which actually behaves for most purposes almost +exactly like <Directory />).

+ +Finally, after having served a request which involved reading +.htaccess files, we need to discard the storage allocated +for handling them. That is solved the same way it is solved wherever +else similar problems come up, by tying those structures to the +per-transaction resource pool.

+ +

Per-directory configuration structures

+ +Let's look out how all of this plays out in mod_mime.c, +which defines the file typing handler which emulates the NCSA server's +behavior of determining file types from suffixes. What we'll be +looking at, here, is the code which implements the +AddType and AddEncoding commands. These +commands can appear in .htaccess files, so they must be +handled in the module's private per-directory data, which in fact, +consists of two separate tables for MIME types and +encoding information, and is declared as follows: + +
+typedef struct {
+    table *forced_types;      /* Additional AddTyped stuff */
+    table *encoding_types;    /* Added with AddEncoding... */
+} mime_dir_config;
+
+ +When the server is reading a configuration file, or +<Directory> section, which includes one of the MIME +module's commands, it needs to create a mime_dir_config +structure, so those commands have something to act on. It does this +by invoking the function it finds in the module's `create per-dir +config slot', with two arguments: the name of the directory to which +this configuration information applies (or NULL for +srm.conf), and a pointer to a resource pool in which the +allocation should happen.

+ +(If we are reading a .htaccess file, that resource pool +is the per-request resource pool for the request; otherwise it is a +resource pool which is used for configuration data, and cleared on +restarts. Either way, it is important for the structure being created +to vanish when the pool is cleared, by registering a cleanup on the +pool if necessary).

+ +For the MIME module, the per-dir config creation function just +ap_pallocs the structure above, and a creates a couple of +tables to fill it. That looks like this: + +

+void *create_mime_dir_config (pool *p, char *dummy)
+{
+    mime_dir_config *new =
+      (mime_dir_config *) ap_palloc (p, sizeof(mime_dir_config));
+
+    new->forced_types = ap_make_table (p, 4);
+    new->encoding_types = ap_make_table (p, 4);
+
+    return new;
+}
+
+ +Now, suppose we've just read in a .htaccess file. We +already have the per-directory configuration structure for the next +directory up in the hierarchy. If the .htaccess file we +just read in didn't have any AddType or +AddEncoding commands, its per-directory config structure +for the MIME module is still valid, and we can just use it. +Otherwise, we need to merge the two structures somehow.

+ +To do that, the server invokes the module's per-directory config merge +function, if one is present. That function takes three arguments: +the two structures being merged, and a resource pool in which to +allocate the result. For the MIME module, all that needs to be done +is overlay the tables from the new per-directory config structure with +those from the parent: + +

+void *merge_mime_dir_configs (pool *p, void *parent_dirv, void *subdirv)
+{
+    mime_dir_config *parent_dir = (mime_dir_config *)parent_dirv;
+    mime_dir_config *subdir = (mime_dir_config *)subdirv;
+    mime_dir_config *new =
+      (mime_dir_config *)ap_palloc (p, sizeof(mime_dir_config));
+
+    new->forced_types = ap_overlay_tables (p, subdir->forced_types,
+                                        parent_dir->forced_types);
+    new->encoding_types = ap_overlay_tables (p, subdir->encoding_types,
+                                          parent_dir->encoding_types);
+
+    return new;
+}
+
+ +As a note --- if there is no per-directory merge function present, the +server will just use the subdirectory's configuration info, and ignore +the parent's. For some modules, that works just fine (e.g., for the +includes module, whose per-directory configuration information +consists solely of the state of the XBITHACK), and for +those modules, you can just not declare one, and leave the +corresponding structure slot in the module itself NULL.

+ +

Command handling

+ +Now that we have these structures, we need to be able to figure out +how to fill them. That involves processing the actual +AddType and AddEncoding commands. To find +commands, the server looks in the module's command table. +That table contains information on how many arguments the commands +take, and in what formats, where it is permitted, and so forth. That +information is sufficient to allow the server to invoke most +command-handling functions with pre-parsed arguments. Without further +ado, let's look at the AddType command handler, which +looks like this (the AddEncoding command looks basically +the same, and won't be shown here): + +
+char *add_type(cmd_parms *cmd, mime_dir_config *m, char *ct, char *ext)
+{
+    if (*ext == '.') ++ext;
+    ap_table_set (m->forced_types, ext, ct);
+    return NULL;
+}
+
+ +This command handler is unusually simple. As you can see, it takes +four arguments, two of which are pre-parsed arguments, the third being +the per-directory configuration structure for the module in question, +and the fourth being a pointer to a cmd_parms structure. +That structure contains a bunch of arguments which are frequently of +use to some, but not all, commands, including a resource pool (from +which memory can be allocated, and to which cleanups should be tied), +and the (virtual) server being configured, from which the module's +per-server configuration data can be obtained if required.

+ +Another way in which this particular command handler is unusually +simple is that there are no error conditions which it can encounter. +If there were, it could return an error message instead of +NULL; this causes an error to be printed out on the +server's stderr, followed by a quick exit, if it is in +the main config files; for a .htaccess file, the syntax +error is logged in the server error log (along with an indication of +where it came from), and the request is bounced with a server error +response (HTTP error status, code 500).

+ +The MIME module's command table has entries for these commands, which +look like this: + +

+command_rec mime_cmds[] = {
+{ "AddType", add_type, NULL, OR_FILEINFO, TAKE2,
+    "a mime type followed by a file extension" },
+{ "AddEncoding", add_encoding, NULL, OR_FILEINFO, TAKE2,
+    "an encoding (e.g., gzip), followed by a file extension" },
+{ NULL }
+};
+
+ +The entries in these tables are: + +
    +
  • The name of the command +
  • The function which handles it +
  • a (void *) pointer, which is passed in the + cmd_parms structure to the command handler --- + this is useful in case many similar commands are handled by the + same function. +
  • A bit mask indicating where the command may appear. There are + mask bits corresponding to each AllowOverride + option, and an additional mask bit, RSRC_CONF, + indicating that the command may appear in the server's own + config files, but not in any .htaccess + file. +
  • A flag indicating how many arguments the command handler wants + pre-parsed, and how they should be passed in. + TAKE2 indicates two pre-parsed arguments. Other + options are TAKE1, which indicates one pre-parsed + argument, FLAG, which indicates that the argument + should be On or Off, and is passed in + as a boolean flag, RAW_ARGS, which causes the + server to give the command the raw, unparsed arguments + (everything but the command name itself). There is also + ITERATE, which means that the handler looks the + same as TAKE1, but that if multiple arguments are + present, it should be called multiple times, and finally + ITERATE2, which indicates that the command handler + looks like a TAKE2, but if more arguments are + present, then it should be called multiple times, holding the + first argument constant. +
  • Finally, we have a string which describes the arguments that + should be present. If the arguments in the actual config file + are not as required, this string will be used to help give a + more specific error message. (You can safely leave this + NULL). +
+ +Finally, having set this all up, we have to use it. This is +ultimately done in the module's handlers, specifically for its +file-typing handler, which looks more or less like this; note that the +per-directory configuration structure is extracted from the +request_rec's per-directory configuration vector by using +the ap_get_module_config function. + +
+int find_ct(request_rec *r)
+{
+    int i;
+    char *fn = ap_pstrdup (r->pool, r->filename);
+    mime_dir_config *conf = (mime_dir_config *)
+             ap_get_module_config(r->per_dir_config, &mime_module);
+    char *type;
+
+    if (S_ISDIR(r->finfo.st_mode)) {
+        r->content_type = DIR_MAGIC_TYPE;
+        return OK;
+    }
+
+    if((i=ap_rind(fn,'.')) < 0) return DECLINED;
+    ++i;
+
+    if ((type = ap_table_get (conf->encoding_types, &fn[i])))
+    {
+        r->content_encoding = type;
+
+        /* go back to previous extension to try to use it as a type */
+
+        fn[i-1] = '\0';
+        if((i=ap_rind(fn,'.')) < 0) return OK;
+        ++i;
+    }
+
+    if ((type = ap_table_get (conf->forced_types, &fn[i])))
+    {
+        r->content_type = type;
+    }
+
+    return OK;
+}
+
+
+ +

Side notes --- per-server configuration, virtual + servers, etc.

+ +The basic ideas behind per-server module configuration are basically +the same as those for per-directory configuration; there is a creation +function and a merge function, the latter being invoked where a +virtual server has partially overridden the base server configuration, +and a combined structure must be computed. (As with per-directory +configuration, the default if no merge function is specified, and a +module is configured in some virtual server, is that the base +configuration is simply ignored).

+ +The only substantial difference is that when a command needs to +configure the per-server private module data, it needs to go to the +cmd_parms data to get at it. Here's an example, from the +alias module, which also indicates how a syntax error can be returned +(note that the per-directory configuration argument to the command +handler is declared as a dummy, since the module doesn't actually have +per-directory config data): + +

+char *add_redirect(cmd_parms *cmd, void *dummy, char *f, char *url)
+{
+    server_rec *s = cmd->server;
+    alias_server_conf *conf = (alias_server_conf *)
+            ap_get_module_config(s->module_config,&alias_module);
+    alias_entry *new = ap_push_array (conf->redirects);
+
+    if (!ap_is_url (url)) return "Redirect to non-URL";
+
+    new->fake = f; new->real = url;
+    return NULL;
+}
+
+ + diff --git a/APACHE_1_3b7/htdocs/manual/misc/FAQ.html b/APACHE_1_3b7/htdocs/manual/misc/FAQ.html new file mode 100644 index 0000000000..949c18844a --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/FAQ.html @@ -0,0 +1,2306 @@ + + + + Apache Server Frequently Asked Questions + + + + +

Apache Server Frequently Asked Questions

+

+ $Revision: 1.116 $ ($Date: 1998/05/20 14:22:39 $) +

+

+ The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

+ + + + + + + + + + + + + + + +

+ If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

+

The Questions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

The Answers

+

+ Background +

+
    +
  1. + What is Apache? + +

    + Apache was originally based on code and ideas found in the most + popular HTTP server of the time.. NCSA httpd 1.3 (early 1995). It has + since evolved into a far superior system which can rival (and probably + surpass) almost any other UNIX based HTTP server in terms of functionality, + efficiency and speed. +

    +

    + Since it began, it has been completely rewritten, and includes many new + features. Apache is, as of January 1997, the most popular WWW server on + the Internet, according to the + Netcraft Survey. +

    +
    +
  2. + +
  3. + Why was Apache created? + +

    + To address the concerns of a group of WWW providers and part-time httpd + programmers that httpd didn't behave as they wanted it to behave. + Apache is an entirely volunteer effort, completely funded by its + members, not by commercial sales. +

    +
    +
  4. + +
  5. + How does The Apache Group's work relate to other + server efforts, such as NCSA's? + +

    + We, of course, owe a great debt to NCSA and their programmers for + making the server Apache was based on. We now, however, have our own + server, and our project is mostly our own. The Apache Project is an + entirely independent venture. +

    +
    +
  6. + +
  7. + Why the name "Apache"? + +

    + A cute name which stuck. Apache is "A + PAtCHy server". It was + based on some existing code and a series of "patch files". +

    +
    +
  8. + +
  9. + OK, so how does Apache compare to other servers? + +

    + For an independent assessment, see + Web Compare's + comparison chart. +

    +

    + Apache has been shown to be substantially faster than many other + free servers. Although certain commercial servers have claimed to + surpass Apache's speed (it has not been demonstrated that any of these + "benchmarks" are a good way of measuring WWW server speed at any + rate), we feel that it is better to have a mostly-fast free server + than an extremely-fast server that costs thousands of dollars. Apache + is run on sites that get millions of hits per day, and they have + experienced no performance difficulties. +

    +
    +
  10. + +
  11. + How thoroughly tested is Apache? + +

    + Apache is run on over 500,000 Internet servers (as of July 1997). It has + been tested thoroughly by both developers and users. The Apache Group + maintains rigorous standards before releasing new versions of their + server, and our server runs without a hitch on over one third of all + WWW servers available on the Internet. When bugs do show up, we + release patches and new versions as soon as they are available. +

    +

    + The Apache project's web site includes a page with a partial list of + sites running + Apache. +

    +
    +
  12. + +
  13. + What are the future plans for Apache? + +

    +

      +
    • to continue as a public domain HTTP server, +
    • +
    • to keep up with advances in HTTP protocol and web developments in + general, +
    • +
    • to collect suggestions for fixes/improvements from its users, +
    • +
    • to respond to needs of large volume providers as well as + occasional users. +
    • +
    +

    +
    +
  14. + +
  15. + Whom do I contact for support? + +

    + There is no official support for Apache. None of the developers want to + be swamped by a flood of trivial questions that can be resolved elsewhere. + Bug reports and suggestions should be sent via + the bug report page. + Other questions should be directed to the + comp.infosystems.www.servers.unix or comp.infosystems.www.servers.ms-windows + newsgroup (as appropriate for the platform you use), where some of the + Apache team lurk, in the company of many other httpd gurus who + should be able to help. +

    +

    + Commercial support for Apache is, however, available from a number + of third parties. +

    +
    +
  16. + +
  17. + Is there any more information available on + Apache? + +

    + Indeed there is. See the main + Apache web site. + There is also a regular electronic publication called + Apache Week + available. Links to relevant Apache Week articles are + included below where appropriate. There are also some + Apache-specific books available. +

    +
    +
  18. + +
  19. + Where can I get Apache? + +

    + You can find out how to download the source for Apache at the + project's + main web page. +

    +
    +
  20. +
+

Technical Questions

+
    +
  1. + "Why can't I ...? Why won't ... work?" What to + do in case of problems + +

    + If you are having trouble with your Apache server software, you should + take the following steps: +

    +
      +
    1. Check the errorlog! +

      + Apache tries to be helpful when it encounters a problem. In many + cases, it will provide some details by writing one or messages to + the server error log. Sometimes this is enough for you to diagnose + & fix the problem yourself (such as file permissions or the like). + The default location of the error log is + /usr/local/apache/logs/error_log, but see the + ErrorLog + directive in your config files for the location on your server. +

      +
    2. +
    3. Check the + FAQ! +

      + The latest version of the Apache Frequently-Asked Questions list can + always be found at the main Apache web site. +

      +
    4. +
    5. Check the Apache bug database +

      + Most problems that get reported to The Apache Group are recorded in + the + bug database. + Please check the existing reports, open + and closed, before adding one. If you find + that your issue has already been reported, please don't add + a "me, too" report. If the original report isn't closed + yet, we suggest that you check it periodically. You might also + consider contacting the original submitter, because there may be an + email exchange going on about the issue that isn't getting recorded + in the database. +

      +
    6. +
    7. Ask in the comp.infosystems.www.servers.unix + USENET newsgroup +

      + A lot of common problems never make it to the bug database because + there's already high Q&A traffic about them in the + comp.infosystems.www.servers.unix + newsgroup. Many Apache users, and some of the developers, can be + found roaming its virtual halls, so it is suggested that you seek + wisdom there. The chances are good that you'll get a faster answer + there than from the bug database, even if you don't see + your question already posted. +

      +
    8. +
    9. If all else fails, report the problem in the bug + database +

      + If you've gone through those steps above that are appropriate and + have obtained no relief, then please do let The Apache + Group know about the problem by + logging a bug report. +

      +

      + If your problem involves the server crashing and generating a core + dump, please include a backtrace (if possible). As an example, +

      +

      +

      +
      # cd ServerRoot
      + # dbx httpd core
      + (dbx) where
      +
      +
      +

      +

      + (Substitute the appropriate locations for your + ServerRoot and your httpd and + core files. You may have to use gdb + instead of dbx.) +

      +
    10. +
    +
    +
  2. + +
  3. + How compatible is Apache with my existing NCSA 1.3 + setup? + +

    + Apache attempts to offer all the features and configuration options + of NCSA httpd 1.3, as well as many of the additional features found in + NCSA httpd 1.4 and NCSA httpd 1.5. +

    +

    + NCSA httpd appears to be moving toward adding experimental features + which are not generally required at the moment. Some of the experiments + will succeed while others will inevitably be dropped. The Apache + philosophy is to add what's needed as and when it is needed. +

    +

    + Friendly interaction between Apache and NCSA developers should ensure + that fundamental feature enhancements stay consistent between the two + servers for the foreseeable future. +

    +
    +
  4. + +
  5. + How do I enable CGI execution in directories other than + the ScriptAlias? + +

    + Apache recognizes all files in a directory named as a + ScriptAlias + as being eligible for execution rather than processing as normal + documents. This applies regardless of the file name, so scripts in a + ScriptAlias directory don't need to be named + "*.cgi" or "*.pl" or + whatever. In other words, all files in a ScriptAlias + directory are scripts, as far as Apache is concerned. +

    +

    + To persuade Apache to execute scripts in other locations, such as in + directories where normal documents may also live, you must tell it how + to recognize them - and also that it's okay to execute them. For + this, you need to use something like the + AddHandler + directive. +

    +

    +

      +
    1. In an appropriate section of your server configuration files, add + a line such as +

      +

      +
      AddHandler cgi-script .cgi +
      +
      +

      +

      + The server will then recognize that all files in that location (and + its logical descendants) that end in ".cgi" + are script files, not documents. +

      +
    2. +
    3. Make sure that the directory location is covered by an + Options + declaration that includes the ExecCGI option. +
    4. +
    +

    +

    + In some situations, you might not want to actually + allow all files named "*.cgi" to be executable. + Perhaps all you want is to enable a particular file in a normal directory to + be executable. This can be alternatively accomplished + via mod_rewrite + and the following steps: +

    +

    +

      +
    1. Locally add to the corresponding .htaccess file a ruleset + similar to this one: +

      +

      +
      RewriteEngine on +
      + RewriteBase /~foo/bar/ +
      + RewriteRule ^quux\.cgi$ - [T=application/x-httpd-cgi]
      +
      +
      +

      +
    2. +
    3. Make sure that the directory location is covered by an + Options + declaration that includes the ExecCGI and + FollowSymLinks option. +
    4. +
    +

    +
    +
  6. + +
  7. + What does it mean when my CGIs fail with + "Premature end of script headers"? + +

    + It means just what it says: the server was expecting a complete set of + HTTP headers (one or more followed by a blank line), and didn't get + them. +

    +

    + The most common cause of this problem is the script dying before + sending the complete set of headers, or possibly any at all, to the + server. To see if this is the case, try running the script standalone + from an interactive session, rather than as a script under the server. + If you get error messages, this is almost certainly the cause of the + "premature end of script headers" message. +

    +

    + The second most common cause of this (aside from people not + outputting the required headers at all) is a result of an interaction + with Perl's output buffering. To make Perl flush its buffers + after each output statement, insert the following statements around + the print or write statements that send your + HTTP headers: +

    +

    +

    +
    {
    +  local ($oldbar) = $|;
    +  $cfh = select (STDOUT);
    +  $| = 1;
    +  #
    +  # print your HTTP headers here
    +  #
    +  $| = $oldbar;
    +  select ($cfh);
    + }
    +
    +
    +

    +

    + This is generally only necessary when you are calling external + programs from your script that send output to stdout, or if there will + be a long delay between the time the headers are sent and the actual + content starts being emitted. To maximize performance, you should + turn buffer-flushing back off (with $| = 0 or the + equivalent) after the statements that send the headers, as displayed + above. +

    +

    + If your script isn't written in Perl, do the equivalent thing for + whatever language you are using (e.g., for C, call + fflush() after writing the headers). +

    +
    +
  8. + +
  9. + How do I enable SSI (parsed HTML)? + +

    + SSI (an acronym for Server-Side Include) directives allow static HTML + documents to be enhanced at run-time (e.g., when delivered to + a client by Apache). The format of SSI directives is covered + in the mod_include manual; + suffice it to say that Apache supports not only SSI but + xSSI (eXtended SSI) directives. +

    +

    + Processing a document at run-time is called parsing it; hence + the term "parsed HTML" sometimes used for documents that + contain SSI instructions. Parsing tends to be extremely + resource-consumptive, and is not enabled by default. It can also + interfere with the cachability of your documents, which can put a + further load on your server. (see the + next question for more information about this.) +

    +

    + To enable SSI processing, you need to +

    +
      +
    • Build your server with the + mod_include + module. This is normally compiled in by default. +
    • +
    • Make sure your server configuration files have an + Options + directive which permits Includes. +
    • +
    • Make sure that the directory where you want the SSI documents to + live is covered by the "server-parsed" content handler, + either explicitly or in some ancestral location. That can be done + with the following + AddHandler + directive: +

      +

      +
      AddHandler server-parsed .shtml +
      +
      +

      +

      + This indicates that all files ending in ".shtml" in that + location (or its descendants) should be parsed. Note that using + ".html" will cause all normal HTML files to be parsed, + which may put an inordinate load on your server. +

      +
    • +
    +

    + For additional information, see the Apache Week article on + Using Server Side Includes. +

    +
    +
  10. + +
  11. + Why don't my parsed files get cached? + +

    + Since the server is performing run-time processing of your SSI + directives, which may change the content shipped to the client, it + can't know at the time it starts parsing what the final size of the + result will be, or whether the parsed result will always be the same. + This means that it can't generate Content-Length or + Last-Modified headers. Caches commonly work by comparing + the Last-Modified of what's in the cache with that being + delivered by the server. Since the server isn't sending that header + for a parsed document, whatever's doing the caching can't tell whether + the document has changed or not - and so fetches it again to be on the + safe side. +

    +

    + You can work around this in some cases by causing an + Expires header to be generated. (See the + mod_expires + documentation for more details.) Another possibility is to use the + XBitHack Full + mechanism, which tells Apache to send (under certain circumstances + detailed in the XBitHack directive description) a + Last-Modified header based upon the last modification + time of the file being parsed. Note that this may actually be lying + to the client if the parsed file doesn't change but the SSI-inserted + content does; if the included content changes often, this can result + in stale copies being cached. +

    +
    +
  12. + +
  13. + How can I have my script output parsed? + +

    + So you want to include SSI directives in the output from your CGI + script, but can't figure out how to do it? + The short answer is "you can't." This is potentially + a security liability and, more importantly, it can not be cleanly + implemented under the current server API. The best workaround + is for your script itself to do what the SSIs would be doing. + After all, it's generating the rest of the content. +

    +

    + This is a feature The Apache Group hopes to add in the next major + release after 1.3. +

    +
    +
  14. + +
  15. + Does or will Apache act as a Proxy server? + +

    + Apache version 1.1 and above comes with a + proxy module. + If compiled in, this will make Apache act as a caching-proxy server. +

    +
    +
  16. + +
  17. + What are "multiviews"? + +

    + "Multiviews" is the general name given to the Apache + server's ability to provide language-specific document variants in + response to a request. This is documented quite thoroughly in the + content negotiation + description page. In addition, Apache Week carried an + article on this subject entitled + "Content Negotiation Explained". +

    +
    +
  18. + +
  19. + Why can't I run more than <n> + virtual hosts? + +

    + You are probably running into resource limitations in your + operating system. The most common limitation is the + per-process limit on file descriptors, + which is almost always the cause of problems seen when adding + virtual hosts. Apache often does not give an intuitive error + message because it is normally some library routine (such as + gethostbyname()) which needs file descriptors and + doesn't complain intelligibly when it can't get them. +

    +

    + Each log file requires a file descriptor, which means that if you are + using separate access and error logs for each virtual host, each + virtual host needs two file descriptors. Each + Listen + directive also needs a file descriptor. +

    +

    + Typical values for <n> that we've seen are in + the neighborhood of 128 or 250. When the server bumps into the file + descriptor limit, it may dump core with a SIGSEGV, it might just + hang, or it may limp along and you'll see (possibly meaningful) errors + in the error log. One common problem that occurs when you run into + a file descriptor limit is that CGI scripts stop being executed + properly. +

    +

    + As to what you can do about this: +

    +
      +
    1. Reduce the number of + Listen + directives. If there are no other servers running on the machine + on the same port then you normally don't + need any Listen directives at all. By default Apache listens to + all addresses on port 80. +
    2. +
    3. Reduce the number of log files. You can use + mod_log_config + to log all requests to a single log file while including the name + of the virtual host in the log file. You can then write a + script to split the logfile into separate files later if + necessary. Such a script is provided with the Apache 1.3 distribution + in the src/support/split-logfile file. +
    4. +
    5. Increase the number of file descriptors available to the server + (see your system's documentation on the limit or + ulimit commands). For some systems, information on + how to do this is available in the + performance hints page. There is a specific + note for FreeBSD below. +
    6. +
    7. "Don't do that" - try to run with fewer virtual hosts +
    8. +
    9. Spread your operation across multiple server processes (using + Listen + for example, but see the first point) and/or ports. +
    10. +
    +

    + Since this is an operating-system limitation, there's not much else + available in the way of solutions. +

    +

    + As of 1.2.1 we have made attempts to work around various limitations + involving running with many descriptors. + More information is available. +

    +
    +
  20. + +
  21. + Can I increase FD_SETSIZE on FreeBSD? + +

    + On versions of FreeBSD before 3.0, the FD_SETSIZE define + defaults to 256. This means that you will have trouble usefully using + more than 256 file descriptors in Apache. This can be increased, but + doing so can be tricky. +

    +

    + If you are using a version prior to 2.2, you need to recompile your + kernel with a larger FD_SETSIZE. This can be done by adding a + line such as: +

    +
    +
    options FD_SETSIZE nnn +
    +
    +

    + to your kernel config file. Starting at version 2.2, this is no + longer necessary. +

    +

    + If you are using a version of 2.1-stable from after 1997/03/10 or + 2.2 or 3.0-current from before 1997/06/28, there is a limit in + the resolver library that prevents it from using more file descriptors + than what FD_SETSIZE is set to when libc is compiled. To + increase this, you have to recompile libc with a higher + FD_SETSIZE. +

    +

    + In FreeBSD 3.0, the default FD_SETSIZE has been increased to + 1024 and the above limitation in the resolver library + has been removed. +

    +

    + After you deal with the appropriate changes above, you can increase + the setting of FD_SETSIZE at Apache compilation time + by adding "-DFD_SETSIZE=nnn" to the + EXTRA_CFLAGS line in your Configuration + file. +

    +
    +
  22. + +
  23. + Why do I keep getting "Method Not Allowed" for + form POST requests? + +

    + This is almost always due to Apache not being configured to treat the + file you are trying to POST to as a CGI script. You can not POST + to a normal HTML file; the operation has no meaning. See the FAQ + entry on CGIs outside ScriptAliased + directories for details on how to configure Apache to treat the + file in question as a CGI. +

    +
    +
  24. + +
  25. + Can I use my /etc/passwd file + for Web page authentication? + +

    + Yes, you can - but it's a very bad idea. Here are + some of the reasons: +

    +
      +
    • The Web technology provides no governors on how often or how + rapidly password (authentication failure) retries can be made. That + means that someone can hammer away at your system's + root password using the Web, using a dictionary or + similar mass attack, just as fast as the wire and your server can + handle the requests. Most operating systems these days include + attack detection (such as n failed passwords for the same + account within m seconds) and evasion (breaking the + connection, disabling the account under attack, disabling + all logins from that source, et cetera), but the + Web does not. +
    • +
    • An account under attack isn't notified (unless the server is + heavily modified); there's no "You have 19483 login + failures" message when the legitimate owner logs in. +
    • +
    • Without an exhaustive and error-prone examination of the server + logs, you can't tell whether an account has been compromised. + Detecting that an attack has occurred, or is in progress, is fairly + obvious, though - if you look at the logs. +
    • +
    • Web authentication passwords (at least for Basic authentication) + generally fly across the wire, and through intermediate proxy + systems, in what amounts to plain text. "O'er the net we + go/Caching all the way;/O what fun it is to surf/Giving my password + away!" +
    • +
    • Since HTTP is stateless, information about the authentication is + transmitted each and every time a request is made to the + server. Essentially, the client caches it after the first + successful access, and transmits it without asking for all + subsequent requests to the same server. +
    • +
    • It's relatively trivial for someone on your system to put up a + page that will steal the cached password from a client's cache + without them knowing. Can you say "password grabber"? +
    • +
    +

    + If you still want to do this in light of the above disadvantages, the + method is left as an exercise for the reader. It'll void your Apache + warranty, though, and you'll lose all accumulated UNIX guru points. +

    +
    +
  26. + +
  27. + Why doesn't my ErrorDocument 401 work? + +

    + You need to use it with a URL in the form + "/foo/bar" and not one with a method and + hostname such as "http://host/foo/bar". See the + ErrorDocument + documentation for details. This was incorrectly documented in the past. +

    +
    +
  28. + +
  29. + How can I use ErrorDocument + and SSI to simplify customized error messages? + +

    + Have a look at this document. + It shows in example form how you can a combination of XSSI and + negotiation to tailor a set of ErrorDocuments to your + personal taste, and returning different internationalized error + responses based on the client's native language. +

    +
    +
  30. + +
  31. + Why do I get "setgid: Invalid + argument" at startup? + +

    + Your + Group + directive (probably in conf/httpd.conf) needs to name a + group that actually exists in the /etc/group file (or + your system's equivalent). +

    +
    +
  32. + +
  33. + Why does Apache send a cookie on every response? + +

    + Apache does not send automatically send a cookie on every + response, unless you have re-compiled it with the + mod_cookies + module. + This module was distributed with Apache prior to 1.2. + This module may help track users, and uses cookies to do this. If + you are not using the data generated by mod_cookies, do + not compile it into Apache. Note that in 1.2 this module was renamed + to the more correct name + mod_usertrack, + and cookies + have to be specifically enabled with the + CookieTracking + directive. +

    +
    +
  34. + +
  35. + Why don't my cookies work, I even compiled in + mod_cookies? + + +

    + Firstly, you do not need to compile in + mod_cookies in order for your scripts to work (see the + previous question + for more about mod_cookies). Apache passes on your + Set-Cookie header fine, with or without this module. If + cookies do not work it will be because your script does not work + properly or your browser does not use cookies or is not set-up to + accept them. +

    +
    +
  36. + +
  37. + Why do my Java app[let]s give me plain text when I request + an URL from an Apache server? + +

    + As of version 1.2, Apache is an HTTP/1.1 (HyperText Transfer Protocol + version 1.1) server. This fact is reflected in the protocol version + that's included in the response headers sent to a client when + processing a request. Unfortunately, low-level Web access classes + included in the Java Development Kit (JDK) version 1.0.2 expect to see + the version string "HTTP/1.0" and do not correctly interpret + the "HTTP/1.1" value Apache is sending (this part of the + response is a declaration of what the server can do rather than a + declaration of the dialect of the response). The result + is that the JDK methods do not correctly parse the headers, and + include them with the document content by mistake. +

    +

    + This is definitely a bug in the JDK 1.0.2 foundation classes from Sun, + and it has been fixed in version 1.1. However, the classes in + question are part of the virtual machine environment, which means + they're part of the Web browser (if Java-enabled) or the Java + environment on the client system - so even if you develop + your classes with a recent JDK, the eventual users might + encounter the problem. + The classes involved are replaceable by vendors implementing the + Java virtual machine environment, and so even those that are based + upon the 1.0.2 version may not have this problem. +

    +

    + In the meantime, a workaround is to tell + Apache to "fake" an HTTP/1.0 response to requests that come + from the JDK methods; this can be done by including a line such as the + following in your server configuration files: +

    +

    +

    +
    BrowserMatch Java1.0 force-response-1.0 +
    + BrowserMatch JDK/1.0 force-response-1.0
    +
    +
    +

    +

    + More information about this issue can be found in the + Java and HTTP/1.1 + page at the Apache web site. +

    +
    +
  38. + +
  39. + Why can't I publish to my Apache server using PUT on + Netscape Gold and other programs? + +

    + Because you need to install and configure a script to handle + the uploaded files. This script is often called a "PUT" handler. + There are several available, but they may have security problems. + Using FTP uploads may be easier and more secure, at least for now. + For more information, see the Apache Week article + Publishing Pages with PUT. +

    +
    +
  40. + +
  41. + Why isn't FastCGI included with Apache any more? + +

    + The simple answer is that it was becoming too difficult to keep the + version being included with Apache synchronized with the master copy + at the + FastCGI web site. When a new version of Apache was released, the + version of the FastCGI module included with it would soon be out of date. +

    +

    + You can still obtain the FastCGI module for Apache from the master + FastCGI web site. +

    +
    +
  42. + +
  43. + Why am I getting "httpd: could not set socket + option TCP_NODELAY" in my error log? + +

    + This message almost always indicates that the client disconnected + before Apache reached the point of calling setsockopt() + for the connection. It shouldn't occur for more than about 1% of the + requests your server handles, and it's advisory only in any case. +

    +
    +
  44. + +
  45. + Why am I getting "connection reset by + peer" in my error log? + +

    + This is a normal message and nothing about which to be alarmed. It simply + means that the client canceled the connection before it had been + completely set up - such as by the end-user pressing the "Stop" + button. People's patience being what it is, sites with response-time + problems or slow network links may experiences this more than + high-capacity ones or those with large pipes to the network. +

    +
    +
  46. + +
  47. + How can I get my script's output without Apache buffering + it? Why doesn't my server push work? + +

    + In order to improve network performance, Apache buffers script output + into relatively large chunks. If you have a script that sends + information in bursts (eg. as partial-done messages in a multi-commit + database transaction or any type of server push), the client will + not necessarily get the output as the script is generating it. +

    +

    + To avoid this, Apache recognizes scripts whose names begin with + "nph-" as non-parsed-header scripts. + That is, Apache won't buffer their output, but connect it directly to + the socket going back to the client. +

    +

    + While this will probably do what you want, there are some + disadvantages to it: +

    +
      +
    • YOU (the script) are responsible for generating + ALL of the HTTP headers, and no longer + just the "Content-type" or + "Location" headers +
    • +
    • Unless your script generates its output carefully, you will see a + performance penalty as excessive numbers of packets go back and forth +
    • +
    +

    + As an example how you might handle the former (in a Perl script): +

    +

    +

    +
    if ($0 =~ m:^(.*/)*nph-[^/]*$:) { +
    +      + $HTTP_headers =  + "HTTP/1.1 200 OK\015\012"; +
    +      + $HTTP_headers .=  + "Connection: close\015\012"; +
    +      + print $HTTP_headers; +
    + }
    +
    +
    +

    +

    + and then follow with your normal non-nph headers. +

    +

    Note that in version 1.3, all CGI scripts will be unbuffered + so the only difference between nph scripts and normal scripts is + that nph scripts require the full HTTP headers to be sent. +

    +
    +
  48. + +
  49. + Why do I get complaints about redefinition + of "struct iovec" when + compiling under Linux? + +

    + This is a conflict between your C library includes and your kernel + includes. You need to make sure that the versions of both are matched + properly. There are two workarounds, either one will solve the problem: +

    +

    +

      +
    • Remove the definition of struct iovec from your C + library includes. It is located in /usr/include/sys/uio.h. + Or, +
    • +
    • Add -DNO_WRITEV to the EXTRA_CFLAGS + line in your Configuration and reconfigure/rebuild. + This hurts performance and should only be used as a last resort. +
    • +
    +

    +
    +
  50. + +
  51. + The errorlog says Apache dumped core, but where's the dump + file? + +

    + In Apache version 1.2, the error log message + about dumped core includes the directory where the dump file should be + located. However, many Unixes do not allow a process that has + called setuid() to dump core for security reasons; + the typical Apache setup has the server started as root to bind to + port 80, after which it changes UIDs to a non-privileged user to + serve requests. +

    +

    + Dealing with this is extremely operating system-specific, and may + require rebuilding your system kernel. Consult your operating system + documentation or vendor for more information about whether your system + does this and how to bypass it. If there is a documented way + of bypassing it, it is recommended that you bypass it only for the + httpd server process if possible. +

    +

    + The canonical location for Apache's core-dump files is the + ServerRoot + directory. As of Apache version 1.3, the location can be set via + the + CoreDumpDirectory + directive to a different directory. Make sure that this directory is + writable by the user the server runs as (as opposed to the user the server + is started as). +

    +
    +
  52. + +
  53. + Why isn't restricting access by host or domain name + working correctly? + +

    + Two of the most common causes of this are: +

    +
      +
    1. An error, inconsistency, or unexpected mapping in the DNS + registration +
      + This happens frequently: your configuration restricts access to + Host.FooBar.Com, but you can't get in from that host. + The usual reason for this is that Host.FooBar.Com is + actually an alias for another name, and when Apache performs the + address-to-name lookup it's getting the real name, not + Host.FooBar.Com. You can verify this by checking the + reverse lookup yourself. The easiest way to work around it is to + specify the correct host name in your configuration. +
    2. +
    3. Inadequate checking and verification in your + configuration of Apache +
      + If you intend to perform access checking and restriction based upon + the client's host or domain name, you really need to configure + Apache to double-check the origin information it's supplied. You do + this by adding the -DMAXIMUM_DNS clause to the + EXTRA_CFLAGS definition in your + Configuration file. For example: +

      +

      +
      EXTRA_CFLAGS=-DMAXIMUM_DNS +
      +
      +

      +

      + This will cause Apache to be very paranoid about making sure a + particular host address is really assigned to the name it + claims to be. Note that this can incur a significant + performance penalty, however, because of all the name resolution + requests being sent to a nameserver. +

      +
    4. +
    +
    +
  54. + +
  55. + Why doesn't Apache include SSL? + +

    + SSL (Secure Socket Layer) data transport requires encryption, and many + governments have restrictions upon the import, export, and use of + encryption technology. If Apache included SSL in the base package, + its distribution would involve all sorts of legal and bureaucratic + issues, and it would no longer be freely available. Also, some of + the technology required to talk to current clients using SSL is + patented by RSA Data Security, + who restricts its use without a license. +

    +

    + Some SSL implementations of Apache are available, however; see the + "related projects" + page at the main Apache web site. +

    +

    + You can find out more about this topic in the Apache Week + article about + Apache and Secure Transactions. +

    +
    +
  56. + +
  57. + Why do I get core dumps under HPUX using HP's ANSI + C compiler? + +

    + We have had numerous reports of Apache dumping core when compiled + with HP's ANSI C compiler using optimization. Disabling the compiler + optimization has fixed these problems. +

    +
    +
  58. + +
  59. + How do I get Apache to send a MIDI file so the browser can + play it? + +

    + Even though the registered MIME type for MIDI files is + audio/midi, some browsers are not set up to recognize it + as such; instead, they look for audio/x-midi. There are + two things you can do to address this: +

    +
      +
    1. Configure your browser to treat documents of type + audio/midi correctly. This is the type that Apache + sends by default. This may not be workable, however, if you have + many client installations to change, or if some or many of the + clients are not under your control. +
    2. +
    3. Instruct Apache to send a different Content-type + header for these files by adding the following line to your server's + configuration files: +

      +

      +
      AddType audio/x-midi .mid .midi .kar +
      +
      +

      +

      + Note that this may break browsers that do recognize the + audio/midi MIME type unless they're prepared to also + handle audio/x-midi the same way. +

      +
    4. +
    +
    +
  60. + +
  61. + Why won't Apache compile with my system's + cc? + +

    + If the server won't compile on your system, it is probably due to one + of the following causes: +

    +
      +
    • The Configure script doesn't recognize your system + environment. +
      + This might be either because it's completely unknown or because + the specific environment (include files, OS version, et + cetera) isn't explicitly handled. If this happens, you may + need to port the server to your OS yourself. +
    • +
    • Your system's C compiler is garbage. +
      + Some operating systems include a default C compiler that is either + not ANSI C-compliant or suffers from other deficiencies. The usual + recommendation in cases like this is to acquire, install, and use + gcc. +
    • +
    • Your include files may be confused. +
      + In some cases, we have found that a compiler installation or system + upgrade has left the C header files in an inconsistent state. Make + sure that your include directory tree is in sync with the compiler and + the operating system. +
    • +
    • Your operating system or compiler may be out of + revision. +
      + Software vendors (including those that develop operating systems) + issue new releases for a reason; sometimes to add functionality, but + more often to fix bugs that have been discovered. Try upgrading + your compiler and/or your operating system. +
    • +
    +

    + The Apache Group tests the ability to build the server on many + different platforms. Unfortunately, we can't test all of the OS + platforms there are. If you have verified that none of the above + issues is the cause of your problem, and it hasn't been reported + before, please submit a + problem report. + Be sure to include complete details, such as the compiler + & OS versions and exact error messages. +

    +
    +
  62. + +
  63. + How do I add browsers and referrers to my logs? + +

    + Apache provides a couple of different ways of doing this. The + recommended method is to compile the + mod_log_config + module into your configuration and use the + CustomLog + directive. +

    +

    + You can either log the additional information in files other than your + normal transfer log, or you can add them to the records already being + written. For example: +

    +

    + + CustomLog logs/access_log "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\"" + +

    +

    + This will add the values of the User-agent: and + Referer: headers, which indicate the client and the + referring page, respectively, to the end of each line in the access + log. +

    +

    + You may want to check out the Apache Week article + entitled: + "Gathering Visitor Information: Customising Your + Logfiles". +

    +
    +
  64. + +
  65. + Why do I get an error about an undefined reference to + "__inet_ntoa" or other + __inet_* symbols? + +

    + If you have installed BIND-8 + then this is normally due to a conflict between your include files + and your libraries. BIND-8 installs its include files and libraries + /usr/local/include/ and /usr/local/lib/, while + the resolver that comes with your system is probably installed in + /usr/include/ and /usr/lib/. If + your system uses the header files in /usr/local/include/ + before those in /usr/include/ but you do not use the new + resolver library, then the two versions will conflict. +

    +

    + To resolve this, you can either make sure you use the include files + and libraries that came with your system or make sure to use the + new include files and libraries. Adding -lbind to the + EXTRA_LDFLAGS line in your Configuration + file, then re-running Configure, should resolve the + problem. (Apache versions 1.2.* and earlier use + EXTRA_LFLAGS instead.) +

    +

    + Note:As of BIND 8.1.1, the bind libraries and files are + installed under /usr/local/bind by default, so you + should not run into this problem. Should you want to use the bind + resolvers you'll have to add the following to the respective lines: +

    +

    +

    +
    EXTRA_CFLAGS=-I/usr/local/bind/include +
    + EXTRA_LDFLAGS=-L/usr/local/bind/lib +
    + EXTRA_LIBS=-lbind
    +
    +
    +

    +
    +
  66. + +
  67. + Why does accessing directories only work when I include + the trailing "/" + (e.g.http://foo.domain.com/~user/) + but not when I omit it + (e.g.http://foo.domain.com/~user)? + +

    + When you access a directory without a trailing "/", Apache needs + to send what is called a redirect to the client to tell it to + add the trailing slash. If it did not do so, relative URLs would + not work properly. When it sends the redirect, it needs to know + the name of the server so that it can include it in the redirect. + There are two ways for Apache to find this out; either it can guess, + or you can tell it. If your DNS is configured correctly, it can + normally guess without any problems. If it is not, however, then + you need to tell it. +

    +

    + Add a ServerName directive + to the config file to tell it what the domain name of the server is. +

    +
    +
  68. + +
  69. + How do I set up Apache to require a username and + password to access certain documents? + +

    + There are several ways to do this; some of the more popular + ones are to use the mod_auth, + mod_auth_db, or + mod_auth_dbm modules. +

    +

    + For an explanation on how to implement these restrictions, see + Apache Week's + articles on + Using User Authentication + or + DBM User Authentication. +

    +
    +
  70. + +
  71. + Why is the environment variable + REMOTE_USER not set? + +

    + This variable is set and thus available in SSI or CGI scripts if and + only if the requested document was protected by access + authentication. For an explanation on how to implement these restrictions, + see + Apache Week's + articles on + Using User Authentication + or + DBM User Authentication. +

    +

    + Hint: When using a CGI script to receive the data of a HTML FORM + notice that protecting the document containing the FORM is not + sufficient to provide REMOTE_USER to the CGI script. You have + to protect the CGI script, too. Or alternatively only the CGI script (then + authentication happens only after filling out the form). +

    +
    +
  72. + +
  73. + How do I set up Apache to allow access to certain + documents only if a site is either a local site or + the user supplies a password and username? + +

    + Use the Satisfy directive, + in particular the Satisfy Any directive, to require + that only one of the access restrictions be met. For example, + adding the following configuration to a .htaccess + or server configuration file would restrict access to people who + either are accessing the site from a host under domain.com or + who can supply a valid username and password: +

    +

    +

    +
    deny from all +
    + allow from .domain.com +
    + AuthType Basic +
    + AuthUserFile /usr/local/apache/conf/htpasswd.users +
    + AuthName special directory +
    + require valid-user +
    + satisfy any
    +
    +
    +

    +

    + See the user authentication + question and the mod_access + module for details on how the above directives work. +

    +
    +
  74. + +
  75. + Why doesn't mod_info list any directives? + +

    + The mod_info + module allows you to use a Web browser to see how your server is + configured. Among the information it displays is the list modules and + their configuration directives. The "current" values for + the directives are not necessarily those of the running server; they + are extracted from the configuration files themselves at the time of + the request. If the files have been changed since the server was last + reloaded, the display will will not match the values actively in use. + If the files and the path to the files are not readable by the user as + which the server is running (see the + User + directive), then mod_info cannot read them in order to + list their values. An entry will be made in the error log in + this event, however. +

    +
    +
  76. + +
  77. + When I run it under Linux I get "shmget: + function not found", what should I do? + +

    + Your kernel has been built without SysV IPC support. You will have to + rebuild the kernel with that support enabled (it's under the + "General Setup" submenu). Documentation for + kernel building is beyond the scope of this FAQ; you should consult + the + Kernel HOWTO, + or the documentation provided with your distribution, or a + Linux newsgroup/mailing list. + As a last-resort workaround, you can + comment out the #define USE_SHMGET_SCOREBOARD + definition in the + LINUX section of + src/conf.h and rebuild the server (prior to 1.3b4, simply + removing #define HAVE_SHMGET would have sufficed). + This will produce a server which is slower and less reliable. +

    +
    +
  78. + +
  79. + Why does my authentication give me a server error? + +

    + Under normal circumstances, the Apache access control modules will + pass unrecognized user IDs on to the next access control module in + line. Only if the user ID is recognized and the password is validated + (or not) will it give the usual success or "authentication + failed" messages. +

    +

    + However, if the last access module in line 'declines' the validation + request (because it has never heard of the user ID or because it is not + configured), the http_request handler will give one of + the following, confusing, errors: +

    +
      +
    • check access +
    • +
    • check user. No user file? +
    • +
    • check access. No groups file? +
    • +
    +

    + This does not mean that you have to add an + 'AuthUserFile /dev/null' line as some magazines suggest! +

    +

    + The solution is to ensure that at least the last module is authoritative + and CONFIGURED. By default, mod_auth is + authoritative and will give an OK/Denied, but only if it is configured + with the proper AuthUserFile. Likewise, if a valid group + is required. (Remember that the modules are processed in the reverse + order from that in which they appear in your compile-time + Configuration file.) +

    +

    + A typical situation for this error is when you are using the + mod_auth_dbm, mod_auth_msql, + mod_auth_mysql, mod_auth_anon or + mod_auth_cookie modules on their own. These are by + default not authoritative, and this will pass the + buck on to the (non-existent) next authentication module when the + user ID is not in their respective database. Just add the appropriate + 'XXXAuthoritative yes' line to the configuration. +

    +

    + In general it is a good idea (though not terribly efficient) to have the + file-based mod_auth a module of last resort. This allows + you to access the web server with a few special passwords even if the + databases are down or corrupted. This does cost a + file open/seek/close for each request in a protected area. +

    +
    +
  80. + +
  81. + Do I have to keep the (mSQL) authentication information + on the same machine? + +

    + Some organizations feel very strongly about keeping the authentication + information on a different machine than the webserver. With the + mod_auth_msql, mod_auth_mysql, and other SQL + modules connecting to (R)DBMses this is quite possible. Just configure + an explicit host to contact. +

    +

    + Be aware that with mSQL and Oracle, opening and closing these database + connections is very expensive and time consuming. You might want to + look at the code in the auth_* modules and play with the + compile time flags to alleviate this somewhat, if your RDBMS licences + allow for it. +

    +
    +
  82. + +
  83. + Why is my mSQL authentication terribly slow? + +

    + You have probably configured the Host by specifying a FQHN, + and thus the libmsql will use a full blown TCP/IP socket + to talk to the database, rather than a fast internal device. The + libmsql, the mSQL FAQ, and the mod_auth_msql + documentation warn you about this. If you have to use different + hosts, check out the mod_auth_msql code for + some compile time flags which might - or might not - suit you. +

    +
    +
  84. + +
  85. + Where can I find mod_rewrite rulesets which already solve + particular URL-related problems? + +

    + There is a collection of + Practical Solutions for URL-Manipulation + where you can + find all typical solutions the author of + mod_rewrite + currently knows of. If you have more + interesting rulesets which solve particular problems not currently covered in + this document, send it to + Ralf S. Engelschall + for inclusion. The + other webmasters will thank you for avoiding the reinvention of the wheel. +

    +
    +
  86. + +
  87. + Where can I find any published information about + URL-manipulations and mod_rewrite? + +

    + There is an article from + Ralf S. Engelschall + about URL-manipulations based on + mod_rewrite + in the "iX Multiuser Multitasking Magazin" issue #12/96. The + german (original) version + can be read online at + <http://www.heise.de/ix/artikel/9612149/>, + the English (translated) version can be found at + <http://www.heise.de/ix/artikel/E/9612149/>. +

    +
    +
  88. + +
  89. + Why is mod_rewrite so difficult to learn and seems so + complicated? + +

    + Hmmm... there are a lot of reasons. First, mod_rewrite itself is a powerful + module which can help you in really all aspects of URL + rewriting, so it can be no trivial module per definition. To accomplish + its hard job it uses software leverage and makes use of a powerful regular + expression + library by Henry Spencer which is an integral part of Apache since its + version 1.2. And regular expressions itself can be difficult to newbies, + while providing the most flexible power to the advanced hacker. +

    +

    + On the other hand mod_rewrite has to work inside the Apache API environment + and needs to do some tricks to fit there. For instance the Apache API as of + 1.x really was not designed for URL rewriting at the .htaccess + level of processing. Or the problem of multiple rewrites in sequence, which + is also not handled by the API per design. To provide this features + mod_rewrite has to do some special (but API compliant!) handling which leads + to difficult processing inside the Apache kernel. While the user usually + doesn't see anything of this processing, it can be difficult to find + problems when some of your RewriteRules seem not to work. +

    +
    +
  90. + +
  91. + What can I do if my RewriteRules don't work as expected? + + +

    + Use "RewriteLog somefile" and + "RewriteLogLevel 9" and have a precise look at the + steps the rewriting engine performs. This is really the only one and best + way to debug your rewriting configuration. +

    +
    +
  92. + +
  93. Why don't some of my URLs + get prefixed with DocumentRoot when using mod_rewrite? + +

    + If the rule starts with /somedir/... make sure that really no + /somedir exists on the filesystem if you don't want to lead the + URL to match this directory, i.e. there must be no root directory named + somedir on the filesystem. Because if there is such a + directory, the URL will not get prefixed with DocumentRoot. This behaviour + looks ugly, but is really important for some other aspects of URL + rewriting. +

    +
    +
  94. + +
  95. + How can I make all my URLs case-insensitive with mod_rewrite? + + +

    + You can't! The reason is: First, case translations for arbitrary length URLs + cannot be done via regex patterns and corresponding substitutions. + One need + a per-character pattern like sed/Perl tr|..|..| feature. + Second, just + making URLs always upper or lower case will not resolve the complete problem + of case-INSENSITIVE URLs, because actually the URLs had to be rewritten to + the correct case-variant residing on the filesystem because in later + processing Apache needs to access the file. And Unix filesystem is always + case-SENSITIVE. +

    +

    + But there is a module named mod_speling.c (yes, it is named + this way!) out there on the net. Try this one. +

    +
    +
  96. + +
  97. + Why are RewriteRules in my VirtualHost parts ignored? + +

    + Because you have to enable the engine for every virtual host explicitly due + to security concerns. Just add a "RewriteEngine on" to your + virtual host configuration parts. +

    +
    +
  98. + +
  99. + How can I use strings with whitespaces in RewriteRule's ENV + flag? + +

    + There is only one ugly solution: You have to surround the complete flag + argument by quotation marks ("[E=...]"). Notice: The argument + to quote here is not the argument to the E-flag, it is the argument of the + Apache config file parser, i.e. the third argument of the RewriteRule here. + So you have to write "[E=any text with whitespaces]". +

    +
    +
  100. + +
  101. + Where can I find the "CGI specification"? + +

    + The Common Gateway Interface (CGI) specification can be found at + the original NCSA site + < + http://hoohoo.ncsa.uiuc.edu/cgi/interface.html>. + This version hasn't been updated since 1995, and there have been + some efforts to update it. +

    +

    + A new draft is being worked on with the intent of making it an informational + RFC; you can find out more about this project at + <http://web.golux.com/coar/cgi/>. +

    +
    +
  102. + +
  103. + Is Apache Year 2000 compliant? + +

    + Yes, Apache is Year 2000 compliant. +

    +

    + Apache internally never stores years as two digits. + On the HTTP protocol level RFC1123-style addresses are generated + which is the only format a HTTP/1.1-compliant server should + generate. To be compatible with older applications Apache + recognizes ANSI C's asctime() and + RFC850-/RFC1036-style date formats, too. + The asctime() format uses four-digit years, + but the RFC850 and RFC1036 date formats only define a two-digit year. + If Apache sees such a date with a value less than 70 it assumes that + the century is 20 rather than 19. +

    +

    + Some aspects of Apache's output may use two-digit years, such as the + automatic listing of directory contents provided by + mod_autoindex + with the + FancyIndexing + option enabled, but it is improper to depend upon such displays for + specific syntax. And even that issue is being addressed by the + developers; a future version of Apache should allow you to format that + display as you like. +

    +

    + Although Apache is Year 2000 compliant, you may still get problems + if the underlying OS has problems with dates past year 2000 + (e.g., OS calls which accept or return year numbers). + Most (UNIX) systems store dates internally as signed 32-bit integers + which contain the number of seconds since 1st January 1970, so + the magic boundary to worry about is the year 2038 and not 2000. + But modern operating systems shouldn't cause any trouble + at all. +

    +
    +
  104. + +
  105. + I upgraded to Apache 1.3b and now my virtual hosts don't + work! + +

    + In versions of Apache prior to 1.3b2, there was a lot of confusion + regarding address-based virtual hosts and (HTTP/1.1) name-based + virtual hosts, and the rules concerning how the server processed + <VirtualHost> definitions were very complex and not + well documented. +

    +

    + Apache 1.3b2 introduced a new directive, + NameVirtualHost, + which simplifies the rules quite a bit. However, changing the rules + like this means that your existing name-based + <VirtualHost> containers probably won't work + correctly immediately following the upgrade. +

    +

    + To correct this problem, add the following line to the beginning of + your server configuration file, before defining any virtual hosts: +

    +
    +
    NameVirtualHost n.n.n.n +
    +
    +

    + Replace the "n.n.n.n" with the IP address to + which the name-based virtual host names resolve; if you have multiple + name-based hosts on multiple addresses, repeat the directive for each + address. +

    +

    + Make sure that your name-based <VirtualHost> blocks + contain ServerName and possibly ServerAlias + directives so Apache can be sure to tell them apart correctly. +

    +

    + Please see the + Apache + Virtual Host documentation for further details about configuration. +

    +
    +
  106. + +
  107. + I'm using RedHat Linux and I have problems with httpd + dying randomly or not restarting properly + + +

    + RedHat Linux versions 4.x (and possibly earlier) RPMs contain + various nasty scripts which do not stop or restart Apache properly. + These can affect you even if you're not running the RedHat supplied + RPMs. +

    +

    + If you're using the default install then you're probably running + Apache 1.1.3, which is outdated. From RedHat's ftp site you can + pick up a more recent RPM for Apache 1.2.x. This will solve one of + the problems. +

    +

    + If you're using a custom built Apache rather than the RedHat RPMs + then you should rpm -e apache. In particular you want + the mildly broken /etc/logrotate.d/apache script to be + removed, and you want the broken /etc/rc.d/init.d/httpd + (or httpd.init) script to be removed. The latter is + actually fixed by the apache-1.2.5 RPMs but if you're building your + own Apache then you probably don't want the RedHat files. +

    +

    + We can't stress enough how important it is for folks, especially + vendors to follow the stopping Apache + directions given in our documentation. In RedHat's defense, + the broken scripts were necessary with Apache 1.1.x because the + Linux support in 1.1.x was very poor, and there were various race + conditions on all platforms. None of this should be necessary with + Apache 1.2 and later. +

    +
    +
  108. + +
  109. + I upgraded from an Apache version earlier + than 1.2.0 and suddenly I have problems with Apache dying randomly + or not restarting properly + + +

    + You should read the previous note about + problems with RedHat installations. It is entirely likely that your + installation has start/stop/restart scripts which were built for + an earlier version of Apache. Versions earlier than 1.2.0 had + various race conditions that made it necessary to use + kill -9 at times to take out all the httpd servers. + But that should not be necessary any longer. You should follow + the directions on how to stop + and restart Apache. +

    +

    As of Apache 1.3 there is a script + src/support/apachectl which, after a bit of + customization, is suitable for starting, stopping, and restarting + your server. +

    +
    +
  110. + +
  111. + I'm using RedHat Linux and my .htm files are showing + up as HTML source rather than being formatted! + + +

    + RedHat messed up and forgot to put a content type for .htm + files into /etc/mime.types. Edit /etc/mime.types, + find the line containing html and add htm to it. + Then restart your httpd server: +

    +
    +
    kill -HUP `cat /var/run/httpd.pid` +
    +
    +

    + Then clear your browsers' caches. (Many browsers won't + re-examine the content type after they've reloaded a page.) +

    +
    +
  112. + +
  113. + I'm using RedHat Linux 5.0, or some other + glibc-based Linux system, and I get errors with the + crypt function when I attempt to build Apache 1.2. + + +

    + glibc puts the crypt function into a separate + library. Edit your src/Configuration file and set this: +

    +
    +
    EXTRA_LIBS=-lcrypt +
    +
    +

    + Then re-run src/Configure and re-execute the make. +

    +
    +
  114. + +
  115. + Server hangs, or fails to start, and/or error log + fills with "fcntl: F_SETLKW: No record locks + available" or similar messages + + +

    + These are symptoms of a fine locking problem, which usually means that + the server is trying to use a synchronization file on an NFS filesystem. +

    +

    + Because of its parallel-operation model, the Apache Web server needs to + provide some form of synchronization when accessing certain resources. + One of these synchronization methods involves taking out locks on a file, + which means that the filesystem whereon the lockfile resides must support + locking. In many cases this means it can't be kept on an + NFS-mounted filesystem. +

    +

    + To cause the Web server to work around the NFS locking limitations, include + a line such as the following in your server configuration files: +

    +
    +
    LockFile /var/run/apache-lock +
    +
    +

    + The directory should not be generally writable (e.g., don't use + /var/tmp). + See the LockFile + documentation for more information. +

    +
    +
  116. +
  117. + What's the best hardware/operating system/... How do + I get the most out of my Apache Web server? + +

    + Check out Dean Gaudet's + performance tuning page. +

    +
    +
  118. +
  119. + What are "regular expressions"? +

    + Regular expressions are a way of describing a pattern - for example, "all the words + that begin with the letter A" or "every 10-digit phone number" or even "Every sentence + with two commas in it, and no capital letter Q". Regular expressions (aka "regexp"s) + are useful in Apache because they let you apply certain attributes against collections + of files or resources in very flexible ways - for example, all .gif and .jpg files under + any "images" directory could be written as /.*\/images\/.*[jpg|gif]/. + +

    The best overview around is probably the one which comes with + Perl. We implement a simple subset of Perl's regexp support, but + it's still a good way to learn what they mean. You can start by + going to the CPAN + page on regular expressions, and branching out from there. + +


    +
  120. + + + +
+ + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/HTTP_Features.tsv b/APACHE_1_3b7/htdocs/manual/misc/HTTP_Features.tsv new file mode 100644 index 0000000000..893403d898 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/HTTP_Features.tsv @@ -0,0 +1,142 @@ +This tab-separated-value file is for use as a checklist +for features against , +since two independently developed and interoperable +implementations are needed for each feature. For each entry, + ? means not filled-in + - means not applicable + n means no + y means yes + Y means yes with the addition of a module that uses feature + +The contents should be placed in the form at +by someone who wants to be the contact for the Apache Group. + +Section Feature Implemented Tested +8.1 Persistent Connections y y +8.2.3 Automatic retrying of requests - - +8.2.4 Use of the 100 (Continue) status n n +9.2 OPTIONS y y +9.3 GET y y +9.4 HEAD y y +9.5 POST y y +9.6 PUT Y y +9.7 DELETE Y y +9.8 TRACE y y +9.9 CONNECT y y +10.1.1 100 Continue y y +10.1.2 101 Switching Protocols Y n +10.2.1 200 OK y y +10.2.2 201 Created y y +10.2.3 202 Accepted y y +10.2.4 203 Non-Authoritative Information y y +10.2.5 204 No Content y y +10.2.6 205 Reset Content y y +10.2.7 206 Partial Content y y +10.3.1 300 Multiple Choices y y +10.3.2 301 Moved Permanently y y +10.3.3 302 Found y y +10.3.4 303 See Other y y +10.3.5 304 Not Modified y y +10.3.6 305 Use Proxy y n +10.3.7 307 Temporary Redirect n n +10.4.1 400 Bad Request y y +10.4.2 401 Unauthorized y y +10.4.3 402 Payment Required Y n +10.4.4 403 Forbidden y y +10.4.5 404 Not Found y y +10.4.6 405 Method Not Allowed y y +10.4.7 406 Not Acceptable y y +10.4.8 407 Proxy Authentication Required y y +10.4.9 408 Request Timeout y y +10.4.10 409 Conflict Y n +10.4.11 410 Gone y y +10.4.12 411 Length Required y y +10.4.13 412 Precondition Failed y y +10.4.14 413 Request Entity Too Large y y +10.4.15 414 Request-URI Too Long y y +10.4.16 415 Unsupported Media Type y n +10.4.17 416 Requested range not satisfiable n n +10.4.18 417 Expectation Failed n n +10.5.1 500 Internal Server Error y y +10.5.2 501 Not Implemented y y +10.5.3 502 Bad Gateway y y +10.5.4 503 Service Unavailable y y +10.5.5 504 Gateway Timeout y y +10.5.6 505 HTTP Version Not Supported Y n +13.3.3 Strong entity tags y y +13.3.3 Weak entity tags y y +14.1 Accept y y +14.2 Accept-Charset y y +14.3 Accept-Encoding n n +14.4 Accept-Language y y +14.5 Accept-Ranges y y +14.6 Age - - +14.7 Allow y y +14.8 Authorization y y +14.9 Cache-Control y y +14.10 Connection y y +14.11 Content-Encoding y y +14.12 Content-Language y y +14.13 Content-Length y y +14.14 Content-Location Y n +14.15 Content-MD5 y n +14.16 Content-Range y y +14.17 Content-Type y y +14.18 Date y y +14.19 ETag y y +14.20 Expect n n +14.21 Expires y y +14.22 From - - +14.23 Host y y +14.24 If-Modified-Since y y +14.25 If-Match y y +14.26 If-None-Match y y +14.27 If-Range y y +14.28 If-Unmodified-Since y y +14.29 Last-Modified y y +14.30 Location y y +14.31 Max-Forwards n n +14.32 Pragma y y +14.33 Proxy-Authenticate y y +14.34 Proxy-Authorization y y +14.35 Range y y +14.36 Referer y y +14.37 Retry-After y y +14.38 Server y y +14.39 TE n n +14.40 Trailer n n +14.41 Transfer-Encoding y y +14.42 Upgrade Y n +14.43 User-Agent - - +14.44 Vary y y +14.45 Via n n +14.46 Warning Y n +14.47 WWW-Authenticate y y +===== ===================================== +Same for : + +A 2 Basic Authentication y y +A 3.2.1 WWW-Authenticate Digest y n +A 3.2.1 qop-options auth n n +A 3.2.1 qop-options auth-int n n +A 3.2.2 Authorization Digest y n +A 3.2.2 request qop auth n n +A 3.2.2 request qop auth-int n n +A 3.2.3 Authentication-Info Digest n n +A 3.2.3 response qop auth n n +A 3.2.3 response qop auth-int n n +A 4.1 Proxy-Authenticate Basic y y +A 4.2 Proxy-Authenticate Digest y n +A 4.2 Proxy qop-options auth n n +A 4.2 Proxy qop-options auth-int n n +A 4.2 Proxy Authorization Digest y n +A 4.2 Proxy request qop auth n n +A 4.2 Proxy request qop auth-int n n +A 4.2 Proxy Authentication-Info Digest n n +A 4.2 Proxy response qop auth n n +A 4.2 Proxy response qop auth-int n n + + +NOTES: +100 Continue sent on all bodied requests, as per RFC 2068. +Accept-Encoding does not allow q-values, as per RFC 2068. diff --git a/APACHE_1_3b7/htdocs/manual/misc/client_block_api.html b/APACHE_1_3b7/htdocs/manual/misc/client_block_api.html new file mode 100644 index 0000000000..e70a8284fc --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/client_block_api.html @@ -0,0 +1,87 @@ + + + +Reading Client Input in Apache 1.2 + + + + + +

Reading Client Input in Apache 1.2

+ +
+ +

Apache 1.1 and earlier let modules handle POST and PUT requests by +themselves. The module would, on its own, determine whether the +request had an entity, how many bytes it was, and then called a +function (read_client_block) to get the data. + +

However, HTTP/1.1 requires several things of POST and PUT request +handlers that did not fit into this module, and all existing modules +have to be rewritten. The API calls for handling this have been +further abstracted, so that future HTTP protocol changes can be +accomplished while remaining backwards-compatible.

+ +
+ +

The New API Functions

+ +
+   int ap_setup_client_block (request_rec *, int read_policy);
+   int ap_should_client_block (request_rec *);
+   long ap_get_client_block (request_rec *, char *buffer, int buffer_size);
+
+ +
    +
  1. Call ap_setup_client_block() near the beginning of the request + handler. This will set up all the necessary properties, and + will return either OK, or an error code. If the latter, + the module should return that error code. The second parameter + selects the policy to apply if the request message indicates a + body, and how a chunked + transfer-coding should be interpreted. Choose one of +
    +    REQUEST_NO_BODY          Send 413 error if message has any body
    +    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
    +    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
    +    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
    +
    + In order to use the last two options, the caller MUST provide a buffer + large enough to hold a chunk-size line, including any extensions. + + + +
  2. When you are ready to possibly accept input, call + ap_should_client_block(). + This will tell the module whether or not to read input. If it is 0, + the module should assume that the input is of a non-entity type + (e.g. a GET request). A nonzero response indicates that the module + should proceed (to step 3). + This step also sends a 100 Continue response + to HTTP/1.1 clients, so should not be called until the module + is *definitely* ready to read content. (otherwise, the + point of the + 100 response is defeated). Never call this function more than once. + +
  3. Finally, call ap_get_client_block in a loop. Pass it a + buffer and its + size. It will put data into the buffer (not necessarily the full + buffer, in the case of chunked inputs), and return the length of + the input block. When it is done reading, it will + return 0 if EOF, or -1 if there was an error. + +
+ +

As an example, please look at the code in +mod_cgi.c. This is properly written to the new API +guidelines.

+ + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/compat_notes.html b/APACHE_1_3b7/htdocs/manual/misc/compat_notes.html new file mode 100644 index 0000000000..30c4ca31ba --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/compat_notes.html @@ -0,0 +1,117 @@ + + +Apache HTTP Server: Compatibility Notes with NCSA's Server + + + + +

Compatibility Notes with NCSA's Server

+ +
+ +While Apache is for the most part a drop-in replacement for NCSA's +httpd, there are a couple gotcha's to watch out for. These are mostly +due to the fact that the parser for config and access control files +was rewritten from scratch, so certain liberties the earlier servers +took may not be available here. These are all easily fixable. If you +know of other non-fatal problems that belong here, let us know. + +

Please also check the known +client problems page. + +

    +
  1. The basic mod_auth AuthGroupFile-specified group file + format allows commas between user names - Apache does not. + +

    +

  2. If you follow the NCSA guidelines for setting up access + restrictions based on client domain, you may well have added + entries for, AuthType, AuthName, AuthUserFile or + AuthGroupFile. None of these are + needed (or appropriate) for restricting access based on client + domain. When Apache sees AuthType it (reasonably) + assumes you are using some authorization type based on username + and password. Please remove AuthType, it's + unnecessary even for NCSA. + +

    +

  3. OldScriptAlias is no longer supported. + +

    +

  4. exec cgi="" produces reasonable malformed + header responses when used to invoke non-CGI scripts.
    + The NCSA code ignores the missing header. (bad idea)
    Solution: + write CGI to the CGI spec or use exec cmd="" instead. +

    We might add virtual support to exec + cmd to make up for this difference. + +

    +

  5. Icons for FancyIndexing broken - well, no, they're not broken, + we've just upgraded the icons from flat .xbm files to pretty and + much smaller .gif files, courtesy of Kevin Hughes at EIT. If you are using the same + srm.conf from an old distribution, make sure you add the new AddIcon, AddIconByType, + and DefaultIcon + directives. + +

    +

  6. Apache versions before 1.2b1 will ignore the last line of configuration + files if the last line does not have a trailing newline. This affects + configuration files (httpd.conf, access.conf and srm.conf), and + htpasswd and htgroup files. + +

    +

  7. Apache does not permit commas delimiting the methods in <Limit>. + +

    +

  8. Apache's <VirtualHost> treats all addresses as + "optional" (i.e. the server should continue booting if it can't + resolve the address). Whereas in NCSA the default is to fail + booting unless an added optional keyword is included. + +

    +

  9. Apache does not implement OnDeny use + ErrorDocument + instead. + +

    +

  10. Apache (as of 1.3) always performs the equivalent of + HostnameLookups minimal. minimal is not an + option to + HostnameLookups. + +

    +

  11. To embed spaces in directive arguments NCSA used a backslash + before the space. Apache treats backslashes as normal characters. To + embed spaces surround the argument with double-quotes instead. + +

    +

  12. Apache does not implement the NCSA referer + directive. See + PR#968 for a few brief suggestions on alternative ways to + implement the same thing under Apache. + +

    +

  13. Apache does not allow ServerRoot settings inside a VirtualHost + container. There is only one global ServerRoot in Apache; any desired + changes in paths for virtual hosts need to be made with the explicit + directives, eg. DocumentRoot, TransferLog, etc. + +
+ +More to come when we notice them.... + + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/custom_errordocs.html b/APACHE_1_3b7/htdocs/manual/misc/custom_errordocs.html new file mode 100644 index 0000000000..7eee41a125 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/custom_errordocs.html @@ -0,0 +1,394 @@ + + + +International Customized Server Error Messages + + + + + + +

Using XSSI and ErrorDocument to configure +customized international server error responses

+

+

Index

+ +
+

Introduction

+This document describes an easy way to provide your apache WWW server +with a set of customized error messages which take advantage of +Content Negotiation +and eXtended Server Side Includes (XSSI) +to return error messages generated by the server in the client's +native language. +

+

+By using XSSI, all +customized messages +can share a homogenous and consistent style and layout, and maintenance work +(changing images, changing links) is kept to a minimum because all layout +information can be kept in a single file.
+Error documents can be shared across different servers, or even hosts, +because all varying information is inserted at the time the error document +is returned on behalf of a failed request. +

+

+Content Negotiation then selects the appropriate language version of a +particular error message text, honoring the language preferences passed +in the client's request. (Users usually select their favorite languages +in the preferences options menu of today's browsers). When an error +document in the client's primary language version is unavailable, the +secondary languages are tried or a default (fallback) version is used. +

+

+You have full flexibility in designing your error documents to +your personal taste (or your company's conventions). For demonstration +purposes, we present a simple generic error document scheme. +For this hypothetic server, we assume that all error messages... +

    +
  • possibly are served by different virtual hosts (different host name, + different IP address, or different port) on the server machine, +
  • show a predefined company logo in the right top of the message + (selectable by virtual host), +
  • print the error title first, followed by an explanatory text and + (depending on the error context) help on how to resolve the error, +
  • have some kind of standardized background image, +
  • display an apache logo and a feedback email address at the bottom + of the error message. +
+

+ +

+An example of a "document not found" message for a german client might +look like this:
+[Needs graphics capability to display]
+All links in the document as well as links to the server's administrator +mail address, and even the name and port of the serving virtual host +are inserted in the error document at "run-time", i.e., when the error +actually occurs. +

+ +

Creating an ErrorDocument directory

+ +For this concept to work as easily as possible, we must take advantage +of as much server support as we can get: +
    +
  1. By defining the MultiViews option, + we enable the language selection of the most appropriate language + alternative (content negotiation). +
  2. By setting the + LanguagePriority + directive we define a set of default fallback languages in the situation + where the client's browser did not express any preference at all. +
  3. By enabling Server Side Includes + (and disallowing execution of cgi scripts for security reasons), + we allow the server to include building blocks of the error message, + and to substitute the value of certain environment variables into the + generated document (dynamic HTML) or even to conditionally include + or omit parts of the text. +
  4. The AddHandler and + AddType directives are useful + for automatically XSSI-expanding all files with a .shtml + suffix to text/html. +
  5. By using the Alias directive, + we keep the error document directory outside of the document tree + because it can be regarded more as a server part than part of + the document tree. +
  6. The <Directory>-Block + restricts these "special" settings to the error document directory + and avoids an impact on any of the settings for the regular document tree. +
  7. For each of the error codes to be handled (see RFC2068 for an exact + description of each error code, or look at + src/main/http_protocol.c + if you wish to see apache's standard messages), an + ErrorDocument + in the aliased /errordocs directory is defined. + Note that we only define the basename of the document here + because the MultiViews option will select the best candidate + based on the language suffixes and the client's preferences. + Any error situation with an error code not handled by a + custom document will be dealt with by the server in the standard way + (i.e., a plain error message in english). +
  8. Finally, the AllowOverride + directive tells apache that it is not necessary to look for + a .htaccess file in the /errordocs directory: a minor speed + optimization. +
+The resulting httpd.conf configuration would the look +similar to this: (Note that you can defrine your own error +messages using this method for only part of the document tree, +e.g., a /~user/ subtree. In this case, the configuration could as well +be put into the .htaccess file at the root of the subtree. In this case, +the <Directory> and </Directory> directives -but not +the contained directives- must be omitted.) +
+  LanguagePriority en fr de 
+  Alias  /errordocs  /usr/local/apache/errordocs
+  <Directory /usr/local/apache/errordocs>
+   AllowOverride none
+   Options MultiViews IncludesNoExec FollowSymLinks
+   AddType text/html .shtml
+   AddHandler server-parsed .shtml
+  </Directory>
+  #    "400 Bad Request",
+  ErrorDocument  400  /errordocs/400
+  #    "401 Authorization Required",
+  ErrorDocument  401  /errordocs/401
+  #    "403 Forbidden",
+  ErrorDocument  403  /errordocs/403
+  #    "404 Not Found",
+  ErrorDocument  404  /errordocs/404
+  #    "500 Internal Server Error",
+  ErrorDocument  500  /errordocs/500
+
+The directory for the error messages (here: +/usr/local/apache/errordocs/) must then be created with the +appropriate permissions (readable and executable by the server uid or gid, +only writable for the administrator). + +

Naming the individual error document files

+ +By defining the MultiViews option, the server was told to +automatically scan the directory for matching variants (looking at language +and content type suffixes) when a requested document was not found. +In the configuration, we defined the names for the error documents to be +just their error number (without any suffix). +

+The names of the individual error documents are now determined like this +(I'm using 403 as an example, think of it as a placeholder for any of +the configured error documents): +

    +
  • No file errordocs/403 should exist. Otherwise, it would be found and + served (with the DefaultType, usually text/plain), all negotiation + would be bypassed. +
  • For each language for which we have a translation (note that this need not + be the same set of languages for each error code - you can get by + with a single language version until you actually have + translated versions), a document + errordocs/403.shtml.lang is created and + filled with the error text in that language (see + below). +
  • One fallback document called errordocs/403.shtml is + created, usually by creating a symlink to the default language + variant (see below). +
+ +

The common header and footer files

+ +By putting as much layout information in two special "include files", +the error documents can be reduced to a bare minimum. +

+One of these layout files defines the HTML document header +and a configurable list of paths to the icons to be shown in the resulting +error document. These paths are exported as a set of XSSI environment +variables and are later evaluated by the "footer" special file. +The title of the current error (which is +put into the TITLE tag and an H1 header) is simply passed in from the main +error document in a variable called title.
+By changing this file, the layout of all generated error +messages can be changed in a second. +(By exploiting the features of XSSI, you can easily define different +layouts based on the current virtual host, or even based on the +client's domain name). +

+The second layout file describes the footer to be displayed at the bottom +of every error message. In this example, it shows an apache logo, the current +server time, the server version string and adds a mail reference to the +site's webmaster. +

+For simplicity, the header file is simply called head.shtml +because it contains server-parsed content but no language specific +information. The footer file exists once for each language translation, +plus a symlink for the default language.

+Example: for English, French and German versions +(default english)
+foot.shtml.en,
+foot.shtml.fr,
+foot.shtml.de,
+foot.shtml symlink to foot.shtml.en

+Both files are then simply included into the error document by using the +directives <!--#include virtual="head" --> +and <!--#include virtual="foot" --> +respectively: the rest of the magic occurs in mod_negotiation and +in mod_include. +

+ +See the listings below to see an actual HTML +implementation of the discussed example. + + +

Creating ErrorDocuments in different languages +

+ +After all this preparation work, little remains to be said about the +actual documents. They all share a simple common structure: +
+<!--#set var="title" value="error description title" -->
+<!--#include virtual="head" -->
+   explanatory error text
+<!--#include virtual="foot" -->
+
+In the listings section, you can see an example +of a [400 Bad Request] error document. Documents as simple as that +certainly cause no problems to translate or expand. + +

The fallback language

+ +Do we need a special handling for languages other than those we have +translations for? We did set the LanguagePriority, didn't we?! +

+Well, the LanguagePriority directive is for the case where the client does +not express any language priority at all. But what +happens in the situation where the client wants one +of the languages we do not have, and none of those we do have? +

+Without doing anything, the Apache server will usually return a +[406 no acceptable variant] error, listing the choices from which the client +may select. But we're in an error message already, and important error +information might get lost when the client had to choose a language +representation first. +

+So, in this situation it appears to be easier to define a fallback language +(by copying or linking, e.g., the english version to a language-less version). +Because the negotiation algorithm prefers "more specialized" variants over +"more generic" variants, these generic alternatives will only be chosen +when the normal negotiation did not succeed. +

+A simple shell script to do it (execute within the errordocs/ dir): +

+  for f in *.shtml.en
+  do
+     ln -s $f `basename $f .en`
+  done
+
+ +

+

+ +

HTML listing of the discussed example

+ +So, to summarize our example, here's the complete listing of the +400.shtml.en document. You will notice that it contains +almost nothing but the error text (with conditional additions). +Starting with this example, you will find it easy to add more error +documents, or to translate the error documents to different languages. +
+<!--#set var="title" value="Bad Request"
+--><!--#include virtual="head" --><P>
+   Your browser sent a request that this server could not understand:
+   <BLOCKQUOTE>
+     <STRONG><!--#echo var="REQUEST_URI" --></STRONG>
+   </BLOCKQUOTE>
+   The request could not be understood by the server due to malformed
+   syntax. The client should not repeat the request without
+   modifications.
+   </P>
+   <P>
+   <!--#if expr="\"$HTTP_REFERER\" != \"\"" -->
+    Please inform the owner of
+    <A HREF="<!--#echo var="HTTP_REFERER" -->">the referring page</A> about 
+    the malformed link.
+   <!--#else -->
+    Please check your request for typing errors and retry.
+   <!--#endif -->
+   </P>
+<!--#include virtual="foot" -->
+

+ +Here is the complete head.shtml file (the funny line +breaks avoid empty lines in the document after XSSI processing). Note the +configuration section at top. That's where you configure the images and logos +as well as the apache documentation directory. Look how this file displays +two different logos depending on the content of the virtual host name +($SERVER_NAME), and that an animated apache logo is shown if the browser +appears to support it (the latter requires server configuration lines +of the form
BrowserMatch "^Mozilla/[2-4]" anigif
+for browser types which support animated GIFs). +
+<!--#if expr="\"$SERVER_NAME\" = /.*\.mycompany\.com/" 
+--><!--#set var="IMG_CorpLogo"
+            value="http://$SERVER_NAME:$SERVER_PORT/errordocs/CorpLogo.gif" 
+--><!--#set var="ALT_CorpLogo" value="Powered by Linux!" 
+--><!--#else
+--><!--#set var="IMG_CorpLogo"
+            value="http://$SERVER_NAME:$SERVER_PORT/errordocs/PrivLogo.gif" 
+--><!--#set var="ALT_CorpLogo" value="Powered by Linux!" 
+--><!--#endif
+--><!--#set var="IMG_BgImage" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/BgImage.gif" 
+--><!--#set var="DOC_Apache" value="http://$SERVER_NAME:$SERVER_PORT/Apache/" 
+--><!--#if expr="$anigif" 
+--><!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_anim.gif" 
+--><!--#else
+--><!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_pb.gif" 
+--><!--#endif
+--><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+ <HEAD>
+  <TITLE>
+   [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" -->
+  </TITLE>
+ </HEAD>
+ <BODY BGCOLOR="white" BACKGROUND="<!--#echo var="IMG_BgImage" -->"><UL>
+  <H1 ALIGN="center">
+   [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" -->
+   <IMG SRC="<!--#echo var="IMG_CorpLogo" -->"
+        ALT="<!--#echo var="ALT_CorpLogo" -->" ALIGN=right>
+  </H1>
+  <HR><!-- ======================================================== -->
+  <DIV>
+

+ and this is the foot.shtml.en file: +
+
+  </DIV>
+  <HR>
+  <DIV ALIGN="right"><SMALL><SUP>Local Server time:
+      <!--#echo var="DATE_LOCAL" -->
+  </SUP></SMALL></DIV>
+  <DIV ALIGN="center">
+    <A HREF="<!--#echo var="DOC_Apache" -->">
+    <IMG SRC="<!--#echo var="IMG_Apache" -->" BORDER=0 ALIGN="bottom"
+         ALT="Powered by <!--#echo var="SERVER_SOFTWARE" -->"></A><BR>
+    <SMALL><SUP><!--#set var="var"
+     value="Powered by $SERVER_SOFTWARE -- File last modified on $LAST_MODIFIED"
+    --><!--#echo var="var" --></SUP></SMALL>
+  </DIV>
+  <ADDRESS>If the indicated error looks like a misconfiguration, please inform
+   <A HREF="mailto:<!--#echo var="SERVER_ADMIN" -->"
+      SUBJECT="Feedback about Error message [<!--#echo var="REDIRECT_STATUS" 
+        -->] <!--#echo var="title" -->, req=<!--#echo var="REQUEST_URI" -->">
+   <!--#echo var="SERVER_NAME" -->'s WebMaster</A>.
+  </ADDRESS>
+ </UL></BODY>
+</HTML>
+

+ + +

More welcome!

+ +If you have tips to contribute, send mail to Martin.Kraemer@Mch.SNI.De + +
+ +Index +Home + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/descriptors.html b/APACHE_1_3b7/htdocs/manual/misc/descriptors.html new file mode 100644 index 0000000000..5841e10e1e --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/descriptors.html @@ -0,0 +1,155 @@ + + + +Descriptors and Apache + + + + + +

Descriptors and Apache

+ +

A descriptor, also commonly called a file handle is +an object that a program uses to read or write an open file, or open +network socket, or a variety of other devices. It is represented +by an integer, and you may be familiar with stdin, +stdout, and stderr which are descriptors 0, +1, and 2 respectively. +Apache needs a descriptor for each log file, plus one for each +network socket that it listens on, plus a handful of others. Libraries +that Apache uses may also require descriptors. Normal programs don't +open up many descriptors at all, and so there are some latent problems +that you may experience should you start running Apache with many +descriptors (i.e. with many virtual hosts). + +

The operating system enforces a limit on the number of descriptors +that a program can have open at a time. There are typically three limits +involved here. One is a kernel limitation, depending on your operating +system you will either be able to tune the number of descriptors available +to higher numbers (this is frequently called FD_SETSIZE). Or you +may be stuck with a (relatively) low amount. The second limit is called +the hard resource limit, and it is sometimes set by root in an +obscure operating system file, but frequently is the same as the kernel +limit. The third limit is called the soft +resource limit. The soft limit is always less than or equal to +the hard limit. For example, the hard limit may be 1024, but the soft +limit only 64. Any user can raise their soft limit up to the hard limit. +Root can raise the hard limit up to the system maximum limit. The soft +limit is the actual limit that is used when enforcing the maximum number +of files a process can have open. + +

To summarize: + +

+  #open files  <=  soft limit  <=  hard limit  <=  kernel limit
+
+ +

You control the hard and soft limits using the limit (csh) +or ulimit (sh) directives. See the respective man pages +for more information. For example you can probably use +ulimit -n unlimited to raise your soft limit up to the +hard limit. You should include this command in a shell script which +starts your webserver. + +

Unfortunately, it's not always this simple. As mentioned above, +you will probably run into some system limitations that will need to be +worked around somehow. Work was done in version 1.2.1 to improve the +situation somewhat. Here is a partial list of systems and workarounds +(assuming you are using 1.2.1 or later): + +

+ +
BSDI 2.0 +
Under BSDI 2.0 you can build Apache to support more descriptors + by adding -DFD_SETSIZE=nnn to + EXTRA_CFLAGS (where nnn is the number of descriptors + you wish to support, keep it less than the hard limit). But it + will run into trouble if more than approximately 240 Listen + directives are used. This may be cured by rebuilding your kernel + with a higher FD_SETSIZE. +

+ +

FreeBSD 2.2, BSDI 2.1+ +
Similar to the BSDI 2.0 case, you should define + FD_SETSIZE and rebuild. But the extra + Listen limitation doesn't exist. +

+ +

Linux +
By default Linux has a kernel maximum of 256 open descriptors + per process. There are several patches available for the + 2.0.x series which raise this to 1024 and beyond, and you + can find them in the "unofficial patches" section of the Linux Information HQ. + None of these patches are perfect, and an entirely different + approach is likely to be taken during the 2.1.x development. + Applying these patches will raise the FD_SETSIZE used to compile + all programs, and unless you rebuild all your libraries you should + avoid running any other program with a soft descriptor limit above + 256. As of this writing the patches available for increasing + the number of descriptors do not take this into account. On a + dedicated webserver you probably won't run into trouble. +

+ +

Solaris through 2.5.1 +
Solaris has a kernel hard limit of 1024 (may be lower in earlier + versions). But it has a limitation that files using + the stdio library cannot have a descriptor above 255. + Apache uses the stdio library for the ErrorLog directive. + When you have more than approximately 110 virtual hosts + (with an error log and an access log each) you will need to + build Apache with -DHIGH_SLACK_LINE=256 added to + EXTRA_CFLAGS. You will be limited to approximately + 240 error logs if you do this. +

+ +

AIX +
AIX version 3.2?? appears to have a hard limit of 128 descriptors. + End of story. Version 4.1.5 has a hard limit of 2000. +

+ +

Others +
If you have details on another operating system, please submit + it through our Bug + Report Page. +

+ +

+ +

In addition to the problems described above there are problems with +many libraries that Apache uses. The most common example is the bind +DNS resolver library that is used by pretty much every unix, which +fails if it ends up with a descriptor above 256. We suspect there +are other libraries that similar limitations. So the code as of 1.2.1 +takes a defensive stance and tries to save descriptors less than 16 +for use while processing each request. This is called the low +slack line. + +

Note that this shouldn't waste descriptors. If you really are pushing +the limits and Apache can't get a descriptor above 16 when it wants +it, it will settle for one below 16. + +

In extreme situations you may want to lower the low slack line, +but you shouldn't ever need to. For example, lowering it can +increase the limits 240 described above under Solaris and BSDI 2.0. +But you'll play a delicate balancing game with the descriptors needed +to serve a request. Should you want to play this game, the compile +time parameter is LOW_SLACK_LINE and there's a tiny +bit of documentation in the header file httpd.h. + +

Finally, if you suspect that all this slack stuff is causing you +problems, you can disable it. Add -DNO_SLACK to +EXTRA_CFLAGS and rebuild. But please report it to +our Bug +Report Page so that +we can investigate. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/fin_wait_2.html b/APACHE_1_3b7/htdocs/manual/misc/fin_wait_2.html new file mode 100644 index 0000000000..f264bf24a0 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/fin_wait_2.html @@ -0,0 +1,324 @@ + + + +Connections in FIN_WAIT_2 and Apache + + + + + + + + +

Connections in the FIN_WAIT_2 state and Apache

+
    +
  1. What is the FIN_WAIT_2 state?

    +Starting with the Apache 1.2 betas, people are reporting many more +connections in the FIN_WAIT_2 state (as reported by +netstat) than they saw using older versions. When the +server closes a TCP connection, it sends a packet with the FIN bit +sent to the client, which then responds with a packet with the ACK bit +set. The client then sends a packet with the FIN bit set to the +server, which responds with an ACK and the connection is closed. The +state that the connection is in during the period between when the +server gets the ACK from the client and the server gets the FIN from +the client is known as FIN_WAIT_2. See the TCP RFC for the +technical details of the state transitions.

    + +The FIN_WAIT_2 state is somewhat unusual in that there is no timeout +defined in the standard for it. This means that on many operating +systems, a connection in the FIN_WAIT_2 state will stay around until +the system is rebooted. If the system does not have a timeout and +too many FIN_WAIT_2 connections build up, it can fill up the space +allocated for storing information about the connections and crash +the kernel. The connections in FIN_WAIT_2 do not tie up an httpd +process.

    + +

  2. But why does it happen?

    + +There are numerous reasons for it happening, some of them may not +yet be fully clear. What is known follows.

    + +

    Buggy clients and persistent connections

    + +Several clients have a bug which pops up when dealing with +persistent connections (aka keepalives). +When the connection is idle and the server closes the connection +(based on the +KeepAliveTimeout), the client is programmed so that the client does +not send back a FIN and ACK to the server. This means that the +connection stays in the FIN_WAIT_2 state until one of the following +happens:

    +

      +
    • The client opens a new connection to the same or a different + site, which causes it to fully close the older connection on + that socket. +
    • The user exits the client, which on some (most?) clients + causes the OS to fully shutdown the connection. +
    • The FIN_WAIT_2 times out, on servers that have a timeout + for this state. +

    +If you are lucky, this means that the buggy client will fully close the +connection and release the resources on your server. However, there +are some cases where the socket is never fully closed, such as a dialup +client disconnecting from their provider before closing the client. +In addition, a client might sit idle for days without making another +connection, and thus may hold its end of the socket open for days +even though it has no further use for it. +This is a bug in the browser or in its operating system's +TCP implementation.

    + +The clients on which this problem has been verified to exist:

    +

      +
    • Mozilla/3.01 (X11; I; FreeBSD 2.1.5-RELEASE i386) +
    • Mozilla/2.02 (X11; I; FreeBSD 2.1.5-RELEASE i386) +
    • Mozilla/3.01Gold (X11; I; SunOS 5.5 sun4m) +
    • MSIE 3.01 on the Macintosh +
    • MSIE 3.01 on Windows 95 +

    + +This does not appear to be a problem on: +

      +
    • Mozilla/3.01 (Win95; I) +
    +

    + +It is expected that many other clients have the same problem. What a +client should do is periodically check its open +socket(s) to see if they have been closed by the server, and close their +side of the connection if the server has closed. This check need only +occur once every few seconds, and may even be detected by a OS signal +on some systems (e.g., Win95 and NT clients have this capability, but +they seem to be ignoring it).

    + +Apache cannot avoid these FIN_WAIT_2 states unless it +disables persistent connections for the buggy clients, just +like we recommend doing for Navigator 2.x clients due to other bugs. +However, non-persistent connections increase the total number of +connections needed per client and slow retrieval of an image-laden +web page. Since non-persistent connections have their own resource +consumptions and a short waiting period after each closure, a busy server +may need persistence in order to best serve its clients.

    + +As far as we know, the client-caused FIN_WAIT_2 problem is present for +all servers that support persistent connections, including Apache 1.1.x +and 1.2.

    + +

    A necessary bit of code introduced in 1.2

    + +While the above bug is a problem, it is not the whole problem. +Some users have observed no FIN_WAIT_2 problems with Apache 1.1.x, +but with 1.2b enough connections build up in the FIN_WAIT_2 state to +crash their server. + +The most likely source for additional FIN_WAIT_2 states +is a function called lingering_close() which was added +between 1.1 and 1.2. This function is necessary for the proper +handling of persistent connections and any request which includes +content in the message body (e.g., PUTs and POSTs). +What it does is read any data sent by the client for +a certain time after the server closes the connection. The exact +reasons for doing this are somewhat complicated, but involve what +happens if the client is making a request at the same time the +server sends a response and closes the connection. Without lingering, +the client might be forced to reset its TCP input buffer before it +has a chance to read the server's response, and thus understand why +the connection has closed. +See the appendix for more details.

    + +The code in lingering_close() appears to cause problems +for a number of factors, including the change in traffic patterns +that it causes. The code has been thoroughly reviewed and we are +not aware of any bugs in it. It is possible that there is some +problem in the BSD TCP stack, aside from the lack of a timeout +for the FIN_WAIT_2 state, exposed by the lingering_close +code that causes the observed problems.

    + +

  3. What can I do about it?
  4. + +There are several possible workarounds to the problem, some of +which work better than others.

    + +

    Add a timeout for FIN_WAIT_2

    + +The obvious workaround is to simply have a timeout for the FIN_WAIT_2 state. +This is not specified by the RFC, and could be claimed to be a +violation of the RFC, but it is widely recognized as being necessary. +The following systems are known to have a timeout: +

    +

      +
    • FreeBSD versions starting at + 2.0 or possibly earlier. +
    • NetBSD version 1.2(?) +
    • OpenBSD all versions(?) +
    • BSD/OS 2.1, with the + + K210-027 patch installed. +
    • Solaris as of around version + 2.2. The timeout can be tuned by using ndd to + modify tcp_fin_wait_2_flush_interval, but the + default should be appropriate for most servers and improper + tuning can have negative impacts. +
    • Linux 2.0.x and + earlier(?) +
    • HP-UX 10.x defaults to + terminating connections in the FIN_WAIT_2 state after the + normal keepalive timeouts. This does not + refer to the persistent connection or HTTP keepalive + timeouts, but the SO_LINGER socket option + which is enabled by Apache. This parameter can be adjusted + by using nettune to modify parameters such as + tcp_keepstart and tcp_keepstop. + In later revisions, there is an explicit timer for + connections in FIN_WAIT_2 that can be modified; contact HP + support for details. +
    • SGI IRIX can be patched to + support a timeout. For IRIX 5.3, 6.2, and 6.3, + use patches 1654, 1703 and 1778 respectively. If you + have trouble locating these patches, please contact your + SGI support channel for help. +
    • NCR's MP RAS Unix 2.xx and + 3.xx both have FIN_WAIT_2 timeouts. In 2.xx it is non-tunable + at 600 seconds, while in 3.xx it defaults to 600 seconds and + is calculated based on the tunable "max keep alive probes" + (default of 8) multiplied by the "keep alive interval" (default + 75 seconds). +
    • Sequent's ptx/TCP/IP for + DYNIX/ptx has had a FIN_WAIT_2 timeout since around + release 4.1 in mid-1994. +
    +

    +The following systems are known to not have a timeout: +

    +

      +
    • SunOS 4.x does not and + almost certainly never will have one because it as at the + very end of its development cycle for Sun. If you have kernel + source should be easy to patch. +
    +

    +There is a +patch available for adding a timeout to the FIN_WAIT_2 state; it +was originally intended for BSD/OS, but should be adaptable to most +systems using BSD networking code. You need kernel source code to be +able to use it. If you do adapt it to work for any other systems, +please drop me a note at marc@apache.org. +

    +

    Compile without using lingering_close()

    + +It is possible to compile Apache 1.2 without using the +lingering_close() function. This will result in that +section of code being similar to that which was in 1.1. If you do +this, be aware that it can cause problems with PUTs, POSTs and +persistent connections, especially if the client uses pipelining. +That said, it is no worse than on 1.1, and we understand that keeping your +server running is quite important.

    + +To compile without the lingering_close() function, add +-DNO_LINGCLOSE to the end of the +EXTRA_CFLAGS line in your Configuration file, +rerun Configure and rebuild the server. +

    +

    Use SO_LINGER as an alternative to +lingering_close()

    + +On most systems, there is an option called SO_LINGER that +can be set with setsockopt(2). It does something very +similar to lingering_close(), except that it is broken +on many systems so that it causes far more problems than +lingering_close. On some systems, it could possibly work +better so it may be worth a try if you have no other alternatives.

    + +To try it, add -DUSE_SO_LINGER -DNO_LINGCLOSE to the end of the +EXTRA_CFLAGS line in your Configuration +file, rerun Configure and rebuild the server.

    + +NOTE: Attempting to use SO_LINGER and +lingering_close() at the same time is very likely to do +very bad things, so don't.

    + +

    Increase the amount of memory used for storing connection state

    +
    +
    BSD based networking code: +
    BSD stores network data, such as connection states, +in something called an mbuf. When you get so many connections +that the kernel does not have enough mbufs to put them all in, your +kernel will likely crash. You can reduce the effects of the problem +by increasing the number of mbufs that are available; this will not +prevent the problem, it will just make the server go longer before +crashing.

    + +The exact way to increase them may depend on your OS; look +for some reference to the number of "mbufs" or "mbuf clusters". On +many systems, this can be done by adding the line +NMBCLUSTERS="n", where n is the number of +mbuf clusters you want to your kernel config file and rebuilding your +kernel.

    +

    + +

    Disable KeepAlive

    +

    If you are unable to do any of the above then you should, as a last +resort, disable KeepAlive. Edit your httpd.conf and change "KeepAlive On" +to "KeepAlive Off". + +

  5. Feedback
  6. + +If you have any information to add to this page, please contact me at +marc@apache.org.

    + +

  7. Appendix
  8. +

    +Below is a message from Roy Fielding, one of the authors of HTTP/1.1. + +

    Why the lingering close functionality is necessary with HTTP

    + +The need for a server to linger on a socket after a close is noted a couple +times in the HTTP specs, but not explained. This explanation is based on +discussions between myself, Henrik Frystyk, Robert S. Thau, Dave Raggett, +and John C. Mallery in the hallways of MIT while I was at W3C.

    + +If a server closes the input side of the connection while the client +is sending data (or is planning to send data), then the server's TCP +stack will signal an RST (reset) back to the client. Upon +receipt of the RST, the client will flush its own incoming TCP buffer +back to the un-ACKed packet indicated by the RST packet argument. +If the server has sent a message, usually an error response, to the +client just before the close, and the client receives the RST packet +before its application code has read the error message from its incoming +TCP buffer and before the server has received the ACK sent by the client +upon receipt of that buffer, then the RST will flush the error message +before the client application has a chance to see it. The result is +that the client is left thinking that the connection failed for no +apparent reason.

    + +There are two conditions under which this is likely to occur: +

      +
    1. sending POST or PUT data without proper authorization +
    2. sending multiple requests before each response (pipelining) + and one of the middle requests resulting in an error or + other break-the-connection result. +
    +

    +The solution in all cases is to send the response, close only the +write half of the connection (what shutdown is supposed to do), and +continue reading on the socket until it is either closed by the +client (signifying it has finally read the response) or a timeout occurs. +That is what the kernel is supposed to do if SO_LINGER is set. +Unfortunately, SO_LINGER has no effect on some systems; on some other +systems, it does not have its own timeout and thus the TCP memory +segments just pile-up until the next reboot (planned or not).

    + +Please note that simply removing the linger code will not solve the +problem -- it only moves it to a different and much harder one to detect. +

+ + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/footer.html b/APACHE_1_3b7/htdocs/manual/misc/footer.html new file mode 100644 index 0000000000..7fe745dcfd --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/footer.html @@ -0,0 +1,8 @@ +
+ +

+ Apache HTTP Server Version 1.3 +

+ +Index +Home diff --git a/APACHE_1_3b7/htdocs/manual/misc/header.html b/APACHE_1_3b7/htdocs/manual/misc/header.html new file mode 100644 index 0000000000..5662300029 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/header.html @@ -0,0 +1,6 @@ +
+ [APACHE DOCUMENTATION] +

+ Apache HTTP Server Version 1.3 +

+
diff --git a/APACHE_1_3b7/htdocs/manual/misc/howto.html b/APACHE_1_3b7/htdocs/manual/misc/howto.html new file mode 100644 index 0000000000..e2995c2473 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/howto.html @@ -0,0 +1,164 @@ + + + + + +Apache HOWTO documentation + + + + + +

Apache HOWTO documentation

+ +How to: + + +
+

How to redirect an entire server or directory to a +single URL

+ +

There are two chief ways to redirect all requests for an entire +server to a single location: one which requires the use of +mod_rewrite, and another which uses a CGI script. + +

First: if all you need to do is migrate a server from one name to +another, simply use the Redirect directive, as supplied +by mod_alias: + +

+  Redirect / http://www.apache.org/
+
+ +

Since Redirect will forward along the complete path, +however, it may not be appropriate - for example, when the directory +structure has changed after the move, and you simply want to direct people +to the home page. + +

The best option is to use the standard Apache module +mod_rewrite. +If that module is compiled in, the following lines + +

RewriteEngine On
+RewriteRule /.* http://www.apache.org/ [R]
+
+ +This will send an HTTP 302 Redirect back to the client, and no matter +what they gave in the original URL, they'll be sent to +"http://www.apache.org". + +The second option is to set up a ScriptAlias pointing to +a cgi script which outputs a 301 or 302 status and the +location +of the other server.

+ +

By using a cgi-script you can intercept various requests +and +treat them specially, e.g. you might want to intercept POST +requests, so that the client isn't redirected to a script on the other +server which expects POST information (a redirect will lose the POST +information.) You might also want to use a CGI script if you don't +want to compile mod_rewrite into your server. + +

Here's how to redirect all requests to a script... In the server +configuration file, +

ScriptAlias / /usr/local/httpd/cgi-bin/redirect_script
+
+ +and here's a simple perl script to redirect requests: + +
+#!/usr/local/bin/perl
+
+print "Status: 302 Moved Temporarily\r
+Location: http://www.some.where.else.com/\r\n\r\n";
+
+

+ +
+ +

How to reset your log files

+ +

Sooner or later, you'll want to reset your log files (access_log and +error_log) because they are too big, or full of old information you don't +need.

+ +

access.log typically grows by 1Mb for each 10,000 requests.

+ +

Most people's first attempt at replacing the logfile is to just move the +logfile or remove the logfile. This doesn't work.

+ +

Apache will continue writing to the logfile at the same offset as before the +logfile moved. This results in a new logfile being created which is just +as big as the old one, but it now contains thousands (or millions) of null +characters.

+ +

The correct procedure is to move the logfile, then signal Apache to tell +it to reopen the logfiles.

+ +

Apache is signaled using the SIGHUP (-1) signal. e.g. +

+mv access_log access_log.old
+kill -1 `cat httpd.pid` +
+

+ +

Note: httpd.pid is a file containing the +process id +of the Apache httpd daemon, Apache saves this in the same directory as the log +files.

+ +

Many people use this method to replace (and backup) their logfiles on a +nightly or weekly basis.

+
+ +

How to stop or restrict robots

+ +

Ever wondered why so many clients are interested in a file called +robots.txt which you don't have, and never did have?

+ +

These clients are called robots (also known as crawlers, +spiders and other cute name) - special automated clients which +wander around the web looking for interesting resources.

+ +

Most robots are used to generate some kind of web index which +is then used by a search engine to help locate information.

+ +

robots.txt provides a means to request that robots limit their +activities at the site, or more often than not, to leave the site alone.

+ +

When the first robots were developed, they had a bad reputation for +sending hundreds/thousands of requests to each site, often resulting +in the site being overloaded. Things have improved dramatically since +then, thanks to +Guidelines for Robot Writers, but even so, some robots may exhibit +unfriendly behavior which the webmaster isn't willing to tolerate, and +will want to stop.

+ +

Another reason some webmasters want to block access to robots, is to +stop them indexing dynamic information. Many search engines will use the +data collected from your pages for months to come - not much use if your +serving stock quotes, news, weather reports or anything else that will be +stale by the time people find it in a search engine.

+ +

If you decide to exclude robots completely, or just limit the areas +in which they can roam, create a robots.txt file; refer +to the robot information pages provided by Martijn Koster for the syntax.

+ + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/index.html b/APACHE_1_3b7/htdocs/manual/misc/index.html new file mode 100755 index 0000000000..579d254bcb --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/index.html @@ -0,0 +1,138 @@ + + + + Apache Miscellaneous Documentation + + + + + +

Apache Miscellaneous Documentation

+ +

+ Below is a list of additional documentation pages that apply to the + Apache web server development project. +

+
+
API +
+
Description of Apache's Application Programming Interface. +
+
FAQ +
+
Frequently-Asked Questions concerning the Apache project and server. +
+
Reading Client Input in Apache 1.2 +
+
Describes differences between Apache 1.1 and 1.2 in how modules + read information from the client. +
+
Compatibility with NCSA +
+
Notes about Apache's compatibility with the NCSA server. +
+
FIN_WAIT_2 +
+
A description of the causes of Apache processes going into the + FIN_WAIT_2 state, and what you can do about it. +
+
"How-To" +
+
Instructions about how to accomplish some commonly-desired server + functionality changes. +
+
HTTP Features list
+
A tab-separate table of HTTP features implemented and tested in Apache. +
+
Known Client Problems +
+
A list of problems in HTTP clients which can be mitigated by Apache. +
+
No PGP +
+
Why we took PEM and PGP support out of the base Apache distribution. +
+
Performance Notes (BSD 4.4) +
+
Some notes about ways to improve/optimize Apache performance on + BSD 4.4 systems. +
+
Performance Notes (Digital UNIX) +
+
Extracts of USENET postings describing how to optimize Apache + performance on Digital UNIX systems. +
+
Performance Notes (HPUX) +
+
Email from an HP engineer on how to optimize HP-UX 10.20. +
+
Performance Notes (General) +
+
Some generic notes about how to improve the performance of your + machine/OS. +
+
Performance Notes -- Apache Tuning +
+
Notes about how to (run-time and compile-time) configure + Apache for highest performance. Notes explaining why Apache does + some things, and why it doesn't do other things (which make it + slower/faster). +
+
Security Tips +
+
Some "do"s - and "don't"s - for keeping your + Apache web site secure. +
+
Virtual Hosts (IP-based) +
+
Excerpts and notes about configuring and using Apache IP-based virtual + hosts. +
+
Windows Bug with Web Keepalive +
+
A brief description of a known problem with Microsoft Windows and + web sites accessed using keepalive connections. +
+
+ + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/known_client_problems.html b/APACHE_1_3b7/htdocs/manual/misc/known_client_problems.html new file mode 100644 index 0000000000..63336e8a65 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/known_client_problems.html @@ -0,0 +1,250 @@ + + + +Apache HTTP Server Project + + + + + +

Known Problems in Clients

+ +

Over time the Apache Group has discovered or been notified of problems +with various clients which we have had to work around. This document +describes these problems and the workarounds available. It's not arranged +in any particular order. Some familiarity with the standards is assumed, +but not necessary. + +

For brevity, Navigator will refer to Netscape's Navigator +product, and MSIE will refer to Microsoft's Internet Explorer +product. All trademarks and copyrights belong to their respective +companies. We welcome input from the various client authors to correct +inconsistencies in this paper, or to provide us with exact version +numbers where things are broken/fixed. + +

For reference, +RFC1945 +defines HTTP/1.0, and +RFC2068 +defines HTTP/1.1. Apache as of version 1.2 is an HTTP/1.1 server (with an +optional HTTP/1.0 proxy). + +

Various of these workarounds are triggered by environment variables. +The admin typically controls which are set, and for which clients, by using +mod_browser. Unless otherwise +noted all of these workarounds exist in versions 1.2 and later. + +

Trailing CRLF on POSTs

+ +

This is a legacy issue. The CERN webserver required POST +data to have an extra CRLF following it. Thus many +clients send an extra CRLF that +is not included in the Content-Length of the request. +Apache works around this problem by eating any empty lines which +appear before a request. + +

Broken keepalive

+ +

Various clients have had broken implementations of keepalive +(persistent connections). In particular the Windows versions of +Navigator 2.0 get very confused when the server times out an +idle connection. The workaround is present in the default config files: +

+BrowserMatch Mozilla/2 nokeepalive +
+Note that this matches some earlier versions of MSIE, which began the +practice of calling themselves Mozilla in their user-agent +strings just like Navigator. + +

MSIE 4.0b2, which claims to support HTTP/1.1, does not properly +support keepalive when it is used on 301 or 302 (redirect) +responses. Unfortunately Apache's nokeepalive code +prior to 1.2.2 would not work with HTTP/1.1 clients. You must apply +this patch to version 1.2.1. Then add this to your config: +

+BrowserMatch "MSIE 4\.0b2;" nokeepalive +
+ +

Incorrect interpretation of +HTTP/1.1 in response

+ +

To quote from section 3.1 of RFC1945: +

+HTTP uses a "<MAJOR>.<MINOR>" numbering scheme to indicate versions +of the protocol. The protocol versioning policy is intended to allow +the sender to indicate the format of a message and its capacity for +understanding further HTTP communication, rather than the features +obtained via that communication. +
+Since Apache is an HTTP/1.1 server, it indicates so as part of its +response. Many client authors mistakenly treat this part of the response +as an indication of the protocol that the response is in, and then refuse +to accept the response. + +

The first major indication of this problem was with AOL's proxy servers. +When Apache 1.2 went into beta it was the first wide-spread HTTP/1.1 +server. After some discussion, AOL fixed their proxies. In +anticipation of similar problems, the force-response-1.0 +environment variable was added to Apache. When present Apache will +indicate "HTTP/1.0" in response to an HTTP/1.0 client, +but will not in any other way change the response. + +

The pre-1.1 Java Development Kit (JDK) that is used in many clients +(including Navigator 3.x and MSIE 3.x) exhibits this problem. As do some +of the early pre-releases of the 1.1 JDK. We think it is fixed in the +1.1 JDK release. In any event the workaround: +

+BrowserMatch Java/1.0 force-response-1.0
+BrowserMatch JDK/1.0 force-response-1.0 +
+ +

RealPlayer 4.0 from Progressive Networks also exhibits this problem. +However they have fixed it in version 4.01 of the player, but version +4.01 uses the same User-Agent as version 4.0. The +workaround is still: +

+BrowserMatch "RealPlayer 4.0" force-response-1.0 +
+ +

Requests use HTTP/1.1 but responses must be +in HTTP/1.0

+ +

MSIE 4.0b2 has this problem. Its Java VM makes requests in HTTP/1.1 +format but the responses must be in HTTP/1.0 format (in particular, it +does not understand chunked responses). The workaround +is to fool Apache into believing the request came in HTTP/1.0 format. +

+BrowserMatch "MSIE 4\.0b2;" downgrade-1.0 force-response-1.0 +
+This workaround is available in 1.2.2, and in a +patch against 1.2.1. + +

Boundary problems with header parsing

+ +

All versions of Navigator from 2.0 through 4.0b2 (and possibly later) +have a problem if the trailing CRLF of the response header starts at +offset 256, 257 or 258 of the response. A BrowserMatch for this would +match on nearly every hit, so the workaround is enabled automatically +on all responses. The workaround is to detect when this condition would +occur in a response and add extra padding to the header to push the +trailing CRLF past offset 258 of the response. + +

Multipart responses and Quoted Boundary +Strings

+ +

On multipart responses some clients will not accept quotes (") +around the boundary string. The MIME standard recommends that +such quotes be used. But the clients were probably written based +on one of the examples in RFC2068, which does not include quotes. +Apache does not include quotes on its boundary strings to workaround +this problem. + +

Byterange requests

+ +

A byterange request is used when the client wishes to retrieve a +portion of an object, not necessarily the entire object. There +was a very old draft which included these byteranges in the URL. +Old clients such as Navigator 2.0b1 and MSIE 3.0 for the MAC +exhibit this behaviour, and +it will appear in the servers' access logs as (failed) attempts to +retrieve a URL with a trailing ";xxx-yyy". Apache does not attempt +to implement this at all. + +

A subsequent draft of this standard defines a header +Request-Range, and a response type +multipart/x-byteranges. The HTTP/1.1 standard includes +this draft with a few fixes, and it defines the header +Range and type multipart/byteranges. + +

Navigator (versions 2 and 3) sends both Range and +Request-Range headers (with the same value), but does not +accept a multipart/byteranges response. The response must +be multipart/x-byteranges. As a workaround, if Apache +receives a Request-Range header it considers it "higher +priority" than a Range header and in response uses +multipart/x-byteranges. + +

The Adobe Acrobat Reader plugin makes extensive use of byteranges and +prior to version 3.01 supports only the multipart/x-byterange +response. Unfortunately there is no clue that it is the plugin +making the request. If the plugin is used with Navigator, the above +workaround works fine. But if the plugin is used with MSIE 3 (on +Windows) the workaround won't work because MSIE 3 doesn't give the +Range-Request clue that Navigator does. To workaround this, +Apache special cases "MSIE 3" in the User-Agent and serves +multipart/x-byteranges. Note that the necessity for this +with MSIE 3 is actually due to the Acrobat plugin, not due to the browser. + +

Netscape Communicator appears to not issue the non-standard +Request-Range header. When an Acrobat plugin prior to +version 3.01 is used with it, it will not properly understand byteranges. +The user must upgrade their Acrobat reader to 3.01. + +

Set-Cookie header is +unmergeable

+ +

The HTTP specifications say that it is legal to merge headers with +duplicate names into one (separated by semicolon). Some browsers +that support Cookies don't like merged headers and prefer that each +Set-Cookie header is sent separately. When parsing the +headers returned by a CGI, Apache will explicitly avoid merging any +Set-Cookie headers. + +

Expires headers and GIF89A +animations

+ +

Navigator versions 2 through 4 will erroneously re-request +GIF89A animations on each loop of the animation if the first +response included an Expires header. This happens +regardless of how far in the future the expiry time is set. There +is no workaround supplied with Apache, however there are hacks for 1.2 +and for 1.3. + +

POST without +Content-Length

+ +

In certain situations Navigator 3.01 through 3.03 appear to incorrectly +issue a POST without the request body. There is no +known workaround. It has been fixed in Navigator 3.04, Netscapes +provides some +information. +There's also + +some information about the actual problem. + +

JDK 1.2 betas lose parts of responses.

+ +

The http client in the JDK1.2beta2 and beta3 will throw away the first part of +the response body when both the headers and the first part of the body are sent +in the same network packet AND keep-alive's are being used. If either condition +is not met then it works fine. + +

See also Bug-ID's 4124329 and 4125538 at the java developer connection. + +

If you are seeing this bug yourself, you can add the following BrowserMatch +directive to work around it: + +

+BrowserMatch "Java1\.2beta[23]" nokeepalive +
+ +

We don't advocate this though since bending over backwards for beta software +is usually not a good idea; ideally it gets fixed, new betas or a final release +comes out, and no one uses the broken old software anymore. In theory. + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/nopgp.html b/APACHE_1_3b7/htdocs/manual/misc/nopgp.html new file mode 100644 index 0000000000..c372c14070 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/nopgp.html @@ -0,0 +1,90 @@ + + + +Why We Took PEM Out of Apache + + + + + +

Why We Took PEM Out of Apache

+ +On May 17th, 1995, we were asked by a representative of NCSA to remove +any copies of NCSA httpd prior to 1.4.1 from our web site. They +were mandated by the NSA to inform us that redistribution of pre-1.4.1 +code violated the same laws that make distributing Phill Zimmerman's +PGP package to other countries illegal. There was no +encryption in NCSA's httpd, only hooks to publicly available libraries +of PEM code. By the NSA's rules, even hooks to this type of +application is illegal. + +

+ +Because Apache is based on NCSA code, and we had basically not touched +that part of the software, we were informed that Apache was also +illegal to distribute to foreign countries, and advised (not mandated) +by NCSA to remove it. So, we removed both the copies of the NCSA +httpd we had, and all versions of Apache previous to 0.6.5. + +

+ +The Apache members are strong advocates of the right to digital +privacy, so the decision to submit to the NSA and remove the code was +not an easy one. Here are some elements in our rationale: + +

    + +
  • The PEM code in httpd was not widely used. No major site relied +upon its use, so its loss is not a blow to encryption and security on +the world wide web. There are other efforts designed to give much +more flexible security - SSL and SHTTP - so this wasn't a function +whose absence would really be missed on a functional level. + +
  • We didn't feel like being just a couple more martyrs in a fight +being fought very well by many other people. Rather than have the +machine that supports the project confiscated or relocated to South +Africa, etc., we think there are more efficient methods to address the +issue. + +
+ +It kind of sickens us that we had to do it, but so be it. + +

+ +Patches that re-implement the PEM code may be available at a foreign +site soon. If it does show up, we'll point to it - that can't be illegal! + +

+ +Finally, here is a compendium of pointers to sites related to +encryption and export law. We can't promise this list will be up to +date, so send us mail when you see a problem or want a link added. +Thanks. + +

+ +Brian, +brian@hyperreal.com + + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/perf-bsd44.html b/APACHE_1_3b7/htdocs/manual/misc/perf-bsd44.html new file mode 100644 index 0000000000..4d60f4b887 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/perf-bsd44.html @@ -0,0 +1,238 @@ + + + +Running a High-Performance Web Server for BSD + + + + + + + +

Running a High-Performance Web Server for BSD

+ +Like other OS's, the listen queue is often the first limit +hit. The +following are comments from "Aaron Gifford <agifford@InfoWest.COM>" +on how to fix this on BSDI 1.x, 2.x, and FreeBSD 2.0 (and earlier): + +

+ +Edit the following two files: +

/usr/include/sys/socket.h
+ /usr/src/sys/sys/socket.h
+In each file, look for the following: +
+    /*
+     * Maximum queue length specifiable by listen.
+     */
+    #define SOMAXCONN       5
+
+ +Just change the "5" to whatever appears to work. I bumped the two +machines I was having problems with up to 32 and haven't noticed the +problem since. + +

+ +After the edit, recompile the kernel and recompile the Apache server +then reboot. + +

+ +FreeBSD 2.1 seems to be perfectly happy, with SOMAXCONN +set to 32 already. + +

+ + +Addendum for very heavily loaded BSD servers
+
+from Chuck Murcko <chuck@telebase.com> + +

+ +If you're running a really busy BSD Apache server, the following are useful +things to do if the system is acting sluggish:

+ +

    + +
  • Run vmstat to check memory usage, page/swap rates, etc. + +
  • Run netstat -m to check mbuf usage + +
  • Run fstat to check file descriptor usage + +
+ +These utilities give you an idea what you'll need to tune in your kernel, +and whether it'll help to buy more RAM. + +Here are some BSD kernel config parameters (actually BSDI, but pertinent to +FreeBSD and other 4.4-lite derivatives) from a system getting heavy usage. +The tools mentioned above were used, and the system memory was increased to +48 MB before these tuneups. Other system parameters remained unchanged. + +

+ +

+maxusers        256
+
+ +Maxusers drives a lot of other kernel parameters: + +
    + +
  • Maximum # of processes + +
  • Maximum # of processes per user + +
  • System wide open files limit + +
  • Per-process open files limit + +
  • Maximum # of mbuf clusters + +
  • Proc/pgrp hash table size + +
+ +The actual formulae for these derived parameters are in +/usr/src/sys/conf/param.c. +These calculated parameters can also be overridden (in part) by specifying +your own values in the kernel configuration file: + +
+# Network options. NMBCLUSTERS defines the number of mbuf clusters and
+# defaults to 256. This machine is a server that handles lots of traffic,
+# so we crank that value.
+options         SOMAXCONN=256           # max pending connects
+options         NMBCLUSTERS=4096        # mbuf clusters at 4096
+
+#
+# Misc. options
+#
+options         CHILD_MAX=512           # maximum number of child processes
+options         OPEN_MAX=512            # maximum fds (breaks RPC svcs)
+
+ +SOMAXCONN is not derived from maxusers, so you'll always need to increase +that yourself. We used a value guaranteed to be larger than Apache's +default for the listen() of 128, currently. + +

+ +In many cases, NMBCLUSTERS must be set much larger than would appear +necessary at first glance. The reason for this is that if the browser +disconnects in mid-transfer, the socket fd associated with that particular +connection ends up in the TIME_WAIT state for several minutes, during +which time its mbufs are not yet freed. Another reason is that, on server +timeouts, some connections end up in FIN_WAIT_2 state forever, because +this state doesn't time out on the server, and the browser never sent +a final FIN. For more details see the +FIN_WAIT_2 page. + +

+ +Some more info on mbuf clusters (from sys/mbuf.h): +

+/*
+ * Mbufs are of a single size, MSIZE (machine/machparam.h), which
+ * includes overhead.  An mbuf may add a single "mbuf cluster" of size
+ * MCLBYTES (also in machine/machparam.h), which has no additional overhead
+ * and is used instead of the internal data area; this is done when
+ * at least MINCLSIZE of data must be stored.
+ */
+
+ +

+ +CHILD_MAX and OPEN_MAX are set to allow up to 512 child processes (different +than the maximum value for processes per user ID) and file descriptors. +These values may change for your particular configuration (a higher OPEN_MAX +value if you've got modules or CGI scripts opening lots of connections or +files). If you've got a lot of other activity besides httpd on the same +machine, you'll have to set NPROC higher still. In this example, the NPROC +value derived from maxusers proved sufficient for our load. + +

+ +Caveats + +

+ +Be aware that your system may not boot with a kernel that is configured +to use more resources than you have available system RAM. +ALWAYS +have a known bootable kernel available when tuning your system this way, +and use the system tools beforehand to learn if you need to buy more +memory before tuning. + +

+ +RPC services will fail when the value of OPEN_MAX is larger than 256. +This is a function of the original implementations of the RPC library, +which used a byte value for holding file descriptors. BSDI has partially +addressed this limit in its 2.1 release, but a real fix may well await +the redesign of RPC itself. + +

+ +Finally, there's the hard limit of child processes configured in Apache. + +

+ +For versions of Apache later than 1.0.5 you'll need to change the +definition for HARD_SERVER_LIMIT in httpd.h and +recompile if you need to run more than the default 150 instances of httpd. + +

+ +From conf/httpd.conf-dist: + +

+# Limit on total number of servers running, i.e., limit on the number
+# of clients who can simultaneously connect --- if this limit is ever
+# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW.
+# It is intended mainly as a brake to keep a runaway server from taking
+# Unix with it as it spirals down...
+
+MaxClients 150
+
+ +Know what you're doing if you bump this value up, and make sure you've +done your system monitoring, RAM expansion, and kernel tuning beforehand. +Then you're ready to service some serious hits! + +

+ +Thanks to Tony Sanders and Chris Torek at BSDI for their +helpful suggestions and information. + +

+ +"M. Teterin" <mi@ALDAN.ziplink.net> writes:

+

It really does help if your kernel and frequently used utilities +are fully optimized. Rebuilding the FreeBSD kernel on an AMD-133 +(486-class CPU) web-server with
+ -m486 -fexpensive-optimizations -fomit-frame-pointer -O2
+helped reduce the number of "unable" errors, because the CPU was +often maxed out.
+

+ +


+ +

More welcome!

+ +If you have tips to contribute, send mail to +apache@apache.org + + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/perf-dec.html b/APACHE_1_3b7/htdocs/manual/misc/perf-dec.html new file mode 100644 index 0000000000..32245e0fbc --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/perf-dec.html @@ -0,0 +1,283 @@ + + + +Performance Tuning Tips for Digital Unix + + + + +

Performance Tuning Tips for Digital Unix

+ +Below is a set of newsgroup posts made by an engineer from DEC in +response to queries about how to modify DEC's Digital Unix OS for more +heavily loaded web sites. Copied with permission. + +
+ +

Update

+From: Jeffrey Mogul <mogul@pa.dec.com>
+Date: Fri, 28 Jun 96 16:07:56 MDT
+ +
    +
  1. The advice given in the README file regarding the + "tcbhashsize" variable is incorrect. The largest value + this should be set to is 1024. Setting it any higher + will have the perverse result of disabling the hashing + mechanism. + +
  2. Patch ID OSF350-146 has been superseded by +
    + Patch ID OSF350-195 for V3.2C
    + Patch ID OSF360-350195 for V3.2D +
    + Patch IDs for V3.2E and V3.2F should be available soon. + There is no known reason why the Patch ID OSF360-350195 + won't work on these releases, but such use is not officially + supported by Digital. This patch kit will not be needed for + V3.2G when it is released. +
+
+ + +
+From           mogul@pa.dec.com (Jeffrey Mogul)
+Organization   DEC Western Research
+Date           30 May 1996 00:50:25 GMT
+Newsgroups     comp.unix.osf.osf1
+Message-ID     <4oirch$bc8@usenet.pa.dec.com>
+Subject        Re: Web Site Performance
+References     1
+
+
+
+In article <skoogDs54BH.9pF@netcom.com> skoog@netcom.com (Jim Skoog) writes:
+>Where are the performance bottlenecks for Alpha AXP running the
+>Netscape Commerce Server 1.12 with high volume internet traffic?
+>We are evaluating network performance for a variety of Alpha AXP
+>runing DEC UNIX 3.2C, which run DEC's seal firewall and behind
+>that Alpha 1000 and 2100 webservers.
+
+Our experience (running such Web servers as altavista.digital.com
+and www.digital.com) is that there is one important kernel tuning
+knob to adjust in order to get good performance on V3.2C.  You
+need to patch the kernel global variable "somaxconn" (use dbx -k
+to do this) from its default value of 8 to something much larger.
+
+How much larger?  Well, no larger than 32767 (decimal).  And
+probably no less than about 2048, if you have a really high volume
+(millions of hits per day), like AltaVista does.
+
+This change allows the system to maintain more than 8 TCP
+connections in the SYN_RCVD state for the HTTP server.  (You
+can use "netstat -An |grep SYN_RCVD" to see how many such
+connections exist at any given instant).
+
+If you don't make this change, you might find that as the load gets
+high, some connection attempts take a very long time.  And if a lot
+of your clients disconnect from the Internet during the process of
+TCP connection establishment (this happens a lot with dialup
+users), these "embryonic" connections might tie up your somaxconn
+quota of SYN_RCVD-state connections.  Until the kernel times out
+these embryonic connections, no other connections will be accepted,
+and it will appear as if the server has died.
+
+The default value for somaxconn in Digital UNIX V4.0 will be quite
+a bit larger than it has been in previous versions (we inherited
+this default from 4.3BSD).
+
+Digital UNIX V4.0 includes some other performance-related changes
+that significantly improve its maximum HTTP connection rate.  However,
+we've been using V3.2C systems to front-end for altavista.digital.com
+with no obvious performance bottlenecks at the millions-of-hits-per-day
+level.
+
+We have some Webstone performance results available at
+        http://www.digital.com/info/alphaserver/news/webff.html
+I'm not sure if these were done using V4.0 or an earlier version
+of Digital UNIX, although I suspect they were done using a test
+version of V4.0.
+
+-Jeff
+
+
+ +---------------------------------------------------------------------------- + +From mogul@pa.dec.com (Jeffrey Mogul) +Organization DEC Western Research +Date 31 May 1996 21:01:01 GMT +Newsgroups comp.unix.osf.osf1 +Message-ID <4onmmd$mmd@usenet.pa.dec.com> +Subject Digital UNIX V3.2C Internet tuning patch info + +---------------------------------------------------------------------------- + +Something that probably few people are aware of is that Digital +has a patch kit available for Digital UNIX V3.2C that may improve +Internet performance, especially for busy web servers. + +This patch kit is one way to increase the value of somaxconn, +which I discussed in a message here a day or two ago. + +I've included in this message the revised README file for this +patch kit below. Note that the original README file in the patch +kit itself may be an earlier version; I'm told that the version +below is the right one. + +Sorry, this patch kit is NOT available for other versions of Digital +UNIX. Most (but not quite all) of these changes also made it into V4.0, +so the description of the various tuning parameters in this README +file might be useful to people running V4.0 systems. + +This patch kit does not appear to be available (yet?) from + http://www.service.digital.com/html/patch_service.html +so I guess you'll have to call Digital's Customer Support to get it. + +-Jeff + +DESCRIPTION: Digital UNIX Network tuning patch + + Patch ID: OSF350-146 + + SUPERSEDED PATCHES: OSF350-151, OSF350-158 + + This set of files improves the performance of the network + subsystem on a system being used as a web server. There are + additional tunable parameters included here, to be used + cautiously by an informed system administrator. + +TUNING + + To tune the web server, the number of simultaneous socket + connection requests are limited by: + + somaxconn Sets the maximum number of pending requests + allowed to wait on a listening socket. The + default value in Digital UNIX V3.2 is 8. + This patch kit increases the default to 1024, + which matches the value in Digital UNIX V4.0. + + sominconn Sets the minimum number of pending connections + allowed on a listening socket. When a user + process calls listen with a backlog less + than sominconn, the backlog will be set to + sominconn. sominconn overrides somaxconn. + The default value is 1. + + The effectiveness of tuning these parameters can be monitored by + the sobacklog variables available in the kernel: + + sobacklog_hiwat Tracks the maximum pending requests to any + socket. The initial value is 0. + + sobacklog_drops Tracks the number of drops exceeding the + socket set backlog limit. The initial + value is 0. + + somaxconn_drops Tracks the number of drops exceeding the + somaxconn limit. When sominconn is larger + than somaxconn, tracks the number of drops + exceeding sominconn. The initial value is 0. + + TCP timer parameters also affect performance. Tuning the following + require some knowledge of the characteristics of the network. + + tcp_msl Sets the tcp maximum segment lifetime. + This is the maximum lifetime in half + seconds that a packet can be in transit + on the network. This value, when doubled, + is the length of time a connection remains + in the TIME_WAIT state after a incoming + close request is processed. The unit is + specified in 1/2 seconds, the initial + value is 60. + + tcp_rexmit_interval_min + Sets the minimum TCP retransmit interval. + For some WAN networks the default value may + be too short, causing unnecessary duplicate + packets to be sent. The unit is specified + in 1/2 seconds, the initial value is 1. + + tcp_keepinit This is the amount of time a partially + established connection will sit on the listen + queue before timing out (e.g. if a client + sends a SYN but never answers our SYN/ACK). + Partially established connections tie up slots + on the listen queue. If the queue starts to + fill with connections in SYN_RCVD state, + tcp_keepinit can be decreased to make those + partial connects time out sooner. This should + be used with caution, since there might be + legitimate clients that are taking a while + to respond to SYN/ACK. The unit is specified + in 1/2 seconds, the default value is 150 + (ie. 75 seconds). + + The hashlist size for the TCP inpcb lookup table is regulated by: + + tcbhashsize The number of hash buckets used for the + TCP connection table used in the kernel. + The initial value is 32. For best results, + should be specified as a power of 2. For + busy Web servers, set this to 2048 or more. + + The hashlist size for the interface alias table is regulated by: + + inifaddr_hsize The number of hash buckets used for the + interface alias table used in the kernel. + The initial value is 32. For best results, + should be specified as a power of 2. + + ipport_userreserved The maximum number of concurrent non-reserved, + dynamically allocated ports. Default range + is 1025-5000. The maximum value is 65535. + This limits the numer of times you can + simultaneously telnet or ftp out to connect + to other systems. + + tcpnodelack Don't delay acknowledging TCP data; this + can sometimes improve performance of locally + run CAD packages. Default is value is 0, + the enabled value is 1. + + Digital UNIX version: + + V3.2C +Feature V3.2C patch V4.0 +======= ===== ===== ==== +somaxconn X X X +sominconn - X X +sobacklog_hiwat - X - +sobacklog_drops - X - +somaxconn_drops - X - +tcpnodelack X X X +tcp_keepidle X X X +tcp_keepintvl X X X +tcp_keepcnt - X X +tcp_keepinit - X X +TCP keepalive per-socket - - X +tcp_msl - X - +tcp_rexmit_interval_min - X - +TCP inpcb hashing - X X +tcbhashsize - X X +interface alias hashing - X X +inifaddr_hsize - X X +ipport_userreserved - X - +sysconfig -q inet - - X +sysconfig -q socket - - X + +
+ + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/perf-hp.html b/APACHE_1_3b7/htdocs/manual/misc/perf-hp.html new file mode 100644 index 0000000000..13ed152e6a --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/perf-hp.html @@ -0,0 +1,118 @@ + + + +Running a High-Performance Web Server on HPUX + + + + +  + + +

Running a High-Performance Web Server for HPUX

+ +
+Date: Wed, 05 Nov 1997 16:59:34 -0800
+From: Rick Jones <raj@cup.hp.com>
+Reply-To: raj@cup.hp.com
+Organization: Network Performance
+Subject: HP-UX tuning tips
+
+ +Here are some tuning tips for HP-UX to add to the tuning page. + +

+ +For HP-UX 9.X: Upgrade to 10.20
+For HP-UX 10.[00|01|10]: Upgrade to 10.20 + +

+ +For HP-UX 10.20: + +

+ +Install the latest cumulative ARPA Transport Patch. This will allow you +to configure the size of the TCP connection lookup hash table. The +default is 256 buckets and must be set to a power of two. This is +accomplished with adb against the *disc* image of the kernel. The +variable name is tcp_hash_size. + +

+ +How to pick the value? Examine the output of + +ftp://ftp.cup.hp.com/dist/networking/tools/connhist and see how many +total TCP connections exist on the system. You probably want that number +divided by the hash table size to be reasonably small, say less than 10. +Folks can look at HP's SPECweb96 disclosures for some common settings. +These can be found at +http://www.specbench.org/. If an HP-UX system was +performing at 1000 SPECweb96 connections per second, the TIME_WAIT time +of 60 seconds would mean 60,000 TCP "connections" being tracked. + +

+ +Folks can check their listen queue depths with + +ftp://ftp.cup.hp.com/dist/networking/misc/listenq. + +

+ +If folks are running Apache on a PA-8000 based system, they should +consider "chatr'ing" the Apache executable to have a large page size. +This would be "chatr +pi L <BINARY>." The GID of the running executable +must have MLOCK privileges. Setprivgrp(1m) should be consulted for +assigning MLOCK. The change can be validated by running Glance and +examining the memory regions of the server(s) to make sure that they +show a non-trivial fraction of the text segment being locked. + +

+ +If folks are running Apache on MP systems, they might consider writing a +small program that uses mpctl() to bind processes to processors. A +simple pid % numcpu algorithm is probably sufficient. This might even go +into the source code. + +

+ +If folks are concerned about the number of FIN_WAIT_2 connections, they +can use nettune to shrink the value of tcp_keepstart. However, they +should be careful there - certainly do not make it less than oh two to +four minutes. If tcp_hash_size has been set well, it is probably OK to +let the FIN_WAIT_2's take longer to timeout (perhaps even the default +two hours) - they will not on average have a big impact on performance. + +

+ +There are other things that could go into the code base, but that might +be left for another email. Feel free to drop me a message if you or +others are interested. + +

+ +sincerely, + +

+ +rick jones
+ +http://www.cup.hp.com/netperf/NetperfPage.html + +


+ +

+ Apache HTTP Server Version 1.3 +

+ +Index +Home + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/perf-tuning.html b/APACHE_1_3b7/htdocs/manual/misc/perf-tuning.html new file mode 100644 index 0000000000..4cc53a9ad9 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/perf-tuning.html @@ -0,0 +1,871 @@ + + + + Apache Performance Notes + + + +

Apache Performance Notes

+ +

Author: Dean Gaudet + +

Introduction

+

Apache is a general webserver, which is designed to be correct first, and +fast second. Even so, it's performance is quite satisfactory. Most +sites have less than 10Mbits of outgoing bandwidth, which Apache can +fill using only a low end Pentium-based webserver. In practice sites +with more bandwidth require more than one machine to fill the bandwidth +due to other constraints (such as CGI or database transaction overhead). +For these reasons the development focus has been mostly on correctness +and configurability. + +

Unfortunately many folks overlook these facts and cite raw performance +numbers as if they are some indication of the quality of a web server +product. There is a bare minimum performance that is acceptable, beyond +that extra speed only caters to a much smaller segment of the market. +But in order to avoid this hurdle to the acceptance of Apache in some +markets, effort was put into Apache 1.3 to bring performance up to a +point where the difference with other high-end webservers is minimal. + +

Finally there are the folks who just plain want to see how fast something +can go. The author falls into this category. The rest of this document +is dedicated to these folks who want to squeeze every last bit of +performance out of Apache's current model, and want to understand why +it does some things which slow it down. + +

Note that this is tailored towards Apache 1.3 on Unix. Some of it applies +to Apache on NT. Apache on NT has not been tuned for performance yet, +in fact it probably performs very poorly because NT performance requires +a different programming model. + +

Hardware and Operating System Issues

+ +

The single biggest hardware issue affecting webserver performance +is RAM. A webserver should never ever have to swap, swapping increases +the latency of each request beyond a point that users consider "fast +enough". This causes users to hit stop and reload, further increasing +the load. You can, and should, control the MaxClients +setting so that your server does not spawn so many children it starts +swapping. + +

Beyond that the rest is mundane: get a fast enough CPU, a fast enough +network card, and fast enough disks, where "fast enough" is something +that needs to be determined by experimentation. + +

Operating system choice is largely a matter of local concerns. But +a general guideline is to always apply the latest vendor TCP/IP patches. +HTTP serving completely breaks many of the assumptions built into Unix +kernels up through 1994 and even 1995. Good choices include +recent FreeBSD, and Linux. + +

Run-Time Configuration Issues

+ +

HostnameLookups

+

Prior to Apache 1.3, HostnameLookups defaulted to On. +This adds latency +to every request because it requires a DNS lookup to complete before +the request is finished. In Apache 1.3 this setting defaults to Off. +However (1.3 or later), if you use any allow from domain or +deny from domain directives then you will pay for a +double reverse DNS lookup (a reverse, followed by a forward to make sure +that the reverse is not being spoofed). So for the highest performance +avoid using these directives (it's fine to use IP addresses rather than +domain names). + +

Note that it's possible to scope the directives, such as within +a <Location /server-status> section. In this +case the DNS lookups are only performed on requests matching the +criteria. Here's an example which disables +lookups except for .html and .cgi files: + +

+HostnameLookups off
+<Files ~ "\.(html|cgi)$>
+    HostnameLookups on
+</Files>
+
+ +But even still, if you just need DNS names +in some CGIs you could consider doing the +gethostbyname call in the specific CGIs that need it. + +

FollowSymLinks and SymLinksIfOwnerMatch

+

Wherever in your URL-space you do not have an +Options FollowSymLinks, or you do have an +Options SymLinksIfOwnerMatch Apache will have to +issue extra system calls to check up on symlinks. One extra call per +filename component. For example, if you had: + +

+DocumentRoot /www/htdocs
+<Directory />
+    Options SymLinksIfOwnerMatch
+</Directory>
+
+ +and a request is made for the URI /index.html. +Then Apache will perform lstat(2) on /www, +/www/htdocs, and /www/htdocs/index.html. The +results of these lstats are never cached, +so they will occur on every single request. If you really desire the +symlinks security checking you can do something like this: + +
+DocumentRoot /www/htdocs
+<Directory />
+    Options FollowSymLinks
+</Directory>
+<Directory /www/htdocs>
+    Options -FollowSymLinks +SymLinksIfOwnerMatch
+</Directory>
+
+ +This at least avoids the extra checks for the DocumentRoot +path. Note that you'll need to add similar sections if you have any +Alias or RewriteRule paths outside of your +document root. For highest performance, and no symlink protection, +set FollowSymLinks everywhere, and never set +SymLinksIfOwnerMatch. + +

AllowOverride

+ +

Wherever in your URL-space you allow overrides (typically +.htaccess files) Apache will attempt to open +.htaccess for each filename component. For example, + +

+DocumentRoot /www/htdocs
+<Directory />
+    AllowOverride all
+</Directory>
+
+ +and a request is made for the URI /index.html. Then +Apache will attempt to open /.htaccess, +/www/.htaccess, and /www/htdocs/.htaccess. +The solutions are similar to the previous case of Options +FollowSymLinks. For highest performance use +AllowOverride None everywhere in your filesystem. + +

Negotiation

+ +

If at all possible, avoid content-negotiation if you're really +interested in every last ounce of performance. In practice the +benefits of negotiation outweigh the performance penalties. There's +one case where you can speed up the server. Instead of using +a wildcard such as: + +

+DirectoryIndex index
+
+ +Use a complete list of options: + +
+DirectoryIndex index.cgi index.pl index.shtml index.html
+
+ +where you list the most common choice first. + +

Process Creation

+ +

Prior to Apache 1.3 the MinSpareServers, +MaxSpareServers, and StartServers settings +all had drastic effects on benchmark results. In particular, Apache +required a "ramp-up" period in order to reach a number of children +sufficient to serve the load being applied. After the initial +spawning of StartServers children, only one child per +second would be created to satisfy the MinSpareServers +setting. So a server being accessed by 100 simultaneous clients, +using the default StartServers of 5 would take on +the order 95 seconds to spawn enough children to handle the load. This +works fine in practice on real-life servers, because they aren't restarted +frequently. But does really poorly on benchmarks which might only run +for ten minutes. + +

The one-per-second rule was implemented in an effort to avoid +swamping the machine with the startup of new children. If the machine +is busy spawning children it can't service requests. But it has such +a drastic effect on the perceived performance of Apache that it had +to be replaced. As of Apache 1.3, +the code will relax the one-per-second rule. It +will spawn one, wait a second, then spawn two, wait a second, then spawn +four, and it will continue exponentially until it is spawning 32 children +per second. It will stop whenever it satisfies the +MinSpareServers setting. + +

This appears to be responsive enough that it's +almost unnecessary to twiddle the MinSpareServers, +MaxSpareServers and StartServers knobs. When +more than 4 children are spawned per second, a message will be emitted +to the ErrorLog. If you see a lot of these errors then +consider tuning these settings. Use the mod_status output +as a guide. + +

Related to process creation is process death induced by the +MaxRequestsPerChild setting. By default this is 30, which +is probably far too low unless your server is using a module such as +mod_perl which causes children to have bloated memory +images. If your server is serving mostly static pages then consider +raising this value to something like 10000. The code is robust enough +that this shouldn't be a problem. + +

When keep-alives are in use, children will be kept busy +doing nothing waiting for more requests on the already open +connection. The default KeepAliveTimeout of +15 seconds attempts to minimize this effect. The tradeoff +here is between network bandwidth and server resources. +In no event should you raise this above about 60 seconds, as +most of the benefits are lost. + +

Compile-Time Configuration Issues

+ +

mod_status and Rule STATUS=yes

+ +

If you include mod_status +and you also set Rule STATUS=yes when building +Apache, then on every request Apache will perform two calls to +gettimeofday(2) (or times(2) depending +on your operating system), and (pre-1.3) several extra calls to +time(2). This is all done so that the status report +contains timing indications. For highest performance, set Rule +STATUS=no. + +

accept Serialization - multiple sockets

+ +

This discusses a shortcoming in the Unix socket API. +Suppose your +web server uses multiple Listen statements to listen on +either multiple ports or multiple addresses. In order to test each +socket to see if a connection is ready Apache uses select(2). +select(2) indicates that a socket has zero or +at least one connection waiting on it. Apache's model includes +multiple children, and all the idle ones test for new connections at the +same time. A naive implementation looks something like this +(these examples do not match the code, they're contrived for +pedagogical purposes): + +

+    for (;;) {
+	for (;;) {
+	    fd_set accept_fds;
+
+	    FD_ZERO (&accept_fds);
+	    for (i = first_socket; i <= last_socket; ++i) {
+		FD_SET (i, &accept_fds);
+	    }
+	    rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
+	    if (rc < 1) continue;
+	    new_connection = -1;
+	    for (i = first_socket; i <= last_socket; ++i) {
+		if (FD_ISSET (i, &accept_fds)) {
+		    new_connection = accept (i, NULL, NULL);
+		    if (new_connection != -1) break;
+		}
+	    }
+	    if (new_connection != -1) break;
+	}
+	process the new_connection;
+    }
+
+ +But this naive implementation has a serious starvation problem. Recall +that multiple children execute this loop at the same time, and so multiple +children will block at select when they are in between +requests. All those blocked children will awaken and return from +select when a single request appears on any socket +(the number of children which awaken varies depending on the operating +system and timing issues). +They will all then fall down into the loop and try to accept +the connection. But only one will succeed (assuming there's still only +one connection ready), the rest will be blocked in +accept. +This effectively locks those children into serving requests from that +one socket and no other sockets, and they'll be stuck there until enough +new requests appear on that socket to wake them all up. +This starvation problem was first documented in +PR#467. There +are at least two solutions. + +

One solution is to make the sockets non-blocking. In this case the +accept won't block the children, and they will be allowed +to continue immediately. But this wastes CPU time. Suppose you have +ten idle children in select, and one connection arrives. +Then nine of those children will wake up, try to accept the +connection, fail, and loop back into select, accomplishing +nothing. Meanwhile none of those children are servicing requests that +occurred on other sockets until they get back up to the select +again. Overall this solution does not seem very fruitful unless you +have as many idle CPUs (in a multiprocessor box) as you have idle children, +not a very likely situation. + +

Another solution, the one used by Apache, is to serialize entry into +the inner loop. The loop looks like this (differences highlighted): + +

+    for (;;) {
+	accept_mutex_on ();
+	for (;;) {
+	    fd_set accept_fds;
+
+	    FD_ZERO (&accept_fds);
+	    for (i = first_socket; i <= last_socket; ++i) {
+		FD_SET (i, &accept_fds);
+	    }
+	    rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
+	    if (rc < 1) continue;
+	    new_connection = -1;
+	    for (i = first_socket; i <= last_socket; ++i) {
+		if (FD_ISSET (i, &accept_fds)) {
+		    new_connection = accept (i, NULL, NULL);
+		    if (new_connection != -1) break;
+		}
+	    }
+	    if (new_connection != -1) break;
+	}
+	accept_mutex_off ();
+	process the new_connection;
+    }
+
+ +The functions +accept_mutex_on and accept_mutex_off +implement a mutual exclusion semaphore. Only one child can have the +mutex at any time. There are several choices for implementing these +mutexes. The choice is defined in src/conf.h (pre-1.3) or +src/main/conf.h (1.3 or later). Some architectures +do not have any locking choice made, on these architectures it is unsafe +to use multiple Listen directives. + +
+
USE_FLOCK_SERIALIZED_ACCEPT +
This method uses the flock(2) system call to lock a +lock file (located by the LockFile directive). + +
USE_FCNTL_SERIALIZED_ACCEPT +
This method uses the fcntl(2) system call to lock a +lock file (located by the LockFile directive). + +
USE_SYSVSEM_SERIALIZED_ACCEPT +
(1.3 or later) This method uses SysV-style semaphores to implement the +mutex. Unfortunately SysV-style semaphores have some bad side-effects. +One is that it's possible Apache will die without cleaning up the semaphore +(see the ipcs(8) man page). The other is that the semaphore +API allows for a denial of service attack by any CGIs running under the +same uid as the webserver (i.e. all CGIs unless you use something +like suexec or cgiwrapper). For these reasons this method is not used +on any architecture except IRIX (where the previous two are prohibitively +expensive on most IRIX boxes). + +
USE_USLOCK_SERIALIZED_ACCEPT +
(1.3 or later) This method is only available on IRIX, and uses +usconfig(2) to create a mutex. While this method avoids +the hassles of SysV-style semaphores, it is not the default for IRIX. +This is because on single processor IRIX boxes (5.3 or 6.2) the +uslock code is two orders of magnitude slower than the SysV-semaphore +code. On multi-processor IRIX boxes the uslock code is an order of magnitude +faster than the SysV-semaphore code. Kind of a messed up situation. +So if you're using a multiprocessor IRIX box then you should rebuild your +webserver with -DUSE_USLOCK_SERIALIZED_ACCEPT on the +EXTRA_CFLAGS. + +
USE_PTHREAD_SERIALIZED_ACCEPT +
(1.3 or later) This method uses POSIX mutexes and should work on +any architecture implementing the full POSIX threads specification, +however appears to only work on Solaris (2.5 or later), and even then +only in certain configurations. If you experiment with this you should +watch out for your server hanging and not responding. Static content +only servers may work just fine. +
+ +

If your system has another method of serialization which isn't in the +above list then it may be worthwhile adding code for it (and submitting +a patch back to Apache). + +

Another solution that has been considered but never implemented is +to partially serialize the loop -- that is, let in a certain number +of processes. This would only be of interest on multiprocessor boxes +where it's possible multiple children could run simultaneously, and the +serialization actually doesn't take advantage of the full bandwidth. +This is a possible area of future investigation, but priority remains +low because highly parallel web servers are not the norm. + +

Ideally you should run servers without multiple Listen +statements if you want the highest performance. But read on. + +

accept Serialization - single socket

+ +

The above is fine and dandy for multiple socket servers, but what +about single socket servers? In theory they shouldn't experience +any of these same problems because all children can just block in +accept(2) until a connection arrives, and no starvation +results. In practice this hides almost the same "spinning" behaviour +discussed above in the non-blocking solution. The way that most TCP +stacks are implemented, the kernel actually wakes up all processes blocked +in accept when a single connection arrives. One of those +processes gets the connection and returns to user-space, the rest spin in +the kernel and go back to sleep when they discover there's no connection +for them. This spinning is hidden from the user-land code, but it's +there nonetheless. This can result in the same load-spiking wasteful +behaviour that a non-blocking solution to the multiple sockets case can. + +

For this reason we have found that many architectures behave more +"nicely" if we serialize even the single socket case. So this is +actually the default in almost all cases. Crude experiments under +Linux (2.0.30 on a dual Pentium pro 166 w/128Mb RAM) have shown that +the serialization of the single socket case causes less than a 3% +decrease in requests per second over unserialized single-socket. +But unserialized single-socket showed an extra 100ms latency on +each request. This latency is probably a wash on long haul lines, +and only an issue on LANs. If you want to override the single socket +serialization you can define SINGLE_LISTEN_UNSERIALIZED_ACCEPT +and then single-socket servers will not serialize at all. + +

Lingering Close

+ +

As discussed in +draft-ietf-http-connection-00.txt section 8, +in order for an HTTP server to reliably implement the protocol +it needs to shutdown each direction of the communication independently +(recall that a TCP connection is bi-directional, each half is independent +of the other). This fact is often overlooked by other servers, but +is correctly implemented in Apache as of 1.2. + +

When this feature was added to Apache it caused a flurry of +problems on various versions of Unix because of a shortsightedness. +The TCP specification does not state that the FIN_WAIT_2 state has a +timeout, but it doesn't prohibit it. On systems without the timeout, +Apache 1.2 induces many sockets stuck forever in the FIN_WAIT_2 state. +In many cases this can be avoided by simply upgrading to the latest +TCP/IP patches supplied by the vendor, in cases where the vendor has +never released patches (i.e. SunOS4 -- although folks with a source +license can patch it themselves) we have decided to disable this feature. + +

There are two ways of accomplishing this. One is the +socket option SO_LINGER. But as fate would have it, +this has never been implemented properly in most TCP/IP stacks. Even +on those stacks with a proper implementation (i.e. Linux 2.0.31) this +method proves to be more expensive (cputime) than the next solution. + +

For the most part, Apache implements this in a function called +lingering_close (in http_main.c). The +function looks roughly like this: + +

+    void lingering_close (int s)
+    {
+	char junk_buffer[2048];
+
+	/* shutdown the sending side */
+	shutdown (s, 1);
+
+	signal (SIGALRM, lingering_death);
+	alarm (30);
+
+	for (;;) {
+	    select (s for reading, 2 second timeout);
+	    if (error) break;
+	    if (s is ready for reading) {
+		read (s, junk_buffer, sizeof (junk_buffer));
+		/* just toss away whatever is here */
+	    }
+	}
+
+	close (s);
+    }
+
+ +This naturally adds some expense at the end of a connection, but it +is required for a reliable implementation. As HTTP/1.1 becomes more +prevalent, and all connections are persistent, this expense will be +amortized over more requests. If you want to play with fire and +disable this feature you can define NO_LINGCLOSE, but +this is not recommended at all. In particular, as HTTP/1.1 pipelined +persistent connections come into use lingering_close +is an absolute necessity (and + +pipelined connections are faster, so you +want to support them). + +

Scoreboard File

+ +

Apache's parent and children communicate with each other through +something called the scoreboard. Ideally this should be implemented +in shared memory. For those operating systems that we either have +access to, or have been given detailed ports for, it typically is +implemented using shared memory. The rest default to using an +on-disk file. The on-disk file is not only slow, but it is unreliable +(and less featured). Peruse the src/main/conf.h file +for your architecture and look for either USE_MMAP_SCOREBOARD or +USE_SHMGET_SCOREBOARD. Defining one of those two (as +well as their companions HAVE_MMAP and HAVE_SHMGET +respectively) enables the supplied shared memory code. If your system has +another type of shared memory, edit the file src/main/http_main.c +and add the hooks necessary to use it in Apache. (Send us back a patch +too please.) + +

Historical note: The Linux port of Apache didn't start to use +shared memory until version 1.2 of Apache. This oversight resulted +in really poor and unreliable behaviour of earlier versions of Apache +on Linux. + +

DYNAMIC_MODULE_LIMIT

+ +

If you have no intention of using dynamically loaded modules +(you probably don't if you're reading this and tuning your +server for every last ounce of performance) then you should add +-DDYNAMIC_MODULE_LIMIT=0 when building your server. +This will save RAM that's allocated only for supporting dynamically +loaded modules. + +

Appendix: Detailed Analysis of a Trace

+ +Here is a system call trace of Apache 1.3 running on Linux. The run-time +configuration file is essentially the default plus: + +
+<Directory />
+    AllowOverride none
+    Options FollowSymLinks
+</Directory>
+
+ +The file being requested is a static 6K file of no particular content. +Traces of non-static requests or requests with content negotiation +look wildly different (and quite ugly in some cases). First the +entire trace, then we'll examine details. (This was generated by +the strace program, other similar programs include +truss, ktrace, and par.) + +
+accept(15, {sin_family=AF_INET, sin_port=htons(22283), sin_addr=inet_addr("127.0.0.1")}, [16]) = 3
+flock(18, LOCK_UN)                      = 0
+sigaction(SIGUSR1, {SIG_IGN}, {0x8059954, [], SA_INTERRUPT}) = 0
+getsockname(3, {sin_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
+setsockopt(3, IPPROTO_TCP1, [1], 4)     = 0
+read(3, "GET /6k HTTP/1.0\r\nUser-Agent: "..., 4096) = 60
+sigaction(SIGUSR1, {SIG_IGN}, {SIG_IGN}) = 0
+time(NULL)                              = 873959960
+gettimeofday({873959960, 404935}, NULL) = 0
+stat("/home/dgaudet/ap/apachen/htdocs/6k", {st_mode=S_IFREG|0644, st_size=6144, ...}) = 0
+open("/home/dgaudet/ap/apachen/htdocs/6k", O_RDONLY) = 4
+mmap(0, 6144, PROT_READ, MAP_PRIVATE, 4, 0) = 0x400ee000
+writev(3, [{"HTTP/1.1 200 OK\r\nDate: Thu, 11"..., 245}, {"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 6144}], 2) = 6389
+close(4)                                = 0
+time(NULL)                              = 873959960
+write(17, "127.0.0.1 - - [10/Sep/1997:23:39"..., 71) = 71
+gettimeofday({873959960, 417742}, NULL) = 0
+times({tms_utime=5, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 446747
+shutdown(3, 1 /* send */)               = 0
+oldselect(4, [3], NULL, [3], {2, 0})    = 1 (in [3], left {2, 0})
+read(3, "", 2048)                       = 0
+close(3)                                = 0
+sigaction(SIGUSR1, {0x8059954, [], SA_INTERRUPT}, {SIG_IGN}) = 0
+munmap(0x400ee000, 6144)                = 0
+flock(18, LOCK_EX)                      = 0
+
+ +

Notice the accept serialization: + +

+flock(18, LOCK_UN)                      = 0
+...
+flock(18, LOCK_EX)                      = 0
+
+ +These two calls can be removed by defining +SINGLE_LISTEN_UNSERIALIZED_ACCEPT as described earlier. + +

Notice the SIGUSR1 manipulation: + +

+sigaction(SIGUSR1, {SIG_IGN}, {0x8059954, [], SA_INTERRUPT}) = 0
+...
+sigaction(SIGUSR1, {SIG_IGN}, {SIG_IGN}) = 0
+...
+sigaction(SIGUSR1, {0x8059954, [], SA_INTERRUPT}, {SIG_IGN}) = 0
+
+ +This is caused by the implementation of graceful restarts. When the +parent receives a SIGUSR1 it sends a SIGUSR1 +to all of its children (and it also increments a "generation counter" +in shared memory). Any children that are idle (between connections) +will immediately die +off when they receive the signal. Any children that are in keep-alive +connections, but are in between requests will die off immediately. But +any children that have a connection and are still waiting for the first +request will not die off immediately. + +

To see why this is necessary, consider how a browser reacts to a closed +connection. If the connection was a keep-alive connection and the request +being serviced was not the first request then the browser will quietly +reissue the request on a new connection. It has to do this because the +server is always free to close a keep-alive connection in between requests +(i.e. due to a timeout or because of a maximum number of requests). +But, if the connection is closed before the first response has been +received the typical browser will display a "document contains no data" +dialogue (or a broken image icon). This is done on the assumption that +the server is broken in some way (or maybe too overloaded to respond +at all). So Apache tries to avoid ever deliberately closing the connection +before it has sent a single response. This is the cause of those +SIGUSR1 manipulations. + +

Note that it is theoretically possible to eliminate all three of +these calls. But in rough tests the gain proved to be almost unnoticeable. + +

In order to implement virtual hosts, Apache needs to know the +local socket address used to accept the connection: + +

+getsockname(3, {sin_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
+
+ +It is possible to eliminate this call in many situations (such as when +there are no virtual hosts, or when Listen directives are +used which do not have wildcard addresses). But no effort has yet been +made to do these optimizations. + +

Apache turns off the Nagle algorithm: + +

+setsockopt(3, IPPROTO_TCP1, [1], 4)     = 0
+
+ +because of problems described in +a +paper by John Heidemann. + +

Notice the two time calls: + +

+time(NULL)                              = 873959960
+...
+time(NULL)                              = 873959960
+
+ +One of these occurs at the beginning of the request, and the other occurs +as a result of writing the log. At least one of these is required to +properly implement the HTTP protocol. The second occurs because the +Common Log Format dictates that the log record include a timestamp of the +end of the request. A custom logging module could eliminate one of the +calls. Or you can use a method which moves the time into shared memory, +see the patches section below. + +

As described earlier, Rule STATUS=yes causes two +gettimeofday calls and a call to times: + +

+gettimeofday({873959960, 404935}, NULL) = 0
+...
+gettimeofday({873959960, 417742}, NULL) = 0
+times({tms_utime=5, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 446747
+
+ +These can be removed by either removing mod_status or +setting Rule STATUS=no. + +

It might seem odd to call stat: + +

+stat("/home/dgaudet/ap/apachen/htdocs/6k", {st_mode=S_IFREG|0644, st_size=6144, ...}) = 0
+
+ +This is part of the algorithm which calculates the +PATH_INFO for use by CGIs. In fact if the request had been +for the URI /cgi-bin/printenv/foobar then there would be +two calls to stat. The first for +/home/dgaudet/ap/apachen/cgi-bin/printenv/foobar +which does not exist, and the second for +/home/dgaudet/ap/apachen/cgi-bin/printenv, which does exist. +Regardless, at least one stat call is necessary when +serving static files because the file size and modification times are +used to generate HTTP headers (such as Content-Length, +Last-Modified) and implement protocol features (such +as If-Modified-Since). A somewhat more clever server +could avoid the stat when serving non-static files, +however doing so in Apache is very difficult given the modular structure. + +

All static files are served using mmap: + +

+mmap(0, 6144, PROT_READ, MAP_PRIVATE, 4, 0) = 0x400ee000
+...
+munmap(0x400ee000, 6144)                = 0
+
+ +On some architectures it's slower to mmap small +files than it is to simply read them. The define +MMAP_THRESHOLD can be set to the minimum +size required before using mmap. By default +it's set to 0 (except on SunOS4 where experimentation has +shown 8192 to be a better value). Using a tool such as lmbench you +can determine the optimal setting for your environment. + +

You may also wish to experiment with MMAP_SEGMENT_SIZE +(default 32768) which determines the maximum number of bytes that +will be written at a time from mmap()d files. Apache only resets the +client's Timeout in between write()s. So setting this +large may lock out low bandwidth clients unless you also increase the +Timeout. + +

It may even be the case that mmap isn't +used on your architecture, if so then defining USE_MMAP_FILES +and HAVE_MMAP might work (if it works then report back to us). + +

Apache does its best to avoid copying bytes around in memory. The +first write of any request typically is turned into a writev +which combines both the headers and the first hunk of data: + +

+writev(3, [{"HTTP/1.1 200 OK\r\nDate: Thu, 11"..., 245}, {"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 6144}], 2) = 6389
+
+ +When doing HTTP/1.1 chunked encoding Apache will generate up to four +element writevs. The goal is to push the byte copying +into the kernel, where it typically has to happen anyhow (to assemble +network packets). On testing, various Unixes (BSDI 2.x, Solaris 2.5, +Linux 2.0.31+) properly combine the elements into network packets. +Pre-2.0.31 Linux will not combine, and will create a packet for +each element, so upgrading is a good idea. Defining NO_WRITEV +will disable this combining, but result in very poor chunked encoding +performance. + +

The log write: + +

+write(17, "127.0.0.1 - - [10/Sep/1997:23:39"..., 71) = 71
+
+ +can be deferred by defining BUFFERED_LOGS. In this case +up to PIPE_BUF bytes (a POSIX defined constant) of log entries +are buffered before writing. At no time does it split a log entry +across a PIPE_BUF boundary because those writes may not +be atomic. (i.e. entries from multiple children could become mixed together). +The code does it best to flush this buffer when a child dies. + +

The lingering close code causes four system calls: + +

+shutdown(3, 1 /* send */)               = 0
+oldselect(4, [3], NULL, [3], {2, 0})    = 1 (in [3], left {2, 0})
+read(3, "", 2048)                       = 0
+close(3)                                = 0
+
+ +which were described earlier. + +

Let's apply some of these optimizations: +-DSINGLE_LISTEN_UNSERIALIZED_ACCEPT -DBUFFERED_LOGS and +Rule STATUS=no. Here's the final trace: + +

+accept(15, {sin_family=AF_INET, sin_port=htons(22286), sin_addr=inet_addr("127.0.0.1")}, [16]) = 3
+sigaction(SIGUSR1, {SIG_IGN}, {0x8058c98, [], SA_INTERRUPT}) = 0
+getsockname(3, {sin_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
+setsockopt(3, IPPROTO_TCP1, [1], 4)     = 0
+read(3, "GET /6k HTTP/1.0\r\nUser-Agent: "..., 4096) = 60
+sigaction(SIGUSR1, {SIG_IGN}, {SIG_IGN}) = 0
+time(NULL)                              = 873961916
+stat("/home/dgaudet/ap/apachen/htdocs/6k", {st_mode=S_IFREG|0644, st_size=6144, ...}) = 0
+open("/home/dgaudet/ap/apachen/htdocs/6k", O_RDONLY) = 4
+mmap(0, 6144, PROT_READ, MAP_PRIVATE, 4, 0) = 0x400e3000
+writev(3, [{"HTTP/1.1 200 OK\r\nDate: Thu, 11"..., 245}, {"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 6144}], 2) = 6389
+close(4)                                = 0
+time(NULL)                              = 873961916
+shutdown(3, 1 /* send */)               = 0
+oldselect(4, [3], NULL, [3], {2, 0})    = 1 (in [3], left {2, 0})
+read(3, "", 2048)                       = 0
+close(3)                                = 0
+sigaction(SIGUSR1, {0x8058c98, [], SA_INTERRUPT}, {SIG_IGN}) = 0
+munmap(0x400e3000, 6144)                = 0
+
+ +That's 19 system calls, of which 4 remain relatively easy to remove, +but don't seem worth the effort. + +

Appendix: Patches Available

+ +There are + +several performance patches available for 1.3. But they may +be slightly out of date by the time Apache 1.3.0 has been released, +it shouldn't be difficult for someone with a little C knowledge to +update them. In particular: + +
    +
  • A +patch to remove all time(2) system calls. +
  • A +patch to remove various system calls from mod_include, +these calls are used by few sites but required for backwards compatibility. +
  • A +patch which integrates the above two plus a few other speedups at the +cost of removing some functionality. +
+ +

Appendix: The Pre-Forking Model

+ +

Apache (on Unix) is a pre-forking model server. The +parent process is responsible only for forking child +processes, it does not serve any requests or service any network +sockets. The child processes actually process connections, they serve +multiple connections (one at a time) before dying. +The parent spawns new or kills off old +children in response to changes in the load on the server (it does so +by monitoring a scoreboard which the children keep up to date). + +

This model for servers offers a robustness that other models do +not. In particular, the parent code is very simple, and with a high +degree of confidence the parent will continue to do its job without +error. The children are complex, and when you add in third party +code via modules, you risk segmentation faults and other forms of +corruption. Even should such a thing happen, it only affects one +connection and the server continues serving requests. The parent +quickly replaces the dead child. + +

Pre-forking is also very portable across dialects of Unix. +Historically this has been an important goal for Apache, and it continues +to remain so. + +

The pre-forking model comes under criticism for various +performance aspects. Of particular concern are the overhead +of forking a process, the overhead of context switches between +processes, and the memory overhead of having multiple processes. +Furthermore it does not offer as many opportunities for data-caching +between requests (such as a pool of mmapped files). +Various other models exist and extensive analysis can be found in the + papers +of the JAWS project. In practice all of these costs vary drastically +depending on the operating system. + +

Apache's core code is already multithread aware, and Apache version +1.3 is multithreaded on NT. There have been at least two other experimental +implementations of threaded Apache, one using the 1.3 code base on DCE, +and one using a custom user-level threads package and the 1.0 code base, +neither are available publically. There is also an experimental port of +Apache 1.3 to +Netscape's Portable Run Time, which +is available +(but you're encouraged to join the +new-httpd mailing list +if you intend to use it). +Part of our redesign for version 2.0 +of Apache will include abstractions of the server model so that we +can continue to support the pre-forking model, and also support various +threaded models. + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/perf.html b/APACHE_1_3b7/htdocs/manual/misc/perf.html new file mode 100644 index 0000000000..238224728e --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/perf.html @@ -0,0 +1,176 @@ + + + +Hints on Running a High-Performance Web Server + + + + + +

Hints on Running a High-Performance Web Server

+ +Running Apache on a heavily loaded web server, one often encounters +problems related to the machine and OS configuration. "Heavy" is +relative, of course - but if you are seeing more than a couple hits +per second on a sustained basis you should consult the pointers on +this page. In general the suggestions involve how to tune your kernel +for the heavier TCP load, hardware/software conflicts that arise, etc. + + + +
+ +

+A/UX (Apple's UNIX) +

+ +If you are running Apache on A/UX, a page that gives some helpful +performance hints (concerning the listen() queue and using +virtual hosts) +can be found here + +


+ +

+BSD-based (BSDI, FreeBSD, etc) +

+ +Quick and +detailed +performance tuning hints for BSD-derived systems. + +


+ +

+Digital UNIX +

+ + + +


+ +

+Linux +

+ +The most common problem on Linux shows up on heavily-loaded systems +where the whole server will appear to freeze for a couple of minutes +at a time, and then come back to life. This has been traced to a +listen() queue overload - certain Linux implementations have a low +value set for the incoming connection queue which can cause problems. + +


+ +

+Solaris 2.4 +

+ +The Solaris 2.4 TCP implementation has a few inherent limitations that +only became apparent under heavy loads. This has been fixed to some +extent in 2.5 (and completely revamped in 2.6), but for now consult +the following URL for tips on how to expand the capabilities if you +are finding slowdowns and lags are hurting performance. + +

+ +Other links: + +

+ +


+ +

+SunOS 4.x +

+ +More information on tuning SOMAXCONN on SunOS can be found at + +http://www.islandnet.com/~mark/somaxconn.html. + +


+ +

+SVR4 +

+ +Some SVR4 versions waste three system calls on every +gettimeofday() call. Depending on the syntactic +form of the TZ environment variable, these +systems have several different algorithms to determine the +local time zone (presumably compatible with +something). The following example uses the central european +time zone to demonstrate this: +
+
TZ=:MET +
This form delegates the knowledge of the time zone + information to an external compiled zoneinfo file + (à la BSD).
+ Caveat: Each time the gettimeofday() + function is called, the external zone info is read in + again (at least on some SVR4 systems). That results in + three wasted system calls with every apache request + served.
+     open("/usr/lib/locale/TZ/MET", O_RDONLY) = 3
+     read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 7944) = 778
+     close(3)                                = 0
+ +
TZ=MET-1MDT,M3.5.0/02:00:00,M10.5.0/03:00:00 +
This syntax form (à la SYSV) contains all the + knowledge about time zone beginning and ending times in + its external representation. It has to be parsed each + time it is evaluated, resulting in a slight computing + overhead, but it requires no system call. Though the + table lookup à la BSD is the more sophisticated + technical solution, the bad SVR4 implementation makes + this the preferred syntax on systems which otherwise + access the external zone info file repeatedly. +
+You should use the truss utility on a +single-process apache server (started with the -X +debugging switch) to determine whether your system can profit +from the second form of the TZ environment +variable. If it does, you could integrate the setting of the +preferred TZ syntax into the httpd startup +script, which is usually simply a copy of (or symbolic link +to) the apachectl utility script, or into the +system's /etc/TIMEZONE script. + +


+ +

More welcome!

+ +If you have tips to contribute, send mail to apache@apache.org + + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/security_tips.html b/APACHE_1_3b7/htdocs/manual/misc/security_tips.html new file mode 100644 index 0000000000..aa6106bf73 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/security_tips.html @@ -0,0 +1,229 @@ + + + +Apache HTTP Server: Security Tips + + + + + +

Security Tips for Server Configuration

+ +
+ +

Some hints and tips on security issues in setting up a web server. Some of +the suggestions will be general, others specific to Apache. + +


+ +

Permissions on ServerRoot Directories

+

In typical operation, Apache is started by the root +user, and it switches to the user defined by the User directive to serve hits. +As is the case with any command that root executes, you must take care +that it is protected from modification by non-root users. Not only +must the files themselves be writeable only by root, but so must the +directories, and parents of all directories. For example, if you +choose to place ServerRoot in /usr/local/apache then it is +suggested that you create that directory as root, with commands +like these: + +

+    mkdir /usr/local/apache
+    cd /usr/local/apache
+    mkdir bin conf logs
+    chown 0 . bin conf logs
+    chgrp 0 . bin conf logs
+    chmod 755 . bin conf logs
+
+ +It is assumed that /, /usr, and /usr/local are only modifiable by root. +When you install the httpd executable, you should ensure that it is +similarly protected: + +
+    cp httpd /usr/local/apache/bin
+    chown 0 /usr/local/apache/bin/httpd
+    chgrp 0 /usr/local/apache/bin/httpd
+    chmod 511 /usr/local/apache/bin/httpd
+
+ +

You can create an htdocs subdirectory which is modifiable by other +users -- since root never executes any files out of there, and shouldn't +be creating files in there. + +

If you allow non-root users to modify any files that root either +executes or writes on then you open your system to root compromises. +For example, someone could replace the httpd binary so that the next +time you start it, it will execute some arbitrary code. If the logs +directory is writeable (by a non-root user), someone +could replace a log file with a symlink to some other system file, +and then root might overwrite that file with arbitrary data. If the +log files themselves are writeable (by a non-root user), then someone +may be able to overwrite the log itself with bogus data. +

+


+

Server Side Includes

+

Server side includes (SSI) can be configured so that users can execute +arbitrary programs on the server. That thought alone should send a shiver +down the spine of any sys-admin.

+ +One solution is to disable that part of SSI. To do that you use the +IncludesNOEXEC option to the Options +directive.

+ +


+ +

Non Script Aliased CGI

+

Allowing users to execute CGI scripts in any directory +should only +be considered if; +

    +
  1. You trust your users not to write scripts which will deliberately or +accidentally expose your system to an attack. +
  2. You consider security at your site to be so feeble in other areas, as to +make one more potential hole irrelevant. +
  3. You have no users, and nobody ever visits your server. +

+


+ +

Script Alias'ed CGI

+

Limiting CGI to special directories gives the admin +control over +what goes into those directories. This is inevitably more secure than +non script aliased CGI, but only if users with write access to the +directories are trusted or the admin is willing to test each new CGI +script/program for potential security holes.

+ +Most sites choose this option over the non script aliased CGI approach.

+ +


+

CGI in general

+

Always remember that you must trust the writers of the CGI script/programs +or your ability to spot potential security holes in CGI, whether they were +deliberate or accidental.

+ +All the CGI scripts will run as the same user, so they have potential to +conflict (accidentally or deliberately) with other scripts e.g. +User A hates User B, so he writes a script to trash User B's CGI +database. One program which can be used to allow scripts to run +as different users is suEXEC which is +included with Apache as of 1.2 and is called from special hooks in +the Apache server code. Another popular way of doing this is with +CGIWrap.

+ +


+ + +

Stopping users overriding system wide settings...

+

To run a really tight ship, you'll want to stop users from setting +up .htaccess files which can override security features +you've configured. Here's one way to do it...

+ +In the server configuration file, put +

+<Directory />
+AllowOverride None
+Options None
+allow from all
+</Directory>
+
+ +Then setup for specific directories

+ +This stops all overrides, Includes and accesses in all directories apart +from those named.

+


+

+ Protect server files by default +

+

+One aspect of Apache which is occasionally misunderstood is the feature +of default access. That is, unless you take steps to change it, if the +server can find its way to a file through normal URL mapping rules, it +can serve it to clients. +

+

+For instance, consider the following example: +

+
    +
  1. # cd /; ln -s / public_html +
  2. +
  3. Accessing http://localhost/~root/ +
  4. +
+

+This would allow clients to walk through the entire filesystem. To work +around this, add the following block to your server's configuration: +

+
+ <Directory />
+     Order deny,allow
+     Deny from all
+ </Directory>
+
+

+This will forbid default access to filesystem locations. Add +appropriate +<Directory> +blocks to allow access only +in those areas you wish. For example, +

+
+ <Directory /usr/users/*/public_html>
+     Order deny,allow
+     Allow from all
+ </Directory>
+ <Directory /usr/local/httpd>
+     Order deny,allow
+     Allow from all
+ </Directory>
+
+

+Pay particular attention to the interactions of +<Location> +and +<Directory> +directives; for instance, even if <Directory /> +denies access, a <Location /> directive might +overturn it. +

+

+Also be wary of playing games with the +UserDir +directive; setting it to something like "./" +would have the same effect, for root, as the first example above. +If you are using Apache 1.3 or above, we strongly recommend that you +include the following line in your server configuration files: +

+
+
UserDir disabled root +
+
+ +
+

Please send any other useful security tips to The Apache Group +by filling out a +problem report, or by +sending mail to +apache-bugs@mail.apache.org +

+


+ + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/vif-info.html b/APACHE_1_3b7/htdocs/manual/misc/vif-info.html new file mode 100644 index 0000000000..dbe0378703 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/vif-info.html @@ -0,0 +1,399 @@ + + +Configuring Multiple IP Addresses + + + + +

Configuring Multiple IP Addresses

+ +
+This material is originally from John Ioannidis (ji@polaris.ctr.columbia.edu)
+I have condensed it some and applied some corrections for SunOS 4.1.x
+courtesy of Chuck Smoko (csmoko@relay.nswc.navy.mil).
+
+Bob Baggerman  (bob@bizweb.com)
+12 Jan 94
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+John Ionnidis writes:
+
+This is a topic that comes up once in a while on comp.protocols.tcp-ip
+and other newsgroups. The question is, how to get a machine with one
+network interface to respond to more than one IP addresses.
+
+I have a solution than might suit you.  For my doctoral work (there's
+a paper about it in this year's ('91) SIGCOMM, also available for
+anonymous FTP from cs.columbia.edu:/pub/ji/sigcomm*.ps.Z), I've
+developed what I call the "Virtual Interface" (VIF). To the networking
+code, it looks like an interface. It gets ifattach()ed when you open
+the /dev/vif* device, and then you can ifconfig it as you like. It
+does not have an if_input procedure; it only has an if_output. Packets
+that it receives (from higher-level protocols) which have its
+IP address, it simply loops back (like any well-behaved if driver).
+Packets that it receives that are destined for some other address, it
+encapsulates in an encapsulation protocol I call IPIP (IP-within-IP,
+protocol number IPPROTO_IPIP == 94), and sends it to another machine
+that groks that encapsulation protocol. This feature you won't need,
+but here's how to have multiple IP addresses on a machine with a
+single real interface:
+
+Let's say your primary interface's IP address is 198.3.2.1, and you
+also want it to respond to addresses 198.4.3.2 and 198.5.4.3 (note
+that these are three distinct class C addresses in three distinct
+class C nets). Here are the ifconfigs:
+
+  ifconfig le0 198.3.2.1 up -trailers   # config primary interface
+
+  ifconfig vif0 198.4.3.2 up            # config first virtual interface
+  route delete net 198.4.3 198.4.3.2    # delete spurious route
+  route add host 198.4.3.2 198.4.3.2 0  # add route for this i/f
+
+  ifconfig vif1 198.5.4.3 up            # config second virtual interface
+  route delete net 198.5.4 198.5.4.3    # delete spurious route
+  route add host 198.5.4.3 198.5.4.3 0  # add route for this i/f
+
+The route deletes are needed because the ifconfig creates a default
+route to the interface's network, which can cause problems; all that's
+needed is the (host) route to the interface's address.
+
+Now, get le0's ethernet address (say, 8:0:20:3:2:1), and add the
+following static ARP entries:
+
+  arp -s 198.4.3.2 8:0:20:3:2:1 pub
+  arp -s 198.5.4.3 8:0:20:3:2:1 pub
+
+This will cause any ARP requests for the VIF addresses to be replied
+with your machine's ethernet address.
+
+Now, make sure your default route is to your segment's gateway,
+through the real interface. Finally, make sure your routers and/or
+hosts on the same segment as yours know that 198.4.3.2 and 198.5.4.3
+are on that cable.
+
+Here's what you've accomplished.
+
+ARP requests for any of your host's addresses will be replied to with
+the host's ethernet address (the real one, because that's what it is,
+the virtual ones because of the public static arp entries). Packets
+reaching your host with any of these addresses will be accepted by the
+ip_input routine because they match the address of one of the host's
+interfaces. Packets leaving your host can have any of its addresses
+(real and virtual).
+
+The code for vif follows. To use it, put the stuff in netinet/if_vif.c
+and netinet/if_vif.h, configure your kernel with the number of
+virtual interfaces you want using a line like:
+
+pseudo-device   vif4            # Virtual IP interface
+
+in your configuration file, and the line
+
+netinet/if_vif.c        optional vif device-driver
+
+in the "files" file. Also, add the appropriate entries in conf.c, so
+that you can access the if_attach() routine when you open the device:
+
+
+-------------------------- conf.c------------------------------------------
+
+add this in the appropriate place in the headers of conf.c:
+
+--------------------
+#include "vif.h"
+#if NVIF > 0
+int     vifopen(), vifclose(), vifread(), vifwrite(), vifselect(), vifioctl();
+#else
+#define vifopen         nodev
+#define vifclose        nodev
+#define vifread         nodev
+#define vifwrite        nodev
+#define vifselect       nodev
+#define vifioctl        nodev
+#endif
+--------------------
+
+then, way down in the definition for cdevsw[]:
+
+--------------------
+        vifopen,        vifclose,       vifread,        vifwrite,       /*14*/
+        vifioctl,       nodev,          nodev,          0,
+        0,      nodev,
+--------------------
+
+Make sure you remember the correct major device number, 14 in this case!
+
+---------------------------------------------------------------------------
+
+Finally, here's the code. It has the tunneling pieces removed (you
+need more code to use that anyway), and it comes from a Mach 2.6
+kernel; it should compile on any Berkeley-derived unix with minor
+changes (most likely only in the includes).
+
+---------------------netinet/if_vif.h--------------------------------------
+typedef struct
+{
+        struct ifnet    vif_if;
+        struct ifnet    *vif_sif;       /* slave interface */
+        int             vif_flags;
+} vif_softc_t;
+
+#define VIFMTU  (1024+512)
+---------------------------------------------------------------------------
+
+and
+
+---------------------netinet/if_vif.c--------------------------------------
+/*
+ * Virtual IP interface module.
+ */
+
+#include "param.h"
+#include "../sys/systm.h"
+#include "../sys/mbuf.h"
+#include "../sys/socket.h"
+#include "../sys/errno.h"
+#include "../sys/ioctl.h"
+
+#include "../net/if.h"
+#include "../net/netisr.h"
+#include "../net/route.h"
+
+#ifdef  INET
+#include "../netinet/in.h"
+#include "../netinet/in_systm.h"
+#include "../netinet/in_var.h"
+#include "../netinet/ip.h"
+#endif
+
+#include "in_pcb.h"
+#include "vif.h"
+
+typedef struct
+{
+        struct ifnet    vif_if;
+        struct ifnet    *vif_sif;       /* slave interface */
+        int             vif_flags;
+} vif_softc_t;
+
+#define VIFMTU  (1024+512)
+
+vif_softc_t vif_softc[NVIF];
+
+int vifs_inited = 0;
+
+
+vifattach()
+{
+        register int i;
+        register struct ifnet *ifp;
+        int     vifoutput(), vififioctl();
+
+        for (i=0; i<NVIF; i++)
+        {
+                ifp = &vif_softc[i].vif_if;
+                ifp->if_name = "vif";
+                ifp->if_unit = i;
+                ifp->if_mtu = VIFMTU;
+                ifp->if_flags = IFF_LOOPBACK | IFF_NOARP;
+                ifp->if_ioctl = vififioctl;
+                ifp->if_output = vifoutput;
+                if_attach(ifp);
+        }
+}
+
+vifopen(dev, flag)
+int dev, flag;
+{
+        int unit;
+
+        if (!vifs_inited)
+        {
+                vifattach();
+                vifs_inited = 1;
+                printf("vif initialized\n");
+        }
+
+        unit = minor(dev);
+        if ((unit < 0) || (unit >= NVIF))
+        {
+                return ENXIO;
+        }
+
+        return 0;
+}
+
+vifclose(dev, flag)
+int dev, flag;
+{
+        return 0;
+}
+
+vifread()
+{
+        return ENXIO;
+}
+
+vifwrite()
+{
+        return ENXIO;
+}
+
+vifselect()
+{
+        return ENXIO;
+}
+
+vifoutput(ifp, m0, dst)
+        struct ifnet *ifp;
+        register struct mbuf *m0;
+        struct sockaddr *dst;
+{
+        int s;
+        register struct ifqueue *ifq;
+        struct mbuf *m;
+        struct sockaddr_in *din;
+
+        if (dst->sa_family != AF_INET)
+        {
+                printf("%s%d: can't handle af%d\n",
+                       ifp->if_name, ifp->if_unit,
+                       dst->sa_family);
+                m_freem(m0);
+                return (EAFNOSUPPORT);
+        }
+
+        din = (struct sockaddr_in *)dst;
+
+        if (din->sin_addr.s_addr == IA_SIN(ifp->if_addrlist)->sin_addr.s_addr)
+        {
+                /* printf("%s%d: looping\n", ifp->if_name, ifp->if_unit); */
+
+                /*
+                 * Place interface pointer before the data
+                 * for the receiving protocol.
+                 */
+                if (m0->m_off <= MMAXOFF &&
+                    m0->m_off >= MMINOFF + sizeof(struct ifnet *)) {
+                        m0->m_off -= sizeof(struct ifnet *);
+                        m0->m_len += sizeof(struct ifnet *);
+                } else {
+                        MGET(m, M_DONTWAIT, MT_HEADER);
+                        if (m == (struct mbuf *)0)
+                          return (ENOBUFS);
+                        m->m_off = MMINOFF;
+                        m->m_len = sizeof(struct ifnet *);
+                        m->m_next = m0;
+                        m0 = m;
+                }
+                *(mtod(m0, struct ifnet **)) = ifp;
+                s = splimp();
+                ifp->if_opackets++;
+                ifq = &ipintrq;
+                if (IF_QFULL(ifq)) {
+                        IF_DROP(ifq);
+                        m_freem(m0);
+                        splx(s);
+                        return (ENOBUFS);
+                }
+                IF_ENQUEUE(ifq, m0);
+                schednetisr(NETISR_IP);
+                ifp->if_ipackets++;
+                splx(s);
+                return (0);
+        }
+
+        return EHOSTUNREACH;
+}
+
+/*
+ * Process an ioctl request.
+ */
+/* ARGSUSED */
+vififioctl(ifp, cmd, data)
+        register struct ifnet *ifp;
+        int cmd;
+        caddr_t data;
+{
+        int error = 0;
+
+        switch (cmd) {
+
+        case SIOCSIFADDR:
+                ifp->if_flags |= IFF_UP;
+                /*
+                 * Everything else is done at a higher level.
+                 */
+                break;
+
+        default:
+                error = EINVAL;
+        }
+        return (error);
+}
+
+vifioctl(dev, cmd, arg, mode)
+dev_t dev;
+int cmd;
+caddr_t arg;
+int mode;
+{
+        int unit;
+
+        unit = minor(dev);
+        if ((unit < 0) || (unit >= NVIF))
+          return ENXIO;
+
+        return EINVAL;
+}
+----------------------------------------------------------------------------
+
+To use it, compile your kernel, and reboot. Then create the vif
+device:
+
+# mknod /dev/vif c 14 0
+
+(or whatever major number it ended up being), and echo something into
+it:
+
+# echo > /dev/vif
+
+This will cause the device to be opened, which will if_attach the
+interfaces. If you feel like playing with the code, you may want to
+kmem_alloc() the vif_softc structure at open time, and use the minor
+number of the device to tell it how many interfaces to create.
+
+Now you can go ahead and ifconfig etc.
+
+I'll be happy to answer minor questions, and hear about success and
+failure stories, but I cannot help you if you don't already know how
+to hack kernels.
+
+Good luck!
+
+/ji
+
+In-Real-Life: John "Heldenprogrammer" Ioannidis
+E-Mail-To: ji@cs.columbia.edu
+V-Mail-To: +1 212 854 8120
+P-Mail-To: 450 Computer Science \n Columbia University \n New York, NY 10027
+
+ +

+ +Note: there is also a commercial-product-turned-freeware +called "Col. Patch" which does this as a loadable kernel module +for SunOS 4.1.3_U1. + +

+ + + + diff --git a/APACHE_1_3b7/htdocs/manual/misc/windoz_keepalive.html b/APACHE_1_3b7/htdocs/manual/misc/windoz_keepalive.html new file mode 100644 index 0000000000..b8a556a804 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/misc/windoz_keepalive.html @@ -0,0 +1,50 @@ + + + +MS Windows Netscape 3.0b4 KeepAlive problem solved + + + + +

HTTP/1.1 KeepAlive problems with Netscape 3.0

+ +
+Date: Mon, 1 Jul 1996 16:03:06 -0700 (PDT)
+From: Alexei Kosut <akosut@organic.com>
+To: Apache Group
+Subject: Re: keepalive and windoze
+
+Good news and good news (of a sort)..
+
+I was able to snag a Windows 95 machine here at Organic, and tried out
+some things:
+
+1) On Netscape 3.0b4, I was able to reproduce the bug, each and every
+time. It's really simple: go to the Network Setup panel. Set it to
+"Connect Every Time" and only let it have 1 connection at once (this may
+not be necessary, but it's helpful). Then load an image that's
+kept-alive. Then wait until the connection times out (this depends on the
+server - 10-30 seconds, except for MIIS, which never times out, near as I
+can tell). Then hit reload. It will hang. (actually, once it crashed).
+
+2) This happens with all forms of server. Apache 1.1, Netscape 2.0,
+Spyglass 1.2, NCSA 1.5 (although, as stated, I couldn't test MIIS).
+
+3) Netscape 3.0b5 does, indeed, *not* have this bug. At least, I couldn't
+get it to perform such. Yipee.
+
+So, we just put up a note on the web page. Make sure we say that all the
+servers have the bug, it's a Windows bug, and Netscape Navigator 3.0b5
+works around it. That way, no one can yell at us. Yes?
+
+-- Alexei Kosut <akosut@organic.com>            The Apache HTTP Server
+   http://www.nueva.pvt.k12.ca.us/~akosut/      http://www.apache.org/
+
+ + diff --git a/APACHE_1_3b7/htdocs/manual/mod/core.html b/APACHE_1_3b7/htdocs/manual/mod/core.html new file mode 100644 index 0000000000..1133b1029b --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/core.html @@ -0,0 +1,2910 @@ + + + +Apache Core Features + + + + + + +

Apache Core Features

+

+These configuration parameters control the core Apache features, and are +always available. +

+

Directives

+ +
+ +

AccessConfig directive

+ +Syntax: AccessConfig filename
+Default: AccessConfig conf/access.conf
+Context: server config, virtual host
+Status: core

+ +The server will read this file for more directives after reading the +ResourceConfig file. Filename is +relative to the ServerRoot. +This feature can be disabled using: +

AccessConfig /dev/null
+Historically, this file only contained +<Directory> sections; in fact it can now +contain any server directive allowed in the server config context. +


+ +

AccessFileName directive

+ +Syntax: AccessFileName filename filename ...
+Default: AccessFileName .htaccess
+Context: server config, virtual host
+Status: core
+Compatibility: AccessFileName can accept more than +one filename only in Apache 1.3 and later

+ +When returning a document to the client the server looks for the first existing +access control file from this list of names in every directory of the path to +the document, if access control files are enabled for that directory. + +For example: +

AccessFileName .acl
+before returning the document /usr/local/web/index.html, the +server will read /.acl, /usr/.acl, /usr/local/.acl and /usr/local/web/.acl +for directives, unless they have been disabled with +
+<Directory />
+AllowOverride None
+</Directory>


+ +

AddModule directive

+ +Syntax: AddModule module module ...
+Context: server config
+Status: core
+Compatibility: AddModule is only available in +Apache 1.2 and later

+ +The server can have modules compiled in which are not actively in use. +This directive can be used to enable the use of those modules. The +server comes with a pre-loaded list of active modules; this list can +be cleared with the ClearModuleList +directive.


+ +

AllowOverride directive

+ +Syntax: AllowOverride override override ...
+Default: AllowOverride All
+Context: directory
+Status: core

+ +When the server finds an .htaccess file (as specified by +AccessFileName) it needs to know which +directives declared in that file can override earlier access information.

+ +Override can be set to None, in which case the server +will not read the file, All in which case the server will +allow all the directives, or one or more of the following: +

+
AuthConfig +
+ +Allow use of the authorization directives +(AuthDBMGroupFile, +AuthDBMUserFile, +AuthGroupFile, +AuthName, AuthType, +AuthUserFile, +require, etc.). +
FileInfo +
+ +Allow use of the directives controlling document types +(AddEncoding, +AddLanguage, +AddType, +DefaultType, +ErrorDocument, +LanguagePriority, etc.). +
Indexes +
+ +Allow use of the directives controlling directory indexing +(AddDescription, +AddIcon, +AddIconByEncoding, +AddIconByType, +DefaultIcon, +DirectoryIndex, +FancyIndexing, +HeaderName, +IndexIgnore, +IndexOptions, +ReadmeName, etc.). +
Limit +
+ +Allow use of the directives controlling host access (allow, deny and order). +
Options +
+ +Allow use of the directives controlling specific directory features +(Options and +XBitHack). +


+ +

AuthName directive

+ +Syntax: AuthName auth-domain
+Context: directory, .htaccess
+Override: AuthConfig
+Status: core

+ +This directive sets the name of the authorization realm for a directory. +This realm is given to the client so that the user knows which username and +password to send. +It must be accompanied by AuthType and +require directives, and directives such as +AuthUserFile and +AuthGroupFile to work.


+ +

AuthType directive

+ +Syntax: AuthType type
+Context: directory, .htaccess
+Override: AuthConfig
+Status: core

+ +This directive selects the type of user authentication for a directory. +Only Basic is currently implemented. + +It must be accompanied by AuthName and +require directives, and directives such as +AuthUserFile and +AuthGroupFile to work.


+ +

BindAddress directive

+ +Syntax: BindAddress saddr
+Default: BindAddress *
+Context: server config
+Status: core

+ +A Unix® http server can either listen for connections to every +IP address of the server machine, or just one IP address of the server +machine. Saddr can be + +

+
  • * +
  • An IP address +
  • A fully-qualified Internet domain name +
  • +If the value is *, then the server will listen for connections on +every IP address, otherwise it will only listen on the IP address +specified.

    + +Only one BindAddress directive can be used. For more +control over which address and ports Apache listens to, use the +Listen directive instead of +BindAddress.

    + +BindAddress can be used as an alternative method for +supporting virtual hosts using +multiple independent servers, instead of using <VirtualHost> sections. + +

    See Also: +DNS Issues
    +See Also: +Setting which addresses and ports Apache uses

    + +
    + +

    BS2000AuthFile directive

    + +Syntax: BS2000AuthFile authfile
    +Default: none
    +Context: server config
    +Status: core
    +Compatibility: BS2000AuthFile is only available for +BS2000 machines, as of Apache 1.3 and later.

    + +The BS2000AuthFile directive is available for BS2000 hosts +only. It must be used to define the password file which is used to +change the BS2000 task environment of the server to the non-privileged +account specified by the User directive. This is +required in the BS2000 POSIX subsystem (by performing a sub-LOGON) to +prevent CGI scripts from accessing resources of the privileged account +which started the server, usually TSOS.
    +Note that the specified authfile must be owned by the super +user and must not be readable or writable by anyone else, otherwise +Apache will refuse to start and exit with an error message.
    +Only one BS2000AuthFile directive can be used.

    + +

    See Also: +Apache EBCDIC port

    + +
    + +

    ClearModuleList directive

    + +Syntax: ClearModuleList
    +Context: server config
    +Status: core
    +Compatibility: ClearModuleList is only available in +Apache 1.2 and later

    + +The server comes with a built-in list of active modules. This +directive clears the list. It is assumed that the list will then be +re-populated using the AddModule directive.


    + +

    ContentDigest directive

    + +Syntax: ContentDigest on|off
    +Default: ContentDigest off
    +Context: server config, virtual host, directory, +.htaccess
    +Override: AuthConfig
    +Status: experimental

    +Compatibility: ContentDigest is only available in +Apache 1.1 and later

    + +This directive enables the generation of Content-MD5 headers +as defined in RFC1864 respectively RFC2068.

    + +MD5 is an algorithm for computing a "message digest" (sometimes called +"fingerprint") of arbitrary-length data, with a high degree of confidence +that any alterations in the data will be reflected in alterations in the +message digest.

    + +The Content-MD5 header provides an end-to-end message +integrity check (MIC) of the entity-body. A proxy or client may check this +header for detecting accidental modification of the entity-body +in transit. +Example header: +

       Content-MD5: AuLb7Dp1rqtRtxz2m9kRpA==

    + +Note that this can cause performance problems on your server +since the message digest is computed on every request +(the values are not cached).

    + +Content-MD5 is only sent for documents served by the +core, and not by any module. For example, SSI documents, output from +CGI scripts, and byte range responses do not have this header. + +


    + +

    CoreDumpDirectory directive

    + +Syntax: CoreDumpDirectory directory
    +Default: the same location as ServerRoot
    +Context: server config
    +Status: core

    + +This controls the directory to which Apache attempts to switch before +dumping core. The default is in the ServerRoot +directory, however since this should not be writable by the user +the server runs as, core dumps won't normally get written. If you +want a core dump for debugging, you can use this directive to place +it in a different location.


    + +

    DefaultType directive

    + +Syntax: DefaultType mime-type
    +Default: DefaultType text/html
    +Context: server config, virtual host, directory, +.htaccess
    +Override: FileInfo
    +Status: core

    + +There will be times when the server is asked to provide a document +whose type cannot be determined by its MIME types mappings.

    + +The server must inform the client of the content-type of the document, so in +the event of an unknown type it uses the DefaultType. For +example: +

    DefaultType image/gif
    +would be appropriate for a directory which contained many gif images +with filenames missing the .gif extension.


    + +

    <Directory> directive

    + +Syntax: <Directory directory> + ... </Directory>
    +Context: server config, virtual host
    +Status: Core.

    + +<Directory> and </Directory> are used to enclose a group of +directives which will apply only to the named directory and sub-directories +of that directory. Any directive which is allowed in a directory +context may be used. Directory is either the full path to a directory, +or a wild-card string. In a wild-card string, `?' matches any single character, +and `*' matches any sequences of characters. As of Apache 1.3, you +may also use `[]' character ranges like in the shell. Also as of Apache 1.3 +none of the wildcards match a `/' character, which more closely mimics the +behaviour of Unix shells. +Example: +

    +   <Directory /usr/local/httpd/htdocs>
    +   Options Indexes FollowSymLinks
    +   </Directory>
    +
    + +

    Apache 1.2 and above: +Extended regular expressions can also be used, with the addition of the +~ character. For example:

    + +
    +   <Directory ~ "^/www/.*/[0-9]{3}">
    +
    + +would match directories in /www/ that consisted of three numbers. + +

    If multiple (non-regular expression) directory sections match the +directory (or its parents) containing +a document, then the directives are applied in the order of shortest match +first, interspersed with the directives from the +.htaccess files. For example, with +

    +<Directory />
    +AllowOverride None
    +</Directory>

    +<Directory /home/*>
    +AllowOverride FileInfo
    +</Directory>
    +for access to the document /home/web/dir/doc.html the +steps are: + +
  • Apply directive AllowOverride None (disabling +.htaccess files). +
  • Apply directive AllowOverride FileInfo (for directory +/home/web). +
  • Apply any FileInfo directives in /home/web/.htaccess +
  • + +

    +Regular expression directory sections are handled slightly differently +by Apache 1.2 and 1.3. In Apache 1.2 they are interspersed with the normal +directory sections and applied in the order they appear in the configuration +file. They are applied only once, and apply when the shortest match +possible occurs. In Apache 1.3 regular expressions are not considered +until after all of the normal sections have been applied. Then all of +the regular expressions are tested in the order they appeared in the +configuration file. For example, with +

    +<Directory ~ abc$>
    +... directives here ...
    +</Directory>
    +
    +Suppose that the filename being accessed is +/home/abc/public_html/abc/index.html. The server +considers each of /, /home, /home/abc, +/home/abc/public_html, and /home/abc/public_html/abc +in that order. In Apache 1.2, when +/home/abc is considered, the regular expression will match +and be applied. In Apache 1.3 the regular expression isn't considered +at all at that point in the tree. It won't be considered until after +all normal <Directory>s and .htaccess files have +been applied. Then the regular expression will +match on /home/abc/public_html/abc and be applied. + +

    + + +Note that the default Apache access for <Directory /> is +Allow from All. This means that Apache will serve any file +mapped from an URL. It is recommended that you change this with a block +such as + +

    + <Directory />
    +     Order Deny,Allow
    +     Deny from All
    + </Directory>
    +
    +

    + +and then override this for directories you want accessible. +See the +Security Tips +page for more details. + +

    + +The directory sections typically occur in the access.conf file, but they +may appear in any configuration file. <Directory> directives cannot +nest, and cannot appear in a <Limit> section. +

    + +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +


    + +

    <DirectoryMatch>

    +Syntax: <DirectoryMatch regex> + ... </DirectoryMatch>
    +Context: server config, virtual host
    +Status: Core.
    +Compatibility: Available in Apache 1.3 and later + +

    <DirectoryMatch> and </DirectoryMatch> are used to enclose a +group of +directives which will apply only to the named directory and sub-directories +of that directory, the same as <Directory>. However, it takes as an +argument a regular expression. For example:

    + +
    +   <DirectoryMatch "^/www/.*/[0-9]{3}">
    +
    + +

    would match directories in /www/ that consisted of three numbers.

    + +

    See Also: +<Directory> for a description of how +regular expressions are mixed in with normal <Directory>s. +
    +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +


    + +

    DocumentRoot directive

    + +Syntax: DocumentRoot directory-filename
    +Default: DocumentRoot +/usr/local/apache/htdocs
    +Context: server config, virtual host
    +Status: core

    + +This directive sets the directory from which httpd will serve files. +Unless matched by a directive like Alias, the server appends the path +from the requested URL to the document root to make the path to the +document. Example: +

    DocumentRoot /usr/web
    +then an access to http://www.my.host.com/index.html refers +to /usr/web/index.html. + +

    There appears to be a bug in mod_dir which causes problems when the +DocumentRoot has a trailing slash (i.e. "DocumentRoot /usr/web/") so +please avoid that. + +


    + +

    ErrorDocument directive

    + +Syntax: ErrorDocument error-code document
    +Context: server config, virtual host, directory, +.htaccess
    +Status: core
    +Override: FileInfo
    +Compatibility: The directory and .htaccess contexts +are only available in Apache 1.1 and later.

    + +In the event of a problem or error, Apache can be configured to do +one of four things, + +

      +
    1. output a simple hardcoded error message +
    2. output a customized message +
    3. redirect to a local URL to handle the problem/error +
    4. redirect to an external URL to handle the problem/error +
    + +

    The first option is the default, while options 2-4 are configured +using the ErrorDocument directive, which is followed by +the HTTP response code and a message or URL. + +

    Messages in this context begin with a single quote +("), which does not form part of the message itself. +Apache will sometimes offer additional information regarding the +problem/error. + +

    URLs can begin with a slash (/) for local URLs, or be a full +URL which the client can resolve. Examples: +

    +ErrorDocument 500 http://foo.example.com/cgi-bin/tester
    +ErrorDocument 404 /cgi-bin/bad_urls.pl
    +ErrorDocument 401 /subscription_info.html
    +ErrorDocument 403 "Sorry can't allow you access today +
    + +

    Note that when you specify an ErrorDocument that +points to a remote URL (ie. anything with a method such as "http" in +front of it) Apache will send a redirect to the client to tell it +where to find the document, even if the document ends up being +on the same server.. This has several implications, the +most important being that if you use an "ErrorDocument 401" +directive then it must refer to a local document. This results +from the nature of the HTTP basic authentication scheme. + +

    See Also: documentation of customizable +responses.


    + +

    ErrorLog directive

    + +Syntax: ErrorLog filename|syslog +
    +Default: ErrorLog logs/error_log
    +Context: server config, virtual host
    +Status: core

    + +The error log directive sets the name of the file to which the server will log +any errors it encounters. If the filename does not begin with a slash (/) +then it is assumed to be relative to the ServerRoot. +If the filename begins with a pipe (|) then it is assumed to be a command to +spawn to handle the error log. + +

    Apache 1.3 and above: +Using syslog instead of a filename enables logging via syslogd(8) +if the system supports it. + +

    +SECURITY: See the +security tips +document for details on why your security could be compromised if +the directory where logfiles are stored is writable by anyone other +than the user that starts the server. + +

    See also: LogLevel +


    + +

    <Files> directive

    +Syntax: <Files filename> +... </Files>
    +Context: server config, virtual host, .htaccess
    +Status: core
    +Compatibility: only available in Apache +1.2 and above.

    + +

    The <Files> directive provides for access control by +filename. It is comparable to the <Directory> directive and +<Location> directives. It +should be matched with a </Files> directive. The +directives given within this section will be applied to any +object with a basename (last component of filename) matching +the specified filename. +<Files> sections are processed in the +order they appear in the configuration file, after the +<Directory> sections and .htaccess files are +read, but before <Location> sections. Note that +<Files> can be nested inside <Directory> +sections to restrict the portion of the filesystem they +apply to.

    + +

    The filename argument should include a filename, or a +wild-card string, where `?' matches any single character, and `*' matches any +sequences of characters. Extended regular expressions can also be used, +with the addition of +the ~ character. For example:

    + +
    +   <Files ~ "\.(gif|jpe?g|png)$">
    +
    + +would match most common Internet graphics formats. In Apache 1.3 and +later, <FilesMatch> is preferred, +however. + +

    Note that unlike <Directory> and <Location> sections, +<Files> sections can be used inside .htaccess +files. This allows users to control access to their own files, at a +file-by-file level. + +

    + +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +


    + +

    <FilesMatch>

    +Syntax: <FilesMatch regex> +... </Files>
    +Context: server config, virtual host, .htaccess
    +Status: core
    +Compatibility: only available in Apache +1.3 and above.

    + +

    The <FilesMatch> directive provides for access control by +filename, just as the <Files> directive +does. However, it accepts a regular expression. For example:

    + +
    +   <FilesMatch "\.(gif|jpe?g|png)$">
    +
    + +

    would match most common Internet graphics formats.

    + +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +
    + +

    Group directive

    + +Syntax: Group unix-group
    +Default: Group #-1
    +Context: server config, virtual host
    +Status: core

    + +The Group directive sets the group under which the server will answer requests. +In order to use this directive, the stand-alone server must be run initially +as root. Unix-group is one of: +

    +
    A group name +
    Refers to the given group by name. +
    # followed by a group number. +
    Refers to a group by its number. +
    + +It is recommended that you set up a new group specifically for running the +server. Some admins use user nobody, but this is not always +possible or desirable.

    + +Note: if you start the server as a non-root user, it will fail to change +to the specified group, and will instead continue to run as the group of the +original user.

    + +Special note: Use of this directive in <VirtualHost> requires a +properly configured suEXEC wrapper. +When used inside a <VirtualHost> in this manner, only the group +that CGIs are run as is affected. Non-CGI requests are still processed +as the group specified in the main Group directive.

    + +SECURITY: See User for a discussion of the security +considerations.


    + +

    HostNameLookups directive

    + +Syntax: HostNameLookups on | off | double
    +Default: HostNameLookups off
    +Context: server config, virtual host, directory, +.htaccess
    +Status: core
    +Compatibility: double available only in +Apache +1.3 and above.
    +Compatibility: Default was on prior to +Apache 1.3.

    + +This directive enables DNS lookups so that host names can be logged (and +passed to CGIs/SSIs in REMOTE_HOST). +The value double refers to doing double-reverse DNS. +That is, after a reverse lookup is performed, a forward lookup is then +performed on that result. At least one of the ip addresses in the forward +lookup must match the original address. (In "tcpwrappers" terminology +this is called PARANOID.)

    + +Regardless of the setting, when mod_access +is used for controlling access by hostname, a double reverse lookup +will be performed. This is necessary for security. Note that the +result of this double-reverse isn't generally available unless +you set HostnameLookups double. For example, if only +HostnameLookups on and a request is made to an object that +is protected by hostname restrictions, regardless of whether the +double-reverse fails or not, CGIs will still be passed the single-reverse +result in REMOTE_HOST.

    + +The default for this directive was previously on in +versions of Apache prior to 1.3. It was changed to off +in order to save the network traffic for those sites that don't truly +need the reverse lookups done. It is also better for the end users +because they don't have to suffer the extra latency that a lookup +entails. +Heavily loaded sites should leave this directive off, since DNS +lookups can take considerable amounts of time. The utility logresolve, +provided in the /support directory, can be used to look up host names +from logged IP addresses offline.


    + +

    IdentityCheck directive

    + +Syntax: IdentityCheck boolean
    +Default: IdentityCheck off
    +Context: server config, virtual host, directory
    +Status: core

    + +This directive enables RFC1413-compliant logging of the remote user name +for each connection, where the client machine runs identd or something similar. +This information is logged in the access log. Boolean is either +on or off.

    + +The information should not be trusted in any way except for rudimentary usage +tracking.

    + +Note that this can cause serious latency problems accessing your server +since every request requires one of these lookups to be performed. When +firewalls are involved each lookup might possibly fail and add 30 seconds +of latency to each hit. So in general this is not very useful on public +servers accessible from the Internet. +


    + +

    <IfModule> directive

    +Syntax: <IfModule [!]module-name> + ... +</IfModule>
    +Default: None
    +Context: all
    +Status: Core
    +Compatibility: IfModule is only available in 1.2 and +later.

    + +

    + +The <IfModule test>...</IfModule> +section is used to mark directives that are conditional. The +directives within an IfModule section are only +processed if the test is true. If test +is false, everything between the start and end markers +is ignored.

    + +The test in the <IfModule> section directive +can be one of two forms: + +

      +
    • module name +
    • !module name +
    + +

    In the former case, the directives between the start and end markers +are only processed if the module named module name is compiled +in to Apache. The second format reverses the test, and only processes +the directives if module name is not compiled in. + +

    The module name argument is a module name as given as the file +name of the module, at the time it was compiled. For example, +mod_rewrite.c. + +

    <IfModule> sections are nest-able, which can be used to implement +simple multiple-module tests. + +


    + +

    Include directive

    +Syntax: (Apache 1.2) Include filename
    +Context: server config
    +Status: Core
    +Compatibility: Include is only available in Apache 1.3 +and later. +

    +This directive allows inclusion of other configuration files from within the +server configuration files. + +


    + +

    KeepAlive directive

    +Syntax: (Apache 1.1) KeepAlive max-requests
    +Default: (Apache 1.1) KeepAlive 5
    +Syntax: (Apache 1.2) KeepAlive on/off
    +Default: (Apache 1.2) KeepAlive On
    +Context: server config
    +Status: Core
    +Compatibility: KeepAlive is only available in Apache +1.1 and later.

    + +This directive enables +Keep-Alive +support. + +

    Apache 1.1: Set max-requests +to the maximum number of requests you want Apache to entertain per +request. A limit is imposed to prevent a client from hogging your +server resources. Set this to 0 to disable support. + +

    Apache 1.2 and later: Set to "On" to enable +persistent connections, "Off" to disable. See also the MaxKeepAliveRequests directive.


    + +

    KeepAliveTimeout directive

    +Syntax: KeepAliveTimeout seconds
    +Default: KeepAliveTimeout 15
    +Context: server config
    +Status: Core
    +Compatibility: KeepAliveTimeout is only available in +Apache 1.1 and later.

    + +The number of seconds Apache will wait for a subsequent request before +closing the connection. Once a request has been received, the timeout +value specified by the Timeout directive +applies. +


    + +

    <Limit> directive

    + +Syntax: + <Limit method method ... > ... </Limit>
    +Context: any
    +Status: core

    + +<Limit> and </Limit> are used to enclose a group of +access control directives which will then apply only to the specified +access methods, where method is any valid HTTP method. +Any directive except another <Limit> or +<Directory> may be used; the majority will be +unaffected by the <Limit>. Example: +

    +<Limit GET POST>
    +require valid-user
    +</Limit>
    + +If an access control directive appears outside a <Limit> +directive, then it applies to all access methods. The method names +listed can be one or more of: GET, POST, PUT, DELETE, CONNECT or +OPTIONS. If GET is used it will also restrict HEAD requests. +If you wish to limit all methods, do not include any +<Limit> directive at all.


    + +

    Listen directive

    +Syntax: +Listen [IP address:]port number
    +Context: server config
    +Status: core
    +Compatibility: Listen is only available in Apache +1.1 and later.

    + +

    The Listen directive instructs Apache to listen to more than one IP +address or port; by default it responds to requests on all IP +interfaces, but only on the port given by the Port directive.

    + +Listen can be used instead of BindAddress and Port. It tells +the server to accept incoming requests on the specified port or +address-and-port combination. If the first format is used, with a port +number only, the server listens to the given port on all interfaces, +instead of the port given by the Port directive. If an IP +address is given as well as a port, the server will listen on the +given port and interface.

    + +Note that you may still require a Port directive so +that URLs that Apache generates that point to your server still +work.

    + +Multiple Listen directives may be used +to specify a number of addresses and ports to listen to. The server +will respond to requests from any of the listed addresses and +ports. +

    + +For example, to make the server accept connections on both port +80 and port 8000, use: +

    +   Listen 80
    +   Listen 8000
    +
    + +To make the server accept connections on two specified +interfaces and port numbers, use +
    +   Listen 192.170.2.1:80
    +   Listen 192.170.2.5:8000
    +
    + +

    See Also: +DNS Issues
    +See Also: +Setting which addresses and ports Apache uses
    +See Also: +Known Bugs +

    +
    + +

    ListenBacklog directive

    +Syntax: ListenBacklog backlog
    +Default: ListenBacklog 511
    +Context: server config
    +Status: Core
    +Compatibility: ListenBacklog is only available in Apache +versions after 1.2.0.

    + +The maximum length of the queue of pending connections. Generally no +tuning is needed or desired, however on some systems it is desirable +to increase this when under a TCP SYN flood attack. See +the backlog parameter to the listen(2) system call.


    + +

    <Location> directive

    + +Syntax: <Location URL> +... </Location>
    +Context: server config, virtual host
    +Status: core
    +Compatibility: Location is only available in Apache +1.1 and later.

    + +

    The <Location> directive provides for access control by +URL. It is similar to the <Directory> directive, and +starts a subsection which is terminated with a </Location> +directive. <Location> sections are processed in the +order they appear in the configuration file, after the +<Directory> sections and .htaccess files are +read, and after the <Files> sections.

    + +

    Note that URLs do not have to line up with the filesystem at all, +it should be emphasized that <Location> operates completely outside +the filesystem. + +

    For all origin (non-proxy) requests, the URL to be matched is +of the form /path/, and you should not include any +http://servername prefix. For proxy requests, the URL +to be matched is of the form scheme://servername/path, +and you must include the prefix. + +

    The URL may use wildcards In a wild-card string, `?' matches any +single character, and `*' matches any sequences of characters. + +

    Apache 1.2 and above: +Extended regular expressions can also be used, with the addition of +the ~ character. + +For example:

    + +
    +   <Location ~ "/(extra|special)/data">
    +
    + +

    would match URLs that contained the substring "/extra/data" or +"/special/data". In Apache 1.3 and above, a new directive +<LocationMatch> exists which +behaves identical to the regex version of +<Location>. + +

    The Location functionality is especially useful when +combined with the SetHandler directive. For example, +to enable status requests, but allow them only +from browsers at foo.com, you might use: + +

    +    <Location /status>
    +    SetHandler server-status
    +    order deny,allow
    +    deny from all
    +    allow from .foo.com
    +    </Location>
    +
    + +

    Apache 1.3 and above note about / (slash): The slash +character has special +meaning depending on where in a URL it appears. People may be used +to its behaviour in the filesystem where multiple adjacent slashes are +frequently collapsed to a single slash (i.e. /home///foo +is the same as /home/foo). In URL-space this is not +necessarily true. The <LocationMatch> directive +and the regex version of <Location> require you +to explicitly specify multiple slashes if that is your intention. +For example, <LocationMatch ^/abc> would match the +request URL /abc but not the request URL //abc. +The (non-regex) <Location> directive behaves +similarly when used for proxy requests. But when (non-regex) +<Location> is used for non-proxy requests it will +implicitly match multiple slashes with a single slash. For example, +if you specify <Location /abc/def> and the request +is to /abc//def then it will match. + +

    +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +


    + +

    <LocationMatch>

    + +Syntax: <LocationMatch regex> +... </LocationMatch>
    +Context: server config, virtual host
    +Status: core
    +Compatibility: Location is only available in Apache +1.3 and later.

    + +

    The <LocationMatch> directive provides for access control by +URL, in an identical manner to <Location>. However, it takes a regular +expression as an argument instead of a simple string. For example:

    + +
    +   <LocationMatch "/(extra|special)/data">
    +
    + +

    would match URLs that contained the substring "/extra/data" or +"/special/data".

    + +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +
    + +

    LockFile directive

    +Syntax: LockFile filename
    +Default: LockFile logs/accept.lock
    +Context: server config
    +Status: core

    + +The LockFile directive sets the path to the lockfile used when +Apache is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or +USE_FLOCK_SERIALIZED_ACCEPT. This directive should normally be +left at its default value. The main reason for changing it is if +the logs directory is NFS mounted, since the lockfile +must be stored on a local disk. The PID of the main +server process is automatically appended to the filename.

    + +SECURITY: It is best to avoid putting this file in a +world writable directory such as /var/tmp because someone +could create a denial of service attack and prevent the server from +starting by creating a lockfile with the same name as the one the +server will try to create.

    + +


    + +

    LogLevel directive

    +Syntax: LogLevel level
    +Default: LogLevel error
    +Context: server config, virtual host
    +Status: core
    +Compatibility: LogLevel is only available in 1.3 or +later. + +

    LogLevel adjusts the verbosity of the messages recorded in the +error logs (see ErrorLog directive). +The following levels are available, in order of +decreasing significance: + +

    +
    Level + Description +
    Example +
    emerg + Emergencies - system is unusable. +
    "Child cannot open lock file. Exiting" +
    alert + Action must be taken immediately. +
    "getpwuid: couldn't determine user name from uid" +
    crit + Critical Conditions. +
    "socket: Failed to get a socket, exiting child" +
    error + Error conditions. +
    "Premature end of script headers" +
    warn + Warning conditions. +
    "child process 1234 did not exit, sending another SIGHUP" +
    notice + Normal but significant condition. +
    "httpd: caught SIGBUS, attempting to dump core in ..." +
    info + Informational. +
    "Server seems busy, (you may need to increase StartServers, or + Min/MaxSpareServers)..." +
    debug + Debug-level messages +
    "Opening config file ..." +
    + +

    When a particular level is specified, messages from all other levels +of higher significance will be reported as well. E.g., when +LogLevel info is specified, then messages with log levels of +notice and warn will also be posted. +

    +Using a level of at least crit is recommended. +


    + +

    MaxClients directive

    + +Syntax: MaxClients number
    +Default: MaxClients 256
    +Context: server config
    +Status: core

    + +The MaxClients directive sets the limit on the number of simultaneous +requests that can be supported; not more than this number of child server +processes will be created. To configure more than 256 clients, you must +edit the HARD_SERVER_LIMIT entry in httpd.h and recompile.


    + +

    MaxKeepAliveRequests directive

    +Syntax: MaxKeepAliveRequests number
    +Default: MaxKeepAliveRequests 100
    +Context: server config
    +Status: core
    +Compatibility: Only available in Apache +1.2 and later. + +

    The MaxKeepAliveRequests directive limits the number of requests +allowed per connection when KeepAlive is +on. If it is set to "0", unlimited requests will be +allowed. We recommend that this setting be kept to a high value for +maximum server performance.


    + +

    MaxRequestsPerChild directive

    + +Syntax: MaxRequestsPerChild number
    +Default: MaxRequestsPerChild 0
    +Context: server config
    +Status: core

    + +The MaxRequestsPerChild directive sets the limit on the number of requests +that an individual child server process will handle. After MaxRequestsPerChild +requests, the child process will die. If MaxRequestsPerChild is 0, then +the process will never expire.

    + +Setting MaxRequestsPerChild to a non-zero limit has two beneficial effects: +

      +
    • it limits the amount of memory that process can consume by (accidental) +memory leakage; +
    • by giving processes a finite lifetime, it helps reduce the +number of processes when the server load reduces. +
    + +

    This directive has no effect on Win32. + +


    + +

    MaxSpareServers directive

    + +Syntax: MaxSpareServers number
    +Default: MaxSpareServers 10
    +Context: server config
    +Status: core

    + +The MaxSpareServers directive sets the desired maximum number of idle +child server processes. An idle process is one which is not handling +a request. If there are more than MaxSpareServers idle, then the parent +process will kill off the excess processes.

    + +Tuning of this parameter should only be necessary on very busy sites. +Setting this parameter to a large number is almost always a bad idea.

    + +This directive has no effect when used with the Apache Web server on a +Microsoft Windows platform. + +

    + +See also MinSpareServers and +StartServers.


    + +

    MinSpareServers directive

    + +Syntax: MinSpareServers number
    +Default: MinSpareServers 5
    +Context: server config
    +Status: core

    + +The MinSpareServers directive sets the desired minimum number of idle +child server processes. An idle process is one which is not handling +a request. If there are fewer than MinSpareServers idle, then the parent +process creates new children at a maximum rate of 1 per second.

    + +Tuning of this parameter should only be necessary on very busy sites. +Setting this parameter to a large number is almost always a bad idea.

    + +This directive has no effect on Microsoft Windows. + +

    + +See also MaxSpareServers and +StartServers.


    + +

    NameVirtualHost directive

    + +Syntax: NameVirtualHost addr[:port]
    +Context: server config
    +Status: core

    +Compatibility: NameVirtualHost is only available in +Apache 1.3 and later

    + +The NameVirtualHost directive is a required directive if you want to configure +name-based virtual hosts.

    + +Although addr can be hostname it is recommended that you always use +an IP address, e.g. + +

    NameVirtualHost 111.22.33.44
    + +With the NameVirtualHost directive you specify the address to which your +name-based virtual host names resolve. If you have multiple name-based +hosts on multiple addresses, repeat the directive for each address.

    + +Note: the "main server" and any _default_ servers will never +be served for a request to a NameVirtualHost IP Address (unless for some +reason you specify NameVirtualHost but then don't define any VirtualHosts +for that address).

    + +Optionally you can specify a port number on which the name-based +virtual hosts should be used, e.g. + +

    NameVirtualHost 111.22.33.44:8080
    + +See also: +Apache Virtual Host documentation + +

    Options directive

    + +Syntax: Options [+|-]option [+|-]option ...
    +Context: server config, virtual host, directory, +.htaccess
    +Override: Options
    +Status: core

    + +The Options directive controls which server features are available in +a particular directory. +

    +option can be set to None, in which case none of +the extra features are enabled, or one or more of the following: +

    +
    All +
    All options except for MultiViews. +
    ExecCGI +
    + +Execution of CGI scripts is permitted. +
    FollowSymLinks +
    + +The server will follow symbolic links in this directory. +Note: even though the server follows the symlink it +does not +change the pathname used to match against <Directory> +sections. +
    Includes +
    + +Server-side includes are permitted. +
    IncludesNOEXEC +
    + +Server-side includes are permitted, but the #exec command and +#include of CGI scripts are disabled. +
    Indexes +
    + +If a URL which maps to a directory is requested, and the there is no +DirectoryIndex (e.g. index.html) in that directory, then the server will +return a formatted listing of the directory. +
    MultiViews +
    + +Content negotiated MultiViews are +allowed. +
    SymLinksIfOwnerMatch +
    + +The server will only follow symbolic links for which the target +file or directory is owned by the same user id as the link. +
    + +Normally, if multiple Options could apply to a directory, +then the most specific one is taken complete; the options are not +merged. However if all the options on the Options +directive are preceded by a + or - symbol, the options are +merged. Any options preceded by a + are added to the options +currently in force, and any options preceded by a - are removed from +the options currently in force.

    + +For example, without any + and - symbols: + +

    +<Directory /web/docs>
    +Options Indexes FollowSymLinks
    +</Directory>
    +<Directory /web/docs/spec>
    +Options Includes
    +</Directory> +
    +then only Includes will be set for the /web/docs/spec +directory. However if the second Options directive uses the + +and - symbols:

    + +

    +<Directory /web/docs>
    +Options Indexes FollowSymLinks
    +</Directory>
    +<Directory /web/docs/spec>
    +Options +Includes -Indexes
    +</Directory> +
    +then the options FollowSymLinks and Includes +are set for the /web/docs/spec directory.

    + +Note: Using -IncludesNOEXEC or +-Includes +disables server-side includes completely regardless of the previous setting.

    + +The default in the absence of any other settings is All.

    +


    + +

    PidFile directive

    + +Syntax: PidFile filename
    +Default: PidFile logs/httpd.pid
    +Context: server config
    +Status: core

    + +The PidFile directive sets the file to which the server records the +process id of the daemon. If the filename does not begin with a slash (/) +then it is assumed to be relative to the ServerRoot. +The PidFile is only used in standalone mode.

    + +It is often useful to be able to send the server a signal, so that it closes +and then reopens its ErrorLog and TransferLog, and +re-reads its configuration files. This is done by sending a SIGHUP (kill -1) +signal to the process id listed in the PidFile.

    + +The PidFile is subject to the same warnings about log file placement and +security. + +


    + +

    Port directive

    + +Syntax: Port number
    +Default: Port 80
    +Context: server config
    +Status: core

    + +Number is a number from 0 to 65535; some port numbers +(especially below +1024) are reserved for particular protocols. See /etc/services +for a list of some defined ports; the standard port for the http protocol +is 80.

    + +The Port directive has two behaviors, the first of which is necessary for +NCSA backwards compatibility (and which is confusing in the context of +Apache).

    + +

      +
    • +In the absence of any Listen or +BindAddress directives specifying a port number, +a Port directive given in the "main server" +(i.e. outside any <VirtualHost> section) +sets the network port on which the server listens. +If there are any Listen or BindAddress directives specifying +:number then Port has no effect on what address the server +listens at. + +
    • The Port directive +sets the SERVER_PORT environment variable (for +CGI and SSI), +and is used when the server must generate a URL that refers to itself +(for example when creating an external redirect to itself). This +behaviour is modified by +UseCanonicalName. +
    + +In no event does a Port setting affect +what ports a VirtualHost responds on, the +VirtualHost directive itself is used for that.

    + +The primary behaviour of Port should be considered to be similar to that of +the ServerName directive. The ServerName +and Port together specify what you consider to be the canonical +address of the server. +(See also UseCanonicalName.)

    + +Port 80 is one of Unix's special ports. All ports numbered +below 1024 are reserved for system use, i.e. regular (non-root) users cannot +make use of them; instead they can only use higher port numbers. +To use port 80, you must start the server from the root account. +After binding to the port and before accepting requests, Apache will change +to a low privileged user as set by the User directive.

    + +If you cannot use port 80, choose any other unused port. Non-root users +will have to choose a port number higher than 1023, such as 8000.

    + +SECURITY: if you do start the server as root, be sure +not to set User to root. If you run the server as +root whilst handling connections, your site may be open to a major security +attack.


    + +

    require directive

    + +Syntax: require entity-name entity entity...
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: core

    + +This directive selects which authenticated users can access a directory. +The allowed syntaxes are: +

      +
    • require user userid userid ...

      +Only the named users can access the directory.

      +

    • require group group-name group-name ...

      +Only users in the named groups can access the directory.

      +

    • require valid-user

      +All valid users can access the directory. +

    +

    +If require appears in a <Limit> +section, then it restricts access to the named methods, otherwise +it restricts access for all methods. Example: +

    +AuthType Basic
    +AuthName somedomain
    +AuthUserFile /web/users
    +AuthGroupFile /web/groups
    +<Limit GET POST>
    +require group admin
    +</Limit> +
    + +Require must be accompanied by AuthName and +AuthType directives, and directives such as +AuthUserFile and +AuthGroupFile (to define users and +groups) in order to work correctly.


    + +

    ResourceConfig directive

    + +Syntax: ResourceConfig filename
    +Default: ResourceConfig conf/srm.conf
    +Context: server config, virtual host
    +Status: core

    + +The server will read this file for more directives after reading the +httpd.conf file. Filename is relative to the +ServerRoot. +This feature can be disabled using: +

    ResourceConfig /dev/null
    +Historically, this file contained most directives except for server +configuration directives and <Directory> +sections; in fact it can now contain any server directive allowed in the +server config context.

    + +See also AccessConfig.


    + +

    RLimitCPU directive

    + +Syntax: RLimitCPU # or 'max' + [# or 'max'] +
    +Default: Unset; uses operating system defaults +
    +Context: server config, virtual host
    +Status: core
    +Compatibility: RLimitCPU is only available in Apache 1.2 +and later

    + +Takes 1 or 2 parameters. The first parameter sets the soft resource limit +for all processes and the second parameter sets the maximum resource limit. +Either parameter can be a number, or max to indicate to the server +that the limit should be set to the maximum allowed by the operating system +configuration. Raising the maximum resource limit requires that the server +is running as root, or in the initial startup phase.

    + +CPU resource limits are expressed in seconds per process.

    + +See also RLimitMEM or +RLimitNPROC.


    + +

    RLimitMEM directive

    + +Syntax: RLimitMEM # or 'max' + [# or 'max']
    +Default: Unset; uses operating system defaults +
    +Context: server config, virtual host
    +Status: core
    +Compatibility: RLimitMEM is only available in Apache 1.2 +and later

    + +Takes 1 or 2 parameters. The first parameter sets the soft resource limit for +all processes and the second parameter sets the maximum resource limit. Either +parameter can be a number, or max to indicate to the server that the +limit should be set to the maximum allowed by the operating system +configuration. Raising the maximum resource limit requires that the +server is running as root, or in the initial startup phase.

    + +Memory resource limits are expressed in bytes per process.

    + +See also RLimitCPU or +RLimitNPROC.


    + +

    RLimitNPROC directive

    + +Syntax: RLimitNPROC # or 'max' + [# or 'max']
    +Default: Unset; uses operating system defaults +
    +Context: server config, virtual host
    +Status: core
    +Compatibility: RLimitNPROC is only available in Apache +1.2 and later

    + +Takes 1 or 2 parameters. The first parameter sets the soft resource limit +for all processes and the second parameter sets the maximum resource limit. +Either parameter can be a number, or max to indicate to the server +that the limit should be set to the maximum allowed by the operating system +configuration. Raising the maximum resource limit requires that the server +is running as root, or in the initial startup phase.

    + +Process limits control the number of processes per user.

    + +Note: If CGI processes are not running under userids other +than the +web server userid, this directive will limit the number of processes that the +server itself can create. Evidence of this situation will be indicated by +cannot fork messages in the error_log.

    + +See also RLimitMEM or +RLimitCPU. + +


    + +

    Satisfy directive

    + +Syntax: Satisfy 'any' or 'all'
    +Default: Satisfy all
    +Context: directory, .htaccess
    +Status: core
    +Compatibility: Satisfy is only available in Apache 1.2 +and later

    + +Access policy if both allow and require used. The parameter can be +either 'all' or 'any'. This directive is only useful +if access to a particular area is being restricted by both +username/password and client host address. In this case the +default behavior ("all") is to require that the client passes the +address access restriction and enters a valid username and +password. With the "any" option the client will be granted access if +they either pass the host restriction or enter a valid username and +password. This can be used to password restrict an area, but to let +clients from particular addresses in without prompting for a password. + + +


    + +

    ScoreBoardFile directive

    + +Syntax: ScoreBoardFile filename
    +Default: ScoreBoardFile logs/apache_status +
    +Context: server config
    +Status: core

    + +The ScoreBoardFile directive is required on some architectures to place +a file that the server will use to communicate between its children and +the parent. The easiest way to find out if your architecture requires +a scoreboard file is to run Apache and see if it creates the file named +by the directive. If your architecture requires it then you must ensure +that this file is not used at the same time by more than one invocation +of Apache.

    + +If you have to use a ScoreBoardFile then you may see improved speed by +placing it on a RAM disk. But be careful that you heed the same warnings +about log file placement and +security.

    + +Apache 1.2 and above:

    + +Linux 1.x users might be able to add +-DHAVE_SHMGET -DUSE_SHMGET_SCOREBOARD to +the EXTRA_CFLAGS in your Configuration. This +might work with some 1.x installations, but won't work with all of +them. (Prior to 1.3b4, HAVE_SHMGET would have sufficed.)

    + +SVR4 users should consider adding +-DHAVE_SHMGET -DUSE_SHMGET_SCOREBOARD to the +EXTRA_CFLAGS in your Configuration. This +is believed to work, but we were unable to test it in time for 1.2 +release. (Prior to 1.3b4, HAVE_SHMGET would have sufficed.)

    + +See Also: +Stopping and Restarting Apache

    + +


    + +

    SendBufferSize directive

    + +Syntax: SendBufferSize bytes
    +Context: server config
    +Status: core

    + +The server will set the TCP buffer size to the number of bytes +specified. Very useful to increase past standard OS defaults on high +speed high latency (i.e. 100ms or so, such as transcontinental +fast pipes) +


    + +

    ServerAdmin directive

    + +Syntax: ServerAdmin email-address
    +Context: server config, virtual host
    +Status: core

    + +The ServerAdmin sets the e-mail address that the server includes in any +error messages it returns to the client.

    + +It may be worth setting up a dedicated address for this, e.g. +

    ServerAdmin www-admin@foo.bar.com
    +as users do not always mention that they are talking about the server!


    + +

    ServerAlias directive

    + +Syntax: ServerAlias host1 host2 ...
    +Context: virtual host
    +Status: core
    +Compatibility: ServerAlias is only available in Apache +1.1 and later.

    + +The ServerAlias directive sets the alternate names for a host, for use +with +name-based virtual hosts. + +

    See also: +Apache Virtual Host documentation + +


    + +

    ServerName directive

    + +Syntax: ServerName fully-qualified domain name +
    +Context: server config, virtual host
    +Status: core

    + +The ServerName directive sets the hostname of the server; this is only +used when creating redirection URLs. If it is not specified, then the +server attempts to deduce it from its own IP address; however this may +not work reliably, or may not return the preferred hostname. For example: +

    ServerName www.wibble.com
    +would be used if the canonical (main) name of the actual machine +were monster.wibble.com.

    +

    See Also:
    +DNS Issues
    +UseCanonicalName
    +

    +
    + +

    ServerPath directive

    + +Syntax: ServerPath pathname
    +Context: virtual host
    +Status: core
    +Compatibility: ServerPath is only available in Apache +1.1 and later.

    + +The ServerPath directive sets the legacy URL pathname for a host, for +use with name-based virtual hosts. + +

    See also: +Apache Virtual Host documentation + +


    + +

    ServerRoot directive

    + +Syntax: ServerRoot directory-filename
    +Default: ServerRoot /usr/local/apache
    +Context: server config
    +Status: core

    + +The ServerRoot directive sets the directory in which the server lives. +Typically it will contain the subdirectories conf/ and +logs/. Relative paths for other configuration files are taken +as relative to this directory.

    + +See also the -d option to httpd.

    +See also the security tips +for information on how to properly set permissions on the ServerRoot.

    + +


    + +

    ServerSignature directive

    + +Syntax: ServerSignature Off | On | EMail
    +Default: ServerSignature Off
    +Context: server config, virtual host, directory, +.htaccess
    +Status: core
    +Compatibility: ServerSignature is only available in +Apache +1.3 and later.

    + +The ServerSignature directive allows the configuration of a trailing +footer line under server-generated documents (error messages, +mod_proxy ftp directory listings, mod_info output, ...). The reason +why you would want to enable such a footer line is that in a chain +of proxies, the user often has no possibility to tell which of the +chained servers actually produced a returned error message.
    +The Off setting, which is the default, suppresses the +error line (and is therefore compatible with the behavior of +Apache-1.2 and below). The On setting simply adds a +line with the server version number and ServerName of the serving virtual host, and +the EMail setting additionally creates a "mailto:" +reference to the ServerAdmin of the +referenced document. + +


    + +

    ServerTokens directive

    + +Syntax: ServerTokens Minimal|OS|Full
    +Default: ServerTokens Full
    +Context: server config
    +Status: core
    +Compatibility: ServerTokens is only available + in Apache 1.3 and later + +

    +This directive controls whether Server response header +field which is sent back to clients includes a description of the generic +OS-type of the server as well as information about compiled-in modules. +

    +
    +
    ServerTokens Min[imal] +
    +
    Server sends (e.g.): Server: Apache/1.3.0 +
    +
    ServerTokens OS +
    +
    Server sends (e.g.): Server: Apache/1.3.0 (Unix) +
    +
    ServerTokens Full (or not specified) +
    +
    Server sends (e.g.): Server: Apache/1.3.0 (Unix) PHP/3.0 + MyMod/1.2 +
    +
    +

    +This setting applies to the entire server, and cannot be enabled or +disabled on a virtualhost-by-virtualhost basis. +

    + +
    + +

    ServerType directive

    + +Syntax: ServerType type
    +Default: ServerType standalone
    +Context: server config
    +Status: core

    + +The ServerType directive sets how the server is executed by the system. +Type is one of +

    +
    inetd +
    The server will be run from the system process inetd; the command to start +the server is added to /etc/inetd.conf +
    standalone +
    The server will run as a daemon process; the command to start the server +is added to the system startup scripts. (/etc/rc.local or +/etc/rc3.d/....) +
    + +Inetd is the lesser used of the two options. For each http +connection received, a new copy of the server is started from scratch; +after the connection is complete, this program exits. There is a high price to +pay per connection, but for security reasons, some admins prefer this option. +Inetd mode is no longer recommended and does not always +work properly. Avoid it if at all possible. +

    + +Standalone is the most common setting for ServerType since +it is far more efficient. The server is started once, and services all +subsequent connections. If you intend running Apache to serve a busy site, +standalone will probably be your only option.

    + +

    StartServers directive

    + +Syntax: StartServers number
    +Default: StartServers 5
    +Context: server config
    +Status: core

    + +The StartServers directive sets the number of child server processes created +on startup. As the number of processes is dynamically controlled depending +on the load, there is usually little reason to adjust this parameter.

    + +

    When running under Microsoft Windows, this directive has no effect. + There is always one child which handles all requests. Within the + child requests are handled by separate threads. The + ThreadsPerChild directive controls + the maximum number of child threads handling requests, which will + have a similar effect to the setting of StartServers + on Unix. + +

    + +See also MinSpareServers and +MaxSpareServers.


    + +

    ThreadsPerChild

    +Syntax: ThreadsPerChild number
    +Default: ThreadsPerChild 50
    +Context: server config
    +Status: core (Windows)
    +Compatbility: Available only with Apache 1.3 and later +with Windows + +

    This directive tells the server how many threads it should use. This + is the maximum number of connections the server can handle at once; be + sure and set this number high enough for your site if you get a lot of + hits. + +

    This directive has no effect on Unix systems. Unix users should look + at StartServers and MaxRequestsPerChild.

    + +
    + +

    TimeOut directive

    + +Syntax: TimeOut number
    +Default: TimeOut 300
    +Context: server config
    +Status: core

    + +The TimeOut directive currently defines the amount of time Apache will +wait for three things: + +

      +
    1. The total amount of time it takes to receive a GET request. +
    2. The amount of time between receipt of TCP packets on a POST or + PUT request. +
    3. The amount of time between ACKs on transmissions of TCP packets + in responses. +
    + +We plan on making these separately configurable at some point down the +road. The timer used to default to 1200 before 1.2, but has been +lowered to 300 which is still far more than necessary in most +situations. It is not set any lower by default because there may +still be odd places in the code where the timer is not reset when +a packet is sent. + +


    + +

    UseCanonicalName directive

    + + +Syntax: UseCanonicalName on|off
    + +Default: UseCanonicalName on
    + +Context: server config, virtual host, directory, .htaccess +
    + +Override: AuthConfig
    + +Compatibility: UseCanonicalName is only available in +Apache 1.3 and later

    + +In many situations Apache has to construct a self-referential +URL. That is, a URL which refers back to the same server. +With UseCanonicalName on (and in all versions prior to +1.3) Apache will use the ServerName and Port directives to construct a canonical name for the +server. This name is used in all self-referential URLs, and for the +values of SERVER_NAME and SERVER_PORT in CGIs. + +

    With UseCanonicalName off Apache will form +self-referential URLs using the hostname and port supplied +by the client if any are supplied (otherwise it will use the +canonical name). These values are the same that are used to +implement name based virtual +hosts, and are available with the same clients. The CGI variables +SERVER_NAME and SERVER_PORT will be constructed +from the client supplied values as well. + +

    An example where this may be useful is on an intranet server where +you have users connecting to the machine using short names such as +www. You'll notice that if the users type a shortname, +and a URL which is a directory, such as http://www/splat, +without the trailing slash then Apache will redirect them to +http://www.domain.com/splat/. If you have authentication +enabled, this will cause the user to have to reauthenticate twice (once +for www and once again for www.domain.com). +But if UseCanonicalName is set off, then Apache will redirect +to http://www/splat/. + +

    Warning: if CGIs make assumptions about the values of +SERVER_NAME they may be broken by this option. The client +is essentially free to give whatever value they want as a hostname. +But if the CGI is only using SERVER_NAME to construct +self-referential URLs then it should be just fine. + +

    See also: +ServerName, +Port + +


    + +

    User directive

    + +Syntax: User unix-userid
    +Default: User #-1
    +Context: server config, virtual host
    +Status: core

    + +The User directive sets the userid as which the server will answer requests. +In order to use this directive, the standalone server must be run initially +as root. Unix-userid is one of: +

    +
    A username +
    Refers to the given user by name. +
    # followed by a user number. +
    Refers to a user by their number. +
    + +The user should have no privileges which result in it being able to access +files which are not intended to be visible to the outside world, and +similarly, the user should not be able to execute code which is not +meant for httpd requests. It is recommended that you set up a new user and +group specifically for running the server. Some admins use user +nobody, but this is not always possible or desirable.

    + +Notes: If you start the server as a non-root user, it will fail to change +to the lesser privileged user, and will instead continue to run as +that original user. If you do start the server as root, then it is normal +for the parent process to remain running as root.

    + +Special note: Use of this directive in <VirtualHost> requires a +properly configured suEXEC wrapper. +When used inside a <VirtualHost> in this manner, only the user +that CGIs are run as is affected. Non-CGI requests are still processed +with the user specified in the main User directive.

    + +SECURITY: Don't set User (or Group) to +root unless you know exactly what you are doing, and what the +dangers are.


    + +

    <VirtualHost> directive

    + +Syntax: <VirtualHost addr[:port] + ...> ... +</VirtualHost>
    +Context: server config
    +Status: Core.
    +Compatibility: Non-IP address-based Virtual Hosting only +available in Apache 1.1 and later.
    +Compatibility: Multiple address support only available in +Apache 1.2 and later.

    + +<VirtualHost> and </VirtualHost> are used to enclose a group of +directives which will apply only to a particular virtual host. +Any directive which is allowed in a virtual host context may be used. +When the server receives a request for a document on a particular virtual +host, it uses the configuration directives enclosed in the <VirtualHost> +section. Addr can be +

    +
  • The IP address of the virtual host +
  • A fully qualified domain name for the IP address of the virtual host. +
  • Example: +
    + +<VirtualHost 10.1.2.3>
    +ServerAdmin webmaster@host.foo.com
    +DocumentRoot /www/docs/host.foo.com
    +ServerName host.foo.com
    +ErrorLog logs/host.foo.com-error_log
    +TransferLog logs/host.foo.com-access_log
    +</VirtualHost> +
    + +Each VirtualHost must correspond to a different IP address, different port +number or a +different host name for the server, in the latter case the server +machine must be configured to accept IP packets for multiple +addresses. (If the machine does not have multiple network interfaces, +then this can be accomplished with the ifconfig alias +command (if your OS supports it), or with kernel patches like VIF (for SunOS(TM) 4.1.x)).

    + +The special name _default_ can be specified in which case +this virtual host will match any IP address that is not explicitly listed +in another virtual host. In the absence of any _default_ virtual host +the "main" server config, consisting of all those definitions outside +any VirtualHost section, is used when no match occurs.

    + +You can specify a :port to change the port that is matched. +If unspecified then it defaults to the same port as the most recent +Port statement of the main server. You +may also specify :* to match all ports on that address. +(This is recommended when used with _default_.)

    + +SECURITY: See the +security tips +document for details on why your security could be compromised if +the directory where logfiles are stored is writable by anyone other +than the user that starts the server. + +

    NOTE: The use of <VirtualHost> does +not affect what addresses Apache listens on. You may +need to ensure that Apache is listening on the correct addresses using +either BindAddress or Listen. + +

    See also: +Apache Virtual Host documentation
    +See also: +Warnings about DNS and Apache
    +See also: +Setting which addresses and ports Apache uses
    +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received +

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/directive-dict.html b/APACHE_1_3b7/htdocs/manual/mod/directive-dict.html new file mode 100644 index 0000000000..a4c13e55f5 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/directive-dict.html @@ -0,0 +1,262 @@ + + + + Definitions of terms used to describe Apache directives + + + + + +

    Terms Used to Describe Apache Directives

    + +

    + Each Apache configuration directive is described using a common format + that looks like this: +

    +
    +
    Syntax: directive-name some args +
    + Default: + directive-name default-value +
    + Context: context-list +
    + Override: override +
    + Status: status +
    + Module: module-name +
    + Compatibility: compatibility notes +
    +
    +

    + Each of the directive's attributes, complete with possible values + where possible, are described in this document. +

    + +

    Directive Terms

    + + +
    +

    Syntax

    +

    + This indicates the format of the directive as it would appear in a + configuration file. This syntax is extremely directive-specific, so + refer to the text of the directive's description for details. +

    + +
    +

    Default

    +

    + If the directive has a default value (i.e., if you omit it + from your configuration entirely, the Apache Web server will behave as + though you set it to a particular value), it is described here. If + there is no default value, this section should say + "None". +

    + +
    +

    Context

    +

    + This indicates where in the server's configuration files the directive + is legal. It's a comma-separated list of one or more of the following + values: +

    +
    +
    server config +
    +
    This means that the directive may be used in the server + configuration files (e.g., httpd.conf, + srm.conf, and access.conf), but + not within any <VirtualHost> or + <Directory> containers. It is not allowed in + .htaccess files at all. +

    +

    +
    +
    virtual host +
    +
    This context means that the directive may appear inside + <VirtualHost> containers in the server + configuration files. +

    +

    +
    +
    directory +
    +
    A directive marked as being valid in this context may be used + inside <Directory> containers in the server + configuration files. +

    +

    +
    +
    .htaccess +
    +
    If a directive is valid in this context, it means that it can + appear inside per-directory .htaccess files. + It may not be processed, though depending upon the + overrides + currently active. +

    +

    +
    +
    +

    + The directive is only allowed within the designated context; + if you try to use it elsewhere, you'll get a configuration error that + will either prevent the server from handling requests in that context + correctly, or will keep the server from operating at all -- + i.e., the server won't even start. +

    +

    + The valid locations for the directive are actually the result of a + Boolean OR of all of the listed contexts. In other words, a directive + that is marked as being valid in "server config, + .htaccess" can be used in the httpd.conf file + and in .htaccess files, but not within any + <Directory> or <VirtualHost> containers. +

    + +
    +

    Override

    +

    + This directive attribute indicates which configuration override must + be active in order for the directive to be processed when it appears + in a .htaccess file. If the directive's + context + doesn't permit it to appear in .htaccess files, this + attribute should say "Not applicable". +

    +

    + Overrides are activated by the + AllowOverride + directive, and apply to a particular scope (such as a directory) and + all descendants, unless further modified by other + AllowOverride directives at lower levels. The + documentation for that directive also lists the possible override + names available. +

    + +
    +

    Status

    +

    + This indicates how tightly bound into the Apache Web server the + directive is; in other words, you may need to recompile the server + with an enhanced set of modules in order to gain access to the + directive and its functionality. Possible values for this attribute + are: +

    +
    +
    Core +
    +
    If a directive is listed as having "Core" status, that + means it is part of the innermost portions of the Apache Web server, + and is always available. +

    +

    +
    +
    Base +
    +
    A directive labeled as having "Base" status is + supported by one of the standard Apache modules which is compiled + into the server by default, and is therefore normally available + unless you've taken steps to remove the module from your configuration. +

    +

    +
    +
    Extension +
    +
    A directive with "Extension" status is provided by one + of the modules included with the Apache server kit, but the module + isn't normally compiled into the server. To enable the directive + and its functionality, you will need to change the server build + configuration files and re-compile Apache. +

    +

    +
    +
    Experimental +
    +
    "Experimental" status indicates that the directive is + available as part of the Apache kit, but you're on your own if you + try to use it. The directive is being documented for completeness, + and is not necessarily supported. The module which provides the + directive may or may not be compiled in by default; check the top of + the page which describes the directive and its module to see if it + remarks on the availability. +

    +

    +
    +
    + +
    +

    Module

    +

    + This quite simply lists the name of the source module which defines + the directive. +

    + +
    +

    Compatibility

    +

    + If the directive wasn't part of the original Apache version 1 + distribution, the version in which it was introduced should be listed + here. If the directive has the same name as one from the NCSA HTTPd + server, any inconsistencies in behaviour between the two should also + be mentioned. Otherwise, this attribute should say "No + compatibility issues." +

    + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/directives.html b/APACHE_1_3b7/htdocs/manual/mod/directives.html new file mode 100644 index 0000000000..ae2952f62f --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/directives.html @@ -0,0 +1,210 @@ + + + +Apache directives + + + + + +

    Apache Directives

    +

    +Each Apache directive available in the standard Apache distribution is +listed here. They are described using a consistent format, and there is +a dictionary +of the terms used in their descriptions available. +

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/footer.html b/APACHE_1_3b7/htdocs/manual/mod/footer.html new file mode 100644 index 0000000000..7fe745dcfd --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/footer.html @@ -0,0 +1,8 @@ +
    + +

    + Apache HTTP Server Version 1.3 +

    + +Index +Home diff --git a/APACHE_1_3b7/htdocs/manual/mod/header.html b/APACHE_1_3b7/htdocs/manual/mod/header.html new file mode 100644 index 0000000000..5662300029 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/header.html @@ -0,0 +1,6 @@ +
    + [APACHE DOCUMENTATION] +

    + Apache HTTP Server Version 1.3 +

    +
    diff --git a/APACHE_1_3b7/htdocs/manual/mod/index.html b/APACHE_1_3b7/htdocs/manual/mod/index.html new file mode 100644 index 0000000000..f003071e9f --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/index.html @@ -0,0 +1,120 @@ + + + +Apache modules + + + + + +

    Apache modules

    + +

    +Below is a list of all of the modules that come as part of the +Apache distribution. See also the complete alphabetical list of +all Apache directives. +

    + +
    +
    Core +
    Core Apache features. +
    mod_access +
    Host based access control. +
    mod_actions Apache 1.1 and later. +
    Filetype/method-based script execution +
    mod_alias +
    Aliases and redirects. +
    mod_asis +
    The .asis file handler. +
    mod_auth +
    User authentication using text files. +
    mod_auth_anon +
    Anonymous user authentication, FTP-style. +
    mod_auth_db +
    User authentication using Berkeley DB files. +
    mod_auth_dbm +
    User authentication using DBM files. +
    mod_autoindex +
    Automatic directory listings. +
    mod_browser Apache 1.2.* only +
    Set environment variables based on User-Agent strings. Replaced by + mod_setenvif in Apache 1.3 and up +
    mod_cern_meta +
    Support for HTTP header metafiles. +
    mod_cgi +
    Invoking CGI scripts. +
    mod_cookies up to Apache 1.1.1 +
    Support for Netscape-like cookies. Replaced in Apache 1.2 by +mod_usertrack +
    mod_digest +
    MD5 authentication +
    mod_dir +
    Basic directory handling. +
    mod_dld Apache 1.2.* and earlier +
    Start-time linking with the GNU libdld. Replaced in Apache 1.3 by mod_so +
    mod_dll Apache 1.3b1 to 1.3b5 only +
    Replaced in 1.3b6 by mod_so +
    mod_env +
    Passing of environments to CGI scripts +
    mod_example Apache 1.2 and up +
    Demonstrates Apache API +
    mod_expires Apache 1.2 and up +
    Apply Expires: headers to resources +
    mod_headers Apache 1.2 and up +
    Add arbitrary HTTP headers to resources +
    mod_imap +
    The imagemap file handler. +
    mod_include +
    Server-parsed documents. +
    mod_info +
    Server configuration information +
    mod_isapi +
    Windows ISAPI Extension support +
    mod_log_agent +
    Logging of User Agents. +
    mod_log_common up to Apache 1.1.1 +
    Standard logging in the Common Logfile Format. Replaced by the +mod_log_config module in Apache 1.2 and up +
    mod_log_config +
    User-configurable logging replacement for mod_log_common. +
    mod_log_referer +
    Logging of document references. +
    mod_mime +
    Determining document types using file extensions. +
    mod_mime_magic +
    Determining document types using "magic numbers". +
    mod_mmap_static +
    Mapping files into memory for faster serving. +
    mod_negotiation +
    Content negotiation. +
    mod_proxy +
    Caching proxy abilities +
    mod_rewrite Apache 1.2 and up +
    Powerful URI-to-filename mapping using regular expressions +
    mod_setenvif Apache 1.3 and up +
    Set environment variables based on client information +
    mod_so Apache 1.3 and up +
    Experimental support for loading modules (DLLs on Windows) at runtime +
    mod_speling Apache 1.3 and up +
    Automatically correct minor typos in URLs +
    mod_status +
    Server status display +
    mod_userdir +
    User home directories. +
    mod_unique_id Apache 1.3 and up +
    Generate unique request identifier for every request +
    mod_usertrack Apache 1.2 and up +
    User tracking using Cookies (replacement for mod_cookies.c) +
    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_access.html b/APACHE_1_3b7/htdocs/manual/mod/mod_access.html new file mode 100644 index 0000000000..3e5675b3d6 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_access.html @@ -0,0 +1,310 @@ + + + +Apache module mod_access + + + + + + +

    Module mod_access

    +

    +This module is contained in the mod_access.c file, and +is compiled in by default. It provides access control based on client +hostname or IP address. +

    + + +
    + + +

    allow directive

    +

    + +Syntax: allow from host host ...
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access +

    +

    +The allow directive affects which hosts can access a given directory. +Host is one of the following: +

    +
    +
    all +
    All hosts are allowed access +
    A (partial) domain-name +
    Hosts whose names match, or end in, this string are allowed access. +
    A full IP address +
    An IP address of a host allowed access +
    A partial IP address +
    The first 1 to 3 bytes of an IP address, for subnet restriction. +
    A network/netmask pair (Apache 1.3 and later) +
    A network a.b.c.d, and a netmask w.x.y.z. For more fine-grained subnet + restriction. (i.e. 10.1.0.0/255.255.0.0) +
    A network/nnn CIDR specification (Apache 1.3 and later) +
    Similar to the previous case, except the netmask consists of nnn + high-order 1 bits. (i.e. 10.1.0.0/16 is the same as 10.1.0.0/255.255.0.0) +
    +

    +Example: +

    +
    allow from .ncsa.uiuc.edu
    +

    +All hosts in the specified domain are allowed access. +

    +

    +Note that this compares whole components; bar.edu +would not match foobar.edu. +

    +

    +See also deny, order, and +BrowserMatch. +

    + +

    +Syntax: allow from + env=variablename
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access
    +Compatibility: Apache 1.2 and above +

    +

    +The allow from env directive controls access to a directory by the +existence (or non-existence) of an environment variable. +

    +

    +Example: +

    +
    +BrowserMatch ^KnockKnock/2.0 let_me_in
    +<Directory /docroot>
    +    order deny,allow
    +    deny from all
    +    allow from env=let_me_in
    +</Directory>
    +
    +In this case browsers with the user-agent string KnockKnock/2.0 will +be allowed access, and all others will be denied. +

    +See also deny from env +and order. +

    +
    + +

    deny directive

    +

    + +Syntax: deny from host host ...
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access +

    +

    +The deny directive affects which hosts can access a given directory. +Host is one of the following: +

    +
    +
    all +
    all hosts are denied access +
    A (partial) domain-name +
    host whose name is, or ends in, this string are denied access. +
    A full IP address +
    An IP address of a host denied access +
    A partial IP address +
    The first 1 to 3 bytes of an IP address, for subnet restriction. +
    A network/netmask pair (Apache 1.3 and later) +
    A network a.b.c.d, and a netmask w.x.y.z. For more fine-grained subnet + restriction. (i.e. 10.1.0.0/255.255.0.0) +
    A network/nnn CIDR specification (Apache 1.3 and later) +
    Similar to the previous case, except the netmask consists of nnn + high-order 1 bits. (i.e. 10.1.0.0/16 is the same as 10.1.0.0/255.255.0.0) +
    +

    +Example: +

    +
    deny from 16
    +

    +All hosts in the specified network are denied access. +

    +

    +Note that this compares whole components; bar.edu +would not match foobar.edu. +

    +

    +See also allow and order. +

    + +

    +Syntax: deny from + env=variablename
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access
    +Compatibility: Apache 1.2 and above +

    +

    +The deny from env directive controls access to a directory by the +existence (or non-existence) of an environment variable. +

    +

    +Example: +

    +
    +BrowserMatch ^BadRobot/0.9 go_away
    +<Directory /docroot>
    +    order allow,deny
    +    allow from all
    +    deny from env=go_away
    +</Directory>
    +
    +In this case browsers with the user-agent string BadRobot/0.9 will +be denied access, and all others will be allowed. + +

    +See also allow from env +and order. +

    +
    + +

    order directive

    +

    + +Syntax: order ordering
    +Default: order deny,allow
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access +

    +

    +The order directive controls the order in which allow and +deny directives are evaluated. Ordering is one +of +

    +
    +
    deny,allow +
    the deny directives are evaluated before the allow directives. (The +initial state is OK.) +
    allow,deny +
    the allow directives are evaluated before the deny directives. (The +initial state is FORBIDDEN.) +
    mutual-failure +
    Only those hosts which appear on the allow list and do not appear +on the deny list are granted access. (The initial state is irrelevant.) +
    +

    +Note that in all cases every allow and deny +statement is evaluated, there is no "short-circuiting". +

    +

    +Example: +

    +
    + order deny,allow
    + deny from all
    + allow from .ncsa.uiuc.edu
    +
    +

    +Hosts in the ncsa.uiuc.edu domain are allowed access; all other hosts are +denied access. +

    + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_actions.html b/APACHE_1_3b7/htdocs/manual/mod/mod_actions.html new file mode 100644 index 0000000000..a9f449002c --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_actions.html @@ -0,0 +1,125 @@ + + + +Module mod_actions + + + + + +

    Module mod_actions

    +

    +This module is contained in the mod_actions.c file, and +is compiled in by default. It provides for +executing CGI scripts based on media type or request method. It is not +present in versions prior to Apache 1.1. +

    +

    Summary

    +

    +This module lets you run CGI scripts whenever a file of a certain type +is requested. This makes it much easier to execute scripts that +process files. +

    +

    Directives

    + + +
    + +

    Action directive

    +

    +Syntax: Action mime-type cgi-script
    +Context: server config, virtual host, directory, + .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_actions
    +Compatibility: Action is only available in Apache 1.1 +and later +

    +

    +This directive adds an action, which will activate cgi-script when +a file of content type mime-type is requested. It sends the +URL and file path of the requested document using the standard +CGI PATH_INFO and PATH_TRANSLATED environment variables. +

    +
    + +

    Script directive

    +

    +Syntax: Script method cgi-script
    +Context: server config, virtual host, directory
    +Status: Base
    +Module: mod_actions
    +Compatibility: Script is only available in Apache 1.1 +and later +

    + +

    +This directive adds an action, which will activate cgi-script when +a file is requested using the method of method, which can be +one of GET, POST, PUT or +DELETE. It sends the +URL and file path of the requested document using the standard +CGI PATH_INFO and PATH_TRANSLATED environment variables. +

    +

    +Note that the Script command defines default actions only. If a CGI +script is called, or some other resource that is capable of handling +the requested method internally, it will do so. Also note that Script +with a method of GET will only be called if there are +query arguments present (e.g. foo.html?hi). Otherwise, the request +will proceed normally. +

    +

    +Examples: +

    +
    +    Script GET /cgi-bin/search     #e.g. for <ISINDEX>-style searching
    +    Script PUT /~bob/put.cgi
    +
    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_alias.html b/APACHE_1_3b7/htdocs/manual/mod/mod_alias.html new file mode 100644 index 0000000000..6ec10f13e4 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_alias.html @@ -0,0 +1,387 @@ + + + +Apache module mod_alias + + + + + + +

    Module mod_alias

    +

    +This module is contained in the mod_alias.c file, and +is compiled in by default. It provides for mapping different parts of the +host filesystem in the the document tree, and for URL redirection. +

    + +

    Directives

    + +
    + + +

    Alias directive

    +

    + +Syntax: Alias url-path directory-filename
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_alias +

    +

    +The Alias directive allows documents to be stored in the local filesystem +other than under the DocumentRoot. +URLs with a (%-decoded) path beginning with url-path will be +mapped to local files beginning with directory-filename. +

    +Example: +

    +
    Alias /image /ftp/pub/image
    +

    +A request for http://myserver/image/foo.gif would cause the server to +return the file /ftp/pub/image/foo.gif. +

    +

    +Note that if you include a trailing / on the url-path then the +server will require a trailing / in order to expand the alias. That is, +if you use Alias /icons/ /usr/local/apache/icons/ then +the url /icons will not be aliased. +

    +

    +Note that you may need to specify additional +<Directory> sections +which cover the destination of aliases. Aliasing occurs +before <Directory> sections are checked, so only +the destination of aliases are affected. (Note however +<Location> +sections are run through once before aliases are performed, so they +will apply.) +

    +See also ScriptAlias. +

    +
    + +

    AliasMatch

    +

    +Syntax: AliasMatch regex directory-filename
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_alias
    +Compatibility: Available in Apache 1.3 and later +

    + +

    This directive is equivalent to Alias, but +makes use of standard regular expressions, instead of simple prefix +matching. The supplied regular expression is matched against the URL, +and if it matches, the server will substitute any parenthesized +matches into the given string and use it as a filename. For example, +to activate the /icons directory, one might use: +

    +    AliasMatch ^/icons(.*) /usr/local/apache/icons$1
    +
    +

    + +
    + +

    Redirect directive

    +

    + +Syntax: Redirect [ status ] + url-path url
    +Context: server config, virtual host, directory, + .htaccess
    +Status: Base
    +Module: mod_alias
    +Compatibility: The directory and .htaccess context's +are only available in versions 1.1 and later. The status +argument is only available in Apache 1.2 or later. +

    +

    +The Redirect directive maps an old URL into a new one. The new URL is returned +to the client which attempts to fetch it again with the new address. +Url-path a (%-decoded) path; any requests for documents beginning with +this path will be returned a redirect error to a new (%-encoded) url +beginning with url. +

    +

    +Example: +

    +
    Redirect /service +http://foo2.bar.com/service
    +

    +If the client requests http://myserver/service/foo.txt, it will be told to +access http://foo2.bar.com/service/foo.txt instead. +

    +

    +Note: Redirect directives take precedence over Alias +and ScriptAlias +directives, irrespective of their ordering in the configuration file. Also, +Url-path must be an absolute path, not a relative path, even +when used with .htaccess files or inside of <Directory> sections. +

    +

    +If no status argument is given, the redirect will be +"temporary" (HTTP status 302). This indicates to the client that the +resources is has moved temporarily. The status +argument can be used to return other HTTP status codes: +

    +

    +
    permanent +
    Returns a permanent redirect status (301) indicating that +the resource has moved permanently. +
    temp +
    Returns a temporary redirect status (302). This is the +default. +
    seeother +
    Returns a "See Other" status (303) indicating that +the resource has been replaced. +
    gone +
    Returns a "Gone" status (410) indicating that the resource +has been permanently removed. When this status is used the url +argument should be omitted. +
    +

    +Other status codes can be returned by giving the numeric status code +as the value of status. If the status is between 300 and 399, +the url argument must be present, otherwise it must be +omitted. Note that the status must be known to the Apache code (see +the function send_error_response in http_protocol.c). +

    +
    + +

    RedirectMatch

    +

    +Syntax: RedirectMatch [status regex url +
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_alias
    +Compatibility: Available in Apache 1.3 and later +

    + +

    This directive is equivalent to Redirect, but +makes use of standard regular expressions, instead of simple prefix +matching. The supplied regular expression is matched against the URL, +and if it matches, the server will substitute any parenthesized +matches into the given string and use it as a filename. For example, +to redirect all GIF files to like-named JPEG files on another server, +one might use: +

    +    RedirectMatch (.*)\.gif$ http://www.anotherserver.com$1.jpg
    +
    +

    + +
    + +

    RedirectTemp directive

    +

    + +Syntax: RedirectTemp url-path url
    +Context: server config, virtual host, directory, + .htaccess
    +Status: Base
    +Module: mod_alias
    +Compatibility: This directive is only available in 1.2 +

    +

    +This directive makes the client know that the Redirect is only +temporary (status 302). Exactly equivalent to Redirect +temporary. +

    +
    + +

    RedirectPermanent directive

    +

    + +Syntax: RedirectPermanent url-path url
    +Context: server config, virtual host, directory, + .htaccess
    +Status: Base
    +Module: mod_alias
    +Compatibility: This directive is only available in 1.2 +

    +

    +This directive makes the client know that the Redirect is permanent +(status 301). Exactly equivalent to Redirect permanent. +

    +
    + +

    ScriptAlias directive

    +

    + +Syntax: ScriptAlias url-path directory-filename +
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_alias +

    +

    +The ScriptAlias directive has the same behavior as the +Alias directive, except that in addition it +marks the target directory as containing CGI scripts. +URLs with a (%-decoded) path beginning with url-path will be +mapped to scripts beginning with directory-filename. +

    +Example: +

    +
    ScriptAlias /cgi-bin/ /web/cgi-bin/
    +

    +A request for http://myserver/cgi-bin/foo would cause the server to +run the script /web/cgi-bin/foo. +

    + +
    + +

    ScriptAliasMatch

    +

    +Syntax: ScriptAliasMatch + regex directory-filename
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_alias
    +Compatibility: Available in Apache 1.3 and later +

    + +

    This directive is equivalent to ScriptAlias, but +makes use of standard regular expressions, instead of simple prefix +matching. The supplied regular expression is matched against the URL, +and if it matches, the server will substitute any parenthesized +matches into the given string and use it as a filename. For example, +to activate the standard /cgi-bin, one might use: +

    +    ScriptAliasMatch ^/cgi-bin(.*) /usr/local/apache/cgi-bin$1
    +
    +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_asis.html b/APACHE_1_3b7/htdocs/manual/mod/mod_asis.html new file mode 100644 index 0000000000..aceb9f2ee7 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_asis.html @@ -0,0 +1,68 @@ + + + +Apache module mod_asis + + + + + + +

    Module mod_asis

    + +This module is contained in the mod_asis.c file, and +is compiled in by default. It provides for .asis files. Any +document with mime type httpd/send-as-is will be processed by +this module. + + +

    Purpose

    +To allow file types to be defined such that Apache sends them without +adding HTTP headers.

    + +This can be used to send any kind of data from the server, including redirects +and other special HTTP responses, without requiring a cgi-script or an nph +script. +

    Usage

    +In the server configuration file, define a new mime type called +httpd/send-as-is e.g. +
    AddType httpd/send-as-is asis
    +this defines the .asis file extension as being of the new +httpd/send-as-is mime type. The contents of any file with a +.asis extension will then be sent by Apache to the client with +almost no changes. Clients will need HTTP headers to be attached, so do not +forget them. A Status: header is also required; the data should be the +3-digit HTTP response code, followed by a textual message.

    + +Here's an example of a file whose contents are sent as is so as to +tell the client that a file has redirected. +

    +Status: 301 Now where did I leave that URL
    +Location: http://xyz.abc.com/foo/bar.html
    +Content-type: text/html
    +
    +<HTML>
    +<HEAD>
    +<TITLE>Lame excuses'R'us</TITLE>
    +</HEAD>
    +<BODY>
    +<H1>Fred's exceptionally wonderful page has moved to
    +<A HREF="http://xyz.abc.com/foo/bar.html">Joe's</A> site.
    +</H1>
    +</BODY>
    +</HTML> +
    +Notes: the server always adds a Date: and Server: header to the data returned +to the client, so these should not be included in the file. +The server does not add a Last-Modified header; it probably should. +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_auth.html b/APACHE_1_3b7/htdocs/manual/mod/mod_auth.html new file mode 100644 index 0000000000..0d1fb8184d --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_auth.html @@ -0,0 +1,201 @@ + + + +Apache module mod_auth + + + + + + +

    Module mod_auth

    + +This module is contained in the mod_auth.c file, and +is compiled in by default. It provides for user authentication using +textual files. + + + +
  • AuthGroupFile +
  • AuthUserFile +
  • AuthAuthoritative +
  • +
    + + +

    AuthGroupFile

    + +Syntax: AuthGroupFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +The AuthGroupFile directive sets the name of a textual file containing the list +of user groups for user authentication. Filename is the path +to the group file. If it is not absolute (i.e., if it +doesn't begin with a slash), it is treated as relative to the ServerRoot. +

    +Each line of the group file contains a groupname followed by a colon, followed +by the member usernames separated by spaces. Example: +

    mygroup: bob joe anne
    +Note that searching large text files is very inefficient; +AuthDBMGroupFile should +be used instead.

    + +Security: make sure that the AuthGroupFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the AuthGroupFile.

    + +See also AuthName, +AuthType and +AuthUserFile.


    + +

    AuthUserFile

    + +Syntax: AuthUserFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +The AuthUserFile directive sets the name of a textual file containing +the list of users and passwords for user +authentication. Filename is the path to the user +file. If it is not absolute (i.e., if it doesn't begin with a +slash), it is treated as relative to the ServerRoot. +

    Each line of the user file file contains a username followed +by a colon, followed by the crypt() encrypted password. The behavior +of multiple occurrences of the same user is undefined. +

    Note that +searching large text files is very inefficient; +AuthDBMUserFile should be +used instead. +

    + +Security: make sure that the AuthUserFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the AuthUserFile.

    + +See also AuthName, +AuthType and +AuthGroupFile.

    +


    +

    AuthAuthoritative

    + +Syntax: AuthAuthoritative < + on(default) | off >
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +Setting the AuthAuthoritative directive explicitly to 'off' +allows for both authentication and authorization to be passed on to +lower level modules (as defined in the Configuration and +modules.c files) if there is no userID or +rule matching the supplied userID. If there is a userID and/or +rule specified; the usual password and access checks will be applied +and a failure will give an Authorization Required reply. + +

    + +So if a userID appears in the database of more than one module; or if +a valid require directive applies to more than one module; then the +first module will verify the credentials; and no access is passed on; +regardless of the AuthAuthoritative setting. + +

    + +A common use for this is in conjunction with one of the database +modules; such as mod_auth_db.c, mod_auth_dbm.c, +mod_auth_msql.c, and mod_auth_anon.c. These modules +supply the bulk of the user credential checking; but a few +(administrator) related accesses fall through to a lower level with a +well protected AuthUserFile. + +

    + +Default: By default; control is not passed on; and an + unknown +userID or rule will result in an Authorization Required reply. Not +setting it thus keeps the system secure; and forces an NSCA compliant +behaviour. + +

    + +Security: Do consider the implications of allowing a user to allow +fall-through in his .htaccess file; and verify that this is really +what you want; Generally it is easier to just secure a single +.htpasswd file, than it is to secure a database such as mSQL. Make +sure that the AuthUserFile is stored outside the document tree of the +web-server; do not put it in the directory that it +protects. Otherwise, clients will be able to download the +AuthUserFile. + +

    +See also AuthName, +AuthType and +AuthGroupFile.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_auth_anon.html b/APACHE_1_3b7/htdocs/manual/mod/mod_auth_anon.html new file mode 100644 index 0000000000..3ab8b2cef2 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_auth_anon.html @@ -0,0 +1,363 @@ + + + +Apache module mod_auth_anon.c + + + + +

    Module mod_auth_anon

    + +This module is contained in the mod_auth_anon.c file and +is not compiled in by default. It is only available in Apache 1.1 and +later. It allows "anonymous" user access to authenticated areas. + +

    Summary

    + +It does access control in a manner similar to anonymous-ftp sites; i.e. +have a 'magic' user id 'anonymous' and the email address as a password. +These email addresses can be logged. +

    +Combined with other (database) access control methods, this allows for +effective user tracking and customization according to a user profile +while still keeping the site open for 'unregistered' users. One advantage +of using Auth-based user tracking is that, unlike magic-cookies and +funny URL pre/postfixes, it is completely browser independent and it +allows users to share URLs. +

    + +Directives / +Example / +Compile time options / +RevisionHistory / +Person to blame / +Sourcecode +

    + +

    Directives

    + + +
    + +

    Anonymous directive

    + +Syntax: Anonymous user user ...
    +Default: none
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + A list of one or more 'magic' userIDs which are allowed access + without password verification. The userIDs are space separated. + It is possible to use the ' and " quotes to allow a space in + a userID as well as the \ escape character. +

    + Please note that the comparison is case-IN-sensitive. +
    + I strongly suggest that the magic username 'anonymous' + is always one of the allowed userIDs. +

    + Example:
    + + Anonymous anonymous "Not Registered" 'I don\'t know' +

    + This would allow the user to enter without password verification + by using the userId's 'anonymous', 'AnonyMous','Not Registered' and + 'I Don't Know'. +


    + +

    Anonymous_Authoritative directive

    +Syntax: Anonymous_Authoritative on | off
    +Default: Anonymous_Authoritative off
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + When set 'on', there is no + fall-through to other authorization methods. So if a + userID does not match the values specified in the + Anonymous directive, access is denied. +

    + Be sure you know what you are doing when you decide to switch + it on. And remember that it is the linking order of the modules + (in the Configuration / Make file) which details the order + in which the Authorization modules are queried. +


    + +

    Anonymous_LogEmail directive

    +Syntax: Anonymous_LogEmail on | off
    +Default: Anonymous_LogEmail on
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + When set 'on', the default, the 'password' entered (which hopefully + contains a sensible email address) is logged in the httpd-log file. +


    + +

    Anonymous_MustGiveEmail directive

    + +Syntax: Anonymous_MustGiveEmail on + | off
    +Default: Anonymous_MustGiveEmail on
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + Specifies whether the user must specify an email + address as the password. This prohibits blank passwords. +


    + +

    Anonymous_NoUserID directive

    +Syntax: Anonymous_NoUserID on | off
    +Default: Anonymous_NoUserID off
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + When set 'on', users can leave + the userID (and perhaps the password field) empty. This + can be very convenient for MS-Explorer users who can + just hit return or click directly on the OK button; which + seems a natural reaction. + +


    + +

    Anonymous_VerifyEmail directive

    +Syntax: Anonymous_VerifyEmail on | off
    +Default: Anonymous_VerifyEmail off
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + When set 'on' the 'password' entered is + checked for at least one '@' and a '.' to encourage users to enter + valid email addresses (see the above Auth_LogEmail). + +


    +

    Example

    + +The example below (when combined with the Auth directives +of a htpasswd-file based (or GDM, mSQL etc.) base access +control system allows users in as 'guests' with the +following properties: +
      +
    • +It insists that the user enters a userId. (Anonymous_NoUserId) +
    • +It insists that the user enters a password. +(Anonymous_MustGiveEmail) +
    • +The password entered must be a valid email address, ie. contain at least one +'@' and a '.'. (Anonymous_VerifyEmail) +
    • +The userID must be one of anonymous guest www test welcome +and comparison is not case sensitive. +
    • +And the Email addresses entered in the passwd field are logged to +the httpd-log file +(Anonymous_LogEmail) +
    +

    +Excerpt of access.conf: +

    +Anonymous_NoUserId off
    +Anonymous_MustGiveEmail on
    +Anonymous_VerifyEmail on
    +Anonymous_LogEmail on
    +Anonymous anonymous guest www test welcome

    +

    +AuthName Use 'anonymous' & Email address for guest entry
    +AuthType basic +

    +# An AuthUserFile/AuthDBUserFile/AuthDBMUserFile
    +# directive must be specified, or use
    +# Anonymous_Authoritative for public access.
    +# In the .htaccess for the public directory, add:
    +<Files *>
    +order deny,allow
    +allow from all
    +

    +require valid-user
    +</Files>
    +

    + + +
    +

    Compile Time Options

    + +Currently there are no Compile options. + +
    +

    Revision History

    + +This version: 23 Nov 1995, 24 Feb 1996, 16 May 1996. + +
    + +
    Version 0.4
    +
    First release +
    +
    Version 0.5
    +
    Added 'VerifyEmail' and 'LogEmail' options. Multiple + 'anonymous' tokens allowed. more docs. Added Authoritative + functionality. +
    +
    + + +
    +

    Contact/person to blame

    + +This module was written for the +European Wide Service Exchange by +<Dirk.vanGulik@jrc.it>. +Feel free to contact me if you have any problems, ice-creams or bugs. This +documentation, courtesy of Nick Himba, +<himba@cs.utwente.nl>. +

    + + +


    +

    Sourcecode

    + +The source code can be found at +http://www.apache.org. A snapshot of a development version +usually resides at +http://me-www.jrc.it/~dirkx/mod_auth_anon.c. Please make sure +that you always quote the version you use when filing a bug report. +

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_auth_db.html b/APACHE_1_3b7/htdocs/manual/mod/mod_auth_db.html new file mode 100644 index 0000000000..707e4586b9 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_auth_db.html @@ -0,0 +1,220 @@ + + + +Apache module mod_auth_db + + + + + +

    Module mod_auth_db

    + +This module is contained in the mod_auth_db.c file, and +is not compiled in by default. It provides for user authentication using +Berkeley DB files. It is an alternative to DBM +files for those systems which support DB and not DBM. It is only +available in Apache 1.1 and later. + +

    +On some BSD systems (e.g. FreeBSD and NetBSD) dbm is automatically mapped to +Berkeley DB. You can use either mod_auth_dbm +or mod_auth_db. The latter makes it more obvious that it's Berkeley DB. On +other platforms where you want to use the DB library you usually have to +install it first. See +http://www.sleepycat.com/ for the +distribution. The interface this module uses is the one from DB version 1.85 +and 1.86, but DB version 2.x can also be used when compatibility mode is +enabled. + +

    +
  • AuthDBGroupFile +
  • AuthDBUserFile +
  • AuthDBAuthoritative +
  • +
    + + +

    AuthDBGroupFile

    + +Syntax: AuthDBGroupFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_db

    + +The AuthDBGroupFile directive sets the name of a DB file containing the list +of user groups for user authentication. Filename is the absolute path +to the group file.

    + +The group file is keyed on the username. The value for a user is a +comma-separated list of the groups to which the users belongs. There must +be no whitespace within the value, and it must never contain any colons.

    + +Security: make sure that the AuthDBGroupFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the +AuthDBGroupFile unless otherwise protected.

    + +Combining Group and Password DB files: In some cases it is easier to +manage a single database which contains both the password and group +details for each user. This simplifies any support programs that need +to be written: they now only have to deal with writing to and locking +a single DBM file. This can be accomplished by first setting the group +and password files to point to the same DB file:

    + +

    +AuthDBGroupFile /www/userbase
    +AuthDBUserFile /www/userbase +
    + +The key for the single DB record is the username. The value consists of

    + +

    +Unix Crypt-ed Password : List of Groups [ : (ignored) ] +
    + +The password section contains the Unix crypt() password as before. This is +followed by a colon and the comma separated list of groups. Other data may +optionally be left in the DB file after another colon; it is ignored by the +authentication module.

    + +See also AuthName, +AuthType and +AuthDBUserFile.


    + +

    AuthDBUserFile

    + +Syntax: AuthDBUserFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_db

    + +The AuthDBUserFile directive sets the name of a DB file containing the list +of users and passwords for user authentication. Filename is the +absolute path to the user file.

    + +The user file is keyed on the username. The value for a user is the +crypt() encrypted password, optionally followed by a colon and +arbitrary data. The colon and the data following it will be ignored +by the server.

    + +Security: make sure that the AuthDBUserFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the +AuthDBUserFile.

    + +Important compatibility note: The implementation of "dbmopen" in the +apache modules reads the string length of the hashed values from the +DB data structures, rather than relying upon the string being +NULL-appended. Some applications, such as the Netscape web server, +rely upon the string being NULL-appended, so if you are having trouble +using DB files interchangeably between applications this may be a +part of the problem.

    + +See also AuthName, +AuthType and +AuthDBGroupFile.

    +


    +

    AuthDBAuthoritative

    + +Syntax: AuthDBAuthoritative < + on(default) | off >
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +Setting the AuthDBAuthoritative directive explicitly to 'off' +allows for both authentication and authorization to be passed on +to lower level modules (as defined in the Configuration +and modules.c file if there is no userID or +rule matching the supplied userID. If there is a userID +and/or rule specified; the usual password and access checks will +be applied and a failure will give an Authorization Required reply. +

    +So if a userID appears in the database of more than one module; or +if a valid require directive applies to more than one module; then +the first module will verify the credentials; and no access is +passed on; regardless of the AuthAuthoritative setting.

    + +A common use for this is in conjunction with one of the basic auth +modules; such as mod_auth.c. +Whereas this DB module supplies the bulk of the user credential +checking; a few (administrator) related accesses fall through to +a lower level with a well protected .htpasswd file.

    + +Default: By default; control is not passed on; and an +unknown +userID or rule will result in an Authorization Required reply. Not +setting it thus keeps the system secure; and forces an NSCA compliant +behaviour.

    +Security: Do consider the implications of allowing a user to allow +fall-through in his .htaccess file; and verify that this is really +what you want; Generally it is easier to just secure a single +.htpasswd file, than it is to secure a database which might have +more access interfaces. + +

    +See also AuthName, +AuthType and +AuthDBGroupFile.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_auth_dbm.html b/APACHE_1_3b7/htdocs/manual/mod/mod_auth_dbm.html new file mode 100644 index 0000000000..cf194ce149 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_auth_dbm.html @@ -0,0 +1,210 @@ + + + +Apache module mod_auth_dbm + + + + + + +

    Module mod_auth_dbm

    + +This module is contained in the mod_auth_dbm.c file, and +is not compiled in by default. It provides for user authentication using +DBM files. + + + +
  • AuthDBMGroupFile +
  • AuthDBMUserFile +
  • AuthDBMAuthoritative +
  • +
    + + +

    AuthDbmGroupFile

    + +Syntax: AuthDBMGroupFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_dbm

    + +The AuthDBMGroupFile directive sets the name of a DBM file containing the list +of user groups for user authentication. Filename is the absolute path +to the group file.

    + +The group file is keyed on the username. The value for a user is a +comma-separated list of the groups to which the users belongs. There must +be no whitespace within the value, and it must never contain any colons.

    + +Security: make sure that the AuthDBMGroupFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the +AuthDBMGroupFile unless otherwise protected.

    + +Combining Group and Password DBM files: In some cases it is easier to +manage a single database which contains both the password and group +details for each user. This simplifies any support programs that need +to be written: they now only have to deal with writing to and locking +a single DBM file. This can be accomplished by first setting the group +and password files to point to the same DBM:

    + +

    +AuthDBMGroupFile /www/userbase
    +AuthDBMUserFile /www/userbase +
    + +The key for the single DBM is the username. The value consists of

    + +

    +Unix Crypt-ed Password : List of Groups [ : (ignored) ] +
    + +The password section contains the Unix crypt() password as before. This is +followed by a colon and the comma separated list of groups. Other data may +optionally be left in the DBM file after another colon; it is ignored by the +authentication module. This is what www.telescope.org uses for its combined +password and group database.

    + +See also AuthName, +AuthType and +AuthDBMUserFile.


    + +

    AuthDBMUserFile

    + +Syntax: AuthDBMUserFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_dbm

    + +The AuthDBMUserFile directive sets the name of a DBM file containing the list +of users and passwords for user authentication. Filename is the +absolute path to the user file.

    + +The user file is keyed on the username. The value for a user is the +crypt() encrypted password, optionally followed by a colon and +arbitrary data. The colon and the data following it will be ignored +by the server.

    + +Security: make sure that the AuthDBMUserFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the +AuthDBMUserFile.

    + +Important compatibility note: The implementation of "dbmopen" in the +apache modules reads the string length of the hashed values from the +DBM data structures, rather than relying upon the string being +NULL-appended. Some applications, such as the Netscape web server, +rely upon the string being NULL-appended, so if you are having trouble +using DBM files interchangeably between applications this may be a +part of the problem.

    + +See also AuthName, +AuthType and +AuthDBMGroupFile.

    + +


    +

    AuthDBMAuthoritative

    + +Syntax: AuthDBMAuthoritative < on(default) | off >
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +Setting the AuthDBMAuthoritative directive explicitly to 'off' +allows for both authentication and authorization to be passed on +to lower level modules (as defined in the Configuration +and modules.c file if there is no userID or +rule matching the supplied userID. If there is a userID +and/or rule specified; the usual password and access checks will +be applied and a failure will give an Authorization Required reply. +

    +So if a userID appears in the database of more than one module; or +if a valid require directive applies to more than one module; then +the first module will verify the credentials; and no access is +passed on; regardless of the AuthAuthoritative setting.

    + +A common use for this is in conjunction with one of the basic auth +modules; such as mod_auth.c. +Whereas this DBM module supplies the bulk of the user credential +checking; a few (administrator) related accesses fall through to +a lower level with a well protected .htpasswd file.

    + +Default: By default; control is not passed on; and an unknown +userID or rule will result in an Authorization Required reply. Not +setting it thus keeps the system secure; and forces an NSCA compliant +behaviour.

    + +Security: Do consider the implications of allowing a user to allow +fall-through in his .htaccess file; and verify that this is really +what you want; Generally it is easier to just secure a single +.htpasswd file, than it is to secure a database which might have +more access interfaces. + +

    +See also AuthName, +AuthType and +AuthDBMGroupFile.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_autoindex.html b/APACHE_1_3b7/htdocs/manual/mod/mod_autoindex.html new file mode 100644 index 0000000000..2dc71e5411 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_autoindex.html @@ -0,0 +1,606 @@ + + + +Apache module mod_autoindex + + + + + +

    Module mod_autoindex

    + +This module is contained in the mod_autoindex.c file, and +is compiled in by default. It provides for automatic directory indexing. + +

    Summary

    +The index of a directory can come from one of two sources: +
      +
    • A file written by the user, typically called index.html. +The DirectoryIndex directive sets +the name of this file. +This is controlled by mod_dir. +
    • Otherwise, a listing generated by the server. The other directives +control the format of this listing. The AddIcon, +AddIconByEncoding and +AddIconByType are used to set a list of +icons to display for various file types; for each file listed, the +first icon listed that matches the file is displayed. These +are controlled by mod_autoindex. +
    +The two functions are separated so that you can completely remove +(or replace) automatic index generation should you want to. +

    +If +FancyIndexing +is enabled, or the FancyIndexing keyword is present on the +IndexOptions +directive, the column headers are links that control the +order of the display. If you select a header link, the +listing will be regenerated, sorted by the values in that +column. Selecting the same header repeatedly toggles +between ascending and descending order. +

    +

    +Note that when the display is sorted by "Size", +it's the actual size of the files that's used, +not the displayed value - so a 1010-byte file will +always be displayed before a 1011-byte file (if in ascending +order) even though they both are shown as "1K". +

    + + +

    Directives

    + + +
  • AddAlt +
  • AddAltByEncoding +
  • AddAltByType +
  • AddDescription +
  • AddIcon +
  • AddIconByEncoding +
  • AddIconByType +
  • DefaultIcon +
  • FancyIndexing +
  • HeaderName +
  • IndexIgnore +
  • IndexOptions +
  • ReadmeName +
  • +
    + +

    AddAlt

    + +Syntax: AddAlt string file file...
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the alternate text to display for a file, instead of an icon, for +FancyIndexing. File is a file +extension, partial filename, wild-card expression or full filename for files +to describe. String is enclosed in double quotes +("). This alternate text is displayed if the client is +image-incapable or has image loading disabled. + +


    +

    AddAltByEncoding

    + +Syntax: AddAltByEncoding string MIME-encoding + MIME-encoding...
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the alternate text to display for a file, instead of an icon, for +FancyIndexing. MIME-encoding is a +valid content-encoding, such as x-compress. +String is enclosed in double quotes +("). This alternate text is displayed if the client is +image-incapable or has image loading disabled. + +


    +

    AddAltByType

    + +Syntax: AddAltByType string MIME-type MIME-type...
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the alternate text to display for a file, instead of an icon, for +FancyIndexing. MIME-type is a +valid content-type, such as text/html. +String is enclosed in double quotes +("). This alternate text is displayed if the client is +image-incapable or has image loading disabled. + +


    + +

    AddDescription

    + +Syntax: AddDescription string file file...
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the description to display for a file, for +FancyIndexing. File is a file +extension, partial filename, wild-card expression or full filename for files +to describe. String is enclosed in double quotes +("). Example: +

    AddDescription "The planet Mars" /web/pics/mars.gif +


    + +

    AddIcon

    + +Syntax: AddIcon icon name name ...
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the icon to display next to a file ending in name for +FancyIndexing. Icon is either a +(%-escaped) relative URL to the icon, or of the format +(alttext,url) where alttext is the text tag given +for an icon for non-graphical browsers.

    + +Name is either ^^DIRECTORY^^ for directories, ^^BLANKICON^^ for +blank lines (to format the list correctly), a file extension, a wildcard +expression, a partial filename or a complete filename. Examples: +

    +AddIcon (IMG,/icons/image.xbm) .gif .jpg .xbm
    +AddIcon /icons/dir.xbm ^^DIRECTORY^^
    +AddIcon /icons/backup.xbm *~ +
    +AddIconByType should be used in preference to +AddIcon, when possible.


    + +

    AddIconByEncoding

    + +Syntax: AddIconByEncoding icon mime-encoding mime-encoding +...
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the icon to display next to files with +mime-encoding for FancyIndexing. +Icon is either a (%-escaped) relative URL to the icon, or of the +format (alttext,url) where alttext is the text tag +given for an icon for non-graphical browsers.

    + +Mime-encoding is a wildcard expression matching required the +content-encoding. Examples: +

    +AddIconByEncoding /icons/compress.xbm x-compress +


    + +

    AddIconByType

    + +Syntax: AddIconByType icon mime-type mime-type ...
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the icon to display next to files of type mime-type for +FancyIndexing. Icon is either a +(%-escaped) relative URL to the icon, or of the format +(alttext,url) where alttext is the text tag given +for an icon for non-graphical browsers.

    +Mime-type is a wildcard expression matching required the mime types. +Examples: +

    +AddIconByType (IMG,/icons/image.xbm) image/* +


    + +

    DefaultIcon

    + +Syntax: DefaultIcon url
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +The DefaultIcon directive sets the icon to display for files when no +specific icon is known, for FancyIndexing. +Url is a (%-escaped) relative URL to the icon. Examples: +

    +DefaultIcon /icon/unknown.xbm +


    + +

    FancyIndexing

    + +Syntax: FancyIndexing boolean
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex +

    +The FancyIndexing directive sets the FancyIndexing option for a directory. +Boolean can be on or off. The +IndexOptions directive should be used in +preference. +

    +
    + Note that the FancyIndexing and + IndexOptions directives will override each other. You + should use IndexOptions FancyIndexing in preference + to the standalone FancyIndexing directive. +
    +
    + +

    HeaderName

    + +Syntax: HeaderName filename
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +The HeaderName directive sets the name of the file that will be inserted +at the top of the index listing. Filename is the name of the file +to include, and is taken to be relative to the directory being indexed. +The server first attempts to include filename.html +as an HTML document, otherwise it will include filename as plain +text. Example: +

    HeaderName HEADER
    +when indexing the directory /web, the server will first look for +the HTML file /web/HEADER.html and include it if found, otherwise +it will include the plain text file /web/HEADER, if it exists. + +

    See also ReadmeName.


    + +

    IndexIgnore

    + +Syntax: IndexIgnore file file ...
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +The IndexIgnore directive adds to the list of files to hide when listing +a directory. File is a file extension, partial filename, +wildcard expression or full filename for files to ignore. Multiple +IndexIgnore directives add to the list, rather than the replacing the list +of ignored files. By default, the list contains `.'. Example: +

    +IndexIgnore README .htaccess *~ +


    + +

    IndexOptions

    + +Syntax: IndexOptions option option ...
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +The IndexOptions directive specifies the behavior of the directory indexing. +Option can be one of +

    +
    FancyIndexing +
    +This turns on fancy indexing of directories. +
    + Note that the FancyIndexing and + IndexOptions directives will override each other. You + should use IndexOptions FancyIndexing in preference + to the standalone FancyIndexing directive. +
    +
    IconHeight[=pixels] (Apache 1.3 and later) +
    + +Presence of this option, when used with IconWidth, will cause the server +to include HEIGHT and WIDTH attributes in the +IMG tag for the file icon. This allows browser to +precalculate the page layout without having to wait until all the +images have been loaded. If no value is given for the option, it +defaults to the standard height of the icons supplied with the Apache +software. +
    IconsAreLinks +
    + +This makes the icons part of the anchor for the filename, for +fancy indexing. +
    IconWidth[=pixels] (Apache 1.3 and later) +
    + +Presence of this option, when used with IconHeight, will cause the server +to include HEIGHT and WIDTH attributes in the +IMG tag for the file icon. This allows browser to +precalculate the page layout without having to wait until all the +images have been loaded. If no value is given for the option, it +defaults to the standard width of the icons supplied with the Apache +software. +
    ScanHTMLTitles +
    +This enables the extraction of the title from HTML documents for fancy +indexing. If the file does not have a description given by +AddDescription then httpd will read the +document for the value of the TITLE tag. This is CPU and disk intensive. +
    SuppressColumnSorting +
    + +If specified, Apache will not make the column headings in a FancyIndexed +directory listing into links for sorting. The default behaviour is +for them to be links; selecting the column heading will sort the directory +listing by the values in that column. +Only available in Apache 1.3 and later. +
    SuppressDescription +
    + +This will suppress the file description in fancy indexing listings. +
    SuppressHTMLPreamble +
    + +If the directory actually contains a file specified by the +HeaderName +directive, the module usually includes the contents of the file +after a standard HTML preamble (<HTML>, <HEAD>, et +cetera). The SuppressHTMLPreamble option disables this behaviour, +causing the module to start the display with the header file contents. +The header file must contain appropriate HTML instructions in this case. +If there is no header file, the preamble is generated as usual. +
    SuppressLastModified +
    + +This will suppress the display of the last modification date, in fancy +indexing listings. +
    SuppressSize +
    + +This will suppress the file size in fancy indexing listings. +
    +This default is that no options are enabled. If multiple IndexOptions +could apply to a directory, then the most specific one is taken complete; +the options are not merged. For example: +
    +<Directory /web/docs>
    +IndexOptions FancyIndexing
    +</Directory>
    +<Directory /web/docs/spec>
    +IndexOptions ScanHTMLTitles
    +</Directory> +
    +then only ScanHTMLTitles will be set for the /web/docs/spec +directory.


    + +

    ReadmeName

    + +Syntax: ReadmeName filename
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +The ReadmeName directive sets the name of the file that will be appended +to the end of the index listing. Filename is the name of the file +to include, and is taken to be relative to the directory being indexed. +The server first attempts to include filename.html +as an HTML document, otherwise it will include filename as plain +text. Example: +

    ReadmeName README
    +when indexing the directory /web, the server will first look for +the HTML file /web/README.html and include it if found, otherwise +it will include the plain text file /web/README, if it exists. + +

    See also HeaderName.

    + + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_browser.html b/APACHE_1_3b7/htdocs/manual/mod/mod_browser.html new file mode 100644 index 0000000000..866f15a074 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_browser.html @@ -0,0 +1,120 @@ + + + +Apache module mod_browser + + + + + +

    Module mod_browser

    + +This module is contained in the mod_browser.c file, and +is compiled in by default. It provides for setting environment +variables based on the browser. This module is part of Apache 1.2.* +only. From Apache 1.3 onwards mod_setenvif provides the functionality +of this module. + +

    Summary

    + +

    This module allows you to set environment variables based on the name of +the browser accessing your document, based on the User-Agent +header field. This is especially useful when combined with a conditional +HTML language such as XSSI or PHP, and +can provide for simple browser-based negotiation of HTML features.

    + +

    Directives

    + + +
    + +

    BrowserMatch

    +Syntax: BrowserMatch regex attr1 attr2...
    +Context: server config
    +Status: base
    +Module: mod_browser
    +Compatibility: Apache 1.2 and above

    + +The BrowserMatch directive defines environment variables based on the +User-Agent +header. The first argument should be a POSIX.2 extended regular +expression (similar to an egrep-style regex). The rest of the arguments +give names of variables to set. These take the form of either +"varname", "!varname" or +"varname=value". In the first form, the value will be set +to "1". The second will remove the given variable if already defined, +and the third will set the variable to the value given by value. If a User-Agent +string matches more than one entry, they will +be merged. Entries are processed in the order they appear, and later +entries can override earlier ones. + +

    For example:

    +
    +    BrowserMatch ^Mozilla forms jpeg=yes browser=netscape
    +    BrowserMatch "^Mozilla/[2-3]" tables agif frames javascript
    +    BrowserMatch MSIE !javascript
    +
    + +

    BrowserMatchNoCase

    +Syntax: BrowserMatchNoCase regex attr1 attr2...
    +Context: server config
    +Status: base
    +Module: mod_browser
    +Compatibility: Apache 1.2 and above + +

    The BrowserMatchNoCase directive is semantically identical to + the BrowserMatch + directive. However, it provides for case-insensitive matching. For + example:

    +
    +    BrowserMatchNoCase mac platform=macintosh
    +    BrowserMatchNoCase win platform=windows
    +
    + + +

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_cern_meta.html b/APACHE_1_3b7/htdocs/manual/mod/mod_cern_meta.html new file mode 100644 index 0000000000..0a212830b2 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_cern_meta.html @@ -0,0 +1,143 @@ + + + +Module mod_cern_meta + + + + + +

    Apache module mod_cern_meta

    + +This module is contained in the mod_cern_meta.c file, and +is not compiled in by default. It provides for CERN httpd metafile +semantics. It is only available in Apache 1.1 and later. + +

    Summary

    + +Emulate the CERN HTTPD Meta file semantics. Meta files are HTTP +headers that can be output in addition to the normal range of headers +for each file accessed. They appear rather like the Apache +.asis files, and are able to provide a crude way of influencing +the Expires: header, as well as providing other curiosities. +There are many ways to manage meta information, this one was +chosen because there is already a large number of CERN users +who can exploit this module. + +

    More information on the +CERN metafile semantics is available. + +

    Directives

    + + +
    + +

    MetaFiles

    +Syntax: MetaFiles on/off
    +Default: MetaFiles off
    +Context: per-directory config
    +Status: Base
    +Module: mod_cern_meta
    +Compatibility: MetaFiles is only available in Apache 1.3 +and later.

    + +Turns on/off Meta file processing on a per-directory basis. This option was introduced in Apache 1.3. + +

    MetaDir

    +Syntax: MetaDir directory name
    +Default: MetaDir .web
    +Context: (Apache prior to 1.3) server config
    +Context: (Apache 1.3) per-directory config
    +Status: Base
    +Module: mod_cern_meta
    +Compatibility: MetaDir is only available in Apache 1.1 +and later.

    + +Specifies the name of the directory in which Apache can find +meta information files. The directory is usually a 'hidden' +subdirectory of the directory that contains the file being +accessed. Set to "." to look in the same directory as the +file. + +

    MetaSuffix

    +Syntax: MetaSuffix suffix
    +Default: MetaSuffix .meta
    +Context: (Apache prior to 1.3) server config
    +Context: (Apache 1.3) per-directory config
    +Status: Base
    +Module: mod_cern_meta
    +Compatibility: MetaSuffix is only available in Apache 1.1 +and later.

    + +Specifies the file name suffix for the file containing the +meta information. For example, the default values for the two +directives will cause a request to +DOCUMENT_ROOT/somedir/index.html to look in +DOCUMENT_ROOT/somedir/.web/index.html.meta and will use +its contents to generate additional MIME header information. + +

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_cgi.html b/APACHE_1_3b7/htdocs/manual/mod/mod_cgi.html new file mode 100644 index 0000000000..94201f0fb5 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_cgi.html @@ -0,0 +1,211 @@ + + + +Apache module mod_cgi + + + + + + +

    Module mod_cgi

    + +This module is contained in the mod_cgi.c file, and +is compiled in by default. It provides for execution of CGI scripts. +Any file with mime type application/x-httpd-cgi will be +processed by this module. + + + +

    Summary

    +Any file that has the mime type application/x-httpd-cgi +or handler cgi-script (Apache 1.1 or later) +will be treated as a CGI script, and run by the server, with its output +being returned to the client. Files acquire this type either by +having a name ending in an extension defined by the +AddType directive, or by being in +a ScriptAlias directory.

    + +When the server invokes a CGI script, it will add a variable called +DOCUMENT_ROOT to the environment. This variable will contain the +value of the DocumentRoot +configuration variable. + +

    CGI Environment variables

    +The server will set the CGI environment variables as described in the +CGI specification, with the +following provisions: +
    +
    REMOTE_HOST +
    This will only be set if the server has not been compiled with +MINIMAL_DNS. +
    REMOTE_IDENT +
    This will only be set if +IdentityCheck is set to on. +
    REMOTE_USER +
    This will only be set if the CGI script is subject to authentication. +
    +

    + +


    + +

    CGI Debugging

    + +Debugging CGI scripts has traditionally been difficult, mainly because +it has +not +been possible to study the output (standard output and error) for +scripts +which are failing to run properly. These directives, included in +Apache 1.2 and later, provide +more detailed logging of errors when they occur. + +
    + +

    CGI Logfile Format

    + +When configured, the CGI error log logs any CGI which does not execute +properly. Each CGI script which fails to operate causes several lines +of information to be logged. The first two lines are always of the +format: + +
    +  %% [time] request-line
    +  %% HTTP-status CGI-script-filename
    +
    + +If the error is that CGI script cannot be run, the log file will +contain +an extra two lines: + +
    +  %%error
    +  error-message
    +
    + +Alternatively, if the error is the result of the script returning +incorrect header information (often due to a bug in the script), the +following information is logged: + +
    +  %request
    +  All HTTP request headers received
    +  POST or PUT entity (if any)
    +  %response
    +  All headers output by the CGI script
    +  %stdout
    +  CGI standard output
    +  %stderr
    +  CGI standard error
    +
    + +(The %stdout and %stderr parts may be missing if the script did not +output +anything on standard output or standard error). + +
    + +

    Directives

    + +

    ScriptLog

    + +Syntax: ScriptLog filename
    +Default: none
    +Context: resource config
    +Status: mod_cgi +

    + +The ScriptLog directive sets the CGI script error logfile. +If no ScriptLog is given, no error log is created. If given, any +CGI errors are logged into the filename given as argument. If this +is a relative file or path it is taken relative to the server root. + +

    This log will be opened as the user the child processes run as, +ie. the user specified in the main User +directive. This means that either the directory the script log is +in needs to be writable by that user or the file needs to be manually +created and set to be writable by that user. If you place the +script log in your main logs directory, do NOT +change the directory permissions to make it writable by the user +the child processes run as.

    + +

    Note that script logging is meant to be a debugging feature when +writing CGI scripts, and is not meant to be activated continuously on +running servers. It is not optimized for speed or efficiency, and may +have security problems if used in a manner other than that for which +it was designed.

    + +

    ScriptLogLength

    + +Syntax: ScriptLogLength size
    +Default: 10385760
    +Context: resource config
    +Status: mod_cgi +

    + +ScriptLogLength can be used to limit the size of the CGI +script logfile. Since the logfile logs a lot of information per CGI +error (all request headers, all script output) it can grow to be a big +file. To prevent problems due to unbounded growth, this directive can +be used to set an maximum file-size for the CGI logfile. If the file +exceeds this size, no more information will be written to it. + +

    ScriptLogBuffer

    + +Syntax: ScriptLogBuffer size
    +Default: 1024
    +Context: resource config
    +Status: mod_cgi +

    + +The size of any PUT or POST entity body that is logged to the file is +limited, to prevent the log file growing too big too quickly if large +bodies are being received. By default, up to 1024 bytes are logged, +but this can be changed with this directive. + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_cookies.html b/APACHE_1_3b7/htdocs/manual/mod/mod_cookies.html new file mode 100644 index 0000000000..6eb44aa04d --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_cookies.html @@ -0,0 +1,59 @@ + + + +Apache module mod_cookies + + + + + +

    Module mod_cookies

    + +This module is obsolete. As of version +1.2 of Apache, it has been replaced with +mod_usertrack. + +

    This module is contained in the mod_cookies.c file, and +is not compiled in by default. It provides for Netscape(TM) cookies. +There is no documentation available for this module. + + +

    +
  • CookieLog +
  • +
    + + +

    CookieLog

    + +Syntax: CookieLog filename
    +Context: server config, virtual host
    +Status: Experimental
    +Module: mod_cookies

    + +The CookieLog directive sets the filename for logging of cookies. +The filename is relative to the ServerRoot. +

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_digest.html b/APACHE_1_3b7/htdocs/manual/mod/mod_digest.html new file mode 100644 index 0000000000..f5803cca51 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_digest.html @@ -0,0 +1,80 @@ + + + +Apache module mod_digest + + + + + +

    Module mod_digest

    + +This module is contained in the mod_digest.c file, and is +not compiled in by default. It is only available in Apache 1.1 and +later. It provides for user authentication using MD5 Digest +Authentication. + + + +
  • AuthDigestFile +
  • +
    + + +

    AuthDigestFile

    +Syntax: AuthDigestFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_digest

    + +

    The AuthDigestFile directive sets the name of a textual file containing +the list +of users and encoded passwords for digest authentication. +Filename +is the absolute path to the user file.

    +

    The digest file uses a special format. Files in this format can be +created using the "htdigest" utility found in the support/ subdirectory of +the Apache distribution.

    + +
    + +

    Using Digest Authentication

    + +

    Using MD5 Digest authentication is very simple. Simply set up +authentication normally. However, use "AuthType Digest" and +"AuthDigestFile" instead of the normal "AuthType Basic" and +"AuthUserFile". Everything else should remain the same.

    + +

    MD5 authentication provides a more secure password system, but only +works with supporting browsers. As of this writing (July 1996), the +majority of browsers do not support digest authentication. Therefore, we +do not recommend using this feature on a large Internet site. However, for +personal and intra-net use, where browser users can be controlled, it is +ideal.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_dir.html b/APACHE_1_3b7/htdocs/manual/mod/mod_dir.html new file mode 100644 index 0000000000..f150aa2e11 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_dir.html @@ -0,0 +1,103 @@ + + + +Apache module mod_dir + + + + + +

    Module mod_dir

    + +This module is contained in the mod_dir.c file, and +is compiled in by default. It provides for "trailing slash" redirects and +serving directory index files. + +

    Summary

    +The index of a directory can come from one of two sources: +
      +
    • A file written by the user, typically called index.html. +The DirectoryIndex directive sets +the name of this file. +This is controlled by mod_dir. +
    • Otherwise, a listing generated by the server. This is provided by +mod_autoindex. +
    +The two functions are separated so that you can completely remove +(or replace) automatic index generation should you want to. +

    A "trailing slash" redirect is issued when the server receives a +request for a URL http://servername/foo/dirname where +dirname is a directory. Directories require a trailing +slash, so mod_dir issues a redirect to +http://servername/foo/dirname/. + +

    Directives

    + + +
  • DirectoryIndex +
  • +
    + +

    DirectoryIndex

    + +Syntax: DirectoryIndex local-url local-url ...
    +Default: DirectoryIndex index.html
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_dir

    + +The DirectoryIndex directive sets the list of resources to look for, +when the client requests an index of the directory by specifying a / +at the end of the a directory name. Local-url is the +(%-encoded) URL of a document on the server relative to the requested +directory; it is usually the name of a file in the directory. Several +URLs may be given, in which case the server will return the first one +that it finds. If none of the resources exist and the +Indexes option is set, the server will generate its own +listing of the directory. +

    + +Example: +

    +DirectoryIndex index.html +
    +then a request for http://myserver/docs/ would return +http://myserver/docs/index.html if it exists, or would list +the directory if it did not.

    + +Note that the documents do not need to be relative to the directory; +

    +DirectoryIndex index.html index.txt /cgi-bin/index.pl
    +would cause the CGI script /cgi-bin/index.pl to be executed +if neither index.html or index.txt existed in +a directory.


    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_dld.html b/APACHE_1_3b7/htdocs/manual/mod/mod_dld.html new file mode 100644 index 0000000000..1d0e7919a2 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_dld.html @@ -0,0 +1,108 @@ + + + +Apache module mod_dld + + + + + +

    Module mod_dld

    + +This module is obsolete. As of version +1.3 of Apache, it has been replaced with +mod_so. + +This module is contained in the mod_dld.c file, and is not +compiled in by default. It provides for loading of executable code +and modules into the server at start-up time, using the GNU dld library. + +

    Summary

    + +The optional dld module is a proof-of-concept piece of code which +loads other modules into the server as it is configuring itself (the +first time only; for now, rereading the config files cannot affect the +state of loaded modules), using the GNU dynamic linking library, DLD. +It isn't compiled into the server by default, since not everyone has +DLD, but it works when I try it. (Famous last words.)

    + +Note that for some reason, LoadFile /lib/libc.a seems to be +required for just about everything.

    + +Note: that DLD needs to read the symbol table out of the server binary +when starting up; these commands will fail if the server can't find +its own binary when it starts up, or if that binary is stripped.

    + + +

    Directives

    + +
    + + +

    LoadFile

    + +Syntax: LoadFile filename filename ...
    +Context: server config
    +Status: Experimental
    +Module: mod_dld

    + +The LoadFile directive links in the named object files or libraries when +the server is started; this is used to load additional code which +may be required for some module to work. Filename is relative +to ServerRoot.


    + +

    LoadModule

    + +Syntax: LoadModule module filename
    +Context: server config
    +Status: Experimental
    +Module: mod_dld

    + +The LoadModule directive links in the object file or library filename +and adds the module structure named module to the list of active +modules. Module is the name of the external variable of type +module in the file. Example: +

    +LoadModule ai_backcompat_module modules/mod_ai_backcompat.o
    +LoadFile /lib/libc.a +
    +loads the module in the modules subdirectory of the ServerRoot.

    + + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_dll.html b/APACHE_1_3b7/htdocs/manual/mod/mod_dll.html new file mode 100644 index 0000000000..882ef32e28 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_dll.html @@ -0,0 +1,151 @@ + + + +Apache module mod_dll + + + + + +

    Module mod_dll

    + +This module is obsolete. As of version +1.3b6 of Apache, it has been replaced with +mod_so. + +

    +This module is contained in the mod_dll.c file, and is +compiled in by default for Windows. It provides for loading of executable code +and modules into the server at start-up time, when they are contained in +Win32 DLLs.

    + +

    Summary

    + +

    The DLL module +loads other modules into the server as it is configuring itself (the +first time only, rereading the config files cannot affect the +state of loaded modules), when these modules are compiled into DLL files.

    + +

    This module is included with Apache 1.3 and later, and is available + only when using Microsoft Windows.

    + +

    Creating DLL Modules

    + +

    The Apache module API is unchanged between the Unix and Windows + versions. Many modules will run on Windows with no or little change + from Unix, although others rely on aspects of the Unix architecture + which are not present in Windows, and will not work.

    + +

    When a module does work, it can be added to the server in one of two + ways. As with Unix, it can be compiled into the server. Because Apache + for Windows does not have the Configure program of Apache + for Unix, the module's source file must be added to the ApacheCore + project file, and its symbols must be added to the + nt\modules.c file.

    + +

    The second way is to compile the module as a DLL, a shared library + that can be loaded into the server at runtime, using the + LoadModule + directive. These module DLLs can be distributed and run on any Apache + for Windows installation, without recompilation of the server.

    + +

    To create a module DLL, a small change is necessary to the module's + source file: The module record must be exported from the DLL (which + will be created later; see below). To do this, add the + MODULE_VAR_EXPORT (defined in the Apache header files) to + your module's module record definition. For example, if your module + has:

    +
    +    module foo_module;
    +
    +

    Replace the above with:

    +
    +    module MODULE_VAR_EXPORT foo_module;
    +
    +

    Note that this will only be activated on Windows, so the module can + continue to be used, unchanged, with Unix if needed. Also, if you are + familiar with .DEF files, you can export the module + record with that method instead.

    + +

    Now, create a DLL containing your module. You will need to link this + against the ApacheCore.lib export library that is created when the + ApacheCore.dll shared library is compiled. You may also have to change + the compiler settings to ensure that the Apache header files are + correctly located.

    + +

    This should create a DLL version of your module. Now simply place it + in the server root, and use the LoadModule directive to + load it.

    + +

    Directives

    + +
    + + +

    LoadFile

    +Syntax: LoadFile filename filename ...
    +Context: server config
    +Status: Core (Windows)
    +Module: mod_dll

    + +The LoadFile directive links in the named object files or libraries when +the server is started; this is used to load additional code which +may be required for some module to work. Filename is relative +to ServerRoot.


    + +

    LoadModule

    +Syntax: LoadModule module filename
    +Context: server config
    +Status: Core (Windows)
    +Module: mod_dll

    + +The LoadModule directive links in the object file or library filename +and adds the module structure named module to the list of active +modules. Module is the name of the external variable of type +module in the file. Example: + +

    +LoadModule status_module modules/ApacheModuleStatus.dll
    +
    +loads the ApacheModuleStatus.dll module in the modules subdirectory of the +ServerRoot.

    + + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_env.html b/APACHE_1_3b7/htdocs/manual/mod/mod_env.html new file mode 100644 index 0000000000..0908220153 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_env.html @@ -0,0 +1,137 @@ + + + +Apache module mod_env + + + + + +

    Apache module mod_env

    + +This module is contained in the mod_env.c file, and +is not compiled in by default. It provides for +passing environment variables to CGI/SSI scripts. Is is only available +in Apache 1.1 and later. + +

    Summary

    + +This module allows Apache's CGI and SSI environment to inherit +environment variables from the shell which invoked the httpd process. +CERN web-servers are able to do this, so this module is especially +useful to web-admins who wish to migrate from CERN to Apache without +rewriting all their scripts + +

    Directives

    + + +
    + +

    PassEnv

    +Syntax: PassEnv variable variable ...
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_env
    +Compatibility: PassEnv is only available in +Apache 1.1 and later.

    + +Specifies one or more environment variables to pass to CGI scripts +from the server's own environment. Example: +

    +    PassEnv LD_LIBRARY_PATH
    +
    + +
    + +

    SetEnv

    +Syntax: SetEnv variable value
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_env
    +Compatibility: SetEnv is only available in +Apache 1.1 and later.

    + +Sets an environment variable, which is then passed on to CGI +scripts. Example: +

    +    SetEnv SPECIAL_PATH /foo/bin
    +
    + +
    + +

    UnsetEnv

    +Syntax: UnsetEnv variable variable ...
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_env
    +Compatibility: UnsetEnv is only available in +Apache 1.1 and later.

    + +Removes one or more environment variables from those passed on to +CGI scripts. Example: +

    +    UnsetEnv LD_LIBRARY_PATH
    +
    + + + +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_example.html b/APACHE_1_3b7/htdocs/manual/mod/mod_example.html new file mode 100644 index 0000000000..f582dd45d2 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_example.html @@ -0,0 +1,167 @@ + + + + Apache module mod_example + + + + +

    Module mod_example

    +

    + This module is contained in the modules/mod_example.c file, and + is not compiled in by default. It illustrates many of + the aspects of the + Apache 1.2 API + and, when used, demonstrates the manner in which module callbacks are + triggered by the server. +

    +

    Summary

    +

    + The files in the src/modules/example directory under the + Apache distribution directory tree are provided as an example to those + that wish to write modules that use the Apache API. +

    +

    + The main file is mod_example.c, which illustrates all + the different callback mechanisms and call syntaxes. By no means does + an add-on module need to include routines for all of the callbacks - + quite the contrary! +

    +

    + The example module is an actual working module. If you link it into + your server, enable the "example-handler" handler for a location, and + then browse to that location, you will see a display of + some of the tracing the example module did as the various callbacks + were made. +

    +

    + To include the example module in your server, follow the steps below: +

    +
      +
    1. Uncomment the "AddModule modules/example/mod_example" line near + the bottom of + the src/Configuration file. If there isn't one, add + it; it should look like this: +
      +     AddModule modules/example/mod_example.o
      +    
      +
    2. +
    3. Run the src/Configure script + ("cd src; ./Configure"). This will + build the Makefile for the server itself, and update the + src/modules/Makefile for any additional modules you + have requested from beneath that subdirectory. +
    4. +
    5. Make the server (run "make" in the src + directory). +
    6. +
    +

    + To add another module of your own: +

    +
      +
    1. mkdir src/modules/mymodule +
    2. +
    3. cp src/modules/example/* src/modules/mymodule +
    4. +
    5. Modify the files in the new directory. +
    6. +
    7. Follow steps [1] through [3] above, with appropriate changes. +
    8. +
    +

    + Using the mod_example Module +

    +

    + To activate the example module, include a block similar to the + following in your srm.conf file: +

    +
    +   <Location /example-info>
    +       SetHandler example-handler
    +   </Location>
    +  
    +

    + As an alternative, you can put the following into a + .htaccess + file and then request the file "test.example" from that + location: +

    +
    +   AddHandler example-handler .example
    +  
    +

    + After reloading/restarting your server, you should be able to browse + to this location and see the brief display mentioned earlier. +

    +

    Directives

    +

    +

    +

    +
    +

    + Example +

    +

    + Syntax: Example +
    + Default: None +
    + Context: server config, virtual host, directory, + .htaccess +
    + Override: Options +
    + Status: Extension +
    + Module: mod_example +
    + Compatibility: Example is only + available in Apache 1.2 and later. +

    +

    + The Example directive activates the example module's + content handler + for a particular location or file type. It takes no arguments. If + you browse to an URL to which the example content-handler applies, you + will get a display of the routines within the module and how and in + what order they were called to service the document request. +

    + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_expires.html b/APACHE_1_3b7/htdocs/manual/mod/mod_expires.html new file mode 100644 index 0000000000..870501e659 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_expires.html @@ -0,0 +1,322 @@ + + + + Apache module mod_expires + + + + +

    Module mod_expires

    +

    + This module is contained in the mod_expires.c file, and + is not compiled in by default. It provides for the + generation of Expires headers according to user-specified + criteria. +

    +

    Summary

    +

    + This module controls the setting of the Expires HTTP + header in server responses. The expiration date can set to be + relative to either the time the source file was last modified, or to + the time of the client access. +

    +

    + The Expires HTTP header is an instruction to the client + about the document's validity and persistence. If cached, the document + may be fetched from the cache rather than from the source until this + time has passed. After that, the cache copy is considered + "expired" and invalid, and a new copy must be obtained from + the source. +

    +

    Directives

    +

    +

    +
  • ExpiresActive +
  • +
  • ExpiresByType +
  • +
  • ExpiresDefault +
  • +
    +
    +

    + ExpiresActive directive +

    + +

    + Syntax: ExpiresActive boolean +
    + Context: server config, virtual host, directory, + .htaccess +
    + Override: Indexes +
    + Status: Extension +
    + Module: mod_expires +

    +

    + This directive enables or disables the generation of the + Expires header for the document realm in question. (That + is, if found in an .htaccess file, for instance, it + applies only to documents generated from that directory.) If set to + Off, no Expires header will be + generated for any document in the realm (unless overridden at a lower + level, such as an .htaccess file overriding a server + config file). If set to On, the header will be + added to served documents according to the criteria defined by the + ExpiresByType + and + ExpiresDefault + directives (q.v.). +

    +

    + Note that this directive does not guarantee that an + Expires header will be generated. If the criteria aren't + met, no header will be sent, and the effect will be as though this + directive wasn't even specified. +

    +
    +

    + ExpiresByType directive +

    + +

    + Syntax: ExpiresByType mime-type + <code>seconds +
    + Context: server config, virtual host, directory, + .htaccess +
    + Override: Indexes +
    + Status: Extension +
    + Module: mod_expires +

    +

    + This directive defines the value of the Expires header + generated for documents of the specified type (e.g., + text/html). The second argument sets the number of + seconds that will be added to a base time to construct the expiration + date. +

    +

    + The base time is either the last modification time of the file, or the + time of the client's access to the document. Which should be used is + specified by the <code> field; + M means that the file's last modification time should + be used as the base time, and A means the client's + access time should be used. +

    +

    + The difference in effect is subtle. If M is used, all current + copies of the document in all caches will expire at the same time, + which can be good for something like a weekly notice that's always + found at the same URL. If A is used, the date of expiration + is different for each client; this can be good for image files that + don't change very often, particularly for a set of related documents + that all refer to the same images (i.e., the images will be + accessed repeatedly within a relatively short timespan). +

    +

    + Example: +

    +

    +

    +   ExpiresActive On                  # enable expirations
    +   ExpiresByType image/gif A2592000  # expire GIF images after a month
    +                                     #  in the client's cache
    +   ExpiresByType text/html M604800   # HTML documents are good for a
    +                                     #  week from the time they were
    +                                     #  changed, period
    +  
    +

    +

    + Note that this directive only has effect if ExpiresActive + On has been specified. It overrides, for the specified MIME + type only, any expiration date set by the + ExpiresDefault + directive. +

    +

    + You can also specify the expiration time calculation using an + alternate syntax, + described later in this document. +

    +
    +

    + ExpiresDefault directive +

    + +

    + Syntax: ExpiresDefault <code>seconds +
    + Context: server config, virtual host, directory, + .htaccess +
    + Override: Indexes +
    + Status: Extension +
    + Module: mod_expires +

    +

    + This directive sets the default algorithm for calculating the + expiration time for all documents in the affected realm. It can be + overridden on a type-by-type basis by the + ExpiresByType + directive. See the description of that directive for details about + the syntax of the argument, and the + alternate syntax + description as well. +

    +
    +

    + Alternate Interval Syntax +

    +

    + The + ExpiresDefault + and + ExpiresByType + directives can also be defined in a more readable syntax of the form: +

    +
    +
    ExpiresDefault "<base> [plus] {<num> <type>}*" +
    + ExpiresByType type/encoding "<base> [plus] + {<num> <type>}*"
    +
    +
    +

    + where <base> is one of: +

    + +
  • access +
  • +
  • now (equivalent to 'access') +
  • +
  • modification +
  • +
    +

    + The 'plus' keyword is optional. <num> should be an + integer value [acceptable to atoi()], and <type> + is one of: +

    + +
  • years +
  • +
  • months +
  • +
  • weeks +
  • +
  • days +
  • +
  • hours +
  • +
  • minutes +
  • +
  • seconds +
  • +
    +

    + For example, any of the following directives can be used to make + documents expire 1 month after being accessed, by default: +

    +
    +
    ExpiresDefault "access plus 1 month" +
    + ExpiresDefault "access plus 4 weeks" +
    + ExpiresDefault "access plus 30 days"
    +
    +
    +

    + The expiry time can be fine-tuned by adding several '<num> + <type>' clauses: +

    +
    +
    ExpiresByType text/html "access plus 1 month 15 days 2 hours" +
    + ExpiresByType image/gif "modification plus 5 hours 3 minutes"
    +
    +
    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_headers.html b/APACHE_1_3b7/htdocs/manual/mod/mod_headers.html new file mode 100644 index 0000000000..7d62d5d1fd --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_headers.html @@ -0,0 +1,121 @@ + + + +Apache module mod_headers + + + + + +

    Module mod_headers

    + +The optional headers module allows for the customization of HTTP +response headers. Headers can be merged, replaced or removed. The +directives described in this document are only available if Apache is +compiled with mod_headers.c. + +
    + +

    Directive

    + + +
    + +

    Header

    +Syntax: Header [ set | append | add ] + header value
    +Syntax: Header unset header
    +Context: server config, virtual host, access.conf, + .htaccess
    +Status: optional
    +Module: mod_header

    + +This directive can replace, merge or remove HTTP response headers. The +action it performs is determined by the first argument. This can be one +of the following values: + +

      +
    • set
      + The response header is set, replacing any previous header with this name + +
    • append
      + The response header is appended to any existing header of the same + name. When a new value is merged onto an existing header it is + separated from the existing header with a comma. This is the HTTP standard + way of giving a header multiple values. + +
    • add
      + The response header is added to the existing set of headers, even if + this header already exists. This can result in two (or more) headers + having the same name. This can lead to unforeseen consequences, and in + general "append" should be used instead. + +
    • unset
      + The response header of this name is removed, if it exists. If there are + multiple headers of the same name, only the first one set will be removed. +
    + +This argument is followed by a header name, which can include the +final colon, but it is not required. Case is ignored. For +add, append and set a value is given as the third argument. If this +value contains spaces, it should be surrounded by double quotes. +For unset, no value should be given. + +

    Order of Processing

    + +The Header directive can occur almost anywhere within the server +configuration. It is valid in the main server config and virtual host +sections, inside <Directory>, <Location> and <Files> +sections, and within .htaccess files. +

    +The Header directives are processed in the following order: +

      +
    1. main server +
    2. virtual host +
    3. <Directory> sections and .htaccess +
    4. <Location> +
    5. <Files> +
    + +Order is important. These two headers have a different effect if reversed: +
    +Header append Author "John P. Doe"
    +Header unset Author
    +
    + +This way round, the Author header is not set. If reversed, the Author +header is set to "John P. Doe". +

    + +The Header directives are processed just before the response is sent +by its handler. These means that some headers that are added just +before the response is sent cannot be unset or overridden. This +includes headers such as "Date" and "Server". +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_imap.html b/APACHE_1_3b7/htdocs/manual/mod/mod_imap.html new file mode 100644 index 0000000000..69517721ab --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_imap.html @@ -0,0 +1,329 @@ + + + +Apache module mod_imap + + + + + +

    Module mod_imap

    + +This module is contained in the mod_imap.c file, and is +compiled in by default. It provides for .map files, +replacing the functionality of the imagemap CGI +program. Any directory or document type configured to use the handler +imap-file (using either AddHandler or SetHandler) will be +processed by this module. + +

    Summary

    + +This module is in the default Apache distribution. The following directive will +activate files ending with .map as imagemap files: + +
    AddHandler imap-file map
    + +Note that the following is still supported: + +
    AddType application/x-httpd-imap map
    + +However, we are trying to phase out "magic MIME types" so we are deprecating +this method. + +

    New Features

    +The imagemap module adds some new features that were not +possible with previously distributed imagemap programs.

    + +

      +
    • URL references relative to the Referer: information. +
    • Default <BASE> assignment through a new map directive +base. +
    • No need for imagemap.conf file. +
    • Point references. +
    • Configurable generation of imagemap menus. +
    +

    + +

    Configuration Directives

    + + + +

    + +

    ImapMenu

    +Syntax: ImapMenu {none, formatted, semi-formatted, + unformatted}
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Module: mod_imap.c
    +Compatibility: ImapMenu is only available in Apache +1.1 and later.

    + +The ImapMenu directive determines the action taken if an imagemap file +is called without valid coordinates. +

    +
    none +
    If ImapMenu is + none, no menu is generated, and the default + action is performed. +
    formatted +
    A formatted menu is the simplest menu. Comments + in the imagemap file are ignored. A level one header is + printed, then an hrule, then the links each on a separate line. + The menu has a consistent, plain look close to that of + a directory listing. +
    semiformatted +
    In the semiformatted menu, comments are printed + where they occur in the imagemap file. Blank lines are turned + into HTML breaks. No header or hrule is printed, but otherwise + the menu is the same as a formatted menu. +
    unformatted +
    Comments are printed, blank lines are ignored. Nothing is + printed that does not appear in the imagemap file. All breaks + and headers must be included as comments in the imagemap file. + This gives you the most flexibility over the appearance of your + menus, but requires you to treat your map files as HTML instead + of plaintext. +
    + +

    + +

    ImapDefault

    +Syntax: ImapDefault {error, nocontent, + map, referer, URL}
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Module: mod_imap.c
    +Compatibility: ImapDefault is only available in Apache +1.1 and later.

    + + +The ImapDefault directive sets the default default used in +the imagemap files. It's value is overridden by a default +directive within the imagemap file. If not present, the +default action is nocontent, which means +that a 204 No Content is sent to the client. In this +case, the client should continue to display the original page. + +

    + +

    ImapBase

    +Syntax: ImapBase {map, referer, URL}
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Module: mod_imap.c
    +Compatibility: ImapBase is only available in Apache +1.1 and later.

    + +The ImapBase directive sets the default base used in +the imagemap files. It's value is overridden by a base +directive within the imagemap file. If not present, the +base defaults to http://servername/. + +


    +

    + +

    Imagemap File

    +The lines in the imagemap files can have one of several formats: +
    +directive value [x,y ...]
    +directive value "Menu text" [x,y ...]
    +directive value x,y ... "Menu text"
    +
    +The directive is one of base, default, +poly, circle, rect, or +point. The value is an absolute or relative URL, or one +of the special values listed below. The coordinates are +x,y pairs separated by whitespace. The quoted text is +used as the text of the link if a imagemap menu is generated. Lines +beginning with '#' are comments. + +

    Imagemap File Directives

    +There are six directives allowed in the imagemap file. The directives +can come in any order, but are processed in the order they are found +in the imagemap file. +
    +
    base Directive +
    Has the effect of <BASE HREF="value">. The + non-absolute URLs of the map-file are taken relative to this value. + The base directive overrides ImapBase as set in a + .htaccess file or in the server configuration files. In the absence + of an ImapBase configuration directive, base defaults to + http://server_name/.
    + base_uri is synonymous with base. Note that + a trailing slash on the URL is significant. +

    +

    default Directive +
    The action taken if the coordinates given do not fit any of the + poly, circle or rect + directives, and there are no point directives. Defaults + to nocontent in the absence of an ImapDefault + configuration setting, causing a status code of 204 No + Content to be returned. The client should keep the same + page displayed. +

    +

    poly Directive +
    Takes three to one-hundred points, and is obeyed if the user selected + coordinates fall within the polygon defined by these points. +

    +

    circle +
    Takes the center coordinates of a circle and a point on the circle. Is + obeyed if the user selected point is with the circle. +

    +

    rect Directive +
    Takes the coordinates of two opposing corners of a rectangle. Obeyed + if the point selected is within this rectangle. +

    +

    point Directive +
    Takes a single point. The point directive closest to the user + selected point is obeyed if no other directives are satisfied. + Note that default will not be followed if a + point directive is present and valid coordinates are + given. +
    + + + +

    Values

    +The values for each of the directives can any of the following: +
    +
    a URL +
    The URL can be relative or absolute URL. Relative URLs can + contain '..' syntax and will be resolved relative to the + base value.
    + base itself will not resolved according to the current + value. A statement base mailto: will work properly, though. +

    +

    map +
    Equivalent to the URL of the imagemap file itself. No + coordinates are sent with this, so a menu will be generated + unless ImapMenu is set to 'none'. +

    +

    menu +
    Synonymous with map. +

    +

    referer +
    Equivalent to the URL of the referring document. + Defaults to http://servername/ if no Referer: + header was present. +

    +

    nocontent +
    Sends a status code of 204 No Content, + telling the client to keep the same page displayed. Valid for + all but base. +

    +

    error +
    Fails with a 500 Server Error. Valid for all but + base, but sort of silly for anything but + default. +
    + +

    Coordinates

    +
    +
    0,0 200,200 +
    A coordinate consists of an x and a y value + separated by a comma. The coordinates are separated from each other + by whitespace. To accommodate the way Lynx handles imagemaps, should a + user select the coordinate 0,0, it is as if + no coordinate had been selected. +
    + +

    Quoted Text

    +
    +
    "Menu Text" +
    After the value or after the coordinates, the line optionally may + contain text within double quotes. This string is used as the + text for the link if a menu is generated:
    + <a HREF="http://foo.com/">Menu text</a>
    + If no quoted text is present, the name of the link will be used + as the text:
    + <a HREF="http://foo.com/">http://foo.com</a>
    + It is impossible to escape double quotes within this text. +
    + +
    + +

    Example Mapfile

    +
    +#Comments are printed in a 'formatted' or 'semiformatted' menu.
    +#And can contain html tags. <hr>
    +base referer
    +poly map "Could I have a menu, please?" 0,0 0,10 10,10 10,0
    +rect .. 0,0 77,27 "the directory of the referer"
    +circle http://www.inetnebr.com/lincoln/feedback/ 195,0 305,27
    +rect another_file "in same directory as referer" 306,0 419,27
    +point http://www.zyzzyva.com/ 100,100
    +point http://www.tripod.com/ 200,200
    +rect mailto:nate@tripod.com 100,150 200,0 "Bugs?"
    +
    +

    + +

    Referencing your mapfile

    +
    +<A HREF="/maps/imagemap1.map">
    +<IMG ISMAP SRC="/images/imagemap1.gif">
    +</A> +

    + + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_include.html b/APACHE_1_3b7/htdocs/manual/mod/mod_include.html new file mode 100644 index 0000000000..fe355d28b1 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_include.html @@ -0,0 +1,420 @@ + + + +Apache module mod_include + + + + + +

    Module mod_include

    + +This module is contained in the mod_include.c file, and +is compiled in by default. It provides for server-parsed html +documents. Several directives beyond the original NCSA definition have been +included in Apache 1.2 - these are flagged below with the phrase +"Apache 1.2 and above". Of particular significance are the new flow +control directives documented at the bottom. + +

    Enabling Server-Side Includes

    + +Any document with handler of "server-parsed" will be parsed by this +module, if the Includes option is set. If documents +containing server-side include directives are given the extension +.shtml, the following directives will make Apache parse them and +assign the resulting document the mime type of text/html: + +
    +AddType text/html .shtml
    +AddHandler server-parsed .shtml
    +
    + +The following directive must be given for the directories containing +the shtml files (typically in a <Directory> section, +but this directive is also valid .htaccess files if AllowOverride +Options is set): + +
    +Options +Includes
    +
    + +Alternatively the XBitHack +directive can be used to parse normal (text/html) files, +based on file permissions.

    + +For backwards compatibility, documents with mime type +text/x-server-parsed-html or +text/x-server-parsed-html3 will also be parsed +(and the resulting output given the mime type text/html). + +

    Basic Elements

    + +The document is parsed as an HTML document, with special commands embedded +as SGML comments. A command has the syntax: + +
    +<!--#element attribute=value attribute=value ... + --> +
    + +The value will often be enclosed in double quotes; many commands only allow +a single attribute-value pair. Note that the comment terminator +(-->) should be preceded by whitespace to ensure that it +isn't considered part of an SSI token. +

    +The allowed elements are:

    + +

    + +
    config +
    +This command controls various aspects of the parsing. The valid attributes +are: +
    +
    errmsg +
    The value is a message that is sent back to the client if an error occurs +whilst parsing the document. +
    sizefmt +
    The value sets the format to be used which displaying the size of a file. +Valid values are bytes for a count in bytes, or +abbrev for a count in Kb or Mb as appropriate. +
    timefmt +
    The value is a string to be used by the strftime(3) library +routine when printing dates. +
    + +
    echo +
    +This command prints one of the include variables, defined below. +If the variable is unset, it is printed as (none). +Any dates printed are subject to the currently configured timefmt. +Attributes: +
    +
    var +
    The value is the name of the variable to print. +
    + +
    exec +
    +The exec command executes a given shell command or CGI script. +The IncludesNOEXEC Option disables this command +completely. The valid attributes are: +
    +
    cgi +
    +The value specifies a (%-encoded) URL relative path to the CGI script. +If the path does not begin with a (/), then it is taken to be relative to +the current document. The document referenced by this path is invoked +as a CGI script, even if the server would not normally recognize it as +such. However, the directory containing the script must be enabled for +CGI scripts (with ScriptAlias +or the ExecCGI Option).

    +The CGI script is given the PATH_INFO and query string (QUERY_STRING) of the +original request from the client; these cannot be specified in the URL path. +The include variables will be available to the script in addition to the +standard CGI environment.

    +If the script returns a Location: header instead of output, then this +will be translated into an HTML anchor.

    +The include virtual element should be used in preference to +exec cgi. +

    cmd +
    The server will execute the given string using /bin/sh. +The include variables are available to the command. +
    + +
    fsize +
    +This command prints the size of the specified file, subject to the +sizefmt format specification. Attributes: +
    +
    file +
    The value is a path relative to the directory containing the current +document being parsed. +
    virtual +
    The value is a (%-encoded) URL-path relative to the current document being +parsed. If it does not begin with a slash (/) then it is taken to be relative +to the current document. +
    + +
    flastmod +
    +This command prints the last modification date of the specified file, +subject to the timefmt format specification. The attributes are +the same as for the fsize command. + +
    include +
    +This command inserts the text of another document or file into the parsed +file. Any included file is subject to the usual access control. If the +directory containing the parsed file has the +Option +IncludesNOEXEC set, and the including the document would cause a program +to be executed, then it will not be included; this prevents the execution of +CGI scripts. Otherwise CGI scripts are invoked as normal using the complete +URL given in the command, including any query string. + +

    + +An attribute defines the location of the document; the inclusion is done for +each attribute given to the include command. The valid attributes are: +

    +
    file +
    The value is a path relative to the directory containing the current +document being parsed. It cannot contain ../, nor can it be an +absolute path. The virtual attribute should always be used +in preference to this one. +
    virtual +
    The value is a (%-encoded) URL relative to the current document being +parsed. The URL cannot contain a scheme or hostname, only a path and +an optional query string. If it does not begin with a slash (/) then it +is taken to be relative to the current document. +
    +A URL is constructed from the attribute, and the output the server +would return if the URL were accessed by the client is included in the parsed +output. Thus included files can be nested. + +
    printenv +
    This prints out a listing of all existing variables and their values. + No attributes. +
    For example: <!--#printenv --> +
    Apache 1.2 and above. + +
    set +
    This sets the value of a variable. Attributes: +
    +
    var +
    The name of the variable to set. +
    value +
    The value to give a variable. +
    +For example: + <!--#set var="category" value="help" --> +
    Apache 1.2 and above. + +
    + +

    Include Variables

    + +In addition to the variables in the standard CGI environment, these are +available for the echo command, for if and +elif, and to any program invoked by the document. + +
    +
    DATE_GMT +
    The current date in Greenwich Mean Time. +
    DATE_LOCAL +
    The current date in the local time zone. +
    DOCUMENT_NAME +
    The filename (excluding directories) of the document requested by the +user. +
    DOCUMENT_URI +
    The (%-decoded) URL path of the document requested by the user. Note that +in the case of nested include files, this is not then URL for the +current document. +
    LAST_MODIFIED +
    The last modification date of the document requested by the user. +
    +

    + +

    Variable Substitution

    +

    Variable substitution is done within quoted strings in most cases + where they may reasonably occur as an argument to an SSI directive. + This includes the + config, + exec, + flastmod, + fsize, + include, and + set + directives, as well as the arguments to conditional operators. + You can insert a literal dollar sign into the string using backslash + quoting: + +

    +    <!--#if expr="$a = \$test" -->
    +
    + +

    If a variable reference needs to be substituted in the middle of a + character sequence that might otherwise be considered a valid + identifier in its own right, it can be disambiguated by enclosing + the reference in braces, à la shell substitution: + +

    +    <!--#set var="Zed" value="${REMOTE_HOST}_${REQUEST_METHOD}" -->
    +
    + +

    This will result in the Zed variable being set to + "X_Y" if REMOTE_HOST is + "X" and REQUEST_METHOD is + "Y". + +

    EXAMPLE: the below example will print "in foo" if the DOCUMENT_URI is +/foo/file.html, "in bar" if it is /bar/file.html and "in neither" +otherwise: +

    +    <!--#if expr="\"$DOCUMENT_URI\" = \"/foo/file.html\"" -->
    +    in foo
    +    <!--#elif expr="\"$DOCUMENT_URI\" = \"/bar/file.html\"" -->
    +    in bar
    +    <!--#else -->
    +    in neither
    +    <!--#endif -->
    +
    + +

    Flow Control Elements

    + +These are available in Apache 1.2 and above. The basic flow control +elements are: + +
    +    <!--#if expr="test_condition" -->
    +    <!--#elif expr="test_condition" -->
    +    <!--#else -->
    +    <!--#endif -->
    +
    + +

    The if element works like an + if statement in a programming language. The test condition + is evaluated and if the result is true, then the text until + the next elif, else. + or endif element is included in the + output stream. + +

    The elif or else + statements are be used the put text into the output stream + if the original test_condition was false. These elements + are optional. + +

    The endif element ends the + if element and is required. + +

    test_condition is one of the following: + +

    + +
    string
    true if string is not empty + +
    string1 = string2 +
    + string1 != string2 +
    + string1 < string2 +
    + string1 <= string2 +
    + string1 > string2 +
    + string1 >= string2 + +
    Compare string1 with string 2. If string2 has the form /string/ + then it is compared as a regular expression. + Regular expressions have the same syntax as those found in the + Unix egrep command. + +
    ( test_condition ) +
    true if test_condition is true +
    ! test_condition +
    true if test_condition is false +
    test_condition1 && test_condition2 +
    true if both test_condition1 and + test_condition2 are true +
    test_condition1 || test_condition2 +
    true if either test_condition1 or + test_condition2 is true +
    + +

    "=" and "!=" bind more tightly than "&&" and + "||". + "!" binds most tightly. Thus, the following are equivalent: + +

    +    <!--#if expr="$a = test1 && $b = test2" -->
    +    <!--#if expr="($a = test1) && ($b = test2)" -->
    +
    + +

    Anything that's not recognized as a variable or an operator is + treated as a string. Strings can also be quoted: 'string'. + Unquoted strings can't contain whitespace (blanks and tabs) + because it is used to separate tokens such as variables. If + multiple strings are found in a row, they are concatenated using + blanks. So, + +

    +     string1    string2  results in string1 string2
    +    'string1    string2' results in string1    string2
    +
    + +
    +

    Directives

    + +
    + + +

    XBitHack

    + +Syntax: XBitHack status
    +Default: XBitHack off
    +Context: server config, virtual host, directory, .htaccess
    +Override: Options
    +Status: Base
    +Module: mod_include

    + +The XBitHack directives controls the parsing of ordinary html documents. +This directive only affects files associated with the MIME type +text/html. +Status can have the following values: +

    +
    off +
    No special treatment of executable files. +
    on +
    Any file that has the user-execute bit set will be treated as a +server-parsed html document. +
    full +
    As for on but also test the group-execute bit. If it +is set, then set the Last-modified date of the returned file to be the +last modified time of the file. If it is not set, then no last-modified date +is sent. Setting this bit allows clients and proxies to cache the result of +the request. +

    Note: you would not want to use this, for example, when you +#include a CGI that produces different output on each hit +(or potentially depends on the hit). +

    +

    + +


    +

    Using Server Side Includes for ErrorDocuments

    + +There is a document which +describes how to use the features of mod_include to offer internationalized +customized server error documents. +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_info.html b/APACHE_1_3b7/htdocs/manual/mod/mod_info.html new file mode 100644 index 0000000000..8afa84dc41 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_info.html @@ -0,0 +1,113 @@ + + + +Apache module mod_info + + + + + +

    Module mod_info

    + +This module is contained in the mod_info.c file. It +provides a comprehensive overview of the server configuration +including all installed modules and directives in the configuration +files. This module is not compiled into the +server by default. It is only available in Apache 1.1 and later. To +enable it, add the following line to the server build Configuration +file, and rebuild the server: + +
    +AddModule modules/standard/mod_info.o
    +
    + +

    Directives

    + + +
    +

    +To configure it, add the following to your access.conf file. + +

    +<Location /server-info>
    +SetHandler server-info
    +</Location>
    +
    + +You may wish to add a +<Limit> +clause inside the +location +directive to limit access to your server configuration information.

    +Once configured, the server information is obtained by accessing +http://your.host.dom/server-info

    +

    + + Note that the configuration files are read by the module at run-time, + and therefore the display may not reflect the running + server's active configuration if the files have been changed since the + server was last reloaded. Also, the configuration files must be + readable by the user as which the server is running (see the + User + directive), or else the directive settings will not be listed. +

    + It should also be noted that if mod_info is compiled into + the server, its handler capability is available in all + configuration files, including per-directory files + (e.g., .htaccess). This may have + security-related ramifications for your site. +

    +
    +
    + +
    + +

    AddModuleInfo

    +Syntax: AddModuleInfo module-name string
    +Context: server config, virtual host
    +Status: base
    +Module: mod_browser
    +Compatibility: Apache 1.3 and above

    + +This allows the content of string to be shown as +HTML interpreted, +Additional Information for the module module-name. +Example: +

    +
    +AddModuleInfo mod_auth.c 'See <A HREF="http://www.apache.org/docs/mod/mod_auth.html">http://www.apache.org/docs/mod/mod_auth.html</A>'
    +
    +
    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_isapi.html b/APACHE_1_3b7/htdocs/manual/mod/mod_isapi.html new file mode 100644 index 0000000000..bb7426379d --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_isapi.html @@ -0,0 +1,73 @@ + + + +Apache module mod_isapi + + + + + + +

    Module mod_isapi

    + +

    This module is contained in the mod_isapi.c file, and is + compiled in by default. It provides support for ISAPI Extensions when + running under Microsoft Windows. Any document with a handler of + isapi-isa will be processed by this module. + +

    Purpose

    + +

    This module implements the ISAPI + Extension API. It allows Internet Server Applications (i.e., ISAPI + Extensions) to be used with Apache for Windows. + +

    Usage

    + +

    In the server configuration file, add a handler called + isapi-isa, and map it to files with a .DLL + extension. In other words:

    +
    +    AddHandler isapi-isa dll
    +
    +

    Now simply place the ISA DLLs into your document root, and they will + be loaded when their URLs are accessed.

    + +

    ISAPI Extensions are governed by the same restrictions as CGI + scripts. That is, Options ExecCGI must be active in the + directory that contains the ISA.

    + +

    Notes

    + +

    Apache's ISAPI implementation conforms to all of the ISAPI 2.0 + specification, except for the "Microsoft-specific" extensions dealing + with asynchronous I/O. Apache's I/O model does not allow asynchronous + reading and writing in a manner that the ISAPI could access. If an ISA + tries to access async I/O, a message will be place in the error log, + to help with debugging. + +

    Some servers, like Microsoft IIS, load the ISA into the server, and + keep it loaded until memory usage is too high, and it is + unloaded. Apache currently loads and unloads the ISA for each + request. This is inefficient, but Apache's request model makes this + method the only method that currently works. A future release may use + a more effective loading method. + +

    Apache 1.3a1 currently limits POST and PUT input to 48k per + request. This is to work around a problem with the ISAPI implementation + that could result in a denial of service attack. It is expected that + support for larger uploads will be added soon. + +

    Also, remember that while Apache supports ISAPI Extensions, it does + not support ISAPI Filters. Support for filters may be added at a later + date, but no support is planned at this time.

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_log_agent.html b/APACHE_1_3b7/htdocs/manual/mod/mod_log_agent.html new file mode 100644 index 0000000000..1506885aba --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_log_agent.html @@ -0,0 +1,76 @@ + + + +Module mod_log_agent + + + + + +

    Module mod_log_agent

    + +This module is contained in the mod_log_agent.c file, and is not +compiled in by default. It provides for logging of the client user agents. + + + +
    + + +

    AgentLog

    + +Syntax: AgentLog file-pipe
    +Default: AgentLog logs/agent_log
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_log_agent

    + +The AgentLog directive sets the name of the file to which the server will +log the UserAgent header of incoming requests. File-pipe is one +of +

    A filename +
    A filename relative to the ServerRoot. +
    `|' followed by a command +
    A program to receive the agent log information on its standard input. +Note the a new program will not be started for a VirtualHost if it inherits +the AgentLog from the main server. +
    +Security: if a program is used, then it will be +run under the user who started httpd. This will be root if the server +was started by root; be sure that the program is secure.

    + +Security: See the security tips document for +details on why your security could be compromised if the directory +where logfiles are stored is writable by anyone other than the user +that starts the server.

    + +This directive is provided for compatibility with NCSA 1.4.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_log_common.html b/APACHE_1_3b7/htdocs/manual/mod/mod_log_common.html new file mode 100644 index 0000000000..17984ddab7 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_log_common.html @@ -0,0 +1,116 @@ + + + +Apache module mod_log_common + + + + + +

    Module mod_log_common

    + +This module is contained in the mod_log_common.c file, +and is compiled in by default. It provides for logging of the requests +made to the server using the Common Logfile Format. This module has +been replaced by mod_log_config in Apache 1.2 + +

    Log file format

    +The log file contains a separate line for each request. A line is composed +of several tokens separated by spaces: +
    +host ident authuser date request status bytes +
    +If a token does not have a value then it is represented by a hyphen (-). +The meanings and values of these tokens are as follows: +
    +
    host +
    The fully-qualified domain name of the client, or its IP number if the +name is not available. +
    ident +
    If IdentityCheck is enabled and the +client machine runs identd, then this is the identity information reported +by the client. +
    authuser +
    If the request was for an password protected document, then this is +the userid used in the request. +
    date +
    The date and time of the request, in the following format: +
    date = [day/month/year:hour:minute:second zone]
    +day = 2*digit
    +month = 3*letter
    +year = 4*digit
    +hour = 2*digit
    +minute = 2*digit
    +second = 2*digit
    +zone = (`+' | `-') 4*digit
    +
    request +
    The request line from the client, enclosed in double quotes +("). +
    status +
    The three digit status code returned to the client. +
    bytes +
    The number of bytes in the object returned to the client, not including +any headers. +
    + + +

    Directives

    + +
    + + +

    TransferLog

    + +Syntax: TransferLog file-pipe
    +Default: TransferLog logs/transfer_log
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_log_common

    + +The TransferLog directive sets the name of the file to which the server will +log the incoming requests. File-pipe is one +of +

    A filename +
    A filename relative to the ServerRoot. +
    `|' followed by a command +
    A program to receive the agent log information on its standard input. +Note the a new program will not be started for a VirtualHost if it inherits +the TransferLog from the main server. +
    +Security: if a program is used, then it will be +run under the user who started httpd. This will be root if the server +was started by root; be sure that the program is secure.

    + +Security: See the security tips document for +details on why your security could be compromised if the directory +where logfiles are stored is writable by anyone other than the user +that starts the server.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_log_config.html b/APACHE_1_3b7/htdocs/manual/mod/mod_log_config.html new file mode 100644 index 0000000000..f23ac3daf4 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_log_config.html @@ -0,0 +1,376 @@ + + + +Apache module mod_log_config + + + + + +

    Module mod_log_config

    + +This module is contained in the mod_log_config.c file, +and is compiled in by default in Apache 1.2. mod_log_config replaces +mod_log_common in Apache 1.2. Prior to version 1.2, mod_log_config was +an optional module. It provides for logging of the requests made to +the server, using the Common Log Format or a user-specified format. + +

    Summary

    + +Three directives are provided by this module: TransferLog +to create a log file, LogFormat to set a custom format, +and CustomLog to define a log file and format in one go. +The TransferLog and CustomLog directives can +be used multiple times in each server to cause each request to be +logged to multiple files. +

    + +

    Compatibility notes

    + +
      +
    • This module is based on mod_log_config distributed with +previous Apache releases, now updated to handle multiple logs. +There is now no need to re-configure Apache to use configuration log +formats. + +
    • The module also implements the CookieLog directive, +used to log user-tracking information created by mod_usertrack. The use of +CookieLog is deprecated, and a CustomLog +should be defined to log user-tracking information instead. + +
    + +

    Log File Formats

    + +Unless told otherwise with LogFormat the log files created by +TransferLog will be in standard "Common Log Format" +(CLF). The contents of each line in a CLF file are explained +below. Alternatively, the log file can be customized (and if multiple +log files are used, each can have a different format). Custom formats +are set with LogFormat and CustomLog. + +

    Common Log Format

    + +The Common Log Format (CLF) file contains a separate line for each +request. A line is composed of several tokens separated by spaces: + +
    +host ident authuser date request status bytes +
    +If a token does not have a value then it is represented by a hyphen (-). +The meanings and values of these tokens are as follows: +
    +
    host +
    The fully-qualified domain name of the client, or its IP number if the +name is not available. +
    ident +
    If IdentityCheck is enabled and the +client machine runs identd, then this is the identity information reported +by the client. +
    authuser +
    If the request was for an password protected document, then this is +the userid used in the request. +
    date +
    The date and time of the request, in the following format: +
    date = [day/month/year:hour:minute:second zone]
    +day = 2*digit
    +month = 3*letter
    +year = 4*digit
    +hour = 2*digit
    +minute = 2*digit
    +second = 2*digit
    +zone = (`+' | `-') 4*digit
    +
    request +
    The request line from the client, enclosed in double quotes +("). +
    status +
    The three digit status code returned to the client. +
    bytes +
    The number of bytes in the object returned to the client, not including +any headers. +
    + +

    Custom Log Formats

    + +The format argument to the LogFormat and +CustomLog is a string. This string is logged to the log +file for each request. It can contain literal characters copied into +the log files, and `%' directives which are replaced in the log file +by the values as follows: + +
    +%...b:          Bytes sent, excluding HTTP headers.
    +%...f:          Filename
    +%...{FOOBAR}e:  The contents of the environment variable FOOBAR
    +%...h:          Remote host
    +%...a:          Remote IP-address
    +%...{Foobar}i:  The contents of Foobar: header line(s) in the request
    +                sent to the server.
    +%...l:          Remote logname (from identd, if supplied)
    +%...{Foobar}n:  The contents of note "Foobar" from another module.
    +%...{Foobar}o:  The contents of Foobar: header line(s) in the reply.
    +%...p:          The canonical Port of the server serving the request
    +%...P:          The process ID of the child that serviced the request.
    +%...r:          First line of request
    +%...s:          Status.  For requests that got internally redirected, this
    +                is status of the *original* request --- %...>s for the last.
    +%...t:          Time, in common log format time format
    +%...{format}t:  The time, in the form given by format, which should
    +                be in strftime(3) format.
    +%...T:          The time taken to serve the request, in seconds.
    +%...u:          Remote user (from auth; may be bogus if return status (%s) is 401)
    +%...U:          The URL path requested.
    +%...v:          The canonical ServerName of the server serving the request.
    +
    + +The `...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can +indicate conditions for inclusion of the item (which will cause it +to be replaced with `-' if the condition is not met). Note that +there is no escaping performed on the strings from %r, %...i and +%...o; some with long memories may remember that I thought this was +a bad idea, once upon a time, and I'm still not comfortable with +it, but it is difficult to see how to `do the right thing' with all +of `%..i', unless we URL-escape everything and break with CLF. + +

    + +The forms of condition are a list of HTTP status codes, which may +or may not be preceded by `!'. Thus, `%400,501{User-agent}i' logs +User-agent: on 400 errors and 501 errors (Bad Request, Not +Implemented) only; `%!200,304,302{Referer}i' logs Referer: on all +requests which did not return some sort of normal status. + +

    + +Note that the common log format is defined by the string "%h %l +%u %t \"%r\" %s %b", which can be used as the basis for +extending for format if desired (e.g. to add extra fields at the end). +NCSA's extended/combined log format would be "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\"". + +

    + +Note that the canonical ServerName +and Port of the server serving the request +are used for %v and %p respectively. This +happens regardless of the +UseCanonicalName setting because +otherwise log analysis programs would have to duplicate the entire +vhost matching algorithm in order to decide what host really served +the request. + +

    Using Multiple Log Files

    + +The TransferLog and CustomLog directives can +be given more than once to log requests to multiple log files. Each +request will be logged to all the log files defined by either of these +directives. + +

    Use with Virtual Hosts

    + +If a <VirtualHost> section does not contain any +TransferLog or CustomLog directives, the +logs defined for the main server will be used. If it does +contain one or more of these directives, requests serviced by +this virtual host will only be logged in the log files defined +within its definition, not in any of the main server's log files. +See the examples below. +

    + +

    Security Considerations

    + +See the security tips +document for details on why your security could be compromised if the +directory where logfiles are stored is writable by anyone other than +the user that starts the server. +

    +

    Directives

    + + +
    + + +

    CookieLog

    + +Syntax: CookieLog filename
    +Context: server config, virtual host
    +Module: mod_cookies
    +Compatibility: Only available in Apache 1.2 and above

    + +The CookieLog directive sets the filename for logging of cookies. +The filename is relative to the ServerRoot. This directive is included +only for compatibility with mod_cookies, and is deprecated. +

    + +


    +

    CustomLog

    +Syntax: CustomLog file-pipe + format-or-nickname
    +Context: server config, virtual host
    +Status: Base
    +Compatibility: Nickname only available in Apache 1.3 + or later +
    +Module: mod_log_config +

    +The first argument is the filename to which log records should be +written. This is used +exactly like the argument to +TransferLog; +that is, it is either a full path or relative to the current +server root. +

    +

    +The format argument specifies a format for each line of the log file. +The options available for the format are exactly the same as for +the argument of the LogFormat directive. If the format +includes any spaces (which it will do in almost all cases) it +should be enclosed in double quotes. +

    +

    +Instead of an actual format string, you can use a format nickname defined with +the +LogFormat +directive. +

    +
    +

    LogFormat

    + +Syntax: LogFormat format [nickname] +
    +Default: LogFormat "%h %l %u %t \"%r\" +%s %b"
    +Context: server config, virtual host
    +Status: Base
    +Compatibility: Nickname only available in Apache 1.3 + or later +
    +Module: mod_log_config +

    +This sets the format of the default logfile named by the +TransferLog +directive . See the section on +Custom Log Formats for details on the format +arguments. +

    +

    +If you include a nickname for the format on the directive line, you can +use it in other LogFormat and +CustomLog +directives rather than repeating the entire format string. +

    +

    +A +LogFormat directive which defines a nickname does +nothing else -- that is, it only defines the nickname, +it doesn't actually apply the format and make it the default. +

    + +
    +

    TransferLog

    + +Syntax: TransferLog file-pipe
    +Default: none
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_log_config

    + +The TransferLog directive adds a log file in the format defined by the +most recent +LogFormat +directive, or Common Log Format if no other default format has been +specified. +File-pipe is one +of +

    A filename +
    A filename relative to the ServerRoot. +
    `|' followed by a command +
    A program to receive the agent log information on its standard input. +Note the a new program will not be started for a VirtualHost if it inherits +the TransferLog from the main server. +
    +Security: if a program is used, then it will be +run under the user who started httpd. This will be root if the server +was started by root; be sure that the program is secure.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_log_referer.html b/APACHE_1_3b7/htdocs/manual/mod/mod_log_referer.html new file mode 100644 index 0000000000..6e500a1f99 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_log_referer.html @@ -0,0 +1,115 @@ + + + +Apache module mod_log_referer + + + + + +

    Module mod_log_referer

    + +This module is contained in the mod_log_referer.c file, and is not +compiled in by default. It provides for logging of the documents which +reference documents on the server. + +

    Log file format

    +The log file contains a separate line for each refer. Each line has the +format +
    uri -> document
    +where uri is the (%-escaped) URI for the document that references +the one requested by the client, and document is the (%-decoded) +local URL to the document being referred to. + + +

    Directives

    + +
    + + +

    RefererIgnore

    + +Syntax: RefererIgnore string string ...
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_log_referer

    + +The RefererIgnore directive adds to the list of strings to ignore in +Referer headers. If any of the strings in the list is contained in +the Referer header, then no referrer information will be logged for the +request. Example: +

    RefererIgnore www.ncsa.uiuc.edu
    +This avoids logging references from www.ncsa.uiuc.edu. +


    + + +

    RefererLog

    + +Syntax: RefererLog file-pipe
    +Default: RefererLog logs/referer_log
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_log_referer

    + +The RefererLog directive sets the name of the file to which the server will +log the Referer header of incoming requests. File-pipe is one +of +

    A filename +
    A filename relative to the ServerRoot. +
    `|' followed by a command +
    A program to receive the referrer log information on its standard input. +Note the a new program will not be started for a VirtualHost if it inherits +the RefererLog from the main server. +
    +Security: if a program is used, then it will be +run under the user who started httpd. This will be root if the server +was started by root; be sure that the program is secure.

    + +Security: See the security tips document for +details on why your security could be compromised if the directory +where logfiles are stored is writable by anyone other than the user +that starts the server.

    + +This directive is provided for compatibility with NCSA 1.4.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_mime.html b/APACHE_1_3b7/htdocs/manual/mod/mod_mime.html new file mode 100644 index 0000000000..08d7e85852 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_mime.html @@ -0,0 +1,365 @@ + + + +Apache module mod_mime + + + + + +

    Module mod_mime

    + +This module is contained in the mod_mime.c file, and is +compiled in by default. It provides for determining the types of files +from the filename. + +

    Summary

    + +This module is used to determine various bits of "meta information" +about documents. This information relates to the content of the +document and is returned to the browser or used in content-negotiation +within the server. In addition, a "handler" can be set for a document, +which determines how the document will be processed within the server. + +

    + +The directives AddEncoding, AddHandler, AddLanguage and AddType +are all used to map file extensions onto the meta-information for that +file. Respectively they set the content-encoding, handler, +content-language and mime-type (content-type) of documents. The +directive TypesConfig is used to specify a +file which also maps extensions onto mime types. The directives ForceType and SetHandler are used to associated all the files +in a given location (e.g. a particular directory) onto a particular +mime type or handler. + +

    + +Files can have more than one extension, and the order of the +extensions is normally irrelevant. For example, if the file +welcome.html.fr maps onto content type text/html and +language French then the file welcome.fr.html will map +onto exactly the same information. The only exception to this is if an +extension is given which Apache does not know how to handle. In this +case it will "forget" about any information it obtained from +extensions to the left of the unknown extension. So, for example, if +the extensions fr and html are mapped to the appropriate language and +type but extension xxx is not assigned to anything, then the file +welcome.fr.xxx.html will be associated with content-type +text/html but no language. + +

    + +Note that changing the type or encoding of a file does not change the +value of the Last-Modified header. Thus, previously cached +copies may still be used by a client or proxy, with the previous headers. + +

    + +Please note that changing a file's type or encoding does not change +the value of the Last-Modified header. Previously cached +copies may still be used by a client or proxy. + +

    + +

    Directives

    + +
    + + +

    AddEncoding

    + +Syntax: AddEncoding mime-enc extension extension...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime

    + +The AddEncoding directive adds to the list of filename extensions which +filenames may end in for the specified encoding type. Mime-enc +is the mime encoding to use for documents ending in extension. +Example: +

    +AddEncoding x-gzip gz
    +AddEncoding x-compress Z +
    + +This will cause files ending in .gz to be marked as encoded using the x-gzip +encoding, and .Z files to be marked as encoded with x-compress.

    + +Old clients expect x-gzip and x-compress, +however the standard dictates that they're equivalent to gzip +and compress respectively. Apache does content encoding +comparisons by ignoring any leading x-. When responding +with an encoding Apache will use whatever form (i.e. x-foo +or foo) the client requested. If the client didn't +specifically request a particular form Apache will use the form given by +the AddEncoding directive. To make this long story short, +you should always use x-gzip and x-compress +for these two specific encodings. More recent encodings, such as +deflate should be specified without the x-. + +


    + +

    AddHandler

    + +Syntax: AddHandler handler-name extension extension...
    +Context: server config, virtual host, directory, .htaccess
    +Status: Base
    +Module: mod_mime
    +Compatibility: AddHandler is only available in Apache +1.1 and later

    + +

    AddHandler maps the filename extensions extension to the +handler +handler-name. For example, to activate CGI scripts +with the file extension ".cgi", you might use: +

    +    AddHandler cgi-script cgi
    +
    + +

    Once that has been put into your srm.conf or httpd.conf file, any +file ending with ".cgi" will be treated as a CGI +program.

    +
    + +

    AddLanguage

    + +Syntax: AddLanguage mime-lang extension extension...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime

    + +The AddLanguage directive adds to the list of filename extensions which +filenames may end in for the specified content language. Mime-lang +is the mime language of files with names ending extension, +after any content encoding extensions have been removed. Example: +

    +AddEncoding x-compress Z
    +AddLanguage en .en
    +AddLanguage fr .fr
    +
    + +Then the document xxxx.en.Z will be treated as being a compressed +English document. Although the content language is reported to the client, +the browser is unlikely to use this information. The AddLanguage directive +is more useful for content negotiation, where the server returns one +from several documents based on the client's language preference.


    + +

    AddType

    + +Syntax: AddType mime-type extension extension...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime

    + +The AddType directive adds to the list of filename extensions which +filenames may end in for the specified content type. Mime-enc +is the mime type to use for documents ending in extension. +after content-encoding and language extensions have been removed. Example: +

    +AddType image/gif GIF +
    +It is recommended that new mime types be added using the AddType directive +rather than changing the TypesConfig file.

    +Note that, unlike the NCSA httpd, this directive cannot be used to set the +type of particular files.


    + +

    ForceType

    + +Syntax: ForceType media type
    +Context: directory, .htaccess
    +Status: Base
    +Module: mod_mime
    +Compatibility: ForceType is only available in Apache +1.1 and later.

    + +

    When placed into an .htaccess file or a +<Directory> or <Location> section, +this directive forces all matching files to be served +as the content type given by media type. For example, if you +had a directory full of GIF files, but did not want to label them all with +".gif", you might want to use: +

    +    ForceType image/gif
    +
    +

    Note that this will override any filename extensions that might determine +the media type.


    + +

    SetHandler

    + +Syntax: SetHandler handler-name
    +Context: directory, .htaccess
    +Status: Base
    +Module: mod_mime
    +Compatibility: SetHandler is only available in Apache +1.1 and later.

    + +

    When placed into an .htaccess file or a +<Directory> or <Location> section, +this directive forces all matching files to be parsed through the +handler +given by handler-name. For example, if you had a +directory you wanted to be parsed entirely as imagemap rule files, +regardless of extension, you might put the following into an +.htaccess file in that directory: +

    +    SetHandler imap-file
    +
    + +

    Another example: if you wanted to have the server display a status +report whenever a URL of http://servername/status was +called, you might put the following into access.conf: +

    +    <Location /status>
    +    SetHandler server-status
    +    </Location>
    +
    +
    + +

    TypesConfig

    + +Syntax: TypesConfig filename
    +Default: TypesConfig conf/mime.types
    +Context: server config
    +Status: Base
    +Module: mod_mime

    + +The TypesConfig directive sets the location of the mime types configuration +file. Filename is relative to the +ServerRoot. This file sets the default list of +mappings from filename extensions to content types; changing this file is not +recommended. Use the AddType directive instead. The +file contains lines in the format of the arguments to an AddType command: +

    mime-type extension extension ...
    +The extensions are lower-cased. Blank lines, and lines beginning with a hash +character (`#') are ignored.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_mime_magic.html b/APACHE_1_3b7/htdocs/manual/mod/mod_mime_magic.html new file mode 100644 index 0000000000..8efde7ea56 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_mime_magic.html @@ -0,0 +1,275 @@ + + + + Apache module mod_mime_magic + + + +

    + [APACHE DOCUMENTATION] +
    + +

    Module mod_mime_magic

    + + This module is contained in the mod_mime_magic.c file, and is + an optional extension to the Apache HTTPD server. + It can be used to determine the MIME type of a file by looking at a + few bytes of its contents, the same way the Unix file(1) command works. + To use mod_mime_magic you have to enable the following line in the + server build Configuration file: + +
    +      AddModule modules/standard/mod_mime_magic.o
    +  
    + + This should be listed before mod_mime in the build + Configuration file so that it will be used after mod_mime. + mod_mime_magic is intended as a "second line of defense" for cases + mod_mime cannot resolve. + +

    Summary

    + + This module is derived from a free version of the file(1) + command for Unix, + which uses "magic numbers" and other hints from a file's contents to + figure out what the contents are. + In the case of this module, + it tries to figure out the MIME type of the file. +

    + This module active only if the magic file is specified by the + MimeMagicFile directive. +

    + The contents of the file are plain ASCII text in 4-5 columns. + Blank lines are allowed but ignored. + Commented lines use a hash mark "#". + The remaining lines are parsed for the following columns: + + + + + + + + + + + + + + + + + + + + + +
    ColumnDescription
    1byte number to begin checking from +
    + ">" indicates a dependency upon the previous non-">" line
    2type of data to match + + + + + + + + + + + + +
    bytesingle character
    shortmachine-order 16-bit integer
    longmachine-order 32-bit integer
    stringarbitrary-length string
    datelong integer date + (seconds since Unix epoch/1970)
    beshortbig-endian 16-bit integer
    belongbig-endian 32-bit integer
    bedatebig-endian 32-bit integer date
    leshortlittle-endian 16-bit integer
    lelonglittle-endian 32-bit integer
    ledatelittle-endian 32-bit integer date
    +
    3contents of data to match
    4MIME type if matched
    5MIME encoding if matched (optional)
    + +

    + For example, the following magic file lines + would recognize some audio formats. + +

    +# Sun/NeXT audio data
    +0       string          .snd
    +>12     belong          1               audio/basic
    +>12     belong          2               audio/basic
    +>12     belong          3               audio/basic
    +>12     belong          4               audio/basic
    +>12     belong          5               audio/basic
    +>12     belong          6               audio/basic
    +>12     belong          7               audio/basic
    +>12     belong          23              audio/x-adpcm
    +
    + + Or these would recognize the difference between "*.doc" files containing + Microsoft Word or FrameMaker documents. (These are incompatible file + formats which use the same file suffix.) + +
    +# Frame
    +0       string          \<MakerFile     application/x-frame
    +0       string          \<MIFFile       application/x-frame
    +0       string          \<MakerDictionary       application/x-frame
    +0       string          \<MakerScreenFon        application/x-frame
    +0       string          \<MML           application/x-frame
    +0       string          \<Book          application/x-frame
    +0       string          \<Maker         application/x-frame
    +
    +# MS-Word
    +0       string          \376\067\0\043                  application/msword
    +0       string          \320\317\021\340\241\261        application/msword
    +0       string          \333\245-\0\0\0                 application/msword
    +
    + + An optional MIME encoding can be included as a fifth column. + For example, this can recognize gzipped files and set the encoding + for them. + +
    +# gzip (GNU zip, not to be confused with [Info-ZIP/PKWARE] zip archiver)
    +0       string          \037\213        application/octet-stream        x-gzip
    +
    + +

    Performance Issues

    + + This module is not for every system. If your system is barely keeping + up with its load or if you're performing a web server benchmark, + you may not want to enable this because the processing is not free. +

    + However, an effort was made to improve the performance of the original + file(1) code to make it fit in a busy web server. + It was designed for a server where there are thousands of users who + publish their own documents. + This is probably very common on intranets. + Many times, it's helpful + if the server can make more intelligent decisions about a file's + contents than the file name allows + ...even if just to reduce the "why doesn't my page work" calls + when users improperly name their own files. + You have to decide if the extra work suits your environment. +

    + When compiling an Apache server, this module should be at or near the + top of the list of modules in the Configuration file. The modules are + listed in increasing priority so that will mean this one is used only + as a last resort, just like it was designed to. + +

    Directives

    +

    +

    +

    +
    +

    + MimeMagicFile +

    +

    + Syntax: MimeMagicFile magic-file-name +
    + Default: none +
    + Context: server config, virtual host +
    + Status: Extension +
    + Module: mod_mime_magic +

    + + The MimeMagicFile directive can be used to enable this module, + the default file is distributed at conf/magic. + Non-rooted paths are relative to the ServerRoot. Virtual hosts + will use the same file as the main server unless a more specific setting + is used, in which case the more specific setting overrides the main server's + file. +

    +


    + +

    Notes

    + + The following notes apply to the mod_mime_magic module and are + included here for compliance with contributors' copyright restrictions + that require their acknowledgment. + +
    +/*
    + * mod_mime_magic: MIME type lookup via file magic numbers
    + * Copyright (c) 1996-1997 Cisco Systems, Inc.
    + *
    + * This software was submitted by Cisco Systems to the Apache Group in July
    + * 1997.  Future revisions and derivatives of this source code must
    + * acknowledge Cisco Systems as the original contributor of this module.
    + * All other licensing and usage conditions are those of the Apache Group.
    + *
    + * Some of this code is derived from the free version of the file command
    + * originally posted to comp.sources.unix.  Copyright info for that program
    + * is included below as required.
    + * ---------------------------------------------------------------------------
    + * - Copyright (c) Ian F. Darwin, 1987. Written by Ian F. Darwin.
    + *
    + * This software is not subject to any license of the American Telephone and
    + * Telegraph Company or of the Regents of the University of California.
    + *
    + * Permission is granted to anyone to use this software for any purpose on any
    + * computer system, and to alter it and redistribute it freely, subject to
    + * the following restrictions:
    + *
    + * 1. The author is not responsible for the consequences of use of this
    + * software, no matter how awful, even if they arise from flaws in it.
    + *
    + * 2. The origin of this software must not be misrepresented, either by
    + * explicit claim or by omission.  Since few users ever read sources, credits
    + * must appear in the documentation.
    + *
    + * 3. Altered versions must be plainly marked as such, and must not be
    + * misrepresented as being the original software.  Since few users ever read
    + * sources, credits must appear in the documentation.
    + *
    + * 4. This notice may not be removed or altered.
    + * -------------------------------------------------------------------------
    + *
    + * For compliance with Mr Darwin's terms: this has been very significantly
    + * modified from the free "file" command.
    + * - all-in-one file for compilation convenience when moving from one
    + *   version of Apache to the next.
    + * - Memory allocation is done through the Apache API's pool structure.
    + * - All functions have had necessary Apache API request or server
    + *   structures passed to them where necessary to call other Apache API
    + *   routines.  (i.e. usually for logging, files, or memory allocation in
    + *   itself or a called function.)
    + * - struct magic has been converted from an array to a single-ended linked
    + *   list because it only grows one record at a time, it's only accessed
    + *   sequentially, and the Apache API has no equivalent of realloc().
    + * - Functions have been changed to get their parameters from the server
    + *   configuration instead of globals.  (It should be reentrant now but has
    + *   not been tested in a threaded environment.)
    + * - Places where it used to print results to stdout now saves them in a
    + *   list where they're used to set the MIME type in the Apache request
    + *   record.
    + * - Command-line flags have been removed since they will never be used here.
    + *
    + */
    +
    + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_mmap_static.html b/APACHE_1_3b7/htdocs/manual/mod/mod_mmap_static.html new file mode 100644 index 0000000000..77100488ea --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_mmap_static.html @@ -0,0 +1,142 @@ + + + + Apache module mod_mmap_static + + + + +

    Module mod_mmap_static

    + +

    + This module is contained in the mod_mmap_static.c file, with + Apache 1.3 and later. It provides mmap()ing of a statically configured list + of frequently requested but not changed files. It is not compiled into the + server by default. To use mod_mmap_static you have to enable + the following line in the server build Configuration file: +

    +    AddModule  modules/experimental/mod_mmap_static.o
    +  
    +

    + +

    Summary

    +

    + This is an experimental module and should be used with + care. You can easily create a broken site using this module, read this + document carefully. + mod_mmap_static maps a list of statically configured files (via + MMapFile directives in the main server configuration) into + memory through the system call mmap(). This system + call is available on most modern Unix derivates, but not on all. There + are sometimes system-specific limits on the size and number of files that + can be mmap()d, experimentation is probably the easiest way to find out. +

    +

    + This mmap()ing is done once at server start or restart, only. So whenever + one of the mapped files changes on the filesystem you have to + restart the server by at least sending it a HUP or USR1 signal (see the + Stopping and Restarting documentation). To + reiterate that point: if the files are modified in place without + restarting the server you may end up serving requests that are completely + bogus. You should update files by unlinking the old copy and putting a new + copy in place. Most tools such as rdist and mv do + this. The reason why this modules doesn't take care of changes to the files + is that this check would need an extra stat() every time which + is a waste and against the intent of I/O reduction. +

    + +

    Directives

    + + +
    + +

    MMapFile

    +

    + Syntax: MMapFile filename ... +
    + Default: None +
    + Context: server-config +
    + Override: Not applicable +
    + Status: Experimental +
    + Module: mod_mmap_static +
    + Compatibility: Only available in Apache 1.3 or later + +

    + The MMapFile directive maps one or more files (given as + whitespace separated arguments) into memory at server startup time. They + are automatically unmapped on a server shutdown. When the files have changed + on the filesystem at least a HUP or USR1 signal should be send to the server + to re-mmap them. +

    + +

    + Be careful with the filename arguments: They have to literally + match the filesystem path Apache's URL-to-filename translation handlers + create. We cannot compare inodes or other stuff to match paths through + symbolic links etc. because that again would cost extra stat() + system calls which is not acceptable. This module may or may not work + with filenames rewritten by mod_alias or + mod_rewrite... it is an experiment after all. +

    + +

    + Notice: You cannot use this for speeding up CGI programs or other files + which are served by special content handlers. It can only be used for + regular files which are usually served by the Apache core content handler. +

    + + Example: + +
    +  MMapFile /usr/local/apache/htdocs/index.html
    +  
    + +

    + Note: don't bother asking for a for a MMapDir + directive which + recursively maps all the files in a directory. Use Unix the way it was + meant to be used. For example, see the + Include directive, and consider this command: +

    +  find /www/htdocs -type f -print \
    +  | sed -e 's/.*/mmapfile &/' > /www/conf/mmap.conf
    +  
    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_negotiation.html b/APACHE_1_3b7/htdocs/manual/mod/mod_negotiation.html new file mode 100644 index 0000000000..e2578bd27d --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_negotiation.html @@ -0,0 +1,177 @@ + + + +Apache module mod_negotiation + + + + + +

    Module mod_negotiation

    + +This module is contained in the mod_negotiation.c file, +and is compiled in by default. It provides for content negotiation. + +

    Summary

    +Content negotiation, or more accurately content selection, is the +selection of the document that best matches the clients +capabilities, from one of several available documents. +There are two implementations of this. +
      +
    • A type map (a file with the handler type-map) +which explicitly lists the files containing the variants. +
    • A MultiViews search (enabled by the MultiViews +Option, where the server does an implicit +filename pattern match, and choose from amongst the results. +
    + +

    Type maps

    +A type map has the same format as RFC822 mail headers. It contains document +descriptions separated by blank lines, with lines beginning with a hash +character ('#') treated as comments. A document description consists of +several header records; records may be continued on multiple lines if the +continuation lines start with spaces. The leading space will be deleted +and the lines concatenated. A header record consists of a keyword +name, which always ends in a colon, followed by a value. Whitespace is allowed +between the header name and value, and between the tokens of value. + +The headers allowed are: + +
    +
    Content-Encoding: +
    The encoding of the file. Currently only two encodings are recognized +by http; x-compress for compressed files, and x-gzip +for gzipped files. +
    Content-Language: +
    The language of the variant, as an Internet standard language code, such +as en. +
    Content-Length: +
    The length of the file, in bytes. If this header is not present, then +the actual length of the file is used. +
    Content-Type: +
    The MIME media type of the document, with optional parameters. +parameters are separated from the media type and from one another by +semi-colons. Parameter syntax is name=value; allowed parameters are: +
    +
    level +
    the value is an integer, which specifies the version of the media type. +For text/html this defaults to 2, otherwise 0. +
    qs +
    the value is a floating-point number with value between 0. and 1. +It indications the 'quality' of this variant. +
    +Example: +
    Content-Type: image/jpeg; qs=0.8
    +
    URI: +
    The path to the file containing this variant, relative to the map file. +
    + +

    MultiViews

    +A MultiViews search is enabled by the MultiViews +Option. +If the server receives a request for /some/dir/foo and +/some/dir/foo does not exist, then the server reads the +directory looking for all files named foo.*, and effectively +fakes up a type map which names all those files, assigning them the same media +types and content-encodings it would have if the client had asked for +one of them by name. It then chooses the best match to the client's +requirements, and returns that document.

    + + + +

    Directives

    + +
    + + +

    CacheNegotiatedDocs

    +Syntax: CacheNegotiatedDocs
    +Context: server config
    +Status: Base
    +Module: mod_negotiation
    +Compatibility: CacheNegotiatedDocs is only available +in Apache 1.1 and later.

    + +

    If set, this directive allows content-negotiated documents to be +cached by proxy servers. This could mean that clients behind those +proxys could retrieve versions of the documents that are not the best +match for their abilities, but it will make caching more +efficient. +

    + +This directive only applies to requests which come from HTTP/1.0 browsers. +HTTP/1.1 provides much better control over the caching of negotiated +documents, and this directive has no effect in responses to +HTTP/1.1 requests. + + + +

    LanguagePriority

    + +Syntax: LanguagePriority mime-lang mime-lang...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_negotiation

    + +The LanguagePriority sets the precedence of language variants for the case +where the client does not express a preference, when handling a +MultiViews request. The list of mime-lang are in order of decreasing +preference. Example: + +

    LanguagePriority en fr de
    + +For a request for foo.html, where foo.html.fr +and foo.html.de both existed, but the browser did not express +a language preference, then foo.html.fr would be returned.

    + +

    + +Note that this directive only has an effect if a 'best' language +cannot be determined by other any other means. Correctly implemented +HTTP/1.1 requests will mean this directive has no effect. + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_proxy.html b/APACHE_1_3b7/htdocs/manual/mod/mod_proxy.html new file mode 100644 index 0000000000..7bd269a6f4 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_proxy.html @@ -0,0 +1,1008 @@ + + + +Apache module mod_proxy + + + + + +

    Apache module mod_proxy

    + +This module is contained in the mod_proxy.c file for Apache 1.1.x, +or the modules/proxy subdirectory for Apache 1.2, and +is not compiled in by default. It provides for an HTTP +1.0 caching proxy +server. It is only available in Apache 1.1 and later. Common configuration +questions are addressed after the directive +descriptions. + +

    Note:

    +

    This module was experimental in Apache 1.1.x. As of Apache 1.2, mod_proxy +stability is greatly improved.

    + +

    Summary

    + +This module implements a proxy/cache for Apache. It implements +proxying capability for +FTP, +CONNECT (for SSL), +HTTP/0.9, and +HTTP/1.0. +The module can be configured to connect to other proxy modules for these +and other protocols. + +

    Directives

    + + +
    + +

    ProxyRequests

    +Syntax: ProxyRequests on/off
    +Default: ProxyRequests Off
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyRequests is only available in +Apache 1.1 and later.

    + +This allows or prevents Apache from functioning as a proxy +server. Setting ProxyRequests to 'off' does not disable use of the ProxyPass directive. + +


    + +

    ProxyRemote

    +Syntax: ProxyRemote <match> <remote-server>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyRemote is only available in +Apache 1.1 and later.

    + +This defines remote proxies to this proxy. <match> is either the +name of a URL-scheme that the remote server supports, or a partial URL +for which the remote server should be used, or '*' to indicate the +server should be contacted for all requests. <remote-server> is a +partial URL for the remote server. Syntax: + +

    +  <remote-server> = <protocol>://<hostname>[:port]
    +
    + +<protocol> is the protocol that should be used to communicate +with the remote server; only "http" is supported by this module. +

    +Example: +

    +  ProxyRemote http://goodguys.com/ http://mirrorguys.com:8000
    +  ProxyRemote * http://cleversite.com
    +  ProxyRemote ftp http://ftpproxy.mydomain.com:8080
    +
    + +In the last example, the proxy will forward FTP requests, encapsulated +as yet another HTTP proxy request, to another proxy which can handle +them. + +
    + +

    ProxyPass

    +Syntax: ProxyPass <path> <url>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyPass is only available in +Apache 1.1 and later.

    + +This directive allows remote servers to be mapped into the space of the local +server; the local server does not act as a proxy in the conventional sense, +but appears to be a mirror of the remote server. <path> is the name of +a local virtual path; <url> is a partial URL for the remote server. +

    +Suppose the local server has address http://wibble.org/; then +

    +   ProxyPass /mirror/foo http://foo.com
    +
    +will cause a local request for the +<http://wibble.org/mirror/foo/bar> to be +internally converted into a proxy request to +<http://foo.com/bar>. + +
    + +

    ProxyPassReverse

    +Syntax: ProxyPassReverse <path> <url>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyPassReverse is only available in +Apache 1.3b6 and later.

    + +This directive lets Apache adjust the URL in the Location header on +HTTP redirect responses. For instance this is essential when Apache is used as +a reverse proxy to avoid by-passing the reverse proxy because of HTTP +redirects on the backend servers which stay behind the reverse proxy. +

    +<path> is the name of a local virtual path.
    +<url> is a partial URL for the remote server - the same way they are +used for the ProxyPass directive. +

    +Example:
    +Suppose the local server has address http://wibble.org/; then +

    +   ProxyPass         /mirror/foo http://foo.com
    +   ProxyPassReverse  /mirror/foo http://foo.com
    +
    +will not only cause a local request for the +<http://wibble.org/mirror/foo/bar> to be internally +converted into a proxy request to <http://foo.com/bar> (the +functionality ProxyPass provides here). It also takes care of +redirects the server foo.com sends: when http://foo.com/bar is +redirected by him to http://foo.com/quux Apache adjusts this to +http://wibble.org/mirror/foo/quux before forwarding the HTTP +redirect response to the client. +

    +Note that this ProxyPassReverse directive can also by used in +conjunction with the proxy pass-through feature ("RewriteRule ... +[P]") from +mod_rewrite because its doesn't depend on a corresponding +ProxyPass directive. + +


    + +

    ProxyBlock

    +Syntax: ProxyBlock <word/host/domain list>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyBlock is only available in +Apache 1.2 and later.

    + +The ProxyBlock directive specifies a list of words, hosts and/or domains, +separated by spaces. HTTP, HTTPS, and FTP document requests to matched words, +hosts or domains are blocked by the proxy server. The proxy module +will also attempt to determine IP addresses of list items which may be +hostnames during startup, and cache them for match test as well. Example: + +

    +  ProxyBlock joes_garage.com some_host.co.uk rocky.wotsamattau.edu
    +
    + +'rocky.wotsamattau.edu' would also be matched if referenced by IP address.

    + +Note that 'wotsamattau' would also be sufficient to match 'wotsamattau.edu'.

    + +Note also that + +

    +ProxyBlock *
    +
    + +blocks connections to all sites. + +
    + +

    ProxyReceiveBufferSize

    +Syntax: ProxyReceiveBufferSize <bytes>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyReceiveBufferSize is only available in +Apache 1.3 and later.

    + +The ProxyReceiveBufferSize directive specifies an explicit network buffer size +for outgoing HTTP and FTP connections, for increased throughput. It has to be +greater than 512 or set to 0 to indicate that the system's default buffer size +should be used. + +

    +Example: + +

    +  ProxyReceiveBufferSize 2048
    +
    + +
    + +

    NoProxy

    +Syntax: NoProxy { <Domain> + | <SubNet> + | <IpAddr> + | <Hostname> + }
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: NoProxy is only available in +Apache 1.3 and later.

    + +This directive is only useful for Apache proxy servers within intranets. +The NoProxy directive specifies a list of subnets, IP addresses, hosts +and/or domains, separated by spaces. A request to a host which matches +one or more of these is always served directly, without forwarding to +the configured ProxyRemote proxy server(s). +

    +Example: + +

    +  ProxyRemote  *  http://firewall.mycompany.com:81
    +  NoProxy         .mycompany.com 192.168.112.0/21 
    +
    +The arguments to the NoProxy directive are one of the following type list: +
    + + +
    Domain +
    A Domain is a partially qualified DNS domain name, preceded + by a period. + It represents a list of hosts which logically belong to the same DNS + domain or zone (i.e. the suffixes of the hostnames are all ending in + Domain).
    + Examples: .com .apache.org.
    + To distinguish Domains from Hostnames (both + syntactically and semantically; a DNS domain can have a DNS A record, + too!), Domains are always written + with a leading period.
    + Note: Domain name comparisons are done without regard to the case, + and Domains are always assumed to be anchored in the root + of the DNS tree, therefore two domains .MyDomain.com and + .mydomain.com. (note the trailing period) are + considered equal. Since a domain comparison does not involve a DNS + lookup, it is much more efficient than subnet comparison. + + + +
    SubNet +
    A SubNet is a partially qualified internet address in + numeric (dotted quad) form, optionally followed by a slash and the + netmask, specified as the number of significant bits in the + SubNet. It is used to represent a subnet of hosts which can + be reached over a common network interface. In the absence of the + explicit net mask it is assumed that omitted (or zero valued) + trailing digits specify the mask. (In this case, the netmask can + only be multiples of 8 bits wide.)
    + Examples: +
    +
    192.168 or 192.168.0.0 +
    the subnet 192.168.0.0 with an implied netmask of 16 valid bits + (sometimes used in the netmask form 255.255.0.0) +
    192.168.112.0/21 +
    the subnet 192.168.112.0/21 with a netmask of 21 + valid bits (also used in the form 255.255.248.0) +
    + As a degenerate case, a SubNet with 32 valid bits is the + equivalent to an IPAddr, while a SubNet with zero + valid bits (e.g., 0.0.0.0/0) is the same as the constant + _Default_, matching any IP address. + + + +
    IPAddr +
    A IPAddr represents a fully qualified internet address in + numeric (dotted quad) form. Usually, this address represents a + host, but there need not necessarily be a DNS domain name + connected with the address.
    + Example: 192.168.123.7
    + Note: An IPAddr does not need to be resolved by the DNS + system, so it can result in more effective apache performance. +

    See Also: + DNS Issues

    + + + +
    Hostname +
    A Hostname is a fully qualified DNS domain name which can + be resolved to one or more IPAddrs via the DNS domain name service. + It represents a logical host (in contrast to + Domains, see + above) and must be resolvable to at least one IPAddr (or often to a list of hosts + with different IPAddr's).
    + Examples: prep.ai.mit.edu + www.apache.org.
    + Note: In many situations, it is more effective to specify an + IPAddr in place of a + Hostname since a DNS lookup + can be avoided. Name resolution in Apache can take a remarkable deal + of time when the connection to the name server uses a slow PPP + link.
    + Note: Hostname comparisons are done without regard to the case, + and Hostnames are always assumed to be anchored in the root + of the DNS tree, therefore two hosts WWW.MyDomain.com + and www.mydomain.com. (note the trailing period) are + considered equal.
    +

    See Also: +DNS Issues

    +
    + +
    + +

    ProxyDomain

    +Syntax: ProxyDomain <Domain>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyDomain is only available in +Apache 1.3 and later.

    + +This directive is only useful for Apache proxy servers within intranets. +The ProxyDomain directive specifies the default domain which the apache +proxy server will belong to. If a request to a host without a domain name +is encountered, a redirection response to the same host +with the configured Domain appended will be generated. +

    +Example: + +

    +  ProxyRemote  *  http://firewall.mycompany.com:81
    +  NoProxy         .mycompany.com 192.168.112.0/21 
    +  ProxyDomain     .mycompany.com
    +
    + +
    + +

    CacheRoot

    +Syntax: CacheRoot <directory>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheRoot is only available in +Apache 1.1 and later.

    + +Sets the name of the directory to contain cache files; this must be +writable +by the httpd server. + +


    + +

    CacheSize

    +Syntax: CacheSize <size>
    +Default: CacheSize 5
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheSize is only available in +Apache 1.1 and later.

    + +Sets the desired space usage of the cache, in KB (1024-byte units). Although +usage may grow above this setting, the garbage collection will delete files +until the usage is at or below this setting. + +


    + +

    CacheGcInterval

    +Syntax: CacheGcInterval <time>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheGcinterval is only available in +Apache 1.1 and later.

    + +Check the cache every <time> hours, and delete files if the space +usage is greater than that set by CacheSize. + +


    + +

    CacheMaxExpire

    +Syntax: CacheMaxExpire <time>
    +Default: CacheMaxExpire 24
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheMaxExpire is only available in +Apache 1.1 and later.

    + +Cachable HTTP documents will be retained for at most <time> hours without +checking the origin server. Thus documents can be at most <time> +hours out of date. This restriction is enforced even if an expiry date +was supplied with the document. + +


    + +

    CacheLastModifiedFactor

    +Syntax: CacheLastModifiedFactor <factor>
    +Default: CacheLastModifiedFactor 0.1
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheLastModifiedFactor is only available in +Apache 1.1 and later.

    + +If the origin HTTP server did not supply an expiry date for the +document, then estimate one using the formula +

    +  expiry-period = time-since-last-modification * <factor>
    +
    +For example, if the document was last modified 10 hours ago, and +<factor> is 0.1, then the expiry period will be set to 10*0.1 = 1 hour. + +

    If the expiry-period would be longer than that set by CacheMaxExpire, +then the latter takes precedence. + +


    + +

    CacheDirLevels

    +Syntax: CacheDirLevels <levels>
    +Default: CacheDirLevels 3
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheDirLevels is only available in +Apache 1.1 and later.

    + +CacheDirLevels sets the number of levels of subdirectories in the cache. +Cached data will be saved this many directory levels below CacheRoot. + +


    + +

    CacheDirLength

    +Syntax: CacheDirLength <length>
    +Default: CacheDirLength 1
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheDirLength is only available in +Apache 1.1 and later.

    + +CacheDirLength sets the number of characters in proxy cache subdirectory names. + +


    + +

    CacheDefaultExpire

    +Syntax: CacheDefaultExpire <time>
    +Default: CacheDefaultExpire 1
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheDefaultExpire is only available in +Apache 1.1 and later.

    + +If the document is fetched via a protocol that does not support expiry times, +then use <time> hours as the expiry time. +CacheMaxExpire does not +override this setting. + +


    + +

    NoCache

    +Syntax: NoCache <word/host/domain list>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: NoCache is only available in +Apache 1.1 and later.

    + +The NoCache directive specifies a list of words, hosts and/or domains, separated +by spaces. HTTP and non-passworded FTP documents from matched words, hosts or +domains are not cached by the proxy server. The proxy module will +also attempt to determine IP addresses of list items which may be hostnames +during startup, and cache them for match test as well. Example: + +

    +  NoCache joes_garage.com some_host.co.uk bullwinkle.wotsamattau.edu
    +
    + +'bullwinkle.wotsamattau.edu' would also be matched if referenced by IP +address.

    + +Note that 'wotsamattau' would also be sufficient to match 'wotsamattau.edu'.

    + +Note also that + +

    +NoCache *
    +
    + +disables caching completely.

    + +


    + +

    Common configuration topics

    + + + +

    Controlling access to your proxy

    + +You can control who can access your proxy via the normal <Directory> +control block using the following example:

    + +

    +<Directory proxy:*>
    +order deny,allow
    +deny from [machines you'd like *not* to allow by IP address or name]
    +allow from [machines you'd like to allow by IP address or name]
    +</Directory>
    +

    + +A <Files> block will also work, and is the only method known to work +for all possible URLs in Apache versions earlier than 1.2b10.

    + +

    Using Netscape hostname shortcuts

    + +There is an optional patch to the proxy module to allow Netscape-like +hostname shortcuts to be used. It's available from the +contrib/patches/1.2 directory on the Apache Web site.

    + +

    Why doesn't file type xxx download via FTP?

    + +You probably don't have that particular file type defined as +application/octet-stream in your proxy's mime.types configuration +file. A useful line can be

    + +

    +application/octet-stream        bin dms lha lzh exe class tgz taz
    +
    + +

    How can I force an FTP ASCII download of File xxx?

    + +In the rare situation where you must download a specific file using the FTP +ASCII transfer method (while the default transfer is in +binary mode), you can override mod_proxy's default by +suffixing the request with ;type=a to force an ASCII transfer.

    + +

    Why does Apache start more slowly when using the + proxy module?

    + +If you're using the ProxyBlock or NoCache +directives, hostnames' IP addresses are looked up and cached during +startup for later match test. This may take a few seconds (or more) +depending on the speed with which the hostname lookups occur.

    + +

    Can I use the Apache proxy module with my SOCKS proxy?

    + +Yes. Just build Apache with the rule SOCKS4=yes in your +Configuration file, and follow the instructions there. SOCKS5 +capability can be added in a similar way (there's no SOCKS5 +rule yet), so use the EXTRA_LDFLAGS definition, or build Apache +normally and run it with the runsocks wrapper provided with SOCKS5, +if your OS supports dynamically linked libraries.

    + +Some users have reported problems when using SOCKS version 4.2 on Solaris. +The problem was solved by upgrading to SOCKS 4.3.

    + +Remember that you'll also have to grant access to your Apache proxy machine by +permitting connections on the appropriate ports in your SOCKS daemon's +configuration.

    + +

    What other functions are useful for an intranet proxy server?

    + +

    An Apache proxy server situated in an intranet needs to forward external +requests through the company's firewall. However, when it has to access +resources within the intranet, it can bypass the firewall when accessing +hosts. The NoProxy directive is useful for specifying +which hosts belong to the intranet and should be accessed directly.

    + +

    Users within an intranet tend to omit the local domain name from their +WWW requests, thus requesting "http://somehost/" instead of +"http://somehost.my.dom.ain/". Some commercial proxy servers let them get +away with this and simply serve the request, implying a configured +local domain. When the ProxyDomain directive +is used and the server is configured for +proxy service, Apache can return a redirect response and send the client +to the correct, fully qualified, server address. This is the preferred method +since the user's bookmark files will then contain fully qualified hosts.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_rewrite.html b/APACHE_1_3b7/htdocs/manual/mod/mod_rewrite.html new file mode 100644 index 0000000000..ce5f5e14fa --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_rewrite.html @@ -0,0 +1,1818 @@ + + + + + + +Apache module mod_rewrite + + + + +
    + + +
    +

    Module mod_rewrite
    URL Rewriting Engine

    + +This module is contained in the mod_rewrite.c file, with Apache +1.2 and later. It provides a rule-based rewriting engine to rewrite requested +URLs on the fly. It is not compiled into the server by default. To use +mod_rewrite you have to enable the following line in the server +build Configuration file: +
    +    AddModule  modules/standard/mod_rewrite.o
    +
    + +

    +


    + +
    +

    Summary

    + +
    +
    +
    +``The great thing about mod_rewrite is it gives you all the +configurability and flexibility of Sendmail. The downside to +mod_rewrite is that it gives you all the configurability and +flexibility of Sendmail.'' +
    +-- Brian Behlendorf
    +Apache Group +
    +
    +
    +
    + +Welcome to mod_rewrite, the Swiss Army Knife of URL manipulation! + +

    +This module uses a rule-based rewriting engine (based on a regular-expression +parser) to rewrite requested URLs on the fly. It supports an unlimited number +of rules and an unlimited number of attached rule conditions for each rule to +provide a really flexible and powerful URL manipulation mechanism. The URL +manipulations can depend on various tests, for instance server variables, +environment variables, HTTP headers, time stamps and even external database +lookups in various formats can be used to achieve a really granular URL +matching. + +

    +This module operates on the full URLs (including the path-info part) both in +per-server context (httpd.conf) and per-directory context +(.htaccess) and even can generate query-string parts on result. +The rewritten result can lead to internal sub-processing, external request +redirection or even to an internal proxy throughput. + +

    +But all this functionality and flexibility has its drawback: complexity. So +don't expect to understand this module in it's whole in just one day. + +

    +This module was invented and originally written in April 1996
    +and gifted exclusively to the The Apache Group in July 1997 by + +

    +

    +Ralf S. Engelschall
    +rse@engelschall.com
    +www.engelschall.com +
    + +

    +


    + +

    Table Of Contents

    + +

    +Internal Processing +

    +

    +Configuration Directives +

    +Miscellaneous + + +

    +


    + +
    +

    Internal Processing

    +
    + +

    +


    + +

    +The internal processing of this module is very complex but needs to be +explained once even to the average user to avoid common mistakes and to let +you exploit its full functionality. + +

    API Phases

    + +

    +First you have to understand that when Apache processes a HTTP request it does +this in phases. A hook for each of these phases is provided by the Apache API. +Mod_rewrite uses two of these hooks: the URL-to-filename translation hook +which is used after the HTTP request was read and before any authorization +starts and the Fixup hook which is triggered after the authorization phases +and after the per-directory config files (.htaccess) where read, +but before the content handler is activated. + +

    +So, after a request comes in and Apache has determined the corresponding +server (or virtual server) the rewriting engine start processing of all +mod_rewrite directives from the per-server configuration in the +URL-to-filename phase. A few steps later when the final data directories are +found, the per-directory configuration directives of mod_rewrite are triggered +in the Fixup phase. In both situations mod_rewrite either rewrites URLs to new +URLs or to filenames, although there is no obvious distinction between them. +This is a usage of the API which was not intended this way when the API +was designed, but as of Apache 1.x this is the only way mod_rewrite can +operate. To make this point more clear remember the following two points: + +

      +
    1. The API currently provides only a URL-to-filename hook. Although + mod_rewrite rewrites URLs to URLs, URLs to filenames and even + filenames to filenames. In Apache 2.0 the two missing hooks + will be added to make the processing more clear. But this + point has no drawbacks for the user, it is just a fact which + should be remembered: Apache does more in the URL-to-filename hook + then the API intends for it. +

      +

    2. Unbelievably mod_rewrite provides URL manipulations in per-directory + context, i.e. within .htaccess files, although these are + reached a very long time after the URLs were translated to filenames (this + has to be this way, because .htaccess files stay in the + filesystem, so processing has already been reached this stage of + processing). In other words: According to the API phases at this time it + is too late for any URL manipulations. To overcome this chicken and egg + problem mod_rewrite uses a trick: When you manipulate a URL/filename in + per-directory context mod_rewrite first rewrites the filename back to its + corresponding URL (which it usually impossible, but see the + RewriteBase directive below for the trick to achieve this) + and then initiates a new internal sub-request with the new URL. This leads + to a new processing of the API phases from the beginning. +

      + Again mod_rewrite tries hard to make this complicated step totally + transparent to the user, but you should remember here: While URL + manipulations in per-server context are really fast and efficient, + per-directory rewrites are slow and inefficient due to this chicken and + egg problem. But on the other hand this is the only way mod_rewrite can + provide (locally restricted) URL manipulations to the average user. +

    + +

    +Don't forget these two points! + +

    Ruleset Processing

    + +Now when mod_rewrite is triggered in these two API phases, it reads the +configured rulesets from its configuration structure (which itself was either +created on startup for per-server context or while the directory walk of the +Apache kernel for per-directory context). Then the URL rewriting engine is +started with the contained ruleset (one or more rules together with their +conditions). The operation of the URL rewriting engine itself is exactly the +same for both configuration contexts. Just the final result processing is +different. + +

    +The order of rules in the ruleset is important because the rewriting engine +processes them in a special order. And this order is not very obvious. The +rule is this: The rewriting engine loops through the ruleset rule by rule +(RewriteRule directives!) and when a particular rule matched it +optionally loops through existing corresponding conditions +(RewriteCond directives). Because of historical reasons the +conditions are given first, the control flow is a little bit winded. See +Figure 1 for more details. + +

    +

    + + + + + + + +
    [Needs graphics capability to display]
    +Figure 1: The control flow through the rewriting ruleset +
    +
    + +

    +As you can see, first the URL is matched against the Pattern of each +rule. When it fails mod_rewrite immediately stops processing this rule and +continues with the next rule. If the Pattern matched, mod_rewrite +looks for corresponding rule conditions. If none are present, it just +substitutes the URL with a new value which is constructed from the string +Substitution and goes on with its rule-looping. But if conditions But +if conditions exists, it starts an inner loop for processing them in order +they are listed. For conditions the logic is different: We don't match a +pattern against the current URL. Instead we first create a string +TestString by expanding variables, back-references, map lookups, etc. +and then we try to match TestPattern against it. If the pattern +doesn't match, the complete set of conditions and the corresponding rule fails. +If the pattern matches, then the next condition is processed until no more +condition is available. If all conditions matched processing is continued with +the substitution of the URL with Substitution. + +

    Regex Back-Reference Availability

    + +One important thing here has to be remembered: Whenever you +use parenthesis in Pattern or in one of the TestPattern +back-reference are internally created which can be used with the +strings $N and %N (see below). And these +are available for creating the strings Substitution and +TestCond. Figure 2 shows at which locations the back-references are +transfered to for expansion. + +

    +

    + + + + + + + +
    [Needs graphics capability to display]
    +Figure 2: The back-reference flow through a rule +
    +
    + +

    +We know, this was a crash course of mod_rewrite's internal processing. But +you will benefit from this knowledge when reading the following documentation +of the available directives. + +

    +


    + +
    +

    Configuration Directives

    +
    + +

    +


    + +

    RewriteEngine

    +Syntax: RewriteEngine {on,off}
    +Default: RewriteEngine off
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteEngine directive enables or disables the runtime +rewriting engine. If it is set to off this module does no runtime +processing at all. It does not even update the SCRIPT_URx +environment variables. + +

    +Use this directive to disable the module instead of commenting out +all RewriteRule directives! + +

    +Note that, by default, rewrite configurations are not inherited. +This means that you need to have a RewriteEngine on +directive for each virtual host you wish to use it in. + +

    +


    +

    + +

    RewriteOptions

    +Syntax: RewriteOptions Option
    +Default: None
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteOptions directive sets some special options for the +current per-server or per-directory configuration. The Option +strings can be one of the following: + +

      +
    • 'inherit'
      + This forces the current configuration to inherit the configuration of the + parent. In per-virtual-server context this means that the maps, + conditions and rules of the main server gets inherited. In per-directory + context this means that conditions and rules of the parent directory's + .htaccess configuration gets inherited. +
    + +

    +


    +

    + +

    RewriteLog

    +Syntax: RewriteLog Filename
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteLog directive sets the name of the file to which the +server logs any rewriting actions it performs. If the name does not begin +with a slash ('/') then it is assumed to be relative to the +Server Root. The directive should occur only once per server +config. + +

    + + +
    +Notice: To disable the logging of rewriting actions it is not recommended +to set Filename +to /dev/null, because although the rewriting engine does +not create output to a logfile it still creates the logfile +output internally. This will slow down the server with no advantage to the +administrator! +To disable logging either remove or comment out the +RewriteLog directive or use RewriteLogLevel 0! +
    + +

    + + +
    +Security: See the Apache Security +Tips document for details on why your security could be compromised if the +directory where logfiles are stored is writable by anyone other than the user +that starts the server. +
    + +

    +Example: +

    +
    +RewriteLog "/usr/local/var/apache/logs/rewrite.log"
    +
    +
    + +

    +


    +

    + +

    RewriteLogLevel

    +Syntax: RewriteLogLevel Level
    +Default: RewriteLogLevel 0
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteLogLevel directive set the verbosity level of the rewriting +logfile. The default level 0 means no logging, while 9 or more means +that practically all actions are logged. + +

    +To disable the logging of rewriting actions simply set Level to 0. +This disables all rewrite action logs. + +

    + + +
    +Notice: Using a high value for Level will slow down your Apache +server dramatically! Use the rewriting logfile only for debugging or at least +at Level not greater than 2! +
    + + +

    +Example: +

    +
    +RewriteLogLevel 3
    +
    +
    + +

    +


    +

    + +

    RewriteLock

    +Syntax: RewriteLock Filename
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.3
    + +

    +This directive sets the filename for a synchronization lockfile which +mod_rewrite needs to communicate with RewriteMap +programs. Set this lockfile to a local path (not on a NFS-mounted +device) when you want to use a rewriting map-program. It is not required for +SAMP using all other types of rewriting maps. + +

    +


    +

    + +

    RewriteMap

    +Syntax: RewriteMap MapName MapType:MapSource
    +Default: not used per default
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2 (partially), Apache 1.3
    + +

    +The RewriteMap directive defines a Rewriting Map +which can be used inside rule substitution strings by the mapping-functions +to insert/substitute fields through a key lookup. The source of this +lookup can be of various types. +

    + +The MapName is the name of the map and will +be used to specify a mapping-function for the substitution strings of a +rewriting rule via one of the following constructs: + +

    +${ MapName : LookupKey +}
    +${ MapName : LookupKey +| DefaultValue } +
    + +When such a construct occurs the map MapName +is consulted and the key LookupKey is looked-up. If the key is +found, the map-function construct is substituted by SubstValue. If +the key is not found then it is substituted by DefaultValue or +the empty string if no DefaultValue was specified. + +

    +The following combinations for MapType and MapSource +can be used: + +

      +
    • Standard Plain Text
      + MapType: txt, MapSource: Unix filesystem path to valid regular file +

      + This is the standard rewriting map feature where the MapSource is + a plain ASCII file containing either blank lines, comment lines (starting + with a '#' character) or pairs like the following - one per line. + +

      + MatchingKey SubstValue +
      + +

      + Example: +

      + + +
      +##
      +##  map.txt -- rewriting map
      +##
      +
      +Ralf.S.Engelschall    rse   # Bastard Operator From Hell
      +Mr.Joe.Average        joe   # Mr. Average
      +
      + +

      + + +
      +RewriteMap real-to-host txt:/path/to/file/map.txt
      +
      + +

      +

    • Randomized Plain Text
      + MapType: rnd, MapSource: Unix filesystem path to valid regular file +

      + This is identical to the Standard Plain Text variant above but with a special + post-processing feature: After looking up a value it is parsed according + to contained ``|'' characters which have the meaning of ``or''. Or + in other words: they indicate a set of alternatives from which the actual + returned value is chosen randomly. Although this sounds crazy and useless, it + was actually designed for load balancing in a reverse proxy situation where + the looked up values are server names. + Example: +

      + + +
      +##
      +##  map.txt -- rewriting map
      +##
      +
      +static   www1|www2|www3|www4
      +dynamic  www5|www6
      +
      + +

      + + +
      +RewriteMap servers rnd:/path/to/file/map.txt
      +
      + +

      +

    • Hash File
      + MapType: dbm, MapSource: Unix filesystem path to valid regular file +

      + Here the source is a binary NDBM format file containing the same contents + as a Plain Text format file, but in a special representation + which is optimized for really fast lookups. You can create such a file with + any NDBM tool or with the following Perl script: +

      + + +
      +#!/path/to/bin/perl
      +##
      +##  txt2dbm -- convert txt map to dbm format
      +##
      +
      +($txtmap, $dbmmap) = @ARGV;
      +open(TXT, "<$txtmap");
      +dbmopen(%DB, $dbmmap, 0644);
      +while (<TXT>) {
      +    next if (m|^s*#.*| or m|^s*$|);
      +    $DB{$1} = $2 if (m|^\s*(\S+)\s+(\S+)$|);
      +}
      +dbmclose(%DB);
      +close(TXT)
      +

      + + +
      $ txt2dbm map.txt map.db 
      +

      +

    • Internal Function
      + MapType: int, MapSource: Internal Apache function +

      + Here the source is an internal Apache function. Currently you cannot + create your own, but the following functions already exists: +

        +
      • toupper:
        + Converts the looked up key to all upper case. +
      • tolower:
        + Converts the looked up key to all lower case. +
      +

      +

    • External Rewriting Program
      + MapType: prg, MapSource: Unix filesystem path to valid regular file +

      + Here the source is a Unix program, not a map file. To create it you can use + the language of your choice, but the result has to be a run-able Unix + executable (i.e. either object-code or a script with the + magic cookie trick '#!/path/to/interpreter' as the first line). +

      + This program gets started once at startup of the Apache servers and then + communicates with the rewriting engine over its stdin and + stdout file-handles. For each map-function lookup it will + receive the key to lookup as a newline-terminated string on + stdin. It then has to give back the looked-up value as a + newline-terminated string on stdout or the four-character string + ``NULL'' if it fails (i.e. there is no corresponding value + for the given key). A trivial program which will implement a 1:1 map + (i.e. key == value) could be: +

      + + +
      +#!/usr/bin/perl
      +$| = 1;
      +while (<STDIN>) {
      +    # ...here any transformations
      +    # or lookups should occur...
      +    print $_;
      +}
      +
      +

      + But be very careful:
      +

        +
      1. ``Keep the program simple, stupid'' (KISS), because + if this program hangs it will lead to a hang of the Apache server + when the rule occurs. +
      2. Avoid one common mistake: never do buffered I/O on stdout! + This will cause a deadloop! Hence the ``$|=1'' in the above + example... +
      3. Use the RewriteLock directive to define a lockfile + mod_rewrite can use to synchronize the communication to the program. + Per default no such synchronization takes place. +
      +
    + +The RewriteMap directive can occur more than once. For each +mapping-function use one RewriteMap directive to declare its +rewriting mapfile. While you cannot declare a map in per-directory +context it is of course possible to use this map in per-directory +context. + +

    + + +
    +Notice: For plain text and DBM format files the looked-up keys are cached in-core +until the mtime of the mapfile changes or the server does a +restart. This way you can have map-functions in rules which are used +for every request. This is no problem, because the external lookup +only happens once! +
    + +

    +


    +

    + +

    RewriteBase

    +Syntax: RewriteBase BaseURL
    +Default: default is the physical directory path
    +Context: directory, .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteBase directive explicitly sets the base URL for +per-directory rewrites. As you will see below, RewriteRule can be +used in per-directory config files (.htaccess). There it will act +locally, i.e. the local directory prefix is stripped at this stage of +processing and your rewriting rules act only on the remainder. At the end +it is automatically added. + +

    +When a substitution occurs for a new URL, this module has to re-inject the URL +into the server processing. To be able to do this it needs to know what the +corresponding URL-prefix or URL-base is. By default this prefix is the +corresponding filepath itself. But at most websites URLs are +NOT directly related to physical filename paths, so this +assumption will be usually be wrong! There you have to use the +RewriteBase directive to specify the correct URL-prefix. + +

    + + +
    +Notice: If your webserver's URLs are not directly +related to physical file paths, you have to use RewriteBase in every +.htaccess files where you want to use RewriteRule +directives. +
    + +

    +Example: + +

    + Assume the following per-directory config file: + +

    + + +
    +#
    +#  /abc/def/.htaccess -- per-dir config file for directory /abc/def
    +#  Remember: /abc/def is the physical path of /xyz, i.e. the server
    +#            has a 'Alias /xyz /abc/def' directive e.g.
    +#
    +
    +RewriteEngine On
    +
    +#  let the server know that we are reached via /xyz and not
    +#  via the physical path prefix /abc/def
    +RewriteBase   /xyz
    +
    +#  now the rewriting rules
    +RewriteRule   ^oldstuff\.html$  newstuff.html
    +
    + +

    +In the above example, a request to /xyz/oldstuff.html gets correctly +rewritten to the physical file /abc/def/newstuff.html. + +

    + + +
    + +Notice - For the Apache hackers:
    +The following list gives detailed information about the internal +processing steps: + +

    +

    +Request:
    +  /xyz/oldstuff.html
    +
    +Internal Processing:
    +  /xyz/oldstuff.html     -> /abc/def/oldstuff.html    (per-server Alias)
    +  /abc/def/oldstuff.html -> /abc/def/newstuff.html    (per-dir    RewriteRule)
    +  /abc/def/newstuff.html -> /xyz/newstuff.html        (per-dir    RewriteBase)
    +  /xyz/newstuff.html     -> /abc/def/newstuff.html    (per-server Alias)
    +
    +Result:
    +  /abc/def/newstuff.html
    +
    + +This seems very complicated but is the correct Apache internal processing, +because the per-directory rewriting comes too late in the process. So, +when it occurs the (rewritten) request has to be re-injected into the Apache +kernel! BUT: While this seems like a serious overhead, it really isn't, because +this re-injection happens fully internal to the Apache server and the same +procedure is used by many other operations inside Apache. So, you can be +sure the design and implementation is correct. +
    +
    + +

    + + +

    +


    +

    + +

    RewriteCond

    +Syntax: RewriteCond TestString CondPattern
    +Default: None
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2 (partially), Apache 1.3
    + +

    +The RewriteCond directive defines a rule condition. Precede a +RewriteRule directive with one or more RewriteCond +directives. + +The following rewriting rule is only used if its pattern matches the current +state of the URI and if these additional conditions apply, too. + +

    +TestString is a string which can contains the following +expanded constructs in addition to plain text: + +

      +
    • RewriteRule backreferences: These are backreferences of the form + +
      +$N +
      + +(1 <= N <= 9) which provide access to the grouped parts (parenthesis!) +of the +pattern from the corresponding RewriteRule directive (the one +following the current bunch of RewriteCond directives). + +

      +

    • RewriteCond backreferences: These are backreferences of +the form + +
      +%N +
      + +(1 <= N <= 9) which provide access to the grouped parts (parenthesis!) of the +pattern from the last matched RewriteCond directive in the current +bunch of conditions. + +

      +

    • Server-Variables: These are variables + of the form + +
      +%{ NAME_OF_VARIABLE } +
      + +where NAME_OF_VARIABLE can be a string +of the following list: + +

      + + + + + + + + + + + + + + + +
      +HTTP headers:

      + +HTTP_USER_AGENT
      +HTTP_REFERER
      +HTTP_COOKIE
      +HTTP_FORWARDED
      +HTTP_HOST
      +HTTP_PROXY_CONNECTION
      +HTTP_ACCEPT
      +
      +

      +connection & request:

      + +REMOTE_ADDR
      +REMOTE_HOST
      +REMOTE_USER
      +REMOTE_IDENT
      +REQUEST_METHOD
      +SCRIPT_FILENAME
      +PATH_INFO
      +QUERY_STRING
      +AUTH_TYPE
      +
      +

      +server internals:

      + +DOCUMENT_ROOT
      +SERVER_ADMIN
      +SERVER_NAME
      +SERVER_PORT
      +SERVER_PROTOCOL
      +SERVER_SOFTWARE
      +SERVER_VERSION
      +
      +

      +system stuff:

      + +TIME_YEAR
      +TIME_MON
      +TIME_DAY
      +TIME_HOUR
      +TIME_MIN
      +TIME_SEC
      +TIME_WDAY
      +TIME
      +
      +

      +specials:

      + +API_VERSION
      +THE_REQUEST
      +REQUEST_URI
      +REQUEST_FILENAME
      +IS_SUBREQ
      +
      +

      + +

      + + +
      +Notice: These variables all correspond to the similar named +HTTP MIME-headers, C variables of the Apache server or struct tm +fields of the Unix system. +
      + +

    + +

    +Special Notes: + +

      +
    1. The variables SCRIPT_FILENAME and REQUEST_FILENAME contain the same +value, i.e. the value of the filename field of the internal +request_rec structure of the Apache server. The first name is just the +commonly known CGI variable name while the second is the consistent +counterpart to REQUEST_URI (which contains the value of the uri +field of request_rec). + +

      +

    2. There is the special format: %{ENV:variable} where +variable can be any environment variable. This is looked-up via +internal Apache structures and (if not found there) via getenv() from +the Apache server process. + +

      +

    3. There is the special format: %{HTTP:header} where +header can be any HTTP MIME-header name. This is looked-up +from the HTTP request. Example: %{HTTP:Proxy-Connection} +is the value of the HTTP header ``Proxy-Connection:''. + +

      +

    4. There is the special format %{LA-U:variable} for look-aheads +which perform an internal (URL-based) sub-request to determine the final value +of variable. Use this when you want to use a variable for rewriting +which actually is set later in an API phase and thus is not available at the +current stage. For instance when you want to rewrite according to the +REMOTE_USER variable from within the per-server context +(httpd.conf file) you have to use %{LA-U:REMOTE_USER} +because this variable is set by the authorization phases which come +after the URL translation phase where mod_rewrite operates. On the +other hand, because mod_rewrite implements its per-directory context +(.htaccess file) via the Fixup phase of the API and because the +authorization phases come before this phase, you just can use +%{REMOTE_USER} there. + +

      +

    5. There is the special format: %{LA-F:variable} which perform an +internal (filename-based) sub-request to determine the final value of +variable. This is the most of the time the same as LA-U above. +
    + +

    +CondPattern is the condition pattern, i.e. a regular expression +which gets applied to the current instance of the TestString, i.e. +TestString gets evaluated and then matched against +CondPattern. + +

    +Remember: CondPattern is a standard +Extended Regular Expression with some additions: + +

      +
    1. You can precede the pattern string with a '!' character +(exclamation mark) to specify a non-matching pattern. + +

      +

    2. +There are some special variants of CondPatterns. Instead of real +regular expression strings you can also use one of the following: +

      +

        +
      • '<CondPattern' (is lexicographically lower)
        +Treats the CondPattern as a plain string and compares it +lexicographically to TestString and results in a true expression if +TestString is lexicographically lower than CondPattern. +

        +

      • '>CondPattern' (is lexicographically greater)
        +Treats the CondPattern as a plain string and compares it +lexicographically to TestString and results in a true expression if +TestString is lexicographically greater than CondPattern. +

        +

      • '=CondPattern' (is lexicographically equal)
        +Treats the CondPattern as a plain string and compares it +lexicographically to TestString and results in a true expression if +TestString is lexicographically equal to CondPattern, i.e the +two strings are exactly equal (character by character). +If CondPattern is just "" (two quotation marks) this +compares TestString against the empty string. +

        +

      • '-d' (is directory)
        +Treats the TestString as a pathname and +tests if it exists and is a directory. +

        +

      • '-f' (is regular file)
        +Treats the TestString as a pathname and +tests if it exists and is a regular file. +

        +

      • '-s' (is regular file with size)
        +Treats the TestString as a pathname and +tests if it exists and is a regular file with size greater than zero. +

        +

      • '-l' (is symbolic link)
        +Treats the TestString as a pathname and +tests if it exists and is a symbolic link. +

        +

      • '-F' (is existing file via subrequest)
        +Checks if TestString is a valid file and accessible via all the +server's currently-configured access controls for that path. This uses an +internal subrequest to determine the check, so use it with care because it +decreases your servers performance! +

        +

      • '-U' (is existing URL via subrequest)
        +Checks if TestString is a valid URL and accessible via all the server's +currently-configured access controls for that path. This uses an internal +subrequest to determine the check, so use it with care because it decreases +your servers performance! +
      +

      + + +
      +Notice: +All of these tests can also be prefixed by a not ('!') character +to negate their meaning. +
      +

    + +

    +Additionally you can set special flags for CondPattern by appending + +

    +[flags] +
    + +as the third argument to the RewriteCond directive. Flags +is a comma-separated list of the following flags: + +
      +
    • 'nocase|NC' (no case)
      + This makes the condition test case-insensitive, i.e. there is + no difference between 'A-Z' and 'a-z' both in the expanded + TestString and the CondPattern. +

      +

    • 'ornext|OR' (or next condition)
      + Use this to combine rule conditions with a local OR instead of the + implicit AND. Typical example: +

      +

      +RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]
      +RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]
      +RewriteCond %{REMOTE_HOST}  ^host3.*
      +RewriteRule ...some special stuff for any of these hosts...
      +
      + Without this flag you had to write down the cond/rule three times. +
    + +

    +Example: +

    + +To rewrite the Homepage of a site according to the ``User-Agent:'' +header of the request, you can use the following: + +
    +RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
    +RewriteRule  ^/$                 /homepage.max.html  [L]
    +
    +RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
    +RewriteRule  ^/$                 /homepage.min.html  [L]
    +
    +RewriteRule  ^/$                 /homepage.std.html  [L]
    +
    + +Interpretation: If you use Netscape Navigator as your browser (which identifies +itself as 'Mozilla'), then you get the max homepage, which includes +Frames, etc. If you use the Lynx browser (which is Terminal-based), then you +get the min homepage, which contains no images, no tables, etc. If you +use any other browser you get the standard homepage. +
    + +

    +


    +

    + +

    RewriteRule

    +Syntax: RewriteRule Pattern Substitution
    +Default: None
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2 (partially), Apache 1.3
    + +

    +The RewriteRule directive is the real rewriting workhorse. The +directive can occur more than once. Each directive then defines one single +rewriting rule. The definition order of these rules is +important, because this order is used when applying the rules at +run-time. + +

    +Pattern can be (for Apache 1.1.x a System +V8 and for Apache 1.2.x a POSIX) regular expression +which gets applied to the current URL. Here ``current'' means the value of the +URL when this rule gets applied. This may not be the original requested +URL, because there could be any number of rules before which already matched +and made alterations to it. + +

    +Some hints about the syntax of regular expressions: + +

    + + + + +
    +
    +Text:
    +  .           Any single character
    +  [chars]     Character class: One  of chars
    +  [^chars]    Character class: None of chars
    +  text1|text2 Alternative: text1 or text2
    +
    +Quantifiers:
    +  ?           0 or 1 of the preceding text
    +  *           0 or N of the preceding text (N > 1)
    +  +           1 or N of the preceding text (N > 1)
    +
    +Grouping:
    +  (text)      Grouping of text
    +              (either to set the borders of an alternative or
    +              for making backreferences where the Nth group can 
    +              be used on the RHS of a RewriteRule with $N)
    +
    +Anchors:
    +  ^           Start of line anchor
    +  $           End   of line anchor
    +
    +Escaping:
    +  \char       escape that particular char
    +              (for instance to specify the chars ".[]()" etc.)
    +
    +
    + +

    +For more information about regular expressions either have a look at your +local regex(3) manpage or its src/regex/regex.3 copy in the +Apache 1.3 distribution. When you are interested in more detailed and deeper +information about regular expressions and its variants (POSIX regex, Perl +regex, etc.) have a look at the following dedicated book on this topic: + +

    +Mastering Regular Expressions
    +Jeffrey E.F. Friedl
    +Nutshell Handbook Series
    +O'Reilly & Associates, Inc. 1997
    +ISBN 1-56592-257-3
    +
    + +

    +Additionally in mod_rewrite the NOT character ('!') is a possible +pattern prefix. This gives you the ability to negate a pattern; to say, for +instance: ``if the current URL does NOT match to this +pattern''. This can be used for special cases where it is better to match +the negative pattern or as a last default rule. + +

    + + +
    +Notice: When using the NOT character to negate a pattern you cannot +have grouped wildcard parts in the pattern. This is impossible because when +the pattern does NOT match, there are no contents for the groups. In +consequence, if negated patterns are used, you cannot use $N in the +substitution string! +
    + +

    +Substitution of a rewriting rule is the string +which is substituted for (or replaces) the original URL for which +Pattern matched. Beside plain text you can use + +

      +
    1. back-references $N to the RewriteRule pattern +
    2. back-references %N to the last matched RewriteCond pattern +
    3. server-variables as in rule condition test-strings (%{VARNAME}) +
    4. mapping-function calls (${mapname:key|default}) +
    + +Back-references are $N (N=1..9) identifiers which +will be replaced by the contents of the Nth group of the matched +Pattern. The server-variables are the same as for the +TestString of a RewriteCond directive. The +mapping-functions come from the RewriteMap directive and are +explained there. These three types of variables are expanded in the order of +the above list. + +

    +As already mentioned above, all the rewriting rules are applied to the +Substitution (in the order of definition in the config file). The +URL is completely replaced by the Substitution and the +rewriting process goes on until there are no more rules (unless explicitly +terminated by a L flag - see below). + +

    +There is a special substitution string named '-' which means: +NO substitution! Sounds silly? No, it is useful to provide rewriting +rules which only match some URLs but do no substitution, e.g. in +conjunction with the C (chain) flag to be able to have more than one +pattern to be applied before a substitution occurs. + +

    +One more note: You can even create URLs in the substitution string containing +a query string part. Just use a question mark inside the substitution string +to indicate that the following stuff should be re-injected into the +QUERY_STRING. When you want to erase an existing query string, end the +substitution string with just the question mark. + +

    + + +
    +Notice: There is a special feature. When you prefix a substitution +field with http://thishost[:thisport] then +mod_rewrite automatically strips it out. This auto-reduction on +implicit external redirect URLs is a useful and important feature when +used in combination with a mapping-function which generates the hostname +part. Have a look at the first example in the example section below to +understand this. +
    + +

    + + +
    +Remember: An unconditional external redirect to your own server will +not work with the prefix http://thishost because of this feature. +To achieve such a self-redirect, you have to use the R-flag (see +below). +
    + +

    +Additionally you can set special flags for Substitution by appending + +

    +[flags] +
    + +as the third argument to the RewriteRule directive. Flags is a +comma-separated list of the following flags: + +
      +
    • 'redirect|R [=code]' (force redirect)
      + Prefix Substitution + with http://thishost[:thisport]/ (which makes the new URL a URI) to + force a external redirection. If no code is given a HTTP response + of 302 (MOVED TEMPORARILY) is used. If you want to use other response + codes in the range 300-400 just specify them as a number or use + one of the following symbolic names: temp (default), permanent, + seeother. + Use it for rules which should + canonicalize the URL and gives it back to the client, e.g. translate + ``/~'' into ``/u/'' or always append a slash to + /u/user, etc.
      +

      + Notice: When you use this flag, make sure that the + substitution field is a valid URL! If not, you are redirecting to an + invalid location! And remember that this flag itself only prefixes the + URL with http://thishost[:thisport]/, but rewriting goes on. + Usually you also want to stop and do the redirection immediately. To stop + the rewriting you also have to provide the 'L' flag. +

      +

    • 'forbidden|F' (force URL to be forbidden)
      + This forces the current URL to be forbidden, i.e. it immediately sends + back a HTTP response of 403 (FORBIDDEN). Use this flag in conjunction with + appropriate RewriteConds to conditionally block some URLs. +

      +

    • 'gone|G' (force URL to be gone)
      + This forces the current URL to be gone, i.e. it immediately sends back a + HTTP response of 410 (GONE). Use this flag to mark no longer existing + pages as gone. +

      +

    • 'proxy|P' (force proxy)
      + This flag forces the substitution part to be internally forced as a proxy + request and immediately (i.e. rewriting rule processing stops here) put + through the proxy module. You have to make sure that the substitution + string is a valid URI (e.g. typically http://) which can + be handled by the Apache proxy module. If not you get an error from + the proxy module. Use this flag to achieve a more powerful implementation + of the mod_proxy directive ProxyPass, to map + some remote stuff into the namespace of the local server. +

      + Notice: You really have to put ProxyRequests On into your + server configuration to prevent proxy requests from leading to core-dumps + inside the Apache kernel. If you have not compiled in the proxy module, + then there is no core-dump problem, because mod_rewrite checks for + existence of the proxy module and if lost forbids proxy URLs. +

      +

    • 'last|L' (last rule)
      + Stop the rewriting process here and + don't apply any more rewriting rules. This corresponds to the Perl + last command or the break command from the C + language. Use this flag to prevent the currently rewritten URL from being + rewritten further by following rules which may be wrong. For + example, use it to rewrite the root-path URL ('/') to a real + one, e.g. '/e/www/'. +

      +

    • 'next|N' (next round)
      + Re-run the rewriting process (starting again with the first rewriting + rule). Here the URL to match is again not the original URL but the URL + from the last rewriting rule. This corresponds to the Perl + next command or the continue command from the C + language. Use this flag to restart the rewriting process, i.e. to + immediately go to the top of the loop.
      + But be careful not to create a deadloop! +

      +

    • 'chain|C' (chained with next rule)
      + This flag chains the current rule with the next rule (which itself can + also be chained with its following rule, etc.). This has the following + effect: if a rule matches, then processing continues as usual, i.e. the + flag has no effect. If the rule does not match, then all following + chained rules are skipped. For instance, use it to remove the + ``.www'' part inside a per-directory rule set when you let an + external redirect happen (where the ``.www'' part should not to + occur!). +

      +

    • 'type|T=mime-type' (force MIME type)
      + Force the MIME-type of the target file to be mime-type. For + instance, this can be used to simulate the old mod_alias + directive ScriptAlias which internally forces all files inside + the mapped directory to have a MIME type of + ``application/x-httpd-cgi''. +

      +

    • 'nosubreq|NS' (used only if no internal sub-request)
      + This flag forces the rewriting engine to skip a rewriting rule if the + current request is an internal sub-request. For instance, sub-requests + occur internally in Apache when mod_include tries to find out + information about possible directory default files (index.xxx). + On sub-requests it is not always useful and even sometimes causes a failure to + if the complete set of rules are applied. Use this flag to exclude some rules.
      +

      + Use the following rule for your decision: whenever you prefix some URLs + with CGI-scripts to force them to be processed by the CGI-script, the + chance is high that you will run into problems (or even overhead) on sub-requests. + In these cases, use this flag. +

      +

    • 'qsappend|QSA' (query string + append)
      + This flag forces the rewriting engine to append a query + string part in the substitution string to the existing one instead of + replacing it. Use this when you want to add more data to the query string + via a rewrite rule. +

      +

    • 'passthrough|PT' (pass through to next handler)
      + This flag forces the rewriting engine to set the uri field + of the internal request_rec structure to the value + of the filename field. This flag is just a hack to be able + to post-process the output of RewriteRule directives by + Alias, ScriptAlias, Redirect, etc. directives + from other URI-to-filename translators. A trivial example to show the + semantics: + If you want to rewrite /abc to /def via the rewriting + engine of mod_rewrite and then /def to /ghi + with mod_alias: +
      +    RewriteRule ^/abc(.*)  /def$1 [PT]
      +    Alias       /def       /ghi
      +    
      + If you omit the PT flag then mod_rewrite + will do its job fine, i.e. it rewrites uri=/abc/... to + filename=/def/... as a full API-compliant URI-to-filename + translator should do. Then mod_alias comes and tries to do a + URI-to-filename transition which will not work. +

      + Notice: You have to use this flag if you want to intermix directives + of different modules which contain URL-to-filename translators. The + typical example is the use of mod_alias and + mod_rewrite.. +

      + + +
      + + Notice - For the Apache hackers:
      + If the current Apache API had a + filename-to-filename hook additionally to the URI-to-filename hook then + we wouldn't need this flag! But without such a hook this flag is the + only solution. The Apache Group has discussed this problem and will + add such hooks into Apache version 2.0. +
      +
      +

      +

    • 'skip|S=num' (skip next rule(s))
      + This flag forces the rewriting engine to skip the next num rules + in sequence when the current rule matches. Use this to make pseudo + if-then-else constructs: The last rule of the then-clause becomes + a skip=N where N is the number of rules in the else-clause. + (This is not the same as the 'chain|C' flag!) +

      +

    • 'env|E=VAR:VAL' (set environment variable)
      + This forces an environment variable named VAR to be set to the + value VAL, where VAL can contain regexp backreferences + $N and %N which will be expanded. You can use this flag + more than once to set more than one variable. The variables can be later + dereferenced at a lot of situations, but the usual location will be from + within XSSI (via <!--#echo var="VAR"-->) or CGI (e.g. + $ENV{'VAR'}). But additionally you can also dereference it in a + following RewriteCond pattern via %{ENV:VAR}. Use this to strip + but remember information from URLs. +
    + +

    + + +
    +Notice: Never forget that Pattern gets applied to a complete URL +in per-server configuration files. But in per-directory configuration +files, the per-directory prefix (which always is the same for a specific +directory!) gets automatically removed for the pattern matching and +automatically added after the substitution has been done. This feature is +essential for many sorts of rewriting, because without this prefix stripping +you have to match the parent directory which is not always possible. +

    +There is one exception: If a substitution string starts with +``http://'' then the directory prefix will be not added and a +external redirect or proxy throughput (if flag P is used!) is forced! +

    + +

    + + +
    +Notice: To enable the rewriting engine for per-directory configuration files +you need to set ``RewriteEngine On'' in these files and +``Option FollowSymLinks'' enabled. If your administrator has +disabled override of FollowSymLinks for a user's directory, then +you cannot use the rewriting engine. This restriction is needed for +security reasons. +
    + +

    +Here are all possible substitution combinations and their meanings: + +

    +Inside per-server configuration (httpd.conf)
    +for request ``GET /somepath/pathinfo'':

    + +

    + + + + +
    +
    +Given Rule                                      Resulting Substitution
    +----------------------------------------------  ----------------------------------
    +^/somepath(.*) otherpath$1                      not supported, because invalid!
    +
    +^/somepath(.*) otherpath$1  [R]                 not supported, because invalid!
    +
    +^/somepath(.*) otherpath$1  [P]                 not supported, because invalid!
    +----------------------------------------------  ----------------------------------
    +^/somepath(.*) /otherpath$1                     /otherpath/pathinfo
    +
    +^/somepath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^/somepath(.*) /otherpath$1 [P]                 not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^/somepath(.*) http://thishost/otherpath$1      /otherpath/pathinfo
    +
    +^/somepath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^/somepath(.*) http://thishost/otherpath$1 [P]  not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^/somepath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
    +                                                via external redirection
    +                                                (the [R] flag is redundant)
    +
    +^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
    +                                                via internal proxy
    +
    +
    + +

    +Inside per-directory configuration for /somepath
    +(i.e. file .htaccess in dir /physical/path/to/somepath containing +RewriteBase /somepath)
    for +request ``GET /somepath/localpath/pathinfo'':

    + +

    + + + + +
    +
    +Given Rule                                      Resulting Substitution
    +----------------------------------------------  ----------------------------------
    +^localpath(.*) otherpath$1                      /somepath/otherpath/pathinfo
    +
    +^localpath(.*) otherpath$1  [R]                 http://thishost/somepath/otherpath/pathinfo
    +                                                via external redirection
    +
    +^localpath(.*) otherpath$1  [P]                 not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^localpath(.*) /otherpath$1                     /otherpath/pathinfo
    +
    +^localpath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^localpath(.*) /otherpath$1 [P]                 not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^localpath(.*) http://thishost/otherpath$1      /otherpath/pathinfo
    +
    +^localpath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^localpath(.*) http://thishost/otherpath$1 [P]  not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^localpath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
    +                                                via external redirection
    +                                                (the [R] flag is redundant)
    +
    +^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
    +                                                via internal proxy
    +
    +
    + +

    +Example: +

    +

    +We want to rewrite URLs of the form +
    +/ Language +/~ Realname +/.../ File +
    +into +
    +/u/ Username +/.../ File +. Language +
    +

    +We take the rewrite mapfile from above and save it under +/anywhere/map.real-to-user. Then we only have to add the +following lines to the Apache server configuration file: + +

    +
    +RewriteLog   /anywhere/rewrite.log
    +RewriteMap   real-to-user               txt:/anywhere/map.real-to-host
    +RewriteRule  ^/([^/]+)/~([^/]+)/(.*)$   /u/${real-to-user:$2|nobody}/$3.$1
    +
    +
    + +
    + +

    +


    + +
    +

    Miscellaneous

    +
    + +

    +


    + +

    Environment Variables

    + +This module keeps track of two additional (non-standard) CGI/SSI environment +variables named SCRIPT_URL and SCRIPT_URI. These contain +the logical Web-view to the current resource, while the standard CGI/SSI +variables SCRIPT_NAME and SCRIPT_FILENAME contain the +physical System-view. + +

    +Notice: These variables hold the URI/URL as they were initially +requested, i.e. in a state before any rewriting. This is +important because the rewriting process is primarily used to rewrite logical +URLs to physical pathnames. + +

    +Example: + +

    +
    +SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html
    +SCRIPT_FILENAME=/u/rse/.www/index.html
    +SCRIPT_URL=/u/rse/
    +SCRIPT_URI=http://en1.engelschall.com/u/rse/
    +
    +
    + +

    +


    + +

    Practical Solutions

    + +There is a comprehensive collection of practical solutions for URL-based +problems available by the author of mod_rewrite. Here you will find real-life +rulesets and additional information. + +
    +Apache URL Rewriting Guide
    +http://www.engelschall.com/pw/apache/rewriteguide/ +
    + + +
    + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_setenvif.html b/APACHE_1_3b7/htdocs/manual/mod/mod_setenvif.html new file mode 100644 index 0000000000..4d2b26fac7 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_setenvif.html @@ -0,0 +1,371 @@ + + + + Apache module mod_setenvif + + + + +

    Module mod_setenvif

    +

    + This module is contained in the mod_setenvif.c file, and + is compiled in by default. It provides for + the ability to set environment variables based upon attributes of the + request. +

    +

    Summary

    +

    + The mod_setenvif module allows you to set environment + variables according to whether different aspects of the request match + regular expressions you specify. These envariables can be used by + other parts of the server to make decisions about actions to be taken. +

    +

    The directives are considered in the order they appear in the + configuration files. So more complex sequences can be used, such + as this example, which sets netscape if the browser + is mozilla but not MSIE. +

    +  BrowserMatch ^Mozilla netscape
    +  BrowserMatch MSIE !netscape
    +  
    +

    + +

    Directives

    + + +
    +

    The BrowserMatch Directive

    +

    + Syntax: BrowserMatch regex envar[=value] [...] +
    + Default: none +
    + Context: server config +
    + Override: none +
    + Status: Base +
    + Module: mod_setenvif +
    + Compatibility: Apache 1.2 and above +

    +

    + The BrowserMatch directive defines environment variables based on the + User-Agent HTTP request header field. The first argument + should be a POSIX.2 extended regular expression (similar to an + egrep-style regex). The rest of the arguments give the + names of variables to set, and optionally values to which they should + be set. These take the form of +

    +
      +
    1. varname, or +
    2. +
    3. !varname, or +
    4. +
    5. varname=value +
    6. +
    +

    + In the first form, the value will be set to "1". The second + will remove the given variable if already defined, and the third will + set the variable to the value given by value. If a + User-Agent string matches more than one entry, they will + be merged. Entries are processed in the order in which they appear, + and later entries can override earlier ones. +

    +

    + For example: +

    +
    +    BrowserMatch ^Mozilla forms jpeg=yes browser=netscape
    +    BrowserMatch "^Mozilla/[2-3]" tables agif frames javascript
    +    BrowserMatch MSIE !javascript
    +  
    +

    + Note that the regular expression string is + case-sensitive. For cane-INsensitive matching, see + the + BrowserMatchNoCase + directive. +

    +

    + The BrowserMatch and BrowserMatchNoCase + directives are special cases of the + SetEnvIf + and + SetEnvIfNoCase + directives. The following two lines have the same effect: +

    +
    +   BrowserMatchNoCase Robot is_a_robot
    +   SetEnvIfNoCase User-Agent Robot is_a_robot
    +  
    + +
    +

    + + The BrowserMatchNoCase Directive + +

    +

    + Syntax: BrowserMatchNoCase regex envar[=value] + [...] +
    + Default: none +
    + Context: server config +
    + Override: none +
    + Status: Base +
    + Module: mod_setenvif +
    + Compatibility: Apache 1.2 and above +

    +

    + The BrowserMatchNoCase directive is semantically identical to + the + BrowserMatch + directive. However, it provides for case-insensitive matching. For + example: +

    +
    +    BrowserMatchNoCase mac platform=macintosh
    +    BrowserMatchNoCase win platform=windows
    +  
    +

    + The BrowserMatch and BrowserMatchNoCase + directives are special cases of the + SetEnvIf + and + SetEnvIfNoCase + directives. The following two lines have the same effect: +

    +
    +   BrowserMatchNoCase Robot is_a_robot
    +   SetEnvIfNoCase User-Agent Robot is_a_robot
    +  
    + +
    +

    + + The SetEnvIf Directive + +

    +

    + Syntax: SetEnvIf attribute regex envar[=value] + [...] +
    + Default: none +
    + Context: server config +
    + Override: none +
    + Status: Base +
    + Module: mod_setenvif +
    + Compatibility: Apache 1.3 and above +

    +

    + The SetEnvIf directive defines environment variables + based on attributes of the request. These attributes can be the + values of various HTTP request header fields (see + RFC2068 + for more information about these), or of other aspects of the request, + including the following: +

    +
      +
    • Remote_Host - the hostname (if available) of the + client making the request +
    • +
    • Remote_Addr - the IP address of the client making + the request +
    • +
    • Remote_User - the authenticated username (if + available) +
    • +
    • Request_Method - the name of the method being used + (GET, POST, et cetera) +
    • +
    • Request_URI - the portion of the URL following the + scheme and host portion +
    • +
    +

    + Some of the more commonly used request header field names include + Host, User-Agent, and Referer. +

    +

    + Example: +

    +
    +   SetEnvIf Request_URI "\.(gif)|(jpg)|(xbm)$" object_is_image
    +   SetEnvIf Referer www\.mydomain\.com intra_site_referral
    +  
    +

    + The first will set the envariable object_is_image if the + request was for an image file, and the second sets + intra_site_referral if the referring page was somewhere + on the www.mydomain.com Web site. +

    + +
    +

    + + The SetEnvIfNoCase Directive + +

    +

    + Syntax: SetEnvIfNoCase + attribute regex envar[=value] [...] +
    + Default: none +
    + Context: server config +
    + Override: none +
    + Status: Base +
    + Module: mod_setenvif +
    + Compatibility: Apache 1.3 and above +

    +

    + The SetEnvIfNoCase is semantically identical to the + SetEnvIf + directive, and differs only in that the regular expression matching is + performed in a case-insensitive manner. For example: +

    +
    +   SetEnvIfNoCase Host Apache\.Org site=apache
    +  
    +

    + This will cause the site envariable to be set to + "apache" if the HTTP request header field + Host: was included and contained Apache.Org, + apache.org, or any other combination. +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_so.html b/APACHE_1_3b7/htdocs/manual/mod/mod_so.html new file mode 100644 index 0000000000..789e7b1afa --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_so.html @@ -0,0 +1,164 @@ + + + +Apache module mod_so + + + + + +

    Module mod_so

    + +This module is contained in the mod_so.c file. It is +compiled in by default on Windows and is not compiled in by default on +Unix. It provides for loading of executable code and modules into the +server at start-up or restart time. On Unix, the loaded code typically +comes from shared object files (usually with .so +extension), whilst on Windows this module loads DLL +files. This module is only available in Apache 1.3 and up. + +

    + +In previous releases, the functionality of this module was provided +for Unix by mod_dld, and for Windows by mod_dll. On Windows, mod_dll +was used in beta release 1.3b1 through 1.3b5. mod_so combines these +two modules into a single module for all operating systems. + +

    Summary

    + +This is an experimental module. On selected operating systems it can be used +to load modules into Apache at runtime via the Dynamic +Shared Object (DSO) mechanism, rather than requiring a recompilation. + +

    Directives

    + +
    + + +

    LoadFile

    + +Syntax: LoadFile filename filename ...
    +Context: server config
    +Status: Experimental
    +Module: mod_so

    + +The LoadFile directive links in the named object files or libraries +when the server is started or restarted; this is used to load +additional code which may be required for some module to +work. Filename is either and absolute path or relative to ServerRoot.


    + +

    LoadModule

    + +Syntax: LoadModule module filename
    +Context: server config
    +Status: Experimental
    +Module: mod_so

    + +The LoadModule directive links in the object file or library filename +and adds the module structure named module to the list of active +modules. Module is the name of the external variable of type +module in the file. Example (Unix): +

    +LoadModule status_module modules/mod_status.so +
    + +

    + +Example (Windows): +

    +LoadModule status_module modules/ApacheModuleStatus.dll
    +
    + +loads the named module from the modules subdirectory of the +ServerRoot.

    + +


    + +

    Creating DLL Modules for Windows

    + +

    The Apache module API is unchanged between the Unix and Windows + versions. Many modules will run on Windows with no or little change + from Unix, although others rely on aspects of the Unix architecture + which are not present in Windows, and will not work.

    + +

    When a module does work, it can be added to the server in one of two + ways. As with Unix, it can be compiled into the server. Because Apache + for Windows does not have the Configure program of Apache + for Unix, the module's source file must be added to the ApacheCore + project file, and its symbols must be added to the + os\win32\modules.c file.

    + +

    The second way is to compile the module as a DLL, a shared library + that can be loaded into the server at runtime, using the + LoadModule + directive. These module DLLs can be distributed and run on any Apache + for Windows installation, without recompilation of the server.

    + +

    To create a module DLL, a small change is necessary to the module's + source file: The module record must be exported from the DLL (which + will be created later; see below). To do this, add the + MODULE_VAR_EXPORT (defined in the Apache header files) to + your module's module record definition. For example, if your module + has:

    +
    +    module foo_module;
    +
    +

    Replace the above with:

    +
    +    module MODULE_VAR_EXPORT foo_module;
    +
    +

    Note that this will only be activated on Windows, so the module can + continue to be used, unchanged, with Unix if needed. Also, if you are + familiar with .DEF files, you can export the module + record with that method instead.

    + +

    Now, create a DLL containing your module. You will need to link this + against the ApacheCore.lib export library that is created when the + ApacheCore.dll shared library is compiled. You may also have to change + the compiler settings to ensure that the Apache header files are + correctly located.

    + +

    This should create a DLL version of your module. Now simply place it + in the modules directory of your server root, and use + the LoadModule directive to + load it.

    + + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_speling.html b/APACHE_1_3b7/htdocs/manual/mod/mod_speling.html new file mode 100644 index 0000000000..95f926de6d --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_speling.html @@ -0,0 +1,107 @@ + + + + Apache module mod_speling + + + + +

    Module mod_speling

    +

    + This module is contained in the mod_speling.c file, + and is not compiled in by default. + It attempts to correct misspellings of + URLs that users might have entered, by ignoring capitalization + and by allowing up to one misspelling.
    + This catches the majority of misspelled requests. An automatic + "spelling corrected" redirection is returned if only one matching + document was found, and a list of matches is returned if more than + one document with a sufficiently similar name is found. +

    + +

    Summary

    +

    + Requests to documents sometimes cannot be served by the core apache + server because the request was misspelled or miscapitalized. This + module addresses this problem by trying to find a matching document, + even after all other modules gave up. It does its work by comparing + each document name in the requested directory against the requested + document name without regard to case, and allowing + up to one misspelling (character insertion / omission + / transposition or wrong character). A list is built with all document + names which were matched using this strategy. +

    +

    + If, after scanning the directory, +

      +
    • no matching document was found, Apache will proceed as usual + and return a "document not found" error. +
    • only one document is found that "almost" matches the request, + then it is returned in the form of a redirection response. +
    • more than one document with a close match was found, then + the list of the matches is returned to the client, and the client + can select the correct candidate. +
    +

    + +

    Directives

    + + +
  • CheckSpelling +
  • + +
    +

    CheckSpelling

    + + Syntax: CheckSpelling on/off
    + Default: CheckSpelling Off
    + Context: server config, virtual host
    + Status: Base
    + Module: mod_speling
    + Compatibility: CheckSpelling was available as a + separately + available module for Apache 1.1, but was limited to miscapitalizations. + As of Apache 1.3, it is part of the Apache distribution.

    + + This directive enables or disables the spelling module. When enabled, + keep in mind that +

      +
    • the directory scan which is necessary for the spelling + correction will have an impact on the server's performance + when many spelling corrections have to be performed at the same time. +
    • the document trees should not contain sensitive files which could + be matched inadvertently, by a spelling "correction". +
    • the module is unable to correct misspelled user names + (as in http://my.host/~apahce/), just file names or + directory names. +
    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_status.html b/APACHE_1_3b7/htdocs/manual/mod/mod_status.html new file mode 100644 index 0000000000..6b61adfa26 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_status.html @@ -0,0 +1,109 @@ + + + + Apache module mod_status + + + + + +

    Module mod_status

    + +The Status Module is only available in Apache 1.1 and later.

    + +

    Function

    + +The Status module allows a server administrator to find out how well +their server is performing. A HTML page is presented that gives +the current server statistics in an easily readable form. If required +this page can be made to automatically refresh (given a compatible +browser). Another page gives a simple machine-readable list of the current +server state. +

    +The details given are: +

      +
    • The number of children serving requests +
    • The number of idle children +
    • The status of each child, the number of requests that child has +performed and the total number of bytes served by the child (*) +
    • A total number of accesses and byte count served (*) +
    • The time the server was started/restarted and the +time it has been running for +
    • Averages giving the number of requests per second, +the number of bytes served per second and the average number +of bytes per request (*) +
    • The current percentage CPU used by each child and in total by +Apache (*) +
    • The current hosts and requests being processed (*) +
    + +A compile-time option must be used to display the details marked "(*)" as +the instrumentation required for obtaining these statistics does not +exist within standard Apache. + +

    Enabling Status Support

    + +To enable status reports only for browsers from the foo.com +domain add this code to your access.conf configuration file +
    +    <Location /server-status>
    +    SetHandler server-status
    +
    +    order deny,allow
    +    deny from all
    +    allow from .foo.com
    +    </Location>
    +
    +

    +You can now access server statistics by using a Web browser to access the +page http://your.server.name/server-status +

    +Note that mod_status will only work when you are running Apache in +standalone mode and not +inetd mode. + +

    Automatic Updates

    +You can get the status page to update itself automatically if you have +a browser that supports "refresh". Access the page +http://your.server.name/server-status?refresh=N to refresh the +page every N seconds. +

    Machine Readable Status File

    +A machine-readable version of the status file is available by accessing the +page http://your.server.name/server-status?auto. This is useful +when automatically run, see the Perl program in the /support +directory of Apache, log_server_status. + +

    Full Instrumentation

    + +To obtain full statistics you must compile Apache with a special +directive. On some machines there may be a small performance loss +if you do this. Try full statistics and see if you notice any +difference. If you do please contact +mark@ukweb.com and tell me your configuration. + +

    + +Do this by adding the following to the AUX_CFLAGS line in the +"Configuration" file and then recompiling as usual. +

    +        AUX_CFLAGS= (something) -DSTATUS
    +
    + +
    + + It should be noted that if mod_status is compiled into + the server, its handler capability is available in all + configuration files, including per-directory files + (e.g., .htaccess). This may have + security-related ramifications for your site. + +
    + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_unique_id.html b/APACHE_1_3b7/htdocs/manual/mod/mod_unique_id.html new file mode 100644 index 0000000000..6756824c96 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_unique_id.html @@ -0,0 +1,180 @@ + + + +Apache module mod_unique_id + + + + + +

    Module mod_unique_id

    + +This module provides a magic token for each request which is guaranteed +to be unique across "all" requests under very specific conditions. +The unique identifier is even unique across multiple machines in a +properly configured cluster of machines. The environment variable +UNIQUE_ID is set to the identifier for each request. +Unique identifiers are useful for various reasons which are beyond the +scope of this document. + +

    Theory

    + +

    +First a brief recap of how the Apache server works on Unix machines. +This feature currently isn't supported on Windows NT. On Unix machines, +Apache creates several children, the children process requests one at +a time. Each child can serve multiple requests in its lifetime. For the +purpose of this discussion, the children don't share any data +with each other. We'll refer to the children as httpd processes. + +

    +Your website has one or more machines under your administrative control, +together we'll call them a cluster of machines. Each machine can +possibly run multiple instances of Apache. All of these collectively +are considered "the universe", and with certain assumptions we'll +show that in this universe we can generate unique identifiers for each +request, without extensive communication between machines in the cluster. + +

    +The machines in your cluster should satisfy these requirements. +(Even if you have only one machine you should synchronize its clock +with NTP.) + +

      +
    • The machines' times are synchronized via NTP or other network time + protocol. + +
    • The machines' hostnames all differ, such that the module can do a + hostname lookup on the hostname and receive a different IP address + for each machine in the cluster. +
    + +

    +As far as operating system assumptions go, we assume that pids (process +ids) fit in 32-bits. If the operating system uses more than 32-bits +for a pid, the fix is trivial but must be performed in the code. + +

    +Given those assumptions, at a single point in time we can identify +any httpd process on any machine in the cluster from all other httpd +processes. The machine's IP address and the pid of the httpd process +are sufficient to do this. So in order to generate unique identifiers +for requests we need only distinguish between different points in time. + +

    +To distinguish time we will use a Unix timestamp (seconds since January +1, 1970 UTC), and a 16-bit counter. The timestamp has only one second +granularity, so the counter is used to represent up to 65536 values +during a single second. The quadruple ( ip_addr, pid, time_stamp, +counter ) is sufficient to enumerate 65536 requests per second per +httpd process. There are issues however with pid reuse over +time, and the counter is used to alleviate this issue. + +

    +When an httpd child is created, the counter is initialized with ( +current microseconds divided by 10 ) modulo 65536 (this formula was +chosen to eliminate some variance problems with the low order bits of +the microsecond timers on some systems). When a unique identifier is +generated, the time stamp used is the time the request arrived at the +web server. The counter is incremented every time an identifier is +generated (and allowed to roll over). + +

    +The kernel generates a pid for each process as it forks the process, and +pids are allowed to roll over (they're 16-bits on many Unixes, but newer +systems have expanded to 32-bits). So over time the same pid will be +reused. However unless it is reused within the same second, it does not +destroy the uniqueness of our quadruple. That is, we assume the system +does not spawn 65536 processes in a one second interval (it may even be +32768 processes on some Unixes, but even this isn't likely to happen). + +

    +Suppose that time repeats itself for some reason. That is, suppose that +the system's clock is screwed up and it revisits a past time (or it is +too far forward, is reset correctly, and then revisits the future time). +In this case we can easily show that we can get pid and time stamp reuse. +The choice of initializer for the counter is intended to help defeat this. +Note that we really want a random number to initialize the counter, +but there aren't any readily available numbers on most systems (i.e. you +can't use rand() because you need to seed the generator, and can't seed +it with the time because time, at least at one second resolution, has +repeated itself). This is not a perfect defense. + +

    +How good a defense is it? Well suppose that one of your machines serves +at most 500 requests per second (which is a very reasonable upper bound +at this writing, because systems generally do more than just shovel out +static files). To do that it will require a number of children which +depends on how many concurrent clients you have. But we'll be pessimistic +and suppose that a single child is able to serve 500 requests per second. +There are 1000 possible starting counter values such that two sequences +of 500 requests overlap. So there is a 1.5% chance that if time (at one +second resolution) repeats itself this child will repeat a counter value, +and uniqueness will be broken. This was a very pessimistic example, +and with real world values it's even less likely to occur. If your +system is such that it's still likely to occur, then perhaps you should +make the counter 32 bits (by editing the code). + +

    +You may be concerned about the clock being "set back" during summer +daylight savings. However this isn't an issue because the times used here +are UTC, which "always" go forward. Note that x86 based Unixes may need +proper configuration for this to be true -- they should be configured to +assume that the motherboard clock is on UTC and compensate appropriately. +But even still, if you're running NTP then your UTC time will be correct +very shortly after reboot. + +

    +The UNIQUE_ID environment variable is constructed by +encoding the 112-bit (32-bit IP address, 32 bit pid, 32 bit time stamp, +16 bit counter) quadruple using the alphabet [A-Za-z0-9@-] +in a manner similar to MIME base64 encoding, producing 19 characters. +The MIME base64 alphabet is actually [A-Za-z0-9+/] however ++ and / need to be specially encoded in URLs, +which makes them less desirable. All values are encoded in network +byte ordering so that the encoding is comparable across architectures of +different byte ordering. The actual ordering of the encoding is: time +stamp, IP address, pid, counter. This ordering has a purpose, but it +should be emphasized that applications should not dissect the encoding. +Applications should treat the entire encoded UNIQUE_ID as an +opaque token, which can be compared against other UNIQUE_IDs +for equality only. + +

    +The ordering was chosen such that it's possible to change the encoding +in the future without worrying about collision with an existing database +of UNIQUE_IDs. The new encodings should also keep the time +stamp as the first element, and can otherwise use the same alphabet and +bit length. Since the time stamps are essentially an increasing sequence, +it's sufficient to have a flag second in which all machines in the +cluster stop serving and request, and stop using the old encoding format. +Afterwards they can resume requests and begin issuing the new encodings. + +

    +This we believe is a relatively portable solution to this problem. It can +be extended to multithreaded systems like Windows NT, and can grow with +future needs. The identifiers generated have essentially an infinite +life-time because future identifiers can be made longer as required. +Essentially no communication is required between machines in the cluster +(only NTP synchronization is required, which is low overhead), and no +communication between httpd processes is required (the communication is +implicit in the pid value assigned by the kernel). In very specific +situations the identifier can be shortened, but more information needs +to be assumed (for example the 32-bit IP address is overkill for any +site, but there is no portable shorter replacement for it). + +


    + +

    Directives

    + +mod_unique_id has no directives. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_userdir.html b/APACHE_1_3b7/htdocs/manual/mod/mod_userdir.html new file mode 100644 index 0000000000..570b1b042a --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_userdir.html @@ -0,0 +1,123 @@ + + + +Apache module mod_userdir + + + + + +

    Module mod_userdir

    + +This module is contained in the mod_userdir.c file, and +is compiled in by default. It provides for user-specific directories. + + + +
    + + +

    UserDir

    + +Syntax: UserDir directory/filename
    +Default: UserDir public_html
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_userdir
    +Compatibility: All forms except the UserDir +public_html form are only available in Apache 1.1 or above. Use +of the enabled keyword, or disabled with a +list of usernames, is only available in Apache 1.3 and above.

    + +The UserDir directive sets the real directory in a user's home directory +to use when a request for a document for a user is received. +Directory/filename is one of the following: +

    +
      +
    • The name of a directory or a pattern such as those shown below. +
    • +
    • The keyword disabled. This turns off all + username-to-directory translations except those explicitly named with + the enabled keyword (see below). +
    • +
    • The keyword disabled followed by a space-delimited + list of usernames. Usernames that appear in such a list will + never have directory translation performed, even if they + appear in an enabled clause. +
    • +
    • The keyword enabled followed by a space-delimited list + of usernames. These usernames will have directory translation + performed even if a global disable is in effect, but not if they also + appear in a disabled clause. +
    • +
    +

    +If neither the enabled nor the disabled +keywords appear in the Userdir directive, the argument is +treated as a filename pattern, and is used to turn the name into a +directory specification. A request for +http://www.foo.com/~bob/one/two.html will be translated to: +

    +UserDir public_html     -> ~bob/public_html/one/two.html
    +UserDir /usr/web        -> /usr/web/bob/one/two.html
    +UserDir /home/*/www     -> /home/bob/www/one/two.html
    +
    +The following directives will send redirects to the client: +
    +UserDir http://www.foo.com/users -> http://www.foo.com/users/bob/one/two.html
    +UserDir http://www.foo.com/*/usr -> http://www.foo.com/bob/usr/one/two.html
    +UserDir http://www.foo.com/~*/   -> http://www.foo.com/~bob/one/two.html
    +
    +

    +
    + + Be careful when using this directive; for instance, + "UserDir ./" would map + "/~root" to + "/" - which is probably undesirable. If you are + running Apache 1.3 or above, it is strongly recommended that your + configuration include a + "UserDir disabled root" declaration. + See also + the + <Directory> + directive and the + Security Tips + page for more information. + +
    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/mod/mod_usertrack.html b/APACHE_1_3b7/htdocs/manual/mod/mod_usertrack.html new file mode 100644 index 0000000000..024e509ba6 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/mod/mod_usertrack.html @@ -0,0 +1,116 @@ + + + +Apache module mod_usertrack + + + + + +

    Module mod_usertrack

    + +Previous releases of Apache have included a module which generates a +'clickstream' log of user activity on a site using cookies. This was +called the "cookies" module, mod_cookies. In Apache 1.2 and later this +module has been renamed the "user tracking" module, +mod_usertrack. This module has been simplified and new directives +added. + +
    + +

    Logging

    + +Previously, the cookies module (now the user tracking module) did its +own logging, using the CookieLog directive. In this release, +this module does no logging at all. Instead, a configurable log +format file should be used to log user click-streams. This is possible +because the logging module now allows multiple log files. The cookie itself is +logged by using the text %{cookie}n + +in the log file format. For example: +
    +CustomLog logs/clickstream "%{cookie}n %r %t"
    +
    + +For backward compatibility the configurable log module implements the +old CookieLog directive, but this should be upgraded to the +above CustomLog directive. + +

    Directives

    + + + +
    + +

    CookieExpires

    +Syntax: CookieExpires expiry-period
    +Context: server config, virtual host
    +Status: optional
    +Module: mod_usertrack

    + +When used, this directive sets an expiry time on the cookie generated +by the usertrack module. The expiry-period can be given either +as a number of seconds, or in the format such as "2 weeks 3 days 7 +hours". Valid denominations are: years, months, weeks, hours, minutes +and seconds. If the expiry time is in any format other than one +number indicating the number of seconds, it must be enclosed by +double quotes. + +

    If this directive is not used, cookies last only for the current +browser session.

    + +

    CookieTracking

    +Syntax: CookieTracking on | off
    +Context: server config, virtual host, directory, +.htaccess
    +Override: FileInfo
    +Status: optional
    +Module: mod_usertrack

    + +When the user track module is compiled in, and "CookieTracking on" is +set, Apache will start sending a user-tracking cookie for all new +requests. This directive can be used to turn this behavior on or off +on a per-server or per-directory basis. By default, compiling +mod_usertrack will not activate cookies. + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/multilogs.html b/APACHE_1_3b7/htdocs/manual/multilogs.html new file mode 100644 index 0000000000..f5601e1594 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/multilogs.html @@ -0,0 +1,134 @@ + + + +Apache Multiple Log Files + + + + + +

    Multiple Log Files

    + +It is now possible to specify multiple log files, each with a fully +customizable format. This is compatible with existing +configurations. Multiple log files are implemented as part of the mod_log_config module which as of +Apache 1.2 is the default log module. + +
    + +

    Using Multiple Log Files

    + +Multiple log files be created with either the TransferLog +or CustomLog directive. These directives can be +repeated to create more than one log file (in previous releases, +only one logfile could be given per server configuration). +The TransferLog directive creates a log file +in the standard "common log format", although this can be customized +with LogFormat. The syntax of these two +directives is the same as for the config log module in previous +Apache releases. +

    + +The real power of multiple log files come from the ability to +create log files in different formats. For example, as well +as a CLF transfer log, the server could log the user agent of +each client, or the referrer information, or any other aspect of +the request, such as the language preferences of the user. +

    + +The new CustomLog directive takes both a filename to log +to, and a log file format. + +


    + +Syntax: CustomLog filename "format"
    +Context: server config, virtual host
    +Status: base
    +Module: mod_log_config

    + +The first argument is the filename to log to. This is used +exactly like the argument to TransferLog, that is, +it is either a file as a full path or relative to the current +server root, or |programname. Be aware that anyone who can write to +the directory where a log file is written can gain access to the uid +that starts the server. See the +security tips document for details.

    + +The format argument specifies a format for each line of the log file. +The options available for the format are exactly the same as for +the argument of the LogFormat directive. If the format +includes any spaces (which it will do in almost all cases) it +should be enclosed in double quotes. +

    + +

    Use with Virtual Hosts

    + +If a <VirtualHost> section does not contain any +TransferLog or CustomLog directives, the +logs defined for the main server will be used. If it does +contain one or more of these directives, requests serviced by +this virtual host will only be logged in the log files defined +within its definition, not in any of the main server's log files. +See the examples below. +

    + +


    + +

    Examples

    + +To create a normal (CLF) format log file in logs/access_log, and a +log of user agents: + +
    +TransferLog logs/access_log
    +CustomLog   logs/agents     "%{user-agent}i"
    +
    + +To define a CLF transfer log and a referrer log which log +all accesses to both the main server and a virtual host: + +
    +TransferLog logs/access_log
    +CustomLog   logs/referer    "%{referer}i"
    +
    +<VirtualHost>
    +  DocumentRoot   /whatever
    +  ServerName     my.virtual.host
    +</VirtualHost>
    +
    + +Since no TransferLog or CustomLog directives appear inside the +<VirtualHost> section, any requests for this virtual host +will be logged in the main server's log files. If however the +directive + +
    +TransferLog logs/vhost_access_log
    +
    + +was added inside the virtual host definition, then accesses to this +virtual host will be logged in vhost_access_log file (in common +log format), and not in logs/access_log or logs/referer. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/new_features_1_0.html b/APACHE_1_3b7/htdocs/manual/new_features_1_0.html new file mode 100644 index 0000000000..1b2199c115 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/new_features_1_0.html @@ -0,0 +1,131 @@ + + + +Apache extra features + + + + + +

    Overview of new features

    + +

    New Features with Apache 1.0

    + +

    New features with this release, as extensions of the Apache +functionality (see also more detailed CHANGES file) in +the source directory. Because the core code has changed so +significantly, there are certain liberties that earlier versions of +Apache (and the NCSA daemon) took that Apache 1.0 is pickier about - +please check the compatibility notes if +you have any problems. + +

      + +
    • API for server extensions --- see below for a brief sermon on +philosophy, or see src/API.html for an actual +overview. Most server functionality (including includes, CGI, and +most forms of access control) are actually implemented as +API-conformant modules; you can also do other neat stuff (we've +included a sample module, for instance, which one of us is using to +track click-trails using the Netscape +cookie mechanism, for visitors who come in through Netscape +clients). Modules can also be loaded +dynamically using GNU DLD. + +

      +The API is not yet quite stable (see src/TODO for some possible +changes), but anything done now will be easily adapted for future +versions --- after all, we have more modules to adapt than you do. + +

      + +

    • New Process Model - much less forking, no +fixed number of children. + +We found that many people were using values for "MaxServers" either +too high or too low, and were hanging themselves on it. The model we +adopted is still based on long-lived minimal-forking processes, but +instead of specifying one number of persistent processes, the +web-master specifies a maximum and minimum number of processes to be +"spare" - every couple of seconds the parent checks the actual number +of spare servers and adjusts accordingly. This should keep the number +of servers concurrently running relatively low while still ensuring +minimal forking. + +

      + +

    • <VirtualHost> (the configuration +directive for +multiple-homed servers) is more general now. Just about any srm.conf or +httpd.conf command can go in a <Virtualhost> section, with the +following specific exceptions: ServerType, UserId, GroupId, +StartServers, MaxRequestsPerChild, BindAddress, PidFile, TypesConfig, +ServerRoot. + +

      + +

    • Support for content negotiation of +languages through MultiViews +(*.fr, *.de, *.en suffixes), via the new AddLanguage and LanguagePriority +commands (code written by Florent Guillaume, guillaum@clipper.ens.fr). + +

      + +

    • Significant internal cleanups and rearrangements. The two externally + visible consequences of this are that just about all of the unchecked + fixed limits are gone, and that the server is somewhat pickier about + config file syntax (noting and complaining about extraneous command + arguments or other stuff at the end of command lines). + +

      + +

    • XBITHACK is a run-time option, and can be selectively enabled per + directory --- the -DXBITHACK compile-time option just changes the + default. The command which configures it is "XBitHack", which is + allowed everywhere "Options" is; this takes an argument --- + "XBitHack Off" turns it off; "XBitHack On" gets you the NCSA + -DXBITHACK behavior; and "XBitHack Full" gets you the Apache GXBIT + stuff on top of that. (-DXBITHACK makes "Full" the default; + otherwise, it defaults "Off"). + +

      + +

    • TransferLog can specify a program which gets the log entries piped to it, + a la 'TransferLog "| /var/www/my-perl-script -arg valu"' --- this should + give the same SIGTERM/pause/SIGKILL treatment to the logging process on + server restarts that a CGI script gets on an aborted request. NB the + server is counting on the logging process to work, and will probably hang + or worse if it dies. + +

      + +

    • Configurable logging module --- this + is a replacement for the standard plane-jane Common Log Format code, which + supports a LogFormat directive which allows you to control the formatting of + entries in the TransferLog, and add some new items if you like (in + particular, Referer and User-Agent). EXPERIMENTAL. +
    +


    + + +

    Other features of Apache

    + + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/new_features_1_1.html b/APACHE_1_3b7/htdocs/manual/new_features_1_1.html new file mode 100644 index 0000000000..f0084cada2 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/new_features_1_1.html @@ -0,0 +1,228 @@ + + +New features with Apache 1.1 + + + + + +

    Overview of new features

    + +

    API Changes

    + +A few changes to the Apache API were made for 1.1. It is possible +that some third-party modules will no longer work with 1.1, though +we have made every effort to provide backwards-compatibility. If you +encounter a module that does not work with 1.1, please let us know. + + +

    New Features with Apache 1.1

    +

    New features with this release, as extensions of the Apache +functionality (see also more detailed CHANGES file in +the source directory.) Because the core code has changed so +significantly, there are certain liberties that earlier versions of +Apache (and the NCSA daemon) took that recent Apache versions are +pickier about - please check the compatibility notes if you have any +problems.

    +
    + +

    In addition to a number of bug fixes and internal performance +enhancements, Apache +1.1 has the following specific new user features:

    + +
      + +
    • Support for Keep-Alive Persistent +Connections
      Apache now has (optional) support for persistent +connections, as defined by the HTTP/1.1 draft. This protocol, +supported by a number of current HTTP servers and browsers (including +Netscape Navigator 2.0) has been shown to increase speed of document +transfer by up to 50% in certain cases. + +
    • New non-IP Intensive VirtualHost +Support
      +Apache's support for virtual hosts has been enhanced to be able to +use information sent by some new Web browsers to determine the server +being accessed, without requiring an additional IP address for each +host. + +
    • Listen to Multiple Addresses and +Ports
      +Using the new Listen directive, Apache can listen to more +than one port and IP address, using the same configuration set. + +
    • Status +Module
      +Apache now contains a module that gives the web-master accurate, +up-to-date information about the server's status and its resource +consumption. It also gives the current state of each server process +including the current URL being processed. For an example, check out +the status of the +www.apache.org server. + +
    • Server Information Module +This module gives a plethora of information about the other modules +installed, their directives, and their configurations. It is +extremely helpful in debugging configuration problems. For an +example, check out information about the +www.apache.org server. + +
    • Experimental Caching Proxy +Server
      +Apache can now act as +an HTTP proxy server, allowing clients behind firewalls to use the +server to access the outside world. In addition, it can cache +documents it proxies, speeding up access to frequently requested +documents. + +
    • URL-based Access Protection +
      +In addition to access checking and authorization by filename (with +<Directory>), +the new <Location> directive allows protection by +URL. + +
    • Filetype-based Script +"Actions"
      +You can now run CGI scripts whenever a file of a certain type is +requested. This makes it much easier to execute scripts that process +files. In addition, you can use the new Script directive to enable scripts +for files called with HTTP methods Apache does not natively support. + +
    • New "Handler" Directives
      +The new AddHandler and SetHandler directive +allows "handlers" to be defined for filename extensions or +directories. These handlers, which can either be built into Apache or +added with the Action directive, extend +Apache's range of usability, and almost entirely remove the "magic" +media types. + +
    • Customizable CGI Environment +Variables
      +New PassEnv and SetEnv directives allow you to +modify the environment variables passed to CGI scripts. + +
    • CERN Metafile Support +
      +Now emulates the CERN httpd's support for metafiles containing additional +HTTP headers to be supplied with a document. + +
    • Improved Imagemap Support +
      +The internal imagemap handling code has been rewritten and +reorganized, adding new handling of default, base and relative URLs, +and support for creating non-graphical menus for use with clients that +do not support imagemaps. + +
    • Improved UserDir +Directive +
      +Now supports the ability to point user's files (as specified by URLs +beginning with the "~" character) at directories other +than those specified by the Unix password file. + +
    • Minimal DNS Now Runtime Option
      +New HostnameLookups +server configuration directive can be used to turn On or +Off DNS lookups. This supersedes the -DMINIMAL_DNS +compile-time configuration option. This option can be set per-directory. + +
    • IdentityCheck Now Per-Directory Option +
      +The IdentityCheck directive, which controls the use of +ident to check the remote user name, can now be set per directory. The +ident support is also RFC 1413-compliant. + +
    • Redirect Now Usable in .htaccess Files +
      +The Redirect +directive can now be used in .htaccess files when the +FileInfo directive has been set on. This allows users to +redirect parts of their directories without requiring CGI scripts + +
    • ErrorDocument Now Usable in .htaccess Files +
      +The ErrorDocument +directive can now be used in .htaccess files when the +FileInfo directive has been set on. This allows users to +have different error messages for different sections of a site. + +
    • ForceType Directive +
      +This new directive, in <Directory> sections or +.htaccess files, allows you to override the filename extensions and +force a single content type. (e.g. ForceType +application/octet-stream) + +
    • File Owner Available to Included CGI Scripts +
      +Server-side includes that call CGI scripts will now set a +USER_NAME environment variable that contains the owner of +the file which included it. + +
    • Improved Icons +
      +Thanks to Kevin +Hughes, Apache's nifty color GIF icons for directory listings have +been updated. In addition, the Powered by Apache +(apache_pb.gif) logo has been included. + +
    + +
    + +

    New Authentication Modules

    + +

    Note: These modules are not +compiled into the server by default, as they require special support +on the host system. They must be enabled specifically in the +Configuration file.

    + +
      + +
    • Anonymous HTTP Logins +
      +New options allow you to allow, using Basic HTTP Authentication, +anonymous logins, like those of FTP. This allows you to collect email +addresses of people accessing your site. + +
    • Support for Digest +Authentication
      +Apache now supports digest authentication using RSA MD5 +encryption. When used with a supporting web browser, this provides a +more secure alternative to Basic authentication. + +
    • Support for Unix DB +Authentication - mod_auth_db.c
      In +addition to DBM support, Apache now +contains optional support for Berkeley DB databases. + +
    • mSQL Database +Authentication - mod_auth_msql.html
      +Support for the use of mSQL databases for user authentication via HTTP +is now supported. + +
    + +
    + +

    OS/2 Support

    + +

    Apache now includes support for OS/2, thanks to +Softlink Services.

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/new_features_1_2.html b/APACHE_1_3b7/htdocs/manual/new_features_1_2.html new file mode 100644 index 0000000000..3d2c194d3c --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/new_features_1_2.html @@ -0,0 +1,210 @@ + + +New features with Apache 1.2 + + + + + +

    Overview of new features

    + +

    API Changes

    + +

    Some non-compatible changes were made to the Apache API in order to +deal with HTTP/1.1 compatibility. It is possible that some modules +will no longer work (specifically, those that process input using the +POST or PUT methods). If you encounter a module that does not work, +please contact the author. A programmer's note on the subject is +available.

    + +

    Additionally, some changes were made to the CGI environment that +may cause some CGI scripts to work incorrectly. If you are +experiencing trouble with a CGI that worked fine under Apache 1.1.1, +please see our explanation of the changes.

    + +

    New Features with Apache 1.2

    +

    New features with this release, as extensions of the Apache +functionality. Because the core code has changed so +significantly, there are certain liberties that earlier versions of +Apache (and the NCSA daemon) took that recent Apache versions are +pickier about - please check the compatibility notes if you have any +problems.

    +
    + +

    In addition to a number of bug fixes and internal performance +enhancements, Apache +1.2 has the following specific new user features:

    + +
      + + +
    • HTTP/1.1 Compliance +[Documentation to be written]
      +Aside from the optional proxy module (which operates as HTTP/1.0), +Apache is conditionally compliant with the HTTP/1.1 proposed standard, +as approved by the IESG and the +IETF HTTP working group. +HTTP/1.1 provides a much-improved protocol, and +should allow for greater performance and efficiency when transferring +files. Apache does, however, still work great with HTTP/1.0 browsers. +We are very close to being unconditionally compliant; if you note any +deviance from the proposed standard, please report it as a bug. + +
    • eXtended Server Side Includes +(XSSI)
      +A new set of server-side include +directives allows the user to better create WWW pages. This includes +number of powerful new features, such as the ability to set variables +and use conditional HTML. + +
    • File-based and Regex-enabled +Directive Sections
      +The new +<Files> +section allows directives to be enabled based on full filename, not just +directory and URL. In +addition, <Files> sections can appear in +.htaccess files. <Files>, along with +<Directory> + and <Location>, can +also now be based on regular expressions, not just simple prefix +matching. + +
    • Browser-based Environment +Variables
      +Environment variables can now be set based on the +User-Agent string of the browser. Combined with XSSI, this allows you to write browser-based +conditional HTML documents. + +
    • SetUID CGI Execution
      + Apache now + supports the execution of CGI scripts as users other + than the server user. A number of security checks are built in + to try and make this as safe as possible. + +
    • URL Rewriting Module +
      +The optional mod_rewrite module is now included. This +module can provide powerful URL mapping, using regular +expressions. There's nothing this module can't do! + +
    • Enhanced, Configurable +Logging
      +The optional mod_log_config included with earlier +versions of Apache is now standard, and has been enhanced to allow +logging of much more detail about the transaction, and can be used to +open more than one log file at once +(each of which can have a different log format). If you have Apache +write any logs to a directory which is writable by anyone other than +the user that starts the server, see the +security tips document to be sure you aren't putting the security +of your server at risk. + + +
    • User Tracking (Cookies) +Revisions
      +The mod_cookies included with previous versions of Apache +has been renamed mod_usertrack, to more accurately +reflect its function (some people inadvertently thought it enabled +cookie support in Apache, which is not true - Apache supports the use +of cookies directly). It is also now possible to disable the +generation of cookies, even when + the cookie module is compiled in. Also, an expiry time can be set + on the cookies. + +
    • <VirtualHost> +Enhancements
      + The <VirtualHost> directive can now take more than one IP + address or hostname. This lets a single vhost handles requests + for multiple IPs or hostnames. Also the special section + <VirtualHost _default_> can be used to handle requests normally + left for the main server configuration. + +
    • CGI Debugging +Environment
      +ScriptLog allows you to now set up a log that records +all input and output to failed CGI scripts. This includes environment +variables, input headers, POST data, output, and more. This makes CGI +scripts much easier to debug. + +
    • Resource Limits for CGI +Scripts
      +New directives allow the limiting of resources used by CGI scripts +(e.g. max CPU time). This is helpful in preventing 'runaway' CGI +processes. + +
    • Redirect Directive Can Return +Alternate Status
      + The Redirect directive can return permanent or temporary redirects, + "Gone" or "See Other" HTTP status. For NCSA-compatibility, + RedirectTemp and RedirectPermanent are also implemented. + +
    • Simplified Compilation
      + The process of configuring Apache for compilation has been + simplified. + +
    • Add or Remove +Options
      + The Options directive can now add or remove options from + those currently in force, rather than always replacing them. + +
    • Command-line Help
      +The -h command-line option now lists all the available +directives. + +
    • Optional Headers Module to Set or +Remove HTTP Headers
      +The optional mod_headers module can be used to set custom +headers in the HTTP response. It can append to existing headers, +replace them, or remove headers from the response. + +
    • Conditional Config +Directives
      +A new <IfModule> section allows directives to be +enabled only if a given module is loaded into the server. + +
    • NCSA Satisfy authentication +directive now implemented
      +Satisfy allows for more flexible access control +configurations. + +
    • Better NCSA Compatibility
      +Apache directives are now more compatible with NCSA 1.5 to make +moving between servers easier. In particular, Apache now implements the +Satisfy, +MaxKeepAliveRequests, +RedirectPermanent and +RedirectTemp, +directives, and the following directives are now syntax-compatible with +NCSA: +AuthUserFile, +AuthGroupFile, +AuthDigestFile, +KeepAlive and +KeepAliveTimeout. + +
    • Optional proxy module
      +An improved FTP, HTTP, and CONNECT mode SSL proxy is included with +Apache 1.2. Some of the changes visible to users: +
      +
      - Improved FTP proxy supporting PASV mode +
      - ProxyBlock directive for excluding sites to proxy +
      - NoCache * directive for disabling proxy caching +
      - Numerous bug fixes +
      + +
    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/new_features_1_3.html b/APACHE_1_3b7/htdocs/manual/new_features_1_3.html new file mode 100644 index 0000000000..ab6cfe0f30 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/new_features_1_3.html @@ -0,0 +1,583 @@ + + +New features with Apache 1.3 + + + + + +

    Overview of New Features in Apache 1.3

    + +

    New features with this release, as extensions of the Apache +functionality. Because the core code has changed so +significantly, there are certain liberties that earlier versions of +Apache (and the NCSA daemon) took that recent Apache versions are +pickier about - please check the +compatibility notes if you have any +problems.

    + +

    If you're upgrading from Apache 1.2, you may wish to read +the upgrade notes. + +

    Enhancements: Core | +Performance | +Configuration | +Modules | +API | +Misc + +


    + +

    Core Enhancements:

    + +
    +
    Dynamic Shared Object (DSO) support +
    Apache modules may now be loaded at runtime; this means that + modules can be loaded into the server process space only when necessary, + thus overall memory usage by Apache will be significantly reduced. DSO + currently is supported on FreeBSD, OpenBSD, NetBSD, Linux, Solaris, SunOS, + OSF1, IRIX, HP/UX, UnixWare, AIX, ReliantUnix and generic SVR4 platforms. + +
    Support for Windows NT/95 +
    Apache now experimentally supports the Windows NT and Windows 95 + operating systems. + +
    Re-organized + Sources +
    The source files for Apache have been re-organized. The main + difference for Apache users is that the "Module" lines in + Configuration have been replaced with "AddModule" + with a slightly different syntax. For module authors there are + some changes designed to make it easier for users to add their + module. + +
    Reliable Piped Logs +
    On almost all Unix architectures Apache now implements "reliable" + piped logs in mod_log_config. Where reliable + means that if the logging child dies for whatever reason, Apache + will recover and respawn it without having to restart the entire + server. Furthermore if the logging child becomes "stuck" and + isn't reading its pipe frequently enough Apache will also restart + it. This opens up more opportunities for log rotation, hit + filtering, real-time splitting of multiple vhosts into separate + logs, and asynchronous DNS resolving on the fly. + +
    + +


    + +

    Performance Improvements

    + +
      +
    • IP-based virtual hosts are looked up via hash table. +
    • <Directory> parsing speedups. +
    • The critical path for static requests has fewer system calls. + This generally helps all requests. (45 syscalls for a static + request in 1.2 versus 22 in 1.3 in a well tuned + configuration). +
    • + ProxyReceiveBufferSize directive gives + mod_proxy's outgoing connections larger network + buffers, for increased throughput. +
    • The low level I/O routines use writev (where + available) to issue multiple writes with a single system call. + They also avoid copying memory into buffers as much as + possible. The result is less CPU time spent on transferring + large files. +
    • Static requests are served using mmap, which + means bytes are only copied from the disk buffer to the + network buffer directly by the kernel. The program never + copies bytes around, which reduces CPU time. (Only where + available/tested.) +
    • When presented with a load spike, the server quickly adapts by + spawning children at faster rates. +
    • The code which dispatches modules was optimized to avoid + repeatedly skipping over modules that don't implement certain + phases of the API. (This skipping showed up as 5% of the cpu + time on profiles of a server with the default module mix.) +
    • Revamp of the Unix scoreboard management code so that less + time is spent counting children in various states. Previously + a scan was performed for each hit, now it is performed only + once per second. This should be noticeable on servers running + with hundreds of children and high loads. +
    • New serialization choices improve performance on Linux, and + IRIX. +
    • mod_log_config can + be compile-time configured to buffer writes. +
    • Replaced strncpy() with + ap_cpystrn(), a routine which doesn't have to + zero-fill the entire result. This has dramatic effects on + mod_include speed. +
    • Additions to the internal "table" API (used for keeping lists + of key/value string pairs) provide for up to 20% performance + improvement in many situations. +
    + +

    See the new performance +documentation for more information. + +


    + +

    Configuration Enhancements

    + +
    +
    Apache Autoconf-style Interface (APACI) +
    Until Apache 1.3 there was no real out-of-the-box batch-capable + build and installation procedure for the complete Apache + package. This is now provided by a top-level + configure script and a corresponding top-level + Makefile.tmpl file. The goal is to provide a GNU + Autoconf-style frontend which is capable to both drive the old + src/Configure stuff in batch and additionally + installs the package with a GNU-conforming directory layout. Any + options from the old configuration scheme are available plus a lot + of new options for flexibly customizing Apache. + +
    APache eXtenSion (APXS) support tool +
    Now that Apache provides full support for loading modules under + runtime from dynamic shared object (DSO) files, a new support tool + apxs was created which provides off-source building, + installing and activating of those DSO-based modules. It + completely hides the platform-dependent DSO-build commands from + the user and provides an easy way to build modules outside the + Apache source tree. To achieve this APACI installs the Apache C + header files together with the apxs tool. + +
    Default Apache directory + path changed to /usr/local/apache/
    +
    The default directory for the apache ServerRoot changed from the + NCSA-compatible /usr/local/etc/httpd/ to + /usr/local/apache/. This change covers only the + default setting (and the documentation); it is of course possible + to override it using the -d + ServerRoot and -f httpd.conf switches when + starting apache. + +
    Improved HTTP/1.1-style Virtual Hosts +
    The new NameVirtualHost + directive is used to list IP address:port pairs on which + HTTP/1.1-style virtual hosting occurs. This is vhosting based on + the Host: header from the client. Previously this + address was implicitly the same as the "main address" of the + machine, and this caused no end of problems for users, and was not + powerful enough. Please see the Apache Virtual Host documentation for + further details on configuration. + +
    Include directive +
    The Include + directive includes other config files immediately at that point in + parsing. + +
    -S command line option for debugging vhost setup +
    If Apache is invoked with the -S command line option + it will dump out information regarding how it parsed the + VirtualHost sections. This is useful for folks + trying to debug their virtual host configuration. + +
    + +


    + +

    Module Enhancements

    + +
    +
    NEW - Spelling correction + module
    +
    This optional module corrects frequently occurring spelling and + capitalization errors in document names requested from the server. + +
    NEW - Conditional setting of + environment variables
    +
    The addition of + + SetEnvIf and + + SetEnvIfNoCase. These allow you to set + environment variables for server and CGI use based upon attributes + of the request. + +
    NEW - "Magic" +MIME-typing +
    The optional mod_mime_magic has been + added. It uses "magic numbers" and other hints from a file's + contents to figure out what the contents are. It then uses this + information to set the file's media type, if it cannot be + determined by the file's extension. + +
    NEW - Unique Request + Identifiers +
    mod_unique_id can be included + to generate a unique identifier that distinguishes a hit from + every other hit. ("Unique" has some restrictions on it.) The + identifier is available in the environment variable + UNIQUE_ID. + +
    mod_proxy enhancements: +
      +
    • NoProxy and ProxyDomain + directives added to proxy, useful for intranets. +
    • New + ProxyPassReverse directive. It lets Apache adjust the + URL in the Location header on HTTP redirect + responses. +
    • Easier navigation in ftp server directory trees. +
    + +
    Enhanced + mod_include string comparisons
    +
    The string-based server-side include (SSI) flow-control directives + now include comparison for less-than (<), less-than-or-equal + (<=), greater-than (>), and greater-than-or-equal (>=). + Previously comparisons could only be made for equality or + inequality. + +
    ServerRoot relative auth filenames +
    Auth filenames for the various authentication modules are now + treated as relative to the ServerRoot if they are not full paths. + +
    Enhancements to directory + indexing: + +
      +
    • Code split:The mod_dir module has + been split in two, with mod_dir handling directory index + files, and mod_autoindex + creating directory listings. Thus allowing folks to remove the + indexing function from critical servers. + +
    • Sortable: Clicking on a column title will now sort + the listing in order by the values in that column. This feature can + be disabled using the SuppressColumnSorting IndexOptions + keyword. + +
    • + SuppressHTMLPreamble can be used if + your README.html file includes its own HTML header. + +
    • IconHeight and IconWidth let + you set + height and width attributes to the <IMG> tag in + directory listings. + +
    + +
    Less Buffering of CGI Script Output +
    In previous versions of Apache, the output from CGI scripts would + be internally buffered by the server, and wouldn't be forwarded to + the client until either the buffers were full or the CGI script + completed. As of Apache 1.3, the buffer to the client is flushed + any time it contains something and the server is waiting for more + information from the script. This allows CGI script to provide + partial status reports during long processing operations. + + +
    Regular Expression support for + Alias and Redirect +
    New AliasMatch, + ScriptAliasMatch, and + RedirectMatch + directives allow for the use of regular expression matching. + Additionally, new + <DirectoryMatch>, + <LocationMatch>, + and + <FilesMatch> + sections provide a new syntax for regular expression sectioning. + +
    AddModuleInfo + directive added to mod_info +
    Allows additional information to be listed along with a specified + module. + +
    Absence of any TransferLog disables + logging +
    If no TransferLog directive is given then no log is + written. This supports co-existence with other logging modules. + +
    Ability to name logging formats +
    The LogFormat + directive has been enhanced to allow you to give nicknames to + specific logging formats. You can then use these nicknames in + other LogFormat and CustomLog directives, rather than having to + spell out the complete log format string each time. + +
    mod_cern_meta configurable per-directory +
    mod_cern_meta is now + configurable on a per-directory basis. + +
    New map types for + RewriteMap + directive +
    The new map types `Randomized Plain Text' and `Internal Function' + were added to the RewriteMap directive of + mod_rewrite. They provide two new features: First, you now can + randomly choose a sub-value from a value which was looked-up in a + rewriting map (which is useful when choosing between backend + servers in a Reverse Proxy situation). Second, you now can + translate URL parts to fixed (upper or lower) case (which is + useful when doing mass virtual hosting by the help of + mod_rewrite). + +
    CIDR and Netmask access control +
    mod_access directives now + support CIDR (Classless Inter-Domain Routing) style prefixes, and + netmasks for greater control over IP access lists. + +
    +


    + +

    API Additions and Changes

    + +

    For all those module writers and code hackers: + +

    +
    child_init +
    A new phase for Apache's API is called once per "heavy-weight process," + before any requests are handled. This allows the module to set up + anything that need to be done once per processes. For example, + connections to databases. + +
    child_exit +
    A new phase called once per "heavy-weight process," when it is + terminating. Note that it can't be called in some fatal cases (such + as segfaults and kill -9). The child_init and + child_exit functions are passed a pool whose lifetime is + the same as the lifetime of the child (modulo completely fatal + events in which apache has no hope of recovering). In contrast, + the module init function is passed a pool whose lifetime + ends when the parent exits or restarts. + +
    child_terminate +
    Used in the child to indicate the child should exit after finishing + the current request. + +
    register_other_child +
    See http_main.h. This is used in the parent to register + a child for monitoring. The parent will report status to a supplied + callback function. This allows modules to create their own children + which are monitored along with the httpd children. + +
    piped_log +
    See http_log.h. This API provides the common code for + implementing piped logs. In particular it implements a reliable piped + log on architectures supporting it (i.e., Unix at the moment). + +
    scoreboard format changed +
    The scoreboard format is quite different. It is considered a + "private" interface in general, so it's only mentioned here as an FYI. + +
    set_last_modified split into three +
    The old function set_last_modified performed multiple + jobs including the setting of the Last-Modified header, the + ETag header, and processing conditional requests (such as + IMS). These functions have been split into three functions: + set_last_modified, set_etag, and + meets_conditions. The field mtime has been + added to request_rec to facilitate + meets_conditions. + +
    New error logging function: ap_log_error +
    All old logging functions are deprecated, we are in the process of + replacing them with a single function called ap_log_error. + This is still a work in progress. + +
    set_file_slot for config parsing +
    The set_file_slot routine provides a standard routine that + prepends ServerRoot to non-absolute paths. + +
    post_read_request module API +
    This request phase occurs immediately after reading the request (headers), + and immediately after creating an internal redirect. It is most useful + for setting environment variables to affect future phases. + +
    psocket, and popendir +
    The psocket and pclosesocket functions allow + for race-condition free socket creation with resource tracking. + Similarly popendir and pclosedir protect + directory reading. + +
    is_initial_req +
    Test if the request is the initial request (i.e., the one + coming from the client). + +
    kill_only_once +
    An option to spawn_child functions which prevents Apache + from aggressively trying to kill off the child. + +
    alloc debugging code +
    Defining ALLOC_DEBUG provides a rudimentary memory + debugger which can be used on live servers with low impact -- + it sets all allocated and freed memory bytes to 0xa5. Defining + ALLOC_USE_MALLOC will cause the alloc code to use + malloc() and free() for each object. This + is far more expensive and should only be used for testing with tools + such as Electric Fence and Purify. See main/alloc.c + for more details. + +
    ap_cpystrn +
    The new strncpy "lookalike", with slightly different + semantics is much faster than strncpy because it + doesn't have to zero-fill the entire buffer. + +
    table_addn, table_setn, + table_mergen +
    These new functions do not call pstrdup + on their arguments. This provides for big speedups. There is + also some debugging support to ensure code uses them properly. + See src/CHANGES for more information. + +
    construct_url +
    The function prototype for this changed from taking a + server_rec * to taking a request_rec *. + +
    get_server_name, get_server_port +
    These are wrappers which deal with the + UseCanonicalName directive + when retrieving the server name and port for a request. + +
    Change to prototype for ap_spawn_child_err_buff and + ap_call_exec +
    Added a child_info * to spawn function + (as passed to ap_spawn_child_err_buff) and to + ap_call_exec to allow children to work correctly on Win32. +
    + +


    + +

    Miscellaneous Enhancements

    + +
    +
    Port to EBCDIC mainframe machine + running BS2000/OSD +
    As a premiere, this version of Apache comes with a beta version of + a port to a mainframe machine which uses the EBCDIC character set + as its native codeset (It is the SIEMENS NIXDORF family of + mainframes running the BS2000/OSD operating system on a IBM/390 + compatible processor This mainframe OS nowadays features a + SVR4-like POSIX subsystem). + +
    AccessFileName + Enhancement +
    The AccessFileName directive can now take more than + one filename. This lets sites serving pages from network file + systems and more than one Apache web server, configure access + based on the server through which shared pages are being served. + +
    HostNameLookups now defaults to "Off" +
    The HostNameLookups + directive now defaults to "Off". This means that, unless explicitly + turned on, the server will not resolve IP addresses into names. This + was done to spare the Internet from unnecessary DNS traffic. + +
    Double-Reverse DNS enforced +
    The HostnameLookups + directive now supports double-reverse DNS. (Known as + PARANOID in the terminology of tcp_wrappers.) An IP + address passes a double-reverse DNS test if the forward map of the + reverse map includes the original IP. Regardless of the + HostnameLookups setting, mod_access access lists using DNS + names require all names to pass a double-reverse + DNS test. (Prior versions of Apache required a compile-time + switch to enable double-reverse DNS.) + +
    LogLevel and syslog support +
    Apache now has configurable error + logging levels and supports error logging via syslogd(8). + +
    Detaching from stdin/out/err +
    On boot Apache will now detach from stdin, stdout, and stderr. It + does not detach from stderr until it has successfully read the + config files. So you will see errors in the config file. This + should make it easier to start Apache via rsh or crontab. + +
    Year-2000 Improvements +
    The default timefmt string used by mod_include has been + modified to display the year using four digits rather than the + two-digit format used previously. The mod_autoindex + module has also been modified to display years using four digits + in FancyIndexed directory listings. + +
    Common routines Moving to a Separate Library +
    There are a number of functions and routines that have been + developed for the Apache project that supplement or supersede + library routines that differ from one operating system to another. + While most of these are used only by the Apache server itself, + some are referenced by supporting applications (such as + htdigest), and these other applications would fail to + build because the routines were built only into the server. These + routines are now being migrated to a separate subdirectory and + library so they can be used by other applications than just the + server. See the src/ap/ subdirectory. + +
    New + ServerSignature directive +
    This directive optionally adds a line containing the server + version and virtual host name to server-generated pages (error + documents, ftp directory listings, mod_info output etc.). This + makes it easier for users to tell which server produced the error + message, especially in a proxy chain (often found in intranet + environments). + +
    New + UseCanonicalName directive +
    This directive gives control over how Apache creates + self-referential URLs. Previously Apache would always use the ServerName and Port directives to construct a + "canonical" name for the server. With UseCanonicalName + off Apache will use the hostname and port supplied by the + client, if available. + +
    SERVER_VERSION definition abstracted, and server + build date added +
    In earlier versions, the Apache server version was available to + modules through the #defined value for + SERVER_VERSION. In order to keep this value + consistent when modules and the core server are compiled at + different times, this information is now available through the + core API routine ap_get_server_version(). The use of + the SERVER_VERSION symbol is deprecated. Also, + ap_get_server_built() returns a string representing + the time the core server was linked. + +
    Including the operating + system in the server identity
    +
    A new directive, ServerTokens, allows the Webmaster + to change the value of the Server response header + field which is sent back to clients. The + ServerTokens directive controls whether the server + will include a non-specific note in the server identity about the + type of operating system on which the server is running as well as + included module information. As of Apache 1.3, this additional + information is included by default. + +
    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/process-model.html b/APACHE_1_3b7/htdocs/manual/process-model.html new file mode 100644 index 0000000000..74f7d4e6eb --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/process-model.html @@ -0,0 +1,68 @@ + + +Server Pool Management + + + + + +

    Server Pool Management

    + +
    +

    +We found that many people were using values for "MaxServers" either +too high or too low, and were hanging themselves on it. The model we +adopted is still based on long-lived minimal-forking processes, but +instead of specifying one number of persistent processes, the +web-master specifies a maximum and minimum number of processes to be +"spare" - every couple of seconds the parent checks the actual number +of spare servers and adjusts accordingly. This should keep the number +of servers concurrently running relatively low while still ensuring +minimal forking. + +

    + +We renamed the current StartServers to MinSpareServers, created +separate StartServers parameter which means what it says, and renamed +MaxServers to MaxSpareServers (though the old name still works, for +NCSA 1.4 back-compatibility). The old names were generally regarded +as too confusing. + +

    + +The defaults for each variable are: + +

    +MinSpareServers         5
    +MaxSpareServers         10
    +StartServers            5
    +
    + +There is an absolute maximum number of simultaneous children defined +by a compile-time limit which defaults to 256 and a "MaxClients" +directive which specifies the number of simultaneous children that +will be allowed. MaxClients can be adjusted up to the compile-time +limit (HARD_SERVER_LIMIT, defined in httpd.h). If you need more +than 256 simultaneous children, you need to modify both HARD_SERVER_LIMIT +and MaxClients.

    + +In versions before 1.2, HARD_SERVER_LIMIT defaulted to 150.

    + +We do not recommend changing either of these values unless: + +

      +
    1. You know you have the server resources to handle more +
    2. You use the machine for other purposes and must limit the amount of memory +Apache uses +
    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/sections.html b/APACHE_1_3b7/htdocs/manual/sections.html new file mode 100644 index 0000000000..a8e4756d92 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/sections.html @@ -0,0 +1,141 @@ + + +How Directory, Location and Files sections work + + + + + +

    How Directory, Location and Files sections work

    + +The sections <Directory>, <Location> and <Files> can contain +directives which only apply to specified directories, URLs or files +respectively. Also htaccess files can be used inside a directory to +apply directives to that directory. This document explains how these +different sections differ and how they relate to each other when +Apache decides which directives apply for a particular directory or +request URL. + +

    Directives allowed in the sections

    + +Everything that is syntactically allowed in +<Directory> is also allowed in +<Location> (except a sub-<Files> +section, but the code doesn't test for that, Lars has an open bug +report on that). Semantically however some things, and the most +notable is AllowOverride, make no sense in +<Location>. The same for +<Files> -- syntactically everything is fine, but +semantically some things are different. + +

    How the sections are merged

    + +The order of merging is: + +
      + +
    1. + + <Directory> (except regular expressions) and + .htaccess done simultaneously (with .htaccess overriding + <Directory>) + +
    2. + +
    3. + <DirectoryMatch>, and + <Directory> with regular expressions + +
    4. + +
    5. <Files> and <FilesMatch> done + simultaneously +
    6. + +
    7. <Location> and <LocationMatch> done + simultaneously +
    8. + +
    + +Apart from <Directory>, each group is processed in +the order that they appear in the configuration +files. <Directory> (group 1 above) is processed in +the order shortest directory component to longest. If multiple +<Directory> sections apply to the same directory +they they are processed in the configuration file order. The +configuration files are read in the order httpd.conf, srm.conf and +access.conf. Configurations included via the Include +directive will be treated as if they where inside the including file +at the location of the Include directive. + +

    + +Sections inside <VirtualHost> sections are applied +after the corresponding sections outside the virtual host +definition. This allows virtual hosts to override the main server +configuration. (Note: this only works correctly from 1.2.2 and 1.3a2 +onwards. Before those releases sections inside virtual hosts were +applied before the main server). + +

    Notes about using sections

    + +The general guidelines are: + +

    + +

      +
    • + If you are attempting to match objects at the filesystem level + then you must use <Directory> and/or + <Files>. +
    • + +
    • + If you are attempting to match objects at the URL level then you + must use <Location> +
    • +
    + +But a notable exception is: + +
      +
    • + proxy control is done via <Directory>. This is + a legacy mistake because the proxy existed prior to + <Location>. A future version of the config + language should probably switch this to + <Location>. +
    • +
    + +Note also that modifying .htaccess parsing during Location doesn't do +anything because .htaccess parsing has already occurred. + +

    + +Another note: +

    + +

      +
    • + There is actually a + <Location>/<LocationMatch> + sequence performed just before the name translation phase (where + Aliases and DocumentRoots are used to + map URLs to filenames). The results of this sequence are + completely thrown away after the translation has completed. +
    • +
    + + + diff --git a/APACHE_1_3b7/htdocs/manual/sourcereorg.html b/APACHE_1_3b7/htdocs/manual/sourcereorg.html new file mode 100644 index 0000000000..dd96b40c5b --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/sourcereorg.html @@ -0,0 +1,298 @@ + + + +Source Re-organisation + + + + + +

    Source Re-organisation

    + +As of 1.3, the Apache source directories have been re-organised. This +re-organisation is designed to simplify the directory structure, +make it easier to add additional modules, and to give module authors +a way of specifying compile time options or distribute binary +modules. + +

    Summary of Changes

    + +The source changes are: +
      +
    • The non-module source files have moved from src into + src/main +
    • +
    • The module source files previously in src have moved + to src/modules/standard +
    • +
    • The support directory is now in src/support +
    • +
    • The existing symbol names used for global Apache function and variable + identifiers have been renamed in the source. This way namespace conflicts + are avoided when linking Apache with third-party libraries. See the file + src/include/compat.h both for the list of renamed symbol + names and for a way to get source backward compatibility in existing + third-party module sources. +
    • +
    + +In addition, the following enhancements have been made: + +
      +
    • OS abstractions can be added in the src/os directory. + Currently this contains information for unix, OS/2 and Windows 32 + platforms. +
    • +
    • Configuration syntax has been simplified for adding new + modules. Users no longer need to enter the module's structure name. + In addition, new modules can be located anywhere on the + file system, or typically in new or existing directories under + src/modules. +
    • +
    • Module authors can give simpler instructions for adding their modules + to Apache compilation. They can also now provide compile time information + required by Configure, such as additional libraries + required. +
    • +
    • Module authors can distribute pre-compiled (.a or .o) versions of their + modules if required, along with a "module definition file" which + contains the information required by Configure. +
    • +
    • All the sub-directories (main, modules/* and os/*) are built as + libraries. +
    • +
    • The new Apache Autoconf-style Interface (APACI) script named + configure replaced the old top-level Makefile + and src/helpers/InstallApache stuff. +
    • +
    + +

    Adding Modules

    + +Modules are added to Apache by adding a reference to them in +src/Configuration then running Configure and +make. In earlier version of Apache before 1.3, the +line added to Configuration looked like this: + +
    +  Module    status_module    mod_status.o
    +
    + +From 1.3 onwards, the AddModule line should be used +instead, and typically looks like this: + +
    +  AddModule    modules/standard/mod_status.o
    +
    + +The argument to AddModule is the path, relative to src, to +the module file's source or object file. + +

    + +Normally when adding a module you should follow the instructions of +the module author. However if the module comes as a single source +file, say mod_foo.c, then the recommended way to add the module to +Apache is as follows: + +

      +
    • Put mod_foo.c into the directory + src/modules/extra +
    • +
    • Go to the src directory and add the following line + to Configuration
      + AddModule modules/extra/mod_foo.o +
    • +
    • Run ./Configure
    • +
    • Run make
    • +
    + +

    New Facilities for Module Authors

    + +In previous releases of Apache, new modules were added to the +src directory, and if the module required any additional +compilation options (such as libraries) they would have to be added +to Configuration. Also the user would have to be +told the module's structure name to add on the Module line +of Configuration. + +

    + +From Apache 1.3 onwards, module authors can make use of these new features: + +

      +
    • Simplified Configuration command AddModule which only + requires a path to the module source or object file +
    • +
    • If the module requires compile time options (such as extra + libraries) these can be specified in the module file source + or an external "module definition file". +
    • +
    • If a module is distributed as binary (.o or .a) then an external + "module definition file" can also be distributed which gives + the information Configure needs to add the module, such as extra + libraries and the module's structure name. +
    • Modules can be installed anywhere on the file system, although a directory + under src/modules is recommended. +
    • +
    • If the module is in its own directory, Apache can automatically + create a Makefile to build the module given a file containing + the module's dependencies. +
    • +
    • For building a third-party module outside + the Apache source tree the new apxs support tool can be used + to compile the module into a dynamic shared object (DSO), install it into + the existing Apache installation and optionally activating it in the + Apache httpd.conf file. The only requirement is that Apache + has DSO-support for the used platform and the module mod_so + was built into the server binary httpd. +
    • +
    + +The rest of this document shows how to package modules for Apache 1.3 +and later and what to tell end-users of the module. + +

    Building a simple source distribution

    + +Consider a simple add-on module, distributed as a single file. For +example, say it is called mod_demo.c. The archive for this module +should consist of two files, in a suitable directory name. For +example: + +
      +
    • mod_demo/mod_demo.c +
    • mod_demo/Makefile.tmpl +
    + +(Of course end-user instructions, README's, etc can also be supplied +in the archive). The end user should be told to extract this archive +in the src/modules directory of their Apache source +tree. This will create a new directory +src/modules/mod_demo. Then they need to add the following +line to the Configuration file: + +
    +  AddModule  modules/mod_demo/mod_demo.o
    +
    + +then run Configure and make as normal. + +

    + +The mod_demo/Makefile.tmpl should contain the dependencies +of the module source. For example, a simple module which just interfaces to +some standard Apache module API functions might look this this: + +

    +  mod_demo.o: mod_demo.c $(INCDIR)/httpd.h $(INCDIR)/http_protocol.h
    +
    + +When the user runs Configure Apache will create a full +makefile to build this module. If this module also requires +some additional built-time options to be given, such as libraries, +see the next section. +

    + +If the module also comes with header files, these can be added to the +archive. If the module consists of multiple source files it can be +built into a library file using a supplied makefile. In this case, +distribute the makefile as mod_demo/Makefile and do +not include a mod_demo/Makefile.tmpl. If +Configure sees a Makefile.tmpl it assumes it +is safe to overwrite any existing Makefile. + +

    + +See the Apache src/modules/standard for an example of a +module directory where the makefile is created automatically from a +Makefile.tmpl file (note that this directory also shows how to +distribute multiple modules in a single directory). See +src/modules/proxy and src/modules/example +for examples of modules built using custom makefiles (to build a +library and an object file, respectively). + +

    Adding Compile time Information

    + +Apache source files (or module definition files, see below) can +contain information used by Configure to add compile-time +options such as additional libraries. For example, if mod_demo in the +example above also requires that Apache be linked against a DBM +library, then the following text could be inserted into the mod_demo.c +source: + +
    +/*
    + * Module definition information - the part between the -START and -END
    + * lines below is used by Configure. This could be stored in a separate
    + * instead.
    + *
    + * MODULE-DEFINITION-START
    + * Name: demo_module
    + * ConfigStart
    +    LIBS="$LIBS $DBM_LIB"
    +    if [ "X$DBM_LIB" != "X" ]; then
    +        echo " + using $DBM_LIB for mod_demo"
    +    fi
    + * ConfigEnd
    + * MODULE-DEFINITION-END
    + */
    +
    + +Note that this is contained inside a C language comment to hide it +from the compiler. Anything between the lines which contains +MODULE-DEFINITION-START and +MODULE-DEFINITION-END is used by Configure. +The Name: line gives the module's structure name. This is +not really necessary in this case since if not present +Configure will guess at a name based on the filename +(e.g. given "mod_demo" it will remove the leading "mod_" and append +"_module" to get a structure name. This works with all modules +distributed with Apache). + +

    + +The lines between ConfigStart and ConfigEnd +as executed by Configure and can be used to add +compile-time options and libraries. In this case it adds the DBM +library (from $DBM_LIB) to the standard compilation libraries ($LIB) +and displays a message. + +

    + +See the default distribution's mod_auth_dbm.c for an example of +an embedded module definition. + +

    Module Definition Information for Binary Distribitions

    + +If the module is to be distributed as binary (object or library) rather +than source, it is not possible to add the module definition +information to the source file. In this case it can be placed in a +separate file which has the same base name as the object or library +file, but with a .module extension. So, for example, if +the distributed module object file is mod_demo.o, the module +definition file should be called mod_demo.module. It contains the same +information as above, but does not need to be inside a C comment or +delimited with MODULE-DEFINITION-START etc. For example: + +
    +Name: demo_module
    +ConfigStart
    + LIBS="$LIBS $DBM_LIB"
    + if [ "X$DBM_LIB" != "X" ]; then
    +     echo " + using $DBM_LIB for mod_demo"
    + fi
    +ConfigEnd
    +
    + +See the default distribution's mod_auth_db.module for an example of +a separate module definition file. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/stopping.html b/APACHE_1_3b7/htdocs/manual/stopping.html new file mode 100644 index 0000000000..3d03d4df97 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/stopping.html @@ -0,0 +1,174 @@ + + + +Stopping and Restarting Apache + + + + + +

    Stopping and Restarting Apache

    + +

    You will notice many httpd executables running on your system, +but you should not send signals to any of them except the parent, whose +pid is in the PidFile. That is to +say you shouldn't ever need to send signals to any process except the +parent. There are three signals that you can send the parent: +TERM, HUP, and USR1, which will +be described in a moment. + +

    To send a signal to the parent you should issue a command such as: +

    +    kill -TERM `cat /usr/local/apache/logs/httpd.pid`
    +
    + +You can read about its progress by issuing: + +
    +    tail -f /usr/local/apache/logs/error_log
    +
    + +Modify those examples to match your +ServerRoot and +PidFile settings. + +

    As of Apache 1.3 we provide a script src/support/apachectl +which can be used to start, stop, and restart Apache. It may need a +little customization for your system, see the comments at the top of +the script. + +

    TERM Signal: stop now

    + +

    Sending the TERM signal to the parent causes it to +immediately attempt to kill off all of its children. It may take it +several seconds to complete killing off its children. Then the +parent itself exits. Any requests in progress are terminated, and no +further requests are served. + +

    HUP Signal: restart now

    + +

    Sending the HUP signal to the parent causes it to kill off +its children like in TERM but the parent doesn't exit. It +re-reads its configuration files, and re-opens any log files. +Then it spawns a new set of children and continues +serving hits. + +

    Users of the +status module +will notice that the server statistics are +set to zero when a HUP is sent. + +

    Note: If your configuration file has errors in it when +you issue a +restart then your parent will not restart, it will exit with an error. +See below for a method of avoiding this. + +

    USR1 Signal: graceful restart

    + +

    Note: prior to release 1.2b9 this code is quite unstable +and shouldn't be used at all. + +

    The USR1 signal causes the parent process to advise +the children to exit after their current request (or to exit immediately +if they're not serving anything). The parent re-reads its configuration +files and re-opens its log files. As each child dies off the parent +replaces it with a child from the new generation of the +configuration, which begins serving new requests immediately. + +

    This code is designed to always respect the +MaxClients, +MinSpareServers, +and MaxSpareServers settings. +Furthermore, it respects StartServers +in the following manner: if after one second at least StartServers new +children have not been created, then create enough to pick up the slack. +This is to say that the code tries to maintain both the number of children +appropriate for the current load on the server, and respect your wishes +with the StartServers parameter. + +

    Users of the +status module +will notice that the server statistics +are not set to zero when a USR1 is sent. The +code +was written to both minimize the time in which the server is unable to serve +new requests (they will be queued up by the operating system, so they're +not lost in any event) and to respect your tuning parameters. In order +to do this it has to keep the scoreboard used to keep track +of all children across generations. + +

    The status module will also use a G to indicate those +children which are still serving requests started before the graceful +restart was given. + +

    At present there is no way for a log rotation script using +USR1 to know for certain that all children writing the +pre-restart log have finished. We suggest that you use a suitable delay +after sending the USR1 signal before you do anything with the +old log. For example if most of your hits take less than 10 minutes to +complete for users on low bandwidth links then you could wait 15 minutes +before doing anything with the old log. + +

    Note: If your configuration file has errors in it when +you issue a +restart then your parent will not restart, it will exit with an error. +In the case of graceful +restarts it will also leave children running when it exits. (These are +the children which are "gracefully exiting" by handling their last request.) +This will cause problems if you attempt to restart the server -- it will +not be able to bind to its listening ports. At present the only work +around is to check the syntax of your files before doing a restart. The +easiest way is to just run httpd as a non-root user. If there are no +errors it will attempt to open its sockets and logs and fail because it's +not root (or because the currently running httpd already has those ports +bound). If it fails for any other reason then it's probably a config file +error and the error should be fixed before issuing the graceful restart. + +

    Appendix: signals and race conditions

    + +

    Prior to Apache 1.2b9 there were several race conditions +involving the restart and die signals (a simple description of race +condition is: a time-sensitive problem, as in if something happens at just +the wrong time it won't behave as expected). For those architectures that +have the "right" feature set we have eliminated as many as we can. +But it should be noted that there still do exist race conditions on +certain architectures. + +

    Architectures that use an on disk +ScoreBoardFile +have the potential to corrupt their scoreboards. This can result in +the "bind: Address already in use" (after HUP) or +"long lost child came home!" (after USR1). The former is +a fatal error, while the latter just causes the server to lose a scoreboard +slot. So it might be advisable to use graceful restarts, with +an occasional hard restart. These problems are very difficult to work +around, but fortunately most architectures do not require a scoreboard file. +See the ScoreBoardFile documentation for a method to determine if your +architecture uses it. + +

    NEXT and MACHTEN (68k only) have small race +conditions +which can cause a restart/die signal to be lost, but should not cause the +server to do anything otherwise problematic. + + +

    All architectures have a small race condition in each child involving +the second and subsequent requests on a persistent HTTP connection +(KeepAlive). It may exit after reading the request line but before +reading any of the request headers. There is a fix that was discovered +too late to make 1.2. In theory this isn't an issue because the KeepAlive +client has to expect these events because of network latencies and +server timeouts. In practice it doesn't seem to affect anything either +-- in a test case the server was restarted twenty times per second and +clients successfully browsed the site without getting broken images or +empty documents. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/suexec.html b/APACHE_1_3b7/htdocs/manual/suexec.html new file mode 100644 index 0000000000..d005739b63 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/suexec.html @@ -0,0 +1,540 @@ + + + +Apache suEXEC Support + + + + + +

    Apache suEXEC Support

    + +

    +

      +
    1. CONTENTS
    2. +
    3. What is suEXEC?
    4. +
    5. Before we begin.
    6. +
    7. suEXEC Security Model.
    8. +
    9. Configuring & Installing suEXEC
    10. +
    11. Enabling & Disabling suEXEC
    12. +
    13. Debugging suEXEC
    14. +
    15. Beware the Jabberwock: Warnings & + Examples
    16. +
    +

    + +

    What is suEXEC?

    +

    +The suEXEC feature -- introduced in Apache 1.2 -- provides +Apache users the ability to run CGI and SSI +programs under user IDs different from the user ID of the calling web-server. +Normally, when a CGI or SSI program executes, it runs as the same user who is +running the web server. +

    + +

    +Used properly, this feature can reduce considerably the security risks involved +with allowing users to develop and run private CGI or SSI programs. However, +if suEXEC is improperly configured, it can cause any number of problems and +possibly create new holes in your computer's security. If you aren't familiar +with managing setuid root programs and the security issues they present, we +highly recommend that you not consider using suEXEC. +

    + +

    +BACK TO CONTENTS +

    + +

    Before we begin.

    +

    +Before jumping head-first into this document, you should be aware of the +assumptions made on the part of the Apache Group and this document. +

    + +

    +First, it is assumed that you are using a UNIX derivate operating system that +is capable of setuid and setgid operations. +All command examples are given in this regard. Other platforms, if they are +capable of supporting suEXEC, may differ in their configuration. +

    + +

    +Second, it is assumed you are familiar with some basic concepts of your +computer's security and its administration. This involves an understanding +of setuid/setgid operations and the various effects they +may have on your system and its level of security. +

    + +

    +Third, it is assumed that you are using an unmodified +version of suEXEC code. All code for suEXEC has been carefully scrutinized and +tested by the developers as well as numerous beta testers. Every precaution +has been taken to ensure a simple yet solidly safe base of code. Altering this +code can cause unexpected problems and new security risks. It is +highly recommended you not alter the suEXEC code unless you +are well versed in the particulars of security programming and are willing to +share your work with the Apache Group for consideration. +

    + +

    +Fourth, and last, it has been the decision of the Apache Group to +NOT make suEXEC part of the default installation of Apache. +To this end, suEXEC configuration requires of the administrator careful +attention to details. After due consideration has been given to the various +settings for suEXEC, the administrator may install suEXEC through normal +installation methods. The values for these settings need to be carefully +determined and specified by the administrator to properly maintain system +security during the use of suEXEC functionality. It is through this detailed +process that the Apache Group hopes to limit suEXEC installation only to those +who are careful and determined enough to use it. +

    + +

    +Still with us? Yes? Good. Let's move on! +

    + +

    +BACK TO CONTENTS +

    + +

    suEXEC Security Model

    +

    +Before we begin configuring and installing suEXEC, we will first discuss +the security model you are about to implement. By doing so, you may +better understand what exactly is going on inside suEXEC and what precautions +are taken to ensure your system's security. +

    + +

    +suEXEC is based on a setuid "wrapper" program that is +called by the main Apache web server. This wrapper is called when an HTTP +request is made for a CGI or SSI program that the administrator has designated +to run as a userid other than that of the main server. When such a request +is made, Apache provides the suEXEC wrapper with the program's name and the +user and group IDs under which the program is to execute. +

    + +

    +The wrapper then employs the following process to determine success or +failure -- if any one of these conditions fail, the program logs the failure +and exits with an error, otherwise it will continue: +

      +
    1. Was the wrapper called with the proper number of + arguments? +
      + The wrapper will only execute if it is given the proper number of arguments. + The proper argument format is known to the Apache web server. If the + wrapper + is not receiving the proper number of arguments, it is either being hacked, + or + there is something wrong with the suEXEC portion of your Apache binary. +
      +
    2. +
    3. Is the user executing this wrapper a valid user of this + system? +
      + This is to ensure that the user executing the wrapper is truly a user of the + system. +
      +
    4. +
    5. Is this valid user allowed to run the wrapper? +
      + Is this user the user allowed to run this wrapper? Only one user (the + Apache user) is allowed to execute this program. +
      +
    6. +
    7. Does the target program have an unsafe hierarchical + reference? +
      + Does the target program contain a leading '/' or have a '..' backreference? + These are not allowed; the target program must reside within the Apache + webspace. +
      +
    8. +
    9. Is the target user name valid? +
      + Does the target user exist? +
      +
    10. +
    11. Is the target group name valid? +
      + Does the target group exist? +
      +
    12. +
    13. Is the target user NOT superuser? +
      + Presently, suEXEC does not allow 'root' to execute CGI/SSI programs. +
      +
    14. +
    15. Is the target userid ABOVE the minimum ID + number? +
      + The minimum user ID number is specified during configuration. This allows + you + to set the lowest possible userid that will be allowed to execute CGI/SSI + programs. This is useful to block out "system" accounts. +
      +
    16. +
    17. Is the target group NOT the superuser group? +
      + Presently, suEXEC does not allow the 'root' group to execute CGI/SSI + programs. +
      +
    18. +
    19. Is the target groupid ABOVE the minimum ID + number? +
      + The minimum group ID number is specified during configuration. This allows + you + to set the lowest possible groupid that will be allowed to execute CGI/SSI + programs. This is useful to block out "system" groups. +
      +
    20. +
    21. Can the wrapper successfully become the target user and + group? +
      + Here is where the program becomes the target user and group via setuid and + setgid + calls. The group access list is also initialized with all of the groups + of which + the user is a member. +
      +
    22. +
    23. Does the directory in which the program resides exist? +
      + If it doesn't exist, it can't very well contain files. +
      +
    24. +
    25. Is the directory within the Apache webspace? +
      + If the request is for a regular portion of the server, is the requested + directory + within the server's document root? If the request is for a UserDir, is + the requested + directory within the user's document root? +
      +
    26. +
    27. Is the directory NOT writable by anyone else? +
      + We don't want to open up the directory to others; only the owner user + may be able + to alter this directories contents. +
      +
    28. +
    29. Does the target program exist? +
      + If it doesn't exists, it can't very well be executed. +
      +
    30. +
    31. Is the target program NOT writable by anyone + else? +
      + We don't want to give anyone other than the owner the ability to + change the program. +
      +
    32. +
    33. Is the target program NOT setuid or setgid? +
      + We do not want to execute programs that will then change our UID/GID again. +
      +
    34. +
    35. Is the target user/group the same as the program's + user/group? +
      + Is the user the owner of the file? +
      +
    36. +
    37. Can we successfully clean the process environment to + ensure safe operations? +
      + suEXEC cleans the process' environment by establishing a safe + execution PATH (defined + during configuration), as well as only passing through those + variables whose names + are listed in the safe environment list (also created during + configuration). +
      +
    38. +
    39. Can we successfully become the target program and + execute? +
      + Here is where suEXEC ends and the target program begins. +
      +
    40. +
    +

    + +

    +This is the standard operation of the the suEXEC wrapper's security model. +It is somewhat stringent and can impose new limitations and guidelines for +CGI/SSI design, but it was developed carefully step-by-step with security +in mind. +

    + +

    +For more information as to how this security model can limit your possibilities +in regards to server configuration, as well as what security risks can be +avoided with a proper suEXEC setup, see the +"Beware the Jabberwock" +section of this document. +

    + +

    +BACK TO CONTENTS +

    + +

    Configuring & Installing suEXEC

    +

    +Here's where we begin the fun. The configuration and installation of suEXEC is +a four step process: edit the suEXEC header file, compile suEXEC, place the +suEXEC binary in its proper location, and configure Apache for use with suEXEC. +

    + +

    +EDITING THE SUEXEC HEADER FILE
    +- From the top-level of the Apache source tree, type:   +cd support [ENTER] +

    + +

    +Edit the suexec.h file and change the following macros to +match your local Apache installation. +

    + +

    +From support/suexec.h +

    +     /*
    +      * HTTPD_USER -- Define as the username under which Apache normally
    +      *               runs.  This is the only user allowed to execute
    +      *               this program.
    +      */
    +     #define HTTPD_USER "www"
    +
    +     /*
    +      * UID_MIN -- Define this as the lowest UID allowed to be a target user
    +      *            for suEXEC.  For most systems, 500 or 100 is common.
    +      */
    +     #define UID_MIN 100
    +
    +     /*
    +      * GID_MIN -- Define this as the lowest GID allowed to be a target group
    +      *            for suEXEC.  For most systems, 100 is common.
    +      */
    +     #define GID_MIN 100
    +
    +     /*
    +      * USERDIR_SUFFIX -- Define to be the subdirectory under users'
    +      *                   home directories where suEXEC access should
    +      *                   be allowed.  All executables under this directory
    +      *                   will be executable by suEXEC as the user so
    +      *                   they should be "safe" programs.  If you are
    +      *                   using a "simple" UserDir directive (ie. one
    +      *                   without a "*" in it) this should be set to
    +      *                   the same value.  suEXEC will not work properly
    +      *                   in cases where the UserDir directive points to
    +      *                   a location that is not the same as the user's
    +      *                   home directory as referenced in the passwd file.
    +      *
    +      *                   If you have VirtualHosts with a different
    +      *                   UserDir for each, you will need to define them to
    +      *                   all reside in one parent directory; then name that
    +      *                   parent directory here.  IF THIS IS NOT DEFINED
    +      *                   PROPERLY, ~USERDIR CGI REQUESTS WILL NOT WORK!
    +      *                   See the suEXEC documentation for more detailed
    +      *                   information.
    +      */
    +     #define USERDIR_SUFFIX "public_html"
    +
    +     /*
    +      * LOG_EXEC -- Define this as a filename if you want all suEXEC
    +      *             transactions and errors logged for auditing and
    +      *             debugging purposes.
    +      */
    +     #define LOG_EXEC "/usr/local/apache/logs/cgi.log" /* Need me? */
    +
    +     /*
    +      * DOC_ROOT -- Define as the DocumentRoot set for Apache.  This
    +      *             will be the only hierarchy (aside from UserDirs)
    +      *             that can be used for suEXEC behavior.
    +      */
    +     #define DOC_ROOT "/usr/local/apache/htdocs"
    +
    +     /*
    +      * SAFE_PATH -- Define a safe PATH environment to pass to CGI executables.
    +      *
    +      */
    +     #define SAFE_PATH "/usr/local/bin:/usr/bin:/bin"
    +
    +

    + +

    +COMPILING THE SUEXEC WRAPPER
    +You now need to compile the suEXEC wrapper. At the shell command prompt, +type:  cc suexec.c -o suexec [ENTER]. +This should create the suexec wrapper executable. +

    + +

    +COMPILING APACHE FOR USE WITH SUEXEC
    +By default, Apache is compiled to look for the suEXEC wrapper in the following +location. +

    + +

    +From src/httpd.h +

    +     /* The path to the suEXEC wrapper */
    +     #define SUEXEC_BIN "/usr/local/apache/sbin/suexec"
    +
    +

    + +

    +If your installation requires location of the wrapper program in a different +directory, edit src/httpd.h and recompile your Apache server. +See Compiling and Installing Apache for more +info on this process. +

    + +

    +COPYING THE SUEXEC BINARY TO ITS PROPER LOCATION
    +Copy the suexec executable created in the +exercise above to the defined location for SUEXEC_BIN. +

    + +

    +cp suexec /usr/local/apache/sbin/suexec [ENTER] +

    + +

    +In order for the wrapper to set the user ID, it must me installed as owner +root and must have the setuserid execution bit +set for file modes. If you are not running a root +user shell, do so now and execute the following commands. +

    + +

    +chown root /usr/local/apache/sbin/suexec [ENTER] +
    +chmod 4711 /usr/local/apache/sbin/suexec [ENTER] +

    + +

    +BACK TO CONTENTS +

    + +

    Enabling & Disabling suEXEC

    +

    +After properly installing the suexec wrapper +executable, you must kill and restart the Apache server. A simple +kill -1 `cat httpd.pid` will not be enough. +Upon startup of the web-server, if Apache finds a properly configured +suexec wrapper, it will print the following message to +the console: +

    + +

    +Configuring Apache for use with suexec wrapper. +

    + +

    +If you don't see this message at server startup, the server is most +likely not finding the wrapper program where it expects it, or the +executable is not installed setuid root. Check +your installation and try again. +

    + +

    +One way to use suEXEC is through the +User and +Group directives in +VirtualHost +definitions. By setting these directives to values different from the +main server user ID, all requests for CGI resources will be executed as +the User and Group defined for that +<VirtualHost>. If only one or +neither of these directives are specified for a +<VirtualHost> then the main +server userid is assumed.

    + +suEXEC can also be used to to execute CGI programs as +the user to which the request is being directed. This is accomplished by +using the ~ character prefixing the user ID for whom +execution is desired. +The only requirement needed for this feature to work is for CGI +execution to be enabled for the user and that the script must meet the +scrutiny of the security checks above. + +

    +BACK TO CONTENTS +

    + +

    Debugging suEXEC

    +

    +The suEXEC wrapper will write log information to the location defined in +the suexec.h as indicated above. If you feel you have +configured and installed the wrapper properly, have a look at this log +and the error_log for the server to see where you may have gone astray. +

    + +

    +BACK TO CONTENTS +

    + +

    +Beware the Jabberwock: Warnings & Examples +

    +

    +NOTE! This section may not be complete. For the latest +revision of this section of the documentation, see the Apache Group's +Online Documentation +version. +

    + +

    +There are a few points of interest regarding the wrapper that can cause +limitations on server setup. Please review these before submitting any +"bugs" regarding suEXEC. +

      +
    • suEXEC Points Of Interest
    • +
    • Hierarchy limitations +
      + For security and efficiency reasons, all suexec requests must + remain within either a top-level document root for virtual + host requests, or one top-level personal document root for + userdir requests. For example, if you have four VirtualHosts + configured, you would need to structure all of your VHosts' + document roots off of one main Apache document hierarchy to + take advantage of suEXEC for VirtualHosts. (Example forthcoming.) +
      +
    • +
    • suEXEC's PATH environment variable +
      + This can be a dangerous thing to change. Make certain every + path you include in this define is a trusted + directory. You don't want to open people up to having someone + from across the world running a trojan horse on them. +
      +
    • +
    • Altering the suEXEC code +
      + Again, this can cause Big Trouble if you try + this without knowing what you are doing. Stay away from it + if at all possible. +
      +
    • +
    + +

    +BACK TO CONTENTS +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/unixware.html b/APACHE_1_3b7/htdocs/manual/unixware.html new file mode 100644 index 0000000000..a77a3b5cd4 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/unixware.html @@ -0,0 +1,62 @@ + + + +Compiling Apache under UnixWare + + + + + + +

    Compiling Apache under UnixWare

    + +To compile a working copy of Apache under UnixWare, there are several other +steps you may need to take. These prevent such problems as zombie processes, +bind errors, and accept errors, to name a few. + +

    UnixWare 1.x

    + +Make sure that USE_FCNTL_SERIALIZE_ACCEPT is defined (if not +defined by Apache autoconfiguration). If using the UnixWare cc +compiler, and you still see accept() errors, don't use compiler optimization, +or get gcc. + +

    UnixWare 2.0.x

    + +SCO patch tf2163 is required +in order for Apache to work correctly on UnixWare 2.0.x. See +http://www.sco.com +for UnixWare patch information.

    + +In addition, make sure that USE_FCNTL_SERIALIZE_ACCEPT is defined (if not +defined by Apache autoconfiguration). To reduce instances of connections +in FIN_WAIT_2 state, you may also want to define NO_LINGCLOSE (Apache 1.2 +only). + +

    UnixWare 2.1.x

    + +SCO patch ptf3123 is required +in order for Apache to work correctly on UnixWare 2.1.x. See +http://www.sco.com +for UnixWare patch information.

    + +NOTE: Unixware 2.1.2 and later already have patch ptf3123 +included

    + +In addition, make sure that USE_FCNTL_SERIALIZE_ACCEPT is defined (if not +defined by Apache autoconfiguration). To reduce instances of connections +in FIN_WAIT_2 state, you may also want to define NO_LINGCLOSE (Apache 1.2 +only).

    + +Thanks to Joe Doupnik <JRD@cc.usu.edu> and Rich Vaughn +<rvaughn@aad.com> for additional info for UnixWare builds.

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/upgrading_to_1_3.html b/APACHE_1_3b7/htdocs/manual/upgrading_to_1_3.html new file mode 100644 index 0000000000..95288d4320 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/upgrading_to_1_3.html @@ -0,0 +1,245 @@ + + +Upgrading to 1.3 from 1.2 + + + + + +

    Upgrading to 1.3 from 1.2

    + +

    In order to assist folks upgrading we are now going to maintain a +document describing information critical to existing Apache users. Note +that it only lists differences between recent major releases, so +for example, folks using Apache 1.1 or earlier will have to figure out +what changed up to Apache 1.2 before this document can be considered +relevant. Old users could look at the src/CHANGES file +which tracks code changes. + +

    These are intended to be brief notes, and you should be able to find +more information in either the New Features +document, or in the src/CHANGES file. + +

    Compile-Time Configuration Changes

    + +
      +
    • The source code has been reorganized, + which affects anyone with custom modules or modifications. But also, + the Module directive has been changed to the + AddModule directive. + +
    • The Configuration variable EXTRA_LFLAGS has + been renamed EXTRA_LDFLAGS. + +
    • The -DMAXIMUM_DNS definition has been obsoleted by + changes to mod_access enforcing double-reverse DNS lookups + when necessary. + +
    • The -DSERVER_SUBVERSION=\"string\" compile-time option has + been replaced with the run-time + AddVersionComponent + directive. +
    • + +
    • mod_dir has been split into two pieces + mod_autoindex, and + mod_dir. + +
    • mod_browser has been + replaced by mod_setenvif. + +
    • IRIX systems with untrusted users who can write CGIs which execute + as the same uid as httpd should consider using suexec, + or adding -DUSE_FCNTL_SERIALIZED_ACCEPT to + EXTRA_CFLAGS. This is slower, more information is available + on the performance tuning + page. There is a mild denial of service attack possible with the + default config, but the default config is an order of magnitude faster. + +
    • mod_auth_msql has been removed from the distribution. + +
    • The new Apache Autoconf-style Interface (APACI) was added to + the top-level to provide a real out-of-the-box build and installation + procedure for the complete Apache package. +
    + +

    Run-Time Configuration Changes

    + +
      +
    • AuthName strings may need to be quoted + in .htaccess or server configuration files. If you use + an AuthName directive like this: +

      +

      +     AuthName This and That
      +    
      +

      + you will need to change it to +

      +

      +     AuthName "This and That"
      +    
      +

      + This change was made for consistency in the config language. +
    • The default Apache ServerRoot directory changed + from the NCSA-compatible /usr/local/etc/httpd/ to + /usr/local/apache/. This change covers only the default + setting (and the documentation); it is of course possible to override it + using the -d ServerRoot and -f httpd.conf switches + when starting apache. + +
    • Folks using HTTP/1.1-style virtual hosting will need to list the + ip:port pairs that are supposed to have HTTP/1.1-style virtual hosting + via the + NameVirtualHost directive (one directive per pair). + Previously this support was given implicitly on the "main server + address". Now it has to be explicitly listed so as to avoid many + problems that users had. + Please see the Apache Virtual Host + documentation for further details on configuration. + +
    • The precedence of virtual hosts has been reversed (applies mainly to + vhosts using HTTP/1.1 Host: headers, and the + ServerPath directive). Now + the earlier vhosts in the file have precedence over the later vhosts. + +
    • HostnameLookups defaults to Off. + +
    • The undocumented + mod_access + syntax "allow user-agents" was removed. The replacement is the + more general "allow from env". + +
    • When using wildcards in pathnames (such as * and ?) they no longer + match / (slash). That is, they more closely behave how a UNIX shell + behaves. This affects <Directory> directives, + for example. + +
    • If no TransferLog directive is given then nothing will + be logged. + (Previously it would default to logs/access_log.) + +
    • Apache now has configurable error + logging levels, and the default eliminates some messages that + earlier versions always generated. + +
    • When booting, Apache will now detach itself from stdin, stdout, + and stderr. stderr will not be detached until after the config + files have been read so you will be able to see initial error + messages. After that all errors are logged in the error_log. + This makes it more convenient to start Apache via rsh, ssh, + or crontabs. + +
    • <Files> sections previously could take a full pathname, and + were matched against the full pathnames. This had some + inconsistancies, and was removed. To emulate this older behaviour + use a <Files> section nested inside a <Directory> + section. + +
    • <Location> matching behaviour with respect to slashes has + changed. See the <Location> + documentation for more info. + +
    + +

    Misc Changes

    + +
      +
    • ServerType inetd has been deprecated. It still exists, + but bugs are unlikely to be fixed. + +
    • httpd_monitor has been deprecated. The replacement is + to use mod_status and make a request to a URL such as + http://myhost/server-status?refresh=10. + +
    • + Apache now provides an effectively unbuffered connection for + CGI scripts. This means that data will be sent to the client + as soon as the CGI pauses or stops output; previously, Apache would + buffer the output up to a fixed buffer size before sending, which + could result in the user viewing an empty page until the CGI finished + or output a complete buffer. It is no longer necessary to use an + "nph-" CGI to get unbuffered output. Given that most CGIs are written + in a language that by default does buffering (e.g. perl) this + shouldn't have a detrimental effect on performance. + +

      "nph-" CGIs, which formerly provided a direct socket to the client + without any server post-processing, were not fully compatible with + HTTP/1.1 or SSL support. As such they would have had to implement + the transport details, such as encryption or chunking, in order + to work properly in certain situations. Now, the only difference + between nph and non-nph scripts is "non-parsed headers". + +

    • + dbmmanage has been overhauled. + +
    + +

    Third Party Modules

    + +

    The following changes between the 1.2 and 1.3 API may require slight +changes in third party modules not maintained by Apache. + +

      +
    • + To avoid symbol clashes with third-party code compiled into the server, the + general prefix `ap_' was globally applied to the following + classes of symbols: Apache provided general functions (e.g., + ap_cpystrn), public API functions (e.g., palloc, + bgets) and private functions which can't be made static + (because of cross-object usage) but should be (e.g., + new_connection). For backward source compatibility with + Apache 1.2 a new header file named compat.h was created which + provides defines for the old symbol names. + You'll either have to #include compat.h or update the API + symbols you use. +
    • +
    • + Be sure and examine the source code + reorganization page to see whether any item there affects you. +
    • + +
    • Use of SERVER_VERSION definition. If third-party + modules reference the server version string using this symbol, + they should be corrected to obtain it by calling the new API routine + const char *ap_get_server_version(). +
    • + +
    • ap_construct_url prototype change. The second parameter + was previously a server_rec, it has been changed to + a request_rec. + +
    • The table datatype has been made an opaque type. + Code which assumes a table is the same as an + array_header will not compile. This is actually a + change to enforce the API the way it was intended, all versions + of Apache have had a table_elts() function which + is intended for code which needs to access the elements of + a table. The changes required for this are pretty easy, and + work with all versions of Apache. + +

      Suppose t is a table. Whenever code refers to + t->elts, replace it with something like this: + +

      +    array_header *arr = table_elts(t);
      +    table_entry *elts = (table_entry *)arr->elts;
      +
      + + Whenever code refers to t->nelts use + arr->nelts. Many examples can be found in + the standard modules, search for table_elts. +
    • + +
    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/details.html b/APACHE_1_3b7/htdocs/manual/vhosts/details.html new file mode 100644 index 0000000000..b7baf591d3 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/details.html @@ -0,0 +1,372 @@ + + +An In-Depth Discussion of Virtual Host Matching + + + + + +

    An In-Depth Discussion of Virtual Host Matching

    + +

    The virtual host code was completely rewritten in +Apache 1.3. +This document attempts to explain exactly what Apache does when +deciding what virtual host to serve a hit from. With the help of the +new NameVirtualHost +directive virtual host configuration should be a lot easier and safer +than with versions prior to 1.3. + +

    If you just want to make it work without understanding +how, here are some examples. + +

    Config File Parsing

    + +

    There is a main_server which consists of all +the definitions appearing outside of <VirtualHost> sections. +There are virtual servers, called vhosts, which are defined by +<VirtualHost> +sections. + +

    The directives +Port, +ServerName, +ServerPath, +and +ServerAlias +can appear anywhere within the definition of +a server. However, each appearance overrides the previous appearance +(within that server). + +

    The default value of the Port field for main_server +is 80. The main_server has no default ServerPath, or +ServerAlias. The default ServerName is +deduced from the servers IP address. + +

    The main_server Port directive has two functions due to legacy +compatibility with NCSA configuration files. One function is +to determine the default network port Apache will bind to. This +default is overridden by the existence of any +Listen directives. +The second function is to specify the port number which is used +in absolute URIs during redirects. + +

    Unlike the main_server, vhost ports do not affect what +ports Apache listens for connections on. + +

    Each address appearing in the VirtualHost directive +can have an optional port. If the port is unspecified it defaults to +the value of the main_server's most recent Port statement. +The special port * indicates a wildcard that matches any port. +Collectively the entire set of addresses (including multiple +A record +results from DNS lookups) are called the vhost's address set. + +

    Unless a NameVirtualHost +directive is used for a specific IP address the first vhost with +that address is treated as an IP-based vhost. + +

    If name-based vhosts should be used a NameVirtualHost +directive must appear with the IP address set to be used for the +name-based vhosts. In other words, you must specify the IP address that +holds the hostname aliases (CNAMEs) for your name-based vhosts via a +NameVirtualHost directive in your configuration file. + +

    Multiple NameVirtualHost directives can be used each +with a set of VirtualHost directives but only one +NameVirtualHost directive should be used for each +specific IP:port pair. + +

    The ordering of NameVirtualHost and +VirtualHost directives is not important which makes the +following two examples identical (only the order of the +VirtualHost directives for one address set +is important, see below): + +

    +                                |
    +  NameVirtualHost 111.22.33.44  | <VirtualHost 111.22.33.44>
    +  <VirtualHost 111.22.33.44>    | # server A
    +  # server A  		        | </VirtualHost>
    +  ... 			        | <VirtualHost 111.22.33.55>
    +  </VirtualHost>	        | # server C
    +  <VirtualHost 111.22.33.44>    | ...
    +  # server B  		        | </VirtualHost>
    +  ... 			        | <VirtualHost 111.22.33.44>
    +  </VirtualHost>	        | # server B
    +                                | ...
    +  NameVirtualHost 111.22.33.55  | </VirtualHost>
    +  <VirtualHost 111.22.33.55>    | <VirtualHost 111.22.33.55>
    +  # server C  		        | # server D
    +  ... 			        | ...
    +  </VirtualHost>	        | </VirtualHost>
    +  <VirtualHost 111.22.33.55>    |
    +  # server D  		        | NameVirtualHost 111.22.33.44
    +  ... 			        | NameVirtualHost 111.22.33.55
    +  </VirtualHost>	        |
    +                                |
    +
    + +

    (To aid the readability of your configuration you should prefer the +left variant.) + +

    After parsing the VirtualHost directive, the vhost server +is given a default Port equal to the port assigned to the +first name in its VirtualHost directive. + +

    The complete list of names in the VirtualHost directive +are treated just like a ServerAlias (but are not overridden by any +ServerAlias statement) if all names resolve to the same address +set. Note that subsequent Port statements for this vhost will not +affect the ports assigned in the address set. + +

    During initialization a list for each IP address +is generated an inserted into an hash table. If the IP address is +used in a NameVirtualHost directive the list contains +all name-based vhosts for the given IP address. If there are no +vhosts defined for that address the NameVirtualHost directive +is ignored and an error is logged. For an IP-based vhost the list in the +hash table is empty. + +

    Due to a fast hashing function the overhead of hashing an IP address +during a request is minimal and almost not existent. Additionally +the table is optimized for IP addresses which vary in the last octet. + +

    For every vhost various default values are set. In particular: + +

      +
    1. If a vhost has no + ServerAdmin, + ResourceConfig, + AccessConfig, + Timeout, + KeepAliveTimeout, + KeepAlive, + MaxKeepAliveRequests, + or + SendBufferSize + directive then the respective value is + inherited from the main_server. (That is, inherited from whatever + the final setting of that value is in the main_server.) + +
    2. The "lookup defaults" that define the default directory + permissions + for a vhost are merged with those of the main_server. This includes + any per-directory configuration information for any module. + +
    3. The per-server configs for each module from the main_server are + merged into the vhost server. +
    + +Essentially, the main_server is treated as "defaults" or a +"base" on which to build each vhost. +But the positioning of these main_server +definitions in the config file is largely irrelevant -- the entire +config of the main_server has been parsed when this final merging occurs. +So even if a main_server definition appears after a vhost definition +it might affect the vhost definition. + +

    If the main_server has no ServerName at this point, +then the hostname of the machine that httpd is running on is used +instead. We will call the main_server address set those IP +addresses returned by a DNS lookup on the ServerName of +the main_server. + +

    For any undefined ServerName fields, a name-based vhost +defaults to the address given first in the VirtualHost +statement defining the vhost. + +

    Any vhost that includes the magic _default_ wildcard +is given the same ServerName as the main_server. + + +

    Virtual Host Matching

    + +

    The server determines which vhost to use for a request as follows: + +

    Hash table lookup

    + +

    When the connection is first made by a client, the IP address to +which the client connected is looked up in the internal IP hash table. + +

    If the lookup fails (the IP address wasn't found) the request is +served from the _default_ vhost if there is such a vhost +for the port to which the client sent the request. If there is no +matching _default_ vhost the request is served from the +main_server. + +

    If the lookup succeeded (a corresponding list for the IP address was +found) the next step is to decide if we have to deal with an IP-based +or a name-base vhost. + +

    IP-based vhost

    + +

    If the entry we found has an empty name list then we have found an +IP-based vhost, no further actions are performed and the request is +served from that vhost. + +

    Name-based vhost

    + +

    If the entry corresponds to a name-based vhost the name list contains +one or more vhost structures. This list contains the vhosts in the same +order as the VirtualHost directives appear in the config +file. + +

    The first vhost on this list (the first vhost in the config file with +the specified IP address) has the highest priority and catches any request +to an unknown server name or a request without a Host: +header field. + +

    If the client provided a Host: header field the list is +searched for a matching vhost and the first hit on a ServerName +or ServerAlias is taken and the request is served from +that vhost. A Host: header field can contain a port number, but +Apache always matches against the real port to which the client sent +the request. + +

    If the client submitted a HTTP/1.0 request without Host: +header field we don't know to what server the client tried to connect and +any existing ServerPath is matched against the URI +from the request. The first matching path on the list is used and the +request is served from that vhost. + +

    If no matching vhost could be found the request is served from the +first vhost with a matching port number that is on the list for the IP +to which the client connected (as already mentioned before). + +

    Persistent connections

    +The IP lookup described above is only done once for a particular +TCP/IP session while the name lookup is done on every request +during a KeepAlive/persistent connection. In other words a client may +request pages from different name-based vhosts during a single +persistent connection. + + +

    Absolute URI

    + +

    If the URI from the request is an absolute URI, and its hostname and +port match the main server or one of the configured virtual hosts +and match the address and port to which the client sent the request, +then the scheme/hostname/port prefix is stripped off and the remaining +relative URI is served by the corresponding main server or virtual host. +If it does not match, then the URI remains untouched and the request is +taken to be a proxy request. + + +

    Observations

    + +
      + +
    • A name-based vhost can never interfere with an IP-base vhost and + vice versa. IP-based vhosts can only be reached through an IP address + of its own address set and never through any other address. + The same applies to name-based vhosts, they can only be reached + through an IP address of the corresponding address set which must + be defined with a NameVirtualHost directive. +

      + +

    • ServerAlias and ServerPath checks are never + performed for an IP-based vhost. +

      + +

    • The order of name-/IP-based, the _default_ + vhost and the NameVirtualHost directive within the config + file is not important. Only the ordering + of name-based vhosts for a specific address set is significant. The one + name-based vhosts that comes first in the configuration file has + the highest priority for its corresponding address set. +

      + +

    • For security reasons the port number given in a Host: + header field is never used during the matching process. Apache always + uses the real port to which the client sent the request. +

      + +

    • If a ServerPath directive exists which is a prefix of + another ServerPath directive that appears later in + the configuration file, then the former will always be matched + and the latter will never be matched. (That is assuming that no + Host: header field was available to disambiguate the two.) +

      + +

    • If two IP-based vhosts have an address in common, the vhost appearing + first in the config file is always matched. Such a thing might happen + inadvertently. The server will give a warning in the error + logfile when it detects this. +

      + +

    • A _default_ vhost catches a request only if there is no + other vhost with a matching IP address and a matching port + number for the request. The request is only caught if the port number + to which the client sent the request matches the port number of your + _default_ vhost which is your standard Port + by default. A wildcard port can be specified (i.e. + _default_:*) to catch requests to any available port. +

      + +

    • The main_server is only used to serve a request if the IP address + and port number to which the client connected is unspecified + and does not match any other vhost (including a _default_ + vhost). In other words the main_server only catches a request for an + unspecified address/port combination (unless there is a + _default_ vhost which matches that port). +

      + +

    • A _default_ vhost or the main_server is never + matched for a request with an unknown or missing Host: header + field if the client connected to an address (and port) which is used + for name-based vhosts, e.g. in a NameVirtualHost directive. +

      + +

    • You should never specify DNS names in VirtualHost + directives because it will force your server to rely on DNS to boot. + Furthermore it poses a security threat if you do not control the + DNS for all the domains listed. + There's more information + available on this and the next two topics. +

      + +

    • ServerName should always be set for each vhost. Otherwise + A DNS lookup is required for each vhost. +

      + +

    + +

    Tips

    + +

    In addition to the tips on the DNS +Issues page, here are some further tips: + +

      + +
    • Place all main_server definitions before any VirtualHost + definitions. (This is to aid the readability of the configuration -- + the post-config merging process makes it non-obvious that definitions + mixed in around virtual hosts might affect all virtual hosts.) +

      + +

    • Group corresponding NameVirtualHost and + VirtualHost definitions in your configuration to ensure + better readability. +

      + +

    • Avoid ServerPaths which are prefixes of other + ServerPaths. If you cannot avoid this then you have to + ensure that the longer (more specific) prefix vhost appears earlier in + the configuration file than the shorter (less specific) prefix + (i.e., "ServerPath /abc" should appear after + "ServerPath /abc/def"). +

      + +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/details_1_2.html b/APACHE_1_3b7/htdocs/manual/vhosts/details_1_2.html new file mode 100644 index 0000000000..e262cb3556 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/details_1_2.html @@ -0,0 +1,396 @@ + + +An In-Depth Discussion of VirtualHost Matching + + + + + +

    An In-Depth Discussion of VirtualHost Matching

    + +

    This is a very rough document that was probably out of date the moment +it was written. It attempts to explain exactly what the code does when +deciding what virtual host to serve a hit from. It's provided on the +assumption that something is better than nothing. The server version +under discussion is Apache 1.2. + +

    If you just want to "make it work" without understanding +how, there's a What Works section at the bottom. + +

    Config File Parsing

    + +

    There is a main_server which consists of all the definitions appearing +outside of VirtualHost sections. There are virtual servers, +called vhosts, which are defined by +VirtualHost +sections. + +

    The directives +Port, +ServerName, +ServerPath, +and +ServerAlias +can appear anywhere within the definition of +a server. However, each appearance overrides the previous appearance +(within that server). + +

    The default value of the Port field for main_server +is 80. The main_server has no default ServerName, +ServerPath, or ServerAlias. + +

    In the absence of any +Listen +directives, the (final if there +are multiple) Port directive in the main_server indicates +which port httpd will listen on. + +

    The Port and ServerName directives for +any server main or virtual are used when generating URLs such as during +redirects. + +

    Each address appearing in the VirtualHost directive +can have an optional port. If the port is unspecified it defaults to +the value of the main_server's most recent Port statement. +The special port * indicates a wildcard that matches any port. +Collectively the entire set of addresses (including multiple +A record +results from DNS lookups) are called the vhost's address set. + +

    The magic _default_ address has significance during +the matching algorithm. It essentially matches any unspecified address. + +

    After parsing the VirtualHost directive, the vhost server +is given a default Port equal to the port assigned to the +first name in its VirtualHost directive. The complete +list of names in the VirtualHost directive are treated +just like a ServerAlias (but are not overridden by any +ServerAlias statement). Note that subsequent Port +statements for this vhost will not affect the ports assigned in the +address set. + +

    +All vhosts are stored in a list which is in the reverse order that +they appeared in the config file. For example, if the config file is: + +

    +    <VirtualHost A>
    +    ...
    +    </VirtualHost>
    +
    +    <VirtualHost B>
    +    ...
    +    </VirtualHost>
    +
    +    <VirtualHost C>
    +    ...
    +    </VirtualHost>
    +
    + +Then the list will be ordered: main_server, C, B, A. Keep this in mind. + +

    +After parsing has completed, the list of servers is scanned, and various +merges and default values are set. In particular: + +

      +
    1. If a vhost has no + ServerAdmin, + ResourceConfig, + AccessConfig, + Timeout, + KeepAliveTimeout, + KeepAlive, + MaxKeepAliveRequests, + or + SendBufferSize + directive then the respective value is + inherited from the main_server. (That is, inherited from whatever + the final setting of that value is in the main_server.) + +
    2. The "lookup defaults" that define the default directory + permissions + for a vhost are merged with those of the main server. This includes + any per-directory configuration information for any module. + +
    3. The per-server configs for each module from the main_server are + merged into the vhost server. +
    + +Essentially, the main_server is treated as "defaults" or a +"base" on +which to build each vhost. But the positioning of these main_server +definitions in the config file is largely irrelevant -- the entire +config of the main_server has been parsed when this final merging occurs. +So even if a main_server definition appears after a vhost definition +it might affect the vhost definition. + +

    If the main_server has no ServerName at this point, +then the hostname of the machine that httpd is running on is used +instead. We will call the main_server address set those IP +addresses returned by a DNS lookup on the ServerName of +the main_server. + +

    Now a pass is made through the vhosts to fill in any missing +ServerName fields and to classify the vhost as either +an IP-based vhost or a name-based vhost. A vhost is +considered a name-based vhost if any of its address set overlaps the +main_server (the port associated with each address must match the +main_server's Port). Otherwise it is considered an IP-based +vhost. + +

    For any undefined ServerName fields, a name-based vhost +defaults to the address given first in the VirtualHost +statement defining the vhost. Any vhost that includes the magic +_default_ wildcard is given the same ServerName as +the main_server. Otherwise the vhost (which is necessarily an IP-based +vhost) is given a ServerName based on the result of a reverse +DNS lookup on the first address given in the VirtualHost +statement. + +

    + +

    Vhost Matching

    + + +

    Apache 1.3 differs from what is documented +here, and documentation still has to be written. + +

    +The server determines which vhost to use for a request as follows: + +

    find_virtual_server: When the connection is first made +by the client, the local IP address (the IP address to which the client +connected) is looked up in the server list. A vhost is matched if it +is an IP-based vhost, the IP address matches and the port matches +(taking into account wildcards). + +

    If no vhosts are matched then the last occurrence, if it appears, +of a _default_ address (which if you recall the ordering of the +server list mentioned above means that this would be the first occurrence +of _default_ in the config file) is matched. + +

    In any event, if nothing above has matched, then the main_server is +matched. + +

    The vhost resulting from the above search is stored with data +about the connection. We'll call this the connection vhost. +The connection vhost is constant over all requests in a particular TCP/IP +session -- that is, over all requests in a KeepAlive/persistent session. + +

    For each request made on the connection the following sequence of +events further determines the actual vhost that will be used to serve +the request. + +

    check_fulluri: If the requestURI is an absoluteURI, that +is it includes http://hostname/, then an attempt is made to +determine if the hostname's address (and optional port) match that of +the connection vhost. If it does then the hostname portion of the URI +is saved as the request_hostname. If it does not match, then the +URI remains untouched. Note: to achieve this address +comparison, +the hostname supplied goes through a DNS lookup unless it matches the +ServerName or the local IP address of the client's socket. + +

    parse_uri: If the URI begins with a protocol +(i.e., http:, ftp:) then the request is +considered a proxy request. Note that even though we may have stripped +an http://hostname/ in the previous step, this could still +be a proxy request. + +

    read_request: If the request does not have a hostname +from the earlier step, then any Host: header sent by the +client is used as the request hostname. + +

    check_hostalias: If the request now has a hostname, +then an attempt is made to match for this hostname. The first step +of this match is to compare any port, if one was given in the request, +against the Port field of the connection vhost. If there's +a mismatch then the vhost used for the request is the connection vhost. +(This is a bug, see observations.) + +

    +If the port matches, then httpd scans the list of vhosts starting with +the next server after the connection vhost. This scan does not +stop if there are any matches, it goes through all possible vhosts, +and in the end uses the last match it found. The comparisons performed +are as follows: + +

      +
    • Compare the request hostname:port with the vhost + ServerName and Port. + +
    • Compare the request hostname against any and all addresses given in + the VirtualHost directive for this vhost. + +
    • Compare the request hostname against the ServerAlias + given for the vhost. +
    + +

    +check_serverpath: If the request has no hostname +(back up a few paragraphs) then a scan similar to the one +in check_hostalias is performed to match any +ServerPath directives given in the vhosts. Note that the +last match is used regardless (again consider the ordering of +the virtual hosts). + +

    Observations

    + +
      + +
    • It is difficult to define an IP-based vhost for the machine's + "main IP address". You essentially have to create a bogus + ServerName for the main_server that does not match the + machine's IPs. +

      + +

    • During the scans in both check_hostalias and + check_serverpath no check is made that the vhost being + scanned is actually a name-based vhost. This means, for example, that + it's possible to match an IP-based vhost through another address. But + because the scan starts in the vhost list at the first vhost that + matched the local IP address of the connection, not all IP-based vhosts + can be matched. +

      + Consider the config file above with three vhosts A, B, C. Suppose + that B is a named-based vhost, and A and C are IP-based vhosts. If + a request comes in on B or C's address containing a header + "Host: A" then + it will be served from A's config. If a request comes in on A's + address then it will always be served from A's config regardless of + any Host: header. +

      + +
    • Unless you have a _default_ vhost, + it doesn't matter if you mix name-based vhosts in amongst IP-based + vhosts. During the find_virtual_server phase above no + named-based vhost will be matched, so the main_server will remain the + connection vhost. Then scans will cover all vhosts in the vhost list. +

      + If you do have a _default_ vhost, then you cannot place + named-based vhosts after it in the config. This is because on any + connection to the main server IPs the connection vhost will always be + the _default_ vhost since none of the name-based are + considered during find_virtual_server. +

      + +
    • You should never specify DNS names in VirtualHost + directives because it will force your server to rely on DNS to boot. + Furthermore it poses a security threat if you do not control the + DNS for all the domains listed. + There's more information + available on this and the next two topics. +

      + +

    • ServerName should always be set for each vhost. Otherwise + A DNS lookup is required for each vhost. +

      + +

    • A DNS lookup is always required for the main_server's + ServerName (or to generate that if it isn't specified + in the config). +

      + +

    • If a ServerPath directive exists which is a prefix of + another ServerPath directive that appears later in + the configuration file, then the former will always be matched + and the latter will never be matched. (That is assuming that no + Host header was available to disambiguate the two.) +

      + +

    • If a vhost that would otherwise be a name-vhost includes a + Port statement that doesn't match the main_server + Port then it will be considered an IP-based vhost. + Then find_virtual_server will match it (because + the ports associated with each address in the address set default + to the port of the main_server) as the connection vhost. Then + check_hostalias will refuse to check any other name-based + vhost because of the port mismatch. The result is that the vhost + will steal all hits going to the main_server address. +

      + +

    • If two IP-based vhosts have an address in common, the vhost appearing + later in the file is always matched. Such a thing might happen + inadvertently. If the config has name-based vhosts and for some reason + the main_server ServerName resolves to the wrong address + then all the name-based vhosts will be parsed as ip-based vhosts. + Then the last of them will steal all the hits. +

      + +

    • The last name-based vhost in the config is always matched for any hit + which doesn't match one of the other name-based vhosts. + +
    + +

    What Works

    + +

    In addition to the tips on the DNS +Issues page, here are some further tips: + +

      + +
    • Place all main_server definitions before any VirtualHost definitions. +(This is to aid the readability of the configuration -- the post-config +merging process makes it non-obvious that definitions mixed in around +virtualhosts might affect all virtualhosts.) +

      + +

    • Arrange your VirtualHosts such +that all name-based virtual hosts come first, followed by IP-based +virtual hosts, followed by any _default_ virtual host +

      + +

    • Avoid ServerPaths which are prefixes of other +ServerPaths. If you cannot avoid this then you have to +ensure that the longer (more specific) prefix vhost appears earlier in +the configuration file than the shorter (less specific) prefix +(i.e., "ServerPath /abc" should appear after +"ServerPath /abcdef"). +

      + +

    • Do not use port-based vhosts in the same server as +name-based vhosts. A loose definition for port-based is a vhost which +is determined by the port on the server (i.e., one server with +ports 8000, 8080, and 80 - all of which have different configurations). +

      + +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/examples.html b/APACHE_1_3b7/htdocs/manual/vhosts/examples.html new file mode 100644 index 0000000000..d6b11426f2 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/examples.html @@ -0,0 +1,512 @@ + + +VirtualHost Examples + + + + + +

    Virtual Host examples for common setups

    + + +

    Base configuration

    + + + +

    Additional features

    + + + +
    + +

    IP-based vhosts only

    + +
      + +
    • Setup 1: + The server machine has two IP addresses (111.22.33.44 + and 111.22.33.55) + which resolve to the names server.domain.tld and + www.otherdomain.tld respectively. + The hostname www.domain.tld is an alias (CNAME) + for server.domain.tld and will represent the + main server. +

      + Server configuration: + + +

      +    ...
      +    Port 80
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/otherdomain
      +    ServerName www.otherdomain.tld
      +    ...
      +    </VirtualHost>
      +    
      + www.otherdomain.tld can only be reached through the + address 111.22.33.55, while www.domain.tld + can only be reached through 111.22.33.44 + (which represents our main server). +
      +

      + +

    • Setup 2: + Same as setup 1, but we don't want to have a dedicated main server. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName server.domain.tld
      +    
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +    ...
      +    </VirtualHost>
      +
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/otherdomain
      +    ServerName www.otherdomain.tld
      +    ...
      +    </VirtualHost>
      +    
      + The main server can never catch a request, because all IP addresses + of our machine are in use for IP-based virtual hosts + (only localhost requests can hit the main server). +
      +

      + +

    • Setup 3: + The server machine has two IP addresses (111.22.33.44 + and 111.22.33.55) + which resolve to the names server.domain.tld and + www-cache.domain.tld respectively. + The hostname www.domain.tld is an alias (CNAME) + for server.domain.tld and will represent the + main server. + www-cache.domain.tld will become our proxy-cache + listening on port 8080, while the web server itself uses the default + port 80. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    Listen 111.22.33.44:80
      +    Listen 111.22.33.55:8080
      +    ServerName server.domain.tld
      +    
      +    <VirtualHost 111.22.33.44:80>
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +    ...
      +    </VirtualHost>
      +
      +    <VirtualHost 111.22.33.55:8080>
      +    ServerName www-cache.domain.tld
      +    ...
      +      <Directory proxy:>
      +      order deny,allow
      +      deny from all
      +      allow from 111.22.33
      +      </Directory>
      +    </VirtualHost>
      +    
      + The main server can never catch a request, because all IP addresses + (apart from localhost) of our machine are in use for IP-based + virtual hosts. The web server can only be reached on the first address + through port 80 and the proxy only on the second address through port 8080. +
      +
    +
    + +

    Name-based vhosts only

    + +
      + +
    • Setup 1: + The server machine has one IP address (111.22.33.44) + which resolves to the name server.domain.tld. + There are two aliases (CNAMEs) www.domain.tld and + www.sub.domain.tld for the address 111.22.33.44. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName server.domain.tld
      +
      +    NameVirtualHost 111.22.33.44 
      +
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +    ...
      +    </VirtualHost>
      +    
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain
      +    ServerName www.sub.domain.tld
      +    ...
      +    </VirtualHost> 
      +    
      + Apart from localhost there are no unspecified + addresses/ports, therefore the main server only serves + localhost requests. Due to the fact + that www.domain.tld has the highest priority + it can be seen as the default or + primary server. +
      +

      + +

    • Setup 2: + The server machine has two IP addresses (111.22.33.44 + and 111.22.33.55) + which resolve to the names server1.domain.tld and + server2.domain.tld respectively. + The alias www.domain.tld should be used for the + main server which should also catch any unspecified addresses. + We want to use a virtual host for the alias + www.otherdomain.tld and one virtual host should + catch any request to hostnames of the form + *.sub.domain.tld with www.sub.domain.tld + as its server name. The address 111.22.33.55 should be + used for the virtual hosts. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName www.domain.tld
      +    DocumentRoot /www/domain
      +
      +    NameVirtualHost 111.22.33.55
      +
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/otherdomain
      +    ServerName www.otherdomain.tld
      +    ...
      +    </VirtualHost>
      +   
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/subdomain
      +    ServerName www.sub.domain.tld
      +    ServerAlias *.sub.domain.tld
      +    ...
      +    </VirtualHost> 
      +    
      + Any request to an address other than 111.22.33.55 + will be served from the main server. A request to + 111.22.33.55 with an unknown or no Host: + header will be served from www.otherdomain.tld. +
      +
    + +
    + +

    Mixed name-/IP-based vhosts

    + +
      + +
    • Setup: + The server machine has three IP addresses (111.22.33.44, + 111.22.33.55 and 111.22.33.66) + which resolve to the names server.domain.tld, + www.otherdomain1.tld and www.otherdomain2.tld + respectively. + The address 111.22.33.44 should we used for a couple + of name-based vhosts and the other addresses for IP-based vhosts. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName server.domain.tld
      +
      +    NameVirtualHost 111.22.33.44
      +
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +    ...
      +    </VirtualHost>
      +   
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain1
      +    ServerName www.sub1.domain.tld
      +    ...
      +    </VirtualHost> 
      +    
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain2
      +    ServerName www.sub2.domain.tld
      +    ...
      +    </VirtualHost> 
      + 
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/otherdomain1
      +    ServerName www.otherdomain1.tld
      +    ...
      +    </VirtualHost> 
      +    
      +    <VirtualHost 111.22.33.66>
      +    DocumentRoot /www/otherdomain2
      +    ServerName www.otherdomain2.tld
      +    ...
      +    </VirtualHost>     
      +    
      + +
    + +
    + +

    Port-based vhosts

    + +
      + +
    • Setup: + The server machine has one IP address (111.22.33.44) + which resolves to the name www.domain.tld. + If we don't have the option to get another address or alias + for our server we can use port-based vhosts if we need + a virtual host with a different configuration. +

      + Server configuration: + +

      +    ...
      +    Listen 80
      +    Listen 8080
      +    ServerName www.domain.tld
      +    DocumentRoot /www/domain
      +
      +    <VirtualHost 111.22.33.44:8080>
      +    DocumentRoot /www/domain2
      +    ...
      +    </VirtualHost>
      +    
      + A request to www.domain.tld on port 80 is served + from the main server and a request to port 8080 is served from + the virtual host. +
      +
    + +
    + +

    Using _default_ vhosts

    + +
      + +
    • Setup 1: + Catching every request to any unspecified IP address and port, + i.e. an address/port combination that is not used for any other + virtual host. +

      + Server configuration: + +

      +    ...
      +    <VirtualHost _default_:*>
      +    DocumentRoot /www/default
      +    ...
      +    </VirtualHost>
      +    
      + Using such a default vhost with a wildcard port effectively + prevents any request going to the main server.
      + A default vhost never serves a request that was sent to an + address/port that is used for name-based vhosts. If the request + contained an unknown or no Host: header it is + always served from the primary name-based vhost (the + vhost for that address/port appearing first in the configuration + file).
      + You can use + AliasMatch + or + RewriteRule + to rewrite any request to a single information page (or script). +
      +

      + +

    • Setup 2: + Same as setup 1, but the server listens on several ports and + we want to use a second _default_ vhost for port 80. +

      + Server configuration: + +

      +    ...
      +    <VirtualHost _default_:80>
      +    DocumentRoot /www/default80
      +    ...
      +    </VirtualHost>
      +    
      +    <VirtualHost _default_:*>
      +    DocumentRoot /www/default
      +    ...
      +    </VirtualHost>    
      +    
      + The default vhost for port 80 (which must appear before + any default vhost with a wildcard port) catches all requests that + were sent to an unspecified IP address. The main server is + never used to serve a request. +
      +

      + +

    • Setup 3: + We want to have a default vhost for port 80, but no other default vhosts. +

      + Server configuration: + +

      +    ...
      +    <VirtualHost _default_:80>
      +    DocumentRoot /www/default
      +    ...
      +    </VirtualHost>
      +    
      + A request to an unspecified address on port 80 is served from the + default vhost any other request to an unspecified address and port + is served from the main server. +
      + +
    + +
    + +

    Migrating a name-based vhost to an IP-based vhost

    + +
      + +
    • Setup: + The name-based vhost with the hostname + www.otherdomain.tld (from our name-based + example, setup 2) should get its own IP address. + To avoid problems with name servers or proxies who cached the old + IP address for the name-based vhost we want to provide both variants + during a migration phase.
      + The solution is easy, because we can simply add the new IP address + (111.22.33.66) to the VirtualHost directive. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName www.domain.tld
      +    DocumentRoot /www/domain
      +
      +    NameVirtualHost 111.22.33.55
      +
      +    <VirtualHost 111.22.33.55 111.22.33.66>
      +    DocumentRoot /www/otherdomain
      +    ServerName www.otherdomain.tld
      +    ...
      +    </VirtualHost>
      +   
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/subdomain
      +    ServerName www.sub.domain.tld
      +    ServerAlias *.sub.domain.tld
      +    ...
      +    </VirtualHost>
      +    
      + The vhost can now be accessed through the new address (as an IP-based + vhost) and through the old address (as a name-based vhost). +
      + +
    + +
    + +

    Using the ServerPath directive

    + +
      + +
    • Setup: + We have a server with two name-based vhosts. In order to match the correct + virtual host a client must send the correct Host: header. + Old HTTP/1.0 clients do not send such a header and Apache has no clue + what vhost the client tried to reach (and serves the request from + the primary vhost). To provide as much backward compatibility + as possible we create a primary vhost which returns a single page + containing links with an URL prefix to the name-based virtual hosts. +

      + Server configuration: + +

      +    ...
      +    NameVirtualHost 111.22.33.44
      +
      +    <VirtualHost 111.22.33.44>
      +    # primary vhost
      +    DocumentRoot /www/subdomain
      +    RewriteEngine On
      +    RewriteRule ^/.* /www/subdomain/index.html
      +    ...
      +    </VirtualHost>
      +
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain/sub1
      +    ServerName www.sub1.domain.tld
      +    ServerPath /sub1/
      +    RewriteEngine On
      +    RewriteRule ^(/sub1/.*) /www/subdomain$1 
      +    ...
      +    </VirtualHost>
      +
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain/sub2
      +    ServerName www.sub2.domain.tld
      +    ServerPath /sub2/
      +    RewriteEngine On
      +    RewriteRule ^(/sub2/.*) /www/subdomain$1 
      +    ...
      +    </VirtualHost>
      +    
      + Due to the ServerPath + directive a request to the + URL http://www.sub1.domain.tld/sub1/ is always + served from the sub1-vhost.
      + A request to the URL http://www.sub1.domain.tld/ + is only served from the sub1-vhost if the client sent a correct + Host: header. + If no Host: header is sent the client gets the + information page from the primary host.
      + Please note that there is one oddity: A request to + http://www.sub2.domain.tld/sub1/ is also served from + the sub1-vhost if the client sent no Host: header.
      + The RewriteRule directives are used to make sure that + a client which sent a correct Host: header can use + both URL variants, i.e. with or without URL prefix. +
      + +
    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/fd-limits.html b/APACHE_1_3b7/htdocs/manual/vhosts/fd-limits.html new file mode 100644 index 0000000000..6b9d0f93c4 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/fd-limits.html @@ -0,0 +1,59 @@ + + + +Apache Server Virtual Host Support + + + + + +

    File Descriptor Limits

    + +

    +When using a large number of Virtual Hosts, Apache may run out of available +file descriptors (sometimes called file handles if each Virtual +Host specifies different log files. +The total number of file descriptors used by Apache is one for each distinct +error log file, one for every other log file directive, plus 10-20 for +internal use. Unix operating systems limit the number of file descriptors that +may be used by a process; the limit is typically 64, and may usually be +increased up to a large hard-limit. +

    +Although Apache attempts to increase the limit as required, this +may not work if: +

      +
    1. Your system does not provide the setrlimit() system call. +
    2. The setrlimit(RLIMIT_NOFILE) call does not function on your system + (such as Solaris 2.3) +
    3. The number of file descriptors required exceeds the hard limit. +
    4. Your system imposes other limits on file descriptors, such as a limit +on stdio streams only using file descriptors below 256. (Solaris 2) +
    + +In the event of problems you can: +
      +
    • Reduce the number of log files; don't specify log files in the VirtualHost +sections, but only log to the main log files. +
    • If you system falls into 1 or 2 (above), then increase the file descriptor +limit before starting Apache, using a script like +
      +#!/bin/sh
      +ulimit -S -n 100
      +exec httpd
      +
    +

    +Please see the +Descriptors and Apache +document containing further details about file descriptor problems and how +they can be solved on your operating system. +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/footer.html b/APACHE_1_3b7/htdocs/manual/vhosts/footer.html new file mode 100644 index 0000000000..7fe745dcfd --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/footer.html @@ -0,0 +1,8 @@ +
    + +

    + Apache HTTP Server Version 1.3 +

    + +Index +Home diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/header.html b/APACHE_1_3b7/htdocs/manual/vhosts/header.html new file mode 100644 index 0000000000..5662300029 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/header.html @@ -0,0 +1,6 @@ +
    + [APACHE DOCUMENTATION] +

    + Apache HTTP Server Version 1.3 +

    +
    diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/host.html b/APACHE_1_3b7/htdocs/manual/vhosts/host.html new file mode 100644 index 0000000000..0065e04861 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/host.html @@ -0,0 +1,172 @@ + + +Apache non-IP Virtual Hosts + + + + + +

    Apache non-IP Virtual Hosts

    + +See Also: +Virtual Host Support + +
    + +

    What is a Virtual Host

    + +

    The "Virtual Host" refers to the practice of maintaining more than +one server on one machine, as differentiated by their apparent +hostname. For example, it is often desirable for companies sharing a +web server to have their own domains, with web servers accessible as +www.company1.com and www.company2.com, +without requiring the user to know any extra path information.

    + +

    Apache was one of the first servers to support virtual hosts right +out of the box, but since the base HTTP (HyperText +Transport Protocol) standard does not allow any method for the server +to determine the hostname it is being addressed as, Apache's virtual +host support has required a separate IP address for each +server. Documentation on using this approach (which still works very +well) is available. + +

    While the approach described above works, with the available IP +address space growing smaller, and the number of domains increasing, +it is not the most elegant solution, and is hard to implement on some +machines. The HTTP/1.1 protocol contains a method for the +server to identify what name it is being addressed as. Apache 1.1 and +later support this approach as well as the traditional +IP-address-per-hostname method.

    + +

    The benefits of using the new virtual host support is a practically +unlimited number of servers, ease of configuration and use, and +requires no additional hardware or software. The main disadvantage is +that the user's browser must support this part of the protocol. The +latest versions of many browsers (including Netscape Navigator 2.0 and +later) do, but many browsers, especially older ones, do not. This can +cause problems, although a possible solution is addressed below.

    + +

    Using non-IP Virtual Hosts

    + +

    Using the new virtual hosts is quite easy, and superficially looks +like the old method. You simply add to one of the Apache configuration +files (most likely httpd.conf or srm.conf) +code similar to the following:

    +
    +    <VirtualHost www.apache.org>
    +    ServerName www.apache.org
    +    DocumentRoot /usr/web/apache
    +    </VirtualHost>
    +
    + +

    Of course, any additional directives can (and should) be placed +into the <VirtualHost> section. To make this work, +all that is needed is to make sure that the www.apache.org +DNS entry points to the same IP address as the main +server. Optionally, you could simply use that IP address in the +<VirtualHost> entry.

    + +

    Additionally, many servers may wish to be accessible by more than +one name. For example, the Apache server might want to be accessible +as apache.org, or ftp.apache.org, assuming +the IP addresses pointed to the same server. In fact, one might want it +so that all addresses at apache.org were picked up by the +server. This is possible with the ServerAlias +directive, placed inside the <VirtualHost> section. For +example:

    + +
    +    ServerAlias apache.org *.apache.org
    +
    + +

    Note that you can use * and ? as wild-card +characters.

    + +

    You also might need ServerAlias if you are serving local users who +do not always include the domain name. For example, if local users are +familiar with typing "www" or "www.physics" then you will need to add +ServerAlias www www.physics. It isn't possible for the +server to know what domain the client uses for their name resolution +because the client doesn't provide that information in the request.

    + +

    Security Considerations

    + +Apache allows all virtual hosts to be made accessible via the +Host: header through all IP interfaces, even those which +are configured to use different IP interfaces. For example, if the +configuration for www.foo.com contained a virtual host +section for www.bar.com, and www.bar.com was +a separate IP interface, such that +non-Host:-header-supporting browsers can use it, as +before with Apache 1.0. If a request is made to +www.foo.com and the request includes the header +Host: www.bar.com, a page from www.bar.com +will be sent. + +

    + +This is a security concern if you are controlling access to a +particular server based on IP-layer controls, such as from within a +firewall or router. Let's say www.bar.com in the above +example was instead an intra-net server called +private.foo.com, and the router used by foo.com only let +internal users access private.foo.com. Obviously, +Host: header functionality now allows someone who has +access to www.foo.com to get +private.foo.com, if they send a Host: +private.foo.com header. It is important to note that this +condition exists only if you only implement this policy at the IP +layer - all security controls used by Apache (i.e., allow, deny from, etc.) are consistently +respected. + +

    Compatibility with Older Browsers

    + +

    As mentioned earlier, a majority of browsers do not send the +required data for the new virtual hosts to work properly. These +browsers will always be sent to the main server's pages. There is a +workaround, albeit a slightly cumbersome one:

    + +

    To continue the www.apache.org example (Note: Apache's +web server does not actually function in this manner), we might use the +new ServerPath directive in the www.apache.org +virtual host, for example: + +

    +    ServerPath /apache
    +
    +

    What does this mean? It means that a request for any file beginning +with "/apache" will be looked for in the Apache +docs. This means that the pages can be accessed as +http://www.apache.org/apache/ for all browsers, although +new browsers can also access it as +http://www.apache.org/.

    + +

    In order to make this work, put a link on your main server's page +to http://www.apache.org/apache/ (Note: Do not use +http://www.apache.org/ - this would create an endless +loop). Then, in the virtual host's pages, be sure to use either purely +relative links (e.g. "file.html" or +"../icons/image.gif" or links containing the prefacing +/apache/ +(e.g. "http://www.apache.org/apache/file.html" or +"/apache/docs/1.1/index.html").

    + +

    This requires a bit of +discipline, but adherence to these guidelines will, for the most part, +ensure that your pages will work with all browsers, new and old. When +a new browser contacts http://www.apache.org/, they will +be directly taken to the Apache pages. Older browsers will be able to +click on the link from the main server, go to +http://www.apache.org/apache/, and then access the +pages.

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/index.html b/APACHE_1_3b7/htdocs/manual/vhosts/index.html new file mode 100644 index 0000000000..b08ea16444 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/index.html @@ -0,0 +1,64 @@ + + + +Apache Virtual Host documentation + + + + + +

    Apache Virtual Host documentation

    + +

    The term Virtual Host refers to the practice of maintaining +more than one server on one machine, as differentiated by their apparent +hostname. For example, it is often desirable for companies sharing a +web server to have their own domains, with web servers accessible as +www.company1.com and www.company2.com, +without requiring the user to know any extra path information.

    + +

    Apache was one of the first servers to support IP-based +virtual hosts right out of the box. Versions 1.1 and later of +Apache support both, IP-based and name-based virtual hosts (vhosts). +The latter variant of virtual hosts is sometimes also called host-based or +non-IP virtual hosts.

    + +

    Below is a list of documentation pages which explain all details +of virtual host support in Apache version 1.3 and later.

    + +
    + +

    Virtual Host Support

    + + + +

    Configuration directives

    + + + +

    Folks trying to debug their virtual host configuration may find the +Apache -S command line switch useful. It will dump out a +description of how Apache parsed the configuration file. Careful +examination of the IP addresses and server names may help uncover +configuration mistakes. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/ip-based.html b/APACHE_1_3b7/htdocs/manual/vhosts/ip-based.html new file mode 100644 index 0000000000..14e529da75 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/ip-based.html @@ -0,0 +1,140 @@ + + + +Apache IP-based Virtual Host Support + + + + + +

    Apache IP-based Virtual Host Support

    + +See also: +Name-based Virtual Hosts Support + +
    + +

    System requirements

    +As the term IP-based indicates, the server must have a +different IP address for each IP-based virtual host. +This can be achieved by the machine having several physical network connections, +or by use of virtual interfaces which are supported by most modern +operating systems (see system documentation for details, these are +frequently called "ip aliases", and the "ifconfig" command +is most commonly used to set them up). + +

    How to set up Apache

    +There are two ways of configuring apache to support multiple hosts. +Either by running a separate httpd daemon for each hostname, or by running a +single daemon which supports all the virtual hosts. +

    +Use multiple daemons when: +

      +
    • There are security partitioning issues, such as company1 does not want + anyone at company2 to be able to read their data except via the web. + In this case you would need two daemons, each running with different + User, + Group, + Listen, and + ServerRoot settings. +
    • You can afford the memory and + file descriptor requirements of + listening to every IP alias on the machine. It's only possible to + Listen + to the "wildcard" address, or to specific addresses. So if you have + a need to listen to a specific address for whatever reason, then you + will need to listen to all specific addresses. (Although one httpd + could listen to N-1 of the addresses, and another could listen to + the remaining address.) +
    +Use a single daemon when: +
      +
    • Sharing of the httpd configuration between virtual hosts is acceptable. +
    • The machine services a large number of requests, and so the performance + loss in running separate daemons may be significant. +
    + +

    Setting up multiple daemons

    +Create a separate httpd installation for each virtual host. +For each installation, use the +Listen directive in the configuration +file to select which IP address (or virtual host) that daemon services. +e.g. +
    +    Listen www.smallco.com:80
    +
    +It is recommended that you use an IP address instead of a hostname +(see DNS caveats). + +

    Setting up a single daemon with virtual hosts

    +For this case, a single httpd will service requests for the main server +and all the virtual hosts. +The VirtualHost directive in the + configuration file is used to set the values of +ServerAdmin, +ServerName, +DocumentRoot, +ErrorLog and +TransferLog or +CustomLog +configuration directives to different values for each virtual host. +e.g. +
    +    <VirtualHost www.smallco.com>
    +    ServerAdmin webmaster@mail.smallco.com
    +    DocumentRoot /groups/smallco/www
    +    ServerName www.smallco.com
    +    ErrorLog /groups/smallco/logs/error_log
    +    TransferLog /groups/smallco/logs/access_log
    +    </VirtualHost>
    +
    +    <VirtualHost www.baygroup.org>
    +    ServerAdmin webmaster@mail.baygroup.org
    +    DocumentRoot /groups/baygroup/www
    +    ServerName www.baygroup.org
    +    ErrorLog /groups/baygroup/logs/error_log
    +    TransferLog /groups/baygroup/logs/access_log
    +    </VirtualHost>
    +
    + +It is recommended that you use an IP address instead of a hostname +(see DNS caveats). + +

    + +Almost any configuration directive can be put +in the VirtualHost directive, with the exception of +ServerType, +StartServers, +MaxSpareServers, +MinSpareServers, +MaxRequestsPerChild, +BindAddress, +Listen, +PidFile, +TypesConfig, +ServerRoot and +NameVirtualHost. +

    +User and +Group may be used inside a VirtualHost +directive if the suEXEC wrapper is used. +

    + +SECURITY: When specifying where to write log files, be aware +of some security risks which are present if anyone other than the +user that starts Apache has write access to the directory where they +are written. See the security +tips document for details. +

    + + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/name-based.html b/APACHE_1_3b7/htdocs/manual/vhosts/name-based.html new file mode 100644 index 0000000000..1a86a32f70 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/name-based.html @@ -0,0 +1,146 @@ + + +Apache name-based Virtual Hosts + + + + + +

    Apache name-based Virtual Host Support

    + +See Also: +IP-based Virtual Host Support + +
    + +

    Name-based vs. IP-based virtual hosts

    + +

    While the approach with IP-based virtual hosts works very well, +it is not the most elegant solution, because a dedicated IP address +is needed for every virtual host and it is hard to implement on some +machines. The HTTP/1.1 protocol contains a method for the +server to identify what name it is being addressed as. Apache 1.1 and +later support this approach as well as the traditional +IP-address-per-hostname method.

    + +

    The benefits of using the new name-based virtual host support is a +practically unlimited number of servers, ease of configuration and use, and +requires no additional hardware or software. +The main disadvantage is that the client must support this part of the +protocol. The latest versions of most browsers do, but there are still +old browsers in use who do not. This can cause problems, although a possible +solution is addressed below.

    + +

    Using non-IP Virtual Hosts

    + +

    Using the new virtual hosts is quite easy, and superficially looks +like the old method. You simply add to one of the Apache configuration +files (most likely httpd.conf or srm.conf) +code similar to the following:

    +
    +    NameVirtualHost 111.22.33.44
    +
    +    <VirtualHost 111.22.33.44>
    +    ServerName www.domain.tld
    +    DocumentRoot /web/domain
    +    </VirtualHost>
    +
    + +

    The notable difference between IP-based and name-based virtual host +configuration is the +NameVirtualHost +directive which specifies an IP address that should be used as a target for +name-based virtual hosts. + +

    Of course, any additional directives can (and should) be placed +into the <VirtualHost> section. To make this work, +all that is needed is to make sure that the name +www.domain.tld points to the IP address +111.22.33.44

    + +

    Note: When you specify an IP address in a NameVirtualHost +directive then requests to that IP address will only ever be served +by matching <VirtualHost>s. The "main server" will never +be served from the specified IP address. + +

    Additionally, many servers may wish to be accessible by more than +one name. For example, the example server might want to be accessible +as domain.tld, or www2.domain.tld, assuming +the IP addresses pointed to the same server. In fact, one might want it +so that all addresses at domain.tld were picked up by the +server. This is possible with the +ServerAlias +directive, placed inside the <VirtualHost> section. For +example:

    + +
    +    ServerAlias domain.tld *.domain.tld
    +
    + +

    Note that you can use * and ? as wild-card +characters.

    + +

    You also might need ServerAlias if you are +serving local users who do not always include the domain name. +For example, if local users are +familiar with typing "www" or "www.foobar" then you will need to add +ServerAlias www www.foobar. It isn't possible for the +server to know what domain the client uses for their name resolution +because the client doesn't provide that information in the request.

    + +

    Compatibility with Older Browsers

    + +

    As mentioned earlier, there are still some clients in use who +do not send the required data for the name-based virtual hosts to work +properly. These clients will always be sent the pages from the +primary name-based virtual host (the first virtual host +appearing in the configuration file for a specific IP address).

    + +

    There is a possible workaround with the +ServerPath +directive, albeit a slightly cumbersome one:

    + +

    Example configuration: + +

    +    NameVirtualHost 111.22.33.44
    +
    +    <VirtualHost 111.22.33.44>
    +    ServerName www.domain.tld
    +    ServerPath /domain
    +    DocumentRoot /web/domain
    +    </VirtualHost>
    +
    + +

    What does this mean? It means that a request for any URI beginning +with "/domain" will be served from the virtual host +www.domain.tld This means that the pages can be accessed as +http://www.domain.tld/domain/ for all clients, although +clients sending a Host: header can also access it as +http://www.domain.tld/.

    + +

    In order to make this work, put a link on your primary virtual host's page +to http://www.domain.tld/domain/ +Then, in the virtual host's pages, be sure to use either purely +relative links (e.g. "file.html" or +"../icons/image.gif" or links containing the prefacing +/domain/ +(e.g. "http://www.domain.tld/domain/misc/file.html" or +"/domain/misc/file.html").

    + +

    This requires a bit of +discipline, but adherence to these guidelines will, for the most part, +ensure that your pages will work with all browsers, new and old.

    + +

    See also: ServerPath configuration +example

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/vhosts-in-depth.html b/APACHE_1_3b7/htdocs/manual/vhosts/vhosts-in-depth.html new file mode 100644 index 0000000000..e262cb3556 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/vhosts-in-depth.html @@ -0,0 +1,396 @@ + + +An In-Depth Discussion of VirtualHost Matching + + + + + +

    An In-Depth Discussion of VirtualHost Matching

    + +

    This is a very rough document that was probably out of date the moment +it was written. It attempts to explain exactly what the code does when +deciding what virtual host to serve a hit from. It's provided on the +assumption that something is better than nothing. The server version +under discussion is Apache 1.2. + +

    If you just want to "make it work" without understanding +how, there's a What Works section at the bottom. + +

    Config File Parsing

    + +

    There is a main_server which consists of all the definitions appearing +outside of VirtualHost sections. There are virtual servers, +called vhosts, which are defined by +VirtualHost +sections. + +

    The directives +Port, +ServerName, +ServerPath, +and +ServerAlias +can appear anywhere within the definition of +a server. However, each appearance overrides the previous appearance +(within that server). + +

    The default value of the Port field for main_server +is 80. The main_server has no default ServerName, +ServerPath, or ServerAlias. + +

    In the absence of any +Listen +directives, the (final if there +are multiple) Port directive in the main_server indicates +which port httpd will listen on. + +

    The Port and ServerName directives for +any server main or virtual are used when generating URLs such as during +redirects. + +

    Each address appearing in the VirtualHost directive +can have an optional port. If the port is unspecified it defaults to +the value of the main_server's most recent Port statement. +The special port * indicates a wildcard that matches any port. +Collectively the entire set of addresses (including multiple +A record +results from DNS lookups) are called the vhost's address set. + +

    The magic _default_ address has significance during +the matching algorithm. It essentially matches any unspecified address. + +

    After parsing the VirtualHost directive, the vhost server +is given a default Port equal to the port assigned to the +first name in its VirtualHost directive. The complete +list of names in the VirtualHost directive are treated +just like a ServerAlias (but are not overridden by any +ServerAlias statement). Note that subsequent Port +statements for this vhost will not affect the ports assigned in the +address set. + +

    +All vhosts are stored in a list which is in the reverse order that +they appeared in the config file. For example, if the config file is: + +

    +    <VirtualHost A>
    +    ...
    +    </VirtualHost>
    +
    +    <VirtualHost B>
    +    ...
    +    </VirtualHost>
    +
    +    <VirtualHost C>
    +    ...
    +    </VirtualHost>
    +
    + +Then the list will be ordered: main_server, C, B, A. Keep this in mind. + +

    +After parsing has completed, the list of servers is scanned, and various +merges and default values are set. In particular: + +

      +
    1. If a vhost has no + ServerAdmin, + ResourceConfig, + AccessConfig, + Timeout, + KeepAliveTimeout, + KeepAlive, + MaxKeepAliveRequests, + or + SendBufferSize + directive then the respective value is + inherited from the main_server. (That is, inherited from whatever + the final setting of that value is in the main_server.) + +
    2. The "lookup defaults" that define the default directory + permissions + for a vhost are merged with those of the main server. This includes + any per-directory configuration information for any module. + +
    3. The per-server configs for each module from the main_server are + merged into the vhost server. +
    + +Essentially, the main_server is treated as "defaults" or a +"base" on +which to build each vhost. But the positioning of these main_server +definitions in the config file is largely irrelevant -- the entire +config of the main_server has been parsed when this final merging occurs. +So even if a main_server definition appears after a vhost definition +it might affect the vhost definition. + +

    If the main_server has no ServerName at this point, +then the hostname of the machine that httpd is running on is used +instead. We will call the main_server address set those IP +addresses returned by a DNS lookup on the ServerName of +the main_server. + +

    Now a pass is made through the vhosts to fill in any missing +ServerName fields and to classify the vhost as either +an IP-based vhost or a name-based vhost. A vhost is +considered a name-based vhost if any of its address set overlaps the +main_server (the port associated with each address must match the +main_server's Port). Otherwise it is considered an IP-based +vhost. + +

    For any undefined ServerName fields, a name-based vhost +defaults to the address given first in the VirtualHost +statement defining the vhost. Any vhost that includes the magic +_default_ wildcard is given the same ServerName as +the main_server. Otherwise the vhost (which is necessarily an IP-based +vhost) is given a ServerName based on the result of a reverse +DNS lookup on the first address given in the VirtualHost +statement. + +

    + +

    Vhost Matching

    + + +

    Apache 1.3 differs from what is documented +here, and documentation still has to be written. + +

    +The server determines which vhost to use for a request as follows: + +

    find_virtual_server: When the connection is first made +by the client, the local IP address (the IP address to which the client +connected) is looked up in the server list. A vhost is matched if it +is an IP-based vhost, the IP address matches and the port matches +(taking into account wildcards). + +

    If no vhosts are matched then the last occurrence, if it appears, +of a _default_ address (which if you recall the ordering of the +server list mentioned above means that this would be the first occurrence +of _default_ in the config file) is matched. + +

    In any event, if nothing above has matched, then the main_server is +matched. + +

    The vhost resulting from the above search is stored with data +about the connection. We'll call this the connection vhost. +The connection vhost is constant over all requests in a particular TCP/IP +session -- that is, over all requests in a KeepAlive/persistent session. + +

    For each request made on the connection the following sequence of +events further determines the actual vhost that will be used to serve +the request. + +

    check_fulluri: If the requestURI is an absoluteURI, that +is it includes http://hostname/, then an attempt is made to +determine if the hostname's address (and optional port) match that of +the connection vhost. If it does then the hostname portion of the URI +is saved as the request_hostname. If it does not match, then the +URI remains untouched. Note: to achieve this address +comparison, +the hostname supplied goes through a DNS lookup unless it matches the +ServerName or the local IP address of the client's socket. + +

    parse_uri: If the URI begins with a protocol +(i.e., http:, ftp:) then the request is +considered a proxy request. Note that even though we may have stripped +an http://hostname/ in the previous step, this could still +be a proxy request. + +

    read_request: If the request does not have a hostname +from the earlier step, then any Host: header sent by the +client is used as the request hostname. + +

    check_hostalias: If the request now has a hostname, +then an attempt is made to match for this hostname. The first step +of this match is to compare any port, if one was given in the request, +against the Port field of the connection vhost. If there's +a mismatch then the vhost used for the request is the connection vhost. +(This is a bug, see observations.) + +

    +If the port matches, then httpd scans the list of vhosts starting with +the next server after the connection vhost. This scan does not +stop if there are any matches, it goes through all possible vhosts, +and in the end uses the last match it found. The comparisons performed +are as follows: + +

      +
    • Compare the request hostname:port with the vhost + ServerName and Port. + +
    • Compare the request hostname against any and all addresses given in + the VirtualHost directive for this vhost. + +
    • Compare the request hostname against the ServerAlias + given for the vhost. +
    + +

    +check_serverpath: If the request has no hostname +(back up a few paragraphs) then a scan similar to the one +in check_hostalias is performed to match any +ServerPath directives given in the vhosts. Note that the +last match is used regardless (again consider the ordering of +the virtual hosts). + +

    Observations

    + +
      + +
    • It is difficult to define an IP-based vhost for the machine's + "main IP address". You essentially have to create a bogus + ServerName for the main_server that does not match the + machine's IPs. +

      + +

    • During the scans in both check_hostalias and + check_serverpath no check is made that the vhost being + scanned is actually a name-based vhost. This means, for example, that + it's possible to match an IP-based vhost through another address. But + because the scan starts in the vhost list at the first vhost that + matched the local IP address of the connection, not all IP-based vhosts + can be matched. +

      + Consider the config file above with three vhosts A, B, C. Suppose + that B is a named-based vhost, and A and C are IP-based vhosts. If + a request comes in on B or C's address containing a header + "Host: A" then + it will be served from A's config. If a request comes in on A's + address then it will always be served from A's config regardless of + any Host: header. +

      + +
    • Unless you have a _default_ vhost, + it doesn't matter if you mix name-based vhosts in amongst IP-based + vhosts. During the find_virtual_server phase above no + named-based vhost will be matched, so the main_server will remain the + connection vhost. Then scans will cover all vhosts in the vhost list. +

      + If you do have a _default_ vhost, then you cannot place + named-based vhosts after it in the config. This is because on any + connection to the main server IPs the connection vhost will always be + the _default_ vhost since none of the name-based are + considered during find_virtual_server. +

      + +
    • You should never specify DNS names in VirtualHost + directives because it will force your server to rely on DNS to boot. + Furthermore it poses a security threat if you do not control the + DNS for all the domains listed. + There's more information + available on this and the next two topics. +

      + +

    • ServerName should always be set for each vhost. Otherwise + A DNS lookup is required for each vhost. +

      + +

    • A DNS lookup is always required for the main_server's + ServerName (or to generate that if it isn't specified + in the config). +

      + +

    • If a ServerPath directive exists which is a prefix of + another ServerPath directive that appears later in + the configuration file, then the former will always be matched + and the latter will never be matched. (That is assuming that no + Host header was available to disambiguate the two.) +

      + +

    • If a vhost that would otherwise be a name-vhost includes a + Port statement that doesn't match the main_server + Port then it will be considered an IP-based vhost. + Then find_virtual_server will match it (because + the ports associated with each address in the address set default + to the port of the main_server) as the connection vhost. Then + check_hostalias will refuse to check any other name-based + vhost because of the port mismatch. The result is that the vhost + will steal all hits going to the main_server address. +

      + +

    • If two IP-based vhosts have an address in common, the vhost appearing + later in the file is always matched. Such a thing might happen + inadvertently. If the config has name-based vhosts and for some reason + the main_server ServerName resolves to the wrong address + then all the name-based vhosts will be parsed as ip-based vhosts. + Then the last of them will steal all the hits. +

      + +

    • The last name-based vhost in the config is always matched for any hit + which doesn't match one of the other name-based vhosts. + +
    + +

    What Works

    + +

    In addition to the tips on the DNS +Issues page, here are some further tips: + +

      + +
    • Place all main_server definitions before any VirtualHost definitions. +(This is to aid the readability of the configuration -- the post-config +merging process makes it non-obvious that definitions mixed in around +virtualhosts might affect all virtualhosts.) +

      + +

    • Arrange your VirtualHosts such +that all name-based virtual hosts come first, followed by IP-based +virtual hosts, followed by any _default_ virtual host +

      + +

    • Avoid ServerPaths which are prefixes of other +ServerPaths. If you cannot avoid this then you have to +ensure that the longer (more specific) prefix vhost appears earlier in +the configuration file than the shorter (less specific) prefix +(i.e., "ServerPath /abc" should appear after +"ServerPath /abcdef"). +

      + +

    • Do not use port-based vhosts in the same server as +name-based vhosts. A loose definition for port-based is a vhost which +is determined by the port on the server (i.e., one server with +ports 8000, 8080, and 80 - all of which have different configurations). +

      + +

    + + + + diff --git a/APACHE_1_3b7/htdocs/manual/vhosts/virtual-host.html b/APACHE_1_3b7/htdocs/manual/vhosts/virtual-host.html new file mode 100644 index 0000000000..fd3dcb2181 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/vhosts/virtual-host.html @@ -0,0 +1,207 @@ + + + +Apache Server Virtual Host Support + + + + + +

    Virtual Host Support

    + +See Also: +Non-IP based virtual hosts + +

    What are virtual hosts?

    +This is the ability of a single machine to be a web server for multiple +domains. For example, an Internet service provider might have a machine +called www.serve.com which provides Web space for several +organizations including, say, smallco and baygroup. +Ordinarily, these groups would be given parts of the Web tree on www.serve.com. +So smallco's home page would have the URL +
    +http://www.serve.com/smallco/ +
    +and baygroup's home page would have the URL +
    +http://www.serve.com/baygroup/ +
    +

    +For esthetic reasons, however, both organizations would rather their home +pages appeared under their own names rather than that of the service +provider's; but they do not want to set up their own Internet links and +servers. +

    +Virtual hosts are the solution to this problem. smallco and baygroup would +have their own Internet name registrations, www.smallco.com and +www.baygroup.org respectively. These hostnames would both +correspond to the service provider's machine (www.serve.com). Thus +smallco's home page would now have the URL +

    +http://www.smallco.com/ +
    +and baygroup's home page would would have the URL +
    +http://www.baygroup.org/ +
    + +

    System requirements

    +Due to limitations in the HTTP/1.0 protocol, the web server must have a +different IP address for each virtual host. This can be achieved +by the machine having several physical network connections, or by use +of a virtual interface on some operating +systems. + +

    How to set up Apache

    +There are two ways of configuring apache to support multiple hosts. +Either by running a separate httpd daemon for each hostname, or by running a +single daemon which supports all the virtual hosts. +

    +Use multiple daemons when: +

      +
    • The different virtual hosts need very different httpd configurations, such + as different values for: ServerType, + User, + Group, + TypesConfig or + ServerRoot. +
    • The machine does not process a very high request rate. +
    +Use a single daemon when: +
      +
    • Sharing of the httpd configuration between virtual hosts is acceptable. +
    • The machine services a large number of requests, and so the performance + loss in running separate daemons may be significant. +
    + +

    Setting up multiple daemons

    +Create a separate httpd installation for each virtual host. +For each installation, use the +BindAddress directive in the +configuration +file to select which IP address (or virtual host) that daemon services. +E.g., +
    BindAddress www.smallco.com
    +This hostname can also be given as an IP address. + +

    Setting up a single daemon

    +For this case, a single httpd will service requests for all the virtual hosts. +The VirtualHost directive in the + configuration file is used to set the values of +ServerAdmin, +ServerName, +DocumentRoot, +ErrorLog and +TransferLog configuration +directives to different values for each virtual host. +E.g., +
    +<VirtualHost www.smallco.com>
    +ServerAdmin webmaster@mail.smallco.com
    +DocumentRoot /groups/smallco/www
    +ServerName www.smallco.com
    +ErrorLog /groups/smallco/logs/error_log
    +TransferLog /groups/smallco/logs/access_log
    +</VirtualHost>
    +
    +<VirtualHost www.baygroup.org>
    +ServerAdmin webmaster@mail.baygroup.org
    +DocumentRoot /groups/baygroup/www
    +ServerName www.baygroup.org
    +ErrorLog /groups/baygroup/logs/error_log
    +TransferLog /groups/baygroup/logs/access_log
    +</VirtualHost>
    +
    + +This VirtualHost hostnames can also be given as IP addresses. + +

    + +Almost ANY configuration directive can be put +in the VirtualHost directive, with the exception of +ServerType, +User, +Group, +StartServers, +MaxSpareServers, +MinSpareServers, +MaxRequestsPerChild, +BindAddress, +PidFile, +TypesConfig, and +ServerRoot. + +

    + +SECURITY: When specifying where to write log files, be aware +of some security risks which are present if anyone other than the +user that starts Apache has write access to the directory where they +are written. See the security +tips document for details. + +

    + +

    File Handle/Resource Limits:

    +When using a large number of Virtual Hosts, Apache may run out of available +file descriptors if each Virtual Host specifies different log files. +The total number of file descriptors used by Apache is one for each distinct +error log file, one for every other log file directive, plus 10-20 for +internal use. Unix operating systems limit the number of file descriptors that +may be used by a process; the limit is typically 64, and may usually be +increased up to a large hard-limit. +

    +Although Apache attempts to increase the limit as required, this +may not work if: +

      +
    1. Your system does not provide the setrlimit() system call. +
    2. The setrlimit(RLIMIT_NOFILE) call does not function on your system + (such as Solaris 2.3) +
    3. The number of file descriptors required exceeds the hard limit. +
    4. Your system imposes other limits on file descriptors, such as a limit +on stdio streams only using file descriptors below 256. (Solaris 2) +
    + +In the event of problems you can: +
      +
    • Reduce the number of log files; don't specify log files in the VirtualHost +sections, but only log to the main log files. +
    • If you system falls into 1 or 2 (above), then increase the file descriptor +limit before starting Apache, using a script like +
      +#!/bin/sh
      +ulimit -S -n 100
      +exec httpd
      +
    + +The have been reports that Apache may start running out of resources allocated +for the root process. This will exhibit itself as errors in the error log like +"unable to fork". There are two ways you can bump this up: + +
      +
    1. Have a csh script wrapper around httpd which sets the +"rlimit" to some large number, like 512. +
    2. Edit http_main.c to add calls to setrlimit() from main(), along the lines +of +
      +        struct rlimit rlp;
      +
      +        rlp.rlim_cur = rlp.rlim_max = 512;
      +        if (setrlimit(RLIMIT_NPROC, &rlp)) {
      +            fprintf(stderr, "setrlimit(RLIMIT_NPROC) failed.\n");
      +            exit(1);
      +        }
      +
      +(thanks to "Aaron Gifford <agifford@InfoWest.COM>" for the patch) +
    + +The latter will probably manifest itself in a later version of Apache. + + + + diff --git a/APACHE_1_3b7/htdocs/manual/windows.html b/APACHE_1_3b7/htdocs/manual/windows.html new file mode 100644 index 0000000000..a1499d8ff3 --- /dev/null +++ b/APACHE_1_3b7/htdocs/manual/windows.html @@ -0,0 +1,372 @@ + + + +Using Apache with Microsoft Windows + + + + + + +

    Using Apache With Microsoft Windows

    + +

    This document explains how to install, configure and run + Apache 1.3b6 (or later) under Microsoft Windows. Please note that at + this time, Windows support is entirely experimental, and is + recommended only for experienced users. The Apache Group does not + guarantee that this software will work as documented, or even at + all. If you find any bugs, or wish to contribute in other ways, please + use our bug reporting + page.

    + +

    Warning: Apache on NT has not yet been optimized for performance. +Apache still performs best, and is most reliable on Unix platforms. Over +time we will improve NT performance. Folks doing comparative reviews +of webserver performance are asked to compare against Apache +on a Unix platform such as Solaris, FreeBSD, or Linux.

    + +

    + +Most of this document assumes that you are installing Windows from a +binary distribution. If you want to compile Apache yourself (possibly +to help with development, or to track down bugs), see the section on +Compiling Apache for Windows below. + +


    + + + +
    + +

    Requirements

    + +

    Apache 1.3b6 requires the following:

    + +
      +
    • Microsoft Windows NT 4.0*, or Windows 95. +
    • An Intel-based PC-compatible capable of running above OS (exact + requirements unknown) with a connection to a TCP/IP network. +
    + +

    * Apache may run with Windows NT 3.5.1, but + has not been tested.

    + +

    If running on Windows 95, using the "Winsock2" upgrade is recommended + but may not be necessary. If running on NT 4.0, installing Service Pack 2 + is recommended.

    + +

    Downloading Apache for Windows

    + +

    Information on the latest version of Apache can be found on the +Apache web server at http://www.apache.org/. This will +list the current release, any more recent alpha or beta-test release, +together with details of mirror web and anonymous ftp sites.

    + +

    + +You should download the version of Apache for Windows with the +.exe extension. This is a single file containing Apache, +ready to install and run. There may also be a .zip file +containing the source code, to compile Apache yourself. + +

    Installing Apache for Windows

    + +Run the Apache .exe file you downloaded above. This will +ask for: + +
      + +
    • the directory to install Apache into (the default is + \Program Files\Apache Group\Apache although you can + change this to any other directory) + +
    • the start menu name (default is "Apache Web Server") + +
    • the installation type. The "Typical" option installs + everything except the source code. The "Minimum" option does not + install the manuals or source code. Choose the "Custom" install if + you want to install the source code. + +
    + +

    + +Important note for 1.3b6 installs: the installer for +1.3b6 will overwrite any existing httpd.conf, +access.conf, srm.conf or +mime.types files in the conf, and will also +overwrite your index.html file in the htdocs +directory. You should copy this files or directories before installing +Apache 1.3b6, or install into a new directory. + +

    + +After installing Apache, you should edit the configuration files in +the conf directory as required. These files will be +configured during the install ready for Apache to be run from the +directory where it was installed, with the documents served from the +subdirectory htdocs. There are lots of other options +which should be set before you start really using Apache. However to +get started the files should work as installed. + +

    Running Apache for Windows

    + +There are two ways you can run Apache: + +
      +
    • As a "service" (available on NT only). This is the best option if + you want Apache to automatically start when you machine boots, and to + keep Apache running when you log-off. + +
    • From a console window. This is the only option available for + Windows 95 users. +
    + +To start Apache as a service, you first need to install it as a +service. Run the "Install Apache as Service" option from the Start +menu. Once this is done you can start Apache by opening the Services +window (in the Control Panel), selecting Apache, then clicking on +Start. Apache will now be running in the background. You can later +stop Apache by clicking on Stop. As an alternative to using the +Services window, you can start and stop Apache from the control line +with + +
    +  NET START APACHE
    +  NET STOP APACHE
    +
    + +To run Apache from a console window, select the "Apache Server" option +from the Start menu. This will open a console window and start Apache +running inside it. The window will remain active until you stop +Apache. To stop Apache running, press Control-C within the console +window. + +

    + +After starting Apache running (either in a console window or as a +service) if will be listening to port 80 (unless you changed the +Port, Listen or BindAddress +directives in the configuration files). To connect to the server and +access the default page, launch a browser and enter this URL: + +

    +  http://localhost/
    +
    + +This should respond with a welcome page, and a link to the Apache +manual. If nothing happens or you get an error, look in the +error_log file in the logs directory. + +

    + +Once your basic installation is working, you should configure it +properly by editing the files in the conf directory. + +

    Configuring Apache for Windows

    + +Apache is configured by files in the conf +directory. These are the same as files used to configure the Unix +version, but there are a few different directives for Apache on +Windows. See the Apache documentation for all the +available directives. + +

    + +The main differences in Apache for Windows are: + +

      +
    • Because Apache for Windows is multithreaded, it does not use a + separate process for each request, as Apache does with + Unix. Instead there are usually only two Apache processes running: + a parent process, and a child which handles the requests. Within + the child each request is handled by a separate thread. +

      + + So the "process"-management directives are different: +

      MaxRequestsPerChild + - Like the Unix directive, this controls how many requests a + process will serve before exiting. However, unlike Unix, a + process serves all the requests at once, not just one, so if + this is set, it is recommended that a very high number is + used. The recommended default, MaxRequestsPerChild + 0, does not cause the process to ever exit. +

      ThreadsPerChild - + This directive is new, and tells the server how many threads it + should use. This is the maximum number of connections the server + can handle at once; be sure and set this number high enough for + your site if you get a lot of hits. The recommended default is + ThreadsPerChild 50.

      +
    • The directives that accept filenames as arguments now must use + Windows filenames instead of Unix ones. However, because Apache + uses Unix-style names internally, you must use forward slashes, not + backslashes. Drive letters can be used; if omitted, the drive with + the Apache executable will be assumed.

      +
    • Apache for Windows contains the ability to load modules at runtime, + without recompiling the server. If Apache is compiled normally, it + will install a number of optional modules in the + \Apache\modules directory. To activate these, or other + modules, the new LoadModule + directive must be used. For example, to active the status module, + use the following (in addition to the status-activating directives + in access.conf):

      +
      +    LoadModule status_module modules/ApacheModuleStatus.dll
      +
      +

      Information on creating loadable + modules is also available.

      +
    • Apache can also load ISAPI Extensions (i.e., Internet Server + Applications), such as those used by Microsoft's IIS, and other + Windows servers. More information + is available. +

    + +

    Running Apache for Windows from the Command Line

    + +The Start menu icons and the NT Service manager can provide an simple +interafce for administering Apache. But in some cases it is easier to +work from the command line. + +

    + +When working with Apache it is important to know how it will find the +configuration files. During installation, a registry key will have +been installed called: + +

    +  HKEY_LOCAL_MACHINE\Software\Apache Group\Apache\1.3 beta\ServerRoot
    +
    + +The value of this key is the "ServerRoot" directory, containing the +conf directory. When Apache starts it will read the +httpd.conf file from this directory. If this file +contains a ServerRoot directive which is different from +the directory obtained from the registry key above, Apache will forget +the registry key and use the directory from the configuration file. +If you copy the Apache directory or configuration files to a new +location it is vital that you update the ServerRoot +directory in the httpd.conf file to the new location. + +

    + +To run Apache from the command line as a console application, use the +following command: + +

    +    apache -s
    +
    + +(The -s option is not required by Windows 95, but on Windows NT it +prevents Apache waiting to see if Apache is running as a +service). Apache will execute, and will remain running until it +is stopped by pressing control-C. + +

    + +To install Apache as a Windows NT service, use the following: + +

    +    apache -i
    +
    + +and to remove the Apache service, use + +
    +    apache -u
    +
    + +If you want to run an installation of Apache in a directory other than +the one in the registry key as above, use the -f +command-line to specify the path to the httpd.conf file, +or the -d option to specify the server root +directory. These options can be used with any of the other flags as +listed above. Again note that once Apache has read the +httpd.conf file it will then start using the directory +given on the ServerRoot directive line instead of the -f +or -d command line argument. + +

    Compiling Apache for Windows

    + +

    Compiling Apache requires Microsoft Visual C++ 5.0 to be properly + installed. It is easiest to compile with the command-line tools + (nmake, etc...). Consult the VC++ manual to determine how to install + them.

    + +

    First, unpack the Apache distribution into an appropriate + directory. Open a command-line prompt, and change to the + src subdirectory of the Apache distribution.

    + +

    The master Apache makefile instructions are contained in the + Makefile.nt file. To compile Apache, simply use one of + the following commands: +

      +
    • nmake /f Makefile.nt _apacher (release build) +
    • nmake /f Makefile.nt _apached (debug build) +
    + +

    These will both compile Apache. The latter will include debugging + information in the resulting files, making it easier to find bugs and + track down problems.

    + +

    Apache can also be compiled using VC++'s Visual Studio development + environment. Although compiling Apache in this manner is not as simple, + it makes it possible to easily modify the Apache source, or to compile + Apache if the command-line tools are not installed.

    + +

    Project files (.DSP) are included for each of the + portions of Apache. The three projects that are necessary for + Apache to run are Apache.dsp, ap/ap.dsp, + regex/regex.dsp, ApacheCore.dsp and + os/win32/ApacheOS.dsp. The src/win32 + subdirectory contains project files for the optional modules (see + below).

    + +

    Once Apache has been compiled, it needs to be installed in its server + root directory. The default is the \Apache + directory, on the current hard drive.

    + +

    To install the files into the \Apache directory + automatically, use one the following nmake commands (see above):

    +
      +
    • nmake /f Makefile.nt installr INSTDIR=dir + (for release build) +
    • nmake /f Makefile.nt installd INSTDIR=dir + (for debug build) +
    + +The dir argument to INSTDIR gives the installation directory. The can +be omitted if Apache is to be installed into \Apache. + +

    This will install the following:

    + +
      +
    • dir\Apache.exe - Apache executable +
    • dir\ApacheCore.dll - Main Apache shared library +
    • dir\modules\ApacheModule*.dll - Optional Apache + modules (7 files) +
    • dir\conf - Empty configuration directory +
    • dir\logs - Empty logging directory +
    + +

    If you do not have nmake, or wish to install in a different directory, + be sure to use a similar naming scheme.

    + + + + diff --git a/APACHE_1_3b7/icons/README b/APACHE_1_3b7/icons/README new file mode 100644 index 0000000000..a1fc5a5a9c --- /dev/null +++ b/APACHE_1_3b7/icons/README @@ -0,0 +1,161 @@ +Public Domain Icons + + These icons were originally made for Mosaic for X and have been + included in the NCSA httpd and Apache server distributions in the + past. They are in the public domain and may be freely included in any + application. The originals were done by Kevin Hughes (kevinh@eit.com). + + Many thanks to Andy Polyakov for tuning the icon colors and adding a + few new images. If you'd like to contribute additions or ideas to + this set, please let me know. + + The distribution site for these icons is at: + + http://www.eit.com/goodies/www.icons/ + + Kevin Hughes + September 11, 1995 + + +Suggested Uses + +The following are a few suggestions, to serve as a starting point for ideas. +Please feel free to tweak and rename the icons as you like. + + a.gif + This might be used to represent PostScript or text layout + languages. + + alert.black.gif, alert.red.gif + These can be used to highlight any important items, such as a + README file in a directory. + + back.gif, forward.gif + These can be used as links to go to previous and next areas. + + ball.gray.gif, ball.red.gif + These might be used as bullets. + + binary.gif + This can be used to represent binary files. + + binhex.gif + This can represent BinHex-encoded data. + + blank.gif + This can be used as a placeholder or a spacing element. + + bomb.gif + This can be used to repreesnt core files. + + box1.gif, box2.gif + These icons can be used to represent generic 3D applications and + related files. + + broken.gif + This can represent corrupted data. + + burst.gif + This can call attention to new and important items. + + c.gif + This might represent C source code. + + comp.blue.gif, comp.red.gif + These little computer icons can stand for telnet or FTP + sessions. + + compressed.gif + This may represent compressed data. + + continued.gif + This can be a link to a continued listing of a directory. + + down.gif, up.gif, left.gif, right.gif + These can be used to scroll up, down, left and right in a + listing or may be used to denote items in an outline. + + dvi.gif + This can represent DVI files. + + f.gif + This might represent FORTRAN or Forth source code. + + folder.gif, folder.open.gif, folder.sec.gif + The folder can represent directories. There is also a version + that can represent secure directories or directories that cannot + be viewed. + + generic.gif, generic.sec.gif, generic.red.gif + These can represent generic files, secure files, and important + files, respectively. + + hand.right.gif, hand.up.gif + These can point out important items (pun intended). + + image1.gif, image2.gif, image3.gif + These can represent image formats of various types. + + index.gif + This might represent a WAIS index or search facility. + + layout.gif + This might represent files and formats that contain graphics as + well as text layout, such as HTML and PDF files. + + link.gif + This might represent files that are symbolic links. + + movie.gif + This can represent various movie formats. + + p.gif + This may stand for Perl or Python source code. + + pie0.gif ... pie8.gif + These icons can be used in applications where a list of + documents is returned from a search. The little pie chart images + can denote how relevant the documents may be to your search + query. + + patch.gif + This may stand for patches and diff files. + + portal.gif + This might be a link to an online service or a 3D world. + + ps.gif, quill.gif + These may represent PostScript files. + + screw1.gif, screw2.gif + These may represent CAD or engineering data and formats. + + script.gif + This can represent any of various interpreted languages, such as + Perl, python, TCL, and shell scripts, as well as server + configuration files. + + sound1.gif, sound2.gif + These can represent sound files. + + sphere1.gif, sphere2.gif + These can represent 3D worlds or rendering applications and + formats. + + tex.gif + This can represent TeX files. + + text.gif + This can represent generic (plain) text files. + + transfer.gif + This can represent FTP transfers or uploads/downloads. + + unknown.gif + This may represent a file of an unknown type. + + uuencoded.gif + This can stand for uuencoded data. + + world1.gif, world2.gif + These can represent 3D worlds or other 3D formats. diff --git a/APACHE_1_3b7/icons/a.gif b/APACHE_1_3b7/icons/a.gif new file mode 100644 index 0000000000000000000000000000000000000000..bb23d971f4ce99b43dcadc7179deab4e3f55d2fd GIT binary patch literal 246 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2nHIbDd^F&3SUp#HU#9hW!Rw()J9@9Pc4|E2W2srx z@ZjD%n_KH1+_viO4gW0IG)3`1D5IB^&A~|*Z0siQ)e*Jc?U}v(RZqm-rsn%xldEMP i9?8v^arV~QxusXc{Vzw0+BY`Y83|alcZ6{=SOWlx{aaiB literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/alert.black.gif b/APACHE_1_3b7/icons/alert.black.gif new file mode 100644 index 0000000000000000000000000000000000000000..eaecd2172a091ee2994c73f33e784e336b23b58b GIT binary patch literal 242 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2sTRBTd^F&3SUp#HU#9hW!Eiwp#*PQqrY@^+(mQa9 zIq>=_)6J=N(?l8rJU#@b9ZU?|#8k#|TH+FuDboTL$LCUaCvA&aeP+vAqk{>XuXw(F ebwjlD^Y4XGxPKmyi?175+0@L8L7oO3fUlDhC^y*iC%Jku8u-*YC%bA zZc=KIf}y3QDTCrq7DfgJW(FOg=?oy-8JM#&cJ29GAmOljuG+p#>+^!)qA83W53Y$i zRmV;6*!V8-#*VCuOa*@qH0ND;#mM2YBw&+P*rb-FJO^IOEcFdnw_3sy#i%{~=Eb~? osgHMN$4+)vHJp`EcP`!U`GY!UILM{ophO`}&oUt=FmBNTY z$`ICVA7j^+h#i;OQDc-ga!qS+8Gc0FW4f z)Bt1yAj_Q32!U{ zRIo-qQptb-t7{uBm(~px;>}n!KArWR1^>`Cf~is&A3~v0s8aF}M#nn9GGt0d7v`yb z*>S>eMWL(I627?MNllQ7BkqHq)M=1k z=&Ky&zXVh2hPE6DHG1$Mj#+!@W<|fAeonA2iB#Un#%N(&&W1dtI~9BfQ#)e2X=lF^XcGT}q=AoZ{H^5&_C+Pv zN&hQZTYONvvH2qVcG~jIh^yqZXMG0jauI~J<^%?yjPC{pb>Ylqd7Qgl5*ph^Ulf=T ztUu|ceZK)dM=IDKg~q~CZoH&Cb~-~Z=;&lvYG{6Kc>2z^;Sv327g?kssFZ=dw}0cH zdw$mEtN!A<`J8^&z3 zt~SwiD6S8)Rjrr!Kx<)&vBl1-$xbOvcBi~nxrDC!TBPace;L%k*DDqrZ4t4XvN(& zu%4H=wkn0>)>bWw*7qy^XgxfL8hEr{3=!aT@x^9eDj^ytk&Chl$kO(lBLUN|dQ6Gs zqR_gQC$$$-23%rt``_I(>C3A7dOXT9Z$frk_k~-Ys+P;@AA_2Pg%%8=^ZRrL+?~|f zW&~d`K5oo!G0s}dw|gtsI8gBY`D(2K(S?RiMa{{iIhO(d)G0SJjuwocN&dl=)Ns$! zkAoL^`msv}wXFIo9^Egsd~xDITuw=a{)ty}PeNiaZ{?=q1Ff-;&+#A?LvlJm+3a2z z0EU`idSaEFK|F|qEq^5hpn?C2d=DQ+H3YkO^OBqUex<5bLo z9(N*aTe0*iA?|UPIVvKLCc?9Ag1I16-HvOfbsA#dH4-dk3 zhnz>*3E(FdLU+yVpuPUsliM=aeNjZUS*@XX3Z53T6iR8-2uO=XFwVs0@AhefEv8q zeI*^7gje{cZVN8?oK%ZT=2#U=<_Ih7M^R~)Ja%@QBEHt-Nj+won-qIvXTfK$!wnkr z2MQ*#TaAN%Ohqz*uQYER7$<|Jgd}A|ZL~mb$%8Fh^ z{1s=ft;T@}n?u#1Sd8|0dAq@XlaA<)Sy)vu-xZB|?3vPJ`3#PxQkI=}-aLquKdtW{ zRsg5o;PBjI;EgPh^zTEWZ?enGho=a|_a2#rB5>8 zTBKlTX=%!!_>+Z^fq{`h2V@1vb_Ql|iCuU8DGPkc5-<+lz3AMXubFeq{lvP)Ggp6^Q($uOC~PM5!3Knu5hd8zzVA-2Z^g;lkQyz{qtht`EC{l FYXAcbPG|rC literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/ball.gray.gif b/APACHE_1_3b7/icons/ball.gray.gif new file mode 100644 index 0000000000000000000000000000000000000000..eb84268c4ccf0146e661f51e63fc7d958d39111f GIT binary patch literal 233 zcmZ?wbhEHb6k!l!c+9}?|Ns9pKy>EJ?%lg*&YaoN(UF#x78)9AY;4Sc4JiKe3(3eV zR!A%=Q2NWsw3(v(5*CkrD310#bD$U2a#7+72kPI#`~Yw`N*?)jcGYB&?6 zl*5^v5@j;O_zpaf^Qf7s_EE`__xyKmPTmvoe(9bH{5w=PbF!#4X}t_l`&F_3!G;Q* IP6h^R09S}j761SM literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/ball.red.gif b/APACHE_1_3b7/icons/ball.red.gif new file mode 100644 index 0000000000000000000000000000000000000000..a8425cb574b1e4250b8cd35656432245cf4b51c8 GIT binary patch literal 205 zcmZ?wbhEHb6k!l!IK;s49|&g7{BLZ0=KudR1_V(2=NFQZS*(y)RH6W+GV>HlGEx-^ zN|SOjlND0(a}zW3^c1{P%YYIdrRf=|#X1VvAYO(;YG#REa(=FkLU3w9NosCVYLSAW zrKKr@;!hSv1_ovZ9grm;+ZmW0EOy=bXK>1Mb*$?2=q7RLtBj2b0*O~xQ!1DFD^5{O pJnUyaTmRk(8|hQW8HD_tlL9-OLb*IseTr8`t-rA*Y$5}LH2|rsMHm18 literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/binary.gif b/APACHE_1_3b7/icons/binary.gif new file mode 100644 index 0000000000000000000000000000000000000000..9a15cbae04ccda7ee515f0e56360afc5a0dba7a5 GIT binary patch literal 246 zcmZ?wbhEHb6k!l!IK;s4|Ns9pKy>EJ%$YNdjg1*#K=GenNJeI{LSj*g0+7ngQz*$u zRVXM;%E?StNXgGl%*@kM@J=lQN_do}XQUSEC}e|p84jtLC3?yExjG8LsRbpexk;%- z3Wk=JrVNTdSr{1@7#VaxR)B10V9xZ|wdbROfWzv!D*Gb21Y#8#gjW{Ev9DOlxiI_H z)^#HHvm9UiDQlh^nDJt>gl6-T1rM0J@~%VW#e jit!gMUf+_g-~76GhV}Y)-JD*HO`g_*&g~t+oD9|gOVnOa literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/binhex.gif b/APACHE_1_3b7/icons/binhex.gif new file mode 100644 index 0000000000000000000000000000000000000000..62d0363108d2585b7574f1eafa0749ae48e15f5b GIT binary patch literal 246 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWsLS&DhwO0R|NR`GsU;7Aqtcl_&tI%shpX zj8uh!(xjZsWQCOc+{Da0Jq7R7GN6P8 zTBKlTX=%!!_>+Z^fq{`h2V@1vb_V85k6n8{8VES7o~yDia@YFk=4>QQyf+b%kUIiE6v`j kq<41P{%f~vu3nm((IxdxXZmdxm!@WCGePSPUrq*V0OwX&D*ylh literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/blank.gif b/APACHE_1_3b7/icons/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ccf01e1983e40365a9ab9f373b6fc497c8603cd GIT binary patch literal 148 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ pvM@3*Ff!-Xz$Dz$zw-23{>5{)-0I$ZZ_jW3Hcv(dYXE)}F?;|3 literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/bomb.gif b/APACHE_1_3b7/icons/bomb.gif new file mode 100644 index 0000000000000000000000000000000000000000..270fdb1c064a678acb8764f49dfab1e4930a437c GIT binary patch literal 308 zcmZ?wbhEHb6k!l!c+9}?9|+DEp8*nQ&g|a3d*;lU9UUEMX=$OMp~l9>3>ZN1pI=Bu zX0bwIQHcVO%FI(J$w*ZwC{4=AOjbzA&rQtC(^K$HEdxq;l%{8-7V9WvgLoMZshK5u z$@#fD3c;xbC8@bdsYMEgmX@Xria%Kx85o!tbU=22T*biBZ*bCc`Hl#c1H12gmgUBI zw%rtC;M!28($IJJckPX3ES?w2x?Bo89EJ%$YNdjg1**8Z)FBGcYhH{__jT$ShV!EGkg| zQki)QB^jv-1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz!(9+VBLGdRGBLf2?gAUMi29WIx%y|;K?))=oQ+_D9Ws|kbwV3Cb!G;~l zr6S87EaNL&_a?hVeW3t@!}Ye?nKK^#j99avpyTG(I#$(nk_Jvoof)on^{`p)&3!-P v58tszhQ3zU#BLwgx4CO~=RuzOzlQVSzZ;^Bd|G^1EJ%$YNdjg1**8Z)FBGcYhH{__jT$ShV!EGkg| zQki)QB^jv-1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz!(9+VBLGdRGBLf2?gAUMi29WIx%=I3-_IxxDa9BN8WnZTCdBN+UN;`V5 zvvyudlx5MGf7Niu+lB8<68M>}CwT0+Sa%>{VugiRTa(75mo;unPcK^%`XY`u`0=&t zU!@MXG|VX05I^^VF*R2EaBhQ*t$*G8!m22pl=_-R+Zy(Sw)W(nhPLXS$-P|O(_IV& Nt>?_0!_UcJ4FEU+X8-^I literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/broken.gif b/APACHE_1_3b7/icons/broken.gif new file mode 100644 index 0000000000000000000000000000000000000000..9f8cbe9f7604077bbd3a2bc8bc3a5bb5f569b838 GIT binary patch literal 247 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2Sr)tYd^F&3SUp#HU#9hW!Rw()J9@9Pc4`>z_|O^T zk}LelhjUMZx0Uz%<6KNN%O7PlP1)n6a$s{L_l_mk)%DU^kLsajo literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/burst.gif b/APACHE_1_3b7/icons/burst.gif new file mode 100644 index 0000000000000000000000000000000000000000..fbdcf575f78a5ebbd3eeac5bbd9f963962ab664f GIT binary patch literal 235 zcmZ?wbhEHb6k!l!IK;s49|+DEpZWiPW*S3UTAH!3F#{MV{__jT$ShV!EGkg|Qki)Q zB^jv-1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXn zDYZz!(9+VBLGdRGBLf2ygAT}iknIf2aT>es{4+SUl4tW3o}3LYCJ5%-`ZlvqY)y_i zON{zvlk8Qc_r#nUUz;+oS7*8wAfNp1ThKa>J&QI6cbF|deBP(?&CiC}j@vi=I#{!y ctx@66$5l65-@mTg36FLd3o%#&030@6>Hq)$ literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/c.gif b/APACHE_1_3b7/icons/c.gif new file mode 100644 index 0000000000000000000000000000000000000000..7555b6c164fc1b4fd61b082d8077fa9d91df56f2 GIT binary patch literal 242 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2sTRBTd^F&3SUp#HU#9hWL3V*Bp^eh6>z=a~rmo~; z@m;PwF+98fv}{9yhQgnc16&t10u@Ug6@{;Ldlgz{Obt2`rF%DR+wn(!`wtpSjoH_A d@zm!TvfmF~E%;F4@aA{Bxj;^{Ha{nWH2?tDSDF9- literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/comp.blue.gif b/APACHE_1_3b7/icons/comp.blue.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8d76a8c23f018497587e3f99b1ca6de51b3f31c GIT binary patch literal 251 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWz6d|FpC;V`F26w3!SH42u8!LNYRo6%va| z6o6D_oCMz{sEjG@SutI|Fl`#I8I43{F+7+RH9?U^n~B&57a> z9SY`avJ)3cpWb!+X3wWT_Y&^C>j_NskYN&^eSY~d0}D@y<%x+OBE#9DLr=Z++8Ul6 x7HBJQ=EA9jH5MFGT$gJ@mp5m{0_#-#wxuc*35QMb=U457e-D7YXCOLU#$QD literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/comp.gray.gif b/APACHE_1_3b7/icons/comp.gray.gif new file mode 100644 index 0000000000000000000000000000000000000000..7664cd03649021707e088ea934495978fb0d2656 GIT binary patch literal 246 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWz6de`8}~1{hHM=NFQZS*(y)RH6W+GV>Hl zGEx-^N|SOjlND0(a}zW3^c1{P%YYIdrRf=|#X1VvAYO(;YG#REa(=FkLU3w9NosCV zYLSAWrKKr@;!hSv1_nk39gr0u+ZmWMC3fBUXK*TF)m~Py1H0L0ZcY^U=uj|Uqn)@& z`t+`&H+w$)xtDP7U5{X*hYXYW?DNZyDNHgr!s_U-Hfnv#g)JxEX01=i4l~r{ICH)$ lVU2;d{qukWdt+~JZ}<_zu;TaoO4H0{QT5pN7)DM8YXGT7UX1_% literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/compressed.gif b/APACHE_1_3b7/icons/compressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..39e732739f562920d69e21b9d5f766103225471e GIT binary patch literal 1038 zcmbu8%S)7D6vm%!Ft{kRtWAqgQ<5~hoFu0y(5j?VVxWbZa?#}6Rb z^C4&mE(8ey7I`1M2JeEG;9*JiK{cogDnVhj&IhN#x!@!?SgZIT8pH*WAfQr!56}P? zAOQ@hO=)Venboj4_SAdly?75B%ShF$^D16p6ihnx&Uq)^!Jt?x>cx2xFCZgZJ=DW_ zhzF;Vnqq_|C9#;}U}{sET5N_bWHFyp6;;@N9LvZ#b)pWoE-9E4ry?rg_Jm@s!YM?- z_2>sN*-bmRKOwjwsVPQiQnHjB987IWQw!#tr5W>yb1);hAICBhaRU0vbxFabgE-Jf zI!yz}#c~?WZD}R_ASSzM2bs7qHzYO12+dAnk%NP&O=;MPteR=YeBi}sB=_T3Mgsdd z%-8tdmW)qmHpf@7+Sq7wJ@(F8V>|2!@rI@pL)%Sa4ik>0`8n`PG>cNN~PuHj#2TU&K?b$PjISFN2mlgUm*z2muv zKiQEemq|xslYK+k{%BxyxHmh}7Dc}w4}4S#{SXahUj#9ESDbc zOOHnflF24it!!Ke)S!Xtuzwj6iq1sMV&VMamBiM~1Dk->?y_AKLvKGkd3CL_zUO(} z{{Gh4ox9inc{4lTIae9-XIHj->p*v3PgZ}I-!Gd(0R3W>2Z59 z@wZv>Co5WRejm!z{yeqNojm@2_0WZ-{JG+hhh&B-mUxe ZEb;5(orN8>^?I=Ddd=ePr!Oz#=sza7#nJ!( literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/continued.gif b/APACHE_1_3b7/icons/continued.gif new file mode 100644 index 0000000000000000000000000000000000000000..b0ffb7e0cc026c1e0c383a17044f5aabcf4b5d91 GIT binary patch literal 214 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWsLS&DhwO0R|NR`GsU;7Aqtcl_&tI%shpX zj8uh!(xjZsWQCOc+{Da0Jq7R7GN6P8 zTBKlTX=%!!_>+Z^fq{`h2V@1vb_QloiCuU88JzN5z4yk{OJ&c!6gd(UCY?Un$r?Nn?=Lqvv3P#w6Kw&mW_iT|AE}uhs$W)G1T8yg@&WtvAFs%+oyn@vrAN+!2FgA&7LgdM$msG{jgj*VKw;b&W_&MNEp LeCV-eWUvMRho4eP literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/down.gif b/APACHE_1_3b7/icons/down.gif new file mode 100644 index 0000000000000000000000000000000000000000..a354c871cd0b1871aea54b437a9fcd88608b6945 GIT binary patch literal 163 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz@*gEzw-23{>5`lI=eR?ORw&$xvkW+XnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2i59!|d^F&3SUp#HpXaXk2Sl>&JZ}wUn<}Oew2Ebh zy5WrhZnywi7`v{UmEc1RMWQW;i796*RD-1HnCY( abURyR&WU;9JD3;O#qV)F(-6+dU=09`UszZG literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/f.gif b/APACHE_1_3b7/icons/f.gif new file mode 100644 index 0000000000000000000000000000000000000000..fbe353c28223f727deb5144a964b67aa52081e42 GIT binary patch literal 236 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2@fN%Gd^F&3SUp#HU#9hW!Rw()I|5y1O%gw{Qrk-4 za}Co**45@VTn>y2mrF4=IdgU;Y~koUdn&jyIjm;NN)0XFePuTmPrrRp@1UjePH&g! XquWjAXkF)P`eAc{t#G$ICxbNr*wRvL literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/folder.gif b/APACHE_1_3b7/icons/folder.gif new file mode 100644 index 0000000000000000000000000000000000000000..48264601ae0655bbb5b5539e54ab9c4c52c0ca96 GIT binary patch literal 225 zcmZ?wbhEHb6k!l!IK;s49|+FOJoEqm%rs*lV1NO|e|{kunZ*i;MI{PADl<=^BqLR! zpfo8bGg%=eKQ}QmPfx)+wG1fXQJS8STCAgx4dP`uq-K`rCFkerCyg@&WtvAFs%+oyn@vrAN+!2FgA&7LgdM$msG{jgj*VKw;b&W_&MNEp LeCV-eWUvMRho4eP literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/folder.open.gif b/APACHE_1_3b7/icons/folder.open.gif new file mode 100644 index 0000000000000000000000000000000000000000..30979cb52855157110d56344ce09ff29ad726585 GIT binary patch literal 242 zcmZ?wbhEHblx7fPIK;s49|+FOJoEqm?%lg*rWpeP0~jd&^9#wyELKP?Dp3GZnRyB& z8L0{drAaxN$qFg?xrv#1dJ5jDWk3m!()5hfVjYES5HG_aHM2x7IX_oNAvm?5BsDiF zwMfCx($bVc@h1x-0|OI-4#<3v?F`JR8oTcNGdShBI#=y=&2-5G4yn89^Q6URrb|x} zc)e?b^5WuCck>TOH!hekVIgPfp~Qt9URLv4mOfysiDC|%v8Jjt&35m)a4xxmqX+dL h7rU*#p8HYSdByGb-X0k#`er{rBo}PktY8g<%qclAuwOB_X8^p_SNX;zKOU}>LQ3y^g zC`rvtN-a__w6rv3Q2fcl$iTqNpaV3W0c1M^bDG7jJO2z$dEVUl?ms=DL1^Wsd78 zTBKlTX=%!!_>+Z^fq{`h2V@1vb_QlYiCuU8wX}SU+2eAh_5B^k_ROg-0w+{X^b?$Q zKX`{e+d0=|9tjPPcd_Mu)Ml%7PAUBP*kHbKD+5<3&kBD{#@jg@+pgRzznQIiy36?2 ILXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf20T#RVd^F&3SUp#HU#9hW!Rw()J9@9Pc4`>z_|O^T zk}LelhjUMZx0Uz%<6KNNmX9Z{SfkK*HucgE9k$hhnp--1%Xa$c7hcewUAg{5?%98; H3=Gx)qghVl literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/generic.red.gif b/APACHE_1_3b7/icons/generic.red.gif new file mode 100644 index 0000000000000000000000000000000000000000..94743981d931466fd6403a80dc4d1425b744822e GIT binary patch literal 220 zcmZ?wbhEHb6k!l!IK;s49|&g7{GXO~=KudR1_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|6E1|5+3Aln(3{XKT=`CK62xLURGi22&%H?LKSN;oNN&RD)A zj7{+T9dF5syeno$->jSG&*;OMYO`?t3LV4QtJ8%g=XgyGN!I7?Roi$yd81>RNCW@e KDqbH325SH#15FnI literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/generic.sec.gif b/APACHE_1_3b7/icons/generic.sec.gif new file mode 100644 index 0000000000000000000000000000000000000000..88d5240c3c3ee7aba7e51be6e49516277cd2c024 GIT binary patch literal 249 zcmZ?wbhEHb6k!l!IK;s49|(+%&;0*CbLPx61_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|5Z1|5+3Aln(3b0VTHIq;y*eT9 pbHuxO``>OATea-a%QUllYxjTS@>KR}wi0z>>0oj07UpEI1^}8@T=4(^ literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/hand.right.gif b/APACHE_1_3b7/icons/hand.right.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cdbc7206da8856227e36b9d8f1fe5668e162607 GIT binary patch literal 217 zcmZ?wbhEHb6k!l!IK;s49|+FOJoEqm%rs*LB%t`uFC-(gSRt{fL;*-;<|&k9q$(7Y zCgo%%E2QM-CT8a8DR`%r0VO<2(=$?wbriBeybOob%o4ri{9GM{;M9VW)ZC=hA_YTB zOH&5LpDc_F3``6 z1P@2d%A8Z(d*Iop;+0_slQ(LVa73?qy!_*&UOA1|IbCl>b_(7P3tlzje1;bjgEav1 C5>Ye& literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/hand.up.gif b/APACHE_1_3b7/icons/hand.up.gif new file mode 100644 index 0000000000000000000000000000000000000000..85a5d683177b439d3bd52a5fbe4f4b88e6b36a51 GIT binary patch literal 223 zcmZ?wbhEHb6k!l!IK;s49|+FOJoEqm%rs*LB%t`uFC-(gSRt{fL;*-;<|&k9q$(7Y zCgo%%E2QM-CT8a8DR`%r0VO<2(=$?wbriBeybOob%o4ri{9GM{;M9VW)ZC=hA_YTB zOH&5LpDc_F3``6slVT^wp$^;wzNj zocQ$p=uWvS+vn$eP!`KQ9AC&Oq&a`zGo|*%R}=iZ3~#^S+H|7K?YGc(Np|IEzH%$YO0yStg0 z|CyPYnPxMYW&ntYh-S?HW@gN0W@ctHnPvb0RaI3pGcy30%mA4)0A`s0W-|aYW&i*H z000000000000000A^uKOXlZjGVRCdJX>%ZHZXk4MWgu{MVr*$+AY^ZCVQFqIAWLO- zX>K4$b!TX0b1WchWp-(9Xh3CYbS`6WZ7d*DWpH$5ZDM6|ATc>PH2@*`1OWg51^_Go z0002s0Sp2F1^=KSj$~<`XsWJk>%MR-&vb3yc&_h!@BhG{a7Zi~kI1BQ$!t2G(5Q4u zt=2Z94c57Jbq!xrSezYad1i2Vl`geKT`f9=ebeIhcKwyc$G&!dYcqgkSA#%-MR_EJ zbY5(ce3FzZifTQ2m_Le|mzyY`jYOh`k2s}nVOo2vOmdj8t*~ISaDH2Wa&@$Wxw&et zaItv0vw_03Yrtj4nY6aX!MDTJx6W+Pz;VRQjk~p}!n}Ud+}`9@(X!gs(&;wmd!S3L z!_cGCXWWkSp0UcT1>ENDp1@Ou_~rBGgPB2j0ng~G#*l?WbG{62B1jJsMo_%=Ed+Sz zBSU8MDF2eYgHKg`4SU=Sq&9D1xIlGG`8y;2=ty2+-&Wr1sp| z+*p&)L!mrrx{P;qE30!7D_W(xwO&_&{k)0{yOM2Ii3Qo>JQ%8~Lbr5L*(ICO;i{?@ z_kvA3w_^)}KT4SJ(V0TC+XE?^m?+L z6!wPC#e7FIzNGl)+46zyJRL1}NZw1QuxEfe0q3 z;QxXQHt67k5Jo8BgcMe2;f4KGpy7rbZumrpAZqwwh#g{RA`B#!=tPPfeh9#eFveH` z02Qnlgof zW;df2035)|0XgbeB>-Q2Rc4k-Sc#*PY$D;NnsA;O;{?UP8mALmk_adjf)XmKm75k}C73-@+NhMQRIq`o ztHP+}tF*$JgqxRUS}U!63h5~nUsV^Zi(nR8sH@19ha#bhqM59%ksi5#qRPH7C;uzV z4jV0uxfYOZGEa1xB6kav8$q>~4WMoT=*kePm|BoYZKKo{s%We?POC+^<+jVhwW#vj zFTMbD`=Y?p_Ufs>d@K;A0})Wb@ErpHFaV|#Ox%K-JPNEa3LN9;F~J9Kpf3RYetZJJ zgC3kR!3MiL@DyA|q=d-{0FVI06hOsc zS~9_E=DTzWxMJ$9)`5z!CAdkL%x}aRZf#Kk7hjyG+DwaTEYgzD7D8nrR z%Xe@4V$6B_ZORB^r`d$r3q*i+cdxYVb;gE|5bE4uPo1=^fgjMF#q0B@7uW% zZVFv-=C5>-_`I(;?s(6xR{oUNL*ofK>T=tAx~VkU&AR6=vI4c!rIXBe;Us7J`w{g< zzxeF5lf5{`xm!=X(MUf(grMgd@4XO4o?Lp;qYGaA=E;)|qw~Wf5q-U-LeC+u%jKCd z(NQ|e{M1nMU;2m_HA$h*a3PZx0{!>DvdxcL3*b)ecE<(EQIL0F;@MFk01+KYm=qBOS;l2CKPYajusCb|WR(1beV-JQI)LKe30 zRT2D@6fWnx6B6N6>36Rj6;~lLf$U(+YfCvO5 z!X{ZRpP^2Ylth>%O@+x!@@tc2Tcmn4?J zdh?s$45v89NzQVb^PK2Rr#jck&UU)D6TRqDBI=rl7XMT)dAFlv~7g4Cg7 z(T++{I)qs^w4{d#g)Ig$(|3^ODD5bYX;gs?*W`3C;_0bR%K;X&B!!@d>CHfd!kKRf zHKZtU2|QR6!^t=`7)ZSiQDU-FZZOhVB*@8i_q1qD}C!6l~NeO5+|*FsL5x*x>t~*^{|KSC}S2QSeWcpqlmTa zM7B{3u|(FOYJtmN;p)-CF0QhZb&O9;yHS&@X0*ymOkU#>oU@X|t*n)(T%Gb+wyIS! zdS%Q*(JGhRp47OZWUXgaJBHpib*Hjr4QYk*Q=HVaHvg!oZd`~_+sP1hAHjkyVE-`F zt@_3@-OWZZHj)tORx32=^^SS_%2}wm7rTjAk4q1Vp8b{@u!c9x;SPKF!ypc^h(}D~jj?D*7&ljPuoRI*~1b`_& z`N=Xwq@A41s1O>t%K)}ctg;B^ddx4yI=1qTNky&&h-r*Y)>Nh9%w`!jKs6O5-;C3A zWh^f)&Utps$2xW4)EqE%xTAn_Wz-iBP~M#+<5~HxHA|u9WBf`Ygd1c zp0h0EBmo3)&-Z%81fMOT> zOEqSYl+m;RHS2g}s$O-gU7cjJi3w$slysb-?L}7T`rEqZGy!cmV{Qw3P{uYkvPr$> z+8J4Da_ZLw=H2QHFs_oTVjQFI4R1GYduH;(HMj@9>typ0)n$A(z|Wm-b&tA2R+8B3 z$W(40ZeZT@&VaoUX7N?KdEePKq?5JGK}-{z;IG1)r{6tTG&TI#52w(nwnPDQ9j)T| z#`py^zHxI4@#4~MHNO{l;~bH^4vxc`4XLY9Y`L@}Qb6l)Fup56TDKlruIc|P=< z)0@#f@AoBN)n^(b(RPDQI=Gh}NM@nBhkpii${}uKoK^jCH|+G*HO{!ak6Y&l;5)zk zPT)HDi0sJ%L!wjt1|+uSI=&Bw*m>xGy#aVt=4H$*y{X!urAYjPcMvThgC5e(h0D7L}B( z@oJyDm$yCn2VDO8*uOmQ4di>YO|bKAM-%AzzGLCb9@68tclj$FePmjP+8c4RP!2CoNwwBlen zFnjj5e9&`hN~SNF=YJ-6f_j#ML8xsrNP|iUXf+5E=i(}jS0f%Ga!FVZ4g*G7xFuZJ zG&&d{8F+uwCwW%Lgk|V-Rg!XPb7vx$b%2J3@{@&KIEPx;H*F{&q=ZV9bV_L zrL=fJkcWCGh~Hy5$N~j~h)RYC9{Tpcsmx zIEtiLil%sqsF;eXxQeXUivOL^*`2#qcEQOXgH-I$FpWgUh?RM6E`I)P_J6;`XjkGs%SvEd7Nc2iUp5;P@V zo6!wTb&z_%4$e12#bJ=y)fYBZRWQ*D{&-9CH4bAnkrY$xALUmS& z63HFGCPNHbEclt9pO$!0HlinrKN|`}ly)-#5Ti00qyDu432>u0dZQ6mC^Ob@>$W2y zN={ywCVOLR;}%6hN(wW&qyb>0(37K3ngC8(HdOX&n@C6_Cw88f zMp^oVuE79I8lz~sr1u!5Zi=HVw*k0!rATlofAelLGc;J3K4udKT3UEtdPPpNJYpJ1 zO{Z{X8V>=$0F2tGjGCql;5Rn^4lk=(A7OKNKs>SM|xOzrp z3WrD9s`m)1u{x`lQK?OOt4tcHr0|B2sHwOUgt#*SpK5cXDz1!kE{h{QXM(DKWO0WE zM6OB*(0Z*5AgxE?rW+umigK;=>Mm(BKUG+#xbrnT7O>!YD;*exLUOQbsIVmpVN<#- zsA`5|c!gyXulm|x)@rdbIULD(%N%ZXeQCo9GUAqhM^$b$angwL9@I*YMz3bi%+ zME`xbhe?nt6Y#4WptYZ}ojL%ZhiZfz^mZ`&v@8w<-F#eT#ykOSXxiri+@oXu7(pTey=ExN*3-TR6L0Vuu4Nh8J48F&hJX zYr2WxsK6V%X;U`ATfFn?y51#A4SNHNh_zAXv6+OtJPW;)B)xagiHTS?F9x>Li@nQ> zQx6-VuXKqAO1@uYzRAj->bt(|+rIAmzVI8r@;kruTfg>uzxbQK`n$jU+rR$%zyAOn zzydtL1YE!de832tzzV#;3d~qyrdisEQ0y3v+zXHYRKe+(!J?I$BQ;+d+!3EZjiq22 z*VvqPb-^P{k00{}?GhgRR7>b61(+4X!-)*^7@P@JcsLAI9SM<88JZWlJ07W8cO_Lp z9Kt^Q8fj@W8>t;hTwMcMlMM-yw~>$;5yhQ(6HRQ8Ch1is5s>;w#m)6oRg9TeHB~Xi zRfsUe54^<~wZx?9eoVoZhQL{-30{@iSd#EqedU;m$zObI$8%g$by>(;xl~i>$870W zK&e!6C72_z7R&XN@kIuOxfjj%$2#d+;Z?^|0m*gj$6?8vGg()I`Ic&Fm;Z1HoCU>| z^`*)bESF4)Rg3k>Gl3Pi99i}?%YYe}yoH;FT*~4I8J=0oEdk0N0moWF%qB(0UpdHN zSzM4A%A-{ft8B`E?92U>%l0VDza^B`yippZ%a}aLy?m6^T+V_y&EjlYANiPiEKs&7 zT}8Z`+{MaL0nfg9#;(c36M4^93DCm~8n=0y-M|xFT+o_{mA2d&5i!IHEf)-(6u?1~ z5&g^)J({T5&y!Hh0(s0AtzXVD!4O=HH$%fg2|XW7lsEj2?pRAZDjgUs!7PEamM~aq zgH$tZ!Q_~o3&y}e9n?ZS)I?p>Mt#&sozzOb)HKs#PM|+ftv~Tu0sr6Xp7oTp5+Wim zlw(J>pIJ))U>(+CJpltSw6XH7OZL6rv;kqwoPp9IVT7e!ZJ}Q+)^<(SWu0Vbjbwnb z)7}BrZr#)+vek0^Wg1$ic750ClGk$v0DBFg6|w=08rY$50ER{YXqUc!7$R|fyM}$( zy_(o#z1WORI*+|(Aj-19vZ$2(6t9PNu(|=bvm%~C*q#k(&yu*J-PZflwUV~iFIo>w z>ely)trlh3k0;#F`mGqqBAwmXN~YOAFaf&_*x`GGjt#U7YG!GQuCKt_we;Gru%_4g ztxbB;wN0U|TBt)n-PH}&`t#e`U2g2{N`t$x_dTP=E!>gn*Z-M--1J9ai(0$^VBY(! z!@gqGTpgyn3j^-`-URSAXFcEa-QX`U-16$EgT>mcJxkO(Ew7Dl6}#M%qqf_KM1NCc zx~tm|9@hM`Eql$ZM!=@z-K5g(N;Imv{_O%XrUj4ZyA2Vq25!Aj)hf^Zxupx_J@DWy z{^C0nCTBA9Rx(ra*ux3IQ?gc_#;+g9m)M7_HUA8N(1WXR$PJTsDj=M+D zq&8mTt9#(*s^9pHfpO-pXq%=(Zk^+MhEYxgY5v}8K1FRlxRK}x~j^iYbF;R;I za$CMlOMPhm>7YL0qVBRs5UERA<5nK4YHD$h+vSIG=|hw0NAQ7v4yI0<>$+a(ZFlHO zP9CN{*)oi;HIBN*UUxFS2+BSIvz`R6W2(1KhIRev)K0qD-Rt2l;EaCW%TeW$J>2+2&v;F8V-!` zP2Mw~y>N&nwky{#?7gL|(UpLHK@O6N)~@x84P zB8jDHiIe#C0pB3`4c?e*gD?ANYbl z_=I2hhJW~opZI}4jTBVEChWuu6~T{Bn;UG>5d4LG5FR^z%cSM_@yK72-@&2ZUk^;2 zi%|N_Ow#|A!>fNd&nU;BZ=9(=oiI#bub@+F?87GI#%UaoxnGd>cvLB@#Fsf&Pj#5V zMaba7`=FK38Y%p;`I$y_{IB`YegXVqJXEWR#wvZuz0Ab%92nlu$E+Ftk#NXRY5vbh zl{<;d26f5koL`R-|3u0DZmG$^DVCw+(f{;i6zts2AYg2UNN#6Yo+xRyqw2OZO^@*H zu5kM5axEzIiCDSR5jRsRhfduJ$U{<}R%ebmr8ckLS~K~(MP=fzu*(FZ+v%!!O|<=b z-*db!C7#jw*pi*xmYa_nA6y_Hp`TsP)L`M=BA{87lqy%UZ0YhP%$PD~(yVFoCeEBXck=A% z^C!@tLWdG9YV;^lG!>RIZORm*)2K_KN_9%L>eHl7ur|fG<15&K3b|&rSOEaqv}(^* zxOi4AT()lE#s$#UEZwzswGMfk*X~}68x9-@yMyqCyAl27m5cW;;J_3a(|xOWBIUZ0 zF++}g`6I({ne}d#IJj_x)T&bhIGva?WXq5L`uz-XblTb#aii5exwq5axkHM*-P!lV z9T65VZ@!@Q3fl+Y?jT*-c!BKN3mk~t`#0JN;>S;5EPeX%wcslV5b)r=@ZlcI>`pJ= zG~(sXnYTuKz8`hf#rGX&+y7}dL2DHxwjgW(OkiLE3o58!gLz5FphT9r_ud0&T}UBE zJIn>yhoOy<-+uhL_8&a~LYG#F1wx2mSPedCV2v4emg8c*aR?uDUxg^*Y!-r*+zR^b z7vyU?zIXzRN9qV+0SKbyoQatD^&pp3R*7YW063Qxm`+x}0Gep3Rc1y~*4LSs&1ETx zYf6r}B5Yp)u;-p^Vz=D|fnLyEoD0lZ2yc8AdZ-(IEudg@&n*hunQ1bh=%j7B2_B}M z%9$LBDfU+wi|+&orKij>+QwOc?s-6X9a?q>*%#!SXRN0?=5BR zu+<8CkzwhwTJ4R++RF@L_2TIys`85aP`2U?YVHNuYB2CvwjwMjygC}%>z*9$x*&ZG zGYMA2f*Ceqr#BYRF+_E)rrM}Y_V^;7&oYc2pARQ|fCUTh`$TOC>s&6noEZvVyNNk< zvk-|gOY|McawamBBhTw>k|{nHZM@aKOptj9M^J$UHD3*&yq+Rm^sMc22<(1i({O57 zBzr6*UQ9RrbjhJE`R~g9x~=i6gqc^eHhANG9*hg=)>C#Of zNcTf^N}aN_>Hiq5Z2NA5h5#Sx5ec2@d+kmjP|J?{12vyLh9 z$yaYGpQpQDbIsUKiz}oj@Cv$5sTQIBN8l$O8gaHeCR|aGVyo)s+SIj_{1gl z&<6g3TmSaHs6B#+kw{?_V-&qu#xAyiEK#Y*8poK%InuF?cDy4V^Qgx?^0AM8{39R( zDab(*vXF*6Bq9^3$VD=;k&b*MBqJ%wNm8a5RA+fy%c6C`auXV(jl8A!)8OGSqp)98xBy1(QgMuE&?go4(C0MkIg54r0u|}VhBwCv&}t@apxrF!KJ#IOg#Kco_Cjbd zEB^t}fR19K!7PSF4~h&+kdzDKv}P!%5ejj}fD^}b20PXO3Pfz98#0xGN}*xXG2pZl zm&gZCS8CFE@-wKY$mvgSSPfTf0;T|QDpG3-k1^rPW@)v^**9&)AY*ltQqyv8)Bir}kATl!b9niU;_-K!Vm7-0PRtqkyM+a))%E+ zEkIg}h+`U}}^@l7D4fj}73Lo5$+$i{Z%QjSUIN zB{t2FeY`^l`)PX~&To@V^JIB~LBBUfr9<*UM&a!4SQ~!C$Z*Gm7 z^ZemRfBDXS{xhKYN#Kvcanp~}7y&{pYEd(qGXY~+ski)SIy+j-R;IL=EloyGUpaHM zmbEr-t!MU$XVjt=50urZ=(hP6(KdbbtG(>$O{==nxQ?lV>(%U7Kl`B3=Jd*ZJ?d2V z$Zshjck0Ad*5(Y_P+bg zZgpFG;P9rCylXvcg9{tK+9q|l)l6(|JImjY1~{?>9&mK0TjS1dcfmgnau_;@(DwFT zzLzm<+ff|P{`UB)Ieu=8V;bGkrui3P^YBo&oNrGmHw$x}aad28=>HyO^^`{*a%vOY z-8qL1p`&i-o|F0K1Wvi8hu&$e%RJd#S2{cl9%(dI=*%AEH;jvo^l`_T?evQI+mqgQ zrqfv#{^~EXv92YH>pkl;pF6YLRCK`~T_delIMi-FnJE^riql~{5FHOSITtz0mFM#1 zfn51&{|?)4E2EItXn3%*xao;McuYy(dDDZC^&EaZ>|-zc+0(xEw!b~@bFcf|^S<}K z|2^=7FZ|&Xzxc*KKJt^V{N*#h`Oben^rJ8R=~KV@*1taXv)_A=K9iz>b!Ksni8N_y zPyGH{rtHjL&Lc!NukVZ}G-v3`i`t@`?0jxv^FQ48^B=pDtN*M1C078}T^is6LtxZb zsS#RT6lguvMxmYp>Hw%iAOkJ9UIb$Rkd|lpm0LNLZ&B4Q)==Tp5?Y}V3IZA?p-G+L7RD7N zJRuXFl^N>Q5w2nV9Tq{&;aRbtIq~6QX_OS=As3cmBD|Gp8N(pHVROY{B>-YqIpR-2 zVlOOWAmrc=9-wR?U}#z3Ygtt%ves?wlQ!(2I#5cHW0^vSn;A`pDLE%C(tRm4M zB4(YSDOQ(dIg=s$6)o~0b$uT&E|+o%AXc#z{Mp|)pwlv@#Gy!+c4e3U`BpT>mM}U* zo9LpD*#ZHEp!R(uIEJG*jw3miqdA@?$oO$dhMW0olZ z1fXO_X4g<+L$|bKnz@*f6(w{nkN?kq=ecSX3t3(E(*pUgS$=R!qjC zOUlVp9$r?~!^e$YRpt+`YybkRKw(5#)p?j)o{yDrr3858SDsc)9@O;6iR9rN;&qV{Q^+=69OKXx(kKrX|W~PY^rdKkndfQtTMr;Zs zk3q?)*`{o60ByF~UfPy$vJbVLMcUY$=e6FPZD;8b=K{6mVK~}!VhfXa+toFkfkmg< zsbqCZWrDOM zj7fPm6nLHh&czFvego#}DxbiKZTYo)Otu zXoZqbh92jCrd@&>4|GBbU3TMwT4#?{fJ+k5hL-4za_5nLXOfbckhWw?-e^hoC}&iF z0^HA&dFXvI<-L5^qX?;$5-5@$W_~WIl8Wg9B~Xi=5Z^UiVhm_{y5~lqXt;D~dyZ+0 z!suF3sF})Uhwf+Iv8kKBDT#3eV-yBl)~TK5sf>E(qR!h~z8RL{%$l0ozD25Y5vqSV zsi1})qvENFiejg7D5UynpWW~;VtE4Oy5 zw|*{8lNa`1Fz!PpM4~vjLqN=l`$cRrPS!5Eq8##~L7n2pE}##R z;HsEHVriB;g%rqs6cmVG6$S$aN+SwhpaiCD3|807x}Yl#mdduG3u<7@!sO42EX)!u zGOC{@EMZjTqA${H$1)fNdF|4&;%srk z7_wB-R+QETVjcG2R)K9e4dT;QZ6k2)N_{OXN<$<#);6_mGWKm%;np7lE;b2n781$d zLha$I6=12YiYT@$UL-a0{Agn_3QsDExVlQ%Ua5---^e#%IAI3T(NnFeLN$fQi*GcT^rA}k= zzAyZGQE$cKF={M}(f_Zz_OJi`F8~Ly01q$$7q9^zaP__8d|`$0Deyd!#R69aRJ>U~ z`ecE@;~m+jP23{}tI(5GFrWGt2v??q$wonnutavmWn_o2j!+Z2elk7Q>kk|1b&QF_P%@+3>(-Z$1x?IjNjvXBCg=ER)faOd1R4axMd>ZhrA%s7f#&h=777 z0Bt}R1F|bCvuj#0HLG(7GnqRp=UA#rI+N8MMa!t@P_htbb3b>r3Cv1R^9>Lgbt02AV!yOvt6Y}Jbd)wUTzBb%7B(C| zHkCESU?`d;=QbuQ>0f`flgzVo$O>e)(T5FnLQ~H%vs`1hP<<{pB+n`AkajBHGgRC* z58QHog0@#jhhT5%Q7%BZgtv5iaF2y`Ry+6n*w0!6-EfmY45hXx_ysS^3VM5RT`Q!5 zaR209=eC!5+hue`g*Yi;$To+58-YJ6Yv<#{wYLEjYD>CyYj0|G+j1rEcA0j!TUV-O zL%14CI0=_(gdezFf;bYdaA$|nRK)3|hWL1^>07gSeVDx1=>ChF56IVpqcog%Q5PdSxWxs_izmS?$^Z#kEDxtD)A zn1{KTk2#r_xtX6iny0y%uQ{8yxtqUv{GM;7)uO)g7Qqsu!`|ySG^{VKFCXNq!cLNj z3_AOQVf(5?_tDecR>S!Upc^VWB>@x*qT*-i0m)+Q$7%u6E|pu|EIWN{(So}B-v5H} z?rf!xY|kFz3|5u`in=0p?O~Bss8^sR?QH9+dJXb}=dNuVHr3=#E$qhCAN&E{_5l;l zBCH#G>2|N>3L(~(ZT$iTD=hEv`XT3jIu{_~A?EGs0{i5$l@N*`Uv00p*A%ipqOZ^H z72@FdZf+)S5-2G9BrdzIUoEe{6jNcYwxl_#%ERpZLXQ2)|54U!y=YUVT4V7GGjSB-7`Ncp z+ylS`kUc`cN=pt3Vch-M^HJKXJ?pT&dYkdvv$b~!emw*V-9L=o-#r|~inkyPtYpC7 z>k)Mva^1ZJ;oHv~&(X^1$s+F=w=n+WLk#4jlio`{D#^U_kQX-%fTGX>aYF+xV|hg#!}NYLw{REbL#EqT{V*t#5}(5Uq82CwV?Dp z@$3BoWB`LFk^r$;Uq|UxK0l03aOa~L`fJnN_rCRGf1vyp-*-RjhyP0k*9PmrvNA*xy%}x zhXb_hy?DKgOy;IdtJmzddsLVlU!swF={m}M3*=o})bpoAv@v%GfHs)ZB=sZ(MTNDf z!WGsf76x^8Hc9yj8hQsuT1qOqk_S`N=ZDG?=<}*lSahg3yEU~76XkoAt9$u{*>zTi z8?3wxYU*6NtoqW^8sixpTg2?L=W~0F+GO=e{tFH&o;g;0aNNlZAOBbPY&sD=*YgdZ z9f*&JDA_AZA6abPrkK~^S%LU|M`=AbtrqsEMI?)3cwI7i^Xe*S_<1L;Z` z!79BBMw+;gn7U17YQnULGiQl9a^~=acT!)-n>uHmL@6>Hq+U#`5FNAu6EQLiAWAHX zHS5keheUYXmd}Wur&>Q91({T7l_)I9k%cPtK-FUq-$aX6g%|o3ror)DT{k| b@W92JKaW1W`t|JFyMGTqzWn*9LI40ePu4mb literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/image1.gif b/APACHE_1_3b7/icons/image1.gif new file mode 100644 index 0000000000000000000000000000000000000000..01e442bfa92332ec1c6f6a3a1310a41da8be5cb4 GIT binary patch literal 274 zcmZ?wbhEHb6k!l!c+9}?9|+DE|4&Oh1EkNKnF$1G493RB3^;(|KfjQS%wmPaq7nrl zm6@kdl98%VP@0sJnXHhKpPQJOr>EeZS_YKxC{52uE!I)U2Jtc+QZq~RlJj$Q6oOL= zN>X!^Qi~J}EiFwM6o0ZXGB7YR=zwelxr%`$x8Q`Q<}TB46{|}Ro;FH4vD|TwVqCRu z(oHG-o-GnG^BH|*TNeaW6tnVAVoo@j5?96H;J7r$On>@QlgzzoTd%A$K6Qt0Rl^Fa tT+{HAkBVmGwl?ql^5gHGE#Ge!M>NIeRkegTICnX-n>O`N&=O>@1_0HcVjBPe literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/image2.gif b/APACHE_1_3b7/icons/image2.gif new file mode 100644 index 0000000000000000000000000000000000000000..751faeea3644ec77fc2758b18522443c86e11e88 GIT binary patch literal 309 zcmZ?wbhEHb6k!l!c+9}?9|(+%&;0*?=FFLyGiRm&0Rw}vu`$EUGYm708H|BE6rlLe zFC-(gSRt{fL;*-;<|&k9q$(7YCgo%%E2QM-CT8a8DR`%r0VO<2(=$?wbriBeybOob z%o4ri{9GM{;M9VW)ZC=hA_YTBOH&5LpDc_F3``6AFlZ-6WvSM=7VP{@&>xS8Bwhc1-A7qQa*6llSbi$3t0`pjwvYB~D2%9p5teUK9 z!JHj-nw2N%{)ee19sAhWn7?J+(8*}hLs;X|rU4J$iGeWf`wdw5G*d!uZZa9_W^ ocG{GwRjPF}8>Y#Xb1hynfA)0M4)%aGYyBN0JvVI*5@fIj0DN?8ZvX%Q literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/image3.gif b/APACHE_1_3b7/icons/image3.gif new file mode 100644 index 0000000000000000000000000000000000000000..4f30484ff64db93ee44ed0a9ad7ee2ddee74b3ff GIT binary patch literal 286 zcmZ?wbhEHb6k!l!c+9}?9|(+%&;0*CbLPx61_oneV}_Y$7-kwX7z24&fZ{*Dkc`Y? zg~Xx~1t67~r%;lSs!&jxl#`jPkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZS zb9EGgQwvH`bCXhw6bvmbO&Jt_vM@3*Ffr(WYy-K9fu(Z83D4y_B18`CzVBL=8|T?3 z8Cj-fRpz22to2}(%Yyfw7ys+~3he!($l^D4LHYfmjv4i)2j@WJuw z(xQEj48%`M?cSeKc2$dA;a$a_s7`|)|JgXI)5;nenzd@X8XG%`OT79!SOcd{3$T;) Lm^~+0kii-Nb17t& literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/index.gif b/APACHE_1_3b7/icons/index.gif new file mode 100644 index 0000000000000000000000000000000000000000..162478fb3a7f690884b1527488a27a9d34ab497b GIT binary patch literal 268 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWz6de`8}~1{hHM=NFQZS*(y)RH6W+GV>Hl zGEx-^N|SOjlND0(a}zW3^c1{P%YYIdrRf=|#X1VvAYO(;YG#REa(=FkLU3w9NosCV zYLSAWrKKr@;!hSv1_nk39gr0u+ZmYaJ$CK+XdvLQdala8OzZQ4*F%+d^j>G}%y8WC zp)<%eSG-8|P1Cu@LU&KQy{J}XRik+(=tTM=GYuMB5h}jym8(tr{ zTHty08q@pqX@{qpFA8HkpSQf;)z`l$D#)_MC9vJG&E2N2-g4rU9X0k#`er{rBo}PktY8g<%qclAuwOB_X8^p_SNX;zKOU}>LQ3y^g zC`rvtN-a__w6rv3Q2fcl$iTqNpaZfI}mo*BX ubMM=^lVvk>^@~}aS-AV^f3&VBD9tXZudR+|59;m-w3jTH=pio1U=0AHb6^Gl literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/left.gif b/APACHE_1_3b7/icons/left.gif new file mode 100644 index 0000000000000000000000000000000000000000..279e6710d4961d7644ea2e3e39e6afd300147aa8 GIT binary patch literal 172 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz@**Nzw-3iM{+%$5nXSNI_AHs_0#Z5ammWC>ec*qNb!1QNo>>3 NI{94w6cGjnYXFzvI#mDw literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/link.gif b/APACHE_1_3b7/icons/link.gif new file mode 100644 index 0000000000000000000000000000000000000000..c5b6889a76d72a1f052d2885a725e7065344ee9b GIT binary patch literal 249 zcmZ?wbhEHb6k!l!IK;s49|(+%&;0*CbLPx61_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|5Z1|5+3Aln(3b0T)_`4k}HuzIfQzD(=$g4aWpcJy9n?OYMK z<3neVTdwpcAKpI=-d5i4k8cuSl8s+i>=HJ`A>=Y=gWs~oHDEJ%$YOO($b8LjTyi|@tVo`|#kjl(c zD9K1wC@4+J$xK#A$0Aq je4J*Rr#@1aJXdjR@wJsoZ!aBYW^HV0ZfO+YWUvMRZ1!36 literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/p.gif b/APACHE_1_3b7/icons/p.gif new file mode 100644 index 0000000000000000000000000000000000000000..7b917b4e91e8004d40241f2c031016f3cb414caa GIT binary patch literal 237 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf22^PEdd^F&3SUp#HU#9hWLHC{`p^eh6ea~4tRaf(| z_%3JAe*U`SyKG~C!;gtpQxXFgX({TuJQm*75*apCqqytJp{nC4Q*X#X Y_^R}pPJ1}};XQE`%{%V$b23;10Di_)fB*mh literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/patch.gif b/APACHE_1_3b7/icons/patch.gif new file mode 100644 index 0000000000000000000000000000000000000000..39bc90e7953103a7fb4d6dbbd3efcfc1cc8de759 GIT binary patch literal 251 zcmZ?wbhEHb6k!l!IK;s49|+RY&iwyBbLPx61_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|5Z1|5+3Aln(3^CEWb`4k}HuzIfQzD(=$g4aWpcJy9n?OYMK z<3neVTdwpcAKpI=-eOD+8f(7P$v8QjjESn*)KFqotJLnbYDxf$LnDLk)v8Bb)9>m( q*HL9Yo3!quRNC&zr)@sV$^5d;vQo}swQXy+(HAuD>9yx%um%8r)mtS1 literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/pdf.gif b/APACHE_1_3b7/icons/pdf.gif new file mode 100644 index 0000000000000000000000000000000000000000..c88fd777c4b2a85b930eb4a6b68440c88536289a GIT binary patch literal 249 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2ITpM2d^F&3SUp#HpXaXk2Sl>&JZ}wU>twhgl(8#J z&4;IaU+5wAJaJ`3 kwKt!oQbM;s-=_PA@BRCyb&avi?yYTZ7J^Yx{G1Hd067U;U;qFB literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/pie0.gif b/APACHE_1_3b7/icons/pie0.gif new file mode 100644 index 0000000000000000000000000000000000000000..6f7a0ae7a703000c365896477c32f9f1434d14ca GIT binary patch literal 188 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz+~Oizw-23{>3JXu0=Fn+uq4rbVj_b$!S{Jq*b>ox4e@+uPSrG fY~A@idsi_sTAZ5D!6YVVJJJ1GWyGRRCI)K&$B{!c literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/pie1.gif b/APACHE_1_3b7/icons/pie1.gif new file mode 100644 index 0000000000000000000000000000000000000000..03aa6be71eb2efded05e937f1ad79549ca2d56bd GIT binary patch literal 198 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz~tJ~zw-23{>3JXu0=3z*v`4OaPFr@>FpEKG8&zNm_A7^cehR7 q{3odT-{ZSYE(_O7ykRZyxV`aZjoH-0n$0tdUlfJ#w+AvXSOWl+b4fP< literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/pie2.gif b/APACHE_1_3b7/icons/pie2.gif new file mode 100644 index 0000000000000000000000000000000000000000..b04c5e090868dbcea50043700d52179ba99e89a4 GIT binary patch literal 198 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz~tJ~zw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N qqqzCzcVC|^a=f79z@jnzl=39bRIB-cn#w!p?CVf&?+9dIum%8pzDGL% literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/pie3.gif b/APACHE_1_3b7/icons/pie3.gif new file mode 100644 index 0000000000000000000000000000000000000000..4db9d023eda78f499c5e5efb7d6739d0d450652d GIT binary patch literal 191 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz+~6czw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N iqqzCzcW*N`uLwVHCM7ial+@(%Il4wxJnexD4AuaG3PW-L literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/pie4.gif b/APACHE_1_3b7/icons/pie4.gif new file mode 100644 index 0000000000000000000000000000000000000000..93471fdd885b4e54a6ebcfb68fa98626f3d43d75 GIT binary patch literal 193 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz~s==zw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N kqqzCzv6IghDLmwE@Ojtg`DD^c7sH|;f6tbO23!o*02@O^$p8QV literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/pie5.gif b/APACHE_1_3b7/icons/pie5.gif new file mode 100644 index 0000000000000000000000000000000000000000..57aee93f0707a6fea58637c351c4ac1dae6459cf GIT binary patch literal 189 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz+}_Yzw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N gqqzCzdnff4?UOy9X2Yes-Xz+~Cezw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N dBfa+_^}iWi*Dq8}v{CBqS-80Up#c|zH2^Q-Xz+}3JXu0=3z*v`4OaPFkWM->GJsune#*ygc&t5eqP cin@0;&wnp$nZ|PQtB_G$pA6d$4F(2l04BFX#Q*>R literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/pie8.gif b/APACHE_1_3b7/icons/pie8.gif new file mode 100644 index 0000000000000000000000000000000000000000..59ddb34ce0f42f40fc010aa2bcf059d891fccadf GIT binary patch literal 173 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz@*dDzw-23{>3JXu4R1A-L;ud>%okkhl!IyUaie(+qXfR+ave> Q)*p2%lMkH{VP&ue01>A?od5s; literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/portal.gif b/APACHE_1_3b7/icons/portal.gif new file mode 100644 index 0000000000000000000000000000000000000000..0e6e506e004caddde40da13470f5b566c4ebd3e4 GIT binary patch literal 254 zcmZ?wbhEHb6k!l!IK;s49|+DEp8*m;Fw=PE%$df<#taM$ivRpVGBS%55{pU{fK+Cl zLP!lN`jBehsZAsfWYa7fK8(M!(H)lmpeEhtIN zO-e0NFtoHZWl;Rd!pOkD#GnH-odIM!19M@xy5abNeolJ^dKQ(i&E!y0oZhYAIz1P__bl`CXaRbu>JEQyKU^X{_%FW>4o vqif4-qpv>D{n{&YXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2=@z^8d^F&3SUp#HpXaXk2Sl>&JZ}wU>twhgl(8#J z&4;IaU+5wAJ;6lrj$UyQTKrXC=eAut`Q_@GqDYq{i?eZ? fuRb@A(YSxvky)&eSX80_ zq%!jqN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1 zK}l+EQfiTcp{1oMgW^vXMg|5(1|6X33?SPXnCmij?fGaR;jntH+P+NdaQBLW*w$93 zLXW4dLa(j`>C2pYt0=I?YR#HS>z@C9sN+1ND~Ts;Qmd-42b05628YQhH#GTgelWA? zX*zt-Xz@**Nzw)%~qgf4szES6oR(^g_8+4;}QR+O8Rat3Y55;}UDY3n~ OBkprQ{}oXN25SJEJ%$YNdjg1*#K=GenNJeI{LSj*g0+7ngQz*$u zRVXM;%E?StNXgGl%*@kM@J=lQN_do}XQUSEC}e|p84jtLC3?yExjG8LsRbpexk;%- z3Wk=JrVNTdSr{1@7#VaxR)B10U@n!|b?2W!n^SiVYewRG7AFm!*eRWl9lSzTtP=4S z(YLfe5`E@s3_lC2EJ%$YNdjg1*#K=GenNJeI{LSj*g0+7ngQz*$u zRVXM;%E?StNXgGl%*@kM@J=lQN_do}XQUSEC}e|p84jtLC3?yExjG8LsRbpexk;%- z3Wk=JrVNTdSr{1@7#VaxR)B10V6O7mwdbROfWzv!D*H06&kJ4;Roc;eowd{9p;(CH zi7%4jOn=^)>HKMOOmxr@^Rrv9(Zj|os#X5-Q4yu|;5S>$t1~+pUK<~i5YtS$=vU@u yeU(L%F~&2zjqBi^) literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/script.gif b/APACHE_1_3b7/icons/script.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8a853bc5828cf534c4c46a0efbf4b1d7d3c52fc GIT binary patch literal 242 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2sTRBTd^F&3SUp#HU#9hW!Rw()J3?6|OcFmLXwbvQ z;yXWN*R#T&@77%j8VV0WP6%GqkhE;|xp+C~4`X#h&eoZ4tM=c%ZhDQk{(Ri#ES<}4 d7Yj^x^9CF~_};qCSmD=yXLEt#WPVNtYXEP%SK9yp literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/sound1.gif b/APACHE_1_3b7/icons/sound1.gif new file mode 100644 index 0000000000000000000000000000000000000000..8efb49f55d6a370df44ad6e3269f6f966ffe25f6 GIT binary patch literal 248 zcmZ?wbhEHb6k!l!IK;s49|(+%&;0*?=FFLyGiRnTFc=#fGcYhH{__jT$ShV!EGkg| zQki)QB^jv-1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz!(9+VBLGdRGBLf2ygAUMi29WIx%-I^d?))<_JM1*!l}uu2Kl{c)an9BQ z8Fjp~isqGPnlRppzAozM@n_rZ?DB^@TMqI1Z!lq-XpvS})uOfhlGZ1!vqC)g^DkYQ rbCHkPIiy`w;vU-;D{*7rCt7AIb`rH-)ly|T)gs(25}jS#oD9|g^MhHm literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/sound2.gif b/APACHE_1_3b7/icons/sound2.gif new file mode 100644 index 0000000000000000000000000000000000000000..48e6a7fb2faeb6ba254a87945246f5ca5980583b GIT binary patch literal 221 zcmZ?wbhEHb6k!l!IK;s4|Ns9pKy>EJ%$YOO($b8LjTyi|@tVo`|#kjl(c zD9K1wC@4+J$xK#A$~K Lz}Ywz1_o;YcDqp^ literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/sphere1.gif b/APACHE_1_3b7/icons/sphere1.gif new file mode 100644 index 0000000000000000000000000000000000000000..7067070da2786b9842212ff1ce2307fb404407ce GIT binary patch literal 285 zcmZ?wbhEHb6k!l!c+9}?9|&g7{BLZ0=KudQXU@!=IWvuc!PwZC0S8e0=NFQZS*(y) zRH6W+GV>HlGEx-^N|SOjlND0(a}zW3^c1{P%YYIdrRf=|#X1VvAYO(;YG#REa(=Fk zLU3w9NosCVYLSAWrKKr@;!hSv1_ovZ9gvM6S23_u6rAu}z1QM(uhlIPp`JtRT@DHy zZ8JL^S8aON%CRcz&DRnUR>3@1XNE@hlZ*^I1j}_C#yT z68XztxyIW*eK)gq&Gg$oObhE&HaxGaZep#g4-2m9Y;B7#>??2R@5{BXndV`dHEXt- HAcHjk`1fN- literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/sphere2.gif b/APACHE_1_3b7/icons/sphere2.gif new file mode 100644 index 0000000000000000000000000000000000000000..a9e462a377c8d451bd0c0d07a47035bd44caf57e GIT binary patch literal 264 zcmZ?wbhEHb6k!l!IK;s49|&g7{BLZ021L(HV_+~gHfCU8Q2gf?l95@gkXTfr0HiYW z6iPBu6$(m|ax#+@Qu1>XGxPKmyi?175+0@L8L7oO3fUlDhC^y*iC%Jku8u-*YC%bA zZc=KIf}y3QDTCrq7DfgJW(FOg=?oy-8JMdxcJ29GAmOljuG+p#>+^!wLzQ;)UT5um zk+|bSXOMfYd{L=zjsF9o(~1rvGBq{}GB`LmSXvkRdn%jF4af{C6R?=uy5ZaLzjm9G zwH8$Kxi4iXD)_78aNoVF=4GE7r)afPMP*}_m05#Wld*D7Z?_kl#}r$ALGzij95@-Q E0diYklmGw# literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/tar.gif b/APACHE_1_3b7/icons/tar.gif new file mode 100644 index 0000000000000000000000000000000000000000..4032c1bd3d407abddd0f0e8801e3091726574171 GIT binary patch literal 219 zcmZ?wbhEHb6k!l!_{6~Q|NsB}`}gnOy*n%{)ZE;h0R|NRxrAh77As^X=jSPa=sbmz zj8uh!(xjZsWQCOc+{Da0Jq1HcOH&2!)H0x~M`?OSYO#(&Hi(zukeXSdmz{U7WG~8yuhh5Zb<@7 z`xV^^pIq^?J6sl`b?E$;oi=gneQc#~{w%G2Eo$=bQcK8x IUrq*V0QdG)RsaA1 literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/tex.gif b/APACHE_1_3b7/icons/tex.gif new file mode 100644 index 0000000000000000000000000000000000000000..45e43233b845960c59aa8933251d6d745b324031 GIT binary patch literal 251 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2c^13&d^F&3SUp#HU#6xa!*tin>9Z0|^A1!l(>hWb zZ!PfsEZ4Gxo$}LGGYd#m9-20(LPaIeg)1oN=Z{6M>Y}HwOe>foy~6k})9y8|ETZxl nuQycuR$g`V{oCDj`rkkOugz?zPGxp)?{Kpc$nTBfWUvMReehfo literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/text.gif b/APACHE_1_3b7/icons/text.gif new file mode 100644 index 0000000000000000000000000000000000000000..4c623909fbfb54658f19186beec8d362f87e233b GIT binary patch literal 229 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf25f;1ld^F&3SUp#HU#9hW!Rw()J9@9P7P`C+IwEjh zoojbq@AhdAxLane{lx8+w_BW5Lq@1~%@UylHdfUEOTOIP6XtsB<@c_)dDA0}cD??? QSNCCuzu3fEy_^iz0A2r7i2wiq literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/transfer.gif b/APACHE_1_3b7/icons/transfer.gif new file mode 100644 index 0000000000000000000000000000000000000000..33697dbb667a8c898bc501cedd8039a3e9e04272 GIT binary patch literal 242 zcmZ?wbhEHb6k!l!IK;s49|(+%&;0*CbLPx61_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|5Z1|5+3Aln(3Q#G`%?loA)#Gq@m*=ucI?DJZ$h{7jq60EN$ z%~d?lR>S0McO~B8j-}Ir=et8&oIMkM8Y@liURvT6>$dvF%11Mo3W@nQRp?BsQ#|oZ hcdptv6Cq9pYXE?dSF`{C literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/unknown.gif b/APACHE_1_3b7/icons/unknown.gif new file mode 100644 index 0000000000000000000000000000000000000000..32b1ea23fb6f6195f1bb17adf9c3cb2cc29dfefa GIT binary patch literal 245 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf285X-Xz@*&Mzw-23{>5{AIi%LijXHkMRw1HyNzyFOS#mnvM?d*oFAHE` Gum%9J?KeFD literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/uu.gif b/APACHE_1_3b7/icons/uu.gif new file mode 100644 index 0000000000000000000000000000000000000000..4387d529f69f77810347be63429d13ff38bcb2c1 GIT binary patch literal 236 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2@fN%Gd^F&3SUp#HpJvB@7K6@PEKNyM9n&%bmCrCe zcjss6%XbLBY-{hkn53brAS;k_~V>SO;rqEX_zty4nJbR|}ofI+Ll^r*| X^XnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2@fN%Gd^F&3SUp#HpJvB@7K6@PEKNyM9n&%bmCrCe zcjss6%XbLBY-{hkn53brAS;k_~V>SO;rqEX_zty4nJbR|}ofI+Ll^r*| X^XGxPKmyi?175+0@L8L7oO3fUlDhC^y*iC%Jku8u-*YC%bAZc=KIf}y3Q zDTCrq7DfgJMg|?A=?own8JLoL`d3=Lojq&DmV<08H)chf_{g}X9%4v)7BSC#N7g2- z#f}=s?(`k{vcq_8jpbY)WyV!4N-Aq^MwZQ4x?oEC?F~i2;bkXPZnEj*mSpYLJUDmD atT54C`TIV6aAK=hU_0K-zaxNw!5RQ*npTkj literal 0 HcmV?d00001 diff --git a/APACHE_1_3b7/icons/world2.gif b/APACHE_1_3b7/icons/world2.gif new file mode 100644 index 0000000000000000000000000000000000000000..e3203f7a881283a15f895af86b7727878592257a GIT binary patch literal 261 zcmZ?wbhEHb6k!l!IK;s4|Ns9pKy>EJ%$YM8W*Rf388d)^;y=HTjLc$%#G(=fAeEV? zP?C|VP*9qblbNiLlAoKHnWv}VomvKz@F-2sNG;Y;$OiE;98xn&^pf*)brgbA3rbRR zlTwQm3@t5985DoAFfuSOGU$NJ2ieZRTp_XR&O5bJ*Ohi!T+-@^=jL?!gy~R6SmeCA7ufyx{6*ATcJslr}Jelts + set $n = ((array_header *)$arg0)->nelts + set $i = 0 + while $i < $n + printf "[%u] '%s'='%s'\n", $i, $t[$i].key, $t[$i].val + set $i = $i + 1 + end +end +document dump_table + Print the key/value pairs in a table. +end diff --git a/APACHE_1_3b7/src/Apache.dsp b/APACHE_1_3b7/src/Apache.dsp new file mode 100644 index 0000000000..25766afeb5 --- /dev/null +++ b/APACHE_1_3b7/src/Apache.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="Apache" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Apache - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Apache.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Apache.mak" CFG="Apache - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Apache - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Apache - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Apache - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\ApacheLa" +# PROP BASE Intermediate_Dir ".\ApacheLa" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\ApacheR" +# PROP Intermediate_Dir ".\ApacheR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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:console /machine:I386 +# ADD LINK32 CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "Apache - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\ApacheL0" +# PROP BASE Intermediate_Dir ".\ApacheL0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\ApacheD" +# PROP Intermediate_Dir ".\ApacheD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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:console /debug /machine:I386 +# ADD LINK32 CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "Apache - Win32 Release" +# Name "Apache - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\os\win32\main_win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/Apache.mak b/APACHE_1_3b7/src/Apache.mak new file mode 100644 index 0000000000..738e11bdb0 --- /dev/null +++ b/APACHE_1_3b7/src/Apache.mak @@ -0,0 +1,170 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on Apache.dsp +!IF "$(CFG)" == "" +CFG=Apache - Win32 Release +!MESSAGE No configuration specified. Defaulting to Apache - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "Apache - Win32 Release" && "$(CFG)" != "Apache - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Apache.mak" CFG="Apache - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Apache - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Apache - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Apache - Win32 Release" + +OUTDIR=.\ApacheR +INTDIR=.\ApacheR +# Begin Custom Macros +OutDir=.\.\ApacheR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\Apache.exe" + +!ELSE + +ALL : "$(OUTDIR)\Apache.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\main_win32.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\Apache.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)\Apache.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheR/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Apache.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console\ + /incremental:no /pdb:"$(OUTDIR)\Apache.pdb" /machine:I386\ + /out:"$(OUTDIR)\Apache.exe" +LINK32_OBJS= \ + "$(INTDIR)\main_win32.obj" + +"$(OUTDIR)\Apache.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Apache - Win32 Debug" + +OUTDIR=.\ApacheD +INTDIR=.\ApacheD +# Begin Custom Macros +OutDir=.\.\ApacheD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\Apache.exe" + +!ELSE + +ALL : "$(OUTDIR)\Apache.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\main_win32.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\Apache.exe" + -@erase "$(OUTDIR)\Apache.ilk" + -@erase "$(OUTDIR)\Apache.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)\Apache.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheD/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Apache.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console\ + /incremental:yes /pdb:"$(OUTDIR)\Apache.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)\Apache.exe" +LINK32_OBJS= \ + "$(INTDIR)\main_win32.obj" + +"$(OUTDIR)\Apache.exe" : "$(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) $< +<< + + +!IF "$(CFG)" == "Apache - Win32 Release" || "$(CFG)" == "Apache - Win32 Debug" +SOURCE=.\os\win32\main_win32.c + +"$(INTDIR)\main_win32.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + + +!ENDIF + diff --git a/APACHE_1_3b7/src/ApacheCore.def b/APACHE_1_3b7/src/ApacheCore.def new file mode 100644 index 0000000000..8bf0fe8ba5 --- /dev/null +++ b/APACHE_1_3b7/src/ApacheCore.def @@ -0,0 +1 @@ +LIBRARY ApacheCore diff --git a/APACHE_1_3b7/src/ApacheCore.dsp b/APACHE_1_3b7/src/ApacheCore.dsp new file mode 100644 index 0000000000..1f5f68e4c8 --- /dev/null +++ b/APACHE_1_3b7/src/ApacheCore.dsp @@ -0,0 +1,413 @@ +# Microsoft Developer Studio Project File - Name="ApacheCore" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheCore - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheCore.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheCore.mak" CFG="ApacheCore - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheCore - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheCore - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\ApacheCo" +# PROP BASE Intermediate_Dir ".\ApacheCo" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\CoreR" +# PROP Intermediate_Dir ".\CoreR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 os\win32\ApacheOSR\ApacheOS.lib regex\release\regex.lib ap\Release\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\ApacheC0" +# PROP BASE Intermediate_Dir ".\ApacheC0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\CoreD" +# PROP Intermediate_Dir ".\CoreD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 os\win32\ApacheOSD\ApacheOS.lib regex\debug\regex.lib ap\Debug\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# SUBTRACT LINK32 /map + +!ENDIF + +# Begin Target + +# Name "ApacheCore - Win32 Release" +# Name "ApacheCore - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\main\alloc.c +# End Source File +# Begin Source File + +SOURCE=.\ApacheCore.def +# End Source File +# Begin Source File + +SOURCE=.\main\buff.c +# End Source File +# Begin Source File + +SOURCE=.\buildmark.c +# End Source File +# Begin Source File + +SOURCE=.\main\fnmatch.c +# End Source File +# Begin Source File + +SOURCE=.\os\win32\getopt.c +# End Source File +# Begin Source File + +SOURCE=.\main\http_config.c +# End Source File +# Begin Source File + +SOURCE=.\main\http_core.c +# End Source File +# Begin Source File + +SOURCE=.\main\http_log.c +# End Source File +# Begin Source File + +SOURCE=.\main\http_main.c +# End Source File +# Begin Source File + +SOURCE=.\main\http_protocol.c +# End Source File +# Begin Source File + +SOURCE=.\main\http_request.c +# End Source File +# Begin Source File + +SOURCE=.\main\http_vhost.c +# End Source File +# Begin Source File + +SOURCE=.\main\md5c.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_access.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_actions.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_alias.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_asis.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_auth.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_autoindex.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_cgi.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_dir.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_env.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_imap.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_include.c +# End Source File +# Begin Source File + +SOURCE=.\os\win32\mod_isapi.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_log_config.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_mime.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_negotiation.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_setenvif.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_so.c +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_userdir.c +# End Source File +# Begin Source File + +SOURCE=.\os\win32\modules.c +# End Source File +# Begin Source File + +SOURCE=.\os\win32\multithread.c +# End Source File +# Begin Source File + +SOURCE=.\os\win32\readdir.c +# End Source File +# Begin Source File + +SOURCE=.\os\win32\registry.c +# End Source File +# Begin Source File + +SOURCE=.\main\rfc1413.c +# End Source File +# Begin Source File + +SOURCE=.\os\win32\service.c +# End Source File +# Begin Source File + +SOURCE=.\main\util.c +# End Source File +# Begin Source File + +SOURCE=.\main\util_date.c +# End Source File +# Begin Source File + +SOURCE=.\main\util_md5.c +# End Source File +# Begin Source File + +SOURCE=.\main\util_script.c +# End Source File +# Begin Source File + +SOURCE=.\main\util_uri.c +# End Source File +# Begin Source File + +SOURCE=.\os\win32\util_win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\include\alloc.h +# End Source File +# Begin Source File + +SOURCE=.\include\ap.h +# End Source File +# Begin Source File + +SOURCE=.\include\buff.h +# End Source File +# Begin Source File + +SOURCE=.\include\conf.h +# End Source File +# Begin Source File + +SOURCE=.\include\explain.h +# End Source File +# Begin Source File + +SOURCE=.\include\fnmatch.h +# End Source File +# Begin Source File + +SOURCE=.\os\win32\getopt.h +# End Source File +# Begin Source File + +SOURCE=.\include\hsregex.h +# End Source File +# Begin Source File + +SOURCE=.\include\http_conf_globals.h +# End Source File +# Begin Source File + +SOURCE=.\include\http_config.h +# End Source File +# Begin Source File + +SOURCE=.\include\http_core.h +# End Source File +# Begin Source File + +SOURCE=.\include\http_log.h +# End Source File +# Begin Source File + +SOURCE=.\include\http_main.h +# End Source File +# Begin Source File + +SOURCE=.\include\http_protocol.h +# End Source File +# Begin Source File + +SOURCE=.\include\http_request.h +# End Source File +# Begin Source File + +SOURCE=.\include\http_vhost.h +# End Source File +# Begin Source File + +SOURCE=.\include\httpd.h +# End Source File +# Begin Source File + +SOURCE=.\include\md5.h +# End Source File +# Begin Source File + +SOURCE=.\modules\standard\mod_mime.h +# End Source File +# Begin Source File + +SOURCE=.\include\multithread.h +# End Source File +# Begin Source File + +SOURCE=.\os\win32\os.h +# End Source File +# Begin Source File + +SOURCE=.\os\win32\readdir.h +# End Source File +# Begin Source File + +SOURCE=.\os\win32\registry.h +# End Source File +# Begin Source File + +SOURCE=.\include\rfc1413.h +# End Source File +# Begin Source File + +SOURCE=.\include\scoreboard.h +# End Source File +# Begin Source File + +SOURCE=.\os\win32\service.h +# End Source File +# Begin Source File + +SOURCE=.\include\util_date.h +# End Source File +# Begin Source File + +SOURCE=.\include\util_md5.h +# End Source File +# Begin Source File + +SOURCE=.\include\util_script.h +# End Source File +# Begin Source File + +SOURCE=.\include\util_uri.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "Generated Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\main\test_char.h +# End Source File +# Begin Source File + +SOURCE=.\main\uri_delims.h +# End Source File +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/ApacheCore.mak b/APACHE_1_3b7/src/ApacheCore.mak new file mode 100644 index 0000000000..f972d1bfef --- /dev/null +++ b/APACHE_1_3b7/src/ApacheCore.mak @@ -0,0 +1,2728 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheCore.dsp +!IF "$(CFG)" == "" +CFG=ApacheCore - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheCore - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "ApacheCore - Win32 Release" && "$(CFG)" !=\ + "ApacheCore - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheCore.mak" CFG="ApacheCore - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheCore - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheCore - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +OUTDIR=.\CoreR +INTDIR=.\CoreR +# Begin Custom Macros +OutDir=.\.\CoreR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheCore.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheCore.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\alloc.obj" + -@erase "$(INTDIR)\buff.obj" + -@erase "$(INTDIR)\buildmark.obj" + -@erase "$(INTDIR)\fnmatch.obj" + -@erase "$(INTDIR)\getopt.obj" + -@erase "$(INTDIR)\http_config.obj" + -@erase "$(INTDIR)\http_core.obj" + -@erase "$(INTDIR)\http_log.obj" + -@erase "$(INTDIR)\http_main.obj" + -@erase "$(INTDIR)\http_protocol.obj" + -@erase "$(INTDIR)\http_request.obj" + -@erase "$(INTDIR)\http_vhost.obj" + -@erase "$(INTDIR)\md5c.obj" + -@erase "$(INTDIR)\mod_access.obj" + -@erase "$(INTDIR)\mod_actions.obj" + -@erase "$(INTDIR)\mod_alias.obj" + -@erase "$(INTDIR)\mod_asis.obj" + -@erase "$(INTDIR)\mod_auth.obj" + -@erase "$(INTDIR)\mod_autoindex.obj" + -@erase "$(INTDIR)\mod_cgi.obj" + -@erase "$(INTDIR)\mod_dir.obj" + -@erase "$(INTDIR)\mod_env.obj" + -@erase "$(INTDIR)\mod_imap.obj" + -@erase "$(INTDIR)\mod_include.obj" + -@erase "$(INTDIR)\mod_isapi.obj" + -@erase "$(INTDIR)\mod_log_config.obj" + -@erase "$(INTDIR)\mod_mime.obj" + -@erase "$(INTDIR)\mod_negotiation.obj" + -@erase "$(INTDIR)\mod_setenvif.obj" + -@erase "$(INTDIR)\mod_so.obj" + -@erase "$(INTDIR)\mod_userdir.obj" + -@erase "$(INTDIR)\modules.obj" + -@erase "$(INTDIR)\multithread.obj" + -@erase "$(INTDIR)\readdir.obj" + -@erase "$(INTDIR)\registry.obj" + -@erase "$(INTDIR)\rfc1413.obj" + -@erase "$(INTDIR)\service.obj" + -@erase "$(INTDIR)\util.obj" + -@erase "$(INTDIR)\util_date.obj" + -@erase "$(INTDIR)\util_md5.obj" + -@erase "$(INTDIR)\util_script.obj" + -@erase "$(INTDIR)\util_uri.obj" + -@erase "$(INTDIR)\util_win32.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheCore.dll" + -@erase "$(OUTDIR)\ApacheCore.exp" + -@erase "$(OUTDIR)\ApacheCore.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D\ + "_WINDOWS" /Fp"$(INTDIR)\ApacheCore.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\CoreR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheCore.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=os\win32\ApacheOSR\ApacheOS.lib regex\release\regex.lib\ + ap\Release\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\ + /incremental:no /pdb:"$(OUTDIR)\ApacheCore.pdb" /machine:I386\ + /def:".\ApacheCore.def" /out:"$(OUTDIR)\ApacheCore.dll"\ + /implib:"$(OUTDIR)\ApacheCore.lib" +DEF_FILE= \ + ".\ApacheCore.def" +LINK32_OBJS= \ + "$(INTDIR)\alloc.obj" \ + "$(INTDIR)\buff.obj" \ + "$(INTDIR)\buildmark.obj" \ + "$(INTDIR)\fnmatch.obj" \ + "$(INTDIR)\getopt.obj" \ + "$(INTDIR)\http_config.obj" \ + "$(INTDIR)\http_core.obj" \ + "$(INTDIR)\http_log.obj" \ + "$(INTDIR)\http_main.obj" \ + "$(INTDIR)\http_protocol.obj" \ + "$(INTDIR)\http_request.obj" \ + "$(INTDIR)\http_vhost.obj" \ + "$(INTDIR)\md5c.obj" \ + "$(INTDIR)\mod_access.obj" \ + "$(INTDIR)\mod_actions.obj" \ + "$(INTDIR)\mod_alias.obj" \ + "$(INTDIR)\mod_asis.obj" \ + "$(INTDIR)\mod_auth.obj" \ + "$(INTDIR)\mod_autoindex.obj" \ + "$(INTDIR)\mod_cgi.obj" \ + "$(INTDIR)\mod_dir.obj" \ + "$(INTDIR)\mod_env.obj" \ + "$(INTDIR)\mod_imap.obj" \ + "$(INTDIR)\mod_include.obj" \ + "$(INTDIR)\mod_isapi.obj" \ + "$(INTDIR)\mod_log_config.obj" \ + "$(INTDIR)\mod_mime.obj" \ + "$(INTDIR)\mod_negotiation.obj" \ + "$(INTDIR)\mod_setenvif.obj" \ + "$(INTDIR)\mod_so.obj" \ + "$(INTDIR)\mod_userdir.obj" \ + "$(INTDIR)\modules.obj" \ + "$(INTDIR)\multithread.obj" \ + "$(INTDIR)\readdir.obj" \ + "$(INTDIR)\registry.obj" \ + "$(INTDIR)\rfc1413.obj" \ + "$(INTDIR)\service.obj" \ + "$(INTDIR)\util.obj" \ + "$(INTDIR)\util_date.obj" \ + "$(INTDIR)\util_md5.obj" \ + "$(INTDIR)\util_script.obj" \ + "$(INTDIR)\util_uri.obj" \ + "$(INTDIR)\util_win32.obj" + +"$(OUTDIR)\ApacheCore.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +OUTDIR=.\CoreD +INTDIR=.\CoreD +# Begin Custom Macros +OutDir=.\.\CoreD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheCore.dll" "$(OUTDIR)\ApacheCore.bsc" + +!ELSE + +ALL : "$(OUTDIR)\ApacheCore.dll" "$(OUTDIR)\ApacheCore.bsc" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\alloc.obj" + -@erase "$(INTDIR)\alloc.sbr" + -@erase "$(INTDIR)\buff.obj" + -@erase "$(INTDIR)\buff.sbr" + -@erase "$(INTDIR)\buildmark.obj" + -@erase "$(INTDIR)\buildmark.sbr" + -@erase "$(INTDIR)\fnmatch.obj" + -@erase "$(INTDIR)\fnmatch.sbr" + -@erase "$(INTDIR)\getopt.obj" + -@erase "$(INTDIR)\getopt.sbr" + -@erase "$(INTDIR)\http_config.obj" + -@erase "$(INTDIR)\http_config.sbr" + -@erase "$(INTDIR)\http_core.obj" + -@erase "$(INTDIR)\http_core.sbr" + -@erase "$(INTDIR)\http_log.obj" + -@erase "$(INTDIR)\http_log.sbr" + -@erase "$(INTDIR)\http_main.obj" + -@erase "$(INTDIR)\http_main.sbr" + -@erase "$(INTDIR)\http_protocol.obj" + -@erase "$(INTDIR)\http_protocol.sbr" + -@erase "$(INTDIR)\http_request.obj" + -@erase "$(INTDIR)\http_request.sbr" + -@erase "$(INTDIR)\http_vhost.obj" + -@erase "$(INTDIR)\http_vhost.sbr" + -@erase "$(INTDIR)\md5c.obj" + -@erase "$(INTDIR)\md5c.sbr" + -@erase "$(INTDIR)\mod_access.obj" + -@erase "$(INTDIR)\mod_access.sbr" + -@erase "$(INTDIR)\mod_actions.obj" + -@erase "$(INTDIR)\mod_actions.sbr" + -@erase "$(INTDIR)\mod_alias.obj" + -@erase "$(INTDIR)\mod_alias.sbr" + -@erase "$(INTDIR)\mod_asis.obj" + -@erase "$(INTDIR)\mod_asis.sbr" + -@erase "$(INTDIR)\mod_auth.obj" + -@erase "$(INTDIR)\mod_auth.sbr" + -@erase "$(INTDIR)\mod_autoindex.obj" + -@erase "$(INTDIR)\mod_autoindex.sbr" + -@erase "$(INTDIR)\mod_cgi.obj" + -@erase "$(INTDIR)\mod_cgi.sbr" + -@erase "$(INTDIR)\mod_dir.obj" + -@erase "$(INTDIR)\mod_dir.sbr" + -@erase "$(INTDIR)\mod_env.obj" + -@erase "$(INTDIR)\mod_env.sbr" + -@erase "$(INTDIR)\mod_imap.obj" + -@erase "$(INTDIR)\mod_imap.sbr" + -@erase "$(INTDIR)\mod_include.obj" + -@erase "$(INTDIR)\mod_include.sbr" + -@erase "$(INTDIR)\mod_isapi.obj" + -@erase "$(INTDIR)\mod_isapi.sbr" + -@erase "$(INTDIR)\mod_log_config.obj" + -@erase "$(INTDIR)\mod_log_config.sbr" + -@erase "$(INTDIR)\mod_mime.obj" + -@erase "$(INTDIR)\mod_mime.sbr" + -@erase "$(INTDIR)\mod_negotiation.obj" + -@erase "$(INTDIR)\mod_negotiation.sbr" + -@erase "$(INTDIR)\mod_setenvif.obj" + -@erase "$(INTDIR)\mod_setenvif.sbr" + -@erase "$(INTDIR)\mod_so.obj" + -@erase "$(INTDIR)\mod_so.sbr" + -@erase "$(INTDIR)\mod_userdir.obj" + -@erase "$(INTDIR)\mod_userdir.sbr" + -@erase "$(INTDIR)\modules.obj" + -@erase "$(INTDIR)\modules.sbr" + -@erase "$(INTDIR)\multithread.obj" + -@erase "$(INTDIR)\multithread.sbr" + -@erase "$(INTDIR)\readdir.obj" + -@erase "$(INTDIR)\readdir.sbr" + -@erase "$(INTDIR)\registry.obj" + -@erase "$(INTDIR)\registry.sbr" + -@erase "$(INTDIR)\rfc1413.obj" + -@erase "$(INTDIR)\rfc1413.sbr" + -@erase "$(INTDIR)\service.obj" + -@erase "$(INTDIR)\service.sbr" + -@erase "$(INTDIR)\util.obj" + -@erase "$(INTDIR)\util.sbr" + -@erase "$(INTDIR)\util_date.obj" + -@erase "$(INTDIR)\util_date.sbr" + -@erase "$(INTDIR)\util_md5.obj" + -@erase "$(INTDIR)\util_md5.sbr" + -@erase "$(INTDIR)\util_script.obj" + -@erase "$(INTDIR)\util_script.sbr" + -@erase "$(INTDIR)\util_uri.obj" + -@erase "$(INTDIR)\util_uri.sbr" + -@erase "$(INTDIR)\util_win32.obj" + -@erase "$(INTDIR)\util_win32.sbr" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheCore.bsc" + -@erase "$(OUTDIR)\ApacheCore.dll" + -@erase "$(OUTDIR)\ApacheCore.exp" + -@erase "$(OUTDIR)\ApacheCore.ilk" + -@erase "$(OUTDIR)\ApacheCore.lib" + -@erase "$(OUTDIR)\ApacheCore.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I ".\include" /D "WIN32" /D "_DEBUG"\ + /D "_WINDOWS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\ApacheCore.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\CoreD/ +CPP_SBRS=.\CoreD/ +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheCore.bsc" +BSC32_SBRS= \ + "$(INTDIR)\alloc.sbr" \ + "$(INTDIR)\buff.sbr" \ + "$(INTDIR)\buildmark.sbr" \ + "$(INTDIR)\fnmatch.sbr" \ + "$(INTDIR)\getopt.sbr" \ + "$(INTDIR)\http_config.sbr" \ + "$(INTDIR)\http_core.sbr" \ + "$(INTDIR)\http_log.sbr" \ + "$(INTDIR)\http_main.sbr" \ + "$(INTDIR)\http_protocol.sbr" \ + "$(INTDIR)\http_request.sbr" \ + "$(INTDIR)\http_vhost.sbr" \ + "$(INTDIR)\md5c.sbr" \ + "$(INTDIR)\mod_access.sbr" \ + "$(INTDIR)\mod_actions.sbr" \ + "$(INTDIR)\mod_alias.sbr" \ + "$(INTDIR)\mod_asis.sbr" \ + "$(INTDIR)\mod_auth.sbr" \ + "$(INTDIR)\mod_autoindex.sbr" \ + "$(INTDIR)\mod_cgi.sbr" \ + "$(INTDIR)\mod_dir.sbr" \ + "$(INTDIR)\mod_env.sbr" \ + "$(INTDIR)\mod_imap.sbr" \ + "$(INTDIR)\mod_include.sbr" \ + "$(INTDIR)\mod_isapi.sbr" \ + "$(INTDIR)\mod_log_config.sbr" \ + "$(INTDIR)\mod_mime.sbr" \ + "$(INTDIR)\mod_negotiation.sbr" \ + "$(INTDIR)\mod_setenvif.sbr" \ + "$(INTDIR)\mod_so.sbr" \ + "$(INTDIR)\mod_userdir.sbr" \ + "$(INTDIR)\modules.sbr" \ + "$(INTDIR)\multithread.sbr" \ + "$(INTDIR)\readdir.sbr" \ + "$(INTDIR)\registry.sbr" \ + "$(INTDIR)\rfc1413.sbr" \ + "$(INTDIR)\service.sbr" \ + "$(INTDIR)\util.sbr" \ + "$(INTDIR)\util_date.sbr" \ + "$(INTDIR)\util_md5.sbr" \ + "$(INTDIR)\util_script.sbr" \ + "$(INTDIR)\util_uri.sbr" \ + "$(INTDIR)\util_win32.sbr" + +"$(OUTDIR)\ApacheCore.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +LINK32_FLAGS=os\win32\ApacheOSD\ApacheOS.lib regex\debug\regex.lib\ + ap\Debug\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\ + /incremental:yes /pdb:"$(OUTDIR)\ApacheCore.pdb" /debug /machine:I386\ + /def:".\ApacheCore.def" /out:"$(OUTDIR)\ApacheCore.dll"\ + /implib:"$(OUTDIR)\ApacheCore.lib" +DEF_FILE= \ + ".\ApacheCore.def" +LINK32_OBJS= \ + "$(INTDIR)\alloc.obj" \ + "$(INTDIR)\buff.obj" \ + "$(INTDIR)\buildmark.obj" \ + "$(INTDIR)\fnmatch.obj" \ + "$(INTDIR)\getopt.obj" \ + "$(INTDIR)\http_config.obj" \ + "$(INTDIR)\http_core.obj" \ + "$(INTDIR)\http_log.obj" \ + "$(INTDIR)\http_main.obj" \ + "$(INTDIR)\http_protocol.obj" \ + "$(INTDIR)\http_request.obj" \ + "$(INTDIR)\http_vhost.obj" \ + "$(INTDIR)\md5c.obj" \ + "$(INTDIR)\mod_access.obj" \ + "$(INTDIR)\mod_actions.obj" \ + "$(INTDIR)\mod_alias.obj" \ + "$(INTDIR)\mod_asis.obj" \ + "$(INTDIR)\mod_auth.obj" \ + "$(INTDIR)\mod_autoindex.obj" \ + "$(INTDIR)\mod_cgi.obj" \ + "$(INTDIR)\mod_dir.obj" \ + "$(INTDIR)\mod_env.obj" \ + "$(INTDIR)\mod_imap.obj" \ + "$(INTDIR)\mod_include.obj" \ + "$(INTDIR)\mod_isapi.obj" \ + "$(INTDIR)\mod_log_config.obj" \ + "$(INTDIR)\mod_mime.obj" \ + "$(INTDIR)\mod_negotiation.obj" \ + "$(INTDIR)\mod_setenvif.obj" \ + "$(INTDIR)\mod_so.obj" \ + "$(INTDIR)\mod_userdir.obj" \ + "$(INTDIR)\modules.obj" \ + "$(INTDIR)\multithread.obj" \ + "$(INTDIR)\readdir.obj" \ + "$(INTDIR)\registry.obj" \ + "$(INTDIR)\rfc1413.obj" \ + "$(INTDIR)\service.obj" \ + "$(INTDIR)\util.obj" \ + "$(INTDIR)\util_date.obj" \ + "$(INTDIR)\util_md5.obj" \ + "$(INTDIR)\util_script.obj" \ + "$(INTDIR)\util_uri.obj" \ + "$(INTDIR)\util_win32.obj" + +"$(OUTDIR)\ApacheCore.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) $< +<< + + +!IF "$(CFG)" == "ApacheCore - Win32 Release" || "$(CFG)" ==\ + "ApacheCore - Win32 Debug" +SOURCE=.\main\alloc.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_ALLOC=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\multithread.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_ALLOC=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\multithread.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\alloc.obj" "$(INTDIR)\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\buff.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_BUFF_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\buff.obj" : $(SOURCE) $(DEP_CPP_BUFF_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_BUFF_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\buff.obj" "$(INTDIR)\buff.sbr" : $(SOURCE) $(DEP_CPP_BUFF_)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\buildmark.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_BUILD=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_BUILD=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\buildmark.obj" : $(SOURCE) $(DEP_CPP_BUILD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_BUILD=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\buildmark.obj" "$(INTDIR)\buildmark.sbr" : $(SOURCE)\ + $(DEP_CPP_BUILD) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\main\fnmatch.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_FNMAT=\ + ".\include\conf.h"\ + ".\include\fnmatch.h"\ + ".\include\hsregex.h"\ + ".\os\win32\os.h"\ + + +"$(INTDIR)\fnmatch.obj" : $(SOURCE) $(DEP_CPP_FNMAT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_FNMAT=\ + ".\include\conf.h"\ + ".\include\fnmatch.h"\ + ".\include\hsregex.h"\ + ".\os\win32\os.h"\ + + +"$(INTDIR)\fnmatch.obj" "$(INTDIR)\fnmatch.sbr" : $(SOURCE) $(DEP_CPP_FNMAT)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\getopt.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + + +"$(INTDIR)\getopt.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + + +"$(INTDIR)\getopt.obj" "$(INTDIR)\getopt.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_config.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\explain.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_HTTP_=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\http_config.obj" : $(SOURCE) $(DEP_CPP_HTTP_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\explain.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\http_config.obj" "$(INTDIR)\http_config.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_core.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_C=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\fnmatch.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\md5.h"\ + ".\include\rfc1413.h"\ + ".\include\scoreboard.h"\ + ".\include\util_md5.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_HTTP_C=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\http_core.obj" : $(SOURCE) $(DEP_CPP_HTTP_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_C=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\fnmatch.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\md5.h"\ + ".\include\rfc1413.h"\ + ".\include\scoreboard.h"\ + ".\include\util_md5.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\http_core.obj" "$(INTDIR)\http_core.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_log.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_L=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_HTTP_L=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\http_log.obj" : $(SOURCE) $(DEP_CPP_HTTP_L) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_L=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\http_log.obj" "$(INTDIR)\http_log.sbr" : $(SOURCE) $(DEP_CPP_HTTP_L)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_main.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\explain.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\multithread.h"\ + ".\include\scoreboard.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\getopt.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + ".\os\win32\registry.h"\ + ".\os\win32\service.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_HTTP_M=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\http_main.obj" : $(SOURCE) $(DEP_CPP_HTTP_M) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\explain.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\multithread.h"\ + ".\include\scoreboard.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\getopt.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + ".\os\win32\registry.h"\ + ".\os\win32\service.h"\ + + +"$(INTDIR)\http_main.obj" "$(INTDIR)\http_main.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_M) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_protocol.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_P=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\util_date.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_HTTP_P=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\http_protocol.obj" : $(SOURCE) $(DEP_CPP_HTTP_P) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_P=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\util_date.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\http_protocol.obj" "$(INTDIR)\http_protocol.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_P) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_request.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_R=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\fnmatch.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\scoreboard.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_HTTP_R=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\http_request.obj" : $(SOURCE) $(DEP_CPP_HTTP_R) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_R=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\fnmatch.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\scoreboard.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\http_request.obj" "$(INTDIR)\http_request.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_R) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_vhost.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_V=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_log.h"\ + ".\include\http_protocol.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_HTTP_V=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\http_vhost.obj" : $(SOURCE) $(DEP_CPP_HTTP_V) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_V=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_log.h"\ + ".\include\http_protocol.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\http_vhost.obj" "$(INTDIR)\http_vhost.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_V) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\md5c.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MD5C_=\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\md5.h"\ + ".\os\win32\os.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MD5C_=\ + ".\include\os.h"\ + + +"$(INTDIR)\md5c.obj" : $(SOURCE) $(DEP_CPP_MD5C_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MD5C_=\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\md5.h"\ + ".\os\win32\os.h"\ + + +"$(INTDIR)\md5c.obj" "$(INTDIR)\md5c.sbr" : $(SOURCE) $(DEP_CPP_MD5C_)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_access.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_A=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_A=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_access.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_A=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_access.obj" "$(INTDIR)\mod_access.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_actions.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AC=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_AC=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_actions.obj" : $(SOURCE) $(DEP_CPP_MOD_AC) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AC=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_actions.obj" "$(INTDIR)\mod_actions.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_AC) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_alias.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AL=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_AL=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_alias.obj" : $(SOURCE) $(DEP_CPP_MOD_AL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AL=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_alias.obj" "$(INTDIR)\mod_alias.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_AL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_asis.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_AS=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_asis.obj" : $(SOURCE) $(DEP_CPP_MOD_AS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_asis.obj" "$(INTDIR)\mod_asis.sbr" : $(SOURCE) $(DEP_CPP_MOD_AS)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_auth.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AU=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_protocol.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_AU=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_auth.obj" : $(SOURCE) $(DEP_CPP_MOD_AU) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AU=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_protocol.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_auth.obj" "$(INTDIR)\mod_auth.sbr" : $(SOURCE) $(DEP_CPP_MOD_AU)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_autoindex.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AUT=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_AUT=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_autoindex.obj" : $(SOURCE) $(DEP_CPP_MOD_AUT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AUT=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_autoindex.obj" "$(INTDIR)\mod_autoindex.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_AUT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_cgi.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_C=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_C=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_cgi.obj" : $(SOURCE) $(DEP_CPP_MOD_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_C=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_cgi.obj" "$(INTDIR)\mod_cgi.sbr" : $(SOURCE) $(DEP_CPP_MOD_C)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_dir.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_D=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_D=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_dir.obj" : $(SOURCE) $(DEP_CPP_MOD_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_D=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_dir.obj" "$(INTDIR)\mod_dir.sbr" : $(SOURCE) $(DEP_CPP_MOD_D)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_env.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_E=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_E=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_env.obj" : $(SOURCE) $(DEP_CPP_MOD_E) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_E=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_env.obj" "$(INTDIR)\mod_env.sbr" : $(SOURCE) $(DEP_CPP_MOD_E)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_imap.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_I=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_I=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_imap.obj" : $(SOURCE) $(DEP_CPP_MOD_I) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_I=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_imap.obj" "$(INTDIR)\mod_imap.sbr" : $(SOURCE) $(DEP_CPP_MOD_I)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_include.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_IN=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_IN=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + ".\modules\standard\config.h"\ + ".\modules\standard\modules\perl\mod_perl.h"\ + + +"$(INTDIR)\mod_include.obj" : $(SOURCE) $(DEP_CPP_MOD_IN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_IN=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_include.obj" "$(INTDIR)\mod_include.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_IN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\mod_isapi.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_IS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_IS=\ + ".\include\ebcdic.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_isapi.obj" : $(SOURCE) $(DEP_CPP_MOD_IS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_IS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_isapi.obj" "$(INTDIR)\mod_isapi.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_IS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_log_config.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_L=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_L=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_log_config.obj" : $(SOURCE) $(DEP_CPP_MOD_L) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_L=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_log_config.obj" "$(INTDIR)\mod_log_config.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_L) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_mime.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_M=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_mime.obj" : $(SOURCE) $(DEP_CPP_MOD_M) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_mime.obj" "$(INTDIR)\mod_mime.sbr" : $(SOURCE) $(DEP_CPP_MOD_M)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_negotiation.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_N=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_N=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_negotiation.obj" : $(SOURCE) $(DEP_CPP_MOD_N) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_N=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_negotiation.obj" "$(INTDIR)\mod_negotiation.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_N) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_setenvif.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_S=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_S=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_setenvif.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_S=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_setenvif.obj" "$(INTDIR)\mod_setenvif.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_so.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_SO=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_SO=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_so.obj" : $(SOURCE) $(DEP_CPP_MOD_SO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_SO=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_so.obj" "$(INTDIR)\mod_so.sbr" : $(SOURCE) $(DEP_CPP_MOD_SO)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_userdir.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_U=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_U=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\mod_userdir.obj" : $(SOURCE) $(DEP_CPP_MOD_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_U=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_userdir.obj" "$(INTDIR)\mod_userdir.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\modules.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MODUL=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MODUL=\ + ".\include\ebcdic.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\modules.obj" : $(SOURCE) $(DEP_CPP_MODUL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MODUL=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_config.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\modules.obj" "$(INTDIR)\modules.sbr" : $(SOURCE) $(DEP_CPP_MODUL)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\multithread.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MULTI=\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\multithread.h"\ + ".\os\win32\os.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\multithread.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MULTI=\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\multithread.h"\ + ".\os\win32\os.h"\ + + +"$(INTDIR)\multithread.obj" "$(INTDIR)\multithread.sbr" : $(SOURCE)\ + $(DEP_CPP_MULTI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\readdir.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_READD=\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\readdir.obj" : $(SOURCE) $(DEP_CPP_READD) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_READD=\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\readdir.obj" "$(INTDIR)\readdir.sbr" : $(SOURCE) $(DEP_CPP_READD)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\registry.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_REGIS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_REGIS=\ + ".\include\ebcdic.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\registry.obj" : $(SOURCE) $(DEP_CPP_REGIS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_REGIS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\registry.obj" "$(INTDIR)\registry.sbr" : $(SOURCE) $(DEP_CPP_REGIS)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\rfc1413.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_RFC14=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\httpd.h"\ + ".\include\rfc1413.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_RFC14=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\rfc1413.obj" : $(SOURCE) $(DEP_CPP_RFC14) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_RFC14=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\httpd.h"\ + ".\include\rfc1413.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\rfc1413.obj" "$(INTDIR)\rfc1413.sbr" : $(SOURCE) $(DEP_CPP_RFC14)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\service.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_SERVI=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\httpd.h"\ + ".\include\multithread.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + ".\os\win32\registry.h"\ + ".\os\win32\service.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_SERVI=\ + ".\include\ebcdic.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\service.obj" : $(SOURCE) $(DEP_CPP_SERVI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_SERVI=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\httpd.h"\ + ".\include\multithread.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + ".\os\win32\registry.h"\ + ".\os\win32\service.h"\ + + +"$(INTDIR)\service.obj" "$(INTDIR)\service.sbr" : $(SOURCE) $(DEP_CPP_SERVI)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\main\test_char.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_UTIL_=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\util.obj" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\main\test_char.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) $(DEP_CPP_UTIL_)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util_date.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_D=\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\util_date.h"\ + ".\os\win32\os.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_UTIL_D=\ + ".\include\os.h"\ + + +"$(INTDIR)\util_date.obj" : $(SOURCE) $(DEP_CPP_UTIL_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_D=\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\util_date.h"\ + ".\os\win32\os.h"\ + + +"$(INTDIR)\util_date.obj" "$(INTDIR)\util_date.sbr" : $(SOURCE)\ + $(DEP_CPP_UTIL_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util_md5.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\httpd.h"\ + ".\include\md5.h"\ + ".\include\util_md5.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_UTIL_M=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\util_md5.obj" : $(SOURCE) $(DEP_CPP_UTIL_M) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\httpd.h"\ + ".\include\md5.h"\ + ".\include\util_md5.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\util_md5.obj" "$(INTDIR)\util_md5.sbr" : $(SOURCE) $(DEP_CPP_UTIL_M)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util_script.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_S=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_date.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_UTIL_S=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\util_script.obj" : $(SOURCE) $(DEP_CPP_UTIL_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_S=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_config.h"\ + ".\include\http_core.h"\ + ".\include\http_log.h"\ + ".\include\http_main.h"\ + ".\include\http_protocol.h"\ + ".\include\http_request.h"\ + ".\include\httpd.h"\ + ".\include\util_date.h"\ + ".\include\util_script.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\util_script.obj" "$(INTDIR)\util_script.sbr" : $(SOURCE)\ + $(DEP_CPP_UTIL_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util_uri.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_U=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\main\uri_delims.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_UTIL_U=\ + ".\include\ebcdic.h"\ + ".\include\os.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\util_uri.obj" : $(SOURCE) $(DEP_CPP_UTIL_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_U=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\http_conf_globals.h"\ + ".\include\http_log.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\main\uri_delims.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\util_uri.obj" "$(INTDIR)\util_uri.sbr" : $(SOURCE) $(DEP_CPP_UTIL_U)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\util_win32.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_W=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_UTIL_W=\ + ".\include\ebcdic.h"\ + ".\include\sfio.h"\ + + +"$(INTDIR)\util_win32.obj" : $(SOURCE) $(DEP_CPP_UTIL_W) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_W=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\buff.h"\ + ".\include\conf.h"\ + ".\include\hsregex.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\util_win32.obj" "$(INTDIR)\util_win32.sbr" : $(SOURCE)\ + $(DEP_CPP_UTIL_W) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/CHANGES b/APACHE_1_3b7/src/CHANGES new file mode 100644 index 0000000000..1ce3131f09 --- /dev/null +++ b/APACHE_1_3b7/src/CHANGES @@ -0,0 +1,4598 @@ +Changes with Apache 1.3b7 + + *) Make sure a MIME-type can be forced via a RewriteRule even when no + substitution takes place, for instance via the following rule: + ``RewriteRule ^myscript$ - [T=application/x-httpd-cgi]'' This was often + requested by users in the past to force a single script without a .cgi + extension and outside any cgi-bin dirs to be executed as a CGI program. + [Ralf S. Engelschall] PR#2254 + + *) A fix for protocol issues surrounding 400, 408, and + 414 responses. [Ed Korthof] + + *) Ignore MaxRequestsPerChild on WIN32. [Brian Behlendorf] + + *) Fix discrepancy in proxy_ftp.c which was causing failures when + trying to connect to certain ftpd's, such as anonftpd. + [Rick Ohnemus ] + + *) Make mod_rewrite use ap_open_piped_log() for RewriteLog directive's + logfile instead of fiddling around itself with child spawning stuff. + [Ralf S. Engelschall] + + *) Made RefererIgnore case-insensitive. + + *) Mod_log_agent, mod_log_referer now use ap_open_piped_log for piped logs. + [Brian Behlendorf] + + *) Replace use of spawn_child with ap_spawn_child_err_buff, to make everything + "safe" under Win32. In: mod_include.c, mod_mime_magic.c + [Brian Behlendorf] + + *) Improve RFC1413 support. [Bob Beck ] + + *) Fix support script `dbmmanage': It was unable to handle some sort + of passwords, especially passwords with "0" chars. + [Ralf S. Engelschall] PR#2242 + + *) WIN32: Clicking on "Last Modified" in a fancy index caused a crash. Fixed. + [Ben Laurie] PR#2238 + + *) WIN32: CGIs could cause a hang (because of a deadlock in the standard C + library), so CGI handling has been changed to use Win32 native handles + instead of C file descriptors. + [Ben Laurie and Bill Stoddard ] PR#1129, 1607 + + *) The proxy cache would store an incorrect content-length in the cached + file copy after a cache update. That resulted in repeated fetching + of the original copy instead of using the cached copy. + [Ernst Kloppenburg ] PR#2094 + + *) The Makefiles assumed that DSO files are build via $(LD). This + is broken for two reasons: First we never defined at least LD=ld + somewhere to make sure this works (it was silently assumed that most Make + provide a built-in LD definition - ARGL!) and second using the generic LD + variable is not the truth. Instead a special variable named LD_SHLIB is + reasonable because although "ld" is usually the default, the command for + building DSO files can be "libtool" or even "cc" on some systems. + [Ralf S. Engelschall] + + *) Replace the AddVersionPlatform directive with ServerTokens which + provides for more control over the format of the Server: + header line. SERVER_SUBVERSION is no longer supported; + all module should use the ap_add_version_component() + API function instead. [Jim Jagielski] + + *) Support for the NCR MP/RAS 3.0 + [John Withers ] + + *) The LDFLAGS_SHLIB_EXPORT variable of src/Configuration[.tmpl] was + not retrieved in src/Configure and thus was not useable. + [Ralf S. Engelschall] + + *) Various Makefile consistency cleanups: + - make OSDIR also automatically be relative to src/ like INCDIR + - SUBDIRS is now generated in src/Makefile only and not in + Makefile.config because it is a local define for this location. + - remove BROKEN_BPRINTF_FLAGS because is it no longer used inside + any Makefile but make sure that at least the "-K inline" is kept in + CFLAGS for SCO 5. + - update the "depend" targets in Makefile.tmpl files to use $(OSDIR), too. + - updated the dependencies theirself + - removed not existing SHLIB variable from "clean" targets + - replaced SHLIB_OBJS/SHLIBS_OBJ consistently with OBJS_PIC because OBJS + already exists and OBJS_PIC are also just plain objects and have not + directly to do with "shared" things. The only difference is that they + contain PIC. So OBJS_PIC is the more canonical name. + - Updated the Makefile-dependency lines for OBJS_PIC + - Removed the Makefile-dependency line in Configure to avoid double + definitions + - replaced ugly xx-so.o/xx.so-o hack with a clean and consistent usage + of xxx.lo as GNU libtool does with its PIC objects + - reduce local complexity in modules Makefile.tmpl by moving the last + existing target "depend" to the generation section in Configure, too. + - removed the historical $(SPACER) which was used in the past together + with BROKEN_BPRINTF_FLAGS to avoid zig-zags in the build process. This + is no longer needed. + - force the build and run of the gen_xxx programs under main/ as the + first step before building the objects because it looks cleaner + [Ralf S. Engelschall] + + *) WIN32: Make Win32 work again after the /dev/null DoS fix. + [Ben Laurie] + + *) WIN32: Check for buffer overflows in ap_os_canonical_filename. + [Ben Laurie] + + *) WIN32: Don't force ISAPI headers to finish with \n. + [Jim Patterson , Ben Laurie] PR#2060 + + *) When opening "configuration" files (like httpd.conf, htaccess + and htpasswd), Apache will not allow them to be non-/dev/null + device files. This closes a DoS hole. At the same time, + we use ap_pfopen to open these files to handle timeouts. + [Jim Jagielski, Martin Kraemer] + + *) Apache will now log the reason its httpd children exit if they exit + due to an unexpected signal. (It requires a new porting define, + SYS_SIGLIST, which if defined should point to a list of text + descriptions of the signals available. See PORTING.) [Dean Gaudet] + + *) chdir() doesn't make sense in a multithreaded environment like WIN32. + Before, Win32 CGI's could have had sporadic failures if a chdir call + from one thread was made between another chdir call and a spawn in + another thread. So, for now don't chdir for CGI scripts in WIN32. + The current CGI "spec" is unclear as to whether it's necessary. Long- + term fix is to either serialize the chdir/spawn combo or use WIN32 + native calls to spawn a process. This temp fix was necessary to remove + this as a showstopper for 1.3's release. [Brian Behlendorf] + + *) Cleanup the suEXEC support in APACI and make it more safe: + 1. Add big fat hint in INSTALL about risks and to read the + htdocs/manual/suexec.html document before using the suexec-related + configure options. + 2. Make sure the user has at least provided one --suexec-xxxx option + (specifies suEXEC parameters) in addition to --enable-suexec option. + If only --enable-suexec is given APACI stops with a hint to INSTALL + and htdocs/manual/suexec.html documents. + 3. Provide two additional --suexec-xxxx options to make the suEXEC + configuration complete (especially for package maintainers who else + had to patch the source tree) by providing ways to configure minimal + UID/GID and safe PATH, too. + [Ralf S. Engelschall] + + *) Cleanup of the `configure --shadow' process: + - make sure the configure script creates its temporary files in the + shadow tree to avoid conflicts with parallel configure runs + - removed unnecessary option "-r" from "rm" call for Makefiles + - make sure the configure scripts creates the shadow-wrapper Makefile + only when no shadow trees already exists + - make sure "make distclean" removes the shadow-wrapper Makefile but only + when no more shadow trees exists + - overhauled mkshadow.sh script: now its more IFS-safe and approx. twice + as fast (in the past it needed 70sec, now it runs just 38sec) + - make sure CVS does not complain about the created files + Makefille. and directories src. + [Ralf S. Engelschall] + + *) Added the ap_add_version_component() API routine and the + AddVersionPlatform core directive. The first allows modules to + declare themselves in the Server response header field value, + augmenting the SERVER_SUBVERSION define in the Configuration file + with run-time settings (more useful in a loadable-module environment). + AddVersionPlatform inserts a comment such as "(UNIX)" or "(Win32)" + into the server version string. [Ken Coar] PR#2056 + + *) Minor stability tweaks to avoid core dumps in ap_snprintf. + [Martin Kraemer] + + *) Emit the "Accept-Range" header for the default handler. + [Brian Behlendorf] PR#1464 + + *) Add a note to httpd.conf-dist that apache will on some systems fail + to start when the Group # is set to a negative or large positive value. + [Martin Kraemer] + + *) Make sure the module execution order is correct even when some modules + are loaded under runtime (`LoadModule') via the DSO mechanism: + 1. The list of loaded modules is now a dynamically allocated one + and not the original statically list from modules.c + 2. The loaded modules are now correctly setup by LoadModule for + later use by the AddModule command. + 3. When the DSO mechanism for modules is used APACI's `install' + target now enables all created `LoadModule' lines per default because + this is both already expected by the user _and_ needed to avoid + confusion with the next point and reduces the Makefile.tmpl complexity + 4. When the DSO mechanism for modules is used, APACI's `install' + target now additionally makes sure the module list is reconstructed + via a complete `ClearModuleList+AddModule...' entry. + 5. The support tool `apxs' now also makes sure an AddModule command + is added in addition to the LoadModule command. + 6. The modules.c generation was extended to now contain two + comments to make sure no one is confused by the confusing terminology + of loading/linking (we use load=link+load & link=activate instead of + the obvious load=activate & link=link :-( ) + This way now there is no longer a difference under execution time between + statically and dynamically linked modules. + [Ralf S. Engelschall] + + *) Fix the generated mod_xxx.c from "apxs -g -f xxx" after the + Big Symbol Renaming. [Ralf S. Engelschall] + + *) Add a comment to mod_example.c showing the format of a FLAG command + handler. [Ken Coar] + + *) Standardized the time format in mod_status to match that of other + places in the code (e.g. DATE_GMT). PR#1551 + + *) Fix handling of %Z in timefmt strings for those platforms with no time + zone information in their tm struct. [Paul Eggert ] + PR#754 + + *) Makes mod_rewrite, mod_log_config, mod_status and the ServerSignature + feature compatible with 'UseCanonicalName off' by changing + r->server->server_hostname to ap_get_server_name(). And I changed some + functions which use r->server->port to use ap_get_server_port() instead, + because if there's no Port directive in the config r->server->port is 0. + [Lars Eilebrecht] + + *) get/set_module_config are trivial enough to be better off inline. Worth + 1.5% performance boost. [Dean Gaudet] + + *) Fix off-by-one error in ap_proxy_date_canon() in proxy_util.c + when ensuring 'x' is at least 30-chars big. [Jim Jagielski, + Brian Behlendorf] + + *) [BS2000 security] BS2000 needs an extra authentication to initialize + the task environment to the unprivileged User id. Otherwise CGI scripts + would have a way to gain super user access. [Martin Kraemer] + + *) Fix debug log messages for BS2000/OSD: instead of logging the whole + absolute path, only log base name of logging source as is done + in unix. [Martin Kraemer] + + *) Ronald Tschalaer's Accept-Encoding patch - preserve the "x-" in + the encoding type from the Accept-Encoding header (if it's there) + and use it in the response, as that's probably what it'll be expecting. + [Ronald.Tschalaer@psi.ch] + + *) Fix to mod_alias: translate_alias_redir is dealing with + a URI, not a filename, so the check for drive letters for win32 + and emx is not necessary. [Dean Gaudet] + + *) WIN32: Allow .cmd as an executable extension. + [Kari Likovuori ] PR#2146 + + *) Make Apache header files, and some variables, C++ friendly. + [Michael Anderson's ] + + *) Child processes can now "signal" (by exiting with a status + of APEXIT_CHILDFATAL) the parent process to abort and + shutdown the server if the error in the child process was + fatal enough. [Jim Jagielski] + + *) mod_autoindex's find_itme() was sensitive to MIME type case. + [Jim Jagielski] PR#2112 + + *) Make sure the referer_log and agent_log entries in the default httpd.conf + file are also adjusted for the actual relative installation paths. + [Ralf S. Engelschall] PR#2175 + + *) WIN32: Extensive overhaul of the way UNCs are handled. [Ben Laurie] + + *) WIN32: Make roots of filesystems (e.g. c:/) work. [Ben Laurie] + PR#1558 + + *) PORT: Various porting changes to support AIX 3.2, 4.1.5, 4.2 and 4.3. + Additionally the checks for finding the vendor DSO library were moved + from mod_so.c to Configure because first it needs $PLAT etc. and second + mod_so already uses an abstraction layer and does not fiddle with the + vendor functions itself. + [Jens-Uwe Mager, Ralf S. Engelschall] + + *) PORT: Some optimization defines for NetBSD + [Jaromir Dolecek ] PR#2165 + + *) PORT: Dynamic Shared Object (DSO) support for NetBSD. + [Jaromir Dolecek , Ralf S. Engelschall] PR#2158 + + *) Add Dynamic Shared Object (DSO) support for AIX (at least 4.2 but older + AIX variants should work fine, too. Even AIX 3.x should work). This is + accomplished by using the free DSO emulation code from Jens-Uwe Mager + which we put into a os/unix/os-dso-aix.c file. + [Ralf S. Engelschall] + + *) PORT: Fix compiler warnings under AIX >= 4.2 where the manual pages imply + that we should use NET_SIZE_T == int but the include files force size_t. + [Ralf S. Engelschall] + + *) Fix two bugs in select() handling in http_main.c. + [Roy Fielding] + + *) Suppress "error(0)" messages for ap_log_error() when the APLOG_NOERRNO + is unset (as it is in situations like timeouts) where it is unclear + whether errno is set or not. [Martin Kraemer] + + *) Just having APACI's localstatedir is too general and not enough for most + of the systems. 1.3b6 again required manual APACI patches by package + maintainers from RedHat and FreeBSD because for their filesystem layout a + little bit more flexibility in configuring the paths is needed. Hence we + provide three additional configure options (--runtimedir, --logfiledir, + --proxycachedir) which now can be used for more granular adjustments if + --localstatedir is not enough to fit the particular needs. As a nice + side-effect this reduces some subdir fiddling in configure+Makefile.tmpl. + [Ralf S. Engelschall] + + *) Make the install root for "make install" in APACI's Makefile overrideable + by package authors. This way we are even more friendly to package + maintainers (especially Debian and RedHat) who build for the real prefix + via "configure --prefix=/" but use a different local prefix via + "make root=/tmp/apache install" for rolling the package without bristling + the target location on their system. + [Ralf S. Engelschall] + + *) Workaround sed limitations in APACI's configure script by now + substituting in chunks of 50 commands (because for instance HPUX's vendor + sed has a limit of max. 98 commands) + [Ralf S. Engelschall] PR#2136 + + *) Adding SOCKS5 support and fixing existing SOCKS4 support. + [Ralf S. Engelschall] PR#2140 + + *) Manually fix some symbols which were not renamed to prefix ap_ in the BIG + RENAMING process because they are defined as pre-processor macros instead + of real functions: bputc, bgetc, piped_log_write_fd, piped_log_read_fd + [Ralf S. Engelschall] + + *) Workaround braindead AWK's when generating ap_config.h: The split() and + substr() functions cannot be nested under vendor AWK from Solaris 2.6. + [Ralf S. Engelschall] PR#2139 + + *) Various bugfixes and cleanups for the APACI configure script: + o fix IFS handling for _nested_ situation + o fix Perl interpreter search: take first one found instead of last one + o fix DSO consistency check + o print error messages to stderr instead of stdout + o add install-quiet for --shadow situation to Makefile stub + o reduce complexity by avoiding sed-hacks for rule and module list loops + [Ralf S. Engelschall] + + *) Fix DEBUG_CGI situation in mod_cgi.c [David MacKenzie] PR#2114 + + *) Make sure the input field separator (IFS) shell variable is explicitly + initialized correctly before _every_ `for' loop and also restored after + the loops. [Ralf S. Engelschall] + + *) Make sure that "make install" doesn't overwrite the `mime.types' and + `magic' files from an existing Apache installation. Because people often + customize these for own MIME and content types. + [Ralf S. Engelschall] + + *) PORT: Dynamic Shared Object (DSO) support for OpenBSD 2.x + [Peter Galbavy, Ralf S. Engelschall] PR#2109 + + *) Fix the path to the ScoreBoardFile in the install-config target, too. + [Ralf S. Engelschall] PR#2105 + + *) Let "configure" clear out the users parameters (provided as shell + variables) to avoid side-effects in "src/Configure" when the user + exported them (which is not needed, but some users do it). + [Ralf S. Engelschall] PR#2101 + + *) Provide backward compatibility from some old src/Configuration.tmpl + parameter names to the canonical Autoconf-style shell variable names. For + instance CFLAGS vs. EXTRA_CFLAGS. The EXTRA_xxx variants are accepted now + but a hint message is displayed. [Ralf S. Engelschall] + + *) Make sure that "make install" doesn't overwrite the DocumentRoot and + CGI scripts from an existing Apache installation. + [Ralf S. Engelschall, Jim Jagielski] PR#2084 + + *) Make `configure --compat' more "compatible" by first + let the libexecdir default to EPREFIX/libexec instead of EPREFIX/bin and + second by making sure the "avoid-bristling-suffix" /apache is not + appended to sysconfdir, datadir, localstatedir and includedir when + --compat is used. [Ralf S. Engelschall, Lars Eilebrecht] + + *) NeXT required strdup() in support/logresolve.c + [Francisco Tomei ] PR#2082 + + *) AIX required sys/select.h in support/ab.c + [Jens Schleusener ] PR#2081 + + *) Fix the path to the MimeMagicFile in the install-config target, too. + [Ralf S. Engelschall] PR#2089 + + *) PORT: Added HP-UX 11 patches [Jeff Earickson ] + + *) If you start apache with the -S command line option it will dump + out the parsed vhost settings. This is useful for folks trying + to figure out what is wrong with their vhost configuration. + (Other dumps may be added in the future.) [Dean Gaudet] + + *) Add %pA, %pI, and %pp codes to ap_vformatter (and hence ap_bprintf, + ap_snprintf, and ap_psprintf). See include/ap.h for docs. + [Dean Gaudet] + + *) Because /usr/local/apache is the default prefix the ``configure + --compat'' option no longer has to set prefix, again. This way the + --compat option honors a leading --prefix option. [Lars Eilebrecht] + + *) PORT: Cast the first argument of dlopen() in ap_os_dso_load() + to `char *' under OSF1 and FreeBSD 2.x where it is defined this way + to avoid "discard const" warnings. [Ralf S. Engelschall] + + *) If a specific handler is set for a file yet the request still + ends up being handled by the default handler, log an error + message before handling it. This catches things such as trying + to use SSIs without mod_include enabled. [Marc Slemko] + + *) Fix error logging for the startup case where ap_log_error() still uses + stderr as the target. Now the default log level is honored here, too. + [Ralf S. Engelschall] + + *) PORT: Make sure some AWK's don't fail in src/Configure with "string too + long" errors when generating the MODULES entry for src/Makefile + [Ben Hyde, Ralf S. Engelschall] + + *) Make sure src/Configure doesn't complain about the old directory + /usr/local/etc/httpd/ when APACI is used. [Lars Eilebrecht] + +Changes with Apache 1.3b6 + + *) PORT: Clean up warnings on Ultrix and HPUX. [Ben Hyde] + + *) Adding DSO support for the HP/UX platform by emulating the dlopen-style + interface via the similar but proprietary HP/UX shl_xxx-style system + calls. [Ralf S. Engelschall] + + *) PORT: Updated UnixWare 2.0.x and 2.1.x entries for DSO support and made + APACI Makefile.tmpl "install" target more robust for sensible UnixWare + Make. [Ralf S. Engelschall] + + *) ++++ THE BIG SYMBOL RENAMING ++++ + To avoid symbol clashes with third-party code compiled into the server, + we globally applied the prefix "ap_" to the following classes of + functions: + - Apache provided general functions (e.g., ap_cpystrn) + - Public API functions (e.g., palloc, bgets) + - Private functions which we can't make static (because of + cross-object usage) but should be (e.g., new_connection) + For backward source compatibility a new header file named compat.h was + created which provides defines for the old symbol names and can be used + by third-party module authors. + [The Apache Group] + + *) Added dynamic shared object (DSO) support for SVR4-derivates: The + problem under SVR4 is that there is no command flag to force the linker + to export the global symbols of the httpd executable therewith they are + available to the DSO's. Instead of problematic hacks like creating a + dummy.so file (containing dummy references to all global symbols) the + httpd binary is linked against, we use a clean trick stolen from Perl 5: + Placing the Apache core code itself into a DSO library named libhttpd.so. + This way the global symbols _HAVE_ to be exported and thus are available + to any manually loaded DSO's under runtime. To reduce the impact to the + user to null we go even further and create a stub httpd executable which + automatically keeps track of the DSO library loading itself and thus + hides the complete mechanism from the user. Although the generation of + this DSO library is automatically triggered for platforms which + essentially need it (mostly all SVR4-derivates) it can be also enabled + manually via the Rule SHARED_CORE. This can be interesting in the future + where we perhaps exploit this libhttpd.so mechanism for providing nifty + features like graceful upgrades, or whatever. + [Ralf S. Engelschall, Martin Kraemer] + + *) Build the libraries before building the rest of the tools. [Ben Hyde] + + *) Add "distclean" target to src/-Makefiles to provide "make distclean" also + inside the src subtree (i.e. for non-APACI users). Following GNU Makefile + conventions while "clean" removes only stuff created by "all" targets, + "distclean" additionally removes the stuff from the configuration + process. This way "make distclean" (hence the name) provides a fresh + source tree as it was for distribution. + [Ralf S. Engelschall] + + *) Allow top-level (APACI) Makefile to break on build errors + the same way the src/ subtree Makefiles breaks on them by replacing the + initial APACI sed-subdir-display-kludge with a more clean + variable-passing-solution: variable SDP can optionally hold the subdir + prefix which is consistently used for displaying the subdir movement. + This way even the top-level Makefile can stop correctly on errors as the + user expects. [Ralf S. Engelschall] + + *) Fixed ordering of argument checks for RewriteBase directive. + [Todd Eigenschink ] PR#2045 + + *) Change Win32 IS_MODULE to SHARED_MODULE to match Unix' method of + indicating that a module is being compiled for dynamic loading. Also + remove #define IS_MODULE from modules and add SHARED_MODULE define + to the mak/dsp files. [Alexei Kosut] + + *) Reduce logging level of "normal" warning messages to APLOG_INFO, + since we are now logging APLOG_WARNING by default. [Roy Fielding] + + *) PORT: OS/2 tweak to deal with multiple .exe targets. [Brian Havard] + + *) Add documentation file and src/Configuration.tmpl entry for the + experimental mod_mmap_static module. Because although it is and marked as + an experimental one it is distributed and thus should be documented and + prepared for configuration the same way as all others modules. + [Ralf S. Engelschall] + + *) Add query (-q) option to apxs support tool to be able to manually query + specific settings from apxs. This is needed for instance when you + manually want to access Apache's header files and you need to assemble + the -I option. Now you can do -I`apxs -q INCLUDEDIR`. + [Ralf S. Engelschall] + + *) Now src/Configure uses a fallback strategy for the shared object support + on platforms where no explicit information is available: If a Perl + installation exists we ask it about its shared object support and if it's + the dlopen-style one we shamelessly guess the compiler and linker flags + for creating shared objects from Perls knowledge. Of course, the user is + warning about what we are doing and informed that he should send us + the guessed flags when they work. [Ralf S. Engelschall] + + *) Provide APACI --without-support option to be able to disable the build + and installation of the support tools from the src/support/ area. + Although its useful to have these installed per default we should provide + a way to compile and install without them for backward-compatibility. + [Ralf S. Engelschall] + + *) Add of the new APache eXtenSion (apxs) support tool for building and + installing modules into an _already installed_ Apache package through the + dynamic shared object (DSO) mechanism [mod_so.c]. The trick here is that + this approach actually doesn't need the Apache source tree. The + (APACI-installed) server package is enough, because this now includes the + Apache C header files (PREFIX/include) and the new APXS tool + (SBINDIR/apxs). The intend is to provide a handy tool for third-party + module authors to build their Apache modules _OUTSIDE_ the Apache source + tree while avoiding them to fiddle around with the totally platform + dependend way of compiling DSO files. The tool supports all ranges of + modules, from trivial ones (single mod_foo.c) to complex ones (like PHP3 + which has a mod_php3.c plus a pre-built libmodphp3-so.a) and even can + on-the-fly generate a minimalistic Makefile and sample module for the + first step to provide both a quick success event and to demonstrate the + APXS mechanism to module authors. [Ralf S. Engelschall] + + *) Fix core dumps in use of CONNECT in proxy. + [Rainer.Scherg@rexroth.de] PR#1326, #1573, #1942 + + *) Modify the log directives in httpd.conf-dist files to use CustomLog + so that users have examples of how CustomLog can be used. + [Lars Eilebrecht] + + *) Add the new Apache Autoconf-style Interface (APACI) for the top-level of + the Apache distribution tree. Until Apache 1.3 there was no real + out-of-the-box batch-capable build and installation procedure for the + complete Apache package. This is now provided by a top-level "configure" + script and a corresponding top-level "Makefile.tmpl" file. The goal is + to provide a GNU Autoconf-style frontend which is capable to both drive + the old src/Configure stuff in batch and additionally installs the + package with a GNU-conforming directory layout. Any options from the old + configuration scheme are available plus a lot of new options for flexibly + customizing Apache. [Ralf S. Engelschall] + + *) The floating point ap_snprintf code wasn't threadsafe. + Had to remove the HAVE_CVT macro in order to do threadsafe + calling of the ?cvt() floating point routines. [Dean Gaudet] + + *) PORT: Add the SCO_SV port. [Jim Jagielski] PR#1962 + + *) PORT: IRIX needs the -n32 flag iff using the 'cc' compiler + [Jim Jagielski] PR#1901 + + *) BUG: Configure was using TCC and CC inconsistantly. Make sure + Configure knows which CC we are using. [Jim Jagielski] + + *) "Options +Includes" wasn't correctly merged if "+IncludesNoExec" + was defined in a parent directory. [Lars Eilebrecht] + + *) API: ap_snprintf() code mutated into ap_vformatter(), which is + a generic printf-style routine that can call arbitrary output + routines. Use this to replace http_bprintf.c. Add new routines + psprintf(), pvsprintf() which allocate the exact amount of memory + required for a string from a pool. Use psprintf() to clean up + various bits of code which used ap_snprintf()/pstrdup(). + [Dean Gaudet] + + *) PORT: HAVE_SNPRINTF doesn't do anything any longer. This is because + ap_snprintf() has different semantics and formatting codes than + snprintf(). [Dean Gaudet] + + *) SIGXCPU and SIGXFSZ are now reset to SIG_DFL at boot-time. This + is necessary on at least Solaris where the /etc/rc?.d scripts + are run with these signals ignored, and "SIG_IGN" settings are + maintained across exec(). + [Rein Tollevik ] PR#2009 + + *) Fix the check for symbolic links in ``RewriteCond ... -l'': stat() was + used instead of lstat() and thus this flag didn't work as expected. + [Rein Tollevik ] PR#2010 + + *) Fix the proxy pass-through feature of mod_rewrite for the case of + existing QUERY_STRING now that mod_proxy was recently changed because of + the new URL parsing stuff. [Ralf S. Engelschall] + + *) A few changes to scoreboard definitions which helps gcc generate + better code. [Dean Gaudet] + + *) ANSI C doesn't guarantee that "int foo : 2" in a structure will + be a signed bitfield. So mark a few bitfields as signed to + ensure correct code. [Dean Gaudet] + + *) The default for HostnameLookups was changed to Off, but there + was a problem and it wasn't taking effect. [Dean Gaudet] + + *) PORT: Clean up undefined signals on some platforms (SCO, BeOS). + [Dean Gaudet] + + *) After a SIGHUP the listening sockets in the parent weren't + properly marked for closure on fork(). + [Jürgen Keil ] PR#2000 + + *) Allow %2F in two situations: 1) it is in the query part of the URI, + therefore not exposed to %2F -> '/' translations and 2) the request + is a proxy request, so we're not dealing with a local resource anyway. + Without this, the proxy would fail to work for any URL's with + %2f in them (occurs quite often in + http://.../cgi-bin/...?http%3A%2F%2F... references) [Martin Kraemer] + + *) Protect against FD_SETSIZE mismatches. [Dean Gaudet] + + *) Make the shared object compilation command more portable by avoiding + the direct combination of `-c' & `-o' which is not honored by some + compilers like UnixWare's cc. [Ralf S. Engelschall] + + *) WIN32: the proxy was creating filenames missing the last four + characters. While this normally doesn't stop anything from + working, it can result in extra collisions. + [Tim Costello ] PR#1890 + + *) Now mod_proxy uses the response string (in addition to the response status + code) from the already used FTP SIZE command to setup the Content-Length + header if available. [Ralf S. Engelschall] PR#1183 + + *) Reanimated the (still undocumented) proxy receive buffer size directive: + Renamed from ReceiveBufferSize to ProxyReceiveBufferSize because the old + name was really too generic, added documentation for this directive to + the mod_proxy.html and corrected the hyperlink to it in the + new_features_1.3.html document. [Ralf S. Engelschall] PR#1348 + + *) Fix a bug in the src/helpers/fp2rp script and make it a little bit + faster [Martin Kraemer] + + *) Make Configure die when you give it an unknown command switch. + [Ben Hyde] + + *) Add five new and fresh manpages for the support programs: dbmmanage.1, + suexec.8, htdigest.1, rotatelogs.8 and logresolve.8. Now all up-to-date + and per default compiled support programs have manual pages - just to + document our stuff a little bit more and to be able to do really + Unix-like installations ;-) [Ralf S. Engelschall] + + *) Major cleanups to the Configure script to make it and its generated + Makefiles again readable and maintainable: add SRCDIR option, removed + INCLUDES_DEPTH[0-2] kludge, cleanup of TARGET option, cleanup of + generated sections, consequently added Makefile headers with inheritance + information, added subdir movement messages for easier following where + the build process currently stays (more verbose then standard Make, less + verbose than GNU make), same style to comments in the Configure script, + added Apache license header, fixed a few bugs, etc. [Ralf S. Engelschall] + + *) Add the new ApacheBench program "ab" to src/support/: This is derived + from the ZeusBench benchmarking program and can be used to determine the + response performance of an Apache installation. This version is + officially licensed with Zeus Technology, Ltd. See the license agreement + statements in <199803171224.NAA24547@en1.engelschall.com> in apache-core. + [Ralf S. Engelschall] + + *) API: Various core functions that are definately not part of the API + have been made static, and a few have been marked API_EXPORT. Still + more have been marked CORE_EXPORT and are not intended for general + use by modules. [Doug MacEachern, Dean Gaudet] + + *) mod_proxy was not clearing the Proxy-Connection header from + requests; now it does. This did not violate any spec, however + causes poor interactions when you are talking to remote proxies. + [Marc Slemko] PR#1741 + + *) Various cleanups to the command line interface and manual pages. + [Ralf S. Engelschall] + + *) cfg_getline() was not properly handling lines that did not end + with a line termination character. [Marc Slemko] PR#1869, 1909 + + *) Performance tweak to mod_log_config. [Dmitry Khrustalev] + + *) Clean up some undocumented behavior of mod_setenvif related to + "merging" two SetEnvIf directives when they match the same header + and regex. Document that mod_setenvif will perform comparisons in + the order they appear in the config file. Optimize mod_setenvif by + doing more work at config time rather than at runtime. + [Dean Gaudet] + + *) src/include/ap_config.h now wraps it's #define's with #ifndef/#endif's + to allow for modules to overrule them and to reduce redefinition + warnings [Jim Jagielski] + + *) [PORT] For A/UX change the OS-#define for -DAUX to -DAUX3. + [Jim Jagielski] + + *) Making the hard-coded cross-module function call mime_find_ct() (from + mod_proxy to mod_mime) obsolete by making sure the API hook for MIME type + checking is really called even for proxy requests except for URLs with + HTTP schemes (because there we can optimize by not running the type + checking hooks due to the fact that the proxy gets the MIME Content-type + from the remote host later). This change cleans up mod_mime by removing + the ugly export kludge, makes the one-liner file mod_mime.h obsolete, and + especially unbundles mod_proxy and mod_mime. This way they both now can + be compiled as shared objects and are no longer tied together. + [Ralf S. Engelschall] + + *) util.c cleanup and speedup. [Dean Gaudet] + + *) API: Clarification, pstrndup() will always copy n bytes of the source + and NUL terminate at the (n+1)st byte. [Dean Gaudet] + + *) Mark module command_rec and handler_rec structures const so that they + end up in the read-only data section (and are friendlier to systems + that don't do optimistic memory allocation on fork()). [Dean Gaudet] + + *) Add check to the "Port" directive to make sure the specified + port is in the appropriate range. [Ben Hyde] + + *) Performance improvements to invoke_handler(). + [Dmitry Khrustalev ] + + *) Added support for building shared objects even for library-style modules + (which are built from more than one object file). This now provides the + ability to build mod_proxy as a shared object module. Additionally + modules like mod_example are now also supported for shared object + building because the generated Makefiles now no longer assume there is at + least one statically linked module. [Ralf S. Engelschall] + + *) API: Clarify usage of content_type, handler, content_encoding, + content_language and content_languages fields in request_rec. They + must always be lowercased; and the strings pointed to shouldn't + be modified (you must copy them to modify them). Fix a few bugs + related to this. [Dean Gaudet] + + *) API: Clarification: except for RAW_ARGS, all command handlers can + treat the char * parameters as permanent, and modifiable. There + is no need to pstrdup() them. Clean up some needless pstrdup(). + [Dean Gaudet] + + *) Now mod_so keeps track of which module shared objects with which names + are loaded and thus avoids multiple loading and unloading and irritating + error_log messages. [Ralf S. Engelschall] + + *) Prior to the existence of mod_setenv it was necessary to tweak the TZ + environment variable in the apache core. But that tweaking interferes + with mod_setenv. So don't tweak if the user has specified an explicit + TZ variable. [Jay Soffian ] PR#1888 + + *) rputs() did not calculate r->sent_bodyct properly. + [Siegmund Stirnweiss ] PR#1900 + + *) The CGI spec says that REMOTE_HOST should be set to the remote hosts's + name, or left unset if this value is unavailable. Apache was setting + it to the IP address when unavailable. + [Tony Fincg ] PR#1925 + + *) Various improvements to the configuration and build support for compiling + modules as shared objects. Especially Solaris 2.x, SunOS 4.1, IRIX and + OSF1 support with GCC and vendor compilers was added. This way shared + object support is now provided out-of-the-box for FreeBSD, Linux, + Solaris, SunOS, IRIX and OSF1. In short: On all major platforms! + [Ralf S. Engelschall] + + *) Minor cleanup in http_main -- split QNX and OS2 specific "mmap" + scoreboard code into separate #defines -- USE_POSIX_SCOREBOARD + and USE_OS2_SCOREBOARD. [Dean Gaudet] + + *) Fix one more special locking problem for RewriteMap programs in + mod_rewrite: According to the documentation of flock(), "Locks are on + files, not file descriptors. That is, file descriptors duplicated + through dup(2) or fork(2) do not result in multiple instances of a lock, + but rather multiple references to a single lock. If a process holding a + lock on a file forks and the child explicitly unlocks the file, the + parent will lose its lock.". To overcome this we have to make sure the + RewriteLock file is opened _AFTER_ the childs were spawned which is now + the case by opening it in the child_init instead of the module_init API + hook. [Ralf S. Engelschall] PR#1029 + + *) Change to Location and LocationMatch semantics. LocationMatch no + longer lets a single slash match multiple adjacent slashes in the + URL. This change is for consistency with RewriteRule and + AliasMatch. Multiple slashes have meaning in URLs that they do + not have in (some) filesystems. Location on the other hand can + be considered a shorthand for a more complicated regex, and it + does match multiple slashes with a single slash -- which is + also consistent with the Alias directive. + [Dean Gaudet] related PR#1440 + + *) Fix bug with mod_mime_magic causing certain files, including files + of length 0, to result in no response from the server. + [Dean Gaudet] + + *) The Configure script now generates src/include/ap_config.h which + contains the set of defines used when Apache is compiled on a platform. + This file can then be included by external modules before including + any Apache header files in case they are being built separately from + Apache. Along with this change, a couple of minor changes were + made to make Apache's #defines coexist peacefully with any autoconf + defines an external module might have. [Rasmus Lerdorf] + + *) Fix mod_rewrite for the ugly API case where sections exist + but without any RewriteXXXXX directives. Here mod_rewrite is given no + chance by the API to initialize its per-server configuration and thus + receives the wrong one from the main server. This is now avoided by + remembering the server together with the config structure while + configuring and later assuming there is no config when we see a + difference between the remembered server and the one calling us. + [Ralf S. Engelschall] PR#1790 + + *) Fixed the DBM RewriteMap support for mod_rewrite: First the support now + is automatically disabled under configure time when the dbm_xxx functions + are not available. Second, two heavy source code errors in the DBM + support code were fixed. This makes DBM RewriteMap's usable again after + a long time of brokenness. [Ralf S. Engelschall] PR#1696 + + *) Now all configuration files support Unix-style line-continuation via + the trailing backslash ("\") character. This enables us to write down + complex or just very long directives in a more readable way. The + backslash character has to be really the last character before the + newline and it has not been prefixed by another (escaping) backslash. + [Ralf S. Engelschall] + + *) When using ProxyPass the ?querystring was not passed correctly. + [Joel Truher ] + + *) To deal with modules being compiled and [dynamically] linked + at a different time from the core, the SERVER_VERSION and + SERVER_BUILT symbols have been abstracted through the new + API routines apapi_get_server_version() and apapi_get_server_built(). + [Ken Coar] PR#1448 + + *) WIN32: Preserve trailing slash in canonical path (and hence + in PATH_INFO). [Paul Sutton, Ben Laurie] + + *) PORT: USE_PTHREAD_SERIALIZED_ACCEPT has proven unreliable + depending on the rev of Solaris and what mixture of modules + are in use. So it has been disabled, and Solaris is back to + using USE_FCNTL_SERIALIZED_ACCEPT. Users may experiment with + USE_PTHREAD_SERIALIZED_ACCEPT at their own risk, it may speed + up static content only servers. Or it may fail unpredictably. + [Dean Gaudet] PR#1779, 1854, 1904 + + *) mod_test_util_uri.c created which tests the logic in util_uri.c. + [Dean Gaudet] + + *) API: Rewrite of absoluteURI handling, and in particular how + absoluteURIs match vhosts. Unless a request is a proxy request, a + "http://host" url is treated as if a similar "Host:" header had been + supplied. This change was made to support future HTTP/1.x protocols + which may require clients to send absoluteURIs for all requests. + + In order to achieve this change subtle changes were made to the API. In a + request_rec, r->hostlen has been removed. r->unparsed_uri now exists so + that the unmodified uri can be retrieved easily. r->proxyreq is not set + by the core, modules must set it during the post_read_request or + translate_names phase. + + Plus changes to the virtualhost test suite for absoluteURI testing. + + This fixes several bugs with the proxy proxying requests to vhosts + managed by the same httpd. + [Dean Gaudet] + + *) API: Cleanup of code in http_vhost.c, and remove vhost matching + code from mod_rewrite. The vhost matching is now performed by a + globally available function matches_request_vhost(). [Dean Gaudet] + + *) Reduce memory usage, and speed up ServerAlias support. As a + side-effect users can list multiple ServerAlias directives + and they're all considered. + [Chia-liang Kao ] PR#1531 + + *) The "poly" directive in image maps did not include the borders of the + polygon, whereas the "rect" directive does. Fix this inconsistency. + [Konstantin Morshnev ] PR#1771 + + *) Make \\ behave as expected. [Ronald.Tschalaer@psi.ch] + + *) Add the `%a' construct to LogFormat and CustomLog to log the client IP + address. [Todd Eigenschink ] PR#1885 + + *) API: A new source module main/util_uri.c; It contains a routine + parse_uri_components() and friends which breaks a URI into its component + parts. These parts are stored in a uri_components structure called + parsed_uri within each request_rec, and are available to all modules. + Additionally, an unparse routine is supplied which re-assembles the URI + components back to an URI, optionally hiding the username:password@ part + from ftp proxy requests, and other useful routines. Within the structure, + you find on a ready-for-use basis: + scheme; /* scheme ("http"/"ftp"/...) */ + hostinfo; /* combined [user[:password]@]host[:port] */ + user; /* user name, as in http://user:passwd@host:port/ */ + password; /* password, as in http://user:passwd@host:port/ */ + hostname; /* hostname from URI (or from Host: header) */ + port_str; /* port string (integer representation is in "port") */ + path; /* the request path (or "/" if only scheme://host was given) */ + query; /* Everything after a '?' in the path, if present */ + fragment; /* Trailing "#fragment" string, if present */ + This is meant to serve as the platform for *BIG* savings in + code complexity for the proxy module (and maybe the vhost logic). + [Martin Kraemer] + + *) Make all possible meta-construct expansions ($N, %N, %{NAME} and + ${map:key}) available for all location where a string is created in + mod_rewrite rewriting rulesets: 1st arg of RewriteCond, 2nd arg of + RewriteRule and for the [E=NAME:STRING] flag of RewriteRule. This way the + possible expansions are consequently usable at all string creation + locations. [Ralf S. Engelschall] + + *) Fix initialization of RewriteLogLevel (default now is 0 as documented + and not 1) and the per-virtual-server merging of directives. Now all + directives except `RewriteEngine' and `RewriteOption' are either + completely overridden (default) or completely inherited (when + `RewriteOptions inherit') is used. [Ralf S. Engelschall] PR#1325 + + *) Fix `RewriteMap' program lookup in situations where such maps are + defined but disabled (`RewriteEngine off') in per-server context. + [Ralf S. Engelschall] PR#1431 + + *) Fix bug introduced in 1.3b4-dev, config with no Port setting would cause + server to bind to port 0 rather than 80. [Dean Gaudet] + + *) Fix long-standing problem with RewriteMap _programs_ under Unix derivates + (like SunOS and FreeBSD) which don't accept the locking of pipes + directly. A new directive RewriteLock is introduced which can be used to + setup a separate locking file which then is used for synchronization. + [Ralf S. Engelschall] PR#1029 + + *) WIN32: The server root is obtained from the registry key + HKLM\SOFTWARE\Apache Group\Apache\ (version is currently + "1.3 beta"), unless overridden by the -d command line flag. The + value is stored by running "apache -i -d serverroot". [Paul Sutton] + + *) Merged os/win32/mod_dll.c into modules/standard/mod_so.c to support + dynamic loading on Win32 and Unix via the same module. [Paul Sutton] + + *) Now mod_rewrite no longer makes problematic assumptions on the characters + a username can contain when trying to expand it via /etc/passwd. + [Ralf S. Engelschall] + + *) The mod_setenvif BrowserMatch backwards compatibility command did not + work properly with spaces in the regex. [Ronald Tschalaer] PR#1825 + + *) Add new RewriteMap types: First, `rnd' which is equivalent to the `txt' + type but with a special post-processing for the looked-up value: It + parses it into alternatives according to `|' chars and then only one + particular alternative is chosen randomly (this is an essential + functionality needed for balancing between backend-servers when using + Apache as a Reverse Proxy. The looked up value here is a list of + servers). Second, `int' with the built-in maps named `tolower' and + `toupper' which can be used to map URL parts to a fixed case (this is an + essential feature to fix the case of server names when doing mass + virtual-hosting with the help of mod_rewrite instead of using + sections). [Ralf S. Engelschall, parts based on code from + Jay Soffian ] PR#1631 + + *) Add a new directive to mod_proxy similar to ProxyPass: `ProxyPassReverse'. + This directive lets Apache adjust the URL in Location-headers on HTTP + redirect responses sent by the remote server. This way the virtually + mapped area is no longer left on redirects and thus by-passed which is + especially essential when running Apache as a reverse proxy. + [Ralf S. Engelschall] + + *) Hide Proxy-Authorization from CGI/SSI/etc just like Authorization is + hidden. [Alvaro Martinez Echevarria] + + *) Apache will, when started with the -X (single process) debugging flag, + honor the SIGINT or SIGQUIT signals again now. This capability got lost + a while ago during OS/2 signal handling changes. + + *) [PORT] Work around the fact that NeXT runs on more than the + m68k chips in mod_status [Scott Anguish and Timothy Luoma + ] + + *) [PORT] Recognize FreeBSD versions so we can use the OS regex as well + as handling unsigned-chars for FreeBSD v3 and v2 [Andrey Chernov + and Jim] PR#1450 + + *) Use SA_RESETHAND or SA_ONESHOT when installing the coredump handlers. + In particular the handlers could trigger themselves into an infinite + loop if RLimitMem was used with a small amount of memory -- too small + for the signal stack frame to be set up. [Dean Gaudet] + + *) Fix problems with absoluteURIs introduced during 1.3b4. [Dean Gaudet, + Alvaro Martinez Echevarria ] + + *) Fix multiple UserDir problem introduced during 1.3b4-dev. + [Dean Gaudet] PR#1850 + + *) ap_cpystrn() had an off-by-1 error. + [Charles Fu ] PR#1847 + + *) API: As Ken suggested the check_cmd_context() function and related + defines are non-static now so modules can use 'em. [Martin Kraemer] + + *) mod_info would occasionally produce an unpaired in its + output. Fixed. [Martin Kraemer] + + *) By default AIX binds a process (and it's children) to a single + processor. httpd children now unbind themselves from that cpu + and re-bind to one selected at random via bindprocessor() + [Doug MacEachern] + + *) Linux 2.0 and above implement RLIMIT_AS, RLIMIT_DATA has almost no + effect. Work around it by using RLIMIT_AS for the RLimitMEM + directive. [Enrik Berkhan ] PR#1816 + + *) mod_mime_magic error message should indicate the filename when + reads fail. ["M.D.Parker" ] PR#1827 + + *) Previously Apache would permit to end (and + similary for Location and Directory), now this is diagnosed as an + error. Improve error messages for mismatched sections (, + , , , ...). + [Dean Gaudet, Martin Kraemer] + + *) is not permitted within (because of the + semantic ordering). [Dean Gaudet] PR#379 + + *) with wildcards was broken by the change in wildcard + semantics (* does not match /). To fix this, now + apply only to the basename of the request filename. This + fixes some other inconsistencies in semantics + (such as not working). [Dean Gaudet] PR#1817 + + *) Removed bogus "dist.tar" target from Makefile.tmpl and make sure + backup files are removed on "clean" target [Ralf S. Engelschall] + + *) PORT: Add -lm to LIBS for HPUX. [Dean Gaudet] PR#1639 + + *) Various errors from select() and accept() in child_main() would + result in an infinite loop. It seems these two tickle kernel + or library bugs occasionally, and result in log spammage and + a generally bad scene. Now the child exits immediately, + which seems to be a good workaround. + [Dean Gaudet] PR#1747, 1107, 588, 1787, 987, 588 + + *) Cleaned up some race conditions in unix child_main during + initialization. [Dean Gaudet] + + *) SECURITY: "UserDir /abspath" without a * in the path would allow + remote users to access "/~.." and bypass access restrictions + (but note /~../.. was handled properly). + [Lauri Jesmin ] PR#1701 + + *) API: os_is_path_absolute() now takes a const char * instead of a char *. + [Dean Gaudet] + +Changes with Apache 1.3b5 + + *) Source file dependencies in Makefile.tmpl files throughout the + source tree were updated to accurately reflect reality. + [Dean Gaudet] + + *) Preserve the content encoding given by the AddEncoding directive + when the client doesn't otherwise specify an encoding. + [Ronald Tschalaer ] + + *) Sort out problems with canonical filename handling happening too late. + [Dean Gaudet, Ben Laurie] + +Changes with Apache 1.3b4 + + *) The module structure was modified to include a *dynamic_load_handle + in the STANDARD_MODULE_STUFF portion, and the MODULE_MAGIC_NUMBER + has been bumped accordingly. [Paul Sutton] + + *) All BrowserMatch directives mentioned in + htdocs/manual/known_client_problems.html are in the default + configuration files. [Lars Eilebrecht] + + *) MiNT port update. [Jan Paul Schmidt] + + *) HTTP/1.1 requires x-gzip and gzip encodings be treated + equivalent, similarly for x-compress and compress. Apache + now ignores a leading x- when comparing encodings. It also + preserves the encoding the client requests (for example if + it requests x-gzip, then Apache will respond with x-gzip + in the Content-Encoding header). + [Ronald Tschalaer ] PR#1772 + + *) Fix a memory leak on keep-alive connections. [Igor Tatarinov] + + *) Added mod_so module to support dynamic loading of modules on Unix + (like mod_dld for Win32). This replaces mod_dld.c. Use SharedModule + instead of AddModule in Configuration to build shared modules + [Sameer Parekh, Paul Sutton] + + *) Minor cleanups to r->finfo handling in some modules. + [Dean Gaudet] + + *) Abstract read()/write() to ap_read()/ap_write(). + Makes it easier to add other types of IO code such as SFIO. + [Randy Terbush] + + *) API: Generalize default_port manipulations to make support of + different protocols easier. [Ben Laurie, Randy Terbush] + + *) There are many cases where users do not want Apache to form + self-referential urls using the "canonical" ServerName and Port. + The new UseCanonicalName directive (default on), if set to off + will cause Apache to use the client-supplied hostname and port. + API: Part of this change required a change to the construct_url() + prototype; and the addition of get_server_name() and + get_server_port(). + [Michael Douglass , Dean Gaudet] + PR#315, 459, 485, 1433 + + *) Yet another rearrangement of the source tree.. now all the common + header files are in the src/include directory. The -Imain -Iap + references in Makefiles have been changed to the simpler -Iinclude + instead. In addition to simplifying the build a little bit, this + also makes it clear when a module is referencing something in a + other than kosher manner (e.g., the proxy including mod_mime.h). + Module-private header files (the proxy, mod_mime, the regex library, + and mod_rewrite) have not been moved to src/include; nor have + the OS-abstraction files. [Ken Coar] + + *) Fix a bug where r->hostname didn't have the :port stripped + from it. [Dean Gaudet] + + *) Tweaked the headers_out table size, and the subprocess_env + table size guess in rename_original_environment(). Added + MAKE_TABLE_PROFILE which can help discover make_table() + calls that use too small an initial guess, see alloc.c. + [Dean Gaudet] + + *) Options and AllowOverride weren't properly merging in the main + server setting inside vhosts (only an issue when you have no + or other section containing an Options that affects + a request). Options +foo or -foo in the main_server wouldn't + affect the main_server's lookup defaults. [Dean Gaudet] + + *) Variable 'cwd' was being used pointlessly before being set. + [Ken Coar] PR#1738 + + *) r->allowed handling cleaned up in the standard modules. + [Dean Gaudet] + + *) Some case-sensitivity issues cleaned up to be consistent with + RFC2068. [Dean Gaudet] + + *) SIGURG doesn't exist everywhere. + [Mark Andrew Heinrich ] + + *) mod_unique_id was erroneously generating a second unique id when + an internal redirect occured. Such redirects occur, for example, + when processing a DirectoryIndex match. [Dean Gaudet] + + *) API: table_add, table_merge, and table_set include implicit pstrdup() + of the key and value. But in many cases this is not required + because the key/value is a constant, or the value has been built + by pstrcat() or other similar means. New routines table_addn, + table_mergen, and table_setn have been added to the API, these + routines do not pstrdup() their arguments. The core code and + standard modules were changed to take advantage of these routines. + The resulting server is up to 20% faster in some situations. + + Note that it is easy to get code subtly wrong if you pass a key/value + which is in a pool other than the pool of the table. The only + safe thing to do is to pass key/values which are in the pool of + the table, or in one of the ancestors of the pool of the table. + i.e. if the table is part of a subrequest, a value from the main + request's pool is OK since the subrequest pool is a sub_pool of the + main request's pool (and therefore has a lifespan at most as long as + the main pool). There is debugging code which can detect improper + usage, enabled by defining POOL_DEBUG. See alloc.c for more details. + [Dmitry Khrustalev , Dean Gaudet] + + *) More mod_mime_magic cleanup: fewer syscalls; should handle "files" + which don't exist on disk more gracefully; handles vhosts properly. + Update documentation to reflect the code -- if there's no + MimeMagicFile directive then the module is not enabled. + [Dean Gaudet] + + *) PORT: Some older *nix dialects cannot automatically start scripts + which begin with a #! interpreter line (the shell starts the scripts + appropriately on these platforms). Apache now supports starting of + "hashbang-scripts" when the NEED_HASHBANG_EMUL define is set. + [Martin Kraemer, with code from peter@zeus.dialix.oz.au (Peter Wemm) + taken from tcsh] + + *) API: "typedef array_header table" removed from alloc.h, folks should + have been writing to use table as if it were an opaque type, but even + some standard modules got this wrong. By changing the definition + to "typedef struct table table" module authors will receive compile + time warnings that they're doing the wrong thing. This change + facilitates future changes with more sophisticated table + structures. Specifically, module authors should be using table_elts() + to get access to an array_header * for the table. [Dean Gaudet] + + *) API: Renamed new_connection() to avoid namespace collision with LDAP + library routines. [Ken Coar, Rasmus Lerdorf] + + *) WIN32: mod_speling is now available on the Win32 platform. + [Marc Slemko] + + *) For clarity the following compile time definition was changed: + + SAFE_UNSERIALIZED_ACCEPT -> SINGLE_LISTEN_UNSERIALIZED_ACCEPT + + Also, for example, HAVE_MMAP would mean to use mmap() scoreboards + and not be a general notice that the OS has mmap(). Now the + HAVE_MMAP/SHMGET #defines strictly are informational that the + OS has that method of shared memory; the type to use for + the scoreboard is a seperate #define (USE_MMAP_SCOREBOARD + and USE_SHMGET_SCOREBOARD). This allows outside modules to + determine if shared memory is available and allows Apache + to determine the best method to use for the scoreboard. + [Jim Jagielski] + + *) PORT: UnixWare 2.1.2 SMP appears to require USE_FCNTL_SERIALIZED_ACCEPT, + as do various earlier versions. It should be safe on all versions. + Unixware 1.x appears to have the same SIGHUP bug as solaris does with + the slack code. A few other cleanups for Unixware. + [Tom Hughes ] PR#1082, PR#1282, PR#1499, PR#1553 + + *) PORT: A/UX can handle single-listen accepts without mutex + locking, so we add SINGLE_LISTEN_UNSERIALIZED_ACCEPT. [Jim Jagielski] + + *) When die() happens we need to eat any request body if one exists. + Otherwise we can't continue with a keepalive session. This shows up + as a POST problem with MSIE 4.0, typically against pages which are + authenticated. [Roy Fielding] PR#1399 + + *) If you define SECURITY_HOLE_PASS_AUTHORIZATION then the Authorization + header will be passed to CGIs. This is generally a security hole, so + it's not a default. [Marc Slemko] PR#549 + + *) Fix Y2K problem with date printing in suexec log. + [Paul Eggert ] PR#1343 + + *) WIN32 deserves a pid file. [Ben Hyde] + + *) suexec errors now include the errno/description. [Marc Slemko] PR#1543 + + *) PORT: OSF/1 now uses USE_FLOCK_SERIALIZED_ACCEPT to solve PR#467. + The choice of flock vs. fcntl was made based on timings which showed that + even on non-NFS, non-exported filesystems fcntl() was an order of + magnitude slower. It also uses SINGLE_LISTEN_UNSERIALIZED_ACCEPT so + that single socket users will see no difference. [Dean Gaudet] PR#467 + + *) "File does not exist" error message was erroneously including the + errno. [Marc Slemko] + + *) Improve the warning message generated when a client drops the + connection (hits stop button, etc.) during a send. [Roy Fielding] + + *) Defining GPROF will disable profiling in the parent and enable it + in the children. If you're profiling under Linux this is pretty much + necessary because SIGPROF is lost across a fork(). [Dean Gaudet] + + *) htdigest and htpasswd needed slight tweaks to work on OS/2 and WIN32. + [Brian Havard] + + *) The NeXT cc (which is gcc hacked up) doesn't appear to support some + gcc functionality. Work around it. + [Keith Severson ] PR#1613 + + *) Some linkers complain when .o files contain no functions. + [Keith Severson ] PR#1614 + + *) Some const declarations in mod_imap.c that were added for debugging + purposes caused some compilers heartburn without adding any + significant value, so they've been removed. [Ken Coar] + + *) The src/main/*.h header files have had #ifndef wrappers added to + insulate them against duplicate calls if they get included through + multiple paths (e.g., in .c files as well as other .h files). + [Ken Coar] + + *) The libap routines now have a header file for their prototypes, + src/ap/ap.h, to ease their use in non-httpd applications. [Ken Coar] + + *) mod_autoindex with a plaintext header file would emit the
    +     start-tag before the HTML preamble, rather than after the preamble
    +     but before the header file contents.  [John Van Essen ]
    +     PR#1667
    +
    +  *) SECURITY: Fix a possible buffer overflow in logresolve.  This is
    +     only an issue on systems without a MAXDNAME define or where
    +     the resolver returns domain names longer than MAXDNAME.  [Marc Slemko]
    +
    +  *) SECURITY: Eliminate possible buffer overflow in cfg_getline, which
    +     is used to read various types of files such as htaccess and
    +     htpasswd files.  [Marc Slemko]
    +
    +  *) SECURITY: Ensure that the buffer returned by ht_time is always
    +     properly null terminated.  [Marc Slemko]
    +
    +  *) The "Connection" header could be sent back with multiple "close"
    +     tokens.  Not an error, but a waste.
    +     [Ronald.Tschalaer@psi.ch] PR#1683
    +
    +  *) mod_rewrite's RewriteLog should behave like mod_log_config, it
    +     shouldn't force hostname lookups.  [Dean Gaudet] PR#1684
    +
    +  *) "basic" auth needs a case-insensitive comparison.
    +     [Ronald.Tschalaer@psi.ch] PR#1666
    +
    +  *) For maximum portability, the environment passed to CGIs should
    +     only contain variables whose names match the regex
    +     /[a-zA-Z][a-zA-Z0-9_]*/.  This is now enforced by stamping
    +     underscores over any character outside the regex.  This
    +     affects HTTP_* variables, in a way that should be backward
    +     compatible for all the standard headers; and affects variables
    +     set with SetEnv/BrowserMatch and similar directives.
    +     [Dean Gaudet]
    +
    +  *) mod_speling returned incorrect HREF's when an ambigous match
    +     was found. Noticed by  (Soeren Ziehe)
    +     [robinton@amtrash.comlink.de (Soeren Ziehe), Martin Kraemer]
    +
    +  *) PORT: Apache now compiles & runs on an EBCDIC mainframe
    +     (the Siemens Nixdorf BS2000-OSD family) in the POSIX subsystem
    +     [Martin Kraemer]
    +
    +  *) PORT: Fix problem killing children when terminating.  Allow ^C
    +     to shut down the server.  [Brian Havard]
    +
    +  *) pstrdup() is implicit in calls to table_* functions, so there's
    +     no need to do it before calling.  Clean up a few cases.
    +     [Marc Slemko, Dean Gaudet]
    +
    +  *) new -C and -c command line arguments
    +     usage:
    +     -C "directive" : process directive before reading config files
    +     -c "directive" : process directive after reading config files
    +     example:
    +     httpd -C "PerlModule Apache::httpd_conf"
    +     [Doug MacEachern, Martin Kraemer]
    +
    +  *) WIN32: Fix the execution of CGIs that are scripts and called 
    +     with path info that does not have an '=' in.
    +     (eg. http://server/cgi-bin/printenv?foobar)  
    +     [Marc Slemko] PR#1591
    +
    +  *) WIN32: Fix a call to os_canonical_filename so it doesn't try to 
    +     mess with fake filenames.  This fixes proxy caching on 
    +     win32. PR#1265
    +
    +  *) SECURITY: General mod_include cleanup, including fixing several
    +     possible buffer overflows and a possible infinite loop.
    +     [Dean Gaudet, Marc Slemko]
    +
    +  *) SECURITY: Numerous changes to mod_imap in a general cleanup
    +     including fixing a possible buffer overflow.  [Dean Gaudet]
    +
    +  *) WIN32: overhaul of multithreading code. Shutdowns are now graceful
    +     (connections are not dropped). Code can handle graceful restarts
    +     (but there is as yet no way to signal this to Apache). Various
    +     other cleanups. [Paul Sutton]
    +
    +  *) The aplog_error changes specific to 1.3 introduced a buffer
    +     overrun in the (now legacy) log_printf function.  Fixed.
    +     [Dean Gaudet]
    +
    +  *) mod_digest didn't properly deal with proxy authentication.  It
    +     also lacked a case-insensitive comparision of the "Digest"
    +     token.  [Ronald Tschalaer ] PR#1599
    +
    +  *) A few cleanups in mod_status for efficiency.  [Dean Gaudet]
    +
    +  *) A few cleanups in mod_info to make it thread-safe, and remove an
    +     off-by-5 bug that could hammer \0 on the stack. [Dean Gaudet]
    +
    +  *) no2slash() was O(n^2) in the length of the input.  Make it O(n).
    +     [Dean Gaudet]
    +
    +  *) API: migration from strncpy() to our "enhanced" version called
    +     ap_cpystrn() for performance and functionality reasons.
    +     Located in libap.a.  [Jim Jagielski]
    +
    +  *) table_set() and table_unset() did not deal correctly with
    +     multiple occurrences of the same key. [Stephen Scheck
    +	 , Ben Laurie] PR#1604
    +
    +  *) The AuthName must now be enclosed in quotes if it is to contain
    +     spaces.  [Ken Coar] PR#1195
    +
    +  *) API: new function: ap_escape_quotes(). [Ken Coar] PR#1195
    +
    +  *) WIN32: Work around optimiser bug that killed ISAPI in release
    +     versions. [Ben Laurie] PR#1533
    +
    +  *) PORT: Update the MPE port [Mark Bixby, Jim Jagielski]
    +
    +  *) Interim (slow) fix for p->sub_pool critical sections in
    +     alloc.c (affects win32 only).  [Ben Hyde]
    +
    +  *) non-WIN32 was missing destroy_mutex definition.  [Ben Hyde]
    +
    +  *) send_fd_length() did not calculate total_bytes_sent properly.
    +     [Ben Reser ] PR#1366
    +
    +  *) The bputc() macro was not properly integrated with the chunking
    +     code; in many cases modules using bputc() could cause completely
    +     bogus chunked output.  (Typically this will show up as problems
    +     with Internet Explorer 4.0 reading a page, but other browsers
    +     having no problem.) [Dean Gaudet]
    +
    +  *) Create LARGE_WRITE_THRESHOLD define which determines how many
    +     bytes have to be supplied to bwrite() before it will consider
    +     doing a writev() to assemble multiple buffers in one system
    +     call.  This is critical for modules such as mod_include,
    +     mod_autoindex, mod_php3 which all use bputc()/bputs() of smaller
    +     strings in some cases.  The result would be extra effort
    +     setting up writev(), and in many cases extra effort building
    +     chunks.  The default is 31, it can be overriden at compile
    +     time. [Dean Gaudet]
    +
    +  *) Move the gid switching code into the child so that log files
    +     and pid files are opened with the root gid.
    +     [Gregory A Lundberg ]
    +
    +  *) WIN32: Check for binaries by looking for the executable header
    +     instead of counting control characters.
    +	 [Jim Patterson ] PR#1340
    +
    +  *) ap_snprintf() moved from main/util_snprintf.c to ap/ap_snprintf.c
    +     so the functionality is available to applications other than the
    +     server itself (like the src/support tools).  [Ken Coar]
    +
    +  *) ap_slack() moved out of main/util.c into ap/ap_slack.c as part of
    +     the libap consolidation work.  [Ken Coar]
    +
    +  *) ap_snprintf() with a len of 0 behaved like sprintf().  This is not
    +     useful, and isn't what the standards require.  Now it returns 0
    +     and writes nothing.  [Dean Gaudet]
    +
    +  *) When an error occurs in fcntl() locking suggest the user look up
    +     the docs for LockFile.  [Dean Gaudet]
    +
    +  *) Eliminate some dead code from writev_it_all().
    +     [Igor Tatarinov ]
    +
    +  *) mod_autoindex had an fread() without checking the result code.
    +     It also wouldn't handle "AddIconByType (TXT,/icons/text.gif text/*"
    +     (note the missing closing paren) properly.  [Dean Gaudet]
    +
    +  *) It appears the "257th byte" bug (see
    +     htdocs/manual/misc/known_client_problems.html#257th-byte) can happen
    +     at the 256th byte as well.  Fixed.  [Dean Gaudet]
    +
    +  *) PORT: Fix mod_mime_magic under OS/2, no support for block devices.
    +     [Brian Havard]
    +
    +  *) Fix memory corruption caused by allocating auth usernames in the
    +     wrong pool.  [Dean Gaudet] PR#1500
    +
    +  *) Fix an off-by-1, and an unterminated string error in
    +     mod_mime_magic.  [Dean Gaudet]
    +
    +  *) Fix a potential SEGV problem in mod_negotiation when dealing
    +     with type-maps.  [Dean Gaudet]
    +
    +  *) Better glibc support under Linux.  [Dean Gaudet] PR#1542
    +
    +  *) "RedirectMatch gone /" would cause a SIGSEGV. [Dean Gaudet] PR#1319
    +
    +  *) WIN32: avoid overflows during file canonicalisations.
    +     [malcolm@mgdev.demon.co.uk] PR#1378
    +
    +  *) WIN32: set_file_slot() didn't detect absolute paths. [Ben Laurie]
    +     PR#1511, 1508
    +
    +  *) WIN32: mod_status display header didn't match fields. [Ben Laurie]
    +
    +  *) The pthread_mutex_* functions return an error code, and don't
    +     set errno.  [Igor Tatarinov ]
    +
    +  *) WIN32: Allow spaces to prefix the interpreter in #! lines.
    +     [Ben Laurie] PR#1101
    +
    +  *) WIN32: Cure file leak in CGIs. [Peter Tillemans ] PR#1523
    +
    +  *) proxy_ftp: the directory listings generated by the proxy ftp module
    +     now have a title in which the path components are clickable and allow
    +     quick navigation to the clicked-on directory on the currently listed
    +     ftp server. This also fixes a bug where the ".." directory links would
    +     sometimes refer to the wrong directory.  [Martin Kraemer]
    +
    +  *) WIN32: Allocate the correct amount of memory for the scoreboard.
    +     [Ben Hyde] PR#1387
    +
    +  *) WIN32: Only lowercase the part of the path that is real. [Ben Laurie]
    +     PR#1505
    +
    +  *) Fix problems with timeouts in inetd mode and -X mode.  [Dean Gaudet]
    +
    +  *) Fix the spurious "(0)unknown error: mmap_handler: mmap failed"
    +     error messages. [Ben Hyde]
    +
    +Changes with Apache 1.3b3
    +
    +  *) WIN32: Work around brain-damaged spawn calls that can't deal
    +     with spaces and slashes.  [Ben Laurie]
    +
    +  *) WIN32: Fix the code so CGIs can use socket calls on Windows.  
    +     The problem was that certain undocumented environment variables
    +	 needed for sockets to work under Win32 were not being passed.
    +     [Frank Faubert ]
    +
    +  *) Add a "-V" command line flag to the httpd binary.  This 
    +     flag shows some of the defines that Apache was compiled with.
    +     It is useful for debugging purposes.  [Martin Kraemer]
    +
    +  *) Start separating the ap_*() routines into their own library, so they
    +     can be used by items in src/support among other things.  
    +     [Ken Coar] PR#512, 905, 1252, 1308 
    +
    +  *) Give a more informative error when no AuthType is set.
    +     [Lars Eilebrecht]
    +
    +  *) Remove strtoul() use from mod_proxy because it isn't available
    +     on all platforms.   [Marc Slemko] PR#1214
    +
    +  *) WIN32: Some Win32 systems terminated all responses after 16 kB. 
    +     This turns out to be a bug in Winsock - select() doesn't always 
    +     return the correct status.  [Ben Laurie]
    +
    +  *) Directives owned by http_core can now use the new check_cmd_context()
    +     routine to ensure that they're not being used within a container
    +     (e.g., ) where they're invalid.  [Martin Kraemer]
    +
    +  *) PORT: Recent changes made it necessary to add explicit prototype
    +     for fgetc() and fgets() on SunOS 4.x.  [Martin Kraemer, Ben Hyde]
    +
    +  *) It was necessary to distinguish between resources which are
    +     allocated in the parent, for cleanup in the parent, and resources
    +     which are allocated in each child, for cleanup in each child.
    +     A new pool was created which is passed to the module child_init
    +     and child_exit functions; modules are free to register per-child
    +     cleanups there.  This fixes a bug with reliable piped logs.
    +     [Dean Gaudet]
    +
    +  *) mod_autoindex wasn't displaying the ReadmeName file at the bottom
    +     unless it was also doing FancyIndexes, but it displayed the
    +     HeaderName file at the top under all circumstances.  It now shows
    +     the ReadmeName file for simple indices, too, as it should.  
    +     [Ken Coar] PR#1373
    +
    +  *) http_core was mmap()ing even in cases where it wasn't going to
    +     read the file.  [Ben Hyde ]
    +
    +  *) Complete rewrite ;-) of mod_rewrite's URL rewriting engine:
    +     Now the rewriting engine (the heart of mod_rewrite) is organized more
    +     straight-forward, first time well documented and reduced to the really
    +     essential parts. All redundant cases were stripped off and processing now
    +     is the same for both per-server and per-directory context with only a
    +     minimum difference (the prefix stripping in per-dir context). As a
    +     side-effect some subtle restrictions and two recently discovered problems
    +     are gone: Wrong escaping of QUERY_STRING on redirects in per-directory
    +     context and restrictions on the substitution URL on redirects.
    +     Additionally some minor source cleanups were done. 
    +     [Ralf S. Engelschall] 
    +
    +  *) Lars Eilebrecht wrote a whole new set of Apache Vhost Internals
    +     documentation, examples, explanations and caveats. They live in a new
    +     subdirectory htdocs/manual/vhost/. [Lars Eilebrecht ]
    +
    +  *) If ap_slack fails to allocate above the low slack line it's a good
    +     indication that further problems will occur; it's a better indication
    +     than many external libraries give us when we actually run out of
    +     descriptors.  So report it to the user once per restart.
    +     [Dean Gaudet] PR#1181
    +
    +  *) Change mod_include and mod_autoindex to use Y2K-safe date formats
    +     by default.  [Ken Coar]
    +
    +  *) Add a "SuppressColumnSorting" option to the IndexOptions list,
    +     which will keep the column heading from being links for sorting
    +     the display.  [Ken Coar, suggested by Brian Tiemann ]
    +     PR #1261
    +
    +  *) PORT: Update the LynxOS port.  [Marius Groeger ]
    +
    +  *) Fix logic error when issuing a mmap() failed message
    +     with a non-zero MMAP_THRESHOLD.
    +     [David Chambers ] PR#1294
    +
    +  *) Preserve handler value on ProxyPass'ed requests by not
    +     calling find_types on a proxy'd request; fixes problems
    +     where some ProxyPass'ed URLs weren't actually passed
    +     to the proxy.
    +     [Lars Eilebrecht] PR#870
    +
    +  *) Fix a byte ordering problem in mod_access which prevented
    +     the old-style syntax (i.e. "a.b.c." to match a class C)
    +     from working properly. [Dean Gaudet] PR#1248, 1328, 1384
    +
    +  *) Fix problem with USE_FLOCK_SERIALIZED_ACCEPT not working
    +     properly. Each child needs to open the lockfile instead
    +     of using the passed file-descriptor from the parent. 
    +     [Jim Jagielski] PR#1056
    +
    +  *) Fix the error logging in mod_cgi; the recent error log changes
    +     introduced a bug that prevented it from working correctly.
    +     [M.D.Parker] PR#1352
    +
    +  *) Default to USE_FCNTL_SERIALIZED_ACCEPT on HPUX to properly 
    +     handle multiple Listen directives.  [Marc Slemko] PR#872
    +
    +  *) Inherit a bugfix to fnmatch.c from FreeBSD sources.
    +     ["[KOI8-R] áÎÄÒÅÊ þÅÒÎÏ×" ] PR#1311
    +
    +  *) When a configuration parse complained about a bad directive,
    +     the logger would use whatever (unrelated) value was in errno.
    +     errno is now forced to EINVAL first in this case.  [Ken Coar]
    +
    +  *) A sed command in the Configure script pushed the edge of POSIXness,
    +     breaking on some systems.  [Bhaba R.Misra ] PR#1368
    +
    +  *) Solaris >= 2.5 was totally broken due to a mess up using pthread
    +     mutexes.  [Roy Fielding, Dean Gaudet]
    +
    +  *) OS/2 Port updated; it should be possible to build OS/2 from the same
    +     sources as Unix now.  [Brian Havard ]
    +
    +  *) Fix a year formatting bug in mod_usertrack.
    +     [Paul Eggert ] PR#1342
    +
    +  *) A mild SIGTERM/SIGALRM race condition was eliminated.
    +     [Dean Gaudet] PR#1211
    +
    +  *) Warn user that default path has changed if /usr/local/etc/httpd
    +     is found on the system.  [Lars Eilebrecht]
    +
    +  *) Various mod_mime_magic bug fixes and cleanups: Uncompression
    +     should work, it should work on WIN32, and a few resource
    +     leaks and abort conditions are fixed.
    +     [Dean Gaudet] PR#1205
    +
    +  *) PORT: On AIX 1.x files can't be named '@', fix the proxy cache
    +     to use '%' instead of '@' in its encodings.
    +     [David Schuler ] PR#1317
    +
    +  *) Improve the warning message generated when the "server is busy".
    +     [Dean Gaudet] PR#1293
    +
    +  *) PORT: All ports which don't otherwise define DEF_WANTHSREGEX will
    +     get Spencer regex by default.  This is to avoid having to
    +     discover bugs in operating system libraries.  [Dean Gaudet]
    +
    +  *) PORT: "Fix" PR#467 by generating warnings on systems which we have
    +     not been able to get working USE_*_SERIALIZED_ACCEPT settings for.
    +     Document this a bit more in src/PORTING.  [Dean Gaudet] PR#467
    +
    +  *) Ensure that one copy of config warnings makes it to the
    +     error_log.  [Dean Gaudet]
    +
    +  *) Invent new structure and associated methods to handle config file
    +     reading. Add "custom" hook to use config file cfg_getline() on
    +     something which is not a FILE*  [Martin Kraemer]
    +
    +  *) Make single-exe Windows install. [Ben Laurie and Eric Esselink]
    +
    +  *) WIN32: Make CGI work under Win95. [Ben Laurie and Paul Sutton]
    +
    +  *) WIN32: Make index.html and friends work under Win95. [Ben Laurie]
    +
    +  *) PORT: Solaris 2.4 needs Spencer regex, the system regex is broken.
    +	[John Line ] PR#1321
    +
    +  *) Default pathname has been changed everywhere to /usr/local/apache
    +     [Sameer ]
    +
    +  *) PORT: AIX now uses USE_FCNTL_SERIALIZED_ACCEPT.
    +	[David Bronder ] PR#849
    +
    +  *) PORT: i386 AIX does not have memmove.
    +     [David Schuler ] PR#1267
    +
    +  *) PORT: HPUX now defaults to using Spencer regex.
    +     [Philippe Vanhaesendonck ,
    +     Omar Del Rio ] PR#482, 1246
    +
    +  *) PORT: Some versions of NetBSD don't automatically define
    +	    __NetBSD__.  Workaround by defining NETBSD.
    +     [Chris Craft ] PR#977
    +
    +  *) PORT: UnixWare 2.x requires -lgen for syslog.
    +     [Hans Snijder ] PR#1249
    +
    +  *) PORT: ULTRIX appears to not have syslog.
    +     [Lars Eilebrecht ]
    +
    +  *) PORT: Basic Gemini port (treat it like unixware212).
    +     ["Pavel Yakovlev (Paul McHacker)" ]
    +
    +  *) PORT: All SVR4 systems now use NET_SIZE_T = size_t, and
    +	    use USE_SHMGET_SCOREBOARD.
    +     [Martin Kraemer]
    +
    +  *) Various improvements in detecting config file errors (missing closing
    +     directives for ,  etc. blocks, prohibiting global
    +     server settings in  blocks, flagging unhandled multiple
    +     arguments to ,  etc.)
    +     [Martin Kraemer]
    +
    +  *) Add support to suexec wrapper program for mod_unique_id's UNIQUE_ID
    +     variable to provide this one to suexec'd CGIs, too.
    +     [M.D.Parker ] PR#1284
    +
    +  *) New support tool: src/support/split-logfile, a sample Perl script which
    +     splits up a combined access log into separate files based on the
    +     name of the virtual host (listed first in the log records by "%v").
    +     [Ken Coar]
    +
    +Changes with Apache 1.3b2 (there is no 1.3b1)
    +
    +  *) TestCompile was not passing $LIBS [Dean Gaudet]
    +
    +  *) Makefile.tmpl was not using $CFLAGS in the link phase. 
    +     [Martin Kraemer]
    +
    +  *) Add debugging code to alloc.c.  Defining ALLOC_DEBUG provides a
    +     rudimentary memory debugger which can be used on live servers with
    +     low impact -- it sets all allocated and freed memory bytes to 0xa5.
    +     Defining ALLOC_USE_MALLOC will cause the alloc code to use malloc()
    +     and free() for each object.  This is far more expensive and should
    +     only be used for testing with tools such as Electric Fence and
    +     Purify.  See main/alloc.c for more details.  [Dean Gaudet]
    +
    +  *) Configure uses a sh trap and didn't set its exitcode properly.
    +     [Dean Gaudet] PR#1159
    +
    +  *) Yet another vhost revamp.  Add the NameVirtualHost directive which
    +     explicitly lists the ip:port pairs that are to be used for name-vhosts.
    +     From a given ip:port, regardless what the Host: header is, you can
    +     only reach the vhosts defined on that ip:port.  The precedence of
    +     vhosts was reversed to match other precedences in the config --
    +     the earlier vhosts override the later vhosts.  All vhost matching was
    +     moved into http_vhost.[ch].  [Dean Gaudet]
    +
    +  *) ap_inline can be used to force inlining.  GNUC __attribute__() can
    +     be used for whatever reason is appropriate (i.e. format() warnings
    +     for printf style functions).  Both are enabled only with
    +     gcc >= 2.7.x (so that we have fewer support issues with older
    +     versions).  [Dean Gaudet]
    +
    +  *) Fix support for Proxy Authentication (we were testing the response
    +     status too early). [Marc Slemko]
    +
    +  *) CoreDumpDirectory directive directs where the core file is
    +     written when a SIGSEGV, SIGBUS, SIGABORT or SIGABRT are
    +     received.  [Marc Slemko, Dean Gaudet]
    +
    +  *) PORT: Support for Atari MINT.
    +     [Jan Paul Schmidt ]
    +
    +  *) When booting, apache will now detach itself from stdin, stdout,
    +     and stderr.  stderr will not be detached until after the config
    +     files have been read so you will be able to see initial error
    +     messages.  After that all errors are logged in the error_log.
    +     This makes it more convenient to start apache via rsh, ssh,
    +     or crontabs.  [Dean Gaudet] PR#523
    +
    +  *) mod_proxy was sending HTTP/1.1 responses to ftp requests by mistake.
    +     Also removed the auto-generated link to www.apache.org that was the
    +     source of so many misdirected bug reports.  [Roy Fielding, Marc Slemko]
    +
    +  *) send_fb would not detect aborted connections in some situations.
    +     [Dean Gaudet]
    +
    +  *) mod_include would use uninitialized data when parsing certain
    +     expressions involving && and ||. [Brian Slesinsky] PR#1139
    +
    +  *) mod_imap should only handle GET methods.  [Jay Bloodworth]
    +
    +  *) suexec.c wouldn't build without -DLOG_EXEC. [Jason A. Dour]
    +
    +  *) mod_autoindex improperly counted &escapes; as more than one
    +     character in the description.  It also improperly truncated
    +     descriptions that were exactly the maximum length.
    +     [Martin Kraemer]
    +
    +  *) RedirectMatch was not properly escaping the result (PR#1155).  Also
    +     "RedirectMatch /advertiser/(.*) $1" is now permitted.
    +     [Dean Gaudet]
    +
    +  *) mod_include now uses symbolic names to check for request success
    +     and return HTTP errors, and correctly handles all types of
    +     redirections (previously it only did temporary redirect correctly).
    +     [Ken Coar, Roy Fielding]
    +
    +  *) mod_userdir was modifying r->finfo in cases where it wasn't setting
    +     r->filename.  Since those two are meant to be in sync with each other
    +     this is a bug.  ["Paul B. Henson" ]
    +
    +  *) PORT: Support Unisys SVR4, whose uname returns mostly useless data.
    +     ["Kaufman, Steven E" ]
    +
    +  *) Inetd mode (which is buggy) uses timeouts without having setup the
    +     jmpbuffer. [Dean Gaudet] PR#1064
    +
    +  *) Work around problem under Linux where a child will start looping
    +     reporting a select error over and over.
    +     [Rick Franchuk ] PR#1107, 987, 588
    +
    +  *) Fixed error in proxy_util.c when looping through multiple host IP
    +     addresses. [Lars Eilebrecht] PR#974
    +
    +  *) If BUFFERED_LOGS is defined then mod_log_config will do atomic
    +     buffered writes -- that is, it will buffer up to PIPE_BUF (i.e. 4k)
    +     bytes before writing, but it will never split a log entry across a
    +     buffer boundary.  [Dean Gaudet]
    +
    +  *) API: the short_score record has been split into two pieces, one which
    +     the parent writes on, and one which the child writes on.  As part of
    +     this change the get_scoreboard_info() function was removed, and
    +     scoreboard_image was exported.  This change fixes a race condition
    +     in file based scoreboard systems, and speeds up changes involving the
    +     scoreboard in earlier 1.3 development.  [Dean Gaudet]
    +
    +  *) API: New register_other_child() API (see http_main.h) which allows
    +     modules to register children with the parent for maintenance.  It
    +     is disabled by defining NO_OTHER_CHILD.  [Dean Gaudet]
    +
    +  *) API: New piped_log API (see http_log.h) which implements piped logs,
    +     and will use register_other_child to implement reliable piped logs
    +     when it is available.  The reliable piped logs part can be disabled
    +     by defining NO_RELIABLE_PIPED_LOGS.  At the moment reliable piped
    +     logs is only available on Unix. [Dean Gaudet]
    +
    +  *) API: set_last_modified() broken into set_last_modified(), set_etag(), and
    +     meets_conditions().  This allows conditional HTTP selection to be
    +     handled separately from the storing of the header fields, and provides
    +     the ability for CGIs to set their own ETags for conditional checking.
    +     [Ken Coar, Roy Fielding]  PR#895
    +
    +  *) Changes to mod_log_config to allow naming of format strings.
    +     Format nicknames are defined with "LogFormat fmt nickname", and can
    +     be used with "LogFormat nickname" and "CustomLog logtarget nickname".
    +     [Ken Coar]
    +
    +  *) New module, "mod_speling", which can help find files even when 
    +     the URL is slightly misspelled. [Martin Kraemer, Alexei Kosut]
    +
    +  *) API: New function child_terminate() triggers the child process to
    +     exit, while allowing the child finish what it needs to for the
    +     current request first.  
    +     [Doug MacEachern, Alexei Kosut]
    +
    +  *) Windows now defaults to using full status reports with mod_status.
    +     [Alexei Kosut] PR #1094
    +
    +  *) *Really* disable all mod_rewrite operations if the engine is off.
    +     Some things (like RewriteMaps) were checked/performed even if they
    +     weren't supposed to be.  [Ken Coar] PR #991
    +
    +  *) Implement a new timer scheme which eliminates the need to call alarm() all
    +     the time.  Instead a counter in the scoreboard for each child is used to
    +     show when the child has made forward progress.  The parent samples this
    +     counter every scoreboard maintenance cycle, and issues SIGALRM if no
    +     progress has been made in the timeout period.  This reduces the static
    +     request best-case syscall count to 22 from 29.  This scheme is only
    +     used by systems with memory-based scoreboards.  [Dean Gaudet]
    +
    +  *) The proxy now properly handles CONNECT requests which are sent
    +     to proxy servers when using ProxyRemote.  [Marc Slemko] PR#1024
    +
    +  *) A script called apachectl has been added to the support 
    +     directory.  This script allows you to do things such as 
    +     "apachectl start" and "apachectl restart" from the command
    +     line.  [Marc Slemko]
    +
    +  *) Modules and core routines are now put into libraries, which
    +     simplifies the link line tremendously (among other advantages).
    +     [Paul Sutton]
    +
    +  *) Some of the MD5 names defined in Apache have been renamed to have
    +     an `ap_' prefix to avoid conflicts with routines supplied by
    +     external libraries.  [Ken Coar]
    +
    +  *) Removal of mod_auth_msql.c from the distribution. There are many
    +     other options for databases today. Rather than offer one option,
    +     offer none at this time. mod_auth_msql and other SQL database
    +     authentication modules can be found at the Apache Module Registry.
    +     http://modules.apache.org/ It would be nice to offer a generic
    +     mod_auth_sql option in the near future.
    +
    +  *) PORT: BeOS support added [Alexei Kosut]
    +
    +  *) Configure no longer accepts the -make option, since it creates
    +     Makefile on the fly based on Makefile.tmpl and Configuration.
    +
    +  *) Apache now gracefully shuts down when it receives a SIGTERM, instead
    +     of forcibly killing off all its processes and exiting without
    +     cleaning up. [Alexei Kosut]
    +
    +  *) API: A new field in the request_rec, r->mtime, has been added to
    +     avoid gratuitous parsing of date strings.  It is intended to hold
    +     the last-modified date of the resource (if applicable).  An
    +     update_mtime() routine has also been added to advance it if
    +     appropriate.  [Roy Fielding, Ken Coar]
    +
    +  *) SECURITY: If a htaccess file can not be read due to bad permissions,
    +     deny access to the directory with a HTTP_FORBIDDEN.  The previous
    +     behavior was to ignore the htaccess file if it could not be read.
    +     This change may make some setups with unreadable htaccess files
    +     stop working.  [Marc Slemko] PR#817
    +
    +  *) Add aplog_error() providing a mechanism to define levels of
    +     verbosity to the server error logging. This addition also provides
    +     the ability to log errors using syslogd. Error logging is configurable
    +     on a per-server basis using the LogLevel directive. Conversion
    +     of log_*() in progress. [Randy Terbush]
    +
    +  *) Further enhance aplog_error() to not log filename, line number, and
    +     errno information when it isn't applicable. [Ken Coar, Dean Gaudet]
    +
    +  *) WIN32: Canonicalise filenames under Win32. Short filenames are
    +     converted to long ones. Backslashes are converted to forward
    +     slashes. Case is converted to lower. Parts of URLs that do not
    +     correspond to files are left completely alone. [Ben Laurie]
    +
    +  *) PORT: 2 new OSs added to the list of ports:
    +      Encore's UMAX V: Arieh Markel 
    +      Acorn RISCiX: Stephen Borrill 
    +
    +  *) Add the server version (SERVER_VERSION macro) to the "server
    +     configured and running" entry in the error_log.  Also build an
    +     object file at link-time that contains the current time
    +     (SERVER_BUILT global const char[]), and include that in the
    +     message.  [Ken Coar]
    +
    +  *) Set r->headers_out when sending responses from the proxy.
    +     This fixes things such as the logging of headers sent from
    +     the proxy.  [Marc Slemko] PR#659
    +
    +  *) support/httpd_monitor is no longer distributed because the 
    +     scoreboard should not be file based if at all possible. Use
    +     mod_status to see current server snapshot.
    +
    +  *) (set_file_slot): New function, allowing auth directives to be
    +     independent of the server root, so the server documents can be
    +     moved to a different directory or machine more easily.
    +     [David J. MacKenzie]
    +
    +  *) If no TransferLog is given explicitly, decline
    +     to log.  This supports coexistence with other logging modules,
    +     such as the custom one that UUNET uses. [David J. MacKenzie]
    +
    +  *) Check for titles in server-parsed HTML files.
    +     Ignore leading newlines and returns in titles.  The old behavior
    +     of replacing a newline after  with a space causes the
    +     title to be misaligned in the listing. [David J. MacKenzie]
    +
    +  *) Change mod_cern_meta to be configurable on a per-directory basis.
    +     [David J. MacKenzie]
    +
    +  *) Add 'Include' directive to allow inclusion of configuration
    +     files within configuration files. [Randy Terbush]
    +
    +  *) Proxy errors on connect() are logged to the error_log (nothing
    +     new); now they include the IP address and port that failed
    +     (*that's* new).   [Ken Coar, Marc Slemko] PR#352
    +
    +  *) Various architectures now define USE_MMAP_FILES which causes
    +     the server to use mmap() for static files.  There are two
    +     compile-time tunables MMAP_THRESHOLD (minimum number of bytes
    +     required to use mmap(), default is 0), and MMAP_SEGMENT_SIZE (maximum
    +     number of bytes written in one cycle from a single mmap()d object,
    +     default 32768).  [Dean Gaudet]
    +
    +  *) API: Added post_read_request API phase which is run right after reading
    +     the request from a client, or right after an internal redirect.  It is
    +     useful for modules setting environment variables that depend only on
    +     the headers/contents of the request.  It does not run during subrequests
    +     because subrequests inherit pretty much everything from the main
    +     request. [Dean Gaudet]
    +
    +  *) Added mod_unique_id which is used to generate a unique identifier for
    +     each hit, available in the environment variable UNIQUE_ID.
    +     [Dean Gaudet]
    +
    +  *) init_modules is now called after the error logs have been opened.  This
    +     allows modules to emit information messages into the error logs.
    +     [Dean Gaudet]
    +
    +  *) Fixed proxy-pass-through feature of mod_rewrite; Added error logging
    +     information for case where proxy module is not available. [Marc Slemko]
    +
    +  *) PORT: Apache has need for mutexes to serialize its children around
    +     accept.  In prior versions either fcntl file locking or flock file
    +     locking were used.  The method is chosen by the definition of
    +     USE_xxx_SERIALIZED_ACCEPT in conf.h.  xxx is FCNTL for fcntl(),
    +     and FLOCK for flock().  New options have been added:
    +	- SYSVSEM to use System V style semaphores
    +	- PTHREAD to use POSIX threads (appears to work on Solaris only)
    +	- USLOCK to use IRIX uslock
    +     Based on timing various techniques, the following changes were made
    +     to the defaults:
    +	- Linux 2.x uses flock instead of fcntl
    +	- Solaris 2.x uses pthreads
    +	- IRIX uses SysV semaphores -- however multiprocessor IRIX boxes
    +	    work far faster if you -DUSE_USLOCK_SERIALIZED_ACCEPT
    +     [Dean Gaudet, Pierre-Yves Kerembellec <Pierre-Yves.Kerembellec@vtcom.fr>,
    +     Martijn Koster <m.koster@pobox.com>]
    +
    +  *) PORT: The semantics of accept/select make it very desirable to use
    +     mutexes to serialize accept when multiple Listens are in use.  But
    +     in the case where only a single socket is open it is sometimes
    +     redundant to serialize accept().  Not all unixes do a good job with
    +     potentially dozens of children blocked on accept() on the same
    +     socket.  It's now possible to define SINGLE_LISTEN_UNSERIALIZED_ACCEPT and
    +     the server will avoid serialization when listening on only one socket,
    +     and use serialization when listening on multiple sockets.
    +     [Dean Gaudet] PR#467
    +
    +  *) Configure changes: TestLib replaced by TestCompile, which has
    +     some additional capability (such as doing a sanity check of
    +     the compiler and flags selected); the version of Solaris is now
    +     available via the #define value of SOLARIS2; IRIX n32bit libs
    +     now supported and selectable by new Configuration Rule: IRIXN32;
    +     We no longer default to -O2 optimization.  [Jim Jagielski]
    +
    +  *) Updated Configure: Configuration now uses AddModule to specify
    +     module source or binary file location, relative to src directory.
    +     Modules can be dropped into modules/extra, or in their own 
    +     directory, and modules can come with a Makefile or Configure can 
    +     create one.  Modules can add compiler or library information to 
    +     generated Makefiles. [Paul Sutton]
    +
    +  *) Source core re-organisation: distributed modules are now in 
    +     modules/standard. All other source code is in main. OS-specific
    +     code is in os/{unix,emx,win32} directories. [Paul Sutton]
    +
    +  *) mod_browser has been removed, since it's replaced by mod_setenvif.
    +     [Ken Coar]
    +
    +  *) Fix another long-standing bug in sub_req_lookup_file where it would
    +     happily skip past access checks on subdirectories looked up with
    +     relative paths.  (It's used by mod_dir, mod_negotiation,
    +     and mod_include.) [Dean Gaudet]
    +
    +  *) directory_walk optimization to reduce an O(N*M) loop to O(N+M) where
    +     N is the number of <Directory> sections, and M is the number of
    +     components in the filename of an object.
    +
    +     To achieve this optimization the following config changes were made:
    +	- Wildcards (* and ?, not the regex forms) in <Directory>s,
    +	  <Files>s, and <Location>s now treat a slash as a special
    +	  character.  For example "/home/*/public_html" previously would
    +	  match "/home/a/andrew/public_html", now it only matches things
    +	  like "/home/bob/public_html".  This mimics /bin/sh behaviour.
    +	- It's possible now to use [] wildcarding in <Directory>, <Files>
    +	  or <Location>.
    +	- Regex <Directory>s are applied after all non-regex <Directory>s.
    +
    +    [Dean Gaudet]
    +
    +  *) Fix a bug introduced in 1.3a1 directory_walk regarding .htaccess files
    +     and corrupted paths.  [Dean Gaudet]
    +
    +  *) Enhanced and cleaned up the URL rewriting engine of mod_rewrite:
    +     First the grouped parts of RewriteRule pattern matches (parenthesis!) can
    +     be accessed now via backreferences $1..$9 in RewriteConds test-against
    +     strings in addition to RewriteRules subst string. Second the grouped
    +     parts of RewriteCond pattern matches (parenthesis!) can be accessed now
    +     via backreferences %1..%9 both in following RewriteCond test-against
    +     strings and RewriteRules subst string. This provides maximum flexibility
    +     through the use of backreferences.
    +     Additionally the rewriting engine was cleaned up by putting common
    +     code to the new expand_backrefs_inbuffer() function. 
    +     [Ralf S. Engelschall]
    +
    +  *) When merging the main server's <Directory> and <Location> sections into
    +     a vhost, put the main server's first and the vhost's second.  Otherwise
    +     the vhost can't override the main server.  [Dean Gaudet] PR#717
    +
    +  *) The <Directory> code would merge and re-merge the same section after
    +     a match was found, possibly causing problems with some modules.
    +     [Dean Gaudet]
    +
    +  *) ip-based vhosts are stored and queried using a hashing function, which
    +     has been shown to improve performance on servers with many ip-vhosts.
    +     Some other changes had to be made to accommodate this:
    +	- the * address for vhosts now behaves like _default_
    +	- the matching process now is:
    +	    - match an ip-vhost directly via hash (possibly matches main
    +		server)
    +	    - if that fails, just pretend it matched the main server
    +	    - if so far only the main server has been matched, perform
    +		name-based lookups (ServerName, ServerAlias, ServerPath)
    +		*only on name-based vhosts*
    +	    - if they fail, look for _default_ vhosts
    +     [Dean Gaudet, Dave Hankins <dhankins@sugarat.net>]
    +
    +  *) dbmmanage overhaul:
    +     - merge dbmmanage and dbmmanage.new functionality, remove dbmmanage.new 
    +     - tie() to AnyDBM_File which will use one of DB_File, NDBM_File or
    +       GDBM_File (-ldb, -lndbm, -lgdbm) (trying each in that order)
    +     - provide better seed for rand
    +     - prompt for password as per getpass(3) (turn off echo, read from
    +       /dev/tty, etc.)
    +     - use "newstyle" crypt based on $Config{osname} ($^O)
    +     - will not add a user if already in database, use new `update' command
    +       instead
    +     - added `check' command to check a users' password
    +     - added `import' command to convert existing password text-files or 
    +       dbm files exported with `view'
    +     - more descriptive usage, general cleanup, 'use strict' clean, etc.
    +     [Doug MacEachern]
    +
    +  *) Added psocket() which is a pool form of socket(), various places within
    +     the proxy weren't properly blocking alarms while registering the cleanup
    +     for its sockets.  bclose() now uses pclose() and pclosesocket().  There
    +     was a bug where the client socket was being close()d twice due a still
    +     registered cleanup.  [Dean Gaudet]
    +
    +  *) A few cleanups were made to reduce time(), getpid(), and signal() calls.
    +     [Dean Gaudet]
    +
    +  *) PORT: AIX >= 4.2 requires -lm due to libc changes.
    +     [Jason Venner <jason@idiom.com>] PR#667
    +
    +  *) Enable ``=""'' for RewriteCond directives to match against
    +     the empty string. This is the preferred way instead of ``^$''.
    +     [Ralf S. Engelschall]
    +
    +  *) Fixed an infinite loop in mod_imap for references above the server root
    +     [Dean Gaudet] PR#748
    +
    +  *) mod_proxy now has a ReceiveBufferSize directive, similar to
    +     SendBufferSize, so that the TCP window can be set appropriately
    +     for LFNs. [Phillip A. Prindeville]
    +
    +  *) mod_browser has been replaced by the more general mod_setenvif
    +     (courtesy of Paul Sutton).  BrowserMatch* directives are still
    +     available, but are now joined by SetEnvIf*, UnSetEnvIf*, and
    +     UnSetEnvIfZero directives.  [Ken Coar]
    +
    +  *) "HostnameLookups double" forces double-reverse DNS to succeed in
    +     order for remote_host to be set (for logging, or for the env var
    +     REMOTE_HOST).  The old define MAXIMUM_DNS has been deprecated.
    +     [Dean Gaudet]
    +
    +  *) mod_access overhaul:
    +     - Now understands network/netmask syntax (i.e.  10.1.0.0/255.255.0.0)
    +	and cidr syntax (i.e. 10.1.0.0/16).  PR#762
    +     - Critical path was sped up by pre-computing a few things at config
    +	time.
    +     - The undocumented syntax "allow user-agents" was removed,
    +	the replacement is "allow from env=foobar" combined with mod_browser.
    +     - When used with hostnames it now forces a double-reverse lookup
    +	no matter what the directory settings are.  This double-reverse
    +	doesn't affect any of the other routines that use the remote
    +	hostname.  In particular it's still passed to CGIs and the log
    +	without the double-reverse check.  Related PR#860.
    +     [Dean Gaudet]
    +
    +  *) When a large bwrite() occurs (larger than the internal buffer size),
    +     while there is already something in the buffer, apache will combine
    +     the large write and the buffer into a single writev().  (This is
    +     in anticipation of using mmap() for reading files.)
    +     [Dean Gaudet]
    +
    +  *) In obscure cases where a partial socket write occurred while chunking,
    +     Apache would omit the chunk header/footer on the next block.  Cleaned
    +     up other bugs/inconsistencies in error conditions in buff.c.  Fixed
    +     a bug where a long pause in DNS lookups could cause the last packet
    +     of a response to be unduly delayed.  [Roy Fielding, Dean Gaudet]
    +
    +  *) API: Added child_exit function to module structure.  This is called
    +     once per "heavy-weight process" just before a server child exit()'s 
    +     e.g. when max_requests_per_child is reached, etc.
    +     [Doug MacEachern, Dean Gaudet]
    +
    +  *) mod_include cleanup showed that handle_else was being used to handle
    +     endif.  It didn't cause problems, but it was cleaned up too.
    +     [Howard Fear]
    +
    +  *) mod_cern_meta would attempt to find meta files for the directory itself
    +     in some cases, but not in others.  It now avoids it in all cases.
    +     [Dean Gaudet]
    +
    +  *) mod_mime_magic would core dump if there was a decompression error.
    +     [Martin Kraemer <Martin.Kraemer@mch.sni.de>] PR#904
    +
    +  *) PORT: some variants of DGUX require -lsocket -lnsl
    +     [Alexander L Jones <alex@systems-options.co.uk>] PR#732
    +
    +  *) mod_autoindex now allows sorting of FancyIndexed directory listings
    +     by the various fields (name, size, et cetera), either in ascending
    +     or descending order.  Just click on the column header.  [Ken Coar]
    +
    +  *) PORT: Various tweaks to eliminate pointer-int casting warnings on 64-bit
    +     CPUs like the Alpha.  Apache still stores ints in pointers, but that's
    +     the relatively safe direction.  [Dean Gaudet] PR#344
    +
    +  *) PORT: QNX mmap() support for faster/more reliable scoreboard handling.
    +     [Igor N Kovalenko <infoh@mail.wplus.net>] PR#683
    +
    +  *) child_main avoids an unneeded call to select() when there is only one
    +     listening socket.  [Dean Gaudet]
    +
    +  *) In the event that the server is starved for idle servers it will
    +     spawn 1, then 2, then 4, ..., then 32 servers each second,
    +     doubling each second.  It'll also give a warning in the errorlog
    +     since the most common reason for this is a poor StartServers
    +     setting.  The define MAX_SPAWN_RATE can be used to raise/lower
    +     the maximum.  [Dean Gaudet]
    +
    +  *) Apache now provides an effectively unbuffered connection for
    +     CGI scripts.  This means that data will be sent to the client
    +     as soon as the CGI pauses or stops output; previously, Apache would
    +     buffer the output up to a fixed buffer size before sending, which
    +     could result in the user viewing an empty page until the CGI finished
    +     or output a complete buffer.  It is no longer necessary to use an
    +     "nph-" CGI to get unbuffered output.  Given that most CGIs are written
    +     in a language that by default does buffering (e.g. perl) this
    +     shouldn't have a detrimental effect on performance.
    +
    +     "nph-" CGIs, which formerly provided a direct socket to the client
    +     without any server post-processing, were not fully compatible with
    +     HTTP/1.1 or SSL support.  As such they would have had to implement
    +     the transport details, such as encryption or chunking, in order
    +     to work properly in certain situations.  Now, the only difference
    +     between nph and non-nph scripts is "non-parsed headers".
    +     [Dean Gaudet, Sameer Parekh, Roy Fielding]
    +
    +  *) If a BUFF is switched from buffered to unbuffered reading the first
    +     bread() will return whatever remained in the buffer prior to the
    +     switch. [Dean Gaudet]
    +
    +Changes with Apache 1.3a1
    +
    +  *) Added another Configure helper script: TestLib. It determines
    +     if a specified library exists.  [Jim Jagielski]
    +
    +  *) PORT: Allow for use of n32bit libraries under IRIX 6.x
    +     [derived from patch from Jeff Hayes <jhayes@aw.sgi.com>]
    +     PR#721
    +
    +  *) PORT: Some architectures use size_t for various lengths in network
    +     functions such as accept(), and getsockname().  The definition
    +     NET_SIZE_T is used to control this. [Dean Gaudet]
    +
    +  *) PORT: Linux: Attempt to detect glibc based systems and include crypt.h
    +     and -lcrypt.  Test for various db libraries (dbm, ndbm, db) when
    +     mod_auth_dbm or mod_auth_db are included.  [Dean Gaudet]
    +
    +  *) PORT: QNX doesn't have initgroups() which support/suexec.c uses.
    +     [Igor N Kovalenko <infoh@mail.wplus.net>]
    +
    +  *) "force-response-1.0" now only applies to requests which are HTTP/1.0 to
    +     begin with.  "nokeepalive" now works for HTTP/1.1 clients.  Added
    +     "downgrade-1.0" which causes Apache to pretend it received a 1.0.
    +     [Dean Gaudet] related PR#875
    +
    +  *) API: Correct child_init() slot declaration from int to void, to
    +     match the init() declaration.  Update mod_example to use the new
    +     hook.  [Ken Coar]
    +
    +  *) added transport handle slot (t_handle) to the BUFF structure
    +     [Doug MacEachern]
    +
    +  *) get_client_block() returns wrong length if policy is
    +     REQUEST_CHUNKED_DECHUNK.
    +     [Kenichi Hori <ken@d2.bs1.fc.nec.co.jp>] PR#815
    +
    +  *) Support the image map format of FrontPage.  For example:
    +        rect /url.hrm 10 20 30 40
    +     ["Chris O'Byrne" <obyrne@iol.ie>] PR#807
    +
    +  *) PORT: -lresolv and -lsocks were in the wrong order for Solaris.
    +     ["Darren O'Shaughnessy" <darren@aaii.oz.au>] PR#846
    +
    +  *) AddModuleInfo directive for mod_info which allows you to annotate
    +     the output of mod_info.  ["Lou D. Langholtz" <ldl@usi.utah.edu>]
    +
    +  *) Added NoProxy directive to avoid using ProxyRemote for selected
    +     addresses.  Added ProxyDomain directive to cause unqualified
    +     names to be qualified by redirection.
    +     [Martin Kraemer <Martin.Kraemer@mch.sni.de>]
    +
    +  *) Support Proxy Authentication, and don't pass the Proxy-Authorize
    +     header to the remote host in the proxy. [Sameer Parekh and
    +     Wallace]
    +
    +  *) Upgraded mod_rewrite from 3.0.6+ to latest officially available version
    +     3.0.9. This upgrade includes: fixed deadlooping on rewriting to same
    +     URLs, fixed rewritelog(), fixed forced response code handling on
    +     redirects from within .htaccess files, disabled pipe locking under
    +     braindead SunOS 4.1.x, allow env variables to be set even on rules with
    +     no substitution, bugfixed situations where HostnameLookups is off, made
    +     mod_rewrite more thread-safe for NT port and fixed problem when creating
    +     an empty query string via "xxx?".
    +         This update also removes the copyright of Ralf S. Engelschall,
    +     i.e. now mod_rewrite no longer has a shared copyright. Instead is is
    +     exclusively copyrighted by the Apache Group now. This happened because
    +     the author now has gifted mod_rewrite exclusively to the Apache Group and 
    +     no longer maintains an external version.
    +     [Ralf S. Engelschall]
    +
    +  *) API: Added child_init function to module structure.  This is called
    +     once per "heavy-weight process" before any requests are handled.
    +     See http_config.h for more details.  [Dean Gaudet]
    +
    +  *) Anonymous_LogEmail was logging on each subrequest.
    +     [Dean Gaudet] PR#421, 868
    +
    +  *) API: Added is_initial_req() which tests if the request being
    +     processed is the initial request, or a subrequest.
    +     [Doug MacEachern]
    +
    +  *) Extended SSI (mod_include) now handles additional relops for
    +     string comparisons (<, >, <=, and >=).  [Bruno Wolff III] PR#41
    +
    +  *) Configure fixed to correctly propagate user-selected options and
    +     settings (such as CC and OPTIM) to Makefiles other than
    +     src/Makefile (notably support/Makefile).  [Ken Coar] PR#666, #834
    +
    +  *) IndexOptions SuppressHTMLPreamble now causes the actual HTML of
    +     directory indices to start with the contents of the HeaderName file
    +     if there is one.  If there isn't one, the behaviour is unchanged.
    +     [Ken Coar, Roy Fielding, Andrey A. Chernov]
    +
    +  *) WIN32: Modules can now be dynamically loaded DLLs using the
    +     LoadModule/LoadFile directives. Note that module DLLs must be
    +     compiled with the multithreaded DLL version of the runtime library.
    +     [Alexei Kosut and Ben Laurie]
    +
    +  *) Automatic indexing removed from mod_dir and placed into mod_autoindex.
    +     This allows the admin to completely remove automatic indexing
    +     from the server, while still supporting the basic functions of
    +     trailing-slash redirects and DirectoryIndex files.  Note that if
    +     you're carrying over an old Configuration file and you use directory
    +     indexing then you'll want to add:
    +
    +     Module autoindex_module    mod_autoindex.o
    +
    +     before mod_dir in your Configuration.  [Dean Gaudet]
    +
    +  *) popendir/pclosedir created to properly protect directory scanning.
    +     [Dean Gaudet] PR#525
    +
    +  *) AliasMatch, ScriptAliasMatch and RedirectMatch directives added,
    +     giving regex support to mod_alias. <DirectoryMatch>, <LocationMatch>
    +     and <FilesMatch> sections added to succeed <DirectoryMatch ~>, etc...
    +     [Alexei Kosut]
    +
    +  *) The AccessFileName directive can now take more than one filename.
    +     ["Lou D. Langholtz" <ldl@usi.utah.edu>]
    +
    +  *) The new mod_mime_magic can be used to "magically" determine the type
    +     of a file if the extension is unknown.  Based on the unix file(1)
    +     command.  [Ian Kluft <ikluft@cisco.com>]
    +
    +  *) We now determine and display the time spent processing a
    +     request if desired.  [Jim Jagielski]
    +
    +  *) mod_status: PID field of "dead" child slots no longer displays
    +     main httpd process's PID.  [Jim Jagielski]
    +
    +  *) Makefile.nt added - to build all the bits from the command line:
    +        nmake -f Makefile.nt
    +         Doesn't yet work properly. [Ben Laurie]
    +
    +  *) Default text of 404 error is now "Not Found" rather than the
    +     potentially misleading "File Not Found".  [Ken Coar]
    +
    +  *) CONFIG: "HostnameLookups" now defaults to off because it is far better
    +     for the net if we require people that actually need this data to
    +     enable it.  [Linus Torvalds]
    +
    +  *) directory_walk() is an expensive function, keep a little more state to
    +     avoid needless string counting.  Add two new functions make_dirstr_parent
    +     and make_dirstr_prefix which replace all existing uses of make_dirstr.
    +     The new functions are a little less general than make_dirstr, but
    +     work more efficiently (less memory, less string counting).
    +     [Dean Gaudet]
    +
    +  *) EXTRA_LFLAGS was changed to EXTRA_LDFLAGS (and LFLAGS was changed
    +     to LDFLAGS) to avoid complications with lex rules in make files.
    +     [Dean Gaudet] PR#372
    +
    +  *) run_method optimized to avoid needless scanning over NULLs in the
    +     module list.  [Dean Gaudet]
    +
    +  *) Revamp of (unix) scoreboard management code such that it avoids
    +     unnecessary traversals of the scoreboard on each hit.  This is
    +     particularly important for high volume sites with a large
    +     HARD_SERVER_LIMIT.  Some of the previous operations were O(n^2),
    +     and are now O(n).  See also SCOREBOARD_MAINTENANCE_INTERVAL in
    +     httpd.h. [Dean Gaudet]
    +
    +  *) In configurations using multiple Listen statements it was possible for
    +     busy sockets to starve other sockets of service.  [Dean Gaudet]
    +
    +  *) Added hook so standalone_main can be replaced at compile time
    +     (define STANDALONE_MAIN)
    +     [Doug MacEachern]
    +
    +  *) Lowest-level read/write functions in buff.c will be replaced with
    +     the SFIO library calls sfread/sfwrite if B_SFIO is defined at
    +     compile time.  The default sfio discipline will behave as apache
    +     would without sfio compiled in.
    +     [Doug MacEachern]
    +
    +  *) Enhance UserDir directive (mod_userdir) to accept a list of
    +     usernames for the 'disable' keyword, and add 'enable user...' to
    +     selectively *en*able userdirs if they're globally disabled.
    +     [Ken Coar]
    +
    +  *) If NETSCAPE_DBM_COMPAT is defined in EXTRA_CFLAGS then Apache
    +     will work with Netscape dbm files.  (dbmmanage will probably not
    +     work however.) [Alexander Spohr <aspohr@netmatic.com>] PR#444
    +
    +  *) Add a ListenBacklog directive to control the backlog parameter
    +     passed to listen().  Also change the default to 511 from 512.
    +     [Marc Slemko]
    +
    +  *) API: A new handler response DONE which informs apache that the
    +     request has been handled and it can finish off quickly, similar to
    +     how it handles errors. [Rob Hartill]
    +
    +  *) Turn off chunked encoding after sending terminating chunk/footer
    +     so that we can't do it twice by accident. [Roy Fielding]
    +
    +  *) mod_expire also issues Cache-Control: max-age headers.
    +     [Rob Hartill]
    +
    +  *) API: Added kill_only_once option for free_proc_chain so that it won't
    +     aggressively try to kill off specific children.  For fastcgi.
    +     [Stanley Gambarin <gambarin@OpenMarket.com>]
    +
    +  *) mod_auth deals with extra ':' delimited fields.  [Marc Slemko]
    +
    +  *) Added IconHeight and IconWidth to mod_dir's IndexOptions directive.
    +     When used together, these cause mod_dir to emit HEIGHT and WIDTH
    +     attributes in the FancyIndexing IMG tags.  [Ken Coar]
    +
    +  *) PORT: Sequent and SONY NEWS-OS support added.  [Jim Jagielski]
    +
    +  *) PORT: Added Windows NT support
    +     [Ben Laurie and Ambarish Malpani <ambarish@valicert.com>]
    +
    +Changes with Apache 1.2.6
    +
    +  *) mod_include when using XBitHack Full would send ETags in addition to
    +     sending Last-Modifieds.  This is incorrect HTTP/1.1 behaviour.
    +     [Dean Gaudet] PR#1133
    +
    +  *) SECURITY: When a client connects to a particular port/addr, and
    +     gives a Host: header ensure that the virtual host requested can
    +     actually be reached via that port/addr.  [Ed Korthof <ed@organic.com>]
    +
    +  *) Support virtual hosts with wildcard port and/or multiple ports
    +     properly.  [Ed Korthof <ed@organic.com>]
    +
    +  *) Fixed some case-sensitivity issues according to RFC2068.
    +     [Dean Gaudet]
    +
    +  *) Set r->allowed properly in mod_asis.c, mod_dir.c, mod_info.c,
    +     and mod_include.c.  [Dean Gaudet]
    +
    +  *) Variable 'cwd' was being used pointlessly before being set.
    +     [Ken Coar] PR#1738
    +
    +  *) SIGURG doesn't exist on all platforms.
    +     [Mark Andrew Heinrich <heinrich@tinderbox.Stanford.EDU>]
    +
    +  *) When an error occurs during a POST, or other operation with a
    +     request body, the body has to be read from the net before allowing
    +     a keepalive session to continue.  [Roy Fielding] PR#1399
    +
    +  *) When an error occurs in fcntl() locking suggest the user look up
    +     the docs for LockFile.  [Dean Gaudet]
    +
    +  *) table_set() and table_unset() did not deal correctly with
    +     multiple occurrences of the same key. [Stephen Scheck
    +     <sscheck@infonex.net>, Ben Laurie] PR#1604
    +
    +  *) send_fd_length() did not calculate total_bytes_sent properly in error
    +     cases.  [Ben Reser <breser@regnow.com>] PR#1366
    +
    +  *) r->connection->user was allocated in the wrong pool causing corruption
    +     in some cases when used with mod_cern_meta.  [Dean Gaudet] PR#1500
    +
    +  *) mod_proxy was sending HTTP/1.1 responses to ftp requests by mistake.
    +     Also removed the auto-generated link to www.apache.org that was the
    +     source of so many misdirected bug reports.  [Roy Fielding, Marc Slemko]
    +
    +  *) Multiple "close" tokens may have been set in the "Connection"
    +     header, not an error, but a waste.
    +     [Ronald.Tschalaer@psi.ch] PR#1683
    +
    +  *) "basic" and "digest" auth tokens should be tested case-insensitive.
    +     [Ronald.Tschalaer@psi.ch] PR#1599, PR#1666
    +
    +  *) It appears the "257th byte" bug (see
    +     htdocs/manual/misc/known_client_problems.html#257th-byte) can happen
    +     at the 256th byte as well.  Fixed.  [Dean Gaudet]
    +
    +  *) mod_rewrite would not handle %3f properly in some situations.
    +     [Ralf Engelschall]
    +
    +  *) Apache could generate improperly chunked HTTP/1.1 responses when
    +     the bputc() or rputc() functions were used by modules (such as
    +     mod_include).  [Dean Gaudet]
    +
    +  *) #ifdef wrap a few #defines in httpd.h to make life easier on
    +     some ports.  [Ralf Engelschall]
    +
    +  *) Fix MPE compilation error in mod_usertrack.c.  [Mark Bixby]
    +
    +  *) Quote CC='$(CC)' to improve recurse make calls.  [Martin Kraemer]
    +
    +  *) Avoid B_ERROR redeclaration on sysvr4 systems.  [Martin Kraemer]
    +
    +Changes with Apache 1.2.5
    +
    +  *) SECURITY: Fix a possible buffer overflow in logresolve.  This is
    +     only an issue on systems without a MAXDNAME define or where 
    +     the resolver returns domain names longer than MAXDNAME.  [Marc Slemko]
    +
    +  *) Fix an improper length in an ap_snprintf call in proxy_date_canon().
    +     [Marc Slemko]
    +
    +  *) Fix core dump in the ftp proxy when reading incorrectly formatted
    +     directory listings.  [Marc Slemko]
    +
    +  *) SECURITY: Fix possible minor buffer overflow in the proxy cache.
    +     [Marc Slemko]
    +
    +  *) SECURITY: Eliminate possible buffer overflow in cfg_getline, which
    +     is used to read various types of files such as htaccess and 
    +     htpasswd files.  [Marc Slemko]
    +
    +  *) SECURITY: Ensure that the buffer returned by ht_time is always
    +     properly null terminated.  [Marc Slemko]
    +
    +  *) SECURITY: General mod_include cleanup, including fixing several
    +     possible buffer overflows and a possible infinite loop.  This cleanup
    +     was done against 1.3 code and then backported to 1.2, the result
    +     is a large difference (due to indentation cleanup in 1.3 code).
    +     Users interested in seeing a smaller set of relevant differences
    +     should consider comparing against src/modules/standard/mod_include.c
    +     from the 1.3b3 release.  Non-indentation changes to mod_include
    +     between 1.2 and 1.3 were minimal.  [Dean Gaudet, Marc Slemko]
    +
    +  *) SECURITY: Numerous changes to mod_imap in a general cleanup
    +     including fixing a possible buffer overflow.  This cleanup also
    +     was done with 1.3 code as a basis, see the the previous note
    +     about mod_include.  [Dean Gaudet]
    +
    +  *) SECURITY: If a htaccess file can not be read due to bad 
    +     permissions, deny access to the directory with a HTTP_FORBIDDEN.  
    +     The previous behavior was to ignore the htaccess file if it could not
    +     be read.  This change may make some setups with unreadable
    +     htaccess files stop working.  PR#817  [Marc Slemko]
    +
    +  *) SECURITY: no2slash() was O(n^2) in the length of the input.  
    +     Make it O(n).  This inefficiency could be used to mount a denial 
    +     of service attack against the Apache server.  Thanks to 
    +     Michal Zalewski <lcamtuf@boss.staszic.waw.pl> for reporting
    +     this.  [Dean Gaudet]
    +
    +  *) mod_include used uninitialized data for some uses of && and ||.
    +     [Brian Slesinsky <bslesins@wired.com>] PR#1139
    +
    +  *) mod_imap should decline all non-GET methods.
    +     [Jay Bloodworth <jay@pathways.sde.state.sc.us>]
    +
    +  *) suexec.c wouldn't build without -DLOG_EXEC. [Jason A. Dour]
    +
    +  *) mod_userdir was modifying r->finfo in cases where it wasn't setting
    +     r->filename.  Since those two are meant to be in sync with each other
    +     this is a bug.  ["Paul B. Henson" <henson@intranet.csupomona.edu>]
    +
    +  *) mod_include did not properly handle all possible redirects from sub-
    +     requests.  [Ken Coar]
    +
    +  *) Inetd mode (which is buggy) uses timeouts without having setup the
    +     jmpbuffer. [Dean Gaudet] PR#1064
    +
    +  *) Work around problem under Linux where a child will start looping
    +     reporting a select error over and over.
    +     [Rick Franchuk <rickf@transpect.net>] PR#1107
    +
    +Changes with Apache 1.2.4
    +
    +  *) The ProxyRemote change in 1.2.3 introduced a bug resulting in the proxy
    +     always making requests with the full-URI instead of just the URI path.
    +     [Marc Slemko, Roy Fielding]
    +
    +  *) Add -lm for AIX versions >= 4.2 to allow Apache to link properly
    +     on this platform.  [Marc Slemko]
    +
    +Changes with Apache 1.2.3
    +
    +  *) The request to a remote proxy was mangled if it was generated as the
    +     result of a ProxyPass directive. URL schemes other than http:// were not
    +     supported when ProxyRemote was used. PR#260, PR#656, PR#699, PR#713,
    +     PR#812 [Lars Eilebrecht]
    +
    +  *) Fixed proxy-pass-through feature of mod_rewrite; Added error logging
    +     information for case where proxy module is not available. [Marc Slemko]
    +
    +  *) Force proxy to always respond as HTTP/1.0, which it was failing to
    +     do for errors and cached responses.  [Roy Fielding]
    +
    +  *) PORT: Improved support for ConvexOS 11.  [Jeff Venters]
    +
    +Changes with Apache 1.2.2 [not released]
    +
    +  *) Fixed another long-standing bug in sub_req_lookup_file where it would
    +     happily skip past access checks on subdirectories looked up with relative
    +     paths.  (It's used by mod_dir, mod_negotiation, and mod_include.)
    +     [Dean Gaudet]
    +
    +  *) Add lockfile name to error message printed out when
    +     USE_FLOCK_SERIALIZED_ACCEPT is defined.
    +     [Marc Slemko]
    +
    +  *) Enhanced the chunking and error handling inside the buffer functions.
    +     [Dean Gaudet, Roy Fielding]
    +
    +  *) When merging the main server's <Directory> and <Location> sections into
    +     a vhost, put the main server's first and the vhost's second.  Otherwise
    +     the vhost can't override the main server.  [Dean Gaudet] PR#717
    +
    +  *) The <Directory> code would merge and re-merge the same section after
    +     a match was found, possibly causing problems with some modules.
    +     [Dean Gaudet]
    +
    +  *) Fixed an infinite loop in mod_imap for references above the server root.
    +     [Dean Gaudet] PR#748
    +
    +  *) mod_include cleanup showed that handle_else was being used to handle
    +     endif.  It didn't cause problems, but it was cleaned up too.
    +     [Howard Fear]
    +
    +  *) Last official synchronization of mod_rewrite with author version (because
    +     mod_rewrite is now directly developed by the author at the Apache Group):
    +     o added diff between mod_rewrite 3.0.6+ and 3.0.9
    +       minus WIN32/NT stuff, but plus copyright removement.
    +       In detail:
    +       - workaround for detecting infinite rewriting loops
    +       - fixed setting of env vars when "-" is used as subst string
    +       - fixed forced response code on redirects (PR#777)
    +       - fixed cases where r->args is ""
    +       - kludge to disable locking on pipes under braindead SunOS
    +       - fix for rewritelog in cases where remote hostname is unknown
    +       - fixed totally damaged request_rec walk-back loop
    +     o remove static from local data and add static to global ones.
    +     o replaced ugly proxy finding stuff by simple
    +       find_linked_module("mod_proxy") call.
    +     o added missing negation char on rewritelog()
    +     o fixed a few comment typos
    +     [Ralf S. Engelschall]
    +
    +  *) Anonymous_LogEmail was logging on each subrequest.
    +     [Dean Gaudet] PR#421, PR#868
    +
    +  *) "force-response-1.0" now only applies to requests which are HTTP/1.0 to
    +     begin with.  "nokeepalive" now works for HTTP/1.1 clients.  Added
    +     "downgrade-1.0" which causes Apache to pretend it received a 1.0.
    +     Additionally mod_browser now triggers during translate_name to workaround
    +     a deficiency in the header_parse phase.
    +     [Dean Gaudet] PR#875
    +
    +  *) get_client_block() returns wrong length if policy is 
    +     REQUEST_CHUNKED_DECHUNK.
    +     [Kenichi Hori <ken@d2.bs1.fc.nec.co.jp>] PR#815
    +
    +  *) Properly treat <files> container like other containers in mod_info.
    +     [Marc Slemko] PR#848
    +
    +  *) The proxy didn't treat the "Host:" keyword of the host header as case-
    +     insensitive.  The proxy would corrupt the first line of a response from
    +     an HTTP/0.9 server.  [Kenichi Hori <ken@d2.bs1.fc.nec.co.jp>] PR#813,814
    +
    +  *) mod_include would log some bogus values occasionally.
    +     [Skip Montanaro <skip@calendar.com>, Marc Slemko] PR#797
    +
    +  *) PORT: The slack fd changes in 1.2.1 introduced a problem with SIGHUP
    +     under Solaris 2.x (up through 2.5.1).  It has been fixed.
    +     [Dean Gaudet] PR#832
    +
    +  *) API: In HTTP/1.1, whether or not a request message contains a body
    +     is independent of the request method and based solely on the presence
    +     of a Content-Length or Transfer-Encoding.  Therefore, our default
    +     handlers need to be prepared to read a body even if they don't know
    +     what to do with it; otherwise, the body would be mistaken for the
    +     next request on a persistent connection.  discard_request_body()
    +     has been added to take care of that.  [Roy Fielding] PR#378
    +
    +  *) API: Symbol APACHE_RELEASE provides a numeric form of the Apache
    +     release version number, such that it always increases along the
    +     same lines as our source code branching.  [Roy Fielding]
    +
    +  *) Minor oversight on multiple variants fixed.  [Paul Sutton] PR#94
    +
    +Changes with Apache 1.2.1
    +
    +  *) SECURITY: Don't serve file system objects unless they are plain files,
    +     symlinks, or directories.  This prevents local users from using pipes
    +     or named sockets to invoke programs for an extremely crude form of
    +     CGI.  [Dean Gaudet]
    +
    +  *) SECURITY: HeaderName and ReadmeName were settable in .htaccess and
    +     could contain "../" allowing a local user to "publish" any file on
    +     the system.  No slashes are allowed now.  [Dean Gaudet]
    +
    +  *) SECURITY: It was possible to violate the symlink Options using mod_dir
    +     (headers, readmes, titles), mod_negotiation (type maps), or
    +     mod_cern_meta (meta files).  [Dean Gaudet]
    +
    +  *) SECURITY: Apache will refuse to run as "User root" unless
    +     BIG_SECURITY_HOLE is defined at compile time.  [Dean Gaudet]
    +
    +  *) CONFIG: If a symlink pointed to a directory then it would be disallowed
    +     if it contained a .htaccess disallowing symlinks.  This is contrary
    +     to the rule that symlink permissions are tested with the symlink
    +     options of the parent directory.  [Dean Gaudet] PR#353
    +
    +  *) CONFIG: The LockFile directive can be used to place the serializing
    +     lockfile in any location.  It previously defaulted to /usr/tmp/htlock.
    +     [Somehow it took four of us: Randy Terbush, Jim Jagielski, Dean Gaudet,
    +     Marc Slemko]
    +
    +  *) Request processing now retains state of whether or not the request
    +     body has been read, so that internal redirects and subrequests will
    +     not try to read it twice (and block). [Roy Fielding]
    +
    +  *) Add a placeholder in modules/Makefile to avoid errors with certain
    +     makes. [Marc Slemko]
    +
    +  *) QUERY_STRING was unescaped in mod_include, it shouldn't be.
    +     [Dean Gaudet] PR#644
    +
    +  *) mod_include was not properly changing the current directory.
    +     [Marc Slemko] PR#742
    +
    +  *) Attempt to work around problems with third party libraries that do not
    +     handle high numbered descriptors (examples include bind, and
    +     solaris libc).  On all systems apache attempts to keep all permanent
    +     descriptors above 15 (called the low slack line).  Solaris users
    +     can also benefit from adding -DHIGH_SLACK_LINE=256 to EXTRA_CFLAGS
    +     which keeps all non-FILE * descriptors above 255.  On all systems
    +     this should make supporting large numbers of vhosts with many open
    +     log files more feasible.  If this causes trouble please report it,
    +     you can disable this workaround by adding -DNO_SLACK to EXTRA_CFLAGS.
    +     [Dean Gaudet] various PRs
    +
    +  *) Related to the last entry, network sockets are now opened before
    +     log files are opened.  The only known case where this can cause
    +     problems is under Solaris with many virtualhosts and many Listen
    +     directives.  But using -DHIGH_SLACK_LINE=256 described above will
    +     work around this problem.  [Dean Gaudet]
    +
    +  *) USE_FLOCK_SERIALIZED_ACCEPT is now default for FreeBSD, A/UX, and
    +     SunOS 4.
    +
    +  *) Improved unix error response logging.  [Marc Slemko]
    +
    +  *) Update mod_rewrite from 3.0.5 to 3.0.6.  New ruleflag
    +     QSA=query_string_append.  Also fixed a nasty bug in per-dir context:
    +     when a URL http://... was used in conjunction with a special
    +     redirect flag, e.g. R=permanent, the permanent status was lost.
    +     [Ronald Tschalaer <Ronald.Tschalaer@psi.ch>, Ralf S. Engelschall]
    +
    +  *) If an object has multiple variants that are otherwise equal Apache
    +     would prefer the last listed variant rather than the first.
    +     [Paul Sutton] PR#94
    +
    +  *) "make clean" at the top level now removes *.o.  [Dean Gaudet] PR#752
    +
    +  *) mod_status dumps core in inetd mode.  [Marc Slemko and Roy Fielding]
    +     PR#566
    +
    +  *) pregsub had an off-by-1 in its error checking code. [Alexei Kosut]
    +
    +  *) PORT: fix rlim_t problems with AIX 4.2. [Marc Slemko] PR#333
    +
    +  *) PORT: Update UnixWare support for 2.1.2.
    +     [Lawrence Rosenman <ler@lerctr.org>] PR#511
    +
    +  *) PORT: NonStop-UX [Joachim Schmitz <schmitz_joachim@tandem.com>] PR#327
    +
    +  *) PORT: Update ConvexOS support for 11.5.
    +     [David DeSimone <fox@convex.com>] PR#399
    +
    +  *) PORT: Support for DEC cc compiler under ULTRIX.
    +     ["P. Alejandro Lopez-Valencia" <alejolo@ideam.gov.co>] PR#388
    +
    +  *) PORT: Support for Maxion/OS SVR4.2 Real Time Unix. [no name given] PR#383
    +
    +  *) PORT: Workaround for AIX 3.x compiler bug in http_bprintf.c.  
    +     [Marc Slemko] PR#725
    +
    +  *) PORT: fix problem compiling http_bprintf.c with gcc under SCO
    +     [Marc Slemko] PR#695
    +
    +Changes with Apache 1.2
    +
    +Changes with Apache 1.2b11
    +
    +  *) Fixed open timestamp fd in proxy_cache.c [Chuck Murcko]
    +
    +  *) Added undocumented perl SSI mechanism for -DUSE_PERL_SSI and mod_perl.
    +     [Doug MacEachern, Rob Hartill]
    +
    +  *) Proxy needs to use hard_timeout instead of soft_timeout when it is
    +     reading from one buffer and writing to another, at least until it has
    +     a custom timeout handler.  [Roy Fielding and Petr Lampa]
    +
    +  *) Fixed problem on IRIX with servers hanging in IdentityCheck,
    +     apparently due to a mismatch between sigaction and setjmp.
    +     [Roy Fielding] PR#502
    +
    +  *) Log correct status code if we timeout before receiving a request (408)
    +     or if we received a request-line that was too long to process (414).
    +     [Ed Korthof and Roy Fielding] PR#601
    +
    +  *) Virtual hosts with the same ServerName, but on different ports, were
    +     not being selected properly.  [Ed Korthof]
    +
    +  *) Added code to return the requested IP address from proxy_host2addr()
    +     if gethostbyaddr() fails due to reverse DNS lookup problems. Original
    +     change submitted by Jozsef Hollosi <hollosi@sbcm.com>.
    +     [Chuck Murcko] PR#614
    +
    +  *) If multiple requests on a single connection are used to retrieve
    +     data from different virtual hosts, the virtual host list would be
    +     scanned starting with the most recently used VH instead of the first,
    +     causing most virtual hosts to be ignored.
    +     [Paul Sutton and Martin Mares] PR#610
    +
    +  *) The OS/2 handling of process group was broken by a porting patch for
    +     MPE, so restored prior code for OS/2.  [Roy Fielding and Garey Smiley]
    +
    +  *) Inherit virtual server port from main server if none (or "*") is
    +     given for VirtualHost.  [Dean Gaudet] PR#576
    +
    +  *) If the lookup for a DirectoryIndex name with content negotiation
    +     has found matching variants, but none are acceptable, return the
    +     negotiation result if there are no more DirectoryIndex names to lookup.
    +     [Petr Lampa and Roy Fielding]
    +
    +  *) If a soft_timeout occurs after keepalive is set, then the main child
    +     loop would try to read another request even though the connection
    +     has been aborted.  [Roy Fielding]
    +
    +  *) Configure changes: Allow for whitespace at the start of a
    +     Module declaration. Also, be more understanding about the
    +     CC=/OPTIM= format in Configuration. Finally, fix compiler
    +     flags if using HP-UX's cc compiler. [Jim Jagielski]
    +
    +  *) Subrequests and internal redirects now inherit the_request from the
    +     original request-line. [Roy Fielding]
    +
    +  *) Test for error conditions before creating output header fields, since
    +     we don't want the error message to include those fields.  Likewise,
    +     reset the content_language(s) and content_encoding of the response
    +     before generating or redirecting to an error message, since the new
    +     message will have its own Content-* definitions. [Dean Gaudet]
    +
    +  *) Restored the semantics of headers_out (headers sent only with 200..299
    +     and 304 responses) and err_headers_out (headers sent with all responses).
    +     Avoid the overhead of copying tables if err_headers_out is empty
    +     (the usual case).  [Roy Fielding]
    +
    +  *) Fixed a couple places where a check for the default Content-Type was
    +     not properly checking both the value configured by the DefaultType
    +     directive and the DEFAULT_TYPE symbol in httpd.h.  Changed the value
    +     of DEFAULT_TYPE to match the documented default (text/plain).
    +     [Dean Gaudet] PR#506
    +
    +  *) Escape the HTML-sensitive characters in the Request-URI that is
    +     output for each child by mod_status. [Dean Gaudet and Ken Coar] PR#501
    +
    +  *) Properly initialize the flock structures used by the mutex locking
    +     around accept() when USE_FCNTL_SERIALIZED_ACCEPT is defined.
    +     [Marc Slemko]
    +
    +  *) The method for determining PATH_INFO has been restored to the pre-1.2b
    +     (and NCSA httpd) definition wherein it was the extra path info beyond
    +     the CGI script filename.  The environment variable FILEPATH_INFO has
    +     been removed, and instead we supply the original REQUEST_URI to any
    +     script that wants to be Apache-specific and needs the real URI path.
    +     This solves a problem with existing scripts that use extra path info
    +     in the ScriptAlias directive to pass options to the CGI script.
    +     [Roy Fielding]
    +
    +  *) The _default_ change in 1.2b10 will change the behaviour on configs
    +     that use multiple Listen statements for listening on multiple ports.
    +     But that change is necessary to make _default_ consistent with other
    +     forms of <VirtualHost>.  It requires such configs to be modified
    +     to use <VirtualHost _default_:*>.  The documentation has been
    +     updated.  [Dean Gaudet] PR#530
    +
    +  *) If an ErrorDocument CGI script is used to respond to an error
    +     generated by another CGI script which has already read the message
    +     body of the request, the server would block trying to read the
    +     message body again.  [Rob Hartill]
    +
    +  *) signal() replacement conflicted with a define on QNX (and potentially
    +     other platforms). Fixed. [Ben Laurie] PR#512
    +
    +Changes with Apache 1.2b10
    +
    +  *) Allow HTTPD_ROOT, SERVER_CONFIG_FILE, DEFAULT_PATH, and SHELL_PATH
    +     to be configured via -D in Configuration.  [Dean Gaudet] PR#449
    +
    +  *) <VirtualHost _default_:portnum> didn't work properly.  [Dean Gaudet]
    +
    +  *) Added prototype for mktemp() for SUNOS4 [Marc Slemko]
    +
    +  *) In mod_proxy.c, check return values for proxy_host2addr() when reading
    +     config, in case the hostent struct returned is trash.
    +     [Chuck Murcko] PR #491
    +
    +  *) Fixed the fix in 1.2b9 for parsing URL query info into args for CGI
    +     scripts.  [Dean Gaudet, Roy Fielding, Marc Slemko]
    +
    +Changes with Apache 1.2b9  [never announced]
    +
    +  *) Reset the MODULE_MAGIC_NUMBER to account for the unsigned port
    +     changes and in anticipation of 1.2 final release.  [Roy Fielding]
    +
    +  *) Fix problem with scripts not receiving a SIGPIPE when client drops
    +     the connection (e.g., when user presses Stop).  Apache will now stop
    +     trying to send a message body immediately after an error from write.
    +     [Roy Fielding and Nathan Kurz] PR#335
    +
    +  *) Rearrange Configuration.tmpl so that mod_rewrite has higher priority
    +     than mod_alias, and mod_alias has higher priority than mod_proxy;
    +     rearranged other modules to enhance understanding of their purpose
    +     and relative order (and maybe even reduce some overhead).
    +     [Roy Fielding and Sameer Parekh]
    +
    +  *) Fix graceful restart.  Eliminate many signal-related race
    +     conditions in both forms of restart, and in SIGTERM.  See
    +     htdocs/manual/stopping.html for details on stopping and
    +     restarting the parent.  [Dean Gaudet]
    +
    +  *) Fix memory leaks in mod_rewrite, mod_browser, mod_include.  Tune
    +     memory allocator to avoid a behaviour that required extra blocks to
    +     be allocated.  [Dean Gaudet]
    +
    +  *) Allow suexec to access files relative to current directory but not
    +     above.  (Excluding leading / or any .. directory.)  [Ken Coar]
    +     PR#269, 319, 395
    +
    +  *) Fix suexec segfault when group doesn't exist. [Gregory Neil Shapiro]
    +     PR#367, 368, 354, 453
    +
    +  *) Fix the above fix: if suexec is enabled, avoid destroying r->url
    +     while obtaining the /~user and save the username in a separate data
    +     area so that it won't be overwritten by the call to getgrgid(), and
    +     fix some misuse of the pool string allocation functions.  Also fixes
    +     a general problem with parsing URL query info into args for CGI scripts.
    +     [Roy Fielding] PR#339, 367, 354, 453
    +
    +  *) Fix IRIX warning about bzero undefined. [Marc Slemko]
    +
    +  *) Fix problem with <Directory proxy:...>. [Martin Kraemer] PR#271
    +
    +  *) Corrected spelling of "authoritative".  AuthDBAuthoratative became
    +     AuthDBAuthoritative. [Marc Slemko] PR#420
    +
    +  *) MaxClients should be at least 1. [Lars Eilebrecht] PR#375
    +
    +  *) The default handler now logs invalid methods or URIs (i.e. PUT on an
    +     object that can't be PUT, or FOOBAR for some method FOOBAR that
    +     apache doesn't know about at all).  Log 404s that occur in mod_include.
    +     [Paul Sutton, John Van Essen]
    +
    +  *) If a soft timeout (or lingerout) occurs while trying to flush a
    +     buffer or write inside buff.c or fread'ing from a CGI's output,
    +     then the timeout would be ignored. [Roy Fielding] PR#373
    +
    +  *) Work around a bug in Netscape Navigator versions 2.x, 3.x and 4.0b2's
    +     parsing of headers.  If the terminating empty-line CRLF occurs starting
    +     at the 256th or 257th byte of output, then Navigator will think a normal
    +     image is invalid.  We are guessing that this is because their initial
    +     read of a new request uses a 256 byte buffer. We check the bytes written
    +     so far and, if we are about to tickle the bug, we instead insert a
    +     padding header of eminent bogosity. [Roy Fielding and Dean Gaudet] PR#232
    +
    +  *) Fixed SIGSEGV problem when a DirectoryIndex file is also the source
    +     of an external redirection.  [Roy Fielding and Paul Sutton]
    +
    +  *) Configure would create a broken Makefile if the configuration file
    +     contained a commented-out Rule.  [Roy Fielding]
    +
    +  *) Promote per_dir_config and subprocess_env from the subrequest to the
    +     main request in mod_negotiation.  In particular this fixes a bug
    +     where <Files> sections wouldn't properly apply to negotiated content.
    +     [Dean Gaudet]
    +
    +  *) Fix a potential deadlock in mod_cgi script_err handling.
    +     [Ralf S. Engelschall]
    +
    +  *) rotatelogs zero-pads the logfile names to improve alphabetic sorting.
    +     [Mitchell Blank Jr]
    +
    +  *) Updated mod_rewrite to 3.0.4: Fixes HTTP redirects from within
    +     .htaccess files because the RewriteBase was not replaced correctly.
    +     Updated mod_rewrite to 3.0.5: Fixes problem with rewriting inside
    +     <Directory> sections missing a trailing /.  [Ralf S. Engelschall]
    +
    +  *) Clean up Linux settings in conf.h by detecting 2.x versus 1.x.  For
    +     1.x the settings are those of pre-1.2b8.  For 2.x we include
    +     USE_SHMGET_SCOREBOARD (scoreboard in shared memory rather than file) and
    +     HAVE_SYS_RESOURCE_H (enable the RLimit commands).
    +     [Dean Gaudet] PR#336, PR#340
    +
    +  *) Redirect did not preserve ?query_strings when present in the client's
    +     request.  [Dean Gaudet]
    +
    +  *) Configure was finding non-modules on EXTRA_LIBS. [Frank Cringle] PR#380
    +
    +  *) Use /bin/sh5 on ULTRIX.  [P. Alejandro Lopez-Valencia] PR#369
    +
    +  *) Add UnixWare compile/install instructions.  [Chuck Murcko]
    +
    +  *) Add mod_example (illustration of API techniques).  [Ken Coar]
    +
    +  *) Add macro for memmove to conf.h for SUNOS4. [Marc Slemko]
    +
    +  *) Improve handling of directories when filenames have spaces in them.
    +     [Chuck Murcko]
    +
    +  *) For hosts with multiple IP addresses, try all additional addresses if
    +     necessary to get a connect. Fail only if hostent address list is
    +     exhausted. [Chuck Murcko]
    +
    +  *) More signed/unsigned port fixes.  [Dean Gaudet]
    +
    +  *) HARD_SERVER_LIMIT can be defined in the Configuration file now.
    +     [Dean Gaudet]
    +
    +Changes with Apache 1.2b8
    +
    +  *) suexec.c doesn't close the log file, allowing CGIs to continue writing
    +     to it.  [Marc Slemko]
    +
    +  *) The addition of <Location> and <File> directives made the
    +     sub_req_lookup_simple() function bogus, so we now handle
    +     the special cases directly.  [Dean Gaudet]
    +
    +  *) We now try to log where the server is dumping core when a fatal
    +     signal is received.  [Ken Coar]
    +
    +  *) Improved lingering_close by adding a special timeout, removing the
    +     spurious log messages, removing the nonblocking settings (they
    +     are not needed with the better timeout), and adding commentary
    +     about the NO_LINGCLOSE and USE_SO_LINGER issues.  NO_LINGCLOSE is
    +     now the default for SunOS4, UnixWare, NeXT, and IRIX.  [Roy Fielding]
    +
    +  *) Send error messages about setsockopt failures to the server error
    +     log instead of stderr.  [Roy Fielding]
    +
    +  *) Fix loopholes in proxy cache expiry vis a vis alarms. [Brian Moore]
    +
    +  *) Stopgap solution for CGI 3-second delay with server-side includes: if
    +     processing a subrequest, allocate memory from r->main->pool instead
    +     of r->pool so that we can avoid waiting for free_proc_chain to cleanup
    +     in the middle of an SSI request.  [Dean Gaudet] PR #122
    +
    +  *) Fixed status of response when POST is received for a nonexistent URL
    +     (was sending 405, now 404) and when any method is sent with a
    +     full-URI that doesn't match the server and the server is not acting
    +     as a proxy (was sending 501, now 403).  [Roy Fielding]
    +
    +  *) Host port changed to unsigned short. [Ken Coar] PR #276
    +
    +  *) Fix typo in command definition of AuthAuthoritative. [Ken Coar] PR #246
    +
    +  *) Defined USE_SHMGET_SCOREBOARD for shared memory on Linux.  [Dean Gaudet]
    +
    +  *) Report extra info from errno with many errors that cause httpd to exit.
    +     spawn_child, popenf, and pclosef now have valid errno returns in the
    +     event of an error.  Correct problems where errno was stomped on
    +     before being reported.  [Dean Gaudet]
    +
    +  *) In the proxy, if the cache filesystem was full, garbage_coll() was
    +     never called, and thus the filesystem would remain full indefinitely.
    +     We now also remove incomplete cache files left if the origin server
    +     didn't send a Content-Length header and either the client has aborted
    +     transfer or bwrite() to client has failed. [Petr Lampa]
    +
    +  *) Fixed the handling of module and script-added header fields.
    +     Improved the interface for sending header fields and reduced
    +     the duplication of code between sending okay responses and errors.
    +     We now always send both headers_out and err_headers_out, and
    +     ensure that the server-reserved fields are not being overridden,
    +     while not overriding those that are not reserved.  [Roy Fielding]
    +
    +  *) Moved transparent content negotiation fields to err_headers_out
    +     to reflect above changes.  [Petr Lampa]
    +
    +  *) Fixed the determination of whether or not we should make the
    +     connection persistent for all of the cases where some other part
    +     of the server has already indicated that we should not.  Also
    +     improved the ordering of the test so that chunked encoding will
    +     be set whenever it is desired instead of only when KeepAlive
    +     is enabled. Added persistent connection capability for most error
    +     responses (those that do not indicate a bad input stream) when
    +     accessed by an HTTP/1.1 client. [Roy Fielding]
    +
    +  *) Added missing timeouts for sending header fields, error responses,
    +     and the last chunk of chunked encoding, each of which could have
    +     resulted in a process being stuck in write forever.  Using soft_timeout
    +     requires that the sender check for an aborted connection rather than
    +     continuing after an EINTR.  Timeouts that used to be initiated before
    +     send_http_header (and never killed) are now initiated only within or
    +     around the routines that actually do the sending, and not allowed to
    +     propagate above the caller.  [Roy Fielding]
    +
    +  *) mod_auth_anon required an @ or a . in the email address, not both.
    +     [Dirk vanGulik]
    +
    +  *) per_dir_defaults weren't set correctly until directory_walk for
    +     name-based vhosts.  This fixes an obscure bug with the wrong config
    +     info being used for vhosts that share the same ip as the server.
    +     [Dean Gaudet]
    +
    +  *) Improved generation of modules/Makefile to be more generic for
    +     new module directories. [Ken Coar, Chuck Murcko, Roy Fielding]
    +
    +  *) Generate makefile dependency for Configuration based on the actual
    +     name given when running the Configure process.  [Dean Gaudet]
    +
    +  *) Fixed problem with vhost error log not being set prior to
    +     initializing virtual hosts. [Dean Gaudet]
    +
    +  *) Fixed infinite loop when a trailing slash is included after a type map
    +     file URL (extra path info). [Petr Lampa]
    +
    +  *) Fixed server status updating of per-connection counters. [Roy Fielding]
    +
    +  *) Add documentation for DNS issues (reliability and security), and try
    +     to explain the virtual host matching process.  [Dean Gaudet]
    +
    +  *) Try to continue gracefully by disabling the vhost if a DNS lookup
    +     fails while parsing the configuration file.  [Dean Gaudet]
    +
    +  *) Improved calls to setsockopt.  [Roy Fielding]
    +
    +  *) Negotiation changes: Don't output empty content-type in variant list;
    +     Output charset in variant list; Return sooner from handle_multi() if
    +     no variants found; Add handling of '*' wildcard in Accept-Charset.
    +     [Petr Lampa and Paul Sutton]
    +
    +  *) Fixed overlaying of request/sub-request notes and headers in
    +     mod_negotiation.  [Dean Gaudet]
    +
    +  *) If two variants' charset quality are equal and one is the default
    +     charset (iso-8859-1), then prefer the variant that was specifically
    +     listed in Accept-Charset instead of the default.  [Petr Lampa]
    +
    +  *) Memory allocation problem in push_array() -- it would corrupt memory
    +     when nalloc==0.  [Kai Risku <krisku@tf.hut.fi> and Roy Fielding]
    +
    +  *) invoke_handler() doesn't handle mime arguments in content-type
    +     [Petr Lampa] PR#160
    +
    +  *) Reduced IdentityCheck timeout to 30 seconds, as per RFC 1413 minimum.
    +     [Ken Coar]
    +
    +  *) Fixed problem with ErrorDocument not working for virtual hosts
    +     due to one of the performance changes in 1.2b7. [Dean Gaudet]
    +
    +  *) Log an error message if we get a request header that is too long,
    +     since it may indicate a buffer overflow attack. [Marc Slemko]
    +
    +  *) Made is_url() allow "[-.+a-zA-Z0-9]+:" as a valid scheme and
    +     not reject URLs without a double-slash, as per RFC2068 section 3.2.
    +     [Ken Coar] PR #146, #187
    +
    +  *) Added table entry placeholder for new header_parser callback
    +     in all of the distributed modules. [Ken Coar] PR #191
    +
    +  *) Allow for cgi files without the .EXE extension on them under OS/2.
    +     [Garey Smiley] PR #59
    +
    +  *) Fixed error message when resource is not found and URL contains
    +     path info. [Petr Lampa and Dean Gaudet] PR #40
    +
    +  *) Fixed user and server confusion over what should be a virtual host
    +     and what is the main server, resulting in access to something
    +     other than the name defined in the virtualhost directive (but
    +     with the same IP address) failing. [Dean Gaudet]
    +
    +  *) Updated mod_rewrite to version 3.0.2, which: fixes compile error on
    +     AIX; improves the redirection stuff to enable the users to generally
    +     redirect to http, https, gopher and ftp; added TIME variable for
    +     RewriteCond which expands to YYYYMMDDHHMMSS strings and added the
    +     special patterns >STRING, <STRING and =STRING to RewriteCond, which
    +     can be used in conjunction with %{TIME} or other variables to create
    +     time-dependent rewriting rules. [Ralf S. Engelschall]
    +
    +  *) bpushfd() no longer notes cleanups for the file descriptors it is handed.
    +     Module authors may need to adjust their code for proper cleanup to take
    +     place (that is, call note_cleanups_for_fd()). This change fixes problems
    +     with file descriptors being erroneously closed when the proxy module was
    +     in use. [Ben Laurie]
    +
    +  *) Fix bug in suexec reintroduced by changes in 1.2b7 which allows
    +     initgroups() to hose the group information needed for later
    +     comparisons. [Randy Terbush]
    +
    +  *) Remove unnecessary call to va_end() in create_argv() which
    +     caused a SEGV on some systems.
    +
    +  *) Use proper MAXHOSTNAMELEN symbol for limiting length of server name.
    +     [Dean Gaudet]
    +
    +  *) Clear memory allocated for listeners. [Randy Terbush]
    +
    +  *) Improved handling of IP address as a virtualhost address and
    +     introduced "_default_" as a synonym for the default vhost config.
    +     [Dean Gaudet] PR #212
    +
    +Changes with Apache 1.2b7
    +
    +  *) Port to  UXP/DS(V20) [Toshiaki Nomura <nom@yk.fujitsu.co.jp>]
    +
    +  *) unset Content-Length if chunked (RFC-2068) [Petr Lampa]
    +
    +  *) mod_negotiation fixes [Petr Lampa] PR#157, PR#158, PR#159
    +     - replace protocol response numbers with symbols
    +     - save variant-list into main request notes
    +     - free allocated memory from subrequests
    +     - merge notes, headers_out and err_headers_out
    +
    +  *) changed status check mask in proxy_http.c from "HTTP/#.# ### *" to
    +     "HTTP/#.# ###*" to be more lenient about what we accept.
    +     [Chuck Murcko]
    +
    +  *) more proxy FTP bug fixes:
    +     - Changed send_dir() to remove user/passwd from displayed URL.
    +     - Changed login error messages to be more descriptive.
    +     - remove setting of SO_DEBUG socket option
    +     - Make ftp_getrc() more lenient about multiline responses,
    +       specifically, 230 responses which don't have continuation 230-
    +       on each line). These seem to be all NT FTP servers, and while
    +       perhaps questionable, they appear to be legal by RFC 959.
    +     - Add missing kill_timeout() after transfer to user completes.
    +     [Chuck Murcko]
    +
    +  *) Fixed problem where a busy server could hang when restarting
    +     after being sent a SIGHUP due to child processes not exiting.
    +     [Marc Slemko]
    +
    +  *) Modify mod_include escaping so a '\' only signifies an escaped
    +     character if the next character is one that needs
    +     escaping.  [Ben Laurie]
    +
    +  *) Eliminated possible infinite loop in mod_imap when relative URLs are
    +     used with a 'base' directive that does not have a '/' in it.
    +     [Marc Slemko, reported by Onno Witvliet <onno@tc.hsa.nl>]
    +
    +  *) Reduced the default timeout from 1200 seconds to 300, and the
    +     one in the sample configfile from 400 to 300.  [Marc Slemko]
    +
    +  *) Stop vbprintf from crashing if given a NULL string pointer;
    +     print (null) instead.  [Ken Coar]
    +
    +  *) Don't disable Nagle algorithm if system doesn't have TCP_NODELAY.
    +     [Marc Slemko and Roy Fielding]
    +
    +  *) Fixed problem with mod_cgi-generated internal redirects trying to
    +     read the request message-body twice. [Archie Cobbs and Roy Fielding]
    +
    +  *) Reduced timeout on lingering close, removed possibility of a blocked
    +     read causing the child to hang, and stopped logging of errors if
    +     the socket is not connected (reset by client).  [Roy Fielding]
    +
    +  *) Rearranged main child loop to remove duplication of code in
    +     select/accept and keep-alive requests, fixed several bugs regarding
    +     checking scoreboard_image for exit indication and failure to
    +     account for all success conditions and trap all error conditions,
    +     prevented multiple flushes before closing the socket; close the entire
    +     socket buffer instead of just one descriptor, prevent logging of
    +     EPROTO and ECONNABORTED on platforms where supported, and generally
    +     improved readability.  [Roy Fielding]
    +
    +  *) Extensive performance improvements. Cleaned up inefficient use of
    +     auto initializers, multiple is_matchexp calls on a static string,
    +     and excessive merging of response_code_strings. [Dean Gaudet]
    +
    +  *) Added double-buffering to mod_include to improve performance on
    +     server-side includes. [Marc Slemko]
    +
    +  *) Several fixes for suexec wrapper. [Randy Terbush]
    +     - Make wrapper work for files on NFS filesystem.
    +     - Fix portability problem of MAXPATHLEN.
    +     - Fix array overrun problem in clean_env().
    +     - Fix allocation of PATH environment variable
    +
    +  *) Removed extraneous blank line is description of mod_status chars.
    +     [Kurt Kohler]
    +
    +  *) Logging of errors from the call_exec routine simply went nowhere,
    +     since the logfile fd has been closed, so now we send them to stderr.
    +     [Harald T. Alvestrand]
    +
    +  *) Fixed core dump when DocumentRoot is a CGI.
    +     [Ben Laurie, reported by geddis@tesserae.com]
    +
    +  *) Fixed potential file descriptor leak in mod_asis; updated it and
    +     http_core to use pfopen/pfclose instead of fopen/fclose.
    +     [Randy Terbush and Roy Fielding]
    +
    +  *) Fixed handling of unsigned ints in ap_snprintf() on some chips such
    +     as the DEC Alpha which is 64-bit but uses 32-bit ints.
    +     [Dean Gaudet and Ken Coar]
    +
    +  *) Return a 302 response code to the client when sending a redirect
    +     due to a missing trailing '/' on a directory instead of a 301; now
    +     it is cacheable. [Markus Gyger]
    +
    +  *) Fix condition where, if a bad directive occurs in .htaccess, and
    +     sub_request() goes first to this directory, then log_reason() will
    +     SIGSEGV because it doesn't have initialized r->per_dir_config.
    +     [PR#162 from Petr Lampa, fix by Marc Slemko and Dean Gaudet]
    +
    +  *) Fix handling of lang_index in is_variant_better().  This was
    +     causing problems which resulted in the server sending the
    +     wrong language document in some cases. [Petr Lampa]
    +
    +  *) Remove free() from clean_env() in suexec wrapper. This was nuking
    +     the clean environment on some systems.
    +
    +  *) Tweak byteserving code (e.g. serving PDF files) to work around
    +     bugs in Netscape Navigator and Microsoft Internet Explorer.
    +     Emit Content-Length header when sending multipart/byteranges.
    +     [Alexei Kosut]
    +
    +  *) Port to HI-UX/WE2. [Nick Maclaren]
    +
    +  *) Port to HP MPE operating system for HP 3000 machines
    +     [Mark Bixby <markb@cccd.edu>]
    +
    +  *) Fixed bug which caused a segmentation fault if only one argument
    +     given to RLimit* directives. [Ed Korthof]
    +
    +  *) Continue persistent connection after 204 or 304 response. [Dean Gaudet]
    +
    +  *) Improved buffered output to the client by delaying the flush decision
    +     until the BUFF code is actually about to read the next request.
    +     This fixes a problem introduced in 1.2b5 with clients that send
    +     an extra CRLF after a POST request. Also improved chunked output
    +     performance by combining writes using writev() and removing as
    +     many bflush() calls as possible.  NOTE: Platforms without writev()
    +     must add -DNO_WRITEV to the compiler CFLAGS, either in Configuration
    +     or Configure, unless we have already done so.  [Dean Gaudet]
    +
    +  *) Fixed mod_rewrite bug which truncated the rewritten URL [Marc Slemko]
    +
    +  *) Fixed mod_info output corruption bug introduced by buffer overflow
    +     fixes. [Dean Gaudet]
    +
    +  *) Fixed http_protocol to correctly output all HTTP/1.1 headers, including
    +     for the special case of a 304 response.  [Paul Sutton]
    +
    +  *) Improved handling of TRACE method by bypassing normal method handling
    +     and header parsing routines; fixed Allow response to always allow TRACE.
    +     [Dean Gaudet]
    +
    +  *) Fixed compiler warnings in the regex library. [Dean Gaudet]
    +
    +  *) Cleaned-up some of the generated HTML. [Ken Coar]
    +
    +Changes with Apache 1.2b6
    +
    +  *) Allow whitespace in imagemap mapfile coordinates. [Marc Slemko]
    +
    +  *) Fix typo introduced in fix for potential infinite loop around
    +     accept() in child_main(). This change caused the rev to 1.2b6.
    +     1.2b5 was never a public beta.
    +
    +Changes with Apache 1.2b5
    +
    +  *) Change KeepAlive semantics (On|Off instead of a number), add
    +     MaxKeepAliveRequests directive. [Alexei Kosut]
    +
    +  *) Various NeXT compilation patches, as well as a change in
    +     regex/regcomp.c since that file also used a NEXT define.
    +     [Andreas Koenig]
    +
    +  *) Allow * to terminate the end of a directory match in mod_dir.
    +     Allows /~* to match for both /~joe and /~joe/. [David Bronder]
    +
    +  *) Don't call can_exec() if suexec_enabled. Calling this requires
    +     scripts executed by the suexec wrapper to be world executable, which
    +     defeats one of the advantages of running the wrapper. [Randy Terbush]
    +
    +  *) Portability Fix: IRIX complained with 'make clean' about *pure* (removed)
    +     [Jim Jagielski]
    +
    +  *) Migration from sprintf() to snprintf() to avoid buffer
    +     overflows. [Marc Slemko]
    +
    +  *) Provide portable snprintf() implementation (ap_snprintf)
    +     as well as *cvt family. [Jim Jagielski]
    +
    +  *) Portability Fix: NeXT lacks unistd.h so we wrap it's inclusion
    +     [Jim Jagielski]
    +
    +  *) Remove mod_fastcgi.c from the distribution. This module appears
    +     to be maintained more through the Open Market channels and should
    +     continue to be easily available at http://www.fastcgi.com/
    +
    +  *) Fixed bug in modules/Makefile that wouldn't allow building in more
    +     than one subdirectory (or cleaning, either). [Jeremy Laidman]
    +
    +  *) mod_info assumed that the config files were relative to ServerRoot.
    +     [Ken the Rodent]
    +
    +  *) CGI scripts called as an error document resulting from failed
    +     CGI execution would hang waiting for POST'ed data. [Rob Hartill]
    +
    +  *) Log reason when mod_dir returns access HTTP_FORBIDDEN
    +     [Ken the Rodent]
    +
    +  *) Properly check errno to prevent display of a directory index
    +     when server receives a long enough URL to confuse stat().
    +     [Marc Slemko]
    +
    +  *) Several security enhancements to suexec wrapper. It is _highly_
    +     recommended that previously installed versions of the wrapper
    +     be replaced with this version.  [Randy Terbush, Jason Dour]
    +
    +        - ~user execution now properly restricted to ~user's home
    +          directory and below.
    +        - execution restricted to UID/GID > 100
    +        - restrict passed environment to known variables
    +        - call setgid() before initgroups() (portability fix)
    +        - remove use of setenv() (portability fix)
    +
    +  *) Add HTTP/1.0 response forcing. [Ben Laurie]
    +
    +  *) Add access control via environment variables. [Ben Laurie]
    +
    +  *) Add rflush() function. [Alexei Kosut]
    +
    +  *) remove duplicate pcalloc() call in new_connection().
    +
    +  *) Fix incorrect comparison which could allow number of children =
    +     MaxClients + 1 if less than HARD_SERVER_LIMIT. Also fix potential
    +     problem if StartServers > HARD_SERVER_LIMIT. [Ed Korthof]
    +
    +  *) Updated support for OSes (MachTen, ULTRIX, Paragon, ISC, OpenBSD
    +     AIX PS/2, CONVEXOS. [Jim Jagielski]
    +
    +  *) Replace instances of inet_ntoa() with inet_addr() for ProxyBlock.
    +     It's more portable. [Martin Kraemer]
    +
    +  *) Replace references to make in Makefile.tmpl with $(MAKE).
    +     [Chuck Murcko]
    +
    +  *) Add ProxyBlock directive w/IP address caching. Add IP address
    +     caching to NoCache directive as well. ProxyBlock works with all
    +     handlers; NoCache now also works with FTP for anonymous logins.
    +     Still more code cleanup. [Chuck Murcko]
    +
    +  *) Add "header parse" API hook [Ben Laurie]
    +
    +  *) Fix byte ordering problems for REMOTE_PORT [Chuck Murcko]
    +
    +  *) suEXEC wrapper was freeing memory that had not been malloc'ed.
    +
    +  *) Correctly allow access and auth directives in <Files> sections in
    +     server config files. [Alexei Kosut]
    +
    +  *) Fix bug with ServerPath that could cause certain files to be not
    +     found by the server. [Alexei Kosut]
    +
    +  *) Fix handling of ErrorDocument so that it doesn't remove a trailing
    +     double-quote from text and so that it properly checks for unsupported
    +     status codes using the new index_of_response interface. [Roy Fielding]
    +
    +  *) Multiple fixes to the lingering_close code in order to avoid being
    +     interrupted by a stray timeout, to avoid lingering on a connection
    +     that has already been aborted or never really existed, to ensure that
    +     we stop lingering as soon as any error condition is received, and to
    +     prevent being stuck indefinitely if the read blocks.  Also improves
    +     reporting of error conditions.  [Marc Slemko and Roy Fielding]
    +
    +  *) Fixed initialization of parameter structure for sigaction.
    +     [mgyger@itr.ch, Adrian Filipi-Martin]
    +
    +  *) Fixed reinitializing the parameters before each call to accept and
    +     select, and removed potential for infinite loop in accept.
    +     [Roy Fielding, after useful PR from adrian@virginia.edu]
    +
    +  *) Fixed condition where, if a child fails to fork, the scoreboard would
    +     continue to say SERVER_STARTING forever. Eventually, the main process
    +     would refuse to start new children because count_idle_servers() will
    +     count those SERVER_STARTING entries and will always report that there
    +     are enough idle servers. [Phillip Vandry]
    +
    +  *) Fixed bug in bcwrite regarding failure to account for partial writes.
    +     Avoided calling bflush() when the client is pipelining requests.
    +     Removed unnecessary flushes from http_protocol. [Dean Gaudet]
    +
    +  *) Added description of "." mode in server-status [Jim Jagielski]
    +
    +
    +Changes with Apache 1.2b4:
    +
    +  *) Fix possible race condition in accept_mutex_init() that
    +     could leave a small security hole open allowing files to be
    +     overwritten in cases where the server UID has write permissions.
    +     [Marc Slemko]
    +
    +  *) Fix awk compatibilty problem in Configure. [Jim Jagielski]
    +
    +  *) Fix portablity problem in util_script where ARG_MAX may not be
    +     defined for some systems.
    +
    +  *) Add changes to allow compilation on Machten 4.0.3 for PowerPC.
    +     [Randal Schwartz]
    +
    +  *) OS/2 changes to support an MMAP style scoreboard file and UNIX
    +     style magic #! token for better script portability. [Garey Smiley]
    +
    +  *) Fix bug in suexec wrapper introduced in b3 that would cause failed
    +     execution for ~userdir CGI. [Jason Dour]
    +
    +  *) Fix initgroups() business in suexec wrapper. [Jason Dour]
    +
    +  *) Fix month off by one in suexec wrapper logging.
    +
    +Changes with Apache 1.2b3:
    +
    +  *) Fix error in mod_cgi which could cause resources not to be properly
    +     freed, or worse. [Dean Gaudet]
    +
    +  *) Fix find_string() NULL pointer dereference. [Howard Fear]
    +
    +  *) Add set_flag_slot() at the request of Dirk and others.
    +     [Dirk vanGulik]
    +
    +  *) Sync mod_rewrite with patch level 10. [Ralf Engelschall]
    +
    +  *) Add changes to improve the error message given for invalid
    +     ServerName parameters. [Dirk vanGulik]
    +
    +  *) Add "Authoritative" directive for Auth modules that don't
    +     currently have it. This gives admin control to assign authoritative
    +     control to an authentication scheme and allow "fall through" for
    +     those authentication modules that aren't "Authoritative" thereby
    +     allowing multiple authentication mechanisms to be chained.
    +     [Dirk vanGulik]
    +
    +  *) Remove requirement for ResourceConfig/AccessConfig if not using
    +     the three config file layout. [Randy Terbush]
    +
    +  *) Add PASV mode to mod_proxy FTP handler. [Chuck Murcko]
    +
    +  *) Changes to suexec wrapper to fix the following problems:
    +     1.  symlinked homedirs will kill ~userdirs.
    +     2.  initgroups() on Linux 2.0.x clobbers gr->grid.
    +     3.  CGI command lines paramters problems
    +     4.  pw-pwdir for "docroot check" still the httpd user's pw record.
    +    [Randy Terbush, Jason Dour]
    +
    +  *) Change create_argv() to accept variable arguments. This fixes
    +     a problem where arguments were not getting passed to the CGI via
    +     argv[] when the suexec wrapper was active. [Randy Terbush, Jake Buchholz]
    +
    +  *) Collapse multiple slashes in path URLs to properly apply
    +     handlers defined by <Location>. [Alexei Kosut]
    +
    +  *) Define a sane set of DEFAULT_USER and DEFAULT_GROUP values for AIX.
    +
    +  *) Improve the accuracy of request duration timings by setting
    +     r->request_time in read_request_line() instead of read_request().
    +     [Dean Gaudet]
    +
    +  *) Reset timeout while reading via get_client_block() in mod_cgi.c
    +     Fixes problem with timed out transfers of large files. [Rasmus Lerdorf]
    +
    +  *) Add the ability to pass different Makefile.tmpl files to Configure
    +     using the -make flag. [Rob Hartill]
    +
    +  *) Fix coredump triggered when sending a SIGHUP to the server caused
    +     by an assertion failure, in turn caused by an uninitialised field in a
    +     listen_rec.
    +     [Ben Laurie]
    +
    +  *) Add FILEPATH_INFO variable to CGI environment, which is equal to
    +     PATH_INFO from previous versions of Apache (in certain situations,
    +     Apache 1.2's PATH_INFO will be different than 1.1's). [Alexei Kosut]
    +     [later removed in 1.2b11]
    +
    +  *) Add rwrite() function to API to allow for sending strings of
    +     arbitrary length. [Doug MacEachern]
    +
    +  *) Remove rlim_t typedef for NetBSD. Do older versions need this?
    +
    +  *) Defined rlim_t and WANTHSREGEX=yes and fixed waitpid() substitute for
    +     NeXT. [Jim Jagielski]
    +
    +  *) Removed recent modification to promote the status code on internal
    +     redirects, since the correct fix was to change the default log format
    +     in mod_log_config so that it outputs the original status. [Rob Hartill]
    +
    +Changes with Apache 1.2b2:
    +
    +  *) Update set_signals() to use sigaction() for setting handlers.
    +     This appears to fix a re-entrant problem in the seg_fault()
    +     bus_error() handlers. [Randy Terbush]
    +
    +  *) Changes to allow mod_status compile for OS/2 [Garey Smiley]
    +
    +  *) changes for DEC AXP running OSF/1 v3.0. [Marc Evans]
    +
    +  *) proxy_http.c bugfixes:  [Chuck Murcko]
    +        1) fixes possible NULL pointer reference w/NoCache
    +        2) fixes NoCache behavior when using ProxyRemote (ProxyRemote
    +           host would cache nothing if it was in the local domain,
    +           and the local domain was in the NoCache list)
    +        3) Adds Host: header when not available
    +        4) Some code cleanup and clarification
    +
    +  *) mod_include.c bugfixes:
    +        1) Fixed an ommission that caused include variables to not
    +           be parsed in config errmsg directives [Howard Fear]
    +        2) Remove HAVE_POSIX_REGEX cruft [Alexei Kosut]
    +        3) Patch to fix compiler warnings [perrot@lal.in2p3.fr]
    +        4) Allow backslash-escaping to all quoted text
    +           [Ben Yoshino <ben@wiliki.eng.hawaii.edu>]
    +        5) Pass variable to command line if not set in XSSI's env
    +           [Howard Fear]
    +
    +  *) Fix infinite loop when processing Content-language lines in
    +     type-map files. [Alexei Kosut]
    +
    +  *) Closed file-globbing hole in test-cgi script. [Brian Behlendorf]
    +
    +  *) Fixed problem in set_[user|group] that prevented CGI execution
    +     for non-virtualhosts when suEXEC was enabled. [Randy Terbush]
    +
    +  *) Added PORTING information file.  [Jim Jagielski]
    +
    +  *) Added definitions for S_IWGRP and S_IWOTH to conf.h [Ben Laurie]
    +
    +  *) Changed default group to "nogroup" instead of "nobody" [Randy Terbush]
    +
    +  *) Fixed define typo of FCNTL_SERIALIZED_ACCEPT where
    +     USE_FCNTL_SERIALIZED_ACCEPT was intended.
    +
    +  *) Fixed additional uses of 0xffffffff where INADDR_NONE was intended,
    +     which caused problems of systems where socket s_addr is >32bits.
    +
    +  *) Added comment to explain (r->chunked = 1) side-effect in
    +     http_protocol.c [Roy Fielding]
    +
    +  *) Replaced use of index() in mod_expires.c with more appropriate
    +     and portable isdigit() test.  [Ben Laurie]
    +
    +  *) Updated Configure for ...
    +        OS/2          (DEF_WANTHSREGEX=yes, other code changes)
    +        *-dg-dgux*    (bad pattern match)
    +        QNX           (DEF_WANTHSREGEX=yes)
    +        *-sunos4*     (DEF_WANTHSREGEX=yes, -DUSEBCOPY)
    +        *-ultrix      (new)
    +        *-unixware211 (new)
    +     and added some user diagnostic info.  [Ben Laurie]
    +
    +  *) In helpers/CutRule, replaced "cut" invocation with "awk" invocation
    +     for better portability. [Jim Jagielski]
    +
    +  *) Updated helpers/GuessOS for ...
    +        SCO 5            (recognize minor releases)
    +        SCO UnixWare     (braindamaged uname, whatever-whatever-unixware2)
    +        SCO UnixWare 2.1.1      (requires a separate set of #defines in conf.h)
    +        IRIX64           (-sgi-irix64)
    +        ULTRIX           (-unknown-ultrix)
    +        SINIX            (-whatever-sysv4)
    +        NCR Unix         (-ncr-sysv4)
    +     and fixed something in helpers/PrintPath  [Ben Laurie]
    +
    +Changes with Apache 1.2b1:
    +
    +  *) Not listed. See <http://www.apache.org/docs/new_features_1_2.html>
    +
    +Changes with Apache 1.1.1:
    +
    +  *) Fixed bug where Cookie module would make two entries in the
    +     logfile for each access [Mark Cox]
    +
    +  *) Fixed bug where Redirect in .htaccess files would cause memory
    +     leak. [Nathan Neulinger]
    +
    +  *) MultiViews now works correctly with AddHandler [Alexei Kosut]
    +
    +  *) Problems with mod_auth_msql fixed [Dirk vanGulik]
    +
    +  *) Fix misspelling of "Anonymous_Authorative" directive in mod_auth_anon.
    +
    +Changes with Apache 1.1.0:
    +
    +  *) Bring NeXT support up to date. [Takaaki Matsumoto]
    +
    +  *) Bring QNX support up to date. [Ben Laurie]
    +
    +  *) Make virtual hosts default to main server keepalive parameters.
    +     [Alexei Kosut, Ben Laurie]
    +
    +  *) Allow ScanHTMLTitles to work with lowercase <title> tags. [Alexei Kosut]
    +
    +  *) Fix missing address family for connect, also remove unreachable statement
    +     in mod_proxy. [Ben Laurie]
    +
    +  *) mod_env now turned on by default in Configuration.tmpl.
    +
    +  *) Bugs which were fixed:
    +        a) yet more mod_proxy bugs [Ben Laurie]
    +        b) CGI works again with inetd [Alexei Kosut]
    +        c) Leading colons were stripped from passwords [osm@interguide.com]
    +        d) Another fix to multi-method Limit problem [jk@tools.de]
    +
    +Changes with Apache 1.1b4:
    +
    +  *) r->bytes_sent variable restored. [Robert Thau]
    +
    +  *) Previously broken multi-method <Limit> parsing fixed. [Robert Thau]
    +
    +  *) More possibly unsecure programs removed from the support directory.
    +
    +  *) More mod_auth_msql authentication improvements.
    +
    +  *) VirtualHosts based on Host: headers no longer conflict with the
    +     Listen directive.
    +
    +  *) OS/2 compatibility enhancements. [Gary Smiley]
    +
    +  *) POST now allowed to directory index CGI scripts.
    +
    +  *) Actions now work with files of the default type.
    +
    +  *) Bugs which were fixed:
    +        a) more mod_proxy bugs
    +        b) early termination of inetd requests
    +        c) compile warnings on several systems
    +        d) problems when scripts stop reading output early
    +
    +Changes with Apache 1.1b3:
    +
    +  *) Much of cgi-bin and all of cgi-src has been removed, due to
    +     various security holes found and that we could no longer support
    +     them.
    +
    +  *) The "Set-Cookie" header is now special-cased to not merge multiple
    +     instances, since certain popular browsers can not handle multiple
    +     Set-Cookie instructions in a single header. [Paul Sutton]
    +
    +  *) rprintf() added to buffer code, occurrences of sprintf removed.
    +     [Ben Laurie]
    +
    +  *) CONNECT method for proxy module, which means tunneling SSL should work.
    +     (No crypto needed)  Also a NoCache config directive.
    +
    +  *) Several API additions: pstrndup(), table_unset() and get_token()
    +     functions now available to modules.
    +
    +  *) mod_imap fixups, in particular Location: headers are now complete
    +     URL's.
    +
    +  *) New "info" module which reports on installed module set through a
    +     special URL, a la mod_status.
    +
    +  *) "ServerPath" directive added - allows for graceful transition
    +     for Host:-header-based virtual hosts.
    +
    +  *) Anonymous authentication module improvements.
    +
    +  *) MSQL authentication module improvements.
    +
    +  *) Status module design improved - output now table-based. [Ben Laurie]
    +
    +  *) htdigest utility included for use with digest authentication
    +     module.
    +
    +  *) mod_negotiation: Accept values with wildcards to be treated with
    +     less priority than those without wildcards at the same quality
    +     value. [Alexei Kosut]
    +
    +  *) Bugs which were fixed:
    +        a) numerous mod_proxy bugs
    +        b) CGI early-termination bug [Ben Laurie]
    +        c) Keepalives not working with virtual hosts
    +        d) RefererIgnore problems
    +        e) closing fd's twice in mod_include (causing core dumps on
    +           Linux and elsewhere).
    +
    +Changes with Apache 1.1b2:
    +
    +  *) Bugfixes:
    +        a) core dumps in mod_digest
    +        b) truncated hostnames/ip address in the logs
    +        c) relative URL's in mod_imap map files
    +
    +Changes with Apache 1.1b1:
    +
    +  *) Not listed. See <http://www.apache.org/docs/new_features_1_1.html>
    +
    +Changes with Apache 1.0.3:
    +
    +  *) Internal redirects which occur in mod_dir.c now preserve the
    +     query portion of a request (the bit after the question mark).
    +     [Adam Sussman]
    +
    +  *) Escape active characters '<', '>' and '&' in html output in
    +     directory listings, error messages and redirection links.
    +     [David Robinson]
    +
    +  *) Apache will now work with LynxOS 2.3 and later [Steven Watt]
    +
    +  *) Fix for POSIX compliance in waiting for processes in alloc.c.
    +     [Nick Williams]
    +
    +  *) setsockopt no longer takes a const declared argument [Martijn Koster]
    +
    +  *) Reset timeout timer after each successful fwrite() to the network.
    +     This patch adds a reset_timeout() procedure that is called by
    +     send_fd() to reset the timeout ever time data is written to the net.
    +     [Nathan Schrenk]
    +
    +  *) timeout() signal handler now checks for SIGPIPE and reports
    +     lost connections in a more user friendly way. [Rob Hartill]
    +
    +  *) Location of the "scoreboard" file which used to live in /tmp is
    +     now configurable (for OSes that can't use mmap) via ScoreBoardFile
    +     which works similar to PidFile (in httpd.conf) [Rob Hartill]
    +
    +  *) Include sys/resource.h in the correct place for SunOS4 [Sameer Parekh]
    +
    +  *) the pstrcat call in mod_cookies.c didn't have an ending NULL,
    +     which caused a SEGV with cookies enabled
    +
    +  *) Output warning when MinSpareServers is set to <= 0 and change it to 1
    +     [Rob Hartill]
    +
    +  *) Log the UNIX textual error returned by some system calls, in
    +     particular errors from accept() [David Robinson]
    +
    +  *) Add strerror function to util.c for SunOS4 [Randy Terbush]
    +
    +Changes with Apache 1.0.2
    +
    +  *) patch to get Apache compiled on UnixWare 2.x, recommended as
    +     a temporary measure, pending rewrite of rfc931.c. [Chuck Murcko]
    +
    +  *) Fix get_basic_auth_pw() to set the auth_type of the request.
    +     [David Robinson]
    +
    +  *) past changes to http_config.c to only use the
    +     setrlimit function on systems defining RLIMIT_NOFILE
    +     broke the feature on SUNOS4. Now defines HAVE_RESOURCE
    +     for SUNOS and prototypes the needed functions.
    +
    +  *) Remove uses of MAX_STRING_LEN/HUGE_STRING_LEN from several routines.
    +     [David Robinson]
    +
    +  *) Fix use of pointer to scratch memory. [Cliff Skolnick]
    +
    +  *) Merge multiple headers from CGI scripts instead of taking last
    +     one. [David Robinson]
    +
    +  *) Add support for SCO 5. [Ben Laurie]
    +
    +Changes with Apache 1.0.1
    +
    +  *) Silence mod_log_referer and mod_log_agent if not configured
    +     [Randy Terbush]
    +
    +  *) Recursive includes can occur if the client supplies PATH_INFO data
    +     and the server provider uses relative links; as file.html
    +     relative to /doc.shtml/pathinfo is /doc.shtml/file.html. [David Robinson]
    +
    +  *) The replacement for initgroups() did not call {set,end}grent(). This
    +     had two implications: if anything else used getgrent(), then
    +     initgroups() would fail, and it was consuming a file descriptor.
    +     [Ben Laurie]
    +
    +  *) On heavily loaded servers it was possible for the scoreboard to get
    +     out of sync with reality, as a result of a race condition.
    +     The observed symptoms are far more Apaches running than should
    +     be, and heavy system loads, generally followed by catastrophic
    +     system failure. [Ben Laurie]
    +
    +  *) Fix typo in license. [David Robinson]
    +
    +Changes with Apache 1.0.0
    +
    +  *) Not listed. See <http://www.apache.org/docs/new_features_1_0.html>
    +
    +Changes with Apache 0.8.16
    +
    +  *) New man page for 'httpd' added to support directory [David Robinson]
    +
    +  *) .htgroup files can have more than one line giving members for a
    +     given group (each must have the group name in front), for NCSA
    +     back-compatibility [Robert Thau]
    +
    +  *) Mutual exclusion around accept() is on by default for SVR4 systems
    +     generally, since they generally can't handle multiple processes in
    +     accept() on the same socket.  This should cure flaky behavior on
    +     a lot of those systems.  [David Robinson]
    +
    +  *) AddType, AddEncoding, and AddLanguage directives take multiple
    +     extensions on a single command line [David Robinson]
    +
    +  *) UserDir can be disabled for a given virtual host by saying
    +     "UserDir disabled" in the <VirtualHost> section --- it was a bug
    +     that this didn't work.  [David Robinson]
    +
    +  *) Compiles on QNX [Ben Laurie]
    +
    +  *) Corrected parsing of ctime time format [David Robinson]
    +
    +  *) httpd does a perror() before exiting if it can't log its pid
    +     to the PidFile, to make diagnosing the error a bit easier.
    +     [David Robinson]
    +
    +  *) <!--#include file="..."--> can no longer include files in the
    +     parent directory, for NCSA back-compatibility.  [David Robinson]
    +
    +  *) '~' is *not* escaped in URIs generated for directory listings
    +     [Roy Fielding]
    +
    +  *) Eliminated compiler warning in the imagemap module [Randy Terbush]
    +
    +  *) Fixed bug involving handling URIs with escaped %-characters
    +     in redirects [David Robinson]
    +
    +Changes with Apache 0.8.15
    +
    +  *) Switched to new, simpler license
    +
    +  *) Eliminated core dumps with improperly formatted DBM group files [Mark Cox]
    +
    +  *) Don't allow requests for ordinary files to have PATH_INFO [Ben Laurie]
    +
    +  *) Reject paths containing %-escaped '%' or null characters [David Robinson]
    +
    +  *) Correctly handles internal redirects to files with names containing '%'
    +     [David Robinson]
    +
    +  *) Repunctuated some error messages [Aram Mirzadeh, Andrew Wilson]
    +
    +  *) Use geteuid() rather than getuid() to see if we have root privilege,
    +     so that server correctly resets privilege if run setuid root.  [Andrew
    +     Wilson]
    +
    +  *) Handle ftp: and telnet: URLs correctly in imagemaps (built-in module)
    +     [Randy Terbush]
    +
    +  *) Fix relative URLs in imagemap files [Randy Terbush]
    +
    +  *) Somewhat better fix for the old "Alias /foo/ /bar/" business
    +     [David Robinson]
    +
    +  *) Don't repeatedly open the ErrorLog if a bunch of <VirtualHost>
    +     entries all name the same one. [David Robinson]
    +
    +  *) Fix directory listings with filenames containing unusual characters
    +     [David Robinson]
    +
    +  *) Better URI-escaping for generated URIs in directories with filenames
    +     containing unusual characters [Ben Laurie]
    +
    +  *) Fixed potential FILE* leak in http_main.c [Ben Laurie]
    +
    +  *) Unblock alarms on error return from spawn_child() [David Robinson]
    +
    +  *) Sample Config files have extra note for SCO users [Ben Laurie]
    +
    +  *) Configuration has note for HP-UX users [Rob Hartill]
    +
    +  *) Eliminated some bogus Linux-only #defines in conf.h [Aram Mirzadeh]
    +
    +  *) Nuked bogus #define in httpd.h [David Robinson]
    +
    +  *) Better test for whether a system has setrlimit() [David Robinson]
    +
    +  *) Calls update_child_status() after reopen_scoreboard() [David Robinson]
    +
    +  *) Doesn't send itself SIGHUP on startup when run in the -X debug-only mode
    +     [Ben Laurie]
    +
    +Changes with Apache 0.8.14
    +
    +  *) Compiles on SCO ODT 3.0 [Ben Laurie]
    +
    +  *) AddDescription works (better) [Ben Laurie]
    +
    +  *) Leaves an intelligible error diagnostic when it can't set group
    +     privileges on standalone startup [Andrew Wilson]
    +
    +  *) Compiles on NeXT again --- the 0.8.13 RLIMIT patch was failing on
    +     that machine, which claims to be BSD but does not support RLIMIT.
    +     [Randy Terbush]
    +
    +  *) gcc -Wall no longer complains about an unused variable when util.c
    +     is compiled with -DMINIMAL_DNS [Andrew Wilson]
    +
    +  *) Nuked another compiler warning for -Wall on Linux [Aram Mirzadeh]
    +
    +Changes with Apache 0.8.13
    +
    +  *) Make IndexIgnore *work* (ooops) [Jarkko Torppa]
    +
    +  *) Have built-in imagemap code recognize & honor Point directive [James
    +     Cloos]
    +
    +  *) Generate cleaner directory listings in directories with a mix of
    +     long and short filenames [Rob Hartill]
    +
    +  *) Properly initialize dynamically loaded modules [Royston Shufflebotham]
    +
    +  *) Properly default ServerName for virtual servers [Robert Thau]
    +
    +  *) Rationalize handling of BSD in conf.h and elsewhere [Randy Terbush,
    +     Paul Richards and a cast of thousands...]
    +
    +  *) On self-identified BSD systems (we don't try to guess any more),
    +     allocate a few extra file descriptors per virtual host with setrlimit,
    +     if we can, to avoid running out. [Randy Terbush]
    +
    +  *) Write 22-character lock file name into buffer with enough space
    +     on startup [Konstantin Olchanski]
    +
    +  *) Use archaic setpgrp() interface on NeXT, which requires it [Brian
    +     Pinkerton]
    +
    +  *) Suppress -Wall warning by casting const away in util.c [Aram Mirzadeh]
    +
    +  *) Suppress -Wall warning by initializing variable in negotiation code
    +     [Tobias Weingartner]
    +
    +Changes with Apache 0.8.12
    +
    +  *) Doesn't pause three seconds after including a CGI script which is
    +     too slow to die off (this is done by not even trying to kill off
    +     subprocesses, including the SIGTERM/pause/SIGKILL routine, until
    +     after the entire document has been processed).  [Robert Thau]
    +
    +  *) Doesn't do SSI if Options Includes is off.  (Ooops).  [David Robinson]
    +
    +  *) Options IncludesNoExec allows inclusion of at least text/* [Roy Fielding]
    +
    +  *) Allows .htaccess files to override <Directory> sections naming the
    +     same directory [David Robinson]
    +
    +  *) Removed an efficiency hack in sub_req_lookup_uri which was
    +     causing certain extremely marginal cases (e.g., ScriptAlias of a
    +     *particular* index.html file) to fail.  [David Robinson]
    +
    +  *) Doesn't log an error when the requested URI requires
    +     authentication, but no auth header line was supplied by the
    +     client; this is a normal condition (the client doesn't no auth is
    +     needed here yet).  [Robert Thau]
    +
    +  *) Behaves more sanely when the name server loses its mind [Sean Welch]
    +
    +  *) RFC931 code compiles cleanly on old BSDI releases [Randy Terbush]
    +
    +  *) RFC931 code no longer passes out name of prior clients on current
    +     requests if the current request came from a server that doesn't
    +     do RFC931.  [David Robinson]
    +
    +  *) Configuration script accepts "Module" lines with trailing whitespace.
    +     [Robert Thau]
    +
    +  *) Cleaned up compiler warning from mod_access.c [Robert Thau]
    +
    +  *) Cleaned up comments in mod_cgi.c [Robert Thau]
    +
    +Changes with Apache 0.8.11
    +
    +  *) Wildcard <Directory> specifications work.  [Robert Thau]
    +
    +  *) Doesn't loop for buggy CGI on Solaris [Cliff Skolnick]
    +
    +  *) Symlink checks (FollowSymLinks off, or SymLinkIfOwnerMatch) always check
    +     the file being requested itself, in addition to the directories leading
    +     up to it. [Robert Thau]
    +
    +  *) Logs access failures due to symlink checks or invalid client address
    +     in the error log [Roy Fielding, Robert Thau]
    +
    +  *) Symlink checks deal correctly with systems where lstat of
    +     "/path/to/some/link/" follows the link.  [Thau, Fielding]
    +
    +  *) Doesn't reset DirectoryIndex to 'index.html' when
    +     other directory options are set in a .htaccess file.  [Robert Thau]
    +
    +  *) Clarified init code and nuked bogus warning in mod_access.c
    +     [Florent Guillaume]
    +
    +  *) Corrected several directives in sample srm.conf
    +     --- includes corrections to directory indexing icon-related directives
    +     (using unknown.gif rather than unknown.xbm as the DefaultIcon, doing
    +     icons for encodings right, and turning on AddEncoding by default).
    +     [Roy Fielding]
    +
    +  *) Corrected descriptions of args to AddIcon and AddAlt in command table
    +     [James Cloos]
    +
    +  *) INSTALL & README mention "contributed modules" directory [Brian
    +     Behlendorf]
    +
    +  *) Fixed English in the license language...  "for for" --> "for".
    +     [Roy Fielding]
    +
    +  *) Fixed ScriptAlias/Alias interaction by moving ScriptAlias handling to
    +     mod_alias.c, merging it almost completely with handling of Alias, and
    +     adding a 'notes' field to the request_rec which allows the CGI module
    +     to discover whether the Alias module has put this request through
    +     ScriptAlias (which it needs to know for back-compatibility, as the old
    +     NCSA code did not check Options ExecCGI in ScriptAlias directories).
    +     [Robert Thau]
    +
    +
    +Changes with Apache 0.8.10
    +
    +  *) AllowOverride applies to the named directory, and not just
    +     subdirectories.  [David Robinson]
    +
    +  *) Do locking for accept() exclusion (on systems that need it)
    +     using a special file created for the purpose in /usr/tmp, and
    +     not the error log; using the error log causes real problems
    +     if it's NFS-mounted; this is known to be the cause of a whole
    +     lot of "server hang" problems with Solaris.  [David Robinson;
    +     thanks to Merten Schumann for help diagnosing the problem].
    +
    +Changes with Apache 0.8.9
    +
    +  *) Compiles with -DMAXIMUM_DNS ---- ooops! [Henrik Mortensen]
    +
    +  *) Nested includes see environment variables of the including document,
    +     for NCSA bug-compatibility (some sites have standard footer includes
    +     which try to print out the last-modified date).  [Eric Hagberg/Robert
    +     Thau]
    +
    +  *) <!--exec cgi="/some/uri/here"--> always treats the item named by the
    +     URI as a CGI script, even if it would have been treated as something
    +     else if requested directly, for NCSA back-compatibility.  (Note that
    +     this means that people who know the name of the script can see the
    +     code just by asking for it).  [Robert Thau]
    +
    +  *) New version of dbmmanage script included in support directory as
    +     dbmmanage.new.
    +
    +  *) Check if scoreboard file couldn't be opened, and say so, rather
    +     then going insane [David Robinson]
    +
    +  *) POST to CGI works on A/UX [Jim Jagielski]
    +
    +  *) AddIcon and AddAlt commands work properly [Rob Hartill]
    +
    +  *) NCSA server push works properly --- the Arena bug compatibility
    +     workaround, which broke it, is gone (use -DARENA_BUG_WORKAROUND
    +     if you still want the workaround).  [Rob Hartill]
    +
    +  *) If client didn't submit any Accept-encodings, ignore encodings in
    +     content negotiation.  (NB this will all have to be reworked anyway
    +     for the new HTTP draft).  [Florent Guillaume]
    +
    +  *) Don't dump core when trying to log timed-out requests [Jim Jagielski]
    +
    +  *) Really honor CacheNegotiatedDocs [Florent Guillaume]
    +
    +  *) Give Redirect priority over Alias, for NCSA bug compatibility
    +     [David Robinson]
    +
    +  *) Correctly set PATH_TRANSLATED in all cases from <!--#exec cmd=""-->,
    +     paralleling earlier bug fix for CGI [David Robinson]
    +
    +  *) If DBM auth is improperly configured, report a server error and don't
    +     dump core.
    +
    +  *) Deleted FCNTL_SERIALIZED_ACCEPTS from conf.h entry for A/UX;
    +     it seems to work well enough without it (even in a 10 hits/sec
    +     workout), and the overhead for the locking under A/UX is
    +     alarmingly high (though it is very low on other systems).
    +     [Eric Hagberg]
    +
    +  *) Fixed portability problems with mod_cookies.c [Cliff Skolnick]
    +
    +  *) Further de-Berklize mod_cookies.c; change the bogus #include.  [Brian
    +     Behlendorf/Eric Hagberg]
    +
    +  *) More improvements to default Configuration for A/UX [Jim Jagielski]
    +
    +  *) Compiles clean on NEXT [Rob Hartill]
    +
    +  *) Compiles clean on SGI [Robert Thau]
    +
    +Changes with Apache 0.8.8
    +
    +  *) SunOS library prototypes now never included unless explicitly
    +     requested in the configuration (via -DSUNOS_LIB_PROTOTYPES);
    +     people using GNU libc on SunOS are screwed by prototypes for the
    +     standard library.
    +
    +     (Those who wish to compile clean with gcc -Wall on a standard
    +     SunOS setup need the prototypes, and may obtain them using
    +     -DSUNOS_LIB_PROTOTYPES.  Those wishing to use -Wall on a system
    +     with nonstandard libraries are presumably competent to make their
    +     own arrangements).
    +
    +  *) Strips trailing '/' characters off both args to the Alias command,
    +     to make 'Alias /foo/ /bar/' work.
    +
    +Changes with Apache 0.8.7
    +
    +  *) Don't hang when restarting with a child from 'TransferLog "|..."' running
    +     [reported by David Robinson]
    +
    +  *) Compiles clean on OSF/1 [David Robinson]
    +
    +  *) Added some of the more recent significant changes (AddLanguage stuff,
    +     experimental LogFormat support) to CHANGES file in distribution root
    +     directory
    +
    +Changes with Apache 0.8.6
    +
    +  *) Deleted Netscape reload workaround --- it's in violation of HTTP specs.
    +     (If you actually wanted a conditional GET which bypassed the cache, you
    +     couldn't get it). [Reported by Roy Fielding]
    +
    +  *) Properly terminate headers on '304 Not Modified' replies to conditional
    +     GETs --- no browser we can find cares much, but the CERN proxy chokes.
    +     [Reported by Cliff Skolnick; fix discovered independently by Rob Hartill]
    +
    +  *) httpd -v doesn't call itself "Shambhala".  [Reported by Chuck Murcko]
    +
    +  *) SunOS lib-function prototypes in conf.h conditionalized on __GNUC__,
    +     not __SUNPRO_C (they're needed to quiet gcc -Wall, but acc chokes on 'em,
    +     and older versions don't set the __SUNPRO_C preprocessor variable).  On
    +     all other systems, these are never used anyway.  [Reported by Mark Cox].
    +
    +  *) Scoreboard file (/tmp/htstatus.*) no longer publically writable.
    +
    +Changes with Apache 0.8.5
    +
    +  *) Added last-minute configurable log experiment, as optional module
    +
    +  *) Correctly set r->bytes_sent for HTTP/0.9 requests, so they get logged
    +     properly.  (One-line fix to http_protocol.c).
    +
    +  *) Work around bogus behavior when reloading from Netscape.
    +     It's Netscape's bug --- for some reason they expect a request with
    +     If-modified-since: to not function as a conditional GET if it also
    +     comes with Pragma: no-cache, which is way out of line with the HTTP
    +     spec (according to Roy Fielding, the redactor).
    +
    +  *) Added parameter to set maximum number of server processes.
    +
    +  *) Added patches to make it work on A/UX.  A/UX is *weird*.  [Eric Hagberg]
    +
    +  *) IdentityCheck bugfix [Chuck Murcko].
    +
    +  *) Corrected cgi-src/Makefile entry for new imagemap script.  [Alexei Kosut]
    +
    +  *) More sample config file corrections; add extension to AddType for
    +     *.asis, move AddType generic description to its proper place, and
    +     fix miscellaneous typos. [ Alexei Kosut ]
    +
    +  *) Deleted the *other* reference to the regents from the Berkeley
    +     legal disclaimer (everyplace).
    +
    +  *) Nuked Shambhala name from src/README; had already cleaned it out
    +     of everywhere else.
    +
    +Changes with Apache 0.8.4
    +
    +  *) Changes to server-pool management parms --- renamed current
    +     StartServers to MinSpareServers, created separate StartServers
    +     parameter which means what it says, and renamed MaxServers to
    +     MaxSpareServers (though the old name still works, for NCSA 1.4
    +     back-compatibility).  The old names were generally regarded as
    +     too confusing.  Also altered "docs" in sample config files.
    +
    +  *) More improvements to default config files ---
    +     sample directives (commented out) for XBitHack, BindAddress,
    +     CacheNegotiatedDocs, VirtualHost; decent set of AddLanguage
    +     defaults, AddTypes for send-as-is and imagemap magic types, and
    +     improvements to samples for DirectoryIndex [Alexei Kosut]
    +
    +  *) Yet more improvements to default config files --- changes to
    +     Alexei's sample AddLanguage directives, and sample LanguagePriority
    +     [ Florent Guillaume ]
    +
    +  *) Set config file locations properly if not set in httpd.conf
    +     [ David Robinson ]
    +
    +  *) Don't escape URIs in internal redirects multiple times; don't
    +     do that when translating PATH_INFO to PATH_TRANSLATED either.
    +     [ David Robinson ]
    +
    +  *) Corrected spelling of "Required" in 401 error reports [Andrew Wilson]
    +
    +Changes with Apache 0.8.3
    +
    +  *) Edited distribution README to *briefly* summarize installation
    +     procedures, and give a pointer to the INSTALL file in the src/
    +     directory.
    +
    +  *) Upgraded imagemap script in cgi-bin to 1.8 version from more
    +     recent NCSA distributions.
    +
    +  *) Bug fix to previous bug fix --- if .htaccess file and <Directory>
    +     exist for the same directory, use both and don't segfault.  [Reported
    +     by David Robinson]
    +
    +  *) Proper makefile dependencies [David Robinson]
    +
    +  *) Note (re)starts in error log --- reported by Rob Hartill.
    +
    +  *) Only call no2slash() after get_path_info() has been done, to
    +     preserve multiple slashes in the PATH_INFO [NCSA compatibility,
    +     reported by Andrew Wilson, though this one is probably a real bug]
    +
    +  *) Fixed mod_imap.c --- relative paths with base_uri referer don't
    +     dump core when Referer is not supplied. [Randy Terbush]
    +
    +  *) Lightly edited sample config files to refer people to our documentation
    +     instead of NCSA's, and to list Rob McCool as *original* author (also
    +     deleted his old, and no doubt non-functional email address).  Would be
    +     nice to have examples of new features...
    +
    +Changes with Apache 0.8.2
    +
    +  *) Added AddLanuage code [Florent Guillaume]
    +
    +  *) Don't say "access forbidden" when a CGI script is not found.  [Mark Cox]
    +
    +  *) All sorts of problems when MultiViews finds a directory.  It would
    +     be nice if mod_dir.c was robust enough to handle that, but for now,
    +     just punt.  [reported by Brian Behlendorf]
    +
    +  *) Wait for all children on restart, to make sure that the old socket
    +     is gone and we can reopen it.  [reported by Randy Terbush]
    +
    +  *) Imagemap module is enabled in default Configuration
    +
    +  *) RefererLog and UserAgentLog modules properly default the logfile
    +     [Randy Terbush]
    +
    +  *) Mark Cox's mod_cookies added to the distribution as an optional
    +     module (commented out in the default Configuration, and noted as
    +     an experiment, along with mod_dld). [Mark Cox]
    +
    +  *) Compiles on ULTRIX (a continuing battle...). [Robert Thau]
    +
    +  *) Fixed nasty bug in SIGTERM handling [reported by Randy Terbush]
    +
    +  *) Changed "Shambhala" to "Apache" in API docs. [Robert Thau]
    +
    +  *) Added new, toothier legal disclaimer. [Robert Thau; copied from BSD
    +     license]
    +
    +Changes with Apache 0.8.1
    +
    +  *) New imagemap module [Randy Terbush]
    +
    +  *) Replacement referer log module with NCSA-compatible RefererIgnore
    +     [Matthew Gray again]
    +
    +  *) Don't mung directory listings with very long filenames.
    +     [Florent Guillaume]
    +
    +Changes with Apache 0.8.0 (nee Shambhala 0.6.2):
    +
    +  *) New config script.  See INSTALL for info.  [Robert Thau]
    +
    +  *) Scoreboard mechanism for regulating the number of extant server
    +     processes.  MaxServers and StartServers defaults are the same as
    +     for NCSA, but the meanings are slightly different.  (Actually,
    +     I should probably lower the MaxServers default to 10).
    +
    +     Before asking for a new connection, each server process checks
    +     the number of other servers which are also waiting for a
    +     connection.  If there are more than MaxServers, it quietly dies
    +     off.  Conversely, every second, the root, or caretaker, process
    +     looks to see how many servers are waiting for a new connection;
    +     if there are fewer than StartServers, it starts a new one.  This
    +     does not depend on the number of server processes already extant.
    +     The accounting is arranged through a "scoreboard" file, named
    +     /tmp/htstatus.*, on which each process has an independent file
    +     descriptor (they need to seek without interference).
    +
    +     The end effect is that MaxServers is the maximum number of
    +     servers on an *inactive* server machine, but more will be forked
    +     off to handle unusually heavy loads (or unusually slow clients);
    +     these will die off when they are no longer needed --- without
    +     reverting to the overhead of full forking operation.  There is a
    +     hard maximum of 150 server processes compiled in, largely to
    +     avoid forking out of control and dragging the machine down.
    +     (This is arguably too high).
    +
    +     In my server endurance tests, this mechanism did not appear to
    +     impose any significant overhead, even after I forced it to put the
    +     scoreboard file on a normal filesystem (which might have more
    +     overhead than tmpfs).  [Robert Thau]
    +
    +  *) Set HTTP_FOO variables for SSI <!--#exec cmd-->s, not just CGI scripts.
    +     [Cliff Skolnick]
    +
    +  *) Read .htaccess files even in directory with <Directory> section.
    +     (Former incompatibility noted on mailing list, now fixed). [Robert
    +     Thau]
    +
    +  *) "HEAD /" gives the client a "Bad Request" error message, rather
    +     than trying to send no body *and* no headers.  [Cliff Skolnick].
    +
    +  *) Don't produce double error reports for some very obscure cases
    +     mainly involving auth configuration (the "all modules decline to
    +     handle" case which is a sure sign of a server bug in most cases,
    +     but also happens when authentication is badly misconfigured).
    +     [Robert Thau]
    +
    +  *) Moved FCNTL_SERIALIZED_ACCEPT defines into conf.h (that's what
    +     it's *for*, and this sort of thing really shouldn't be cluttering
    +     up the Makefile). [Robert Thau]
    +
    +  *) Incidental code cleanups in http_main.c --- stop dragging
    +     sa_client around; just declare it where used.  [Robert Thau]
    +
    +  *) Another acc-related fix.  (It doesn't like const char
    +     in some places...). [Mark Cox]
    +
    +Changes with 0.6.1
    +
    +  *) Fixed auth_name-related typos in http_core.c [Brian Behlendorf]
    +     Also, fixed auth typo in http_protocol.c unmasked by this fix.
    +
    +  *) Compiles clean with acc on SunOS [Paul Sutton]
    +
    +  *) Reordered modules in modules.c so that Redirect takes priority
    +     over ScriptAlias, for NCSA bug-compatibility [Rob Hartill] ---
    +     believe it or not, he has an actual site with a ScriptAlias and
    +     a Redirect declared for the *exact same directory*.  Even *my*
    +     compatibility fetish wouldn't motivate me to fix this if the fix
    +     required any effort, but it doesn't, so what the hey.
    +
    +  *) Fixed to properly default several server_rec fields for virtual
    +     servers from the corresponding fields in the main server_rec.
    +     [Cliff Skolnick --- 'port' was a particular irritant].
    +
    +  *) No longer kills off nph- child processes before they are
    +     finished sending output. [Matthew Gray]
    +
    +Changes with 0.6.0
    +
    +  *) Two styles of timeout --- hard and soft.  soft_timeout()s just put
    +     the connection to the client in an "aborted" state, but otherwise
    +     allow whatever handlers are running to clean up.  hard_timeout()s
    +     abort the request in progress completely; anything not tied to some
    +     resource pool cleanup will leak.  They're still around because I
    +     haven't yet come up with a more elegant way of handling
    +     timeouts when talking to something that isn't the client.  The
    +     default_handler and the dir_handler now use soft timeouts, largely
    +     so I can test the feature.  [Robert Thau]
    +
    +  *) TransferLog "| my_postprocessor ..." seems to be there.  Note that
    +     the case of log handlers dying prematurely is probably handled VERY
    +     gracelessly at this point, and if the logger stops reading input,
    +     the server will hang.  (It is known to correctly restart the
    +     logging process on server restart; this is (should be!) going through
    +     the same SIGTERM/pause/SIGKILL routine used to ding an errant CGI
    +     script).  [Robert Thau]
    +
    +  *) asis files supported (new module).  [Robert Thau]
    +
    +  *) IdentityCheck code is compiled in, but has not been tested.  (I
    +     don't know anyone who runs identd). [Robert Thau]
    +
    +  *) PATH_INFO and PATH_TRANSLATED are not set unless some real PATH_INFO
    +     came in with the request, for NCSA bug-compatibility. [Robert Thau]
    +
    +  *) Don't leak the DIR * on HEAD request for a directory. [Robert Thau]
    +
    +  *) Deleted the block_alarms() stuff from dbm_auth; no longer necessary,
    +     as timeouts are not in scope. [Robert Thau]
    +
    +  *) quoted-string args in config files now handled correctly (doesn't drop
    +     the last character). [Robert Thau; reported by Randy Terbush]
    +
    +  *) Fixed silly typo in http_main.c which was suddenly fatal in HP-UX.
    +     How the hell did it ever work? [Robert Thau; reported by Rob Hartill]
    +
    +  *) mod_core.c --- default_type returns DEFAULT_TYPE (the compile-time
    +     default default type); the former default default behavior when all
    +     type-checkers defaulted had been a core dump.  [Paul Sutton]
    +
    +  *) Copy filenames out of the struct dirent when indexing
    +     directories.  (On Linux, readdir() returns a pointer to the same
    +     memory area every time).  Fix is in mod_dir.c.  [Paul Sutton]
    +
    +Changes with 0.5.3 [not released]
    +
    +  *) Default response handler notes "file not found" in the error log,
    +     if the file was not found.  [Cliff Skolnick].
    +
    +  *) Another Cliff bug --- "GET /~user" now properly redirects (the userdir
    +     code no longer sets up bogus PATH_INFO which fakes out the directory
    +     handler). [Cliff Skolnick]
    +
    +Changes with 0.5.2
    +
    +  *) Changes to http_main.c --- root server no longer plays silly
    +     games with SIGCHLD, and so now detects and replaces dying
    +     children.  Child processes just die on SIGTERM, without taking
    +     the whole process group with them.  Potential problem --- if any
    +     child process refuses to die, we hang in restart.
    +     MaxRequestsPerChild may still not work, but it certainly works
    +     better than it did before this!  [Robert Thau]
    +
    +  *) mod_dir.c bug fixes: ReadmeName and HeaderName
    +     work (or work better, at least); over-long description lines
    +     properly terminated. [Mark Cox]
    +
    +  *) http_request.c now calls unescape_url() more places where it
    +     should [Paul Sutton].
    +
    +  *) More directory handling bugs (reported by Cox)
    +     Parent Directory link is now set correctly. [Robert Thau]
    +
    +Changes with 0.5.1: [Hopefully complete]                  10 Apr 1995
    +
    +  *) Generalized cleanup interface in alloc.c --- any function can be
    +     registered with alloc.c as a cleanup for a resource pool;
    +     tracking of files and file descriptors has been reimplemented in
    +     terms of this interface, so I can give it some sort of a test.
    +     [Robert Thau]
    +
    +  *) More changes in alloc.c --- new cleanup_for_exec() function,
    +     which tracks down and closes all file descriptors which have been
    +     registered with the alloc.c machinery before the server exec()s a
    +     child process for CGI or <!--#exec-->.  CGI children now get
    +     started with exactly three file descriptors open.  Hopefully,
    +     this cures the problem Rob H. was having with overly persistent
    +     CGI connections. [Robert Thau]
    +
    +  *) Mutual exclusion around the accept() in child_main() --- this is
    +     required on at least SGI, Solaris and Linux, and is #ifdef'ed in
    +     by default on those systems only (-DFCNTL_SERIALIZED_ACCEPT).
    +     This uses fcntl(F_SETLK,...) on the error log descriptor because
    +     flock() on that descriptor won't work on systems which have BSD
    +     flock() semantics, including (I think) Linux 1.3 and Solaris.
    +
    +     This does work on SunOS (when the server is idle, only one
    +     process in the pool is waiting on accept()); it *ought* to work
    +     on the other systems. [Robert Thau]
    +
    +  *) FreeBSD and BSDI portability tweaks [Chuck Murcko]
    +
    +  *) sizeof(*sa_client) bugfix from [Rob Hartill]
    +
    +  *) pstrdup(..., NULL) returns NULL, [Randy Terbush]
    +
    +  *) block_alarms() to avoid leaking the DBM* in dbm auth (this should
    +     be unnecessary if I go to the revised timeout-handling scheme).
    +     [Robert Thau]
    +
    +  *) For NCSA bug-compatibility, set QUERY_STRING env var (to a null
    +     string) even if none came in with the request.  [Robert Thau]
    +
    +  *) CHANGES file added to distribution ;-).
    +
    +Changes with 0.4                                          02 Apr 1995
    +
    +  *) Patches by Brian Behlendorf, Andrew Wilson, Robert Thau,
    +     and Rob Hartill.
    +
    +Changes with 0.3                                          24 Mar 1995
    +
    +  *) Patches by Robert Thau, David Robinson, Rob Hartill, and
    +     Carlos Varela
    +
    +Changes with 0.2                                          18 Mar 1995
    +
    +  *) Based on NCSA httpd 1.3 by Rob McCool and patches by CERT,
    +     Roy Fielding, Robert Thau, Nicolas Pioch, David Robinson,
    +     Brian Behlendorf, Rob Hartill, and Cliff Skolnick
    diff --git a/APACHE_1_3b7/src/Configuration.tmpl b/APACHE_1_3b7/src/Configuration.tmpl
    new file mode 100644
    index 0000000000..e5d2a766aa
    --- /dev/null
    +++ b/APACHE_1_3b7/src/Configuration.tmpl
    @@ -0,0 +1,376 @@
    +# Config file for the Apache httpd.
    +
    +# Configuration.tmpl is the template for Configuration. Configuration should
    +# be edited to select the modules to be included as well as various flags
    +# for Makefile.
    +
    +# The template should only be changed when a new system or module is added,
    +# or an existing one modified. This will also most likely require some minor
    +# changes to Configure to recognize those changes.
    +
    +# There are 5 types of lines here:
    +
    +# '#' comments, distinguished by having a '#' as the first non-blank character
    +#
    +# Makefile options, such as CC=gcc, etc...
    +#
    +# Rules, distinguished by having "Rule" at the front. These are used to
    +# control Configure's behavior as far as how to create Makefile.
    +#
    +# Module selection lines, distinguished by having 'AddModule' at the front.
    +# These list the configured modules, in priority order (highest priority
    +# last).  They're down at the bottom.
    +#
    +# Optional module selection lines, distinguished by having `%Module'
    +# at the front.  These specify a module that is to be compiled in (but
    +# not enabled).  The AddModule directive can be used to enable such a
    +# module.  By default no such modules are defined.
    +
    +
    +################################################################
    +# Makefile configuration
    +#
    +# These are added to the general flags determined by Configure.
    +# Edit these to work around Configure if needed. The EXTRA_* family
    +# will be added to the regular Makefile flags. For example, if you
    +# want to compile with -Wall, then add that to EXTRA_CFLAGS. These
    +# will be added to whatever flags Configure determines as appropriate
    +# and needed for your platform.
    +#
    +# You can also set the compiler (CC) and optimization (OPTIM) used here as
    +# well.  Settings here have priority; If not set, Configure will attempt to
    +# guess the C compiler, looking for gcc first, then cc.
    +#
    +# Optimization note: 
    +# Be careful when adding optimization flags (like -O3 or -O6) on the OPTIM
    +# entry, especially when using some GCC variants. Experience showed that using
    +# these for compiling Apache is risky. If you don't want to see Apache dumping
    +# core regularly then at most use -O or -O2.
    +#
    +EXTRA_CFLAGS=
    +EXTRA_LDFLAGS=
    +EXTRA_LIBS=
    +EXTRA_INCLUDES=
    +
    +#CC=
    +#OPTIM=
    +#RANLIB=
    +
    +################################################################
    +# Dynamic Shared Object (DSO) support
    +#
    +# There is experimental support for compiling the Apache core and
    +# the Apache modules into dynamic shared object (DSO) files for
    +# maximum runtime flexibility.
    +#
    +# The Configure script currently has only limited built-in
    +# knowledge on how to compile these DSO files because this is
    +# heavily platform-dependent. The current state of supported and
    +# explicitly unsupported platforms can be found in the file 
    +# "htdocs/manual/sharedobjects.html", under 
    +# "Supported Platforms".
    +#
    +# For other platforms where you want to use the DSO mechanism you
    +# first have to make sure it supports the pragmatic dlopen()
    +# system call and then you have to provide the appropriate
    +# compiler and linker flags below to create the DSO files on your
    +# particular platform.
    +#
    +# The placement of the Apache core into a DSO file is triggered
    +# by the SHARED_CORE rule below while support for building
    +# individual Apache Modules as DSO files and loading them under
    +# runtime without recompilation is triggered by `SharedModule'
    +# commands. To be able to use the latter one first enable the
    +# module mod_so (see corresponding `AddModule' command below).
    +# Then enable the DSO feature for particular modules individually
    +# by replacing their `AddModule' command with `SharedModule' and
    +# change the filename extension from `.o' to `.so'. 
    +
    +#CFLAGS_SHLIB=
    +#LD_SHLIB=
    +#LDFLAGS_SHLIB=
    +#LDFLAGS_SHLIB_EXPORT=
    +
    +Rule SHARED_CORE=default
    +
    +################################################################
    +# Rules configuration
    +#
    +# These are used to let Configure know that we want certain
    +# functions. The format is: Rule RULE=value
    +#
    +# At present, only the following RULES are known: WANTHSREGEX, SOCKS4,
    +# SOCKS5, STATUS, IRIXNIS, IRIXN32 and PARANOID.
    +#
    +# For all Rules, if set to "yes", then Configure knows we want that
    +# capability and does what is required to add it in. If set to "default"
    +# then Configure makes a "best guess"; if set to anything else, or not
    +# present, then nothing is done.
    +#
    +# SOCKS4:
    +#  If SOCKS4 is set to 'yes', be sure that you add the socks library
    +#  location to EXTRA_LIBS, otherwise Configure will assume
    +#  "-L/usr/local/lib -lsocks"
    +#
    +# SOCKS5:
    +#  If SOCKS5 is set to 'yes', be sure that you add the socks5 library
    +#  location to EXTRA_LIBS, otherwise Configure will assume
    +#  "-L/usr/local/lib -lsocks5"
    +#
    +# STATUS:
    +#  If Configure determines that you are using the status_module,
    +#  it will automatically enable full status information if set
    +#  to 'yes'. If the status module is not included, having STATUS
    +#  set to 'yes' has no impact.
    +#
    +# IRIXNIS:
    +#  Only takes effect if Configure determines that you are running
    +#  SGI IRIX.  If you are using a (ancient) 4.x version of IRIX, you
    +#  need this if you are using NIS and Apache needs access to it for
    +#  things like mod_userdir.  This is not required on 5.x and later
    +#  and you should not enable it on such systems.
    +#
    +# IRIXN32:
    +#  If you are running a version of IRIX and Configure detects
    +#  n32 libraries, it will use those instead of the o32 ones.
    +#
    +# PARANOID:
    +#  New with version 1.3, during Configure modules can run
    +#  pre-programmed shell commands in the same environment that
    +#  Configure runs in. This allows modules to control how Configure
    +#  works. Normally, Configure will simply note that a module
    +#  is performing this function. If PARANOID is set to yes, it will
    +#  actually print-out the code that the modules execute
    +#
    +
    +Rule STATUS=yes
    +Rule SOCKS4=no
    +Rule SOCKS5=no
    +Rule IRIXNIS=no
    +Rule IRIXN32=yes
    +Rule PARANOID=no
    +
    +# The following rules should be set automatically by Configure. However, if
    +# they are not set by Configure (because we don't know the correct value for
    +# your platform), or are set incorrectly, you may override them here.
    +# If you have to do this, please let us know what you set and what your
    +# platform is, by filling out a problem report form at the Apache web site:
    +# <http://bugs.apache.org/>.  If your browser is forms-incapable, you
    +# can get the information to us by sending mail to apache-bugs@apache.org.
    +#
    +# WANTHSREGEX:
    +#  Apache requires a POSIX regex implementation. Henry Spencer's
    +#  excellent regex package is included with Apache and can be used
    +#  if desired. If your OS has a decent regex, you can elect to
    +#  not use this one by setting WANTHSREGEX to 'no' or commenting
    +#  out the Rule. The "default" action is "yes" unless overruled
    +#  by OS specifics
    +
    +Rule WANTHSREGEX=default
    +
    +################################################################
    +# Module configuration
    +#
    +# Modules are listed in reverse priority order --- the ones that come
    +# later can override the behavior of those that come earlier.  This
    +# can have visible effects; for instance, if UserDir followed Alias,
    +# you couldn't alias out a particular user's home directory.
    +
    +# The configuration below is what we consider a decent default 
    +# configuration.  If you want the functionality provided by a particular
    +# module, remove the "#" sign at the beginning of the line. But remember, 
    +# the more modules you compile into the server, the larger the executable
    +# is and the more memory it will take, so if you are unlikely to use the
    +# functionality of a particular module you might wish to leave it out.
    +
    +##
    +## Config manipulation modules
    +##
    +## mod_env sets up additional or restricted environment variables to be
    +## passed to CGI/SSI scripts.  It is listed first (lowest priority) since
    +## it does not do per-request stuff.
    +
    +AddModule modules/standard/mod_env.o
    +
    +##
    +## Request logging modules
    +##
    +
    +AddModule modules/standard/mod_log_config.o
    +
    +## Optional modules for NCSA user-agent/referer logging compatibility
    +## We recommend, however, that you just use the configurable access_log.
    +
    +# AddModule modules/standard/mod_log_agent.o
    +# AddModule modules/standard/mod_log_referer.o
    +
    +##
    +## Type checking modules
    +##
    +## mod_mime_magic determines the type of a file by examining a few bytes
    +## of it and testing against a database of filetype signatures.  It is
    +## based on the unix file(1) command.
    +## mod_mime maps filename extensions to content types, encodings, and
    +## "magic" type handlers (the latter is obsoleted by mod_actions, and
    +## don't confuse it with the previous module).
    +## mod_negotiation allows content selection based on the Accept* headers.
    +
    +# AddModule modules/standard/mod_mime_magic.o
    +AddModule modules/standard/mod_mime.o
    +AddModule modules/standard/mod_negotiation.o
    +
    +##
    +## Content delivery modules
    +##
    +## The status module allows the server to display current details about 
    +## how well it is performing and what it is doing.  Consider also enabling 
    +## STATUS=yes (see the Rules section near the start of this file) to allow
    +## full status information.  Check conf/access.conf on how to enable this.
    +
    +# AddModule modules/standard/mod_status.o
    +
    +## The Info module displays configuration information for the server and 
    +## all included modules. It's very useful for debugging.
    +
    +# AddModule modules/standard/mod_info.o
    +
    +## mod_include translates server-side include (SSI) statements in text files.
    +## mod_autoindex handles requests for directories which have no index file
    +## mod_dir handles requests on directories and directory index files.
    +## mod_cgi handles CGI scripts.
    +
    +AddModule modules/standard/mod_include.o
    +AddModule modules/standard/mod_autoindex.o
    +AddModule modules/standard/mod_dir.o
    +AddModule modules/standard/mod_cgi.o
    +
    +## The asis module implements ".asis" file types, which allow the embedding
    +## of HTTP headers at the beginning of the document.  mod_imap handles internal 
    +## imagemaps (no more cgi-bin/imagemap/!).  mod_actions is used to specify 
    +## CGI scripts which act as "handlers" for particular files, for example to
    +## automatically convert every GIF to another file type.
    +
    +AddModule modules/standard/mod_asis.o
    +AddModule modules/standard/mod_imap.o
    +AddModule modules/standard/mod_actions.o
    +
    +##
    +## URL translation modules.
    +##
    +
    +## The Speling module attempts to correct misspellings of URLs that
    +## users might have entered, namely by checking capitalizations
    +## or by allowing up to one misspelling (character insertion / omission /
    +## transposition/typo). This catches the majority of misspelled requests.
    +## If it finds a match, a "spelling corrected" redirection is returned.
    +
    +# AddModule modules/standard/mod_speling.o
    +
    +## The UserDir module for selecting resource directories by user name
    +## and a common prefix, e.g., /~<user> , /usr/web/<user> , etc.
    +
    +AddModule modules/standard/mod_userdir.o
    +
    +## The proxy module enables the server to act as a proxy for outside
    +## http and ftp services. It's not as complete as it could be yet.
    +## NOTE: You do not want this module UNLESS you are running a proxy;
    +##       it is not needed for normal (origin server) operation.
    +
    +# AddModule modules/proxy/libproxy.a
    +
    +## The Alias module provides simple URL translation and redirection.
    +
    +AddModule modules/standard/mod_alias.o
    +
    +## The URL rewriting module allows for powerful URI-to-URI and 
    +## URI-to-filename mapping using a regular expression based 
    +## rule-controlled rewriting engine.
    +
    +# AddModule modules/standard/mod_rewrite.o
    +
    +##
    +## Access control and authentication modules. 
    +##
    +AddModule modules/standard/mod_access.o
    +AddModule modules/standard/mod_auth.o
    +
    +## The anon_auth module allows for anonymous-FTP-style username/ 
    +## password authentication.
    +
    +# AddModule modules/standard/mod_auth_anon.o
    +
    +## db_auth and dbm_auth work with Berkeley DB files - make sure there
    +## is support for DBM files on your system.  You may need to grab the GNU
    +## "gdbm" package if not and possibly adjust EXTRA_LIBS. (This may be
    +## done by Configure at a later date)
    +
    +# AddModule modules/standard/mod_auth_dbm.o
    +# AddModule modules/standard/mod_auth_db.o
    +
    +## "digest" implements HTTP Digest Authentication rather than the less 
    +## secure Basic Auth used by the other modules.
    +
    +# AddModule modules/standard/mod_digest.o
    +
    +## Optional response header manipulation modules. 
    +##
    +## cern_meta mimics the behavior of the CERN web server with regards to 
    +## metainformation files.  
    +
    +# AddModule modules/standard/mod_cern_meta.o
    +
    +## The expires module can apply Expires: headers to resources,
    +## as a function of access time or modification time.
    +
    +# AddModule modules/standard/mod_expires.o
    +
    +## The headers module can set arbitrary HTTP response headers,
    +## as configured in server, vhost, access.conf or .htaccess configs
    +
    +# AddModule modules/standard/mod_headers.o
    +
    +## Miscellaneous modules
    +##
    +## mod_usertrack is the new name for mod_cookies.  This module
    +## uses Netscape cookies to automatically construct and log
    +## click-trails from Netscape cookies, or compatible clients who
    +## aren't coming in via proxy.   
    +##
    +## You do not need this, or any other module to allow your site
    +## to use Cookies.  This module is for user tracking only
    +
    +# AddModule modules/standard/mod_usertrack.o
    +
    +## The example module, which demonstrates the use of the API.  See
    +## the file modules/example/README for details.  This module should
    +## only be used for testing -- DO NOT ENABLE IT on a production server.
    +
    +# AddModule modules/example/mod_example.o
    +
    +## mod_unique_id generates unique identifiers for each hit, which are
    +## available in the environment variable UNIQUE_ID.  It may not work on all
    +## systems, hence it is not included by default.
    +
    +# AddModule modules/standard/mod_unique_id.o
    +
    +## mod_so lets you add modules to Apache without recompiling.
    +## This is an experimental feature at this stage and only supported 
    +## on a subset of the platforms we generally support. 
    +## Don't change this entry to a 'SharedModule' variant (Bootstrapping!)
    +
    +# AddModule modules/standard/mod_so.o
    +
    +## mod_mmap_static is an experimental module, you almost certainly
    +## don't need it.  It can make some webservers faster.  No further
    +## documentation is provided here because you'd be foolish
    +## to use mod_mmap_static without reading the full documentation.
    +
    +# AddModule modules/experimental/mod_mmap_static.o
    +
    +## mod_setenvif lets you set environment variables based on the HTTP header
    +## fields in the request; this is useful for conditional HTML, for example.
    +## Since it is also used to detect buggy browsers for workarounds, it
    +## should be the last (highest priority) module.
    +
    +AddModule modules/standard/mod_setenvif.o
    +
    diff --git a/APACHE_1_3b7/src/Configure b/APACHE_1_3b7/src/Configure
    new file mode 100755
    index 0000000000..3fda5c099c
    --- /dev/null
    +++ b/APACHE_1_3b7/src/Configure
    @@ -0,0 +1,1769 @@
    +#!/bin/sh
    +## ====================================================================
    +## Copyright (c) 1995-1998 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/>.
    +
    +# HISTORY:
    +#
    +# Apache configuration script, first cut --- rst.
    +# Don't like it?  Inspired to do something better?  Go for it.
    +#
    +# second cut --- jmj
    +# At this point we change what Configuration contains. It maintain
    +# contains comments, specific compiler flags, a list of included
    +# modules and "rules". These rules are used to allow Configure to
    +# be totally configured from Configuration.
    +#
    +# third cut --- rse
    +# Big cleanup of the generated Makefiles and remove of
    +# some old kludges
    +
    +# Uses 6 supplemental scripts located in ./helpers:
    +#	CutRule: Determines the value for a specified Rule
    +#	GuessOS: Uses uname to determine OS/platform
    +#	PrintPath: generic "type" or "whence" replacement
    +#	TestCompile: Can check for libs and if $(CC) is ANSI
    +#	 (i.e., a simple "sanity check")
    +#	mfhead:
    +#	fp2rp:
    +
    +exitcode=0
    +trap 'rm -f $tmpfile $tmpfile2 $tmpfile3 $tmpconfig $awkfile; exit $exitcode' 0 1 2 3 15
    +
    +####################################################################
    +## Set up some defaults
    +##
    +file=Configuration
    +tmpfile=htconf.$$
    +tmpfile2=$tmpfile.2
    +tmpfile3=$tmpfile.3
    +awkfile=$tmpfile.4
    +tmpconfig=$tmpfile.5
    +SUBDIRS="ap main modules"
    +
    +####################################################################
    +## Now handle any arguments, which, for now, is -file
    +## to select an alternate Configuration file
    +##
    +while [ "x$1" != "x" ]; do
    +  if [ "x$1" = "x-file" ] ; then
    +    shift 1; file=$1; shift 1
    +    if [ ! -r $file ]; then
    +      echo "$file does not exist or is not readable."
    +      exitcode=1
    +      exit 1
    +    fi
    +  else
    +    echo "ERROR: Bad command line option '$1'"
    +    echo "  Please read the file INSTALL."
    +    exit 1
    +  fi
    +done
    +if [ ! -r $file ]; then
    +  echo "Can't see or read \"$file\""
    +  echo "Please copy Configuration.tmpl to $file, edit it for your platform,"
    +  echo "and re-run $0 again."
    +  exitcode=1
    +  exit 1
    +fi
    +
    +####################################################################
    +## Now see if Configuration.tmpl is more recent than $file. If
    +## so, then we complain and bail out
    +##
    +if ls -lt Configuration.tmpl $file | head -1 | \
    +  grep 'Configuration.tmpl' > /dev/null
    +then
    +  echo "Configuration.tmpl is more recent than $file;"
    +  echo "Make sure that $file is valid and, if it is, simply"
    +  echo "'touch $file' and re-run $0 again."
    +  exitcode=1
    +  exit 1
    +fi
    +
    +echo "Using config file: $file"
    +
    +####################################################################
    +## From the Configuration file, create a "cleaned-up" version
    +## that's easy to scan
    +##
    +
    +# Strip comments and blank lines, remove whitespace around
    +# "=" assignments, change Rules to comments and then remove whitespace
    +# before Module declarations
    +sed 's/#.*//' $file | \
    + sed '/^[ 	]*$/d' | \
    + sed 's/[ 	]*$//' | \
    + sed 's/[ 	]*=[ 	]*/=/' | \
    + sed '/^Rule[ 	]*/d' | \
    + sed 's/^[ 	]*AddModule/AddModule/' | \
    + sed 's/^[ 	]*%AddModule/%AddModule/' | \
    + sed 's/^[ 	]*SharedModule/SharedModule/' | \
    + sed 's/^[ 	]*Module/Module/' | \
    + sed 's/^[ 	]*%Module/%Module/' > $tmpfile
    +
    +# Determine if shared objects are used
    +using_shlib=`grep  '^SharedModule' $tmpfile >/dev/null && echo 1`
    +
    +# But perhaps later via apxs when just mod_so is compiled in!
    +if [ ".$using_shlib" = . ]; then
    +    using_shlib=`grep  '^AddModule modules/standard/mod_so.o' $tmpfile >/dev/null && echo 1`
    +fi
    +
    +# Only "assignment" ("=") statements and Module lines
    +# should be left at this point. If there is other stuff
    +# we bail out
    +if egrep -v '^%?Module[ 	]+[A-Za-z0-9_]+[ 	]+[^ 	]+$' $tmpfile \
    + | egrep -v '^%?AddModule[ 	]+[^ 	]+$' \
    + | egrep -v '^SharedModule[ 	]+[^ 	]+$' \
    + | grep -v = > /dev/null
    +then
    +  echo "Syntax error --- The configuration file is used only to"
    +  echo "define the list of included modules or to set Makefile"
    +  echo "options or Configure rules, and I don't see that at all:"
    +  egrep -v '^%?Module[ 	]+[A-Za-z0-9_]+[ 	]+[^ 	]+$' $tmpfile \
    +   | egrep -v '^%?AddModule[ 	]+[^ 	]+$'  \
    +   | egrep -v '^%?SharedModule[ 	]+[^ 	]+$'  \
    +   | grep -v =
    +  exitcode=1
    +  exit 1
    +fi
    +
    +####################################################################
    +## If we find the directory /usr/local/etc/httpd and there is
    +## no HTTPD_ROOT flag set in the Configuration file we assume
    +## that the user was using the old default root directory
    +## and issue a notice about it.
    +##
    +if [ $file != "Configuration.apaci" ]
    +then
    +  if [ -d /usr/local/etc/httpd/ ]
    +  then
    +    if egrep '^EXTRA_CFLAGS.*HTTPD_ROOT' $file >/dev/null
    +    then
    +      :
    +    else
    +      echo " | Please note that the default httpd root directory has changed"
    +      echo " | from '/usr/local/etc/httpd/' to '/usr/local/apache/.'"
    +      echo " | You may add '-DHTTPD_ROOT=\\\"/usr/local/etc/httpd\\\"' to EXTRA_CFLAGS"
    +      echo " | in your Configuration file (and re-run Configure) or start"
    +      echo " | httpd with the option '-d /usr/local/etc/httpd' if you still"
    +      echo " | want to use the old root directory for your server."
    +    fi
    +  fi
    +fi
    +
    +####################################################################
    +## Start creating the Makefile. We add some comments and
    +## then fold in the modules that were included in Configuration
    +##
    +echo "Creating Makefile"
    +./helpers/mfhead . $file > Makefile
    +
    +####################################################################
    +## Now we create a stub file, called Makefile.config, which
    +## just includes those assignments (eg: CC=gcc) in Configuration
    +##
    +awk >Makefile.config <$tmpfile '
    +    BEGIN {
    +	print "##"
    +	print "##  Inherited Makefile options from Configure script"
    +	print "##  (Begin of automatically generated section)"
    +	print "##"
    +	print "SRCDIR=."
    +    } 
    +    /\=/ { print } 
    +    '
    +
    +####################################################################
    +## Extract the rules.
    +##
    +RULE_WANTHSREGEX=`./helpers/CutRule WANTHSREGEX $file`
    +RULE_STATUS=`./helpers/CutRule STATUS $file`
    +RULE_SOCKS4=`./helpers/CutRule SOCKS4 $file`
    +RULE_SOCKS5=`./helpers/CutRule SOCKS5 $file`
    +RULE_IRIXNIS=`./helpers/CutRule IRIXNIS $file`
    +RULE_IRIXN32=`./helpers/CutRule IRIXN32 $file`
    +RULE_PARANOID=`./helpers/CutRule PARANOID $file`
    +RULE_SHARED_CORE=`./helpers/CutRule SHARED_CORE $file`
    +
    +####################################################################
    +## Rule SHARED_CORE implies required DSO support
    +##
    +if [ "$RULE_SHARED_CORE" = "yes" ]; then
    +	using_shlib=1
    +fi
    +
    +####################################################################
    +## Preset some "constants";
    +## can be overridden on a per-platform basis below.
    +##
    +DBM_LIB="-ldbm"
    +DB_LIB="-ldb"
    +SHELL="/bin/sh"
    +TARGET="httpd"
    +SUBTARGET="target_static"
    +SHLIB_SUFFIX_LIST=""
    +AP_PRINTPATH=PrintPath
    +export AP_PRINTPATH
    +CAT="cat"
    +if ./helpers/$AP_PRINTPATH -s ranlib; then
    +    RANLIB="ranlib"
    +else
    +    RANLIB="true"
    +fi
    +
    +####################################################################
    +## Now we determine the OS/Platform automagically, thanks to
    +## GuessOS, a home-brewed OS-determiner ala config.guess
    +##
    +## We adjust CFLAGS, LIBS, LDFLAGS and INCLUDES (and other Makefile
    +## options) as required. Setting CC and OPTIM here has no effect
    +## if they were set in Configure.
    +##
    +## Also, we set DEF_WANTHSREGEX and to the appropriate
    +## value for each platform.
    +##
    +## As more PLATFORMs are added to Configuration.tmpl, be sure to
    +## add the required lines below.
    +##
    +PLAT=`./helpers/GuessOS`
    +SHELL="/bin/sh"
    +OSDIR="os/unix"
    +
    +case "$PLAT" in
    +    *mint)
    +        OS="MiNT"
    +        CFLAGS="-DMINT"
    +        LIBS="$LIBS -lportlib -lsocket"
    +        DEF_WANTHSREGEX=yes
    +        ;;
    +    *MPE/iX*)
    +        OS='MPE/iX'
    +	CFLAGS="$CFLAGS -DMPE -D_POSIX_SOURCE -D_SOCKET_SOURCE"
    +	LIBS="$LIBS -lsocket -lsvipc"
    +	LDFLAGS="$LDFLAGS -Xlinker \"-WL,cap=ia,ba,ph,pm;nmstack=1024000\""
    +	CAT="/bin/cat" # built-in cat is badly broken for stdin redirection
    +	;;
    +    *-apple-aux3*)
    +	OS='A/UX 3.1.x'
    +	CFLAGS="$CFLAGS -DAUX3 -D_POSIX_SOURCE"
    +	LIBS="$LIBS -lposix -lbsd"
    +	LDFLAGS="$LDFLAGS -s"
    +	DEF_WANTHSREGEX=no
    +	;;
    +    i386-ibm-aix*)
    +	OS='IBM AIX PS/2'
    +	CFLAGS="$CFLAGS -DAIX=1 -U__STR__ -DUSEBCOPY"
    +	DEF_WANTHSREGEX=no
    +	;;
    +    *-ibm-aix[1-2].*)
    +	OS='IBM AIX 1.x/2.x'
    +	CFLAGS="$CFLAGS -DAIX=1 -DNEED_RLIM_T -U__STR__"
    +	;;
    +    *-ibm-aix3.*)
    +	OS='IBM AIX 3.x'
    +	CFLAGS="$CFLAGS -DAIX=30 -DNEED_RLIM_T -U__STR__"
    +	;;
    +    *-ibm-aix4.1)
    +	OS='IBM AIX 4.1'
    +	CFLAGS="$CFLAGS -DAIX=41 -DNEED_RLIM_T -U__STR__"
    +	;;
    +    *-ibm-aix4.2)
    +	OS='IBM AIX 4.2'
    +	CFLAGS="$CFLAGS -DAIX=42 -U__STR__"
    +	LDFLAGS="$LDFLAGS -lm"
    +	;;
    +    *-ibm-aix4.3)
    +	OS='IBM AIX 4.3'
    +	CFLAGS="$CFLAGS -DAIX=43 -U__STR__"
    +	LDFLAGS="$LDFLAGS -lm"
    +	;;
    +    *-ibm-aix*)
    +	OS='IBM AIX'
    +	CFLAGS="$CFLAGS -DAIX=1 -U__STR__"
    +	LDFLAGS="$LDFLAGS -lm"
    +	;;
    +    *-apollo-*)
    +	OS='Apollo Domain'
    +	CFLAGS="$CFLAGS -DAPOLLO"
    +	;;
    +    *-dg-dgux*)
    +	OS='DG/UX 5.4'
    +	CFLAGS="$CFLAGS -DDGUX"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *OS/2*)
    +	OSDIR="os/emx"
    +	DEF_WANTHSREGEX=yes
    +	OS='EMX OS/2'
    +	CFLAGS="$CFLAGS -Zbsd-signals -Zbin-files -DTCPIPV4 -g"
    +	LDFLAGS="$LDFLAGS -Zexe"
    +	LIBS="$LIBS -lsocket -lufc -lbsd"
    +	DBM_LIB="-lgdbm"
    +	SHELL=sh
    +	AP_PRINTPATH=PrintPathOS2
    +	export AP_PRINTPATH
    +	;;
    +    *-hi-hiux)
    +	OS='HI-UX'
    +	CFLAGS="$CFLAGS -DHIUX"
    +	;;
    +    *-hp-hpux11.*)
    +	OS='HP-UX 11'
    +	CFLAGS="$CFLAGS -DHPUX11"
    +	LIBS="$LIBS -lm -lpthread"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-hp-hpux10.*)
    +	OS='HP-UX 10'
    +	CFLAGS="$CFLAGS -DHPUX10"
    + 	case "$PLAT" in
    + 	  *-hp-hpux10.01)
    +	       # We know this is a problem in 10.01.
    +               # Not a problem in 10.20.  Otherwise, who knows?
    +               CFLAGS="$CFLAGS -DSELECT_NEEDS_CAST"
    +               ;;	     
    + 	esac
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-hp-hpux*)
    +	OS='HP-UX'
    +	CFLAGS="$CFLAGS -DHPUX"
    +	DEF_WANTHSREGEX=yes
    +	LIBS="$LIBS -lm"
    +	;;
    +    *-sgi-irix64)
    +        # Note: We'd like to see patches to compile 64-bit, but for now...
    +	echo "You are running 64-bit Irix. For now, we will compile 32-bit"
    +	echo "but if you would care to port to 64-bit, send us the patches."
    +	DEF_WANTHSREGEX=yes
    +	DBM_LIB=""
    +	if [ "$RULE_IRIXNIS" = "yes" ]; then
    +	    OS='SGI IRIX-64 w/NIS'
    +	    CFLAGS="$CFLAGS -DIRIX"
    +	    LIBS="$LIBS -lsun"
    +	else
    +	    OS='SGI IRIX-64'
    +	    CFLAGS="$CFLAGS -DIRIX"
    +	fi
    +	;;
    +    *-sgi-irix32)
    +	DEF_WANTHSREGEX=yes
    +	DBM_LIB=""
    +	if [ "$RULE_IRIXN32" = "yes" ]; then
    +	    if [ "$RULE_IRIXNIS" = "yes" ]; then
    +		OS='SGI IRIX-32 w/NIS'
    +	    else
    +		OS='SGI IRIX-32'
    +	    fi
    +	else
    +	    if [ "$RULE_IRIXNIS" = "yes" ]; then
    +		OS='SGI IRIX w/NIS'
    +	    else
    +		OS='SGI IRIX'
    +	    fi
    +	fi
    +	CFLAGS="$CFLAGS -DIRIX"
    +	;;
    +    *-sgi-irix)
    +	DEF_WANTHSREGEX=yes
    +	DBM_LIB=""
    +	if [ "$RULE_IRIXNIS" = "yes" ]; then
    +	    OS='SGI IRIX w/NIS'
    +	    CFLAGS="$CFLAGS -DIRIX"
    +	    LIBS="$LIBS -lsun"
    +	else
    +	    OS='SGI IRIX'
    +	    CFLAGS="$CFLAGS -DIRIX"
    +	fi
    +	;;
    +    *-linux2)
    +	DEF_WANTHSREGEX=yes
    +	OS='Linux'
    +	CFLAGS="$CFLAGS -DLINUX=2"
    +	LIBS="$LIBS -lm"
    +	;;
    +    *-linux1)
    +	DEF_WANTHSREGEX=yes
    +	OS='Linux'
    +	CFLAGS="$CFLAGS -DLINUX=1"
    +	;;
    +    *-lynx-lynxos)
    +	OS='LynxOS 2.x'
    +	CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__ -DLYNXOS"
    +	LIBS="$LIBS -lbsd -lcrypt"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *486-*-bsdi*)
    +	OS='BSDI w/486'
    +	CFLAGS="$CFLAGS -m486"
    +	DBM_LIB=""
    +	DB_LIB=""
    +	;;
    +    *-bsdi*)
    +	OS='BSDI'
    +	DBM_LIB=""
    +	DB_LIB=""
    +	;;
    +    *-netbsd*)
    +	OS='NetBSD'
    +	CFLAGS="$CFLAGS -DNETBSD"
    +	LIBS="$LIBS -lcrypt"
    +	DBM_LIB=""
    +	DB_LIB=""
    +	DEF_WANTHSREGEX=no
    +	;;
    +    *-freebsd*)
    +    	PLATOSVERS=`echo $PLAT | sed 's/^.*freebsd//'`
    +	OS="FreeBSD $PLATOSVERS"
    +	case "$PLATOSVERS" in
    +	    [23]*)
    +		DEF_WANTHSREGEX=no
    +		CFLAGS="$CFLAGS -funsigned-char"
    +		;;
    +	esac
    +	LIBS="$LIBS -lcrypt"
    +	DBM_LIB=""
    +	DB_LIB=""
    +	;;
    +    *-openbsd*)
    +	OS='OpenBSD'
    +	DBM_LIB=""
    +	;;
    +    *-next-nextstep*)
    +	OS='NeXT'
    +	CFLAGS="$CFLAGS -DNEXT"
    +	DEF_WANTHSREGEX=yes
    +	RANLIB="sleep 5; /bin/ranlib"
    +	# ranlib on most NeXTs sets the time wrong. 5 secs wait does much good
    +	;;
    +    *-dec-osf*)
    +	OS='DEC OSF/1'
    +	CFLAGS="$CFLAGS -DOSF1"
    +	LIBS="$LIBS -lm"
    +	;;
    +    *-qnx)
    +	OS='QNX'
    +	CFLAGS="$CFLAGS -DQNX"
    +	LIBS="$LIBS -N128k -lsocket -lunix"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-qnx32)
    +	OS='QNX32'
    +	CFLAGS="$CFLAGS -DQNX -mf -3"
    +	LIBS="$LIBS -N128k -lsocket -lunix"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-isc4*)
    +	OS='ISC 4'
    +	CC='gcc'
    +	CFLAGS="$CFLAGS -posix -DISC"
    +	LDFLAGS="$LDFLAGS -posix"
    +	LIBS="$LIBS -linet"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-sco3*)
    +	OS='SCO 3'
    +	CFLAGS="$CFLAGS -DSCO -Oacgiltz"
    +	LIBS="$LIBS -lPW -lsocket -lmalloc -lcrypt_i"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-sco5*)
    +	OS='SCO 5'
    +	CFLAGS="$CFLAGS -DSCO5"
    +	LIBS="$LIBS -lsocket -lmalloc -lprot"
    +	DEF_WANTHSREGEX=no
    +	;;
    +    *-sco_sv*)
    +	OS='SCO SV'
    +	CFLAGS="$CFLAGS -DSCO"
    +	LIBS="$LIBS -lPW -lsocket -lmalloc -lcrypt_i"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-solaris2*)
    +    	PLATOSVERS=`echo $PLAT | sed 's/^.*solaris2.//'`
    +	OS="Solaris $PLATOSVERS"
    +	CFLAGS="$CFLAGS -DSOLARIS2=$PLATOSVERS"
    +	LIBS="$LIBS -lsocket -lnsl"
    +	DBM_LIB=""
    +	case "$PLATOSVERS" in
    +	    2[01234]*)
    +		DEF_WANTHSREGEX=yes
    +		;;
    +	    *)
    +		DEF_WANTHSREGEX=no
    +		;;
    +	esac
    +	;;
    +    *-sunos4*)
    +	OS='SunOS 4'
    +	CFLAGS="$CFLAGS -DSUNOS4 -DUSEBCOPY"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-unixware1)
    +	DEF_WANTHSREGEX=yes
    +	OS='UnixWare 1.x'
    +	CFLAGS="$CFLAGS -DUW=100"
    +	LIBS="$LIBS -lsocket -lnsl -lcrypt"
    +	;;
    +    *-unixware2)
    +	DEF_WANTHSREGEX=yes
    +	OS='UnixWare 2.x'
    +	CFLAGS="$CFLAGS -DUW=200"
    +	LIBS="$LIBS -lsocket -lnsl -lcrypt -lgen"
    +	;;
    +    *-unixware211)
    +	OS='UnixWare 2.1.1'
    +	CFLAGS="$CFLAGS -DUW=211"
    +	LIBS="$LIBS -lsocket -lnsl -lcrypt -lgen"
    +	;;
    +    *-unixware212)
    +	OS='UnixWare 2.1.2'
    +	CFLAGS="$CFLAGS -DUW=212"
    +	LIBS="$LIBS -lsocket -lnsl -lcrypt -lgen"
    +	DBM_LIB=""
    +	;;
    +    maxion-*-sysv4*)
    +    	OS='SVR4'
    +	CFLAGS="$CFLAGS -DSVR4"
    +	DEF_WANTHSREGEX=yes
    +	LIBS="$LIBS -lsocket -lnsl -lc -lgen"
    +	;;
    +    BS2000*-sni-sysv4*)
    +	OS='BS2000'
    +	OSDIR='os/bs2000'
    +	CC='c89 -XLLML -XLLMK'
    +	CFLAGS="$CFLAGS -DCHARSET_EBCDIC -DSVR4 -D_XPG_IV"
    +	DEF_WANTHSREGEX=yes
    +	LIBS="$LIBS -lsocket -lnsl -lc"
    +	;;
    +    *-sni-sysv4*)
    +	OS='SVR4'
    +	CFLAGS="$CFLAGS -DSVR4 -D_XPG_IV -DHAS_DLFCN -DUSE_MMAP_FILES -DUSE_SYSVSEM_SERIALIZED_ACCEPT -DNEED_UNION_SEMUN"
    +	DEF_WANTHSREGEX=yes
    +	LIBS="$LIBS -lsocket -lnsl -lc"
    +	;;
    +    DS/90\ 7000-*-sysv4*)
    +	OS='UXP/DS'
    +	CFLAGS="$CFLAGS -DUXPDS"
    +	LIBS="$LIBS -lsocket -lnsl"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-tandem-sysv4*)
    +	OS='SVR4'
    +	CFLAGS="$CFLAGS -DSVR4"
    +	LIBS="$LIBS -lsocket -lnsl"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-sysv4*)
    +	OS='SVR4'
    +	CFLAGS="$CFLAGS -DSVR4"
    +	LIBS="$LIBS -lsocket -lnsl -lc"
    +	;;
    +    88k-encore-sysv4)
    +	OS='Encore UMAX V'
    +	CFLAGS="$CFLAGS -DSVR4 -DENCORE"
    +	DEF_WANTHSREGEX=yes
    +	LIBS="$LIBS -lPW"
    +	;;
    +    *-uts*)
    +	OS='Amdahl UTS'
    +	CFLAGS="$CFLAGS -Xa -eft -DUTS21"
    +	LIBS="$LIBS -lsocket -lbsd -la"
    +	;;
    +    *-ultrix)
    +	OS='ULTRIX'
    +	CFLAGS="-DULTRIX"
    +	DEF_WANTHSREGEX=yes
    +	SHELL="/bin/sh5"
    +	;;
    +    *powerpc-tenon-machten*)
    +	OS='MachTen PPC'
    +	LDFLAGS="$LDFLAGS -Xlstack=0x14000 -Xldelcsect"
    +	;;
    +    *-machten*)
    +	OS='MachTen 68K'
    +	LDFLAGS="$LDFLAGS -stack 0x14000"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *convex-v11*)
    +	OS='CONVEXOS11'
    +	CFLAGS="$CFLAGS -ext -DCONVEXOS11"
    +	OPTIM="-O1" # scalar optimization only
    +	CC='cc'
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    i860-intel-osf1)
    +	DEF_WANTHSREGEX=yes
    +	OS='Paragon OSF/1'
    +	CFLAGS="$CFLAGS -DPARAGON"
    +	;;
    +    *DYNIX*)
    +	DEF_WANTHSREGEX=yes
    +	OS='SEQUENT'
    +	CFLAGS="$CFLAGS -DSEQUENT"
    +	;;
    +    *NEWS-OS*)
    +	DEF_WANTHSREGEX=yes
    +	OS='SONY NEWS-OS'
    +	CFLAGS="$CFLAGS -DNEWSOS"
    +	;;
    +    *-riscix)
    +	OS='Acorn RISCix'
    +	CFLAGS="$CFLAGS -DRISCIX"
    +	OPTIM="-O"
    +	MAKE="make"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-BeOS*)
    +	OS='BeOS';
    +	CFLAGS="$CFLAGS -DBEOS"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    4850-*.*)
    +        OS='NCR MP/RAS'
    +        CFLAGS="$CFLAGS -DSVR4 -DMPRAS"
    +        DEF_WANTHSREGEX=yes
    +        LIBS="$LIBS -lsocket -lnsl -lc -L/usr/ucblib -lucb"
    +        ;;
    +    *) # default: Catch systems we don't know about
    +        OS='Unknown and unsupported OS'
    +    	echo Sorry, but we cannot grok \"$PLAT\"
    +	echo uname -m
    +	uname -m
    +	echo uname -r
    +	uname -r
    +	echo uname -s
    +	uname -s
    +	echo uname -v
    +	uname -v
    +	echo uname -X
    +	uname -X
    +	echo Ideally, read the file PORTING, do what it says, and send the
    +	echo resulting patches to The Apache Group by filling out a report
    +	echo form at http://www.apache.org/bug_report.html. If you don\'t 
    +        echo wish to do the port yourself, please submit this output rather 
    +        echo than the patches. Thank you.
    +	echo
    +	echo Pressing on with the build process, but all bets are off.
    +	echo Do not be surprised if it fails. If it works, and even
    +	echo if it does not, please contact the above address.
    +	echo
    +	;;
    +esac
    +
    +####################################################################
    +## Show user what OS we came up with
    +##
    +echo " + configured for $OS platform"
    +SUBDIRS="$OSDIR $SUBDIRS"
    +
    +####################################################################
    +## And adjust/override WANTHSREGEX as needed
    +##
    +if [ "$RULE_WANTHSREGEX" = "default" ]; then
    +	if [ "x$DEF_WANTHSREGEX" = "x" ]; then
    +		RULE_WANTHSREGEX=yes
    +	else
    +		RULE_WANTHSREGEX=$DEF_WANTHSREGEX
    +	fi
    +fi
    +
    +####################################################################
    +## Now we determine the C-compiler and optimization level
    +## to use. Settings of CC and OPTIM in Configuration have
    +## the highest precedence; next comes any settings from
    +## the above "OS-specific" section. If still unset,
    +## then we look for a known compiler somewhere in PATH
    +##
    +
    +# First, look for a CC=<whatever> setting in Configuration (recall, we
    +# copied these to Makefile.config)
    +#
    +# If $TCC is null, then no such line exists in Configuration
    +#
    +TCC=`egrep '^CC=' Makefile.config | tail -1 | awk -F= '{print $2}'`
    +if [ "x$TCC" = "x" ]; then
    +    if [ "x$CC" = "x" ]; then
    +        # At this point, CC is not set in Configuration or above, so we
    +        # try to find one
    +	for compilers in "gcc" "cc" "acc" "c89"
    +	do
    +	    lookedfor="$lookedfor $compilers"
    +	    if ./helpers/$AP_PRINTPATH -s $compilers; then
    +		COMPILER="$compilers"
    +		break
    +	    fi
    +	done
    +	if [ "x$COMPILER" = "x" ]; then
    +	    echo "Error: could not find any of these C compilers"
    +	    echo " anywhere in your PATH: $lookedfor"
    +	    echo "Configure terminated"
    +	    exitcode=1
    +	    exit 1
    +	fi
    +	CC=$COMPILER
    +    fi
    +    echo " + setting C compiler to $CC"
    +fi
    +
    +####################################################################
    +## Write the value of $CC to Makefile.config... We only do this
    +## is not done already (ie: a 'CC=' line was in Configuration).
    +## If there was an entry for it, then set $CC for our own internal
    +## use.
    +##
    +if [ "x$TCC" = "x" ]; then
    +    echo "CC=$CC" >> Makefile.config
    +else
    +    CC=$TCC
    +fi
    +
    +####################################################################
    +## Look for OPTIM and save for later
    +##
    +TOPTIM=`egrep '^OPTIM=' Makefile.config | tail -1 | awk -F= '{print $2}'`
    +
    +####################################################################
    +## Check for user provided flags for shared object support
    +##
    +TLD_SHLIB=`egrep '^LD_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
    +TLDFLAGS_SHLIB=`egrep '^LDFLAGS_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
    +TLDFLAGS_SHLIB_EXPORT=`egrep '^LDFLAGS_SHLIB_EXPORT=' Makefile.config | tail -1 | awk -F= '{print $2}'`
    +TCFLAGS_SHLIB=`egrep '^CFLAGS_SHLIB=' Makefile.config | tail -1 | awk -F= '{print $2}'`
    +
    +####################################################################
    +## We adjust now CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT as
    +## required.  For more platforms just add the required lines below.
    +##
    +if [ "x$using_shlib" = "x1" ] ; then
    +    LD_SHLIB="ld"
    +    DEF_SHARED_CORE=no
    +    SHLIB_SUFFIX_DEPTH=all
    +    SHLIB_EXPORT_FILES=no
    +    case "$PLAT" in
    +        *-linux1)
    +            CFLAGS_SHLIB="-fpic"
    +            LDFLAGS_SHLIB="-Bshareable"
    +            LDFLAGS_SHLIB_EXPORT="-rdynamic"
    +            ;;
    +        *-linux2)
    +            CFLAGS_SHLIB="-fpic"
    +            LDFLAGS_SHLIB="-Bshareable"
    +            LDFLAGS_SHLIB_EXPORT="-rdynamic"
    +            SHLIB_SUFFIX_DEPTH=0
    +            ;;
    +        *-freebsd*)
    +            CFLAGS_SHLIB="-fpic"
    +            LDFLAGS_SHLIB="-Bshareable"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            SHLIB_SUFFIX_DEPTH=2
    +            ;;
    +        *-openbsd2*)
    +            CFLAGS_SHLIB="-fPIC"
    +            LDFLAGS_SHLIB="-Bforcearchive -Bshareable"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            SHLIB_SUFFIX_DEPTH=2
    +            ;;
    +        alpha-*-netbsd*|mips-*-netbsd*|powerpc-*-netbsd*)
    +            CFLAGS_SHLIB="-fpic -DPIC"
    +            LDFLAGS_SHLIB="-shared"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            SHLIB_SUFFIX_DEPTH=2
    +            ;;
    +        *-netbsd*)
    +            CFLAGS_SHLIB="-fpic -DPIC"
    +            LDFLAGS_SHLIB="-Bshareable"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            SHLIB_SUFFIX_DEPTH=2
    +            ;;
    +        *-solaris2*)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="-KPIC" ;;
    +            esac
    +            LDFLAGS_SHLIB="-G"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            SHLIB_SUFFIX_DEPTH=1
    +            ;;
    +        *-sunos4*)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */acc|acc ) CFLAGS_SHLIB="-pic" ;;
    +            esac
    +            LDFLAGS_SHLIB="-assert pure-text"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            ;;
    +        *-sgi-irix32)
    +            case $CC in
    +                */gcc|gcc )
    +		    CFLAGS_SHLIB="-fpic"
    +		    N32FLAG=""
    +		    ;;
    +                */cc|cc )
    +		    CFLAGS_SHLIB="-KPIC"
    +		    N32FLAG="-n32"
    +		    ;;
    +            esac
    +            if [ "$RULE_IRIXN32" = "yes" ]; then
    +                LDFLAGS_SHLIB="$N32FLAG -shared"
    +            else
    +                LDFLAGS_SHLIB="-shared"
    +            fi
    +            LDFLAGS_SHLIB_EXPORT=""
    +            ;;
    +        *-sgi-irix)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="-KPIC" ;;
    +            esac
    +            LDFLAGS_SHLIB="-shared"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            ;;
    +        *-dec-osf*)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="" ;;
    +            esac
    +            LDFLAGS_SHLIB="-shared -expect_unresolved '*' -msym -s"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            ;;
    +        *-unixware2)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="-KPIC" ;;
    +            esac
    +            LDFLAGS_SHLIB="-Bdynamic -G"
    +            LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport"
    +            ;;
    +        *-unixware21*)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="-KPIC" ;;
    +            esac
    +            LDFLAGS_SHLIB="-Bdynamic -G"
    +            LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport"
    +            ;;
    +        RM*-sni-sysv4*)
    +            # MIPS hosts can take advantage of the LDFLAGS_SHLIB_EXPORT switch
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="-KPIC" ;;
    +            esac
    +            LDFLAGS_SHLIB="-G"
    +            LDFLAGS_SHLIB_EXPORT="-Wl,-Blargedynsym"
    +            ;;
    +        *-sni-sysv4*)
    +            # Older SINIX machines must be linked as "shared core"-Apache
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="-KPIC" ;;
    +            esac
    +            LDFLAGS_SHLIB="-G"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            SHLIB_SUFFIX_DEPTH=0
    +            DEF_SHARED_CORE=yes
    +            ;;
    +        *-sysv4*)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="-KPIC" ;;
    +            esac
    +            LDFLAGS_SHLIB="-G"
    +            LDFLAGS_SHLIB_EXPORT=""
    +            DEF_SHARED_CORE=yes
    +            ;;
    +        *-hp-hpux9.*)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="+z" ;;
    +            esac
    +            LDFLAGS_SHLIB="-b"
    +            LDFLAGS_SHLIB_EXPORT="-Wl,-E -Wl,-B,deferred"
    +            ;;
    +        *-hp-hpux10.*|*-hp-hpux11.*)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="+z" ;;
    +            esac
    +            LDFLAGS_SHLIB="-b"
    +            LDFLAGS_SHLIB_EXPORT="-Wl,-E -Wl,-B,deferred"
    +            ;;
    +        *-ibm-aix*)
    +            case $CC in
    +                */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +                */cc|cc   ) CFLAGS_SHLIB="" ;;
    +            esac
    +            case $PLAT in
    +                *-ibm-aix4*)
    +                    LDFLAGS_SHLIB="-H512 -T512 -bhalt:4 -bM:SRE -bnoentry"
    +                    ;;
    +                *-ibm-aix*)
    +                    LDFLAGS_SHLIB="-H512 -T512 -bhalt:4 -bM:SRE -e _nostart"
    +                    ;;
    +            esac
    +            LDFLAGS_SHLIB="$LDFLAGS_SHLIB -bI:\$(SRCDIR)/support/httpd.exp "
    +            LDFLAGS_SHLIB="$LDFLAGS_SHLIB -bE:\`echo \$@|sed -e 's:\.so\$\$:.exp:'\`"
    +            LDFLAGS_SHLIB="$LDFLAGS_SHLIB -lc"
    +            LDFLAGS_SHLIB_EXPORT="-Wl,-bE:\$(SRCDIR)/support/httpd.exp"
    +            SHLIB_EXPORT_FILES=yes
    +            ;;
    +        *)
    +            ##  ok, no known explict support for shared objects
    +            ##  on this platform, but we give not up immediately.
    +            ##  We take a second chance by guessing the compiler
    +            ##  and linker flags from the Perl installation
    +            ##  if it exists.
    +            PERL=
    +            for dir in `echo $PATH | sed -e 's/:/ /g'`
    +            do
    +                if [ -f "$dir/perl5" ]; then
    +                    PERL="$dir/perl5"
    +                    break
    +                fi
    +                if [ -f "$dir/perl" ]; then
    +                    PERL="$dir/perl"
    +                    break
    +                fi
    +            done
    +            if [ ".$PERL" != . ]; then
    +                #   cool, Perl is installed on this platform...
    +                if [ ".`$PERL -V:dlsrc 2>/dev/null | grep dlopen`" != . ]; then
    +                    #   ...and actually uses the dlopen-style interface,
    +                    #   so we can guess the flags from its knowledge
    +                    CFLAGS_SHLIB="`perl -V:cccdlflags | cut -d\' -f2`"
    +                    LDFLAGS_SHLIB="`perl -V:lddlflags | cut -d\' -f2`"
    +                    LDFLAGS_SHLIB_EXPORT="`perl -V:ccdlflags | cut -d\' -f2`"
    +                    #   but additionally we have to inform the
    +                    #   user that we are just guessing the flags
    +                    echo ""
    +                    echo "** WARNING: We have no explicit knowledge about shared object"
    +                    echo "** support for your particular platform. But perhaps you have"
    +                    echo "** luck: We were able to guess the compiler and linker flags"
    +                    echo "** for creating shared objects from your Perl installation."
    +                    echo "** If they actually work, please send the following information"
    +                    echo "** for inclusion into later releases to new-httpd@apache.org or make"
    +                    echo "** a suggestion report at http://www.apache.org/bug_report.html:"
    +                    echo "**     PLATFORM=$PLAT"
    +                    echo "**     CFLAGS_SHLIB=$CFLAGS_SHLIB"
    +                    echo "**     LDFLAGS_SHLIB=$LDFLAGS_SHLIB"
    +                    echo "**     LDFLAGS_SHLIB_EXPORT=$LDFLAGS_SHLIB_EXPORT"
    +                    echo ""
    +                fi
    +            fi
    +            ;;
    +    esac
    +fi
    +
    +####################################################################
    +## Check if we really have some information to compile
    +## the shared objects if SharedModule was used.
    +##
    +if [ "x$using_shlib" = "x1" ] ; then
    +    if [ "x$TCFLAGS_SHLIB"  = x -a "x$CFLAGS_SHLIB"  = x  -a \
    +         "x$TLDFLAGS_SHLIB" = x -a "x$LDFLAGS_SHLIB" = x ]; then
    +        echo ""
    +        echo "** FAILURE: Sorry, no shared object support available."
    +        echo "** Either compile all modules statically (use AddModule instead"
    +        echo "** of SharedModule in the Configuration file) or at least provide"
    +        echo "** us with the appropriate compiler and linker flags via the"
    +        echo "** CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT entries"
    +        echo "** in the Configuration file."
    +        echo ""
    +        exit 1
    +    fi
    +fi
    +
    +####################################################################
    +## Set the value of the shared libary flags, if they aren't explicitly
    +## set in the configuration file
    +##
    +if [ "x$using_shlib" = "x1" ] ; then
    +    if [ "x$TCFLAGS_SHLIB" = "x" ]; then
    +        echo "CFLAGS_SHLIB=$CFLAGS_SHLIB -DSHARED_MODULE" >> Makefile.config
    +    fi
    +    if [ "x$TLD_SHLIB" = "x" ]; then
    +        echo "LD_SHLIB=$LD_SHLIB" >> Makefile.config
    +    fi
    +    if [ "x$TLDFLAGS_SHLIB" = "x" ]; then
    +        echo "LDFLAGS_SHLIB=$LDFLAGS_SHLIB" >> Makefile.config
    +    fi
    +    if [ "x$TLDFLAGS_SHLIB_EXPORT" = "x" ]; then
    +        echo "LDFLAGS_SHLIB_EXPORT=$LDFLAGS_SHLIB_EXPORT" >> Makefile.config
    +    fi
    +fi
    +
    +####################################################################
    +## Some OS-related stuff for the DSO mechanism:
    +## Finding the vendor DSO functions
    +##
    +if [ "x$using_shlib" = "x1" ] ; then
    +    DL_LIB=""
    +    case $PLAT in
    +        *-ibm-aix* )
    +            DL_LIB="-lld"
    +            ;;
    +        * )
    +            if ./helpers/TestCompile func dlopen; then
    +                :
    +            else
    +                if ./helpers/TestCompile lib dl; then
    +                    DL_LIB="-ldl"
    +                fi
    +            fi
    +            ;;
    +    esac
    +    if [ ".$DL_LIB" != . ]; then
    +        LIBS="$LIBS $DL_LIB"
    +        echo " + using $DL_LIB for vendor DSO support"
    +    fi
    +fi
    +
    +####################################################################
    +## Now we do some OS specific adjustments... for some OSs, we need
    +## to adjust CFLAGS and/or OPTIM depending on which compiler we
    +## are going to use. This is easy, since this can be gleamed from
    +## Makefile.config
    +##
    +case "$OS" in
    +    'ULTRIX')
    +	case "$CC" in
    +	    */cc|cc ) CFLAGS="$CFLAGS -std" ;;
    +	esac
    +	;;
    +    'SCO 5')
    +	case "$CC" in
    +	    */cc|cc ) CFLAGS="$CFLAGS -K noinline" ;;
    +	esac
    +	;;
    +    'HI-UX')
    +	case "$CC" in
    +	    */cc|cc )
    +		CFLAGS="$CFLAGS -Aa -D_HIUX_SOURCE"
    +		OPTIM=" "
    +		TOPTIM=""
    +	    ;;
    +	esac
    +	;;
    +    'HP-UX'|'HP-UX 10'|'HP-UX 11')
    +	case "$CC" in
    +	    */cc|cc )
    +		CFLAGS="$CFLAGS -Aa -D_HPUX_SOURCE"
    +		OPTIM=" "
    +		TOPTIM=""
    +	    ;;
    +	esac
    +	;;
    +    *IRIX-64*)
    +	case "$CC" in
    +	    */cc|cc )
    +		CFLAGS="$CFLAGS -n32"
    +		LDFLAGS="$LDFLAGS -n32"
    +	    ;;
    +	esac
    +	;;
    +    *IRIX-32*)
    +	case "$CC" in
    +	    */cc|cc )
    +		CFLAGS="$CFLAGS -n32"
    +		LDFLAGS="$LDFLAGS -n32"
    +	    ;;
    +	esac
    +	;;
    +    IBM?AIX?4.[123])
    +	case $CC in
    +	    */cc|cc ) 
    +		CFLAGS="$CFLAGS -qnogenpcomp -qnousepcomp"
    +	    ;;
    +	esac
    +	;;
    +esac
    +
    +####################################################################
    +## OK, now we can write OPTIM
    +##
    +if [ "x$TOPTIM" = "x" ]; then
    +    echo "OPTIM=$OPTIM" >> Makefile.config
    +fi
    +
    +####################################################################
    +## Now we do some general checks and some intelligent Configuration
    +## control.
    +
    +# Use TestCompile to look for various LIBS
    +case "$PLAT" in
    +    *-linux*)
    +	# newer systems using glibc 2.x need -lcrypt
    +	if ./helpers/TestCompile lib crypt; then
    +	    LIBS="$LIBS -lcrypt"
    +	fi
    +	;;
    +
    +    *-dg-dgux*)
    +	# R4.11MU02 requires -lsocket -lnsl ... no idea if it's earlier or
    +	# later than what we already knew about.  PR#732
    +	if ./helpers/TestCompile lib socket; then
    +	    LIBS="$LIBS -lsocket"
    +	fi
    +	if ./helpers/TestCompile lib nsl; then
    +	    LIBS="$LIBS -lnsl"
    +	fi
    +	;;
    +esac
    +
    +# SOCKS4 support:
    +# We assume that if they are using SOCKS4, then they've
    +# adjusted EXTRA_LIBS and/or EXTRA_LDFLAGS as required,
    +# otherwise we assume "-L/usr/local/lib -lsocks"
    +if [ "$RULE_SOCKS4" = "yes" ]; then
    +    echo " + enabling SOCKS4 support"
    +    CFLAGS="$CFLAGS -DSOCKS -DSOCKS4"
    +    CFLAGS="$CFLAGS -Dconnect=Rconnect -Dselect=Rselect"
    +    CFLAGS="$CFLAGS -Dgethostbyname=Rgethostbyname"
    +    if [ ".`grep EXTRA_ Makefile | grep lsocks`" = . ]; then
    +	LIBS="$LIBS -L/usr/local/lib -lsocks"
    +    fi
    +    case $PLAT in
    +        *-solaris2* )
    +            LIBS="$LIBS -lresolv"
    +            ;;
    +    esac
    +fi
    +
    +# SOCKS5 support:
    +# We assume that if they are using SOCKS5, then they've
    +# adjusted EXTRA_LIBS and/or EXTRA_LDFLAGS as required,
    +# otherwise we assume "-L/usr/local/lib -lsocks5"
    +if [ "$RULE_SOCKS5" = "yes" ]; then
    +    echo " + enabling SOCKS5 support"
    +    CFLAGS="$CFLAGS -DSOCKS -DSOCKS5"
    +    CFLAGS="$CFLAGS -Dconnect=SOCKSconnect -Dselect=SOCKSselect"
    +    CFLAGS="$CFLAGS -Dgethostbyname=SOCKSgethostbyname -Dclose=SOCKSclose"
    +    if [ ".`grep EXTRA_ Makefile | grep lsocks5`" = . ]; then
    +        LIBS="$LIBS -L/usr/local/lib -lsocks5"
    +    fi
    +    case $PLAT in
    +        *-solaris2* )
    +            LIBS="$LIBS -lresolv"
    +            ;;
    +    esac
    +fi
    +
    +####################################################################
    +## Find out what modules we want and try and configure things for them
    +## Module lines can look like this:
    +##
    +##  Module  name_module    some/path/mod_name[.[oa]]
    +##  AddModule              some/path/mod_name[.[oa]]
    +##
    +## In both cases, the some/path can either be an arbitrary path (including
    +## an absolute path), or a path like "modules/DIR", in which case we _might_
    +## auto-generate a Makefile in modules/DIR (see later).
    +##
    +## The first case is the original style, where we give the module's
    +## name as well as it's binary file location - either a .o or .a.
    +##
    +## The second format is new, and means we do not repeat the module
    +## name, which is already part of the module source or definition.
    +## The way we find the module name (and other optional information about
    +## the module) is like this:
    +##
    +##  1 If extension is not given or is .c, assume .o was given and goto 3
    +##  2 If extension if .module, go to D1
    +##  3 If extension is .o, look for a corresponding .c file and if
    +##      found, go to C1
    +##  4 If no .c file was found, look for a .module file (Apache module
    +##      definition file). If found, go to D1
    +##  5 Assume module name is the "name" part of "mod_name", as in
    +##      name_module.
    +##
    +## If a C file is found:
    +##
    +## C1 Look for module name given by an MODULE: line (e.g. MODULE: name_module)
    +##      If found assume module contains a definition, and go to D1
    +## C2 If not found, look for a module name given on the declaration of the
    +##      module structure (e.g. module name_module).
    +## C3 If neither given, go to 4 above.
    +##
    +## If a definition file is found, or a .c file includes a module definition:
    +##
    +## D1 Get the module name from the MODULE: name= line
    +## D2 Get other module options (libraries etc). To be done later.
    +##
    +##
    +## For now, we will convert the AddModule lines into Module format
    +## lines, so the rest of Configure can do its stuff without too much
    +## additional hackery. It would be nice to reduce the number of times
    +## we have to awk the $tmpfile, though.
    +
    +## MODFILES contains a list of module filenames (could be .c, .o, .so, .a
    +##    or .module files) from AddModule lines only
    +## MODDIRS contains a list of subdirectories under 'modules' which
    +##    contain modules we want to build from both AddModule and Module
    +##    lines
    +
    +echo " + adding selected modules"
    +
    +MODFILES=`awk <$tmpfile '($1 == "AddModule" || $1 == "SharedModule") { printf "%s ", $2 }'`
    +MODDIRS=`awk < $tmpfile '
    +	($1 == "Module" && $3 ~ /^modules\//) {
    +	    split ($3, pp, "/")
    +	    if (! SEEN[pp[2]]) {
    +		printf "%s ", pp[2]
    +		SEEN[pp[2]] = 1
    +	    }
    +    	}
    +	(($1 == "AddModule" || $1 == "SharedModule") && $2 ~ /^modules\//) { 
    +	    split ($2, pp, "/")
    +	    if (! SEEN[pp[2]]) {
    +		printf "%s ", pp[2]
    +		SEEN[pp[2]] = 1
    +	    } 
    +    	}'`
    +MODDIRS_NO_SO=`awk < $tmpfile '
    +	($1 == "Module" && $3 ~ /^modules\//) {
    +	    split ($3, pp, "/")
    +	    if (! SEEN[pp[2]]) {
    +		printf "%s ", pp[2]
    +		SEEN[pp[2]] = 1
    +	    }
    +    	}
    +	(($1 == "AddModule") && $2 ~ /^modules\//) { 
    +	    split ($2, pp, "/")
    +	    if (! SEEN[pp[2]]) {
    +		printf "%s ", pp[2]
    +		SEEN[pp[2]] = 1
    +	    } 
    +    	}'`
    +
    +# Now autoconfigure each of the modules specified by AddModule.
    +# Use tmpfile2 for the module definition file, and tmpfile3 for the
    +# shell commands to be executed for this module.
    +
    +for modfile in $MODFILES ; do
    +	rm -f $tmpfile2 $tmpfile3
    +	modname=''
    +
    +	ext=`echo $modfile | sed 's/^.*\.//'`
    +	modbase=`echo $modfile | sed 's/\.[^.]*$//'`
    +	if [ x$ext = x$modfile ]; then ext=o; modbase=$modfile; modfile=$modbase.o; fi
    +	if [ x$ext = x ] ; then ext=o; modbase=$modfile; fi
    +	if [ x$ext = xc ] ; then ext=o; fi
    +
    +	# modbase is the path+filename without extension, ext is the
    +	# extension given, or if none, o
    +	if [ -r $modbase.module ] ; then
    +		$CAT $modbase.module > $tmpfile2
    +	else
    +	    if [ -f $modbase.c ] ; then
    +		# Guess module structure name in case there is not
    +		# module definition in this file
    +		modname=`egrep '^module .*;' $modbase.c | head -1 |\
    +			sed 's/^module.*[ 	][ 	]*//' | \
    +			sed 's/[ 	]*;[ 	]*$//'`
    +		# Get any module definition part
    +		if grep "MODULE-DEFINITION-" $modbase.c > /dev/null; then
    +		$CAT $modbase.c | \
    +		sed '1,/MODULE-DEFINITION-START/d;/MODULE-DEFINITION-END/,$d' \
    +			> $tmpfile2
    +		fi
    +	    fi
    +	fi		
    +	if [ -r $tmpfile2 ] ; then
    +		# Read a module definition from .module or .c
    +		modname=`grep "Name:" $tmpfile2 | sed 's/^.*Name:[ 	]*//'`
    +		if grep "ConfigStart" $tmpfile2 > /dev/null \
    +		 && grep "ConfigEnd" $tmpfile2 > /dev/null; then
    +		    sed '1,/ConfigStart/d;/ConfigEnd/,$d' $tmpfile2 > \
    +		     $tmpfile3
    +		    echo "    o $modname uses ConfigStart/End"
    +		    if [ "$RULE_PARANOID" = "yes" ]; then
    +			sed 's/^/>> /' $tmpfile3
    +		    fi
    +		    . ./$tmpfile3
    +		fi
    +		rm -f $tmpfile2 $tmpfile3
    +		if [ $ext != so ]; then
    +		    ext=o
    +		fi
    +	fi
    +	if [ "x$modname" = "x" ] ; then
    +		modname=`echo $modbase | sed 's/^.*\///' | \
    +			sed 's/^mod_//' | sed 's/^lib//' | sed 's/$/_module/'`
    +	fi
    +	if [ $ext != so ]; then
    +		echo "Module $modname $modbase.$ext" >>$tmpfile
    +	fi
    +	#   optionally generate export file for some linkers 
    +	if [ $ext = so -a .$SHLIB_EXPORT_FILES = .yes ]; then
    +		echo "$modname" >$modbase.exp
    +	fi
    +done
    +# $tmpfile now contains Module lines for all the modules we want
    +
    +####################################################################
    +## Now HS's POSIX regex implementation if needed/wanted. We do it
    +## now since AddModule may have changed it
    +##
    +if [ "$RULE_WANTHSREGEX" = "yes" ]; then
    +    REGLIB="regex/libregex.a"
    +    SUBDIRS="regex $SUBDIRS"
    +    CFLAGS="$CFLAGS -DUSE_HSREGEX"
    +fi
    +
    +####################################################################
    +## Now the SHARED_CORE stuff
    +##
    +if [ "x$using_shlib" = "x1" ] ; then
    +    if [ ".$RULE_SHARED_CORE" = .default ] ; then
    +        RULE_SHARED_CORE=$DEF_SHARED_CORE
    +    fi
    +    if [ ".$RULE_SHARED_CORE" = .yes ]; then
    +    echo " + enabling generation of Apache core as DSO"
    +        #    shuffle compiler flags from shlib variant to standard
    +        CFLAGS="$CFLAGS $CFLAGS_SHLIB"
    +        CFLAGS_SHLIB=""
    +        #    indicate that Rule SHARED_CORE is active
    +        CFLAGS="$CFLAGS -DSHARED_CORE"
    +        #    select the special subtarget for shared core generation
    +        SUBTARGET=target_shared
    +        #    determine additional suffixes for libhttpd.so
    +        V=1 R=3 P=0
    +        if [ ".$SHLIB_SUFFIX_DEPTH" = .0 ]; then
    +            SHLIB_SUFFIX_LIST=""
    +        fi
    +        if [ ".$SHLIB_SUFFIX_DEPTH" = .1 ]; then
    +            SHLIB_SUFFIX_LIST="$V"
    +        fi
    +        if [ ".$SHLIB_SUFFIX_DEPTH" = .2 ]; then
    +            SHLIB_SUFFIX_LIST="$V.$R"
    +        fi
    +        if [ ".$SHLIB_SUFFIX_DEPTH" = .3 ]; then
    +            SHLIB_SUFFIX_LIST="$V.$R.$P"
    +        fi
    +        if [ ".$SHLIB_SUFFIX_DEPTH" = .all ]; then
    +            SHLIB_SUFFIX_LIST="$V $V.$R $V.$R.$P"
    +        fi
    +    fi
    +fi
    +
    +####################################################################
    +## Now create modules.c
    +##
    +sed 's/_module//' $tmpfile | awk >modules.c '
    +    BEGIN {
    +	modules[n++] = "core"
    +	pmodules[pn++] = "core"
    +    } 
    +    /^Module/ { modules[n++] = $2 ; pmodules[pn++] = $2 } 
    +    /^%Module/ { pmodules[pn++] = $2 } 
    +    END {
    +	print "/*"
    +	print " * modules.c --- automatically generated by Apache"
    +	print " * configuration script.  DO NOT HAND EDIT!!!!!"
    +	print " */"
    +	print ""
    +	print "#include \"httpd.h\""
    +	print "#include \"http_config.h\""
    +	print ""
    +	for (i = 0; i < pn; ++i) {
    +	    printf ("extern module %s_module;\n", pmodules[i])
    +	}
    +	print ""
    +	print "/*"
    +	print " *  Modules which implicitly form the"
    +	print " *  list of activated modules on startup,"
    +	print " *  i.e. these are the modules which are"
    +	print " *  initially linked into the Apache processing"
    +	print " *  [extendable under run-time via AddModule]"
    +	print " */"
    +	print "module *ap_prelinked_modules[] = {"
    +	for (i = 0; i < n; ++i) {
    +	    printf "  &%s_module,\n", modules[i]
    +	}
    +	print "  NULL"
    +	print "};"
    +	print ""
    +	print "/*"
    +	print " *  Modules which initially form the"
    +	print " *  list of available modules on startup,"
    +	print " *  i.e. these are the modules which are"
    +	print " *  initially loaded into the Apache process"
    +	print " *  [extendable under run-time via LoadModule]"
    +	print " */"
    +	print "module *ap_preloaded_modules[] = {"
    +	for (i = 0; i < pn; ++i) {
    +	    printf "  &%s_module,\n", pmodules[i]
    +	}
    +	print "  NULL"
    +	print "};"
    +	print ""
    +    }'
    +
    +####################################################################
    +## figure out which module dir require use to autocreate a Makefile.
    +## for these dirs we must not list the object files from the AddModule
    +## lines individually since the auto-generated Makefile will create
    +## a library called libMODDIR.a for it (MODDIR is the module dir
    +## name). We create two variable here:
    +##
    +##   AUTODIRS   Space separated list of module directories, relative to
    +##              src
    +##   AUTOLIBS   Space separated list of auto-generated library files
    +##
    +for moddir in $MODDIRS 
    +do
    +	if [ -f modules/$moddir/Makefile.tmpl ] ; then
    +		AUTODIRS="$AUTODIRS modules/$moddir"
    +	fi
    +done
    +for moddir in $MODDIRS_NO_SO
    +do
    +	if [ -f modules/$moddir/Makefile.tmpl ] ; then
    +		AUTOLIBS="$AUTOLIBS modules/$moddir/lib$moddir.a"
    +	fi
    +done
    +
    +####################################################################
    +## Add the module targets to the Makefile. Do not add individual object
    +## targets for auto-generated directories.
    +##
    +$CAT > $awkfile <<EOF1
    +    BEGIN {
    +	split ("$AUTODIRS", tmp, " ")
    +EOF1
    +$CAT >> $awkfile <<'EOF2'
    +	for ( key in tmp ) {
    +	    autodirs[tmp[key]] = 1
    +	}
    +     }
    +    /^Module/ { modules[n++] = $3 }
    +    /^%Module/ { modules[n++] = $3 }
    +    END {
    +	print "MODULES= \\"
    +	for (i = 0; i < n; ++i) {
    +	    split (modules[i], pp, "/")
    +	    dir = pp[1] "/" pp[2] 
    +	    inthere = 0
    +	    for ( tdir in autodirs ) {
    +	        if (tdir == dir) 
    +		    inthere = 1
    +	    }
    +	    if (inthere == 1)
    +		continue
    +	    else
    +		printf ("  %s \\\n", modules[i])
    +	}
    +    }
    +EOF2
    +awk -f $awkfile >>Makefile <$tmpfile
    +
    +####################################################################
    +## Now add the auto-generated library targets.  Need to use awk so we
    +## don't hang a continuation on the last line.
    +##
    +$CAT > $awkfile <<'EOF4'
    +    {
    +	z = 0
    +	split ($0, libs)
    +	for ( lib in libs ) {
    +	    if (z != 0)
    +		printf (" \\\n")
    +	    z++
    +	    printf ("  %s", libs[lib])
    +	}
    +    }
    +    END {
    +	printf ("\n")
    +    }
    +EOF4
    +echo "$AUTOLIBS" | awk -f $awkfile >>Makefile
    +echo "" >>Makefile
    +
    +####################################################################
    +## Now add the target for the main Makefile
    +##
    +echo "TARGET=$TARGET" >> Makefile
    +echo "SUBDIRS=$SUBDIRS" >> Makefile
    +echo "SUBTARGET=$SUBTARGET" >> Makefile
    +echo "SHLIB_SUFFIX_LIST=$SHLIB_SUFFIX_LIST" >> Makefile
    +echo "" >> Makefile
    +
    +####################################################################
    +## Now add -DSERVER_SUBVERSION if $SUBVERSION is set
    +##
    +if [ "x$SUBVERSION" != "x" ] ; then
    +        SUBVERSION=`echo $SUBVERSION | sed 's/^ +//'`
    +	CFLAGS="$CFLAGS -DSERVER_SUBVERSION=\\\"$SUBVERSION\\\""
    +fi
    +
    +####################################################################
    +## Determine GNU Make variant because
    +## it uses ugly looking built-in directory walk messages
    +## while we are already using our own messages
    +##
    +if [ ".`make -v 2>/dev/null | grep 'GNU Make'`" = . ]; then
    +	MFLAGS_STATIC=
    +else
    +	MFLAGS_STATIC=--no-print-directory
    +fi
    +
    +####################################################################
    +## Continue building Makefile.config.
    +##
    +echo "CFLAGS1=$CFLAGS">> Makefile.config
    +echo "OSDIR=\$(SRCDIR)/$OSDIR">> Makefile.config
    +echo "INCDIR=\$(SRCDIR)/include" >>Makefile.config
    +echo "INCLUDES0=-I\$(OSDIR) -I\$(INCDIR)">> Makefile.config
    +echo "INCLUDES1=$INCLUDES">> Makefile.config
    +echo "LIBS1=$LIBS">> Makefile.config
    +echo "LDFLAGS1=$LDFLAGS">> Makefile.config
    +echo "MFLAGS_STATIC=$MFLAGS_STATIC">> Makefile.config
    +echo "REGLIB=$REGLIB">> Makefile.config
    +echo "RANLIB=$RANLIB">> Makefile.config
    +echo "SHELL=$SHELL">> Makefile.config
    +echo "##" >> Makefile.config
    +echo "##  (End of automatically generated section)">> Makefile.config
    +echo "##" >> Makefile.config
    +echo "" >> Makefile.config
    +
    +####################################################################
    +## Continue building include/ap_config.h
    +##
    +## We pick out all -D's from CFLAGS and create ap_config.h which
    +## can be used by external modules needing to include Apache
    +## header files.
    +##
    +for cflag in $CFLAGS; do
    +	echo $cflag | sed 's/\\\"/\"/g' >>$tmpconfig ;
    +done
    +awk > include/ap_config.h < $tmpconfig '
    +	BEGIN {
    +		printf "/* Automatically generated file - do not edit */\n\n"
    +	}
    +	/^-D.*/ {
    +		define = substr($1, 3, length($1)-2)
    +		split(define, parts, "=")
    +		printf ("#ifndef %s\n#define %s %s\n#endif\n", parts[1],parts[1],parts[2])
    +	}
    +'
    +
    +####################################################################
    +## Use TestCompile to see if $(CC) is ANSI and as a "final" sanity
    +## check
    +##
    +echo " + doing sanity check on compiler and options"
    +if ./helpers/TestCompile sanity; then
    +    :
    +else
    +   echo "** A test compilation with your Makefile configuration"
    +   echo "** failed. This is most likely because your C compiler"
    +   echo "** is not ANSI. Apache requires an ANSI C Compiler, such"
    +   echo "** as gcc. The above error message from your compiler"
    +   echo "** will also provide a clue."
    +   echo " Aborting!"
    +   exitcode=1
    +   exit 1
    +fi
    +
    +####################################################################
    +## Now (finish) creating the makefiles
    +##
    +
    +# ./Makefile
    +$CAT Makefile.config >> Makefile
    +sed -e "s#@@Configuration@@#$file#" "Makefile.tmpl" >>Makefile
    +
    +# xxx/Makefile
    +MAKEDIRS="support main ap regex $OSDIR"
    +for dir in $MAKEDIRS ; do
    +	echo Creating Makefile in $dir
    +	./helpers/mfhead $dir $file > $dir/Makefile
    +	$CAT Makefile.config $dir/Makefile.tmpl |\
    +	sed -e "s:^SRCDIR=.*:SRCDIR=`./helpers/fp2rp $dir`:" >> $dir/Makefile
    +done
    +
    +####################################################################
    +## Now create the modules/Makefile
    +##
    +./helpers/mfhead modules $file > modules/Makefile
    +$CAT Makefile.config | sed -e 's:^SRCDIR=.*:SRCDIR=..:' >> modules/Makefile
    +
    +$CAT << EOF >> modules/Makefile
    +MODULES=$MODDIRS
    +CFLAGS=\$(OPTIM) \$(CFLAGS1) \$(EXTRA_CFLAGS)
    +
    +default: all
    +
    +all clean distclean depend :: 
    +	@for i in \$(MODULES); do \\
    +	    echo "===> \$(SDP)modules/\$\$i"; \\
    +		(cd \$\$i && \$(MAKE) \$(MFLAGS_STATIC) SDP='\$(SDP)' CC='\$(CC)' AUX_CFLAGS='\$(CFLAGS)' RANLIB='\$(RANLIB)' \$@) || exit 1; \\
    +		echo "<=== \$(SDP)modules/\$\$i"; \\
    +	done
    +
    +EOF
    +
    +####################################################################
    +## Now create modules/xxx/Makefile
    +##
    +for moddir in $AUTODIRS ; do
    +	echo "Creating Makefile in $moddir"
    +
    +    ./helpers/mfhead $moddir $file > $moddir/Makefile
    +	$CAT Makefile.config |\
    +	sed -e "s:^SRCDIR=.*:SRCDIR=`./helpers/fp2rp $moddir`:" >> $moddir/Makefile
    +	$CAT << 'EOF' >> $moddir/Makefile
    +##
    +##  Default Makefile options from Configure script
    +##  (Begin of automatically generated section)
    +##
    +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
    +LIBS=$(EXTRA_LIBS) $(LIBS1)
    +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
    +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
    +INCDIR=$(SRCDIR)/include
    +EOF
    +	if [ -f $moddir/Makefile.libdir ]; then
    +	    basedir=`echo $moddir | sed 's@^[^/]*/@@g'`
    +	    awk >> $moddir/Makefile < $tmpfile '
    +		($2 ~ /^modules\/'$basedir'\//) {
    +		    split($2, pp, "/");
    +		    split(pp[3], parts, ".");
    +		    libext=parts[2];
    +		}
    +		END { 
    +		    printf "LIBEXT=%s\n", libext;
    +		}'
    +	    # it's responsible for the rest of its Makefile...
    +	else
    +	    basedir=`echo $moddir | sed 's@^[^/]*/@@g'`
    +	    OBJS=`awk < $tmpfile '
    +		($1 == "Module" && $3 ~ /^modules\/'$basedir'\//) { 
    +		    split ($3, pp, "/")
    +		    printf "%s ", pp[3] 
    +		} 
    +		'`
    +	    echo "OBJS=$OBJS" >> $moddir/Makefile
    +	    if [ ".$OBJS" != . ]; then
    +		echo "LIB=lib$basedir.a" >> $moddir/Makefile
    +	    else
    +		#   essential!
    +		echo "LIB=" >> $moddir/Makefile
    +	    fi
    +	    awk >> $moddir/Makefile < $tmpfile '
    +	    ($1 == "SharedModule" && $2 ~ /^modules\/'$basedir'\//) {
    +		split($2, pp, "/")
    +		shlibs=shlibs " " pp[3]
    +		so=pp[3]
    +		split(pp[3], parts, ".")
    +		base=parts[1]
    +		objspic=objspic " " base ".lo"
    +	    }
    +	    END { 
    +		printf "SHLIBS=%s\n", shlibs;
    +		printf "OBJS_PIC=%s\n", objspic;
    +            }'
    +
    +	    $CAT << 'EOF' >> $moddir/Makefile
    +
    +all: lib shlib
    +
    +lib:	$(LIB) 
    +
    +shlib:	$(SHLIBS)
    +
    +$(LIB): $(OBJS)
    +	rm -f $@
    +	ar cr $@ $(OBJS)
    +	$(RANLIB) $@
    +
    +.SUFFIXES: .o .so
    +
    +.c.o:
    +	$(CC) -c $(INCLUDES) $(CFLAGS) $<
    +
    +.c.so:
    +	$(CC) -c $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $< && mv $*.o $*.lo
    +	$(LD_SHLIB) $(LDFLAGS_SHLIB) -o $@ $*.lo
    +
    +clean:
    +	rm -f $(LIB) $(OBJS) $(SHLIBS) $(OBJS_PIC)
    +
    +distclean: clean
    +	rm -f Makefile
    +
    +#   NOT FOR END USERS!
    +depend:
    +	cp Makefile.tmpl Makefile.tmpl.bak \
    +	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
    +	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
    +	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
    +	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
    +		> Makefile.tmpl \
    +	    && rm Makefile.new
    +
    +EOF
    +	fi
    +
    +	$CAT << 'EOF' >> $moddir/Makefile
    +##
    +##  (End of automatically generated section)
    +##
    +EOF
    +    $CAT >> $moddir/Makefile < $moddir/Makefile.tmpl
    +
    +done
    +
    diff --git a/APACHE_1_3b7/src/INDENT b/APACHE_1_3b7/src/INDENT
    new file mode 100644
    index 0000000000..9f02cc3b09
    --- /dev/null
    +++ b/APACHE_1_3b7/src/INDENT
    @@ -0,0 +1,140 @@
    +This is the current status of running indent on the source code.
    +If you are about to edit a file, mark it as RESERVED below with your name.
    +If a file has already been indent'd, or doesn't need it, mark it as DONE.
    +AND don't forget to run expand on the file after it has been indent'd.
    +
    +./main:				STATUS
    +   alloc.c			DONE by Dean
    +   alloc.h			DONE by Dean
    +   buff.c			DONE by Dean
    +   buff.h			DONE by Dean
    +   conf.h			DONE by Dean
    +   dummy.c			DONE by Dean
    +   explain.c			DONE by Dean
    +   explain.h			DONE by Dean
    +   fnmatch.c			DONE by Dean
    +   fnmatch.h			DONE by Dean
    +   http_bprintf.c		DONE by Dean
    +   http_conf_globals.h		DONE by Dean
    +   http_config.c		DONE by Dean
    +   http_config.h		DONE by Dean
    +   http_core.c			RESERVED by Randy
    +   http_core.h			RESERVED by Randy
    +   http_log.c			RESERVED by Randy
    +   http_log.h			RESERVED by Randy
    +   http_main.c			DONE by Dean
    +   http_main.h			DONE by Dean
    +   http_protocol.c		DONE by Roy
    +   http_protocol.h		DONE by Roy
    +   http_request.c		DONE by Roy
    +   http_request.h		DONE by Roy
    +   httpd.h			DONE by Dean
    +   md5.h			DONE by Dean
    +   md5c.c			DONE by Dean
    +   multithread.h		DONE by Dean
    +   rfc1413.c			DONE by Dean
    +   rfc1413.h			DONE by Dean
    +   scoreboard.h			DONE by Dean
    +   util.c			DONE by Randy
    +   util_date.c			DONE by Randy
    +   util_date.h			DONE by Randy
    +   util_md5.c			DONE by Randy
    +   util_md5.h			DONE by Randy
    +   util_script.c		DONE by Randy
    +   util_script.h		DONE by Randy
    +   util_snprintf.c		DONE by Randy
    +
    +./modules/example:
    +   mod_example.c		DONE by Ken
    +
    +./modules/proxy:
    +   mod_proxy.c			DONE by Dean
    +   mod_proxy.h			DONE by Dean
    +   proxy_cache.c		DONE by Dean
    +   proxy_connect.c		DONE by Dean
    +   proxy_ftp.c			DONE by Dean
    +   proxy_http.c			DONE by Dean
    +   proxy_util.c			DONE by Dean
    +
    +./modules/standard:
    +   mod_access.c			DONE by Dean
    +   mod_actions.c		DONE by Dean
    +   mod_alias.c			DONE by Dean
    +   mod_asis.c			DONE by Dean
    +   mod_auth.c			DONE by Dean
    +   mod_auth_anon.c		DONE by Dean
    +   mod_auth_db.c		DONE by Dean
    +   mod_auth_dbm.c		DONE by Dean
    +   mod_autoindex.c		DONE by Dean
    +   mod_cern_meta.c		DONE by Dean
    +   mod_cgi.c			DONE by Dean
    +   mod_digest.c			DONE by Dean
    +   mod_dir.c			DONE by Brian
    +   mod_dld.c			DONE by Brian
    +   mod_env.c			DONE by Brian
    +   mod_expires.c		DONE by Brian
    +   mod_headers.c		DONE by Brian
    +   mod_imap.c			DONE by Brian
    +   mod_include.c		DONE by Brian
    +   mod_info.c			DONE by Ken
    +   mod_log_agent.c		DONE by Brian
    +   mod_log_config.c		DONE by Ken
    +   mod_log_referer.c		DONE by Brian
    +   mod_mime.c			DONE by Brian
    +   mod_mime.h			DONE by Brian
    +   mod_mime_magic.c		DONE by Brian
    +   mod_negotiation.c		DONE by Ken
    +   mod_rewrite.c                DONE by Roy & Ralf
    +   mod_rewrite.h                DONE by Roy
    +   mod_setenvif.c		DONE by Ken
    +   mod_speling.c		DONE by Brian
    +   mod_status.c			DONE by Dean
    +   mod_unique_id.c		DONE by Brian
    +   mod_userdir.c		DONE by Brian
    +   mod_usertrack.c		DONE by Brian
    +
    +./os/unix:
    +   os-inline.c
    +   os.c
    +   os.h
    +
    +./os/win32:
    +   getopt.c
    +   getopt.h
    +   mod_dll.c
    +   mod_isapi.c
    +   modules.c
    +   multithread.c
    +   os.c
    +   os.h
    +   passwd.c
    +   passwd.h
    +   readdir.c
    +   readdir.h
    +   service.c
    +   service.h
    +   util_win32.c
    +
    +./regex:			(we are not doing this one, right?)
    +   cclass.h			DONE
    +   cname.h			DONE
    +   debug.c			DONE
    +   engine.c			DONE
    +   main.c			DONE
    +   regcomp.c			DONE
    +   regerror.c			DONE
    +   regex.h			DONE
    +   regex2.h			DONE
    +   regexec.c			DONE
    +   regfree.c			DONE
    +   split.c			DONE
    +   utils.h			DONE
    +
    +./support:
    +   cls.c			DONE by Randy
    +   htdigest.c			DONE by Randy
    +   htpasswd.c			DONE by Randy
    +   logresolve.c			DONE by Randy
    +   rotatelogs.c			DONE by Randy
    +   suexec.c			DONE by Randy
    +   suexec.h			DONE by Randy
    diff --git a/APACHE_1_3b7/src/INSTALL b/APACHE_1_3b7/src/INSTALL
    new file mode 100644
    index 0000000000..a39d37f925
    --- /dev/null
    +++ b/APACHE_1_3b7/src/INSTALL
    @@ -0,0 +1,169 @@
    +
    +  A P A C H E   I N S T A L L A T I O N
    +
    +  NOTE: Windows users please read the documents ../README.NT and
    +        http://www.apache.org/docs/windows.html, (or the
    +        htdocs/manual/windows.html file included with Apache).  
    +        The following applies only to Unix users.
    +
    +  Installing the Apache 1.3 HTTP server with APACI
    +  ================================================
    +
    +  For the out-of-the-box build and installation through the new Apache
    +  Autoconf-style Interface (APACI) see the file INSTALL in the parent
    +  directory. This document describes only the manual way of installing Apache.
    +
    +  Installing the Apache 1.3 HTTP server manually
    +  ==============================================
    +
    +  Unless you grabbed a binary distribution of Apache, you must compile it for
    +  your specific platform.  In order to compile it, you must set compile-time
    +  options (in particular, system type) for your system by editing a
    +  Configuration file, run a script which generates a Makefile and a small
    +  piece of C code, and then compile it.
    +
    +  Compilation
    +  -----------
    +
    +  Building the Apache Web server absolutely REQUIRES an ANSI C-compliant
    +  compiler.  If your compiler does not meet this requirement, don't even
    +  bother trying to build the server; it won't work.  The server may or may not
    +  build correctly with a C++ compiler.  Making it compilable with C++ is not a
    +  goal at this point, so if it doesn't work please use a normal ANSI C
    +  compiler instead.
    +
    +  This release of Apache supports the notion of "optional modules".  However,
    +  the server has to know which modules are compiled into it, in order for
    +  those modules to be effective; this requires generation of a short bit of
    +  code ("modules.c") which simply has a list of them.
    +
    +  It is also necessary to choose the correct options for your platform.
    +
    +  To do this:
    +
    +  1) Copy the file "Configuration.tmpl" to "Configuration" and then edit
    +     "Configuration".  This contains the list and settings of various "Rules"
    +     and an additional section at the bottom which lists the modules which
    +     have been compiled in, and also names the files containing them.  You
    +     will need to:
    +
    +     a) Adjust the Rules and EXTRA_CFLAGS|LIBS|LDFLAGS|INCLUDES if
    +        you feel so inclined.
    +
    +     b) Uncomment lines corresponding to those optional modules you wish to
    +        include (among the Module lines at the bottom of the file), or add new
    +        lines corresponding to custom modules you have written.  (See API.html
    +        for preliminary docs on how to do that).    
    +
    +     Note that DBM auth has to be explicitly configured in, if you want it ---
    +     just uncomment the corresponding line.
    +
    +  2) Run the "Configure" script:
    +
    +     $ ./Configure
    +     Using config file: Configuration
    +     Creating Makefile
    +      + configured for <whatever> platform
    +      + setting C compiler to <whatever>
    +      + Adding selected modules
    +      + doing sanity check on compiler and options
    +     Creating Makefile in support
    +     Creating Makefile in main
    +     Creating Makefile in os/unix
    +     Creating Makefile in modules/standard
    +     $ _
    +
    +     This generates new versions of the Makefiles and of modules.c.  (If you
    +     want to maintain multiple configurations, you can say, e.g.,
    +
    +     $ ./Configure -file Configuration.ai
    +     Using config file: Configuration.ai
    +     Creating Makefile
    +      + configured for <whatever> platform
    +      + setting C compiler to <whatever>
    +      + Adding selected modules
    +      + doing sanity check on compiler and options
    +     Creating Makefile in support
    +     Creating Makefile in main
    +     Creating Makefile in os/unix
    +     Creating Makefile in modules/standard
    +     $ _
    +
    +  3) Now compile the program:
    +  
    +     $ make
    +
    +  The modules we place in the Apache distribution are the ones we have tested
    +  and are used regularly by various members of the Apache development group.
    +  Additional modules contributed by members or third parties with specific
    +  needs or functions are available at
    +  http://www.apache.org/dist/contrib/modules/.  There are instructions
    +  on that page for linking these modules into the core Apache code.
    +
    +  If during compilation you get a warning about a missing 'regex.h', set
    +  WANTHSREGEX=yes in the 'Configuration', and let The Apache Group know you
    +  needed to do this for your OS by filling out a problem report form at
    +  http://bugs.apache.org/, or by sending a mail message to
    +  apache-bugs@apache.org. Include the output of the command "uname -a".
    +
    +  Installation
    +  ------------
    + 
    +  After compilation, you will have a binary called "httpd" in this src/
    +  directory.  If you received a binary distribution of apache, you should have
    +  this file already.
    +
    +  The next step is to edit the configuration files for the server.  In the
    +  top-level subdirectory called "conf" you should find distribution versions
    +  of the three configuration files: srm.conf-dist, access.conf-dist, and
    +  httpd.conf-dist.  Copy them to srm.conf, access.conf, httpd.conf
    +  respectively.
    +
    +  First edit httpd.conf.  This sets up general attributes about the server -
    +  the port number, the user it runs as, etc.  Next edit the srm.conf file -
    +  this sets up the root of the document tree, special functions like
    +  server-parsed HTML or internal imagemap parsing, etc.  Finally, edit the
    +  access.conf file to at least set the base cases of access. Documentation for
    +  all of these is located at http://www.apache.org/docs/.
    +
    +  Finally, make a call to httpd, with a -f to the full path to the httpd.conf
    +  file. I.e., the common case:
    +
    +    $ /usr/local/apache/httpd -f /usr/local/apache/conf/httpd.conf
    +
    +  And voila! The server should be running.
    +
    +  By default the srm.conf and access.conf files are located by name - to
    +  specifically call them by other names, use the AccessConfig and
    +  ResourceConfig directives in httpd.conf.
    +
    +  Set your system time properly!
    +
    +  Proper operation of a public web server requires accurate time
    +  keeping, since elements of the HTTP protocol are expressed as the time
    +  of day.  So, it's time to investigate setting up NTP or some other
    +  time synchronization system on your Unix box, or whatever the
    +  equivalent on NT would be.
    +
    +  Upgrading an Existing Apache Environment
    +  ----------------------------------------
    +
    +  Between releases of Apache, there are several files that are likely to get
    +  changed (aside from the source, of course).  These include:
    +
    +    src/Makefile.tmpl
    +    src/Configuration.tmpl
    +    src/Configure
    +    conf/*.conf-dist
    +    conf/mime.types
    +
    +  It's recommended that you unpack a new Apache version distribution into a
    +  different directory than the existing one, and check these files against the
    +  ones you already have for new or changed directives.  It's almost certain
    +  that the Configure, Configuration.tmpl, and Makefile.tmpl files are going to
    +  change, so pay particular attention to merging your existing Configuration
    +  settings with the ones in the Configuration.tmpl file to make a new
    +  Configuration file in the new Apache src directory.  Then follow the steps
    +  for a new installation to build and test the new server before replacing the
    +  existing Apache directory tree with the one from the new distribution.
    +
    diff --git a/APACHE_1_3b7/src/Makefile.nt b/APACHE_1_3b7/src/Makefile.nt
    new file mode 100644
    index 0000000000..8e2a874961
    --- /dev/null
    +++ b/APACHE_1_3b7/src/Makefile.nt
    @@ -0,0 +1,140 @@
    +# Makefile for Windows NT and Windows 95
    +
    +# Targets are:
    +#   _apacher   - build Apache in Release mode
    +#   _apached   - build Apache in Debug mode
    +#   installr   - build and install a Release build
    +#   installd   - build and install a Debug build
    +#   clean      - remove (most) generated files
    +#   _cleanr    - remove (most) files generated by a Release build
    +#   _cleand    - remove (most) files generated by a Debug build
    +#
    +# The default installation directory is \Apache. This can be changed
    +# with the INSTDIR macro, for example:
    +#
    +#   nmake /f Makefile.nt INSTDIR="d:\Program Files\Apache" installr
    +#
    +# Note: this does *NOT* change the compiled in default "server root"
    +
    +!IF "$(INSTDIR)" == ""
    +INSTDIR=\Apache
    +!MESSAGE Using default install directory \Apache
    +!ENDIF 
    +
    +default:	_apacher
    +
    +_release:
    +	set SHORT=R
    +	set LONG=Release
    +
    +_debug:
    +	set SHORT=D
    +	set LONG=Debug
    +
    +_apacher: _release _build
    +_apached: _debug   _build
    +installr: _release _build _install
    +installd: _debug   _build _install
    +_cleanr:  _release _clean
    +_cleand:  _debug   _clean
    +
    +clean:
    +	$(MAKE) /f Makefile.nt _cleanr
    +	$(MAKE) /f Makefile.nt _cleand
    +
    +installdll: _release _installdll
    +
    +_build:
    +#	echo LONG %LONG% SHORT %SHORT% x
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheOS - Win32 %LONG%" -f ApacheOS.mak
    +	cd ..\..
    +	cd regex
    +	 nmake /nologo CFG="regex - Win32 %LONG%" -f regex.mak
    +	cd ..
    +	cd ap
    +	 nmake /nologo CFG="ap - Win32 %LONG%" -f ap.mak
    +	cd ..
    +	cd main
    +	 nmake /nologo CFG="gen_uri_delims - Win32 %LONG%" -f gen_uri_delims.mak
    +	 nmake /nologo CFG="gen_test_char - Win32 %LONG%" -f gen_test_char.mak
    +	cd ..
    +	 -del Core%SHORT%\buildmark.obj
    +	 nmake /nologo CFG="ApacheCore - Win32 %LONG%" -f ApacheCore.mak
    +	 nmake /nologo CFG="Apache - Win32 %LONG%" -f Apache.mak
    +	cd os\win32
    +	 set CFG=ApacheModuleStatus - Win32 %LONG%
    +	 nmake /nologo CFG="ApacheModuleStatus - Win32 %LONG%" -f ApacheModuleStatus.mak
    +#	 nmake /nologo CFG ""/nologo -f ApacheModuleStatus.mak"=ApacheModuleInfo - Win32 %LONG%" -f ApacheModuleInfo.mak
    +	 nmake /nologo CFG="ApacheModuleAuthAnon - Win32 %LONG%" -f ApacheModuleAuthAnon.mak
    +	 nmake /nologo CFG="ApacheModuleDigest - Win32 %LONG%" -f ApacheModuleDigest.mak
    +	 nmake /nologo CFG="ApacheModuleCERNMeta - Win32 %LONG%" -f ApacheModuleCERNMeta.mak
    +	 nmake /nologo CFG="ApacheModuleExpires - Win32 %LONG%" -f ApacheModuleExpires.mak
    +	 nmake /nologo CFG="ApacheModuleHeaders - Win32 %LONG%" -f ApacheModuleHeaders.mak
    +	 nmake /nologo CFG="ApacheModuleSpeling - Win32 %LONG%" -f ApacheModuleSpeling.mak
    +	 nmake /nologo CFG="ApacheModuleUserTrack - Win32 %LONG%" -f ApacheModuleUserTrack.mak
    +	 nmake /nologo CFG="ApacheModuleRewrite - Win32 %LONG%" -f ApacheModuleRewrite.mak
    +	cd ..\..
    +	cd modules\proxy
    +	 nmake /nologo CFG="ApacheModuleProxy - Win32 %LONG%" -f ApacheModuleProxy.mak
    +	cd ..\..
    +
    +_install:
    +	-mkdir $(INSTDIR)
    +	-mkdir $(INSTDIR)\modules
    +	-mkdir $(INSTDIR)\logs
    +	-mkdir $(INSTDIR)\conf
    +	copy Apache%SHORT%\Apache.exe $(INSTDIR)
    +	copy Core%SHORT%\ApacheCore.dll $(INSTDIR)
    +	copy os\win32\ApacheModuleStatus%SHORT%\ApacheModuleStatus.dll $(INSTDIR)\modules
    +#       copy os\win32\ApacheModuleInfo%SHORT%\ApacheModuleInfo.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleAuthAnon%SHORT%\ApacheModuleAuthAnon.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleDigest%SHORT%\ApacheModuleDigest.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleCERNMeta%SHORT%\ApacheModuleCERNMeta.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleExpires%SHORT%\ApacheModuleExpires.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleHeaders%SHORT%\ApacheModuleHeaders.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleRewrite%SHORT%\ApacheModuleRewrite.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleSpeling%SHORT%\ApacheModuleSpeling.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleUserTrack%SHORT%\ApacheModuleUserTrack.dll $(INSTDIR)\modules
    +	copy modules\proxy\%LONG%\ApacheModuleProxy.dll $(INSTDIR)\modules
    +
    +_clean:
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheOS - Win32 %LONG%" -f ApacheOS.mak clean
    +	cd ..\..
    +	cd regex
    +	 nmake /nologo CFG="regex - Win32 %LONG%" -f regex.mak clean
    +	cd ..
    +	cd ap
    +	 nmake /nologo CFG="ap - Win32 %LONG%" -f ap.mak clean
    +	cd ..
    +	cd main
    +	 nmake /nologo CFG="gen_uri_delims - Win32 %LONG%" -f gen_uri_delims.mak clean
    +	 del uri_delims.h
    +	 nmake /nologo CFG="gen_test_char - Win32 %LONG%" -f gen_test_char.mak clean
    +	 del test_char.h
    +	cd ..
    +	 nmake /nologo CFG="ApacheCore - Win32 %LONG%" -f ApacheCore.mak clean
    +	 nmake /nologo CFG="Apache - Win32 %LONG%" -f Apache.mak clean
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheModuleStatus - Win32 %LONG%" -f ApacheModuleStatus.mak clean
    +#	 nmake /nologo CFG="ApacheModuleInfo - Win32 %LONG%" -f ApacheModuleInfo.mak clean
    +	 nmake /nologo CFG="ApacheModuleAuthAnon - Win32 %LONG%" -f ApacheModuleAuthAnon.mak clean
    +	 nmake /nologo CFG="ApacheModuleDigest - Win32 %LONG%" -f ApacheModuleDigest.mak clean
    +	 nmake /nologo CFG="ApacheModuleCERNMeta - Win32 %LONG%" -f ApacheModuleCERNMeta.mak clean
    +	 nmake /nologo CFG="ApacheModuleExpires - Win32 %LONG%" -f ApacheModuleExpires.mak clean
    +	 nmake /nologo CFG="ApacheModuleHeaders - Win32 %LONG%" -f ApacheModuleHeaders.mak clean
    +	 nmake /nologo CFG="ApacheModuleSpeling - Win32 %LONG%" -f ApacheModuleSpeling.mak clean
    +	 nmake /nologo CFG="ApacheModuleUserTrack - Win32 %LONG%" -f ApacheModuleUserTrack.mak clean
    +	cd ..\..
    +	cd modules\proxy
    +	 nmake /nologo CFG="ApacheModuleProxy - Win32 %LONG%" -f ApacheModuleProxy.mak clean
    +	cd ..\..
    + 	cd os\win32\installer\installdll
    +	 nmake /nologo CFG="install - Win32 %LONG%" -f install.mak clean
    +	cd ..\..\..
    +
    +_installdll:
    + 	cd os\win32\installer\installdll
    +	 nmake /nologo CFG="install - Win32 %LONG%" -f install.mak
    +	cd ..\..\..
    diff --git a/APACHE_1_3b7/src/Makefile.tmpl b/APACHE_1_3b7/src/Makefile.tmpl
    new file mode 100644
    index 0000000000..0bee1299a2
    --- /dev/null
    +++ b/APACHE_1_3b7/src/Makefile.tmpl
    @@ -0,0 +1,114 @@
    +
    +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
    +LIBS=$(EXTRA_LIBS) $(LIBS1)
    +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
    +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
    +
    +OBJS= \
    +  modules.o \
    +  $(MODULES) \
    +  main/libmain.a \
    +  $(OSDIR)/libos.a \
    +  ap/libap.a
    +
    +.c.o:
    +	$(CC) -c $(INCLUDES) $(CFLAGS) $<
    +
    +all: @@Configuration@@ $(TARGET)
    +
    +@@Configuration@@: Configuration.tmpl
    +	@echo "@@Configuration@@ older than Configuration.tmpl, or doesn't exist."
    +	@echo "Consider copying Configuration.tmpl to @@Configuration@@, editing and rerunning"
    +	@echo "Configure."
    +	@echo "If not, you will at least have to touch @@Configuration@@."
    +	@false
    +
    +$(TARGET): $(SUBTARGET)
    +
    +target_static: subdirs modules.o
    +	$(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c
    +	$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \
    +	      -o $(TARGET) buildmark.o $(OBJS) $(REGLIB) $(LIBS)
    +
    +target_shared: libhttpd.ep
    +	$(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \
    +	      -o $(TARGET) -DSHARED_CORE_BOOTSTRAP main/http_main.c
    +
    +libhttpd.ep: libhttpd.so
    +	$(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \
    +	      -o libhttpd.ep -DSHARED_CORE_TIESTATIC main/http_main.c \
    +		  -L. -lhttpd $(LIBS)
    +
    +libhttpd.so: subdirs modules.o
    +	$(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c
    +	$(LD_SHLIB) $(LDFLAGS_SHLIB) -o libhttpd.so buildmark.o $(OBJS) $(REGLIB)
    +	@if [ ".$(SHLIB_SUFFIX_LIST)" != . ]; then \
    +		rm -f libhttpd.so.*; \
    +		for suffix in $(SHLIB_SUFFIX_LIST) ""; do \
    +			[ ".$$suffix" = . ] && continue; \
    +		    echo "ln libhttpd.so libhttpd.so.$$suffix"; \
    +		    ln libhttpd.so libhttpd.so.$$suffix; \
    +		done; \
    +	fi
    +
    +subdirs:
    +	@for i in $(SUBDIRS); do \
    +		echo "===> $(SDP)$$i"; \
    +		( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)') || exit 1; \
    +		echo "<=== $(SDP)$$i"; \
    +	done
    +
    +support: support-dir
    +
    +support-dir:
    +	@echo "===> $(SDP)support"; \
    +	cd support; $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)'; \
    +	echo "<=== $(SDP)support"
    +
    +clean:
    +	rm -f $(TARGET) libhttpd.* *.o
    +	@for i in $(SUBDIRS); do \
    +		echo "===> $(SDP)$$i"; \
    +		( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' $@ ) || exit 1; \
    +		echo "<=== $(SDP)$$i"; \
    +	done
    +
    +distclean:
    +	-rm -f $(TARGET) *.o
    +	@for i in $(SUBDIRS); do \
    +		echo "===> $(SDP)$$i"; \
    +		( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' $@ ) || exit 1; \
    +		echo "<=== $(SDP)$$i"; \
    +	done
    +	-rm -f include/ap_config.h
    +	-rm -f modules.c
    +	-rm -f modules/Makefile
    +	-rm -f regex/Makefile
    +	-rm -f Makefile.config
    +	-rm -f Makefile
    +
    +# We really don't expect end users to use this rule.  It works only with
    +# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
    +# using it.
    +depend:
    +	cp Makefile.tmpl Makefile.tmpl.bak \
    +	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
    +	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
    +	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
    +	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
    +		> Makefile.tmpl \
    +	    && rm Makefile.new
    +	for i in $(SUBDIRS); do \
    +	    ( cd $$i && $(MAKE) CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' depend ) || exit 1; \
    +	done
    +
    +#Dependencies
    +
    +$(OBJS): Makefile
    +
    +# DO NOT REMOVE
    +buildmark.o: buildmark.c include/conf.h os/unix/os.h include/httpd.h \
    + include/alloc.h include/buff.h include/ap.h include/util_uri.h
    +modules.o: modules.c include/httpd.h include/conf.h os/unix/os.h \
    + include/alloc.h include/buff.h include/ap.h include/util_uri.h \
    + include/http_config.h
    diff --git a/APACHE_1_3b7/src/PORTING b/APACHE_1_3b7/src/PORTING
    new file mode 100644
    index 0000000000..ffa7a32b6a
    --- /dev/null
    +++ b/APACHE_1_3b7/src/PORTING
    @@ -0,0 +1,377 @@
    +The Semi-Official Guide to Porting Apache
    +
    +-------------
    +Introduction:
    +-------------
    +Apache has been ported to a wide variety of platforms, from multiple
    +UNIX variants to OS/2. Starting with v1.3, it will even run under
    +Windows95 and Windows NT. Nonetheless, there are most likely a few
    +platforms out there that currently are not "officially" supported under
    +Apache. Porting Apache to these platforms can be quite simple
    +depending on the "genericness" of the OS. This document will provide
    +some basic guidelines to help the potential porter.
    +
    +-------------
    +Requirements:
    +-------------
    +One of the basic requirements for a potential Apache platform is
    +a robust TCP/IP implementation. Just about any UNIX out there
    +nowadays, even some ancient ones, have a TCP/IP stack that will
    +work. In particular, the UNIX should provide for sockets and the
    +basic controlling functions for them (like accept(), bind(), etc).
    +
    +The source for Apache is written in ANSI-C, so an ANSI-C compiler
    +is required. However, Apache does not use or require ANSI-only
    +functions or options (eg: the "%n" parameter in the scanf()
    +family) as much as possible to ease portability. Generally,
    +an ANSI-C compiler (eg: gcc) even without a full-blown ANSI
    +C library is usually sufficient.
    +
    +At present, the Apache source is not compatible with C++.
    +
    +-------------------
    +The Starting Point:
    +-------------------
    +The first thing to look at is the output of the ./helpers/GuessOS
    +script. This is a simple script that attempts to determine the
    +platform and OS you are running on. The output of this script
    +is used by Configure to set some basic compilation parameters.
    +
    +The output of ./helpers/GuessOS was designed to be GNU 'config.guess'
    +compatible (from GNU/autoconf). The format of the output string
    +is:
    +
    +   machine-vendor-OS
    +
    +This string is returned to the main Configure script as the
    +shell variable $PLAT. If Configure is not "aware" of that platform
    +(or cannot correctly parse it), it will complain and die. We realize
    +that this may not be the best solution; the intent is to get as
    +much feedback as possible.
    +
    +----------------------
    +Configure cannot Grok:
    +----------------------
    +If this happens to you, then it means that Configure doesn't know
    +how to configure and compile Apache for your OS. It will still try
    +nonetheless, but at this point, all bets are off.
    +
    +The best solution if this happens to you is to make Apache aware
    +of your OS.  The first course of action is the easiest:  Look in
    +Configure and see if there are any OSs which are similar to yours.
    +
    +For example, let's say that your OS is similar to HP-UX, but that
    +GuessOS returns "foobar-intel-hubble". You would then edit
    +Configure as follows:
    +
    +    *-hp-hpux*|*-*-hubble)
    +	OS='HP-UX'
    +	CFLAGS="$CFLAGS -DHPUX"
    +	;;
    +
    +The '|*-*-hubble' was added to the switch statement for HP-UX.
    +
    +Another fix may involve editing the GuessOS helper script. Let's
    +say, for example, that your system is SysV4-based, but that
    +GuessOS does not return that info. You could then add a switch
    +to the script that does something like:
    +
    +	*WeirdSystem*)
    +	    echo "${MACHINE}-whatever-sysv4"; exit 0
    +	    ;;
    +
    +In this case, we force GuessOS to return a string that includes
    +the "sysv4" cookie for Configure to recognize.
    +
    +Unfortunately, unless you are running a very generic BSD or SysV
    +system, no "supported" OS will be close enough in all aspects to
    +allow for a clear (and possibly workable) build of Apache. If this
    +is the case, you will need to port Apache to your OS.
    +
    +-------------------
    +Porting for Apache:
    +-------------------
    +When all else fails, it's time to hack some code. The source itself
    +is generic enough that most ports are incredibly easy. No matter
    +what, however, there are 2 source files that need to be updated
    +for the port:
    +
    +   ./Configure
    +   ./include/conf.h
    +
    +Configure:
    +==========
    +Configure concerns itself with determining the OS-type for the
    +build and setting up a few Makefile variables for the build. The
    +most important are 'OS' and 'CFLAGS'. For example, when Configure
    +determines a build for A/UX, it runs the following lines:
    +
    +  case "$PLAT" in
    +    *-apple-aux3*)
    +	OS='A/UX 3.1.x'
    +	CFLAGS="$CFLAGS -DAUX -D_POSIX_SOURCE"
    +	LIBS="$LIBS -lposix -lbsd"
    +	LDFLAGS="$LDFLAGS -s"
    +	DEF_WANTHSREGEX=no
    +	;;
    +
    +The 'OS' variable is used to define the system Apache is being built
    +for. You will also note that 'CFLAGS' defines "-DAUX". In this case,
    +'AUX' is a magic cookie used by the Apache code (mainly conf.h [see
    +below]) to handle OS-specific code. Each code that has and requires
    +such OS-specific code will require a unique "system cookie" defined
    +in 'CFLAGS'. You will also note that Configure also goes ahead and
    +predefines the LIBS and LDFLAGS Makefile variables.
    +
    +DEF_WANTHSREGEX indicates the "default" setting of the WANTHSREGEX rule.
    +If left undefined it'll default to yes.  Yes means the src/regex/
    +directory, containing Henry Spencer's regex library will be used rather
    +than any system supplied regex.  It's been our experience that system
    +supplied regex libraries are generally buggy, and should be avoided.
    +
    +conf.h:
    +=======
    +The Apache code, specifically in conf.h, uses a variety of #defines to
    +control how the code is compiled and what options are available for each
    +supported OS. One of the hardest parts about the porting process is
    +determining which of the following are applicable for your system and
    +setup. This time using the example of AIX, we see:
    +
    +   #elif defined(AIX)
    +   #undef HAVE_GMTOFF
    +   #undef NO_KILLPG
    +   #undef NO_SETSID
    +   #define HAVE_SYS_SELECT_H
    +   #define JMP_BUF sigjmp_buf
    +   #define HAVE_MMAP
    +   #define USE_MMAP_SCOREBOARD
    +   typedef int rlim_t;
    +
    +The above lines describe which functions,  capabilities and specifics
    +are required for Apache to build and run under IBM AIX (the #undefs
    +are not strictly required, but are a Good Idea anyway).
    +
    +The following several lines provide a list and short description
    +of these #defines. By correctly #defining the ones you need in conf.h
    +(wrapped by the above mentioned "system cookie"), you can fine tune the
    +build for your OS.
    +
    +--
    +
    + NEED_*:
    +  If the particular OS doesn't supply the specified function, we use the
    +  Apache-supplied version (in util.c). 
    +
    +    NEED_STRERROR:
    +    NEED_STRDUP:
    +    NEED_STRCASECMP:
    +    NEED_STRNCASECMP:
    +    NEED_INITGROUPS:
    +    NEED_WAITPID:
    +    NEED_STRERROR:
    +--
    +
    + HAVE_*:
    +  Does this OS have/support this capability?
    +
    +    HAVE_MMAP:
    +      The OS has a working mmap() implementation
    +
    +    HAVE_SHMGET:
    +      The OS has a working shmget() (SystemV shared memory) implementation
    +
    +    HAVE_GMTOFF:
    +      Define if the OS's tm struct has the tm_gmtoff element
    +
    +    HAVE_RESOURCE:
    +      Define if the OS supports the getrlimit()/setrlimit() functions
    +
    +    HAVE_CRYPT_H:
    +      Define if the OS has the <crypt.h> header file.
    +
    +    HAVE_SYS_SELECT_H:
    +      Define if the OS has the <sys/select.h> header file.
    +
    +    HAVE_SYS_RESOURCE_H:
    +      Define if the OS has and supports the getrlimit/setrlimit
    +      family. Apache uses this to determine if RLIMIT_CPU|VMEM|DATA|RLIMIT
    +      is found and used.
    +--
    +
    + USE_*:
    +  These #defines are used for functions and ability that aren't exactly
    +  required but should be used.
    +
    +     USE_MMAP_SCOREBOARD:
    +      Define if the OS supports the BSD mmap() call. This is used by various
    +      OSs to allow the scoreboard file to be held in shared mmapped-memory
    +      instead of a real file.  Note that this is only used to determine
    +      if mmap should be used for shared memory. If HAVE_MMAP is not
    +      #defined, this will automatically be unset.
    +
    +     USE_SHMGET_SCOREBOARD:
    +      Define if the OS has the SysV-based shmget() family of shared-memory
    +      functions. Used to allow the scoreboard to live in a shared-memory
    +      slot instead of a real file. If HAVE_SHMGET is not #defined,
    +      this will automatically be unset.
    +
    +     <<NOTE: If neither USE_MMAP_SCOREBOARD or USE_SHMGET_SCOREBOARD
    +	     is defined, a file-based scoreboard will be used and
    +	     SCOREBOARD_FILE will automatically be defined >>
    +
    +     USE_POSIX_SCOREBOARD:
    +      Defined on QNX currently where the shared memory scoreboard follows
    +      the POSIX 1003.4 spec.
    +    
    +     USE_OS2_SCOREBOARD:
    +      Defined on OS2, uses OS2 primitives to construct shared memory for
    +      the scoreboard.
    +
    +     USE_LONGJMP:
    +      Define to use the longjmp() call instead of siglongjmp()
    +      (as well as setjmp() instead of sigsetjmp()).
    +
    +     USE_MMAP_FILES:
    +      Enable the use of mmap() for sending static files. If HAVE_MMAP
    +      is not #defined, this will automatically be unset.
    +
    + USE_*_SERIALIZED_ACCEPT:
    +  See htdocs/manual/misc/perf-tuning.html for an in-depth discussion of
    +  why these are required.  These are choices for implementing a semaphore
    +  between children entering accept().  A complete port should define one
    +  of these, many may work and it's worthwhile timing them.  Without these
    +  the server will not implement multiple Listen directives reliably.
    +
    +     USE_FCNTL_SERIALIZED_ACCEPT:
    +      Use fcntl() to implement the semaphore.
    +
    +     USE_FLOCK_SERIALIZED_ACCEPT:
    +      Use flock() to implement the semaphore (fcntl() is expensive on
    +      some OSs, esp.  when using NFS).
    +
    +     USE_USLOCK_SERIALIZED_ACCEPT:
    +      Probably IRIX only: use uslock() to serialize, which is far faster
    +      on multiprocessor boxes (and far slower on uniprocessor, yay).
    +
    +     USE_SYSVSEM_SERIALIZED_ACCEPT:
    +      Use System V semaphores to implement the semaphore.  These are
    +      problematic in that they won't be cleaned up if apache is kill -9d,
    +      and there's the potential of a CGI causing a denial of service
    +      attack if it's running as the same uid as apache (i.e. suexec
    +      is recommended on public servers).  But they can be faster than
    +      either of fcntl() or flock() on some systems.
    +
    +     USE_PTHREAD_SERIALIZED_ACCEPT:
    +      Use POSIX mutexes to implement the semaphore.
    +
    +     << NOTE: If none of the above USE_*SERIALIZED_ACCEPTs are
    +	      defined, NO_SERIALIZED_ACCEPT will automatically
    +	      be defined if MULTITHREAD is not defined >>
    +
    +     SINGLE_LISTEN_UNSERIALIZED_ACCEPT:
    +      It's safe to unserialize single-socket accept().
    +
    +--
    +
    +  NO_*:
    +   These are defined if the OS does NOT have the specified function or if
    +   we should not use it.
    +
    +      NO_SHMGET:
    +       Do not use shmget() (SystemV shared memory) at all.
    +
    +      NO_MMAP:
    +       Do not use mmap() at all.
    +
    +      NO_UNISTD_H:
    +
    +      NO_KILLPG:
    +
    +      NO_SETSID:
    +
    +      NO_USE_SIGACTION:
    +       Do not use the sigaction() call, even if we have it.
    +
    +      NO_LINGCLOSE:
    +       Do not use Apache's soft, "lingering" close feature to
    +       terminate connections. If you find that your server crashes
    +       due to being choked by too many FIN_WAIT_2 network states, 
    +       some reports indicate that #define'ing this will help.
    +
    +      NO_SLACK:
    +       Do not use the "slack" fd feature which requires a working fcntl
    +       F_DUPFD.
    +
    +      NO_GETTIMEOFDAY:
    +       OS does not have the gettimeofday() function (which is
    +       BSDish).
    +
    +      NO_TIMES:
    +       OS does not have the times() function.
    +
    +      NO_OTHER_CHILD:
    +       Do not implement the register_other_child API, usually because
    +       certain system calls aren't available.
    +
    +      NO_RELIABLE_PIPED_LOGS:
    +       Do not use reliable piped logs, which happen to also require
    +       the register_other_child API.  The reliable piped log code
    +       requires another child spawning interface which hasn't been
    +       generalised yet.
    +
    +--
    +
    +  MISC #DEFINES:
    +   Various other #defines used in the code.
    +
    +      MULTITHREAD:
    +       Defined if the OS is multi-threaded. Valid only on
    +       Win32 at present.
    +
    +      JMP_BUF:
    +       The variable-type for siglongjmp() or longjmp() call.
    +
    +      MOVEBREAK:
    +       Amount to move sbrk() breakpoint, if required, before attaching
    +       shared-memory segment.
    +
    +      NET_SIZE_T:
    +       Some functions such as accept(), getsockname(), getpeername() take
    +       an int *len on some architectures and a size_t *len on others.
    +       If left undefined apache will default it to int.
    +
    +      NEED_HASHBANG_EMUL:
    +       The execve()/etc. functions on this platform do not deal with #!,
    +       so it must be emulated by Apache.
    +
    +      SYS_SIGLIST
    +       Should be defined to point to a const char * const * array of
    +       signal descriptions.  This is frequently sys_siglist or
    +       _sys_siglist, defined in <signals.h>
    +
    +-----------
    +Conclusion:
    +-----------
    +The above hints, and a good understanding of your OS and Apache, will
    +go a LONG way in helping you get Apache built and running on your
    +OS. If you have a port, PLEASE send Email to 'Apache@Apache.Org',
    +or log a suggestion report at <http://bugs.apache.org/>, with
    +the patches so that we may add them to the official version.
    +If you hit a rough spot in the porting process, you can also try
    +sending Email to that address as well and, if you are lucky, someone
    +will respond. Another good source is the 'comp.infosystems.www.servers.unix'
    +Usenet group as well.
    +
    +Good luck and happy porting!
    +
    +
    +----------------------------
    +Appendix: OS-Specific Notes:
    +----------------------------
    +A/UX:
    +  Don't even try with cc. Instead, use gcc-2.7.2 and the libUTIL.a
    +  function library, both of which are available on jagubox.gsfc.nasa.gov.
    +  libUTIL.a includes many basic functions that Apache (and other software)
    +  requires as well as fixed versions of functions in libc.a. Contact
    +  Jim Jagielski (jim@apache.org) if you need a precompiled build for
    +  A/UX 3.1.x.
    diff --git a/APACHE_1_3b7/src/README b/APACHE_1_3b7/src/README
    new file mode 100644
    index 0000000000..9aefdcac47
    --- /dev/null
    +++ b/APACHE_1_3b7/src/README
    @@ -0,0 +1,147 @@
    +The following document was written by Robert S. Thau (rst@ai.mit.edu) on the
    +release of Apache 1.0.  Some details may have changed since then regarding the
    +functions and names of modules, but the basic ideas are still intact.
    + =================================================
    +
    +The basic idea of the new Apache release is to make a modular
    +"tinkertoy" server, to which people can easily add code which is
    +valuable to them (even if it isn't universally useful) without hairing
    +up a monolithic server.  Applications for this idea include database
    +integration, support for experimental search and scripting extensions,
    +new authentication modes (digest authentication, for instance, could
    +be done entirely as a module), and so forth.  All modules have the
    +same interface to the server core, and through it, to each other.
    +
    +In particular, the following are modules in the current code base:
    +common log format (other loggers can easily coexist with it), auth and
    +dbm auth (although both use common code in http_protocol.c to parse
    +the Authorization: line), directory handling (which can be added or
    +replaced), handling of aliases and access control, content
    +negotiation, CGI, includes, aliases, and so forth.  (What's left in
    +the basic server?  Not a whole lot).  The configuration file commands
    +which configure these things are defined, for the most part, by the
    +modules themselves, and not by the server core (each module has, or
    +can have, a command dispatch table).
    +
    +Besides carving up the base code into modules, this release makes a
    +few other fairly pervasive changes.  Most of the global variables are
    +gone; most of the MAX_STRING_LENGTH char arrays are gone (the few that
    +are left being sprintf() targets, or I/O buffers of various sorts),
    +and unmunge_name has vanished.  The most drastic change is the use of
    +a "compool" strategy to manage resources allocated for a request ---
    +the code in alloc.c keeps track of it all and allows it to be freed en
    +bloc at the end of the request.  This strategy seems to be effective
    +in stanching memory and descriptor leaks.
    +
    +Additional third-party modules can be found at
    +<URL:http://www.apache.org/dist/contrib/modules/>.
    +
    +
    +A brief code review:
    +
    +The code here can be divided into the server core (the http_* files,
    +along with alloc.c and the various utility files), and several modules
    +(the mod_* files).
    +
    +The core interfaces to modules through the "module" structure which
    +describes each one.  There's a linked list of these things rooted at
    +top_module, through which http_config.c dispatches when necessary.  The
    +module structures themselves are defined at the bottom of the mod_foo
    +files.  (Loading new modules dynamically at runtime should be simple;
    +just push them onto the linked list.  The only complication is what to
    +do with AddModule commands when the config files are reread,
    +particularly if you find a module has been taken out).
    +
    +In addition to the core itself (which does have a module structure to
    +hold its command tables, and the handlers for various phases of
    +request handling which make it *barely* a web server on its own),
    +the modules included here are the following:
    +
    +mod_mime.c --- deduction of MIME types and content-encodings from
    +  filename extensions.  This module defines the AddType, AddEncoding,
    +  and TypesConfig config-file directives.  This code is off in a
    +  module by itself so that people who want to experiment with other
    +  meta-information schemes can replace it, and still have content
    +  negotiation work.
    +
    +mod_log_config.c --- logging in configurable or common log format.
    +
    +mod_auth.c --- HTTP authentication.  Defines the AuthUserFile and
    +  AuthGroupFile directives (other auth-related commands are handled by
    +  the core itself, so it knows which requests require it to poll the
    +  modules for authentication handlers).
    +
    +mod_auth_dbm.c --- DBM auth.  Untested, and left out of the modules
    +  list in modules.c because of that, but it does at least compile.
    +  Grump. 
    +
    +mod_access.c --- access checking by DNS name or IP address; defines
    +  the "order", "allow" and "deny" config-file commands.  (If this
    +  module is compiled out, the server fails safe --- any attempt to
    +  configure access control will die on a config file syntax error when
    +  the relevant commands go unrecognized).
    +
    +mod_negotiation.c --- Content negotiation.  Defines the
    +  CacheNegotiatedDocs config-file command.  Making this a module is
    +  perhaps going overboard, but I wanted to see how far I could push
    +  it. 
    +
    +mod_alias.c --- Alias command and file translation.
    +
    +mod_userdir.c --- ditto for Userdir.
    +
    +mod_cgi.c --- Common Gateway Interface.  Also defines ScriptAlias,
    +  because scripts are treated slightly differently depending on
    +  whether they are ScriptAliased or not (in particular, ExecCGI is not
    +  required in the former case).
    +
    +mod_includes.c --- server-side includes.
    +
    +mod_dir.c --- defines a whole *raft* of commands; handles directories.
    +
    +mod_asis.c --- ASIS file handling.
    +
    +mod_dld.c --- the experimental runtime-code-loader described above.
    +  You'll have to alter the makefile and modules.c to make this active
    +  if you want it.
    +
    +
    +
    +As to the core, here's a brief review of what's where:
    +
    +http_protocol.c --- functions for dealing directly with the client.
    +  Reading requests, writing replies of various sorts.  I've tried to
    +  route all data transfer between server and client through here, so
    +  there's a single piece of code to change if we want to add, say,
    +  HTTP-NG packetization.  The major glaring exception is NPH- CGI
    +  scripts; what *will* we do with those for HTTP-NG?
    +
    +http_request.c --- functions which direct the processing of requests,
    +  including error handling.  Generally responsible for making sure
    +  that the right module handlers get invoked, in the right order.
    +  (This includes the "sub-request" mechanism, which is used by
    +  includes and other stuff to ask about the status of particular
    +  subfiles).
    +
    +http_core.c --- 
    +  Contains the core module structure, its command table, and the
    +  command handlers, also the filename translation routine, and the
    +  like for the core.  (Basically, this is all of the core module stuff
    +  which looks more or less like the boilerplate from the other modules).
    +
    +http_config.c --- Functions to read config files and dispatch to the
    +  command handlers; also, routines to manage configuration vectors,
    +  and to dispatch to modules' handlers for the various phases of
    +  handling a request.  
    +
    +http_log.c --- just the error log.  Error handling is split between
    +  http_protocol.c (for generating the default error responses) and
    +  http_request.c (for executive handling, including ErrorDocument
    +  invocation); transaction logging is in the modules.
    +
    +http_main.c --- System startup, restart, and accepting connections;
    +  also timeout handling (which is pretty grotesque right now; ideas?)
    +
    +alloc.c --- allocation of all resources which might have to be reclaimed
    +  eventually, including memory, files, and child processes.
    +
    diff --git a/APACHE_1_3b7/src/README.EBCDIC b/APACHE_1_3b7/src/README.EBCDIC
    new file mode 100644
    index 0000000000..749ddc6676
    --- /dev/null
    +++ b/APACHE_1_3b7/src/README.EBCDIC
    @@ -0,0 +1,148 @@
    +			    README.EBCDIC
    +
    +This version of Apache comes with a first-cut (working, but not
    +fully tested) port to a mainframe machine which uses the EBCDIC
    +character set as its native codeset (It is the SIEMENS NIXDORF
    +family of mainframes running the BS2000 operating system. This
    +mainframe OS nowadays features a SVR4-like POSIX subsystem).
    +
    +The port was started initially to
    +- prove the feasibility
    +- find a "worthy and capable" successor for the CERN daemon (which
    +  was ported a couple of years ago), and to
    +- prove that Apache's preforking process model can on this platform
    +  easily outperform the accept-fork-serve model used by CERN by a
    +  factor of 5 or more.
    +
    +This document serves as a rationale to describe some of the design
    +decisions of the port to this machine.
    +
    +* The relevant changes in the source are #ifdef'ed into two
    +  categories:
    +  #ifdef CHARSET_EBCDIC     Code which is needed for any EBCDIC
    +			    based machine
    +  #ifdef _OSD_POSIX         Code which is needed for the BS2000
    +			    SIEMENS NIXDORF mainframe platform only.
    +
    +* The possibility to translate between ASCII and EBCDIC at the
    +  socket level (on BS2000 POSIX, there is a socket option which
    +  supports this) was intentionally not chosen, because the byte
    +  stream at the HTTP protocol level consists of a mixture of
    +  protocol related strings and non-protocol related raw file data.
    +  HTTP protocol strings are always encoded in ASCII (the GET
    +  request, any Header: lines, the chunking information etc.) whereas
    +  the file transfer parts (i.e., GIF images, CGI output etc.) should
    +  usually be just "passed thru" by the server. This separation
    +  between "protocol string" and "raw data" is reflected in the
    +  server code by functions like bgets() or rvputs() for strings, and
    +  functions like bwrite() for binary data. A global translation of
    +  everything would therefore be inadequate.
    +  (In the case of text files of course, provisions must be made so
    +  that the documents are always served in ASCII format)
    +
    +* This port therefore features a built-in protocol level conversion
    +  for the server-internal strings (which the compiler translated to
    +  EBCDIC strings) and server-generated documents. The hard coded
    +  ASCII escapes \012 and \015 which are ubiquitious in the server
    +  code are an exception: they are not converted to ASCII a second
    +  time.
    +
    +* By examining the call hierarchy for the BUFF management routines,
    +  I added an "ebcdic/ascii conversion layer" which would be crossed
    +  on every puts/write/get/gets, and a conversion flag which allowed
    +  switching of the conversions on-the-fly. So it is now possible to
    +  read the header lines of a CGI-script output in EBCDIC format, and
    +  then find out that the remainder of the script's output is in
    +  ASCII (like in the output of a WWW Counter program). Likewise, the
    +  server always generates its header lines in EBCDIC (and with ASCII
    +  conversion enabled) and determines, based on the type of document
    +  being served, whether the document body (except for the chunking
    +  information, of course) is in ASCII already or is converted from
    +  EBCDIC.
    +
    +* For Text documents (MIME types text/plain, text/html etc.), an
    +  implicit translation to ASCII can be used, or (if the users prefer
    +  to store some documents in raw ASCII form for faster serving) can
    +  be served without conversion.
    +  Example:
    +      to serve files with the suffix .ahtml as a raw ASCII text/html
    +      document (and suffix .ascii as ASCII text/plain), use the
    +      directives:
    +    AddType  text/x-ascii-html  .ahtml
    +    AddType  text/x-ascii-plain .ascii
    +  Similarly, any text/XXXX MIME type can be served as "raw ASCII" by
    +  configuring a MIME type "text/x-ascii-XXXX" for it using AddType.
    +
    +* Non-text documents are always served "binary" without conversion.
    +  This seems to be the most sensible choice for, .e.g., GIF/ZIP/AU
    +  file types. This of course requires the user to copy them to the
    +  mainframe host using the "rcp -b" binary switch.
    +
    +* Server parsed files are always assumed to be in native (i.e.,
    +  EBCDIC) format as used on the machine, and are converted after
    +  processing.
    +
    +* For CGI output, the CGI script determines whether a conversion is
    +  needed or not: by setting the appropriate Content-Type, text files
    +  can be converted, or GIF output can be passed through unmodified.
    +  An example for the latter case is the wwwcount program which we ported
    +  as well.
    +
    +What works:
    +- In the following list,
    +    + means: works, tested
    +    - means: doesn't work for some reason
    +    ? means: compiled-in, but untested
    +
    +  http_core.c       +
    +  mod_access.c      +
    +  mod_actions.c     ?
    +  mod_alias.c       +
    +  mod_asis.c        ?
    +  mod_auth.c        +
    +  mod_auth_anon.c   +
    +  mod_auth_db.c     ? with own libdb.a
    +  mod_auth_dbm.c    ? with own libdb.a
    +  mod_autoindex.c   +
    +  mod_cern_meta.c   ?
    +  mod_cgi.c         +
    +  mod_digest.c      - / MD5 not ported yet
    +  mod_dir.c         +
    +  mod_env.c         +
    +  mod_example.c     - / not tried yet
    +  mod_expires.c     +
    +  mod_headers.c     +
    +  mod_imap.c        +
    +  mod_include.c     +
    +  mod_info.c        +
    +  mod_log_agent.c   +
    +  mod_log_config.c  +
    +  mod_log_referer.c +
    +  mod_mime.c        +
    +  mod_mime_magic.c  - / not tried yet
    +  mod_negotiation.c +
    +  mod_proxy.c       +
    +  mod_rewrite.c     ? / untested
    +  mod_setenvif.c    +
    +  mod_so.c          - / no shared libs
    +  mod_speling.c     +
    +  mod_status.c      +
    +  mod_unique_id.c   +
    +  mod_userdir.c     +
    +  mod_usertrack.c   ? / untested
    +
    +Additional (third-party) modules:                    See:
    +  mod_jserv.c       - / JAVA still being ported  http://java.apache.org/
    +  mod_php.c         - / not ported yet           http://www.php.net/
    +  mod_put.c         ? / untested                 http://hpwww.ec-lyon.fr/~vincent/apache/mod_put.html
    +  mod_session.c     ? / untested                 ftp://hachiman.vidya.com/pub/apache/mod_session.tar.gz
    +
    +
    +Notes:
    +    To use the mod_auth_db functionality, you will need a working libdb.a.
    +On the system where I did the port none was available, so I ported the
    +standard db-1.85.14 with little problems. Note however that you will need
    +a working perl5 as well if you want to use Apache's dbmmanage script to
    +maintain db user databases.
    +
    +			    Martin Kraemer, 31-Mar-1998
    diff --git a/APACHE_1_3b7/src/ap/.cvsignore b/APACHE_1_3b7/src/ap/.cvsignore
    new file mode 100644
    index 0000000000..964f0bd942
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/.cvsignore
    @@ -0,0 +1,2 @@
    +Makefile
    +Debug
    diff --git a/APACHE_1_3b7/src/ap/.indent.pro b/APACHE_1_3b7/src/ap/.indent.pro
    new file mode 100644
    index 0000000000..a9fbe9f9a1
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/.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/APACHE_1_3b7/src/ap/Makefile.tmpl b/APACHE_1_3b7/src/ap/Makefile.tmpl
    new file mode 100644
    index 0000000000..ab6e73b19d
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/Makefile.tmpl
    @@ -0,0 +1,59 @@
    +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
    +LIBS=$(EXTRA_LIBS) $(LIBS1)
    +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
    +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
    +
    +LIB=libap.a
    +
    +OBJS=ap_execve.o ap_cpystrn.o ap_signal.o \
    +     ap_slack.o ap_snprintf.o ap_strings.o
    +
    +.c.o:
    +	$(CC) -c $(INCLUDES) $(CFLAGS) $<
    +
    +all: $(LIB)
    +
    +clean:
    +	rm -f *.o *.a
    +
    +distclean: clean
    +	-rm -f Makefile
    +
    +$(OBJS): Makefile
    +
    +$(LIB): $(OBJS)
    +	rm -f $@
    +	ar cr $@ $(OBJS)
    +	$(RANLIB) $@
    +
    +# We really don't expect end users to use this rule.  It works only with
    +# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
    +# using it.
    +depend:
    +	cp Makefile.tmpl Makefile.tmpl.bak \
    +	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
    +	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
    +	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
    +	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
    +		> Makefile.tmpl \
    +	    && rm Makefile.new
    +
    +# DO NOT REMOVE
    +ap_cpystrn.o: ap_cpystrn.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h
    +ap_execve.o: ap_execve.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h
    +ap_signal.o: ap_signal.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h
    +ap_slack.o: ap_slack.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_log.h
    +ap_snprintf.o: ap_snprintf.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h
    +ap_strings.o: ap_strings.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h
    diff --git a/APACHE_1_3b7/src/ap/ap.dsp b/APACHE_1_3b7/src/ap/ap.dsp
    new file mode 100644
    index 0000000000..f26e9128e4
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap.dsp
    @@ -0,0 +1,106 @@
    +# Microsoft Developer Studio Project File - Name="ap" - Package Owner=<4>
    +# Microsoft Developer Studio Generated Build File, Format Version 5.00
    +# ** DO NOT EDIT **
    +
    +# TARGTYPE "Win32 (x86) Static Library" 0x0104
    +
    +CFG=ap - Win32 Debug
    +!MESSAGE This is not a valid makefile. To build this project using NMAKE,
    +!MESSAGE use the Export Makefile command and run
    +!MESSAGE 
    +!MESSAGE NMAKE /f "ap.mak".
    +!MESSAGE 
    +!MESSAGE You can specify a configuration when running NMAKE
    +!MESSAGE by defining the macro CFG on the command line. For example:
    +!MESSAGE 
    +!MESSAGE NMAKE /f "ap.mak" CFG="ap - Win32 Debug"
    +!MESSAGE 
    +!MESSAGE Possible choices for configuration are:
    +!MESSAGE 
    +!MESSAGE "ap - Win32 Release" (based on "Win32 (x86) Static Library")
    +!MESSAGE "ap - Win32 Debug" (based on "Win32 (x86) Static Library")
    +!MESSAGE 
    +
    +# Begin Project
    +# PROP Scc_ProjName ""
    +# PROP Scc_LocalPath ""
    +CPP=cl.exe
    +
    +!IF  "$(CFG)" == "ap - 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 "Release"
    +# PROP Intermediate_Dir "Release"
    +# PROP Target_Dir ""
    +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
    +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
    +BSC32=bscmake.exe
    +# ADD BASE BSC32 /nologo
    +# ADD BSC32 /nologo
    +LIB32=link.exe -lib
    +# ADD BASE LIB32 /nologo
    +# ADD LIB32 /nologo
    +
    +!ELSEIF  "$(CFG)" == "ap - 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 "Debug"
    +# PROP Intermediate_Dir "Debug"
    +# PROP Target_Dir ""
    +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
    +# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
    +BSC32=bscmake.exe
    +# ADD BASE BSC32 /nologo
    +# ADD BSC32 /nologo
    +LIB32=link.exe -lib
    +# ADD BASE LIB32 /nologo
    +# ADD LIB32 /nologo
    +
    +!ENDIF 
    +
    +# Begin Target
    +
    +# Name "ap - Win32 Release"
    +# Name "ap - Win32 Debug"
    +# Begin Group "Source Files"
    +
    +# PROP Default_Filter ""
    +# Begin Source File
    +
    +SOURCE=.\ap_cpystrn.c
    +# End Source File
    +# Begin Source File
    +
    +SOURCE=.\ap_signal.c
    +# End Source File
    +# Begin Source File
    +
    +SOURCE=.\ap_slack.c
    +# End Source File
    +# Begin Source File
    +
    +SOURCE=.\ap_snprintf.c
    +# End Source File
    +# Begin Source File
    +
    +SOURCE=.\ap_strings.c
    +# End Source File
    +# End Group
    +# Begin Group "Header Files"
    +
    +# PROP Default_Filter ""
    +# End Group
    +# End Target
    +# End Project
    diff --git a/APACHE_1_3b7/src/ap/ap.mak b/APACHE_1_3b7/src/ap/ap.mak
    new file mode 100644
    index 0000000000..24dd9b4ddc
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap.mak
    @@ -0,0 +1,241 @@
    +# Microsoft Developer Studio Generated NMAKE File, Based on ap.dsp
    +!IF "$(CFG)" == ""
    +CFG=ap - Win32 Debug
    +!MESSAGE No configuration specified. Defaulting to ap - Win32 Debug.
    +!ENDIF 
    +
    +!IF "$(CFG)" != "ap - Win32 Release" && "$(CFG)" != "ap - Win32 Debug"
    +!MESSAGE Invalid configuration "$(CFG)" specified.
    +!MESSAGE You can specify a configuration when running NMAKE
    +!MESSAGE by defining the macro CFG on the command line. For example:
    +!MESSAGE 
    +!MESSAGE NMAKE /f "ap.mak" CFG="ap - Win32 Debug"
    +!MESSAGE 
    +!MESSAGE Possible choices for configuration are:
    +!MESSAGE 
    +!MESSAGE "ap - Win32 Release" (based on "Win32 (x86) Static Library")
    +!MESSAGE "ap - Win32 Debug" (based on "Win32 (x86) Static Library")
    +!MESSAGE 
    +!ERROR An invalid configuration is specified.
    +!ENDIF 
    +
    +!IF "$(OS)" == "Windows_NT"
    +NULL=
    +!ELSE 
    +NULL=nul
    +!ENDIF 
    +
    +CPP=cl.exe
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +OUTDIR=.\Release
    +INTDIR=.\Release
    +# Begin Custom Macros
    +OutDir=.\Release
    +# End Custom Macros
    +
    +!IF "$(RECURSE)" == "0" 
    +
    +ALL : "$(OUTDIR)\ap.lib"
    +
    +!ELSE 
    +
    +ALL : "$(OUTDIR)\ap.lib"
    +
    +!ENDIF 
    +
    +CLEAN :
    +	-@erase "$(INTDIR)\ap_cpystrn.obj"
    +	-@erase "$(INTDIR)\ap_signal.obj"
    +	-@erase "$(INTDIR)\ap_slack.obj"
    +	-@erase "$(INTDIR)\ap_snprintf.obj"
    +	-@erase "$(INTDIR)\ap_strings.obj"
    +	-@erase "$(INTDIR)\vc50.idb"
    +	-@erase "$(OUTDIR)\ap.lib"
    +
    +"$(OUTDIR)" :
    +    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
    +
    +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D\
    + "_WINDOWS" /Fp"$(INTDIR)\ap.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
    +CPP_OBJS=.\Release/
    +CPP_SBRS=.
    +BSC32=bscmake.exe
    +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ap.bsc" 
    +BSC32_SBRS= \
    +	
    +LIB32=link.exe -lib
    +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ap.lib" 
    +LIB32_OBJS= \
    +	"$(INTDIR)\ap_cpystrn.obj" \
    +	"$(INTDIR)\ap_signal.obj" \
    +	"$(INTDIR)\ap_slack.obj" \
    +	"$(INTDIR)\ap_snprintf.obj" \
    +	"$(INTDIR)\ap_strings.obj"
    +
    +"$(OUTDIR)\ap.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
    +    $(LIB32) @<<
    +  $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
    +<<
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +OUTDIR=.\Debug
    +INTDIR=.\Debug
    +# Begin Custom Macros
    +OutDir=.\Debug
    +# End Custom Macros
    +
    +!IF "$(RECURSE)" == "0" 
    +
    +ALL : "$(OUTDIR)\ap.lib"
    +
    +!ELSE 
    +
    +ALL : "$(OUTDIR)\ap.lib"
    +
    +!ENDIF 
    +
    +CLEAN :
    +	-@erase "$(INTDIR)\ap_cpystrn.obj"
    +	-@erase "$(INTDIR)\ap_signal.obj"
    +	-@erase "$(INTDIR)\ap_slack.obj"
    +	-@erase "$(INTDIR)\ap_snprintf.obj"
    +	-@erase "$(INTDIR)\ap_strings.obj"
    +	-@erase "$(INTDIR)\vc50.idb"
    +	-@erase "$(OUTDIR)\ap.lib"
    +
    +"$(OUTDIR)" :
    +    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
    +
    +CPP_PROJ=/nologo /MDd /W3 /GX /Z7 /Od /I "../include" /D "WIN32" /D "_DEBUG" /D\
    + "_WINDOWS" /Fp"$(INTDIR)\ap.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
    +CPP_OBJS=.\Debug/
    +CPP_SBRS=.
    +BSC32=bscmake.exe
    +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ap.bsc" 
    +BSC32_SBRS= \
    +	
    +LIB32=link.exe -lib
    +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ap.lib" 
    +LIB32_OBJS= \
    +	"$(INTDIR)\ap_cpystrn.obj" \
    +	"$(INTDIR)\ap_signal.obj" \
    +	"$(INTDIR)\ap_slack.obj" \
    +	"$(INTDIR)\ap_snprintf.obj" \
    +	"$(INTDIR)\ap_strings.obj"
    +
    +"$(OUTDIR)\ap.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
    +    $(LIB32) @<<
    +  $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_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) $< 
    +<<
    +
    +
    +!IF "$(CFG)" == "ap - Win32 Release" || "$(CFG)" == "ap - Win32 Debug"
    +SOURCE=.\ap_cpystrn.c
    +DEP_CPP_AP_CP=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\buff.h"\
    +	"..\include\conf.h"\
    +	"..\include\hsregex.h"\
    +	"..\include\httpd.h"\
    +	"..\os\win32\os.h"\
    +	"..\os\win32\readdir.h"\
    +	
    +
    +"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)"
    +
    +
    +SOURCE=.\ap_signal.c
    +DEP_CPP_AP_SI=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\buff.h"\
    +	"..\include\conf.h"\
    +	"..\include\hsregex.h"\
    +	"..\include\httpd.h"\
    +	"..\os\win32\os.h"\
    +	"..\os\win32\readdir.h"\
    +	
    +
    +"$(INTDIR)\ap_signal.obj" : $(SOURCE) $(DEP_CPP_AP_SI) "$(INTDIR)"
    +
    +
    +SOURCE=.\ap_slack.c
    +DEP_CPP_AP_SL=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\buff.h"\
    +	"..\include\conf.h"\
    +	"..\include\hsregex.h"\
    +	"..\include\http_log.h"\
    +	"..\include\httpd.h"\
    +	"..\os\win32\os.h"\
    +	"..\os\win32\readdir.h"\
    +	
    +
    +"$(INTDIR)\ap_slack.obj" : $(SOURCE) $(DEP_CPP_AP_SL) "$(INTDIR)"
    +
    +
    +SOURCE=.\ap_snprintf.c
    +DEP_CPP_AP_SN=\
    +	"..\include\conf.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +	
    +
    +"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)"
    +
    +
    +SOURCE=.\ap_strings.c
    +DEP_CPP_AP_ST=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\buff.h"\
    +	"..\include\conf.h"\
    +	"..\include\hsregex.h"\
    +	"..\include\httpd.h"\
    +	"..\os\win32\os.h"\
    +	"..\os\win32\readdir.h"\
    +	
    +
    +"$(INTDIR)\ap_strings.obj" : $(SOURCE) $(DEP_CPP_AP_ST) "$(INTDIR)"
    +
    +
    +
    +!ENDIF 
    +
    diff --git a/APACHE_1_3b7/src/ap/ap_cpystrn.c b/APACHE_1_3b7/src/ap/ap_cpystrn.c
    new file mode 100644
    index 0000000000..159bdbe80d
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap_cpystrn.c
    @@ -0,0 +1,93 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +#include "httpd.h"
    +
    +/*
    + * Apache's "replacement" for the strncpy() function. We roll our
    + * own to implement these specific changes:
    + *   (1) strncpy() doesn't always null terminate and we want it to.
    + *   (2) strncpy() null fills, which is bogus, esp. when copy 8byte
    + *       strings into 8k blocks.
    + *   (3) Instead of returning the pointer to the beginning of
    + *       the destination string, we return a pointer to the
    + *       terminating '\0' to allow us to "check" for truncation
    + *
    + * ap_cpystrn() follows the same call structure as strncpy().
    + */
    +
    +API_EXPORT(char *) ap_cpystrn(char *dst, const char *src, size_t dst_size)
    +{
    +
    +    char *d, *end;
    +
    +    if (!dst_size)
    +        return (dst);
    +
    +    d = dst;
    +    end = dst + dst_size - 1;
    +
    +    for (; d < end; ++d, ++src) {
    +	if (!(*d = *src)) {
    +	    return (d);
    +	}
    +    }
    +
    +    *d = '\0';	/* always null terminate */
    +
    +    return (d);
    +}
    diff --git a/APACHE_1_3b7/src/ap/ap_execve.c b/APACHE_1_3b7/src/ap/ap_execve.c
    new file mode 100644
    index 0000000000..32c9e376c5
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap_execve.c
    @@ -0,0 +1,340 @@
    +/* ====================================================================
    + * Copyright (c) 1998 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/>.
    + *
    + */
    +
    +/*
    + * Portions of this code are under this license:
    + *
    + * Copyright (c) 1980, 1991 The Regents of the University of California.
    + * 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 acknowledgement:
    + *	This product includes software developed by the University of
    + *	California, Berkeley and its contributors.
    + * 4. Neither the name of the University nor the names of its contributors
    + *    may be used to endorse or promote products derived from this software
    + *    without specific prior written permission.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    + * ANY EXPRESS 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 REGENTS OR 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.
    + */
    +
    +#include "httpd.h"
    +
    +/*---------------------------------------------------------------*/
    +
    +#ifdef NEED_HASHBANG_EMUL
    +
    +#undef execle
    +#undef execve
    +
    +static const char **hashbang(const char *filename, char **argv);
    +
    +
    +/* Historically, a list of arguments on the stack was often treated as
    + * being equivalent to an array (since they already were "contiguous"
    + * on the stack, and the arguments were pushed in the correct order).
    + * On today's processors, this is not necessarily equivalent, because
    + * often arguments are padded or passed partially in registers,
    + * or the stack direction is backwards.
    + * To be on the safe side, we copy the argument list to our own
    + * local argv[] array. The va_arg logic makes sure we do the right thing.
    + * XXX: malloc() is used because we expect to be overlaid soon.
    + */
    +int ap_execle(const char *filename, const char *argv0, ...)
    +{
    +    va_list adummy;
    +    char **envp;
    +    char **argv;
    +    int argc, ret;
    +
    +    /* First pass: Count arguments on stack */
    +    va_start(adummy, argv0);
    +    for (argc = 1; va_arg(adummy, char *) != NULL; ++argc) {
    +	continue;
    +    }
    +    va_end(adummy);
    +
    +    argv = (char **) malloc((argc + 2) * sizeof(*argv));
    +
    +    /* Pass two --- copy the argument strings into the result space */
    +    va_start(adummy, argv0);
    +    argv[0] = argv0;
    +    for (argc = 1; (argv[argc] = va_arg(adummy, char *)) != NULL; ++argc) {
    +	continue;
    +    }
    +    envp = va_arg(adummy, char **);
    +    va_end(adummy);
    +
    +    ret = ap_execve(filename, argv, envp);
    +    free(argv);
    +
    +    return ret;
    +}
    +
    +int ap_execve(const char *filename, const char *argv[],
    +	      const char *envp[])
    +{
    +    const char *argv0 = argv[0];
    +    extern char **environ;
    +
    +    if (envp == NULL) {
    +	envp = (const char **) environ;
    +    }
    +
    +    /* Try to execute the file directly first: */
    +    execve(filename, argv, envp);
    +
    +    /* Still with us? Then something went seriously wrong.
    +     * From the (linux) man page:
    +     * EACCES The file is not a regular file.
    +     * EACCES Execute permission is denied for the file.
    +     * EACCES Search  permission  is denied on a component of the path prefix.
    +     * EPERM  The file system is mounted noexec.
    +     * EPERM  The file system is mounted nosuid and the file  has an SUID
    +     *        or SGID bit set.
    +     * E2BIG  The argument list is too big.
    +     * ENOEXEC The magic number in the file is incorrect.
    +     * EFAULT filename  points  outside  your  accessible address space.
    +     * ENAMETOOLONG filename is too long.
    +     * ENOENT The file does not exist.
    +     * ENOMEM Insufficient kernel memory was available.
    +     * ENOTDIR A component of the path prefix is not a  directory.
    +     * ELOOP  filename contains a circular reference (i.e., via a symbolic link)
    +     */
    +
    +    if (errno == ENOEXEC
    +    /* Probably a script.
    +     * Have a look; if there's a "#!" header then try to emulate
    +     * the feature found in all modern OS's:
    +     * Interpret the line following the #! as a command line
    +     * in shell style.
    +     */
    +	&& (argv = hashbang(filename, argv)) != NULL) {
    +
    +	/* new filename is the interpreter to call */
    +	filename = argv[0];
    +
    +	/* Restore argv[0] as on entry */
    +	if (argv0 != NULL) {
    +	    argv[0] = argv0;
    +	}
    +
    +	execve(filename, argv, envp);
    +
    +	free(argv);
    +    }
    +    return -1;
    +}
    +
    +/*---------------------------------------------------------------*/
    +
    +/*
    + * From: peter@zeus.dialix.oz.au (Peter Wemm)
    + * (taken from tcsh)
    + * If exec() fails look first for a #! [word] [word] ....
    + * If it is, splice the header into the argument list and retry.
    + * Return value: the original argv array (sans argv[0]), with the
    + * script's argument list prepended.
    + * XXX: malloc() is used so that everything can be free()ed after a failure.
    + */
    +#define HACKBUFSZ 1024		/* Max chars in #! vector */
    +#define HACKVECSZ 128		/* Max words in #! vector */
    +static const char **hashbang(const char *filename, char **argv)
    +{
    +    char lbuf[HACKBUFSZ];
    +    char *sargv[HACKVECSZ];
    +    const char **newargv;
    +    char *p, *ws;
    +    int fd;
    +    int sargc = 0;
    +    int i, j;
    +#ifdef WIN32
    +    int fw = 0;			/* found at least one word */
    +    int first_word = 0;
    +#endif /* WIN32 */
    +
    +    if ((fd = open(filename, O_RDONLY)) == -1) {
    +	return NULL;
    +    }
    +
    +    if (read(fd, (char *) lbuf, 2) != 2
    +	|| lbuf[0] != '#' || lbuf[1] != '!'
    +	|| read(fd, (char *) lbuf, HACKBUFSZ) <= 0) {
    +	close(fd);
    +	return NULL;
    +    }
    +
    +    close(fd);
    +
    +    ws = NULL;			/* word started = 0 */
    +
    +    for (p = lbuf; p < &lbuf[HACKBUFSZ];) {
    +	switch (*p) {
    +	case ' ':
    +	case '\t':
    +#ifdef NEW_CRLF
    +	case '\r':
    +#endif /*NEW_CRLF */
    +	    if (ws) {		/* a blank after a word.. save it */
    +		*p = '\0';
    +#ifndef WIN32
    +		if (sargc < HACKVECSZ - 1) {
    +		    sargv[sargc++] = ws;
    +		}
    +		ws = NULL;
    +#else /* WIN32 */
    +		if (sargc < HACKVECSZ - 1) {
    +		    sargv[sargc] = first_word ? NULL : hb_subst(ws);
    +		    if (sargv[sargc] == NULL) {
    +			sargv[sargc] = ws;
    +		    }
    +		    sargc++;
    +		}
    +		ws = NULL;
    +		fw = 1;
    +		first_word = 1;
    +#endif /* WIN32 */
    +	    }
    +	    p++;
    +	    continue;
    +
    +	case '\0':		/* Whoa!! what the hell happened */
    +	    return NULL;
    +
    +	case '\n':		/* The end of the line. */
    +	    if (
    +#ifdef WIN32
    +		   fw ||
    +#endif /* WIN32 */
    +		   ws) {	/* terminate the last word */
    +		*p = '\0';
    +#ifndef WIN32
    +		if (sargc < HACKVECSZ - 1) {
    +		    sargv[sargc++] = ws;
    +		}
    +#else /* WIN32 */
    +		if (sargc < HACKVECSZ - 1) {	/* deal with the 1-word case */
    +		    sargv[sargc] = first_word ? NULL : hb_subst(ws);
    +		    if (sargv[sargc] == NULL) {
    +			sargv[sargc] = ws;
    +		    }
    +		    sargc++;
    +		}
    +#endif /* !WIN32 */
    +		sargv[sargc] = NULL;
    +	    }
    +	    /* Count number of entries in the old argv vector */
    +	    for (i = 0; argv[i] != NULL; ++i) {
    +		continue;
    +	    }
    +	    ++i;
    +
    +	    newargv = (char **) malloc((p - lbuf + 1)
    +                      + (i + sargc + 1) * sizeof(*newargv));
    +	    ws = &((char *) newargv)[(i + sargc + 1) * sizeof(*newargv)];
    +
    +	    /* Copy entries to allocated memory */
    +	    for (j = 0; j < sargc; ++j) {
    +		newargv[j] = strcpy(ws, sargv[j]);
    +		ws += strlen(ws) + 1;	/* skip trailing '\0' */
    +	    }
    +	    newargv[sargc] = filename;
    +
    +	    /* Append the old array. The old argv[0] is skipped. */
    +	    if (i > 1) {
    +		memcpy(&newargv[sargc + 1], &argv[1],
    +                       (i - 1) * sizeof(*newargv));
    +	    }
    +	
    +	    newargv[sargc + i] = NULL;
    +
    +	    ws = NULL;
    +
    +	    return newargv;
    +
    +	default:
    +	    if (!ws) {		/* Start a new word? */
    +		ws = p;
    +	    }
    +	    p++;
    +	    break;
    +	}
    +    }
    +    return NULL;
    +}
    +#else
    +extern void ap_execve_is_not_here(void);
    +void ap_execve_is_not_here(void) {}
    +#endif /* NEED_HASHBANG_EMUL */
    diff --git a/APACHE_1_3b7/src/ap/ap_fnmatch.c b/APACHE_1_3b7/src/ap/ap_fnmatch.c
    new file mode 100644
    index 0000000000..3856226468
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap_fnmatch.c
    @@ -0,0 +1,213 @@
    +/*
    + * Copyright (c) 1989, 1993, 1994
    + *      The Regents of the University of California.  All rights reserved.
    + *
    + * This code is derived from software contributed to Berkeley by
    + * Guido van Rossum.
    + *
    + * 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 acknowledgement:
    + *      This product includes software developed by the University of
    + *      California, Berkeley and its contributors.
    + * 4. Neither the name of the University nor the names of its contributors
    + *    may be used to endorse or promote products derived from this software
    + *    without specific prior written permission.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    + * ANY EXPRESS 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 REGENTS OR 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.
    + */
    +
    +#if defined(LIBC_SCCS) && !defined(lint)
    +static char sccsid[] = "@(#)fnmatch.c	8.2 (Berkeley) 4/16/94";
    +#endif /* LIBC_SCCS and not lint */
    +
    +/*
    + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
    + * Compares a filename or pathname to a pattern.
    + */
    +
    +#include "conf.h"
    +#include "fnmatch.h"
    +#include <string.h>
    +
    +#define	EOS	'\0'
    +
    +static const char *rangematch(const char *, int, int);
    +
    +API_EXPORT(int) ap_fnmatch(pattern, string, flags)
    +     const char *pattern, *string;
    +     int flags;
    +{
    +    const char *stringstart;
    +    char c, test;
    +
    +    for (stringstart = string;;)
    +	switch (c = *pattern++) {
    +	case EOS:
    +	    return (*string == EOS ? 0 : FNM_NOMATCH);
    +	case '?':
    +	    if (*string == EOS)
    +		return (FNM_NOMATCH);
    +	    if (*string == '/' && (flags & FNM_PATHNAME))
    +		return (FNM_NOMATCH);
    +	    if (*string == '.' && (flags & FNM_PERIOD) &&
    +		(string == stringstart ||
    +		 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
    +		return (FNM_NOMATCH);
    +	    ++string;
    +	    break;
    +	case '*':
    +	    c = *pattern;
    +	    /* Collapse multiple stars. */
    +	    while (c == '*')
    +		c = *++pattern;
    +
    +	    if (*string == '.' && (flags & FNM_PERIOD) &&
    +		(string == stringstart ||
    +		 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
    +		return (FNM_NOMATCH);
    +
    +	    /* Optimize for pattern with * at end or before /. */
    +	    if (c == EOS) {
    +		if (flags & FNM_PATHNAME) {
    +		    return (strchr(string, '/') == NULL ?
    +			    0 : FNM_NOMATCH);
    +		}
    +		else {
    +		    return (0);
    +		}
    +	    }
    +	    else if (c == '/' && flags & FNM_PATHNAME) {
    +		if ((string = strchr(string, '/')) == NULL)
    +		    return (FNM_NOMATCH);
    +		break;
    +	    }
    +
    +	    /* General case, use recursion. */
    +	    while ((test = *string) != EOS) {
    +		if (!ap_fnmatch(pattern, string, flags & ~FNM_PERIOD))
    +		    return (0);
    +		if (test == '/' && flags & FNM_PATHNAME)
    +		    break;
    +		++string;
    +	    }
    +	    return (FNM_NOMATCH);
    +	case '[':
    +	    if (*string == EOS)
    +		return (FNM_NOMATCH);
    +	    if (*string == '/' && flags & FNM_PATHNAME)
    +		return (FNM_NOMATCH);
    +	    if (*string == '.' && (flags & FNM_PERIOD) &&
    +		(string == stringstart ||
    +		((flags & FNM_PATHNAME) && *(string - 1) == '/')))
    +		    return (FNM_NOMATCH);
    +	    if ((pattern =
    +		 rangematch(pattern, *string, flags)) == NULL)
    +		return (FNM_NOMATCH);
    +	    ++string;
    +	    break;
    +	case '\\':
    +	    if (!(flags & FNM_NOESCAPE)) {
    +		if ((c = *pattern++) == EOS) {
    +		    c = '\\';
    +		    --pattern;
    +		}
    +	    }
    +	    /* FALLTHROUGH */
    +	    default:
    +		if (c != *string++)
    +		return (FNM_NOMATCH);
    +	    break;
    +	}
    +    /* NOTREACHED */
    +}
    +
    +static const char *
    +     rangematch(pattern, test, flags)
    +     const char *pattern;
    +     int test, flags;
    +{
    +    int negate, ok;
    +    char c, c2;
    +
    +    /*
    +     * A bracket expression starting with an unquoted circumflex
    +     * character produces unspecified results (IEEE 1003.2-1992,
    +     * 3.13.2).  This implementation treats it like '!', for
    +     * consistency with the regular expression syntax.
    +     * J.T. Conklin (conklin@ngai.kaleida.com)
    +     */
    +    if ((negate = (*pattern == '!' || *pattern == '^')))
    +	++pattern;
    +
    +    for (ok = 0; (c = *pattern++) != ']';) {
    +	if (c == '\\' && !(flags & FNM_NOESCAPE))
    +	    c = *pattern++;
    +	if (c == EOS)
    +	    return (NULL);
    +	if (*pattern == '-'
    +	    && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
    +	    pattern += 2;
    +	    if (c2 == '\\' && !(flags & FNM_NOESCAPE))
    +		c2 = *pattern++;
    +	    if (c2 == EOS)
    +		return (NULL);
    +	    if (c <= test && test <= c2)
    +		ok = 1;
    +	}
    +	else if (c == test)
    +	    ok = 1;
    +    }
    +    return (ok == negate ? NULL : pattern);
    +}
    +
    +
    +/* This function is an Apache addition */
    +/* return non-zero if pattern has any glob chars in it */
    +API_EXPORT(int) ap_is_fnmatch(const char *pattern)
    +{
    +    int nesting;
    +
    +    nesting = 0;
    +    while (*pattern) {
    +	switch (*pattern) {
    +	case '?':
    +	case '*':
    +	    return 1;
    +
    +	case '\\':
    +	    if (*pattern++ == '\0') {
    +		return 0;
    +	    }
    +	    break;
    +
    +	case '[':	/* '[' is only a glob if it has a matching ']' */
    +	    ++nesting;
    +	    break;
    +
    +	case ']':
    +	    if (nesting)
    +		return 1;
    +	    break;
    +	}
    +	++pattern;
    +    }
    +    return 0;
    +}
    diff --git a/APACHE_1_3b7/src/ap/ap_md5c.c b/APACHE_1_3b7/src/ap/ap_md5c.c
    new file mode 100644
    index 0000000000..72ee3fea66
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap_md5c.c
    @@ -0,0 +1,392 @@
    +/*
    + * This is work is derived from material Copyright RSA Data Security, Inc.
    + *
    + * The RSA copyright statement and Licence for that original material is
    + * included below. This is followed by the Apache copyright statement and
    + * licence for the modifications made to that material.
    + */
    +
    +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
    + */
    +
    +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
    +   rights reserved.
    +
    +   License to copy and use this software is granted provided that it
    +   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
    +   Algorithm" in all material mentioning or referencing this software
    +   or this function.
    +
    +   License is also granted to make and use derivative works provided
    +   that such works are identified as "derived from the RSA Data
    +   Security, Inc. MD5 Message-Digest Algorithm" in all material
    +   mentioning or referencing the derived work.
    +
    +   RSA Data Security, Inc. makes no representations concerning either
    +   the merchantability of this software or the suitability of this
    +   software for any particular purpose. It is provided "as is"
    +   without express or implied warranty of any kind.
    +
    +   These notices must be retained in any copies of any part of this
    +   documentation and/or software.
    + */
    +
    +/* ====================================================================
    + * Copyright (c) 1996-1998 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/>.
    + *
    + */
    +
    +#include <string.h>
    +
    +#include "conf.h"
    +#include "md5.h"
    +#ifdef CHARSET_EBCDIC
    +#include "ebcdic.h"
    +#endif /*CHARSET_EBCDIC*/
    +
    +/* Constants for MD5Transform routine.
    + */
    +
    +#define S11 7
    +#define S12 12
    +#define S13 17
    +#define S14 22
    +#define S21 5
    +#define S22 9
    +#define S23 14
    +#define S24 20
    +#define S31 4
    +#define S32 11
    +#define S33 16
    +#define S34 23
    +#define S41 6
    +#define S42 10
    +#define S43 15
    +#define S44 21
    +
    +static void MD5Transform(UINT4 state[4], const unsigned char block[64]);
    +static void Encode(unsigned char *output, const UINT4 *input,
    +		   unsigned int len);
    +static void Decode(UINT4 *output, const unsigned char *input,
    +		   unsigned int len);
    +
    +static unsigned char PADDING[64] =
    +{
    +    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    +};
    +
    +/* F, G, H and I are basic MD5 functions.
    + */
    +#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
    +#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
    +#define H(x, y, z) ((x) ^ (y) ^ (z))
    +#define I(x, y, z) ((y) ^ ((x) | (~z)))
    +
    +/* ROTATE_LEFT rotates x left n bits.
    + */
    +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
    +
    +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
    +   Rotation is separate from addition to prevent recomputation.
    + */
    +#define FF(a, b, c, d, x, s, ac) { \
    + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
    + (a) = ROTATE_LEFT ((a), (s)); \
    + (a) += (b); \
    +  }
    +#define GG(a, b, c, d, x, s, ac) { \
    + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
    + (a) = ROTATE_LEFT ((a), (s)); \
    + (a) += (b); \
    +  }
    +#define HH(a, b, c, d, x, s, ac) { \
    + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
    + (a) = ROTATE_LEFT ((a), (s)); \
    + (a) += (b); \
    +  }
    +#define II(a, b, c, d, x, s, ac) { \
    + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
    + (a) = ROTATE_LEFT ((a), (s)); \
    + (a) += (b); \
    +  }
    +
    +/* MD5 initialization. Begins an MD5 operation, writing a new context.
    + */
    +API_EXPORT(void) ap_MD5Init(AP_MD5_CTX * context)
    +{
    +    context->count[0] = context->count[1] = 0;
    +    /* Load magic initialization constants. */
    +    context->state[0] = 0x67452301;
    +    context->state[1] = 0xefcdab89;
    +    context->state[2] = 0x98badcfe;
    +    context->state[3] = 0x10325476;
    +}
    +
    +/* MD5 block update operation. Continues an MD5 message-digest
    +   operation, processing another message block, and updating the
    +   context.
    + */
    +API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input,
    +			   unsigned int inputLen)
    +{
    +    unsigned int i, idx, partLen;
    +
    +    /* Compute number of bytes mod 64 */
    +    idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
    +
    +    /* Update number of bits */
    +    if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
    +	context->count[1]++;
    +    context->count[1] += (UINT4) inputLen >> 29;
    +
    +    partLen = 64 - idx;
    +
    +    /* Transform as many times as possible. */
    +#ifndef CHARSET_EBCDIC
    +    if (inputLen >= partLen) {
    +	memcpy(&context->buffer[idx], input, partLen);
    +	MD5Transform(context->state, context->buffer);
    +
    +	for (i = partLen; i + 63 < inputLen; i += 64)
    +	    MD5Transform(context->state, &input[i]);
    +
    +	idx = 0;
    +    }
    +    else
    +	i = 0;
    +
    +    /* Buffer remaining input */
    +    memcpy(&context->buffer[idx], &input[i], inputLen - i);
    +#else /*CHARSET_EBCDIC*/
    +    if (inputLen >= partLen) {
    +	ebcdic2ascii_strictly(&context->buffer[idx], input, partLen);
    +	MD5Transform(context->state, context->buffer);
    +
    +	for (i = partLen; i + 63 < inputLen; i += 64) {
    +	    unsigned char inp_tmp[64];
    +	    ebcdic2ascii_strictly(inp_tmp, &input[i], 64);
    +	    MD5Transform(context->state, inp_tmp);
    +	}
    +
    +	idx = 0;
    +    }
    +    else
    +	i = 0;
    +
    +    /* Buffer remaining input */
    +    ebcdic2ascii_strictly(&context->buffer[idx], &input[i], inputLen - i);
    +#endif /*CHARSET_EBCDIC*/
    +}
    +
    +/* MD5 finalization. Ends an MD5 message-digest operation, writing the
    +   the message digest and zeroizing the context.
    + */
    +API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX * context)
    +{
    +    unsigned char bits[8];
    +    unsigned int idx, padLen;
    +
    +
    +    /* Save number of bits */
    +    Encode(bits, context->count, 8);
    +
    +#ifdef CHARSET_EBCDIC
    +    /* XXX: @@@: In order to make this no more complex than necessary,
    +     * this kludge converts the bits[] array using the ascii-to-ebcdic
    +     * table, because the following ap_MD5Update() re-translates
    +     * its input (ebcdic-to-ascii).
    +     * Otherwise, we would have to pass a "conversion" flag to ap_MD5Update()
    +     */
    +    ascii2ebcdic(bits,bits,8);
    +
    +    /* Since everything is converted to ascii within ap_MD5Update(), 
    +     * the initial 0x80 (PADDING[0]) must be stored as 0x20 
    +     */
    +    PADDING[0] = os_toebcdic[0x80];
    +#endif /*CHARSET_EBCDIC*/
    +
    +    /* Pad out to 56 mod 64. */
    +    idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
    +    padLen = (idx < 56) ? (56 - idx) : (120 - idx);
    +    ap_MD5Update(context, PADDING, padLen);
    +
    +    /* Append length (before padding) */
    +    ap_MD5Update(context, bits, 8);
    +
    +    /* Store state in digest */
    +    Encode(digest, context->state, 16);
    +
    +    /* Zeroize sensitive information. */
    +    memset(context, 0, sizeof(*context));
    +}
    +
    +/* MD5 basic transformation. Transforms state based on block. */
    +static void MD5Transform(UINT4 state[4], const unsigned char block[64])
    +{
    +    UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
    +
    +    Decode(x, block, 64);
    +
    +    /* Round 1 */
    +    FF(a, b, c, d, x[0], S11, 0xd76aa478);	/* 1 */
    +    FF(d, a, b, c, x[1], S12, 0xe8c7b756);	/* 2 */
    +    FF(c, d, a, b, x[2], S13, 0x242070db);	/* 3 */
    +    FF(b, c, d, a, x[3], S14, 0xc1bdceee);	/* 4 */
    +    FF(a, b, c, d, x[4], S11, 0xf57c0faf);	/* 5 */
    +    FF(d, a, b, c, x[5], S12, 0x4787c62a);	/* 6 */
    +    FF(c, d, a, b, x[6], S13, 0xa8304613);	/* 7 */
    +    FF(b, c, d, a, x[7], S14, 0xfd469501);	/* 8 */
    +    FF(a, b, c, d, x[8], S11, 0x698098d8);	/* 9 */
    +    FF(d, a, b, c, x[9], S12, 0x8b44f7af);	/* 10 */
    +    FF(c, d, a, b, x[10], S13, 0xffff5bb1);	/* 11 */
    +    FF(b, c, d, a, x[11], S14, 0x895cd7be);	/* 12 */
    +    FF(a, b, c, d, x[12], S11, 0x6b901122);	/* 13 */
    +    FF(d, a, b, c, x[13], S12, 0xfd987193);	/* 14 */
    +    FF(c, d, a, b, x[14], S13, 0xa679438e);	/* 15 */
    +    FF(b, c, d, a, x[15], S14, 0x49b40821);	/* 16 */
    +
    +    /* Round 2 */
    +    GG(a, b, c, d, x[1], S21, 0xf61e2562);	/* 17 */
    +    GG(d, a, b, c, x[6], S22, 0xc040b340);	/* 18 */
    +    GG(c, d, a, b, x[11], S23, 0x265e5a51);	/* 19 */
    +    GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);	/* 20 */
    +    GG(a, b, c, d, x[5], S21, 0xd62f105d);	/* 21 */
    +    GG(d, a, b, c, x[10], S22, 0x2441453);	/* 22 */
    +    GG(c, d, a, b, x[15], S23, 0xd8a1e681);	/* 23 */
    +    GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);	/* 24 */
    +    GG(a, b, c, d, x[9], S21, 0x21e1cde6);	/* 25 */
    +    GG(d, a, b, c, x[14], S22, 0xc33707d6);	/* 26 */
    +    GG(c, d, a, b, x[3], S23, 0xf4d50d87);	/* 27 */
    +    GG(b, c, d, a, x[8], S24, 0x455a14ed);	/* 28 */
    +    GG(a, b, c, d, x[13], S21, 0xa9e3e905);	/* 29 */
    +    GG(d, a, b, c, x[2], S22, 0xfcefa3f8);	/* 30 */
    +    GG(c, d, a, b, x[7], S23, 0x676f02d9);	/* 31 */
    +    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);	/* 32 */
    +
    +    /* Round 3 */
    +    HH(a, b, c, d, x[5], S31, 0xfffa3942);	/* 33 */
    +    HH(d, a, b, c, x[8], S32, 0x8771f681);	/* 34 */
    +    HH(c, d, a, b, x[11], S33, 0x6d9d6122);	/* 35 */
    +    HH(b, c, d, a, x[14], S34, 0xfde5380c);	/* 36 */
    +    HH(a, b, c, d, x[1], S31, 0xa4beea44);	/* 37 */
    +    HH(d, a, b, c, x[4], S32, 0x4bdecfa9);	/* 38 */
    +    HH(c, d, a, b, x[7], S33, 0xf6bb4b60);	/* 39 */
    +    HH(b, c, d, a, x[10], S34, 0xbebfbc70);	/* 40 */
    +    HH(a, b, c, d, x[13], S31, 0x289b7ec6);	/* 41 */
    +    HH(d, a, b, c, x[0], S32, 0xeaa127fa);	/* 42 */
    +    HH(c, d, a, b, x[3], S33, 0xd4ef3085);	/* 43 */
    +    HH(b, c, d, a, x[6], S34, 0x4881d05);	/* 44 */
    +    HH(a, b, c, d, x[9], S31, 0xd9d4d039);	/* 45 */
    +    HH(d, a, b, c, x[12], S32, 0xe6db99e5);	/* 46 */
    +    HH(c, d, a, b, x[15], S33, 0x1fa27cf8);	/* 47 */
    +    HH(b, c, d, a, x[2], S34, 0xc4ac5665);	/* 48 */
    +
    +    /* Round 4 */
    +    II(a, b, c, d, x[0], S41, 0xf4292244);	/* 49 */
    +    II(d, a, b, c, x[7], S42, 0x432aff97);	/* 50 */
    +    II(c, d, a, b, x[14], S43, 0xab9423a7);	/* 51 */
    +    II(b, c, d, a, x[5], S44, 0xfc93a039);	/* 52 */
    +    II(a, b, c, d, x[12], S41, 0x655b59c3);	/* 53 */
    +    II(d, a, b, c, x[3], S42, 0x8f0ccc92);	/* 54 */
    +    II(c, d, a, b, x[10], S43, 0xffeff47d);	/* 55 */
    +    II(b, c, d, a, x[1], S44, 0x85845dd1);	/* 56 */
    +    II(a, b, c, d, x[8], S41, 0x6fa87e4f);	/* 57 */
    +    II(d, a, b, c, x[15], S42, 0xfe2ce6e0);	/* 58 */
    +    II(c, d, a, b, x[6], S43, 0xa3014314);	/* 59 */
    +    II(b, c, d, a, x[13], S44, 0x4e0811a1);	/* 60 */
    +    II(a, b, c, d, x[4], S41, 0xf7537e82);	/* 61 */
    +    II(d, a, b, c, x[11], S42, 0xbd3af235);	/* 62 */
    +    II(c, d, a, b, x[2], S43, 0x2ad7d2bb);	/* 63 */
    +    II(b, c, d, a, x[9], S44, 0xeb86d391);	/* 64 */
    +
    +    state[0] += a;
    +    state[1] += b;
    +    state[2] += c;
    +    state[3] += d;
    +
    +    /* Zeroize sensitive information. */
    +    memset(x, 0, sizeof(x));
    +}
    +
    +/* Encodes input (UINT4) into output (unsigned char). Assumes len is
    +   a multiple of 4.
    + */
    +static void Encode(unsigned char *output, const UINT4 *input, unsigned int len)
    +{
    +    unsigned int i, j;
    +    UINT4 k;
    +
    +    for (i = 0, j = 0; j < len; i++, j += 4) {
    +	k = input[i];
    +	output[j] = (unsigned char) (k & 0xff);
    +	output[j + 1] = (unsigned char) ((k >> 8) & 0xff);
    +	output[j + 2] = (unsigned char) ((k >> 16) & 0xff);
    +	output[j + 3] = (unsigned char) ((k >> 24) & 0xff);
    +    }
    +}
    +
    +/* Decodes input (unsigned char) into output (UINT4). Assumes len is
    +   a multiple of 4.
    + */
    +static void Decode(UINT4 *output, const unsigned char *input, unsigned int len)
    +{
    +    unsigned int i, j;
    +
    +    for (i = 0, j = 0; j < len; i++, j += 4)
    +	output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
    +	    (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
    +}
    diff --git a/APACHE_1_3b7/src/ap/ap_signal.c b/APACHE_1_3b7/src/ap/ap_signal.c
    new file mode 100644
    index 0000000000..26ad707b55
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap_signal.c
    @@ -0,0 +1,83 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +#include "httpd.h"
    +
    +#ifndef NO_USE_SIGACTION
    +/*
    + * Replace standard signal() with the more reliable sigaction equivalent
    + * from W. Richard Stevens' "Advanced Programming in the UNIX Environment"
    + * (the version that does not automatically restart system calls).
    + */
    +Sigfunc *signal(int signo, Sigfunc * func)
    +{
    +    struct sigaction act, oact;
    +
    +    act.sa_handler = func;
    +    sigemptyset(&act.sa_mask);
    +    act.sa_flags = 0;
    +#ifdef  SA_INTERRUPT		/* SunOS */
    +    act.sa_flags |= SA_INTERRUPT;
    +#endif
    +    if (sigaction(signo, &act, &oact) < 0)
    +	return SIG_ERR;
    +    return oact.sa_handler;
    +}
    +#else
    +/* need some function in this file, otherwise the linker on NeXT bitches */
    +void ap_signal_is_not_here(void) {}
    +#endif
    diff --git a/APACHE_1_3b7/src/ap/ap_slack.c b/APACHE_1_3b7/src/ap/ap_slack.c
    new file mode 100644
    index 0000000000..ffad1f1d61
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap_slack.c
    @@ -0,0 +1,116 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +/*
    + * ap_slack.c: File descriptor preallocation
    + * 
    + * 3/21/93 Rob McCool
    + * 1995-96 Many changes by the Apache Group
    + * 
    + */
    +
    +#include "httpd.h"
    +#include "http_log.h"
    +
    +#ifndef NO_SLACK
    +int ap_slack(int fd, int line)
    +{
    +#if !defined(F_DUPFD)
    +    return fd;
    +#else
    +    static int low_warned;
    +    int new_fd;
    +
    +#ifdef HIGH_SLACK_LINE
    +    if (line == AP_SLACK_HIGH && fd < HIGH_SLACK_LINE) {
    +	new_fd = fcntl(fd, F_DUPFD, HIGH_SLACK_LINE);
    +	if (new_fd != -1) {
    +	    close(fd);
    +	    return new_fd;
    +	}
    +    }
    +#endif
    +    /* otherwise just assume line == AP_SLACK_LOW */
    +    if (fd >= LOW_SLACK_LINE) {
    +	return fd;
    +    }
    +    new_fd = fcntl(fd, F_DUPFD, LOW_SLACK_LINE);
    +    if (new_fd == -1) {
    +	if (!low_warned) {
    +	    /* Give them a warning here, because we really can't predict
    +	     * how libraries and such are going to fail.  If we can't
    +	     * do this F_DUPFD there's a good chance that apache has too
    +	     * few descriptors available to it.  Note we don't warn on
    +	     * the high line, because if it fails we'll eventually try
    +	     * the low line...
    +	     */
    +	    ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
    +		        "unable to open a file descriptor above %u, "
    +			"you may need to increase the number of descriptors",
    +			LOW_SLACK_LINE);
    +	    low_warned = 1;
    +	}
    +	return fd;
    +    }
    +    close(fd);
    +    return new_fd;
    +#endif
    +}
    +#else
    +/* need at least one function in the file for some linkers */
    +void ap_slack_is_not_here(void) {}
    +#endif /* NO_SLACK */
    diff --git a/APACHE_1_3b7/src/ap/ap_snprintf.c b/APACHE_1_3b7/src/ap/ap_snprintf.c
    new file mode 100644
    index 0000000000..813f41e639
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap_snprintf.c
    @@ -0,0 +1,1021 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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 code is based on, and used with the permission of, the
    + * SIO stdio-replacement strx_* functions by Panos Tsirigotis
    + * <panos@alumni.cs.colorado.edu> for xinetd.
    + */
    +
    +#include "httpd.h"
    +
    +#include <stdio.h>
    +#include <ctype.h>
    +#include <sys/types.h>
    +#include <stdarg.h>
    +#include <string.h>
    +#include <stdlib.h>
    +#include <math.h>
    +
    +typedef enum {
    +    NO = 0, YES = 1
    +} boolean_e;
    +
    +#define FALSE			0
    +#define TRUE			1
    +#define NUL			'\0'
    +#define INT_NULL		((int *)0)
    +#define WIDE_INT		long
    +
    +typedef WIDE_INT wide_int;
    +typedef unsigned WIDE_INT u_wide_int;
    +typedef int bool_int;
    +
    +#define S_NULL			"(null)"
    +#define S_NULL_LEN		6
    +
    +#define FLOAT_DIGITS		6
    +#define EXPONENT_LENGTH		10
    +
    +/*
    + * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
    + *
    + * XXX: this is a magic number; do not decrease it
    + */
    +#define NUM_BUF_SIZE		512
    +
    +/*
    + * cvt.c - IEEE floating point formatting routines for FreeBSD
    + * from GNU libc-4.6.27.  Modified to be thread safe.
    + */
    +
    +/*
    + *    ap_ecvt converts to decimal
    + *      the number of digits is specified by ndigit
    + *      decpt is set to the position of the decimal point
    + *      sign is set to 0 for positive, 1 for negative
    + */
    +
    +#define	NDIG	80
    +
    +/* buf must have at least NDIG bytes */
    +static char *ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf)
    +{
    +    register int r2;
    +    double fi, fj;
    +    register char *p, *p1;
    +
    +    if (ndigits >= NDIG - 1)
    +	ndigits = NDIG - 2;
    +    r2 = 0;
    +    *sign = 0;
    +    p = &buf[0];
    +    if (arg < 0) {
    +	*sign = 1;
    +	arg = -arg;
    +    }
    +    arg = modf(arg, &fi);
    +    p1 = &buf[NDIG];
    +    /*
    +     * Do integer part
    +     */
    +    if (fi != 0) {
    +	p1 = &buf[NDIG];
    +	while (fi != 0) {
    +	    fj = modf(fi / 10, &fi);
    +	    *--p1 = (int) ((fj + .03) * 10) + '0';
    +	    r2++;
    +	}
    +	while (p1 < &buf[NDIG])
    +	    *p++ = *p1++;
    +    }
    +    else if (arg > 0) {
    +	while ((fj = arg * 10) < 1) {
    +	    arg = fj;
    +	    r2--;
    +	}
    +    }
    +    p1 = &buf[ndigits];
    +    if (eflag == 0)
    +	p1 += r2;
    +    *decpt = r2;
    +    if (p1 < &buf[0]) {
    +	buf[0] = '\0';
    +	return (buf);
    +    }
    +    while (p <= p1 && p < &buf[NDIG]) {
    +	arg *= 10;
    +	arg = modf(arg, &fj);
    +	*p++ = (int) fj + '0';
    +    }
    +    if (p1 >= &buf[NDIG]) {
    +	buf[NDIG - 1] = '\0';
    +	return (buf);
    +    }
    +    p = p1;
    +    *p1 += 5;
    +    while (*p1 > '9') {
    +	*p1 = '0';
    +	if (p1 > buf)
    +	    ++ * --p1;
    +	else {
    +	    *p1 = '1';
    +	    (*decpt)++;
    +	    if (eflag == 0) {
    +		if (p > buf)
    +		    *p = '0';
    +		p++;
    +	    }
    +	}
    +    }
    +    *p = '\0';
    +    return (buf);
    +}
    +
    +static char *ap_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
    +{
    +    return (ap_cvt(arg, ndigits, decpt, sign, 1, buf));
    +}
    +
    +static char *ap_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
    +{
    +    return (ap_cvt(arg, ndigits, decpt, sign, 0, buf));
    +}
    +
    +/*
    + * ap_gcvt  - Floating output conversion to
    + * minimal length string
    + */
    +
    +static char *ap_gcvt(double number, int ndigit, char *buf, boolean_e altform)
    +{
    +    int sign, decpt;
    +    register char *p1, *p2;
    +    register int i;
    +    char buf1[NDIG];
    +
    +    p1 = ap_ecvt(number, ndigit, &decpt, &sign, buf1);
    +    p2 = buf;
    +    if (sign)
    +	*p2++ = '-';
    +    for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
    +	ndigit--;
    +    if ((decpt >= 0 && decpt - ndigit > 4)
    +	|| (decpt < 0 && decpt < -3)) {		/* use E-style */
    +	decpt--;
    +	*p2++ = *p1++;
    +	*p2++ = '.';
    +	for (i = 1; i < ndigit; i++)
    +	    *p2++ = *p1++;
    +	*p2++ = 'e';
    +	if (decpt < 0) {
    +	    decpt = -decpt;
    +	    *p2++ = '-';
    +	}
    +	else
    +	    *p2++ = '+';
    +	if (decpt / 100 > 0)
    +	    *p2++ = decpt / 100 + '0';
    +	if (decpt / 10 > 0)
    +	    *p2++ = (decpt % 100) / 10 + '0';
    +	*p2++ = decpt % 10 + '0';
    +    }
    +    else {
    +	if (decpt <= 0) {
    +	    if (*p1 != '0')
    +		*p2++ = '.';
    +	    while (decpt < 0) {
    +		decpt++;
    +		*p2++ = '0';
    +	    }
    +	}
    +	for (i = 1; i <= ndigit; i++) {
    +	    *p2++ = *p1++;
    +	    if (i == decpt)
    +		*p2++ = '.';
    +	}
    +	if (ndigit < decpt) {
    +	    while (ndigit++ < decpt)
    +		*p2++ = '0';
    +	    *p2++ = '.';
    +	}
    +    }
    +    if (p2[-1] == '.' && !altform)
    +	p2--;
    +    *p2 = '\0';
    +    return (buf);
    +}
    +
    +/*
    + * The INS_CHAR macro inserts a character in the buffer and writes
    + * the buffer back to disk if necessary
    + * It uses the char pointers sp and bep:
    + *      sp points to the next available character in the buffer
    + *      bep points to the end-of-buffer+1
    + * While using this macro, note that the nextb pointer is NOT updated.
    + *
    + * NOTE: Evaluation of the c argument should not have any side-effects
    + */
    +#define INS_CHAR(c, sp, bep, cc)				\
    +	    {							\
    +		if (sp >= bep) {				\
    +		    vbuff->curpos = sp;                         \
    +		    if (flush_func(vbuff))			\
    +			return -1;				\
    +		    sp = vbuff->curpos;				\
    +		    bep = vbuff->endpos;			\
    +		} 						\
    +		*sp++ = (c);					\
    +		cc++; 						\
    +	    }
    +
    +#define NUM( c )			( c - '0' )
    +
    +#define STR_TO_DEC( str, num )		\
    +    num = NUM( *str++ ) ;		\
    +    while ( isdigit( *str ) )		\
    +    {					\
    +	num *= 10 ;			\
    +	num += NUM( *str++ ) ;		\
    +    }
    +
    +/*
    + * This macro does zero padding so that the precision
    + * requirement is satisfied. The padding is done by
    + * adding '0's to the left of the string that is going
    + * to be printed.
    + */
    +#define FIX_PRECISION( adjust, precision, s, s_len )	\
    +    if ( adjust )					\
    +	while ( s_len < precision )			\
    +	{						\
    +	    *--s = '0' ;				\
    +	    s_len++ ;					\
    +	}
    +
    +/*
    + * Macro that does padding. The padding is done by printing
    + * the character ch.
    + */
    +#define PAD( width, len, ch )	do		\
    +	{					\
    +	    INS_CHAR( ch, sp, bep, cc ) ;	\
    +	    width-- ;				\
    +	}					\
    +	while ( width > len )
    +
    +/*
    + * Prefix the character ch to the string str
    + * Increase length
    + * Set the has_prefix flag
    + */
    +#define PREFIX( str, length, ch )	 *--str = ch ; length++ ; has_prefix = YES
    +
    +
    +/*
    + * Convert num to its decimal format.
    + * Return value:
    + *   - a pointer to a string containing the number (no sign)
    + *   - len contains the length of the string
    + *   - is_negative is set to TRUE or FALSE depending on the sign
    + *     of the number (always set to FALSE if is_unsigned is TRUE)
    + *
    + * The caller provides a buffer for the string: that is the buf_end argument
    + * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
    + * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
    + */
    +static char *conv_10(register wide_int num, register bool_int is_unsigned,
    +		     register bool_int *is_negative, char *buf_end,
    +		     register int *len)
    +{
    +    register char *p = buf_end;
    +    register u_wide_int magnitude;
    +
    +    if (is_unsigned) {
    +	magnitude = (u_wide_int) num;
    +	*is_negative = FALSE;
    +    }
    +    else {
    +	*is_negative = (num < 0);
    +
    +	/*
    +	 * On a 2's complement machine, negating the most negative integer 
    +	 * results in a number that cannot be represented as a signed integer.
    +	 * Here is what we do to obtain the number's magnitude:
    +	 *      a. add 1 to the number
    +	 *      b. negate it (becomes positive)
    +	 *      c. convert it to unsigned
    +	 *      d. add 1
    +	 */
    +	if (*is_negative) {
    +	    wide_int t = num + 1;
    +
    +	    magnitude = ((u_wide_int) -t) + 1;
    +	}
    +	else
    +	    magnitude = (u_wide_int) num;
    +    }
    +
    +    /*
    +     * We use a do-while loop so that we write at least 1 digit 
    +     */
    +    do {
    +	register u_wide_int new_magnitude = magnitude / 10;
    +
    +	*--p = (char) (magnitude - new_magnitude * 10 + '0');
    +	magnitude = new_magnitude;
    +    }
    +    while (magnitude);
    +
    +    *len = buf_end - p;
    +    return (p);
    +}
    +
    +
    +
    +static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
    +{
    +    unsigned addr = ntohl(ia->s_addr);
    +    char *p = buf_end;
    +    bool_int is_negative;
    +    int sub_len;
    +
    +    p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);
    +    *--p = '.';
    +    p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);
    +    *--p = '.';
    +    p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
    +    *--p = '.';
    +    p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
    +
    +    *len = buf_end - p;
    +    return (p);
    +}
    +
    +
    +
    +static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len)
    +{
    +    char *p = buf_end;
    +    bool_int is_negative;
    +    int sub_len;
    +
    +    p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
    +    *--p = ':';
    +    p = conv_in_addr(&si->sin_addr, p, &sub_len);
    +
    +    *len = buf_end - p;
    +    return (p);
    +}
    +
    +
    +
    +/*
    + * Convert a floating point number to a string formats 'f', 'e' or 'E'.
    + * The result is placed in buf, and len denotes the length of the string
    + * The sign is returned in the is_negative argument (and is not placed
    + * in buf).
    + */
    +static char *conv_fp(register char format, register double num,
    +    boolean_e add_dp, int precision, bool_int *is_negative,
    +    char *buf, int *len)
    +{
    +    register char *s = buf;
    +    register char *p;
    +    int decimal_point;
    +    char buf1[NDIG];
    +
    +    if (format == 'f')
    +	p = ap_fcvt(num, precision, &decimal_point, is_negative, buf1);
    +    else			/* either e or E format */
    +	p = ap_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
    +
    +    /*
    +     * Check for Infinity and NaN
    +     */
    +    if (isalpha(*p)) {
    +	*len = strlen(strcpy(buf, p));
    +	*is_negative = FALSE;
    +	return (buf);
    +    }
    +
    +    if (format == 'f') {
    +	if (decimal_point <= 0) {
    +	    *s++ = '0';
    +	    if (precision > 0) {
    +		*s++ = '.';
    +		while (decimal_point++ < 0)
    +		    *s++ = '0';
    +	    }
    +	    else if (add_dp)
    +		*s++ = '.';
    +	}
    +	else {
    +	    while (decimal_point-- > 0)
    +		*s++ = *p++;
    +	    if (precision > 0 || add_dp)
    +		*s++ = '.';
    +	}
    +    }
    +    else {
    +	*s++ = *p++;
    +	if (precision > 0 || add_dp)
    +	    *s++ = '.';
    +    }
    +
    +    /*
    +     * copy the rest of p, the NUL is NOT copied
    +     */
    +    while (*p)
    +	*s++ = *p++;
    +
    +    if (format != 'f') {
    +	char temp[EXPONENT_LENGTH];	/* for exponent conversion */
    +	int t_len;
    +	bool_int exponent_is_negative;
    +
    +	*s++ = format;		/* either e or E */
    +	decimal_point--;
    +	if (decimal_point != 0) {
    +	    p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative,
    +			&temp[EXPONENT_LENGTH], &t_len);
    +	    *s++ = exponent_is_negative ? '-' : '+';
    +
    +	    /*
    +	     * Make sure the exponent has at least 2 digits
    +	     */
    +	    if (t_len == 1)
    +		*s++ = '0';
    +	    while (t_len--)
    +		*s++ = *p++;
    +	}
    +	else {
    +	    *s++ = '+';
    +	    *s++ = '0';
    +	    *s++ = '0';
    +	}
    +    }
    +
    +    *len = s - buf;
    +    return (buf);
    +}
    +
    +
    +/*
    + * Convert num to a base X number where X is a power of 2. nbits determines X.
    + * For example, if nbits is 3, we do base 8 conversion
    + * Return value:
    + *      a pointer to a string containing the number
    + *
    + * The caller provides a buffer for the string: that is the buf_end argument
    + * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
    + * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
    + */
    +static char *conv_p2(register u_wide_int num, register int nbits,
    +		     char format, char *buf_end, register int *len)
    +{
    +    register int mask = (1 << nbits) - 1;
    +    register char *p = buf_end;
    +    static const char low_digits[] = "0123456789abcdef";
    +    static const char upper_digits[] = "0123456789ABCDEF";
    +    register const char *digits = (format == 'X') ? upper_digits : low_digits;
    +
    +    do {
    +	*--p = digits[num & mask];
    +	num >>= nbits;
    +    }
    +    while (num);
    +
    +    *len = buf_end - p;
    +    return (p);
    +}
    +
    +
    +/*
    + * Do format conversion placing the output in buffer
    + */
    +API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
    +    ap_vformatter_buff *vbuff, const char *fmt, va_list ap)
    +{
    +    register char *sp;
    +    register char *bep;
    +    register int cc = 0;
    +    register int i;
    +
    +    register char *s = NULL;
    +    char *q;
    +    int s_len;
    +
    +    register int min_width = 0;
    +    int precision = 0;
    +    enum {
    +	LEFT, RIGHT
    +    } adjust;
    +    char pad_char;
    +    char prefix_char;
    +
    +    double fp_num;
    +    wide_int i_num = (wide_int) 0;
    +    u_wide_int ui_num;
    +
    +    char num_buf[NUM_BUF_SIZE];
    +    char char_buf[2];		/* for printing %% and %<unknown> */
    +
    +    /*
    +     * Flag variables
    +     */
    +    boolean_e is_long;
    +    boolean_e alternate_form;
    +    boolean_e print_sign;
    +    boolean_e print_blank;
    +    boolean_e adjust_precision;
    +    boolean_e adjust_width;
    +    bool_int is_negative;
    +
    +    sp = vbuff->curpos;
    +    bep = vbuff->endpos;
    +
    +    while (*fmt) {
    +	if (*fmt != '%') {
    +	    INS_CHAR(*fmt, sp, bep, cc);
    +	}
    +	else {
    +	    /*
    +	     * Default variable settings
    +	     */
    +	    adjust = RIGHT;
    +	    alternate_form = print_sign = print_blank = NO;
    +	    pad_char = ' ';
    +	    prefix_char = NUL;
    +
    +	    fmt++;
    +
    +	    /*
    +	     * Try to avoid checking for flags, width or precision
    +	     */
    +	    if (isascii(*fmt) && !islower(*fmt)) {
    +		/*
    +		 * Recognize flags: -, #, BLANK, +
    +		 */
    +		for (;; fmt++) {
    +		    if (*fmt == '-')
    +			adjust = LEFT;
    +		    else if (*fmt == '+')
    +			print_sign = YES;
    +		    else if (*fmt == '#')
    +			alternate_form = YES;
    +		    else if (*fmt == ' ')
    +			print_blank = YES;
    +		    else if (*fmt == '0')
    +			pad_char = '0';
    +		    else
    +			break;
    +		}
    +
    +		/*
    +		 * Check if a width was specified
    +		 */
    +		if (isdigit(*fmt)) {
    +		    STR_TO_DEC(fmt, min_width);
    +		    adjust_width = YES;
    +		}
    +		else if (*fmt == '*') {
    +		    min_width = va_arg(ap, int);
    +		    fmt++;
    +		    adjust_width = YES;
    +		    if (min_width < 0) {
    +			adjust = LEFT;
    +			min_width = -min_width;
    +		    }
    +		}
    +		else
    +		    adjust_width = NO;
    +
    +		/*
    +		 * Check if a precision was specified
    +		 *
    +		 * XXX: an unreasonable amount of precision may be specified
    +		 * resulting in overflow of num_buf. Currently we
    +		 * ignore this possibility.
    +		 */
    +		if (*fmt == '.') {
    +		    adjust_precision = YES;
    +		    fmt++;
    +		    if (isdigit(*fmt)) {
    +			STR_TO_DEC(fmt, precision);
    +		    }
    +		    else if (*fmt == '*') {
    +			precision = va_arg(ap, int);
    +			fmt++;
    +			if (precision < 0)
    +			    precision = 0;
    +		    }
    +		    else
    +			precision = 0;
    +		}
    +		else
    +		    adjust_precision = NO;
    +	    }
    +	    else
    +		adjust_precision = adjust_width = NO;
    +
    +	    /*
    +	     * Modifier check
    +	     */
    +	    if (*fmt == 'l') {
    +		is_long = YES;
    +		fmt++;
    +	    }
    +	    else {
    +		if (*fmt == 'h')  /* "short" backward compatibility */
    +		    ++fmt;
    +		is_long = NO;
    +	    }
    +
    +	    /*
    +	     * Argument extraction and printing.
    +	     * First we determine the argument type.
    +	     * Then, we convert the argument to a string.
    +	     * On exit from the switch, s points to the string that
    +	     * must be printed, s_len has the length of the string
    +	     * The precision requirements, if any, are reflected in s_len.
    +	     *
    +	     * NOTE: pad_char may be set to '0' because of the 0 flag.
    +	     *   It is reset to ' ' by non-numeric formats
    +	     */
    +	    switch (*fmt) {
    +	    case 'u':
    +		if (is_long)
    +		    i_num = va_arg(ap, u_wide_int);
    +		else
    +		    i_num = (wide_int) va_arg(ap, unsigned int);
    +		s = conv_10(i_num, 1, &is_negative,
    +			    &num_buf[NUM_BUF_SIZE], &s_len);
    +		FIX_PRECISION(adjust_precision, precision, s, s_len);
    +		break;
    +
    +	    case 'd':
    +	    case 'i':
    +		if (is_long)
    +		    i_num = va_arg(ap, wide_int);
    +		else
    +		    i_num = (wide_int) va_arg(ap, int);
    +		s = conv_10(i_num, 0, &is_negative,
    +			    &num_buf[NUM_BUF_SIZE], &s_len);
    +		FIX_PRECISION(adjust_precision, precision, s, s_len);
    +
    +		if (is_negative)
    +		    prefix_char = '-';
    +		else if (print_sign)
    +		    prefix_char = '+';
    +		else if (print_blank)
    +		    prefix_char = ' ';
    +		break;
    +
    +
    +	    case 'o':
    +		if (is_long)
    +		    ui_num = va_arg(ap, u_wide_int);
    +		else
    +		    ui_num = (u_wide_int) va_arg(ap, unsigned int);
    +		s = conv_p2(ui_num, 3, *fmt,
    +			    &num_buf[NUM_BUF_SIZE], &s_len);
    +		FIX_PRECISION(adjust_precision, precision, s, s_len);
    +		if (alternate_form && *s != '0') {
    +		    *--s = '0';
    +		    s_len++;
    +		}
    +		break;
    +
    +
    +	    case 'x':
    +	    case 'X':
    +		if (is_long)
    +		    ui_num = (u_wide_int) va_arg(ap, u_wide_int);
    +		else
    +		    ui_num = (u_wide_int) va_arg(ap, unsigned int);
    +		s = conv_p2(ui_num, 4, *fmt,
    +			    &num_buf[NUM_BUF_SIZE], &s_len);
    +		FIX_PRECISION(adjust_precision, precision, s, s_len);
    +		if (alternate_form && i_num != 0) {
    +		    *--s = *fmt;	/* 'x' or 'X' */
    +		    *--s = '0';
    +		    s_len += 2;
    +		}
    +		break;
    +
    +
    +	    case 's':
    +		s = va_arg(ap, char *);
    +		if (s != NULL) {
    +		    s_len = strlen(s);
    +		    if (adjust_precision && precision < s_len)
    +			s_len = precision;
    +		}
    +		else {
    +		    s = S_NULL;
    +		    s_len = S_NULL_LEN;
    +		}
    +		pad_char = ' ';
    +		break;
    +
    +
    +	    case 'f':
    +	    case 'e':
    +	    case 'E':
    +		fp_num = va_arg(ap, double);
    +		/*
    +		 * * We use &num_buf[ 1 ], so that we have room for the sign
    +		 */
    +		s = conv_fp(*fmt, fp_num, alternate_form,
    +			(adjust_precision == NO) ? FLOAT_DIGITS : precision,
    +			    &is_negative, &num_buf[1], &s_len);
    +		if (is_negative)
    +		    prefix_char = '-';
    +		else if (print_sign)
    +		    prefix_char = '+';
    +		else if (print_blank)
    +		    prefix_char = ' ';
    +		break;
    +
    +
    +	    case 'g':
    +	    case 'G':
    +		if (adjust_precision == NO)
    +		    precision = FLOAT_DIGITS;
    +		else if (precision == 0)
    +		    precision = 1;
    +		/*
    +		 * * We use &num_buf[ 1 ], so that we have room for the sign
    +		 */
    +		s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1],
    +		            alternate_form);
    +		if (*s == '-')
    +		    prefix_char = *s++;
    +		else if (print_sign)
    +		    prefix_char = '+';
    +		else if (print_blank)
    +		    prefix_char = ' ';
    +
    +		s_len = strlen(s);
    +
    +		if (alternate_form && (q = strchr(s, '.')) == NULL) {
    +		    s[s_len++] = '.';
    +		    s[s_len] = '\0'; /* delimit for following strchr() */
    +		}
    +		if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
    +		    *q = 'E';
    +		break;
    +
    +
    +	    case 'c':
    +		char_buf[0] = (char) (va_arg(ap, int));
    +		s = &char_buf[0];
    +		s_len = 1;
    +		pad_char = ' ';
    +		break;
    +
    +
    +	    case '%':
    +		char_buf[0] = '%';
    +		s = &char_buf[0];
    +		s_len = 1;
    +		pad_char = ' ';
    +		break;
    +
    +
    +	    case 'n':
    +		*(va_arg(ap, int *)) = cc;
    +		break;
    +
    +		/*
    +		 * This is where we extend the printf format, with a second
    +		 * type specifier
    +		 */
    +	    case 'p':
    +		switch(*++fmt) {
    +		    /*
    +		     * If the pointer size is equal to the size of an unsigned
    +		     * integer we convert the pointer to a hex number, otherwise 
    +		     * we print "%p" to indicate that we don't handle "%p".
    +		     */
    +		case 'p':
    +		    ui_num = (u_wide_int) va_arg(ap, void *);
    +
    +		    if (sizeof(char *) <= sizeof(u_wide_int))
    +				s = conv_p2(ui_num, 4, 'x',
    +					    &num_buf[NUM_BUF_SIZE], &s_len);
    +		    else {
    +			s = "%p";
    +			s_len = 2;
    +			prefix_char = NUL;
    +		    }
    +		    pad_char = ' ';
    +		    break;
    +
    +		    /* print a struct sockaddr_in as a.b.c.d:port */
    +		case 'I':
    +		    {
    +			struct sockaddr_in *si;
    +
    +			si = va_arg(ap, struct sockaddr_in *);
    +			if (si != NULL) {
    +			    s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
    +			    if (adjust_precision && precision < s_len)
    +				s_len = precision;
    +			}
    +			else {
    +			    s = S_NULL;
    +			    s_len = S_NULL_LEN;
    +			}
    +			pad_char = ' ';
    +		    }
    +		    break;
    +
    +		    /* print a struct in_addr as a.b.c.d */
    +		case 'A':
    +		    {
    +			struct in_addr *ia;
    +
    +			ia = va_arg(ap, struct in_addr *);
    +			if (ia != NULL) {
    +			    s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
    +			    if (adjust_precision && precision < s_len)
    +				s_len = precision;
    +			}
    +			else {
    +			    s = S_NULL;
    +			    s_len = S_NULL_LEN;
    +			}
    +			pad_char = ' ';
    +		    }
    +		    break;
    +
    +		case NUL:
    +		    /* if %p ends the string, oh well ignore it */
    +		    continue;
    +
    +		default:
    +		    s = "bogus %p";
    +		    s_len = 8;
    +		    prefix_char = NUL;
    +		    break;
    +		}
    +		break;
    +
    +	    case NUL:
    +		/*
    +		 * The last character of the format string was %.
    +		 * We ignore it.
    +		 */
    +		continue;
    +
    +
    +		/*
    +		 * The default case is for unrecognized %'s.
    +		 * We print %<char> to help the user identify what
    +		 * option is not understood.
    +		 * This is also useful in case the user wants to pass
    +		 * the output of format_converter to another function
    +		 * that understands some other %<char> (like syslog).
    +		 * Note that we can't point s inside fmt because the
    +		 * unknown <char> could be preceded by width etc.
    +		 */
    +	    default:
    +		char_buf[0] = '%';
    +		char_buf[1] = *fmt;
    +		s = char_buf;
    +		s_len = 2;
    +		pad_char = ' ';
    +		break;
    +	    }
    +
    +	    if (prefix_char != NUL && s != S_NULL && s != char_buf) {
    +		*--s = prefix_char;
    +		s_len++;
    +	    }
    +
    +	    if (adjust_width && adjust == RIGHT && min_width > s_len) {
    +		if (pad_char == '0' && prefix_char != NUL) {
    +		    INS_CHAR(*s, sp, bep, cc);
    +		    s++;
    +		    s_len--;
    +		    min_width--;
    +		}
    +		PAD(min_width, s_len, pad_char);
    +	    }
    +
    +	    /*
    +	     * Print the string s. 
    +	     */
    +	    for (i = s_len; i != 0; i--) {
    +		INS_CHAR(*s, sp, bep, cc);
    +		s++;
    +	    }
    +
    +	    if (adjust_width && adjust == LEFT && min_width > s_len)
    +		PAD(min_width, s_len, pad_char);
    +	}
    +	fmt++;
    +    }
    +    vbuff->curpos = sp;
    +    return cc;
    +}
    +
    +
    +static int snprintf_flush(ap_vformatter_buff *vbuff)
    +{
    +    /* if the buffer fills we have to abort immediately, there is no way
    +     * to "flush" an ap_snprintf... there's nowhere to flush it to.
    +     */
    +    return -1;
    +}
    +
    +
    +API_EXPORT(int) ap_snprintf(char *buf, size_t len, const char *format,...)
    +{
    +    int cc;
    +    va_list ap;
    +    ap_vformatter_buff vbuff;
    +
    +    if (len == 0)
    +	return 0;
    +
    +    /* save one byte for nul terminator */
    +    vbuff.curpos = buf;
    +    vbuff.endpos = buf + len - 1;
    +    va_start(ap, format);
    +    cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
    +    va_end(ap);
    +    *vbuff.curpos = '\0';
    +    return (cc == -1) ? len : cc;
    +}
    +
    +
    +API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
    +			     va_list ap)
    +{
    +    int cc;
    +    ap_vformatter_buff vbuff;
    +
    +    if (len == 0)
    +	return 0;
    +
    +    /* save one byte for nul terminator */
    +    vbuff.curpos = buf;
    +    vbuff.endpos = buf + len - 1;
    +    cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
    +    *vbuff.curpos = '\0';
    +    return (cc == -1) ? len : cc;
    +}
    diff --git a/APACHE_1_3b7/src/ap/ap_strings.c b/APACHE_1_3b7/src/ap/ap_strings.c
    new file mode 100644
    index 0000000000..beeeda4d04
    --- /dev/null
    +++ b/APACHE_1_3b7/src/ap/ap_strings.c
    @@ -0,0 +1,108 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +#include "httpd.h"
    +
    +/*
    + * Given a string, replace any bare " with \" .
    + */
    +API_EXPORT(char *) ap_escape_quotes (pool *p, const char *instring)
    +{
    +    int newlen = 0;
    +    const char *inchr = instring;
    +    char *outchr, *outstring;
    +
    +    /*
    +     * Look through the input string, jogging the length of the output
    +     * string up by an extra byte each time we find an unescaped ".
    +     */
    +    while (*inchr != '\0') {
    +	newlen++;
    +        if (*inchr == '"') {
    +	    newlen++;
    +	}
    +	/*
    +	 * If we find a slosh, and it's not the last byte in the string,
    +	 * it's escaping something - advance past both bytes.
    +	 */
    +	if ((*inchr == '\\') && (inchr[1] != '\0')) {
    +	    inchr++;
    +	}
    +	inchr++;
    +    }
    +    outstring = ap_palloc(p, newlen + 1);
    +    inchr = instring;
    +    outchr = outstring;
    +    /*
    +     * Now copy the input string to the output string, inserting a slosh
    +     * in front of every " that doesn't already have one.
    +     */
    +    while (*inchr != '\0') {
    +	if ((*inchr == '\\') && (inchr[1] != '\0')) {
    +	    *outchr++ = *inchr++;
    +	    *outchr++ = *inchr++;
    +	}
    +	if (*inchr == '"') {
    +	    *outchr++ = '\\';
    +	}
    +	if (*inchr != '\0') {
    +	    *outchr++ = *inchr++;
    +	}
    +    }
    +    *outchr = '\0';
    +    return outstring;
    +}
    diff --git a/APACHE_1_3b7/src/buildmark.c b/APACHE_1_3b7/src/buildmark.c
    new file mode 100644
    index 0000000000..a410e7926d
    --- /dev/null
    +++ b/APACHE_1_3b7/src/buildmark.c
    @@ -0,0 +1,70 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +#include "conf.h"
    +#include "httpd.h"
    +
    +#if defined(__DATE__) && defined(__TIME__)
    +static const char server_built[] = __DATE__ " " __TIME__;
    +#else
    +static const char server_built[] = "unknown";
    +#endif
    +
    +API_EXPORT(const char *) ap_get_server_built()
    +{
    +    return server_built;
    +}
    diff --git a/APACHE_1_3b7/src/helpers/CutRule b/APACHE_1_3b7/src/helpers/CutRule
    new file mode 100755
    index 0000000000..ca4b1f8eab
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/CutRule
    @@ -0,0 +1,8 @@
    +#!/bin/sh
    +# Helper script for Configure - cut a rule from Configuration.
    +# note that there is a tab and a space in the character groups.
    +# Map to lowercase to make tests easier
    +
    +egrep "^[	 ]*Rule[	 ]+$1[	 ]*=" $2 | \
    +awk 'BEGIN {FS="="}{print $2}' | \
    +sed 's/[	 ]//g' | tr "A-Z" "a-z"
    diff --git a/APACHE_1_3b7/src/helpers/GuessOS b/APACHE_1_3b7/src/helpers/GuessOS
    new file mode 100755
    index 0000000000..cae1c1ba54
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/GuessOS
    @@ -0,0 +1,263 @@
    +#!/bin/sh
    +#
    +# Simple OS/Platform guesser. Similar to config.guess but
    +# much, much smaller. Since it was developed for use with
    +# Apache, it follows under Apache's regular licensing
    +# with one specific addition: Any changes or additions
    +# to this script should be Emailed to the Apache
    +# group (apache@apache.org) in general and to
    +# Jim Jagielski (jim@jaguNET.com) in specific.
    +#
    +# Be as similar to the output of config.guess/config.sub
    +# as possible.
    +
    +# First get uname entries that we use below
    +
    +MACHINE=`(uname -m) 2>/dev/null` || MACHINE="unknown"
    +RELEASE=`(uname -r) 2>/dev/null` || RELEASE="unknown"
    +SYSTEM=`(uname -s) 2>/dev/null`  || SYSTEM="unknown"
    +VERSION=`(uname -v) 2>/dev/null` || VERSION="unknown"
    +
    +
    +# Now test for ISC and SCO, since it is has a braindamaged uname.
    +#
    +# We need to work around FreeBSD 1.1.5.1 
    +XREL=`uname -X 2>/dev/null | grep "^Release" | awk '{print $3}'`
    +if [ "x$XREL" != "x" ]; then
    +    if [ -f /etc/kconfig ]; then
    +	case "$XREL" in
    +	    4.0|4.1)
    +		    echo "${MACHINE}-whatever-isc4"; exit 0
    +		;;
    +	esac
    +    else
    +	case "$XREL" in
    +	    3.2v4.2)
    +		echo "whatever-whatever-sco3"; exit 0
    +		;;
    +	    3.2v5.0*)
    +		echo "whatever-whatever-sco5"; exit 0
    +		;;
    +	    4.2MP)
    +		if [ "x$VERSION" = "x2.1.1" ]; then
    +		    echo "${MACHINE}-whatever-unixware211"; exit 0
    +		elif [ "x$VERSION" = "x2.1.2" ]; then
    +		    echo "${MACHINE}-whatever-unixware212"; exit 0
    +		else
    +		    echo "${MACHINE}-whatever-unixware2"; exit 0
    +		fi
    +		;;
    +	    4.2)
    +		echo "whatever-whatever-unixware1"; exit 0
    +		;;
    +	esac
    +    fi
    +fi
    +# Now we simply scan though... In most cases, the SYSTEM info is enough
    +#
    +case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in
    +    MiNT:*)
    +        echo "m68k-atari-mint"; exit 0
    +	;;
    +    A/UX:*)
    +	echo "m68k-apple-aux3"; exit 0
    +	;;
    +
    +    AIX:*)
    +	echo "${MACHINE}-ibm-aix${VERSION}.${RELEASE}"; exit 0
    +	;;
    +
    +    dgux:*)
    +	echo "${MACHINE}-dg-dgux"; exit 0
    +	;;
    +
    +    HI-UX:*)
    +	echo "${MACHINE}-hi-hiux"; exit 0
    +	;;
    +
    +    HP-UX:*)
    +	HPUXVER=`echo ${RELEASE}|sed -e 's/[^.]*.[0B]*//'`
    +	echo "${MACHINE}-hp-hpux${HPUXVER}"; exit 0
    +	;;
    +
    +    IRIX:*)
    +	if [ -f /usr/lib32/mips4/libm.so ]; then
    +	    echo "${MACHINE}-sgi-irix32"; exit 0
    +	else
    +	    echo "${MACHINE}-sgi-irix"; exit 0
    +	fi
    +	;;
    +
    +    IRIX64:*)
    +	echo "${MACHINE}-sgi-irix64"; exit 0
    +	;;
    +
    +    Linux:[2-9].*)
    +	echo "${MACHINE}-whatever-linux2"; exit 0
    +	;;
    +
    +    Linux:1.*)
    +	echo "${MACHINE}-whatever-linux1"; exit 0
    +	;;
    +
    +    LynxOS:*)
    +	echo "${MACHINE}-lynx-lynxos"; exit 0
    +	;;
    +
    +    BSD/386:*:*:*486*|BSD/OS:*:*:*:*486*)
    +	echo "i486-whatever-bsdi"; exit 0
    +	;;
    +
    +    BSD/386:*|BSD/OS:*)
    +	echo "${MACHINE}-whatever-bsdi"; exit 0
    +	;;
    +
    +    FreeBSD:*:*:*486*)
    +	FREEBSDVERS=`echo ${RELEASE}|sed -e 's/[-(].*//'`
    +	echo "i486-whatever-freebsd${FREEBSDVERS}"; exit 0
    +	;;
    +
    +    FreeBSD:*)
    +	FREEBSDVERS=`echo ${RELEASE}|sed -e 's/[-(].*//'`
    +	echo "${MACHINE}-whatever-freebsd${FREEBSDVERS}"; exit 0
    +	;;
    +
    +    NetBSD:*:*:*486*)
    +	echo "i486-whatever-netbsd"; exit 0
    +	;;
    +
    +    NetBSD:*)
    +	echo "${MACHINE}-whatever-netbsd"; exit 0
    +	;;
    +
    +    OpenBSD:*)
    +	echo "${MACHINE}-whatever-openbsd"; exit 0
    +	;;
    +
    +    OSF1:*:*:*alpha*)
    +	echo "${MACHINE}-dec-osf"; exit 0
    +	;;
    +
    +    QNX:*)
    +	case "$VERSION" in
    +	    423)
    +		echo "${MACHINE}-qssl-qnx32"
    +		;;
    +	    *)
    +		echo "${MACHINE}-qssl-qnx"
    +		;;
    +	esac
    +	exit 0
    +	;;
    +
    +    Paragon*:*:*:*)
    +	echo "i860-intel-osf1"; exit 0
    +	;;
    +
    +    SunOS:5.*)
    +	SOLVER=`echo ${RELEASE}|awk -F. '{
    +	    if (NF < 3)
    +		printf "2%s0\n",$2
    +	    else
    +	    	printf "2%s%s\n",$2,$3
    +	}'`
    +	echo "${MACHINE}-sun-solaris2.${SOLVER}"; exit 0
    +	;;
    +
    +    SunOS:*)
    +	echo "${MACHINE}-sun-sunos4"; exit 0
    +	;;
    +
    +    UNIX_System_V:4.*:*)
    +	echo "${MACHINE}-whatever-sysv4"; exit 0
    +	;;
    +
    +    unix:3.0.9*:*:88k)
    +	echo "${MACHINE}-encore-sysv4"; exit 0
    +	;;
    +
    +    *:4*:R4*:m88k)
    +	echo "${MACHINE}-whatever-sysv4"; exit 0
    +	;;
    +
    +    UnixWare:5:99*:*)
    +	# Gemini, beta release of next rev of unixware
    +	echo "${MACHINE}-whatever-unixware212"; exit 0
    +	;;
    +
    +    DYNIX/ptx:4*:*)
    +	echo "${MACHINE}-whatever-sysv4"; exit 0
    +	;;
    +
    +    *:4.0:3.0:3[34]?? | *:4.0:3.0:3[34]??,*)
    +	echo "i486-ncr-sysv4"; exit 0
    +	;;
    +
    +    ULTRIX:*)
    +	echo "${MACHINE}-unknown-ultrix"; exit 0
    +	;;
    +
    +    SINIX-?:* | ReliantUNIX-?:*)
    +	echo "${MACHINE}-sni-sysv4"; exit 0
    +	;;
    +
    +    POSIX*BS2000)
    +	echo "${MACHINE}-sni-sysv4"; exit 0
    +	;;
    +
    +    machten:*)
    +       echo "${MACHINE}-tenon-${SYSTEM}"; exit 0;
    +       ;;
    +
    +    library:*)
    +	echo "${MACHINE}-ncr-sysv4"; exit 0
    +	;;
    +
    +    ConvexOS:*:11.*:*)
    +	echo "${MACHINE}-v11-${SYSTEM}"; exit 0;
    +	;;
    +    
    +    UNIX_SV:*:*:maxion)
    +	echo "${MACHINE}-ccur-sysv4"; exit 0;
    +	;;
    +    
    +    NonStop-UX:4.[02]*:[BC]*:*)
    +	echo "${MACHINE}-tandem-sysv4"; exit 0;
    +	;;
    +
    +    "RISC iX":*)
    +	echo "arm-whatever-riscix"; exit 0;
    +	;;
    +
    +    *:4.0:2:*)
    +	echo "whatever-unisys-sysv4"; exit 0;
    +	;;
    +
    +esac
    +
    +#
    +# Ugg. These are all we can determine by what we know about
    +# the output of uname. Be more creative:
    +#
    +
    +# Do the Apollo stuff first. Here, we just simply assume
    +# that the existance of the /usr/apollo directory is proof
    +# enough
    +if [ -d /usr/apollo ]; then
    +    echo "whatever-apollo-whatever"
    +    exit 0
    +fi
    +
    +# Now NeXT
    +ISNEXT=`hostinfo 2>/dev/null`
    +case "$ISNEXT" in
    +    *NeXT*)
    +	echo "whatever-next-nextstep"; exit 0
    +	;;
    +esac
    +
    +# At this point we gone through all the one's
    +# we know of: Punt
    +
    +echo "${MACHINE}-whatever-${SYSTEM}|${RELEASE}|${VERSION}" 
    +exit 0
    diff --git a/APACHE_1_3b7/src/helpers/MakeLint b/APACHE_1_3b7/src/helpers/MakeLint
    new file mode 100644
    index 0000000000..4ab6bba1c4
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/MakeLint
    @@ -0,0 +1,31 @@
    +#!perl
    +
    +# Create a Configuration.lint with every Module except for the modules
    +# specified in the 'isbad' subroutine.
    +
    +sub isbad
    +{
    +    local($module) = @_;
    +    return 1 if $module =~ /mod_dld/;
    +    return 1 if $module =~ /mod_dld/;
    +    return 1 if $module =~ /mod_auth_msql/;
    +    return 1 if $module =~ /mod_example/;
    +
    +    return 0;
    +}
    +
    +open(TMPL, "Configuration.tmpl") || die "can't open Configuration.tmpl: $!";
    +open(LINT, ">Configuration.lint") || die "can't write Configuration.link: $!";
    +
    +while(<TMPL>)
    +{
    +    next if /^$/;
    +    print LINT if /^[^#]/;
    +    if(/^# AddModule\s+(.*)$/)
    +    {
    +	   $module = $1;
    +	   print LINT "AddModule $module\n" if ! &isbad($module);
    +    }
    +}
    +close(TMPL);
    +close(LINT);
    diff --git a/APACHE_1_3b7/src/helpers/PrintPath b/APACHE_1_3b7/src/helpers/PrintPath
    new file mode 100755
    index 0000000000..847ae7c5fc
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/PrintPath
    @@ -0,0 +1,51 @@
    +#!/bin/sh
    +# Look for $1 somewhere in $PATH. As an extra bonus,
    +#  if $AP_PPSEARCHPATH is set, this will look for $i
    +#  in there instead. Will print out the full pathname unless
    +#  called with the '-s' option
    +#
    +# We do some funny stuff to check to see
    +# if test/[] knows about -x
    +#
    +testfile="pp.t.$$"
    +
    +cat > $testfile <<ENDTEST
    +#!/bin/sh
    +if [ -x / ] || [ -x /bin ] || [ -x /bin/ls ]; then
    + exit 0
    +fi
    +exit 1
    +ENDTEST
    +
    +if `/bin/sh $testfile 2>/dev/null`; then
    +    test_exec_flag="-x"
    +else
    +    test_exec_flag="-r"
    +fi
    +rm -f $testfile
    +
    +if [ "x$1" = "x-s" ]; then
    +    shift
    +else
    +    echo="yes"
    +fi
    +
    +if [ "x$AP_PPSEARCHPATH" = "x" ] ; then
    +    AP_PPSEARCHPATH=$PATH
    +fi
    +
    +for path in `echo $AP_PPSEARCHPATH |
    + sed 's/^:/.:/
    +      s/::/:.:/g
    +      s/:$/:./
    +      s/:/ /g' `
    +do
    +    if [ $test_exec_flag $path/$1 ] && [ ! -d $path/$1 ]; then
    +        if [ "$echo" = "yes" ]; then
    +	    echo $path/$1
    +	fi
    +	exit 0
    +    fi
    +done
    +exit 1
    +
    diff --git a/APACHE_1_3b7/src/helpers/PrintPathOS2 b/APACHE_1_3b7/src/helpers/PrintPathOS2
    new file mode 100644
    index 0000000000..436f1e6f70
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/PrintPathOS2
    @@ -0,0 +1,33 @@
    +#!/bin/sh
    +# Look for $1 somewhere in $PATH. As an extra bonus,
    +#  if $AP_PPSEARCHPATH is set, this will look for $i
    +#  in there instead. Will print out the full pathname unless
    +#  called with the '-s' option
    +#
    +
    +if [ "x$1" = "x-s" ]; then
    +    shift
    +else
    +    echo="yes"
    +fi
    +
    +if [ "x$AP_PPSEARCHPATH" = "x" ] ; then
    +    AP_PPSEARCHPATH=$PATH
    +fi
    +
    +for path in `echo $AP_PPSEARCHPATH |
    + sed 's/^;/.;/
    +      s/;;/;.;/g
    +      s/;$/;./
    +      s/;/ /g
    +      s/\\\\/\\//g' `
    +do
    +    if [ -r $path/$1.exe ] && [ ! -d $path/$1.exe ]; then
    +        if [ "$echo" = "yes" ]; then
    +	    echo $path/$1.exe
    +	fi
    +	exit 0
    +    fi
    +done
    +exit 1
    +
    diff --git a/APACHE_1_3b7/src/helpers/TestCompile b/APACHE_1_3b7/src/helpers/TestCompile
    new file mode 100755
    index 0000000000..85cc5a83a6
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/TestCompile
    @@ -0,0 +1,138 @@
    +#!/bin/sh
    +exstat=1
    +trap 'rm -f Makefile dummy testfunc.c testfunc; exit $exstat' 0 1 2 3 15
    +#
    +# Yet another Apache Configure helper script.
    +# This script tests certain aspects of the compilation
    +# process. Right now, it can perform 3 tests:
    +#
    +# ./helpers/TestCompile lib <libname>
    +#    Which checks to see if <libname> exists on this system
    +#
    +# ./helpers/TestCompile lib <libname> <func>
    +#    Which checks to see if <libname> exists on this system and
    +#    contains func.
    +#
    +# ./helpers/TestCompile func <function>
    +#    Which checks to see if <function> exists
    +#
    +# ./helpers/TestCompile sanity
    +#    Which does a simple sanity check/test compile
    +#
    +# It does these by creating a small mini-makefile, based on
    +# ../Makefile.config and trying to compile a small dummy
    +# program. If the compilation succeeds, we assume the test
    +# was successful as well.
    +#
    +# This must be run as './helpers/TestCompile' from
    +# the ./src directory (same directory that Configure is
    +# located) if you want to test it out. Configure must
    +# also call it as './helpers/TestCompile'
    +#
    +
    +cd ./helpers
    +
    +#
    +# Handle "verbose" and "silent" flags
    +#
    +case "$1" in
    +    "-v")
    +        VERBOSE="yes"
    +	shift
    +	;;
    +    "-s")
    +        VERBOSE="no"
    +	shift
    +	;;
    +esac
    +
    +#
    +# Make sure have the right arguments
    +#
    +
    +case "$1" in
    +    "lib")
    +	if [ "x$2" = "x" ]; then
    +	    exit
    +	fi
    +	TLIB="-l$2"
    +	if [ "$VERBOSE" = "yes" ]; then
    +	    ERRDIR=""
    +	else
    +	    ERRDIR='2>/dev/null'
    +	fi
    +	if [ "x$3" = "x" ]; then
    +	    TARGET='dummy'
    +	else
    +	    TARGET='testfunc'
    +	    echo "void main(void) { $3(); }" > testfunc.c
    +	fi
    +	;;
    +    "sanity")
    +	TLIB=""
    +	if [ "$VERBOSE" = "no" ]; then
    +	    ERRDIR='2>/dev/null'
    +	else
    +	    ERRDIR=""
    +	fi
    +	TARGET='dummy'
    +	;;
    +    "func")
    +	if [ "x$2" = "x" ]; then
    +	    exit
    +	fi
    +	TLIB=""
    +	if [ "$VERBOSE" = "yes" ]; then
    +	    ERRDIR=""
    +	else
    +	    ERRDIR='2>/dev/null'
    +	fi
    +	TARGET='testfunc'
    +	cat <<EOF >testfunc.c
    +void main(void) {
    +    $2();
    +}
    +EOF
    +	;;
    +    *)
    +    	exit
    +	;;
    +esac
    +
    +#
    +# Get makefile settings and build a basic Makefile
    +#
    +rm -f dummy
    +cat ../Makefile.config > Makefile
    +cat <<EOF >> Makefile
    +CFLAGS=\$(OPTIM) \$(CFLAGS1) \$(EXTRA_CFLAGS)
    +LIBS=\$(EXTRA_LIBS) \$(LIBS1)
    +INCLUDES=\$(INCLUDES1) \$(EXTRA_INCLUDES)
    +LDFLAGS=\$(LDFLAGS1) \$(EXTRA_LDFLAGS)
    +
    +dummy:
    +	cd ..; \$(CC) \$(CFLAGS) \$(INCLUDES) \$(LDFLAGS) helpers/dummy.c -o helpers/dummy $TLIB \$(LIBS)
    +
    +testfunc:
    +	cd ..; \$(CC) \$(CFLAGS) \$(INCLUDES) \$(LDFLAGS) helpers/testfunc.c -o helpers/testfunc $TLIB \$(LIBS)
    +EOF
    +
    +# Now run that Makefile
    +eval "make $TARGET >/dev/null $ERRDIR"
    +
    +# And see if dummy exists and is executable, if so, then we
    +# assume the condition we are testing for is good
    +#
    +# Use our PrintPath helper script, knowing that we have
    +# 2 versions of it though... Configure should set AP_PRINTPATH
    +# but if not, just assume we use our "generic" version. We
    +# also use the AP_PPSEARCHPATH "hack" to have PrintPath
    +# just search this directory.
    +
    +if [ "x$AP_PRINTPATH" = "x" ] ; then
    +    AP_PRINTPATH=PrintPath
    +fi
    +
    +if AP_PPSEARCHPATH=`pwd` ./$AP_PRINTPATH -s $TARGET ; then
    +    exstat=0
    +fi
    diff --git a/APACHE_1_3b7/src/helpers/dummy.c b/APACHE_1_3b7/src/helpers/dummy.c
    new file mode 100644
    index 0000000000..b1e4964cbb
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/dummy.c
    @@ -0,0 +1,12 @@
    +/* this file is used by TestLib */
    +/* the extra decl is to shutup gcc -Wmissing-prototypes */
    +extern int foo (const char *c);
    +int foo ( const char *c )
    +{
    +return *c;
    +}
    +int main(void) {
    +    const char *c = '\0';
    +    (void)foo(c);
    +    return 0;
    +}
    diff --git a/APACHE_1_3b7/src/helpers/find-dbm-lib b/APACHE_1_3b7/src/helpers/find-dbm-lib
    new file mode 100644
    index 0000000000..0355965af5
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/find-dbm-lib
    @@ -0,0 +1,43 @@
    +# Our config tool sucks... if this script decides to modify the
    +# LIBS variable it won't be used by any of the other TestCompiles.
    +# So unless we protect ourselves with the found_dbm variable
    +# we'd end up having to do the work twice... and we'd end up putting
    +# two -ldbm -ldbm into the LIBS variable.
    +
    +if [ "x$found_dbm" = "x" ]; then
    +    if ./helpers/TestCompile func dbm_open; then
    +	found_dbm=1
    +    else
    +	found_dbm=0
    +	case "$PLAT" in
    +	    *-linux*)
    +		# many systems don't have -ldbm
    +		DBM_LIB=""
    +		if ./helpers/TestCompile lib dbm dbm_open; then
    +		    DBM_LIB="-ldbm"
    +		elif ./helpers/TestCompile lib ndbm dbm_open; then
    +		    DBM_LIB="-lndbm"
    +		fi
    +		if [ "X$DBM_LIB" != "X" ]; then
    +		    LIBS="$LIBS $DBM_LIB"
    +		    found_dbm=1
    +		fi
    +		;;
    +	    *)
    +		if [ "X$DBM_LIB" != "X" ]; then
    +		    oldLIBS="$LIBS"
    +		    LIBS="$LIBS $DBM_LIB"
    +		    if ./helpers/TestCompile func dbm_open; then
    +			found_dbm=1
    +		    else
    +			found_dbm=0
    +			LIBS="$oldLIBS"
    +		    fi
    +		fi
    +		;;
    +	esac
    +	if [ "X$found_dbm" = "X1" ]; then
    +	    echo " + using $DBM_LIB for DBM support"
    +	fi
    +    fi
    +fi
    diff --git a/APACHE_1_3b7/src/helpers/fmn.sh b/APACHE_1_3b7/src/helpers/fmn.sh
    new file mode 100755
    index 0000000000..02a58864ef
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/fmn.sh
    @@ -0,0 +1,46 @@
    +#!/bin/sh
    +##
    +##  fmn.sh -- find a modules (structure) name
    +##
    +##  Extracted from the Configure script by
    +##  Ralf S. Engelschall <rse@apache.org> for use with 
    +##  Apache's Autoconf-style Interface (APACI).
    +##
    +
    +#   input: the modules source file
    +modfile=$1
    +
    +#   the part from the Configure script
    +tmpfile=/tmp/fmn.tmp.$$
    +rm -f $tmpfile
    +modname=''
    +ext=`echo $modfile | sed 's/^.*\.//'`
    +modbase=`echo $modfile | sed 's/\.[^.]*$//'`
    +if [ x$ext = x$modfile ]; then ext=o; modbase=$modfile; modfile=$modbase.o; fi
    +if [ x$ext = x ] ; then ext=o; modbase=$modfile; fi
    +if [ x$ext = xc ] ; then ext=o; fi
    +if [ -r $modbase.module ] ; then
    +    cat $modbase.module >$tmpfile
    +else
    +    if [ -f $modbase.c ] ; then
    +        modname=`egrep '^module .*;' $modbase.c | head -1 |\
    +                sed 's/^module.*[ 	][ 	]*//' | \
    +                sed 's/[ 	]*;[ 	]*$//'`
    +        if grep "MODULE-DEFINITION-" $modbase.c >/dev/null; then
    +            cat $modbase.c | \
    +            sed '1,/MODULE-DEFINITION-START/d;/MODULE-DEFINITION-END/,$d' >$tmpfile
    +        fi
    +    fi
    +fi              
    +if [ -r $tmpfile ] ; then
    +    modname=`grep "Name:" $tmpfile | sed 's/^.*Name:[ 	]*//'`
    +fi
    +if [ "x$modname" = "x" ] ; then
    +    modname=`echo $modbase | sed 's/^.*\///' | \
    +        sed 's/^mod_//' | sed 's/^lib//' | sed 's/$/_module/'`
    +fi
    +rm -f $tmpfile
    +
    +#   output: the name of the module structure symbol
    +echo "$modname"
    +
    diff --git a/APACHE_1_3b7/src/helpers/fp2rp b/APACHE_1_3b7/src/helpers/fp2rp
    new file mode 100755
    index 0000000000..6c594ba723
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/fp2rp
    @@ -0,0 +1,13 @@
    +#!/bin/sh
    +##
    +## fp2rp -- convert a standard forward path to a reverse dotted path
    +##
    +if [ "x$1" = x. ]; then
    +    rp="."
    +else
    +    rp=""
    +    for pe in `IFS="$IFS/"; echo $1`; do
    +        rp="../$rp"
    +    done
    +fi
    +echo $rp | sed -e 's:/$::'
    diff --git a/APACHE_1_3b7/src/helpers/install.sh b/APACHE_1_3b7/src/helpers/install.sh
    new file mode 100755
    index 0000000000..ef97990ab2
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/install.sh
    @@ -0,0 +1,96 @@
    +#!/bin/sh
    +##
    +##  install.sh -- install a program, script or datafile
    +##
    +##  Based on `install-sh' from the X Consortium's X11R5 distribution
    +##  as of 89/12/18 which is freely available.
    +##  Cleaned up for Apache's Autoconf-style Interface (APACI)
    +##  by Ralf S. Engelschall <rse@apache.org>
    +##
    +
    +#
    +#   put in absolute paths if you don't have them in your path; 
    +#   or use env. vars.
    +#
    +mvprog="${MVPROG-mv}"
    +cpprog="${CPPROG-cp}"
    +chmodprog="${CHMODPROG-chmod}"
    +chownprog="${CHOWNPROG-chown}"
    +chgrpprog="${CHGRPPROG-chgrp}"
    +stripprog="${STRIPPROG-strip}"
    +rmprog="${RMPROG-rm}"
    +
    +#
    +#   parse argument line
    +#
    +instcmd="$mvprog"
    +chmodcmd=""
    +chowncmd=""
    +chgrpcmd=""
    +stripcmd=""
    +rmcmd="$rmprog -f"
    +mvcmd="$mvprog"
    +src=""
    +dst=""
    +while [ ".$1" != . ]; do
    +    case $1 in
    +        -c) instcmd="$cpprog"
    +            shift; continue
    +            ;;
    +        -m) chmodcmd="$chmodprog $2"
    +            shift; shift; continue
    +            ;;
    +        -o) chowncmd="$chownprog $2"
    +            shift; shift; continue
    +            ;;
    +        -g) chgrpcmd="$chgrpprog $2"
    +            shift; shift; continue
    +            ;;
    +        -s) stripcmd="$stripprog"
    +            shift; continue;;
    +        *)  if [ ".$src" = . ]; then
    +                src=$1
    +            else
    +                dst=$1
    +            fi
    +            shift; continue
    +            ;;
    +    esac
    +done
    +if [ ".$src" = . ]; then
    +     echo "install.sh: no input file specified"
    +     exit 1
    +fi
    +if [ ".$dst" = . ]; then
    +     echo "install.sh: no destination specified"
    +     exit 1
    +fi
    +
    +#
    +#  If destination is a directory, append the input filename; if
    +#  your system does not like double slashes in filenames, you may
    +#  need to add some logic
    +#
    +if [ -d $dst ]; then
    +    dst="$dst/`basename $src`"
    +fi
    +
    +#  Make a temp file name in the proper directory.
    +dstdir=`dirname $dst`
    +dsttmp=$dstdir/#inst.$$#
    +
    +#  Move or copy the file name to the temp name
    +$instcmd $src $dsttmp
    +
    +#  And set any options; do chmod last to preserve setuid bits
    +if [ ".$chowncmd" != . ]; then $chowncmd $dsttmp; fi
    +if [ ".$chgrpcmd" != . ]; then $chgrpcmd $dsttmp; fi
    +if [ ".$stripcmd" != . ]; then $stripcmd $dsttmp; fi
    +if [ ".$chmodcmd" != . ]; then $chmodcmd $dsttmp; fi
    +
    +#  Now rename the file to the real destination.
    +$rmcmd $dst
    +$mvcmd $dsttmp $dst
    +
    +exit 0
    +
    diff --git a/APACHE_1_3b7/src/helpers/mfhead b/APACHE_1_3b7/src/helpers/mfhead
    new file mode 100755
    index 0000000000..277c396246
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/mfhead
    @@ -0,0 +1,8 @@
    +#!/bin/sh
    +echo "##"
    +echo "##  Apache Makefile, automatically generated by Configure script."
    +echo "##  Hand-edited changes will be lost if the Configure script is re-run."
    +echo "##  Sources: - `./helpers/fp2rp $1`/Makefile.config (via $2)"
    +echo "##           - ./Makefile.tmpl"
    +echo "##"
    +echo ""
    diff --git a/APACHE_1_3b7/src/helpers/mkdir.sh b/APACHE_1_3b7/src/helpers/mkdir.sh
    new file mode 100755
    index 0000000000..9c960d65a4
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/mkdir.sh
    @@ -0,0 +1,31 @@
    +#!/bin/sh
    +## 
    +##  mkdir.sh -- make directory hierarchy
    +##
    +##  Based on `mkinstalldirs' from Noah Friedman <friedman@prep.ai.mit.edu>
    +##  as of 1994-03-25, which was placed in the Public Domain.
    +##  Cleaned up for Apache's Autoconf-style Interface (APACI)
    +##  by Ralf S. Engelschall <rse@apache.org>
    +##
    +
    +umask 022
    +errstatus=0
    +for file in ${1+"$@"} ; do 
    +    set fnord `echo ":$file" |\
    +               sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
    +    shift
    +    pathcomp=
    +    for d in ${1+"$@"}; do
    +        pathcomp="$pathcomp$d"
    +        case "$pathcomp" in
    +            -* ) pathcomp=./$pathcomp ;;
    +        esac
    +        if test ! -d "$pathcomp"; then
    +            echo "mkdir $pathcomp" 1>&2
    +            mkdir "$pathcomp" || errstatus=$?
    +        fi
    +        pathcomp="$pathcomp/"
    +    done
    +done
    +exit $errstatus
    +
    diff --git a/APACHE_1_3b7/src/helpers/mkshadow.sh b/APACHE_1_3b7/src/helpers/mkshadow.sh
    new file mode 100755
    index 0000000000..8c374a617f
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/mkshadow.sh
    @@ -0,0 +1,83 @@
    +#!/bin/sh
    +##
    +##  mkshadow.sh -- create a shadow tree
    +##
    +##  Written by Ralf S. Engelschall <rse@apache.org>
    +##  for the shadow tree generation option (--shadow) of 
    +##  Apache's Autoconf-style Interface (APACI) 
    +##
    +
    +#   default IFS
    +DIFS=' 	
    +'
    +
    +#   source and destination directory
    +src=`echo $1 | sed -e 's:/$::'`
    +dst=`echo $2 | sed -e 's:/$::'`
    +
    +#   determine if source is an absolute path
    +case $src in
    +    /* ) srcisabs=1 ;;
    +     * ) srcisabs=0 ;;
    +esac
    +
    +#   determine reverse directory to directory
    +case $dst in
    +    /* ) dstrevdir='' ;;
    +     * ) dstrevdir="`$src/helpers/fp2rp $dst`/" ;;
    +esac
    +
    +#   create directory tree at destination
    +if [ ! -d $dst ]; then
    +    mkdir $dst
    +fi
    +DIRS="`cd $src
    +       find . -type d -print |\
    +       sed -e '/\/CVS/d' \
    +           -e '/^\.$/d' \
    +           -e 's:^\./::'`"
    +OIFS="$IFS" IFS="$DIFS"
    +for dir in $DIRS; do
    +    mkdir $dst/$dir
    +done
    +IFS="$OIFS"
    +
    +#   fill directory tree with symlinks to files
    +FILES="`cd $src
    +        find . -type f -depth -print |\
    +        sed -e '/\.o$/d' \
    +            -e '/\.a$/d' \
    +            -e '/\.so$/d' \
    +            -e '/\.so-o$/d' \
    +            -e '/\.cvsignore$/d' \
    +            -e '/\/CVS/d' \
    +            -e '/\.indent\.pro$/d' \
    +            -e '/\.apaci.*/d' \
    +            -e '/Makefile$/d' \
    +            -e '/\/\.#/d' \
    +            -e '/\.orig$/d' \
    +            -e 's/^\.\///'`"
    +OIFS="$IFS" IFS="$DIFS"
    +for file in $FILES; do
    +     basename=`echo $file | sed -e 's:^.*/::'`
    +     dir=`echo $file | sed -e 's:[^/]*$::' -e 's:/$::' -e 's:$:/:' -e 's:^/$::'`
    +     from="$src/$file"
    +     to="$dst/$dir$basename"
    +     if [ $srcisabs = 0 -a ".$dir" != . ]; then
    +         subdir=`echo $dir | sed -e 's:/$::'`
    +         #   (inlined fp2rp)
    +         revdir=''
    +         OIFS2="$IFS"; IFS='/'
    +         for pe in $subdir; do
    +             revdir="../$revdir"
    +         done
    +         IFS="$OIFS2"
    +         #   finalize from
    +         from="$revdir$from"
    +     fi
    +     from="$dstrevdir$from"
    +     echo "    $to"
    +     ln -s $from $to
    +done
    +IFS="$OIFS"
    +
    diff --git a/APACHE_1_3b7/src/helpers/ppl.sh b/APACHE_1_3b7/src/helpers/ppl.sh
    new file mode 100755
    index 0000000000..fccd992f39
    --- /dev/null
    +++ b/APACHE_1_3b7/src/helpers/ppl.sh
    @@ -0,0 +1,51 @@
    +#!/bin/sh
    +##
    +##  ppl.sh -- pretty print a colon-sperarated list by avoiding 
    +##            `tr' and `fmt' because these tools are different
    +##            between Unix platforms
    +##
    +##  Written by Ralf S. Engelschall <rse@apache.org>
    +##  for pretty printing lists in the --help option of
    +##  Apache's Autoconf-style Interface (APACI)
    +##
    +
    +list=`
    +IFS=:
    +for entry in $*; do
    +    if [ ".$entry" != . ]; then
    +        echo $entry
    +    fi
    +done |\
    +sort |\
    +awk '
    +    BEGIN { list = ""; n = 0; }
    +    { 
    +        list = list $1;
    +        n = n + 1;
    +        if (n == 1 || n == 2) {
    +            list = list ":";
    +        }
    +        if (n == 3) {
    +            list = list "\n";
    +            n = 0;
    +        }
    +    }
    +    END { print list; }
    +'`
    +IFS='
    +'
    +for entry in $list; do
    +    echo $entry |\
    +    awk -F: '
    +        { printf("%-15s %-15s %-15s\n", $1, $2, $3); }
    +    '
    +done |\
    +awk '{ 
    +    if (length($0) > 48) { 
    +        printf("%s\n", substr($0, 0, 47));
    +    } else { 
    +        print $0; 
    +    }
    +}' |\
    +sed -e 's/^/                        [/' -e 's/$/]/'
    +
    diff --git a/APACHE_1_3b7/src/include/.cvsignore b/APACHE_1_3b7/src/include/.cvsignore
    new file mode 100644
    index 0000000000..69299dc681
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/.cvsignore
    @@ -0,0 +1 @@
    +ap_config.h
    diff --git a/APACHE_1_3b7/src/include/.indent.pro b/APACHE_1_3b7/src/include/.indent.pro
    new file mode 100644
    index 0000000000..a9fbe9f9a1
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/.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/APACHE_1_3b7/src/include/alloc.h b/APACHE_1_3b7/src/include/alloc.h
    new file mode 100644
    index 0000000000..ce13079036
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/alloc.h
    @@ -0,0 +1,332 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_ALLOC_H
    +#define APACHE_ALLOC_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/*
    + * Resource allocation routines...
    + *
    + * designed so that we don't have to keep track of EVERYTHING so that
    + * it can be explicitly freed later (a fundamentally unsound strategy ---
    + * particularly in the presence of die()).
    + *
    + * Instead, we maintain pools, and allocate items (both memory and I/O
    + * handlers) from the pools --- currently there are two, one for per
    + * transaction info, and one for config info.  When a transaction is over,
    + * we can delete everything in the per-transaction pool without fear, and
    + * without thinking too hard about it either.
    + *
    + * rst
    + */
    +
    +/* Arenas for configuration info and transaction info
    + * --- actual layout of the pool structure is private to 
    + * alloc.c.  
    + */
    +
    + /* Need declaration of DIR on Win32 */
    +#ifdef WIN32
    +#include "../os/win32/readdir.h"
    +#endif
    +
    +typedef struct pool pool;
    +typedef struct pool ap_pool;
    +
    +pool * ap_init_alloc(void);		/* Set up everything */
    +API_EXPORT(pool *) ap_make_sub_pool(pool *);	/* All pools are subpools of permanent_pool */
    +API_EXPORT(void) ap_destroy_pool(pool *);
    +
    +/* used to guarantee to the pool debugging code that the sub pool will not be
    + * destroyed before the parent pool
    + */
    +#ifndef POOL_DEBUG
    +#ifdef ap_pool_join
    +#undef ap_pool_join
    +#endif
    +#define ap_pool_join(a,b)
    +#else
    +API_EXPORT(void) ap_pool_join(pool *p, pool *sub);
    +API_EXPORT(pool *) ap_find_pool(const void *ts);
    +API_EXPORT(int) ap_pool_is_ancestor(pool *a, pool *b);
    +#endif
    +
    +/* Clearing out EVERYTHING in an pool... destroys any sub-pools */
    +
    +API_EXPORT(void) ap_clear_pool(struct pool *);
    +
    +/* Preparing for exec() --- close files, etc., but *don't* flush I/O
    + * buffers, *don't* wait for subprocesses, and *don't* free any memory.
    + */
    +
    +API_EXPORT(void) ap_cleanup_for_exec(void);
    +
    +/* routines to allocate memory from an pool... */
    +
    +API_EXPORT(void *) ap_palloc(struct pool *, int nbytes);
    +API_EXPORT(void *) ap_pcalloc(struct pool *, int nbytes);
    +API_EXPORT(char *) ap_pstrdup(struct pool *, const char *s);
    +/* make a nul terminated copy of the n characters starting with s */
    +API_EXPORT(char *) ap_pstrndup(struct pool *, const char *s, int n);
    +API_EXPORT_NONSTD(char *) ap_pstrcat(struct pool *,...);	/* all '...' must be char* */
    +API_EXPORT_NONSTD(char *) ap_psprintf(struct pool *, const char *fmt, ...)
    +    __attribute__((format(printf,2,3)));
    +API_EXPORT(char *) ap_pvsprintf(struct pool *, const char *fmt, va_list);
    +
    +/* array and alist management... keeping lists of things.
    + * Common enough to want common support code ...
    + */
    +
    +typedef struct {
    +    ap_pool *pool;
    +    int elt_size;
    +    int nelts;
    +    int nalloc;
    +    char *elts;
    +} array_header;
    +
    +API_EXPORT(array_header *) ap_make_array(pool *p, int nelts, int elt_size);
    +API_EXPORT(void *) ap_push_array(array_header *);
    +API_EXPORT(void) ap_array_cat(array_header *dst, const array_header *src);
    +API_EXPORT(array_header *) ap_append_arrays(pool *, const array_header *,
    +					 const array_header *);
    +
    +/* copy_array copies the *entire* array.  copy_array_hdr just copies
    + * the header, and arranges for the elements to be copied if (and only
    + * if) the code subsequently does a push or arraycat.
    + */
    +
    +API_EXPORT(array_header *) ap_copy_array(pool *p, const array_header *src);
    +API_EXPORT(array_header *) ap_copy_array_hdr(pool *p, const array_header *src);
    +
    +
    +/* Tables.  Implemented alist style, for now, though we try to keep
    + * it so that imposing a hash table structure on top in the future
    + * wouldn't be *too* hard...
    + *
    + * Note that key comparisons for these are case-insensitive, largely
    + * because that's what's appropriate and convenient everywhere they're
    + * currently being used...
    + */
    +
    +typedef struct table table;
    +
    +typedef struct {
    +    char *key;		/* maybe NULL in future;
    +			 * check when iterating thru table_elts
    +			 */
    +    char *val;
    +} table_entry;
    +
    +API_EXPORT(table *) ap_make_table(pool *p, int nelts);
    +API_EXPORT(table *) ap_copy_table(pool *p, const table *);
    +API_EXPORT(void) ap_clear_table(table *);
    +API_EXPORT(char *) ap_table_get(const table *, const char *);
    +API_EXPORT(void) ap_table_set(table *, const char *name, const char *val);
    +API_EXPORT(void) ap_table_setn(table *, const char *name, const char *val);
    +API_EXPORT(void) ap_table_merge(table *, const char *name, const char *more_val);
    +API_EXPORT(void) ap_table_mergen(table *, const char *name, const char *more_val);
    +API_EXPORT(void) ap_table_unset(table *, const char *key);
    +API_EXPORT(void) ap_table_add(table *, const char *name, const char *val);
    +API_EXPORT(void) ap_table_addn(table *, const char *name, const char *val);
    +API_EXPORT(void) ap_table_do(int (*comp) (void *, const char *, const char *), void *rec,
    +			  const table *t,...);
    +
    +API_EXPORT(table *) ap_overlay_tables(pool *p, const table *overlay, const table *base);
    +
    +/* XXX: these know about the definition of struct table in alloc.c.  That
    + * definition is not here because it is supposed to be private, and by not
    + * placing it here we are able to get compile-time diagnostics from modules
    + * written which assume that a table is the same as an array_header. -djg
    + */
    +#define table_elts(t) ((array_header *)(t))
    +#define is_empty_table(t) (((t) == NULL)||(((array_header *)(t))->nelts == 0))
    +
    +/* routines to remember allocation of other sorts of things...
    + * generic interface first.  Note that we want to have two separate
    + * cleanup functions in the general case, one for exec() preparation,
    + * to keep CGI scripts and the like from inheriting access to things
    + * they shouldn't be able to touch, and one for actually cleaning up,
    + * when the actual server process wants to get rid of the thing,
    + * whatever it is.  
    + *
    + * kill_cleanup disarms a cleanup, presumably because the resource in
    + * question has been closed, freed, or whatever, and it's scarce
    + * enough to want to reclaim (e.g., descriptors).  It arranges for the
    + * resource not to be cleaned up a second time (it might have been
    + * reallocated).  run_cleanup does the same, but runs it first.
    + *
    + * Cleanups are identified for purposes of finding & running them off by the
    + * plain_cleanup and data, which should presumably be unique.
    + *
    + * NB any code which invokes register_cleanup or kill_cleanup directly
    + * is a critical section which should be guarded by block_alarms() and
    + * unblock_alarms() below...
    + */
    +
    +API_EXPORT(void) ap_register_cleanup(pool *p, void *data,
    +				  void (*plain_cleanup) (void *),
    +				  void (*child_cleanup) (void *));
    +
    +API_EXPORT(void) ap_kill_cleanup(pool *p, void *data, void (*plain_cleanup) (void *));
    +API_EXPORT(void) ap_run_cleanup(pool *p, void *data, void (*cleanup) (void *));
    +
    +/* A "do-nothing" cleanup, for register_cleanup; it's faster to do
    + * things this way than to test for NULL. */
    +API_EXPORT_NONSTD(void) ap_null_cleanup(void *data);
    +
    +/* The time between when a resource is actually allocated, and when it
    + * its cleanup is registered is a critical section, during which the
    + * resource could leak if we got interrupted or timed out.  So, anything
    + * which registers cleanups should bracket resource allocation and the
    + * cleanup registry with these.  (This is done internally by run_cleanup).
    + *
    + * NB they are actually implemented in http_main.c, since they are bound
    + * up with timeout handling in general...
    + */
    +
    +API_EXPORT(void) ap_block_alarms(void);
    +API_EXPORT(void) ap_unblock_alarms(void);
    +
    +/* Common cases which want utility support..
    + * the note_cleanups_for_foo routines are for 
    + */
    +
    +API_EXPORT(FILE *) ap_pfopen(struct pool *, const char *name, const char *fmode);
    +API_EXPORT(FILE *) ap_pfdopen(struct pool *, int fd, const char *fmode);
    +API_EXPORT(int) ap_popenf(struct pool *, const char *name, int flg, int mode);
    +
    +API_EXPORT(void) ap_note_cleanups_for_file(pool *, FILE *);
    +API_EXPORT(void) ap_note_cleanups_for_fd(pool *, int);
    +#ifdef WIN32
    +API_EXPORT(void) ap_note_cleanups_for_h(pool *, HANDLE);
    +#endif
    +API_EXPORT(void) ap_kill_cleanups_for_fd(pool *p, int fd);
    +
    +API_EXPORT(void) ap_note_cleanups_for_socket(pool *, int);
    +API_EXPORT(void) ap_kill_cleanups_for_socket(pool *p, int sock);
    +API_EXPORT(int) ap_psocket(pool *p, int, int, int);
    +API_EXPORT(int) ap_pclosesocket(pool *a, int sock);
    +
    +API_EXPORT(regex_t *) ap_pregcomp(pool *p, const char *pattern, int cflags);
    +API_EXPORT(void) ap_pregfree(pool *p, regex_t * reg);
    +
    +/* routines to note closes... file descriptors are constrained enough
    + * on some systems that we want to support this.
    + */
    +
    +API_EXPORT(int) ap_pfclose(struct pool *, FILE *);
    +API_EXPORT(int) ap_pclosef(struct pool *, int fd);
    +#ifdef WIN32
    +API_EXPORT(int) ap_pcloseh(struct pool *, HANDLE hDevice);
    +#endif
    +
    +/* routines to deal with directories */
    +API_EXPORT(DIR *) ap_popendir(pool *p, const char *name);
    +API_EXPORT(void) ap_pclosedir(pool *p, DIR * d);
    +
    +/* ... even child processes (which we may want to wait for,
    + * or to kill outright, on unexpected termination).
    + *
    + * spawn_child is a utility routine which handles an awful lot of
    + * the rigamarole associated with spawning a child --- it arranges
    + * for pipes to the child's stdin and stdout, if desired (if not,
    + * set the associated args to NULL).  It takes as args a function
    + * to call in the child, and an argument to be passed to the function.
    + */
    +
    +enum kill_conditions {
    +    kill_never,			/* process is never sent any signals */
    +    kill_always,		/* process is sent SIGKILL on pool cleanup */
    +    kill_after_timeout,		/* SIGTERM, wait 3 seconds, SIGKILL */
    +    just_wait,			/* wait forever for the process to complete */
    +    kill_only_once		/* send SIGTERM and then wait */
    +};
    +
    +typedef struct child_info child_info;
    +API_EXPORT(void) ap_note_subprocess(pool *a, int pid,
    +				    enum kill_conditions how);
    +API_EXPORT(int) ap_spawn_child_err(pool *, int (*)(void *, child_info *),
    +				   void *, enum kill_conditions,
    +				   FILE **pipe_in, FILE **pipe_out,
    +				   FILE **pipe_err);
    +#define spawn_child(p,f,v,k,in,out) ap_spawn_child_err(p,f,v,k,in,out,NULL)
    +
    +/* magic numbers --- min free bytes to consider a free pool block useable,
    + * and the min amount to allocate if we have to go to malloc() */
    +
    +#ifndef BLOCK_MINFREE
    +#define BLOCK_MINFREE 4096
    +#endif
    +#ifndef BLOCK_MINALLOC
    +#define BLOCK_MINALLOC 8192
    +#endif
    +
    +/* Finally, some accounting */
    +
    +API_EXPORT(long) ap_bytes_in_pool(pool *p);
    +API_EXPORT(long) ap_bytes_in_free_blocks(void);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_ALLOC_H */
    diff --git a/APACHE_1_3b7/src/include/ap.h b/APACHE_1_3b7/src/include/ap.h
    new file mode 100644
    index 0000000000..17ebee3c3c
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/ap.h
    @@ -0,0 +1,169 @@
    +/* ====================================================================
    + * Copyright (c) 1998 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 code is based on, and used with the permission of, the
    + * SIO stdio-replacement strx_* functions by Panos Tsirigotis
    + * <panos@alumni.cs.colorado.edu> for xinetd.
    + */
    +
    +#ifndef APACHE_AP_H
    +#define APACHE_AP_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +API_EXPORT(char *) ap_cpystrn(char *, const char *, size_t);
    +int ap_slack(int, int);
    +API_EXPORT(char *) ap_escape_quotes(pool *, const char *);
    +API_EXPORT(int) ap_snprintf(char *, size_t, const char *, ...);
    +API_EXPORT(int) ap_vsnprintf(char *, size_t, const char *, va_list ap);
    +int ap_execle(const char *, const char *, ...);
    +int ap_execve(const char *, const char *argv[], const char *envp[]);
    +
    +/* small utility macros to make things easier to read */
    +
    +#ifdef WIN32
    +#define ap_killpg(x, y)
    +#else
    +#ifdef NO_KILLPG
    +#define ap_killpg(x, y)		(kill (-(x), (y)))
    +#else
    +#define ap_killpg(x, y)		(killpg ((x), (y)))
    +#endif
    +#endif /* WIN32 */
    +
    +/* ap_vformatter() is a generic printf-style formatting routine
    + * with some extensions.  The extensions are:
    + *
    + * %pA	takes a struct in_addr *, and prints it as a.b.c.d
    + * %pI	takes a struct sockaddr_in * and prints it as a.b.c.d:port
    + * %pp  takes a void * and outputs it in hex
    + *
    + * The %p hacks are to force gcc's printf warning code to skip
    + * over a pointer argument without complaining.  This does
    + * mean that the ANSI-style %p (output a void * in hex format) won't
    + * work as expected at all, but that seems to be a fair trade-off
    + * for the increased robustness of having printf-warnings work.
    + *
    + * Additionally, ap_vformatter allows for arbitrary output methods
    + * using the ap_vformatter_buff and flush_func.
    + *
    + * The ap_vformatter_buff has two elements curpos and endpos.
    + * curpos is where ap_vformatter will write the next byte of output.
    + * It proceeds writing output to curpos, and updating curpos, until
    + * either the end of output is reached, or curpos == endpos (i.e. the
    + * buffer is full).
    + *
    + * If the end of output is reached, ap_vformatter returns the
    + * number of bytes written.
    + *
    + * When the buffer is full, the flush_func is called.  The flush_func
    + * can return -1 to indicate that no further output should be attempted,
    + * and ap_vformatter will return immediately with -1.  Otherwise
    + * the flush_func should flush the buffer in whatever manner is
    + * appropriate, re-initialize curpos and endpos, and return 0.
    + *
    + * Note that flush_func is only invoked as a result of attempting to
    + * write another byte at curpos when curpos >= endpos.  So for
    + * example, it's possible when the output exactly matches the buffer
    + * space available that curpos == endpos will be true when
    + * ap_vformatter returns.
    + *
    + * ap_vformatter does not call out to any other code, it is entirely
    + * self-contained.  This allows the callers to do things which are
    + * otherwise "unsafe".  For example, ap_psprintf uses the "scratch"
    + * space at the unallocated end of a block, and doesn't actually
    + * complete the allocation until ap_vformatter returns.  ap_psprintf
    + * would be completely broken if ap_vformatter were to call anything
    + * that used a pool.  Similarly http_bprintf() uses the "scratch"
    + * space at the end of its output buffer, and doesn't actually note
    + * that the space is in use until it either has to flush the buffer
    + * or until ap_vformatter returns.
    + */
    +
    +typedef struct {
    +    char *curpos;
    +    char *endpos;
    +} ap_vformatter_buff;
    +
    +API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
    +    ap_vformatter_buff *, const char *fmt, va_list ap);
    +
    +/* These are snprintf implementations based on ap_vformatter().
    + *
    + * Note that various standards and implementations disagree on the return
    + * value of snprintf, and side-effects due to %n in the formatting string.
    + * ap_snprintf behaves as follows:
    + *
    + * Process the format string until the entire string is exhausted, or
    + * the buffer fills.  If the buffer fills then stop processing immediately
    + * (so no further %n arguments are processed), and return the buffer
    + * length.  In all cases the buffer is NUL terminated.
    + *
    + * In no event does ap_snprintf return a negative number.  It's not possible
    + * to distinguish between an output which was truncated, and an output which
    + * exactly filled the buffer.
    + */
    +API_EXPORT(int) ap_snprintf(char *buf, size_t len, const char *format,...)
    +			    __attribute__((format(printf,3,4)));
    +API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
    +			     va_list ap);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_AP_H */
    diff --git a/APACHE_1_3b7/src/include/ap_compat.h b/APACHE_1_3b7/src/include/ap_compat.h
    new file mode 100644
    index 0000000000..06c5963d4d
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/ap_compat.h
    @@ -0,0 +1,410 @@
    +/*
    +**  compat.h -- Apache Backward Compatibility
    +**
    +**  INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED
    +**  BACKWARD COMPATIBILITY TO OLD APACHE RESOURCES.
    +*/
    +
    +#ifndef APACHE_COMPAT_H
    +#define APACHE_COMPAT_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/* 
    + *   Mapping of Apache 1.2 global symbols to the
    + *   namespace conflict free variants used in Apache 1.3
    + */
    +
    +#define MD5Final                       ap_MD5Final
    +#define MD5Init                        ap_MD5Init
    +#define MD5Update                      ap_MD5Update
    +#define acquire_mutex                  ap_acquire_mutex
    +#define add_cgi_vars                   ap_add_cgi_vars
    +#define add_common_vars                ap_add_common_vars
    +#define add_module                     ap_add_module
    +#define add_named_module               ap_add_named_module
    +#define add_per_dir_conf               ap_add_per_dir_conf
    +#define add_per_url_conf               ap_add_per_url_conf
    +#define allow_options                  ap_allow_options
    +#define allow_overrides                ap_allow_overrides
    +#define apapi_get_server_built         ap_get_server_built
    +#define apapi_get_server_version       ap_get_server_version
    +#define aplog_error                    ap_log_error
    +#define append_arrays                  ap_append_arrays
    +#define array_cat                      ap_array_cat
    +#define auth_name                      ap_auth_name
    +#define auth_type                      ap_auth_type
    +#define basic_http_header              ap_basic_http_header
    +#define bclose                         ap_bclose
    +#define bcreate                        ap_bcreate
    +#define bfilbuf                        ap_bfilbuf
    +#define bfileno                        ap_bfileno
    +#define bflsbuf                        ap_bflsbuf
    +#define bflush                         ap_bflush
    +#define bgetc                          ap_bgetc
    +#define bgetopt                        ap_bgetopt
    +#define bgets                          ap_bgets
    +#define bhalfduplex                    ap_bhalfduplex
    +#define bind_address                   ap_bind_address
    +#define block_alarms                   ap_block_alarms
    +#define blookc                         ap_blookc
    +#define bnonblock                      ap_bnonblock
    +#define bonerror                       ap_bonerror
    +#define bprintf                        ap_bprintf
    +#define bpushfd                        ap_bpushfd
    +#define bputc                          ap_bputc
    +#define bputs                          ap_bputs
    +#define bread                          ap_bread
    +#define bsetflag                       ap_bsetflag
    +#define bsetopt                        ap_bsetopt
    +#define bskiplf                        ap_bskiplf
    +#define bvputs                         ap_bvputs
    +#define bwrite                         ap_bwrite
    +#define bytes_in_free_blocks           ap_bytes_in_free_blocks
    +#define bytes_in_pool                  ap_bytes_in_pool
    +#define call_exec                      ap_call_exec
    +#define can_exec                       ap_can_exec
    +#define cfg_closefile                  ap_cfg_closefile
    +#define cfg_getc                       ap_cfg_getc
    +#define cfg_getline                    ap_cfg_getline
    +#define chdir_file                     ap_chdir_file
    +#define check_access                   ap_check_access
    +#define check_alarm                    ap_check_alarm
    +#define check_auth                     ap_check_auth
    +#define check_cmd_context              ap_check_cmd_context
    +#define check_user_id                  ap_check_user_id
    +#define checkmask                      ap_checkmask
    +#define child_exit_modules             ap_child_exit_modules
    +#define child_init_modules             ap_child_init_modules
    +#define child_terminate                ap_child_terminate
    +#define cleanup_for_exec               ap_cleanup_for_exec
    +#define clear_module_list              ap_clear_module_list
    +#define clear_pool                     ap_clear_pool
    +#define clear_table                    ap_clear_table
    +#define close_piped_log                ap_close_piped_log
    +#define construct_server               ap_construct_server
    +#define construct_url                  ap_construct_url
    +#define copy_array                     ap_copy_array
    +#define copy_array_hdr                 ap_copy_array_hdr
    +#define copy_table                     ap_copy_table
    +#define core_reorder_directories       ap_core_reorder_directories
    +#define coredump_dir                   ap_coredump_dir
    +#define count_dirs                     ap_count_dirs
    +#define create_environment             ap_create_environment
    +#define create_mutex                   ap_create_mutex
    +#define create_per_dir_config          ap_create_per_dir_config
    +#define create_request_config          ap_create_request_config
    +#define daemons_limit                  ap_daemons_limit
    +#define daemons_max_free               ap_daemons_max_free
    +#define daemons_min_free               ap_daemons_min_free
    +#define daemons_to_start               ap_daemons_to_start
    +#define day_snames                     ap_day_snames
    +#define default_port_for_request       ap_default_port_for_request
    +#define default_port_for_scheme        ap_default_port_for_scheme
    +#define default_type                   ap_default_type
    +#define destroy_mutex                  ap_destroy_mutex
    +#define destroy_pool                   ap_destroy_pool
    +#define destroy_sub_req                ap_destroy_sub_req
    +#define die                            ap_die
    +#define discard_request_body           ap_discard_request_body
    +#define document_root                  ap_document_root
    +#define dummy_mutex                    ap_dummy_mutex
    +#define each_byterange                 ap_each_byterange
    +#define error_log2stderr               ap_error_log2stderr
    +#define escape_html                    ap_escape_html
    +#define escape_path_segment            ap_escape_path_segment
    +#define escape_shell_cmd               ap_escape_shell_cmd
    +#define excess_requests_per_child      ap_excess_requests_per_child
    +#define exists_scoreboard_image        ap_exists_scoreboard_image
    +#define finalize_request_protocol      ap_finalize_request_protocol
    +#define finalize_sub_req_protocol      ap_finalize_sub_req_protocol
    +#define find_command                   ap_find_command
    +#define find_command_in_modules        ap_find_command_in_modules
    +#define find_last_token                ap_find_last_token
    +#define find_linked_module             ap_find_linked_module
    +#define find_module_name               ap_find_module_name
    +#define find_path_info                 ap_find_path_info
    +#define find_pool                      ap_find_pool
    +#define find_token                     ap_find_token
    +#define find_types                     ap_find_types
    +#define fini_vhost_config              ap_fini_vhost_config
    +#define fnmatch                        ap_fnmatch
    +#define force_library_loading          ap_force_library_loading
    +#define get_basic_auth_pw              ap_get_basic_auth_pw
    +#define get_client_block               ap_get_client_block
    +#define get_gmtoff                     ap_get_gmtoff
    +#define get_local_host                 ap_get_local_host
    +#define get_module_config              ap_get_module_config
    +#define get_remote_host                ap_get_remote_host
    +#define get_remote_logname             ap_get_remote_logname
    +#define get_server_name                ap_get_server_name
    +#define get_server_port                ap_get_server_port
    +#define get_time                       ap_get_time
    +#define get_token                      ap_get_token
    +#define get_virthost_addr              ap_get_virthost_addr
    +#define getparents                     ap_getparents
    +#define getword                        ap_getword
    +#define getword_conf                   ap_getword_conf
    +#define getword_conf_nc                ap_getword_conf_nc
    +#define getword_nc                     ap_getword_nc
    +#define getword_nulls                  ap_getword_nulls
    +#define getword_nulls_nc               ap_getword_nulls_nc
    +#define getword_white                  ap_getword_white
    +#define getword_white_nc               ap_getword_white_nc
    +#define gm_timestr_822                 ap_gm_timestr_822
    +#define gname2id                       ap_gname2id
    +#define group_id                       ap_group_id
    +#define handle_command                 ap_handle_command
    +#define hard_timeout                   ap_hard_timeout
    +#define header_parse                   ap_header_parse
    +#define ht_time                        ap_ht_time
    +#define ind                            ap_ind
    +#define index_of_response              ap_index_of_response
    +#define init_alloc                     ap_init_alloc
    +#define init_modules                   ap_init_modules
    +#define init_vhost_config              ap_init_vhost_config
    +#define init_virtual_host              ap_init_virtual_host
    +#define internal_redirect              ap_internal_redirect
    +#define internal_redirect_handler      ap_internal_redirect_handler
    +#define invoke_handler                 ap_invoke_handler
    +#define is_directory                   ap_is_directory
    +#define is_fnmatch                     ap_is_fnmatch
    +#define is_initial_req                 ap_is_initial_req
    +#define is_matchexp                    ap_is_matchexp
    +#define is_url                         ap_is_url
    +#define keepalive_timeout              ap_keepalive_timeout
    +#define kill_cleanup                   ap_kill_cleanup
    +#define kill_cleanups_for_fd           ap_kill_cleanups_for_fd
    +#define kill_cleanups_for_socket       ap_kill_cleanups_for_socket
    +#define kill_timeout                   ap_kill_timeout
    +#define limit_section                  ap_limit_section
    +#define listenbacklog                  ap_listenbacklog
    +#define listeners                      ap_listeners
    +#define lock_fname                     ap_lock_fname
    +#define log_assert                     ap_log_assert
    +#define log_error                      ap_log_error_old
    +#define log_pid                        ap_log_pid
    +#define log_printf                     ap_log_printf
    +#define log_reason                     ap_log_reason
    +#define log_transaction                ap_log_transaction
    +#define log_unixerr                    ap_log_unixerr
    +#define make_array                     ap_make_array
    +#define make_dirstr                    ap_make_dirstr
    +#define make_dirstr_parent             ap_make_dirstr_parent
    +#define make_dirstr_prefix             ap_make_dirstr_prefix
    +#define make_full_path                 ap_make_full_path
    +#define make_sub_pool                  ap_make_sub_pool
    +#define make_table                     ap_make_table
    +#define matches_request_vhost          ap_matches_request_vhost
    +#define max_requests_per_child         ap_max_requests_per_child
    +#define md5                            ap_md5
    +#define meets_conditions               ap_meets_conditions
    +#define merge_per_dir_configs          ap_merge_per_dir_configs
    +#define month_snames                   ap_month_snames
    +#define no2slash                       ap_no2slash
    +#define note_auth_failure              ap_note_auth_failure
    +#define note_basic_auth_failure        ap_note_basic_auth_failure
    +#define note_cleanups_for_fd           ap_note_cleanups_for_fd
    +#define note_cleanups_for_file         ap_note_cleanups_for_file
    +#define note_cleanups_for_socket       ap_note_cleanups_for_socket
    +#define note_digest_auth_failure       ap_note_digest_auth_failure
    +#define note_subprocess                ap_note_subprocess
    +#define null_cleanup                   ap_null_cleanup
    +#define open_logs                      ap_open_logs
    +#define open_mutex                     ap_open_mutex
    +#define open_piped_log                 ap_open_piped_log
    +#define os_canonical_filename          ap_os_canonical_filename
    +#define os_dl_load                     ap_os_dso_load
    +#define os_dl_unload                   ap_os_dso_unload
    +#define os_dl_sym                      ap_os_dso_sym
    +#define os_dl_error                    ap_os_dso_error
    +#define os_escape_path                 ap_os_escape_path
    +#define os_is_path_absolute            ap_os_is_path_absolute
    +#define overlay_tables                 ap_overlay_tables
    +#define palloc                         ap_palloc
    +#define parseHTTPdate                  ap_parseHTTPdate
    +#define parse_hostinfo_components      ap_parse_hostinfo_components
    +#define parse_htaccess                 ap_parse_htaccess
    +#define parse_uri                      ap_parse_uri
    +#define parse_uri_components           ap_parse_uri_components
    +#define parse_vhost_addrs              ap_parse_vhost_addrs
    +#define pcalloc                        ap_pcalloc
    +#define pcfg_open_custom               ap_pcfg_open_custom
    +#define pcfg_openfile                  ap_pcfg_openfile
    +#define pclosedir                      ap_pclosedir
    +#define pclosef                        ap_pclosef
    +#define pclosesocket                   ap_pclosesocket
    +#define pduphostent                    ap_pduphostent
    +#define pfclose                        ap_pfclose
    +#define pfdopen                        ap_pfdopen
    +#define pfopen                         ap_pfopen
    +#define pgethostbyname                 ap_pgethostbyname
    +#define pid_fname                      ap_pid_fname
    +#define piped_log_read_fd              ap_piped_log_read_fd
    +#define piped_log_write_fd             ap_piped_log_write_fd
    +#define pool_is_ancestor               ap_pool_is_ancestor
    +#define pool_join                      ap_pool_join
    +#define popendir                       ap_popendir
    +#define popenf                         ap_popenf
    +#define pregcomp                       ap_pregcomp
    +#define pregfree                       ap_pregfree
    +#define pregsub                        ap_pregsub
    +#define process_request                ap_process_request
    +#define process_resource_config        ap_process_resource_config
    +#define proxy_add_header               ap_proxy_add_header
    +#define proxy_c2hex                    ap_proxy_c2hex
    +#define proxy_cache_check              ap_proxy_cache_check
    +#define proxy_cache_error              ap_proxy_cache_error
    +#define proxy_cache_tidy               ap_proxy_cache_tidy
    +#define proxy_cache_update             ap_proxy_cache_update
    +#define proxy_canon_netloc             ap_proxy_canon_netloc
    +#define proxy_canonenc                 ap_proxy_canonenc
    +#define proxy_connect_handler          ap_proxy_connect_handler
    +#define proxy_date_canon               ap_proxy_date_canon
    +#define proxy_del_header               ap_proxy_del_header
    +#define proxy_doconnect                ap_proxy_doconnect
    +#define proxy_ftp_canon                ap_proxy_ftp_canon
    +#define proxy_ftp_handler              ap_proxy_ftp_handler
    +#define proxy_garbage_coll             ap_proxy_garbage_coll
    +#define proxy_garbage_init             ap_proxy_garbage_init
    +#define proxy_get_header               ap_proxy_get_header
    +#define proxy_hash                     ap_proxy_hash
    +#define proxy_hex2c                    ap_proxy_hex2c
    +#define proxy_hex2sec                  ap_proxy_hex2sec
    +#define proxy_host2addr                ap_proxy_host2addr
    +#define proxy_http_canon               ap_proxy_http_canon
    +#define proxy_http_handler             ap_proxy_http_handler
    +#define proxy_is_domainname            ap_proxy_is_domainname
    +#define proxy_is_hostname              ap_proxy_is_hostname
    +#define proxy_is_ipaddr                ap_proxy_is_ipaddr
    +#define proxy_is_word                  ap_proxy_is_word
    +#define proxy_liststr                  ap_proxy_liststr
    +#define proxy_log_uerror               ap_proxy_log_uerror
    +#define proxy_read_headers             ap_proxy_read_headers
    +#define proxy_sec2hex                  ap_proxy_sec2hex
    +#define proxy_send_fb                  ap_proxy_send_fb
    +#define proxy_send_headers             ap_proxy_send_headers
    +#define proxyerror                     ap_proxyerror
    +#define psignature                     ap_psignature
    +#define psocket                        ap_psocket
    +#define psprintf                       ap_psprintf
    +#define pstrcat                        ap_pstrcat
    +#define pstrdup                        ap_pstrdup
    +#define pstrndup                       ap_pstrndup
    +#define push_array                     ap_push_array
    +#define pvsprintf                      ap_pvsprintf
    +#define rationalize_mtime              ap_rationalize_mtime
    +#define read_config                    ap_read_config
    +#define read_request                   ap_read_request
    +#define register_cleanup               ap_register_cleanup
    +#define register_other_child           ap_register_other_child
    +#define release_mutex                  ap_release_mutex
    +#define remove_module                  ap_remove_module
    +#define requires                       ap_requires
    +#define reset_timeout                  ap_reset_timeout
    +#define response_code_string           ap_response_code_string
    +#define restart_time                   ap_restart_time
    +#define rfc1413                        ap_rfc1413
    +#define rfc1413_timeout                ap_rfc1413_timeout
    +#define rflush                         ap_rflush
    +#define rind                           ap_rind
    +#define rprintf                        ap_rprintf
    +#define rputc                          ap_rputc
    +#define rputs                          ap_rputs
    +#define run_cleanup                    ap_run_cleanup
    +#define run_fixups                     ap_run_fixups
    +#define run_post_read_request          ap_run_post_read_request
    +#define run_sub_req                    ap_run_sub_req
    +#define rvputs                         ap_rvputs
    +#define rwrite                         ap_rwrite
    +#define satisfies                      ap_satisfies
    +#define scan_script_header_err         ap_scan_script_header_err
    +#define scan_script_header_err_buff    ap_scan_script_header_err_buff
    +#define scoreboard_fname               ap_scoreboard_fname
    +#define scoreboard_image               ap_scoreboard_image
    +#define send_error_response            ap_send_error_response
    +#define send_fb                        ap_send_fb
    +#define send_fb_length                 ap_send_fb_length
    +#define send_fd                        ap_send_fd
    +#define send_fd_length                 ap_send_fd_length
    +#define send_header_field              ap_send_header_field
    +#define send_http_header               ap_send_http_header
    +#define send_http_options              ap_send_http_options
    +#define send_http_trace                ap_send_http_trace
    +#define send_mmap                      ap_send_mmap
    +#define send_size                      ap_send_size
    +#define server_argv0                   ap_server_argv0
    +#define server_confname                ap_server_confname
    +#define server_post_read_config        ap_server_post_read_config
    +#define server_pre_read_config         ap_server_pre_read_config
    +#define server_root                    ap_server_root
    +#define server_root_relative           ap_server_root_relative
    +#define set_byterange                  ap_set_byterange
    +#define set_callback_and_alarm         ap_set_callback_and_alarm
    +#define set_content_length             ap_set_content_length
    +#define set_etag                       ap_set_etag
    +#define set_file_slot                  ap_set_file_slot
    +#define set_flag_slot                  ap_set_flag_slot
    +#define set_keepalive                  ap_set_keepalive
    +#define set_last_modified              ap_set_last_modified
    +#define set_module_config              ap_set_module_config
    +#define set_name_virtual_host          ap_set_name_virtual_host
    +#define set_string_slot                ap_set_string_slot
    +#define set_string_slot_lower          ap_set_string_slot_lower
    +#define set_sub_req_protocol           ap_set_sub_req_protocol
    +#define setup_client_block             ap_setup_client_block
    +#define setup_prelinked_modules        ap_setup_prelinked_modules
    +#define should_client_block            ap_should_client_block
    +#define show_directives                ap_show_directives
    +#define show_modules                   ap_show_modules
    +#define soft_timeout                   ap_soft_timeout
    +#define some_auth_required             ap_some_auth_required
    +#define spawn_child_err                ap_spawn_child_err
    +#define spawn_child_err_buff           ap_spawn_child_err_buff
    +#define srm_command_loop               ap_srm_command_loop
    +#define standalone                     ap_standalone
    +#define start_restart                  ap_start_restart
    +#define start_shutdown                 ap_start_shutdown
    +#define str_tolower                    ap_str_tolower
    +#define strcasecmp_match               ap_strcasecmp_match
    +#define strcmp_match                   ap_strcmp_match
    +#define sub_req_lookup_file            ap_sub_req_lookup_file
    +#define sub_req_lookup_uri             ap_sub_req_lookup_uri
    +#define suexec_enabled                 ap_suexec_enabled
    +#define sync_scoreboard_image          ap_sync_scoreboard_image
    +#define table_add                      ap_table_add
    +#define table_addn                     ap_table_addn
    +#define table_do                       ap_table_do
    +#define table_get                      ap_table_get
    +#define table_merge                    ap_table_merge
    +#define table_mergen                   ap_table_mergen
    +#define table_set                      ap_table_set
    +#define table_setn                     ap_table_setn
    +#define table_unset                    ap_table_unset
    +#define threads_per_child              ap_threads_per_child
    +#define time_process_request           ap_time_process_request
    +#define tm2sec                         ap_tm2sec
    +#define translate_name                 ap_translate_name
    +#define uname2id                       ap_uname2id
    +#define unblock_alarms                 ap_unblock_alarms
    +#define unescape_url                   ap_unescape_url
    +#define unparse_uri_components         ap_unparse_uri_components
    +#define unregister_other_child         ap_unregister_other_child
    +#define update_child_status            ap_update_child_status
    +#define update_mtime                   ap_update_mtime
    +#define update_vhost_from_headers      ap_update_vhost_from_headers
    +#define update_vhost_given_ip          ap_update_vhost_given_ip
    +#define user_id                        ap_user_id
    +#define user_name                      ap_user_name
    +#define util_init                      ap_util_init
    +#define util_uri_init                  ap_util_uri_init
    +#define uudecode                       ap_uudecode
    +#define vbprintf                       ap_vbprintf
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif /* APACHE_COMPAT_H */
    diff --git a/APACHE_1_3b7/src/include/ap_config.h b/APACHE_1_3b7/src/include/ap_config.h
    new file mode 100644
    index 0000000000..1e67a5b3f7
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/ap_config.h
    @@ -0,0 +1,1170 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_CONF_H
    +#define APACHE_CONF_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/*
    + * conf.h: system-dependant #defines and includes...
    + * See PORTING for a listing of what they mean
    + */
    +
    +
    +/* Have to include sys/stat.h before ../os/win32/os.h so we can override
    +stat() properly */
    +#include <sys/types.h>
    +#include <sys/stat.h>
    +
    +#ifdef WIN32
    +/* include process.h first so we can override spawn[lv]e* properly */
    +#include <process.h>
    +#include "../os/win32/os.h"
    +#else
    +#include "os.h"
    +#endif
    +
    +#if !defined(QNX) && !defined(MPE) && !defined(WIN32)
    +#include <sys/param.h>
    +#endif
    +
    +/* Define one of these according to your system. */
    +#if defined(MINT)
    +typedef int rlim_t;
    +#define HAVE_SYS_RESOURCE_H 1
    +#define JMP_BUF sigjmp_buf
    +#define NO_LONG_DOUBLE
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define _BSD_SOURCE
    +#define EAGAIN EWOULDBLOCK
    +int initgroups (char *, int);     
    +char *crypt (const char *pw, const char *salt);
    +int gethostname (char *name, int namelen);
    +
    +#elif defined(MPE)
    +#include <sys/times.h>
    +#define NO_SETSID
    +#define NO_KILLPG
    +#define NO_WRITEV
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define SHM_R 0400  /* Read permission */
    +#define SHM_W 0200  /* Write permission */
    +#define NEED_INITGROUPS
    +#define NEED_STRCASECMP
    +#define NEED_STRDUP
    +#define NEED_STRNCASECMP
    +extern void GETPRIVMODE();
    +extern void GETUSERMODE();
    +extern char *inet_ntoa();
    +#define NO_SLACK
    +#define NO_GETTIMEOFDAY
    +#define S_IEXEC  S_IXUSR
    +#define S_IREAD  S_IRUSR
    +#define S_IWRITE S_IWUSR
    +#define PF_INET  AF_INET
    +
    +#elif defined(SUNOS4)
    +#define HAVE_GMTOFF 1
    +#define HAVE_SYS_RESOURCE_H 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +char *crypt(const char *pw, const char *salt);
    +char *mktemp(char *template);
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#include <sys/time.h>
    +#define NEED_STRERROR
    +typedef int rlim_t;
    +#define memmove(a,b,c) bcopy(b,a,c)
    +#define NO_LINGCLOSE
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define NEED_DIFFTIME
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(SOLARIS2)
    +#undef HAVE_GMTOFF
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SYS_RESOURCE_H 1
    +#define HAVE_DLFCN_H 1
    +#define bzero(a,b) memset(a,0,b)
    +#if !defined(USE_SYSVSEM_SERIALIZED_ACCEPT) && \
    +    !defined(USE_PTHREAD_SERIALIZED_ACCEPT)
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#endif
    +#define NEED_UNION_SEMUN
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +int gethostname(char *name, int namelen);
    +#define HAVE_SYSLOG 1
    +#define SYS_SIGLIST _sys_siglist
    +
    +#elif defined(IRIX)
    +#undef HAVE_GMTOFF
    +/* IRIX has killpg, but it's only in _BSD_COMPAT, so don't use it in case
    + * there's some weird conflict with non-BSD signals */
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#if !defined(USE_FCNTL_SERIALIZED_ACCEPT) && !defined(USE_USLOCK_SERIALIZED_ACCEPT)
    +#define USE_SYSVSEM_SERIALIZED_ACCEPT
    +#endif
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define HAVE_MMAP 1
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +#define HAVE_DLFCN_H 1
    +#define NO_LONG_DOUBLE
    +#define HAVE_BSTRING_H 1
    +#define NO_LINGCLOSE
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(HIUX)
    +#define HAVE_SYS_RESOURCE_H 1
    +#undef HAVE_GMTOFF
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#ifndef _HIUX_SOURCE
    +#define _HIUX_SOURCE
    +#endif
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define SELECT_NEEDS_CAST
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(HPUX) || defined(HPUX10)
    +#define HAVE_SYS_RESOURCE_H 1
    +#undef HAVE_GMTOFF
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#ifndef _HPUX_SOURCE
    +#define _HPUX_SOURCE
    +#endif
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define HAVE_SYSLOG 1
    +#ifndef HPUX10
    +#define SELECT_NEEDS_CAST
    +typedef int rlim_t;
    +#endif
    +
    +#elif defined(HPUX11)
    +#ifndef _HPUX_SOURCE
    +#define _HPUX_SOURCE
    +#endif
    +#define HAVE_SHMGET
    +#define USE_SHMGET_SCOREBOARD
    +#undef  HAVE_GMTOFF
    +#define HAVE_RESOURCE
    +#define HAVE_CRYPT_H
    +#undef  HAVE_SYS_SELECT_H
    +#define HAVE_SYS_RESOURCE_H
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +/* feeling brave?  want to try using POSIX mutexes? */
    +/* #define HAVE_MMAP */
    +/* #define USE_MMAP_SCOREBOARD */
    +/* #define USE_MMAP_FILES */
    +/* #define USE_PTHREAD_SERIALIZED_ACCEPT */
    +#define NO_KILLPG
    +#undef  NO_SETSID
    +#define HAVE_SYSLOG
    +
    +#elif defined(AIX)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SYS_SELECT_H 1
    +#ifndef __ps2__
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_SYSLOG 1
    +#ifndef DEFAULT_GROUP
    +#define DEFAULT_GROUP "nobody"
    +#endif
    +#endif
    +#ifndef DEFAULT_USER
    +#define DEFAULT_USER "nobody"
    +#endif
    +#ifdef NEED_RLIM_T
    +typedef int rlim_t;
    +#endif
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#ifdef USEBCOPY
    +#define memmove(a,b,c) bcopy(b,a,c)
    +#endif
    +#if AIX >= 42
    +#define NET_SIZE_T size_t
    +#endif
    +
    +#elif defined(ULTRIX)
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define ULTRIX_BRAIN_DEATH
    +#define NEED_STRDUP
    +/* If you have Ultrix 4.3, and are using cc, const is broken */
    +#ifndef __ultrix__		/* Hack to check for pre-Ultrix 4.4 cc */
    +#define const			/* Not implemented */
    +#endif
    +
    +#elif defined(OSF1)
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +#define NO_LONG_DOUBLE
    +#define HAVE_SYSLOG 1
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +
    +#elif defined(PARAGON)
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +#define NO_LONG_DOUBLE
    +#define HAVE_SYSLOG 1
    +typedef int rlim_t;
    +
    +#elif defined(SEQUENT)
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#define NO_SETSID
    +#define NEED_STRDUP
    +#define HAVE_SYSLOG 1
    +#define tolower(c) (isupper(c) ? tolower(c) : c)
    +
    +#elif defined(NEXT)
    +typedef unsigned short mode_t;
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#define NO_SETSID
    +#define NEED_STRDUP
    +#define NO_LINGCLOSE
    +#define NO_UNISTD_H
    +#undef _POSIX_SOURCE
    +#ifndef FD_CLOEXEC
    +#define FD_CLOEXEC 1
    +#endif
    +#ifndef S_ISDIR
    +#define S_ISDIR(m)      (((m)&(S_IFMT)) == (S_IFDIR))
    +#endif
    +#ifndef S_ISREG
    +#define S_ISREG(m)      (((m)&(S_IFMT)) == (S_IFREG))
    +#endif
    +#ifndef S_IXUSR
    +#define S_IXUSR 00100
    +#endif
    +#ifndef S_IRGRP
    +#define S_IRGRP 00040
    +#endif
    +#ifndef S_IXGRP
    +#define S_IXGRP 00010
    +#endif
    +#ifndef S_IROTH
    +#define S_IROTH 00004
    +#endif
    +#ifndef S_IXOTH
    +#define S_IXOTH 00001
    +#endif
    +#ifndef S_IRUSR
    +#define S_IRUSR S_IREAD
    +#endif
    +#ifndef S_IWUSR
    +#define S_IWUSR S_IWRITE
    +#endif
    +#ifndef S_IWGRP
    +#define S_IWGRP	000020
    +#endif
    +#ifndef S_IWOTH
    +#define S_IWOTH 000002
    +#ifndef rlim_t
    +typedef int rlim_t;
    +#endif
    +typedef u_long n_long;
    +#endif
    +
    +#define STDIN_FILENO  0
    +#define STDOUT_FILENO 1
    +#define STDERR_FILENO 2
    +#define waitpid(a,b,c) wait4((a) == -1 ? 0 : (a),(union wait *)(b),c,NULL)
    +typedef int pid_t;
    +#define USE_LONGJMP
    +#define NO_USE_SIGACTION
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(LINUX)
    +#define HAVE_DLFCN_H 1
    +
    +#if LINUX > 1
    +#include <features.h>
    +
    +/* libc4 systems probably still work, it probably doesn't define
    + *  __GNU_LIBRARY__
    + * libc5 systems define __GNU_LIBRARY__ == 1, but don't define __GLIBC__
    + * glibc 2.x and later systems define __GNU_LIBRARY__ == 6, but list it as
    + * "deprecated in favour of __GLIBC__"; the value 6 will never be changed.
    + * glibc 1.x systems (i.e. redhat 4.x on sparc/alpha) should have
    + * __GLIBC__ < 2
    + * all glibc based systems need crypt.h
    + */
    +#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
    +#include <crypt.h>
    +#endif
    +
    +/* glibc 2.0.0 through 2.0.4 need size_t * here, where 2.0.5 needs socklen_t *
    + * there's no way to discern between these two libraries.  But using int should
    + * be portable because otherwise these libs would be hopelessly broken with
    + * reams of existing networking code.  We'll use socklen_t * for 2.1.x and
    + * later.
    + *
    + * int works for all the earlier libs, and is picked up by default later.
    + */
    +#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0))
    +#define NET_SIZE_T socklen_t
    +#endif
    +
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define HAVE_MMAP 1
    +#define USE_MMAP_FILES
    +#define HAVE_SYS_RESOURCE_H 1
    +
    +/* glibc 2.1 and later finally define rlim_t */
    +#if !defined(__GLIBC__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
    +typedef int rlim_t;
    +#endif
    +
    +/* flock is faster ... but hasn't been tested on 1.x systems */
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +
    +#define SYS_SIGLIST	_sys_siglist
    +
    +#else
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#endif
    +
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#undef NEED_STRDUP
    +#include <sys/time.h>
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(SCO)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define NEED_INITGROUPS
    +#define NO_WRITEV
    +#include <sys/time.h>
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(SCO5)
    +
    +#define HAVE_SYS_SELECT_H 1
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_SYS_RESOURCE_H 1
    +#define SecureWare
    +#define HAVE_SYSLOG 1
    +
    +/* Although SCO 5 defines these in <strings.h> (note the "s") they don't have
    +   consts. Sigh. */
    +extern int strcasecmp(const char *, const char *);
    +extern int strncasecmp(const char *, const char *, unsigned);
    +
    +#elif defined(AUX3)
    +/* These are to let -Wall compile more cleanly */
    +extern int strcasecmp(const char *, const char *);
    +extern int strncasecmp(const char *, const char *, unsigned);
    +extern int set42sig(), getopt(), getpeername(), bzero();
    +extern int listen(), bind(), socket(), getsockname();
    +extern int accept(), gethostname(), connect(), lstat();
    +extern int select(), killpg(), shutdown();
    +extern int initgroups(), setsockopt();
    +extern char *shmat();
    +extern int shmctl();
    +extern int shmget();
    +extern char *sbrk();
    +extern char *crypt();
    +#include <sys/time.h>
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define NEED_STRDUP
    +/* fcntl() locking is expensive with NFS */
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +/*
    + * NOTE: If when you run Apache under A/UX and you get a warning
    + * that httpd couldn't move break, then the below value for
    + * MOVEBREAK (64megs) is too large for your setup. Try reducing
    + * to 0x2000000 which is still PLENTY of space. I doubt if
    + * even on heavy systems sbrk() would be called at all...
    + */
    +#define MOVEBREAK		0x4000000
    +#define NO_LINGCLOSE
    +#define NO_SLACK
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(SVR4)
    +#define NO_KILLPG
    +#undef  NO_SETSID
    +#undef NEED_STRDUP
    +#ifndef MPRAS
    +#define NEED_STRCASECMP
    +#ifndef ENCORE
    +#define NEED_STRNCASECMP
    +#endif /* ENCORE */
    +#endif /* MPRAS */
    +#define bzero(a,b) memset(a,0,b)
    +/* A lot of SVR4 systems need this */
    +#ifndef USE_SYSVSEM_SERIALIZED_ACCEPT
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#endif
    +#define HAVE_SYSLOG 1
    +#define NET_SIZE_T size_t
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#ifdef _OSD_POSIX /* BS2000-POSIX mainframe needs initgroups */
    +#define NEED_INITGROUPS
    +#define NEED_HASHBANG_EMUL /* execve() doesn't start shell scripts by default */
    +#undef HAVE_SHMGET
    +#undef USE_SHMGET_SCOREBOARD
    +#undef bzero
    +#endif /*_OSD_POSIX*/
    +
    +#elif defined(UW)
    +#define NO_LINGCLOSE
    +#define NO_KILLPG
    +#undef  NO_SETSID
    +#undef NEED_STRDUP
    +#define NEED_STRCASECMP
    +#define NEED_STRNCASECMP
    +#define bzero(a,b) memset(a,0,b)
    +#define HAVE_RESOURCE 1
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_SHMGET 1
    +#undef USE_SHMGET_SCOREBOARD	/* force use of mmap() scoreboard */
    +#define HAVE_CRYPT_H 1
    +#define HAVE_SYS_SELECT_H 1
    +#define HAVE_SYS_RESOURCE_H 1
    +#include <sys/time.h>
    +#if UW >= 200
    +#define _POSIX_SOURCE
    +#endif
    +#define NET_SIZE_T size_t
    +#define HAVE_SYSLOG 1
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +
    +#elif defined(DGUX)
    +#define NO_KILLPG
    +#undef  NO_SETSID
    +#undef NEED_STRDUP
    +#define NEED_STRCASECMP
    +#define NEED_STRNCASECMP
    +#define bzero(a,b) memset(a,0,b)
    +/* A lot of SVR4 systems need this */
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#define ap_inet_addr inet_network
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(NETBSD)
    +#define HAVE_SYS_RESOURCE_H 1
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SYSLOG 1
    +#ifndef DEFAULT_USER
    +#define DEFAULT_USER "nobody"
    +#endif
    +#ifndef DEFAULT_GROUP
    +#define DEFAULT_GROUP "nogroup"
    +#define HAVE_SHMGET 1
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#endif
    +
    +#elif defined(UTS21)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#define NO_SETSID
    +#define NEED_WAITPID
    +#define NO_OTHER_CHILD
    +#define STDIN_FILENO 0
    +#define STDOUT_FILENO 1
    +#define STDERR_FILENO 2
    +#define HAVE_SYSLOG 1
    +#define strftime(buf,bufsize,fmt,tm)    ascftime(buf,fmt,tm)
    +#include <sys/types.h>
    +
    +#elif defined(APOLLO)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(__FreeBSD__) || defined(__bsdi__)
    +#if defined(__FreeBSD__)
    +#include <osreldate.h>
    +#endif
    +#define HAVE_DLFCN_H 1
    +#define HAVE_SYS_RESOURCE_H 1
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#ifndef DEFAULT_USER
    +#define DEFAULT_USER "nobody"
    +#endif
    +#ifndef DEFAULT_GROUP
    +#define DEFAULT_GROUP "nogroup"
    +#endif
    +#if defined(__bsdi__) || \
    +(defined(__FreeBSD_version) && (__FreeBSD_version < 220000))
    +typedef quad_t rlim_t;
    +#endif
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define HAVE_SYSLOG 1
    +#define SYS_SIGLIST sys_siglist
    +
    +#elif defined(QNX)
    +#ifndef crypt
    +char *crypt(const char *pw, const char *salt);
    +#endif
    +#ifndef initgroups
    +int initgroups(char *, int);
    +#endif
    +#ifndef strncasecmp
    +#define strncasecmp strnicmp
    +#endif
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define NEED_INITGROUPS
    +#define NEED_SELECT_H
    +#define NEED_PROCESS_H
    +#define HAVE_SYS_SELECT_H 1
    +#include <unix.h>
    +#define HAVE_MMAP 1
    +#define USE_POSIX_SCOREBOARD
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(LYNXOS)
    +#undef HAVE_GMTOFF
    +#define HAVE_RESOURCE 1
    +#undef USE_MMAP_SCOREBOARD
    +#undef USE_SHMGET_SCOREBOARD
    +#undef HAVE_CRYPT_H
    +#undef HAVE_SYS_SELECT_H
    +#define HAVE_SYS_RESOURCE_H 1
    +#undef USE_FCNTL_SERIALIZED_ACCEPT
    +#undef USE_FLOCK_SERIALIZED_ACCEPT
    +#define USE_LONGJMP
    +#undef NO_UNISTD_H
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#undef NO_USE_SIGACTION
    +#undef NO_LINGCLOSE
    +extern char *crypt(char *pw, char *salt);
    +typedef int rlim_t;
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(UXPDS)
    +#undef NEED_STRCASECMP
    +#undef NEED_STRNCASECMP
    +#undef NEED_STRDUP
    +#undef HAVE_GMTOFF
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_RESOURCE 1 
    +#define bzero(a,b) memset(a,0,b)
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(__EMX__)
    +/* Defines required for EMX OS/2 port. */
    +#define NO_KILLPG
    +#define NEED_STRCASECMP
    +#define NEED_STRNCASECMP
    +#define NO_SETSID
    +#define NO_TIMES
    +/* Add some drive name support */
    +#define chdir _chdir2
    +#include <sys/time.h>
    +#define MAXSOCKETS 4096
    +#define USE_OS2_SCOREBOARD
    +#define NO_RELIABLE_PIPED_LOGS
    +
    +#elif defined(__MACHTEN__)
    +typedef int rlim_t;
    +#undef NO_KILLPG
    +#define NO_SETSID
    +#define HAVE_GMTOFF 1
    +#ifndef __MACHTEN_PPC__
    +#ifndef __MACHTEN_68K__
    +#define __MACHTEN_68K__
    +#endif
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define NO_USE_SIGACTION
    +#define JMP_BUF sigjmp_buf
    +#define USE_LONGJMP
    +#undef NEED_STRDUP
    +#else
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#endif
    +
    +/* Convex OS v11 */
    +#elif defined(CONVEXOS11)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#undef NEED_STRDUP
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_SYSLOG 1
    +
    +#define NO_TIMEZONE
    +#include <stdio.h>
    +#include <sys/types.h>
    +typedef int rlim_t;
    +
    +#elif defined(ISC)
    +#include <net/errno.h>
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(NEWSOS)
    +#define HAVE_SYS_RESOURCE_H 1
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define USE_LONGJMP
    +#define NO_SETSID
    +#define NO_USE_SIGACTION
    +#define NEED_WAITPID
    +#define NO_OTHER_CHILD
    +#define HAVE_SYSLOG 1
    +#include <sys/time.h>
    +#include <stdlib.h>
    +#include <sys/types.h>
    +typedef int pid_t;
    +typedef int rlim_t;
    +typedef int mode_t;
    +
    +#elif defined(RISCIX)
    +#include <sys/time.h>
    +typedef int rlim_t;
    +#define NO_USE_SIGACTION
    +#define USE_LONGJMP
    +#define NEED_STRCASECMP
    +#define NEED_STRNCASECMP
    +#define NEED_STRDUP
    +
    +#elif defined(BEOS)
    +#include <stddef.h>
    +
    +#define NO_WRITEV
    +#define NO_KILLPG
    +#define NEED_INITGROUPS
    +
    +#define isascii(c)	(!((c) & ~0177))
    +
    +#elif defined(WIN32)
    +
    +/* All windows stuff is now in os/win32/os.h */
    +
    +#else
    +/* Unknown system - Edit these to match */
    +#ifdef BSD
    +#define HAVE_GMTOFF 1
    +#else
    +#undef HAVE_GMTOFF
    +#endif
    +/* NO_KILLPG is set on systems that don't have killpg */
    +#undef NO_KILLPG
    +/* NO_SETSID is set on systems that don't have setsid */
    +#undef NO_SETSID
    +/* NEED_STRDUP is set on stupid systems that don't have strdup. */
    +#undef NEED_STRDUP
    +#endif
    +
    +/* stuff marked API_EXPORT is part of the API, and intended for use
    + * by modules
    + */
    +#ifndef API_EXPORT
    +#define API_EXPORT(type)    type
    +#endif
    +
    +/* Stuff marked API_EXPORT_NONSTD is part of the API, and intended for
    + * use by modules.  The difference between API_EXPORT and
    + * API_EXPORT_NONSTD is that the latter is required for any functions
    + * which use varargs or are used via indirect function call.  This
    + * is to accomodate the two calling conventions in windows dlls.
    + */
    +#ifndef API_EXPORT_NONSTD
    +#define API_EXPORT_NONSTD(type)    type
    +#endif
    +
    +#ifndef MODULE_VAR_EXPORT
    +#define MODULE_VAR_EXPORT
    +#endif
    +#ifndef API_VAR_EXPORT
    +#define API_VAR_EXPORT
    +#endif
    +
    +/* modules should not used functions marked CORE_EXPORT
    + * or CORE_EXPORT_NONSTD */
    +#ifndef CORE_EXPORT
    +#define CORE_EXPORT	API_EXPORT
    +#endif
    +#ifndef CORE_EXPORT_NONSTD
    +#define CORE_EXPORT_NONSTD	API_EXPORT_NONSTD
    +#endif
    +
    +/* So that we can use inline on some critical functions, and use
    + * GNUC attributes (such as to get -Wall warnings for printf-like
    + * functions).  Only do this in gcc 2.7 or later ... it may work
    + * on earlier stuff, but why chance it.
    + *
    + * We've since discovered that the gcc shipped with NeXT systems
    + * as "cc" is completely broken.  It claims to be __GNUC__ and so
    + * on, but it doesn't implement half of the things that __GNUC__
    + * means.  In particular it's missing inline and the __attribute__
    + * stuff.  So we hack around it.  PR#1613. -djg
    + */
    +#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 7 || defined(NEXT)
    +#define ap_inline
    +#define __attribute__(__x)
    +#define ENUM_BITFIELD(e,n,w)  signed int n : w
    +#else
    +#define ap_inline __inline__
    +#define USE_GNU_INLINE
    +#define ENUM_BITFIELD(e,n,w)  e n : w
    +#endif
    +
    +/* Do we have sys/resource.h; assume that BSD does. */
    +#ifndef HAVE_SYS_RESOURCE_H
    +#ifdef BSD
    +#define HAVE_SYS_RESOURCE_H 1
    +#endif
    +#endif /* HAVE_SYS_RESOURCE_H */
    +
    +/*
    + * The particular directory style your system supports. If you have dirent.h
    + * in /usr/include (POSIX) or /usr/include/sys (SYSV), #include 
    + * that file and define DIR_TYPE to be dirent. Otherwise, if you have 
    + * /usr/include/sys/dir.h, define DIR_TYPE to be direct and include that
    + * file. If you have neither, I'm confused.
    + */
    +
    +#include <sys/types.h>
    +#include <stdarg.h>
    +
    +#if !defined(NEXT) && !defined(WIN32)
    +#include <dirent.h>
    +#define DIR_TYPE dirent
    +#elif !defined(WIN32)
    +#include <sys/dir.h>
    +#define DIR_TYPE direct
    +#else
    +#define DIR_TYPE dirent
    +#endif
    +
    +#include <stdio.h>
    +#include <stdlib.h>
    +#include <string.h>
    +#include <ctype.h>
    +#if !defined(MPE) && !defined(WIN32)
    +#include <sys/file.h>
    +#endif
    +#ifndef WIN32
    +#include <sys/socket.h>
    +#ifdef HAVE_SYS_SELECT_H
    +#include <sys/select.h>
    +#endif /* HAVE_SYS_SELECT_H */
    +#include <netinet/in.h>
    +#include <netdb.h>
    +#include <sys/ioctl.h>
    +#if !defined(MPE) && !defined(BEOS)
    +#include <arpa/inet.h>		/* for inet_ntoa */
    +#endif
    +#include <sys/wait.h>
    +#include <pwd.h>
    +#include <grp.h>
    +#include <fcntl.h>
    +#include <limits.h>
    +#define closesocket(s) close(s)
    +#ifndef O_BINARY
    +#define O_BINARY (0)
    +#endif
    +
    +#else /* WIN32 */
    +#include <winsock.h>
    +#include <malloc.h>
    +#include <io.h>
    +#include <fcntl.h>
    +#endif /* ndef WIN32 */
    +
    +#include <time.h>		/* for ctime */
    +#include <signal.h>
    +#include <errno.h>
    +#if !defined(QNX) && !defined(CONVEXOS11) && !defined(NEXT)
    +#include <memory.h>
    +#endif
    +
    +#ifdef NEED_PROCESS_H
    +#include <process.h>
    +#endif
    +
    +#ifdef WIN32
    +#include "../include/hsregex.h"
    +#elif defined(USE_HSREGEX)
    +#include "hsregex.h"
    +#else
    +#include <regex.h>
    +#endif
    +
    +#ifdef HAVE_SYS_RESOURCE_H
    +#include <sys/resource.h>
    +#ifdef SUNOS4
    +int getrlimit(int, struct rlimit *);
    +int setrlimit(int, struct rlimit *);
    +#endif
    +#endif
    +#ifdef USE_MMAP_SCOREBOARD
    +#if !defined(__EMX__) && !defined(WIN32)
    +/* This file is not needed for OS/2 */
    +#include <sys/mman.h>
    +#endif
    +#endif
    +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
    +#define MAP_ANON MAP_ANONYMOUS
    +#endif
    +
    +#if defined(USE_MMAP_FILES) && (defined(NO_MMAP) || !defined(HAVE_MMAP))
    +#undef USE_MMAP_FILES
    +#endif
    +
    +#if defined(USE_MMAP_SCOREBOARD) && (defined(NO_MMAP) || !defined(HAVE_MMAP))
    +#undef USE_MMAP_SCOREBOARD
    +#endif
    +
    +#if defined(USE_SHMGET_SCOREBOARD) && (defined(NO_SHMGET) || !defined(HAVE_SHMGET))
    +#undef USE_SHMGET_SCOREBOARD
    +#endif
    +
    +#ifndef LOGNAME_MAX
    +#define LOGNAME_MAX 25
    +#endif
    +
    +#ifndef NO_UNISTD_H
    +#include <unistd.h>
    +#endif
    +
    +#ifdef ultrix
    +#define ULTRIX_BRAIN_DEATH
    +#endif
    +
    +#ifndef S_ISLNK
    +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
    +#endif
    +
    +#ifndef INADDR_NONE
    +#define INADDR_NONE ((unsigned long) -1)
    +#endif
    +
    +/*
    + * Replace signal function with sigaction equivalent
    + */
    +#ifndef NO_USE_SIGACTION
    +typedef void Sigfunc(int);
    +
    +#if defined(SIG_IGN) && !defined(SIG_ERR)
    +#define SIG_ERR ((Sigfunc *)-1)
    +#endif
    +
    +/*
    + * For some strange reason, QNX defines signal to signal. Eliminate it.
    + */
    +#ifdef signal
    +#undef signal
    +#endif
    +#define signal(s,f)	ap_signal(s,f)
    +Sigfunc *signal(int signo, Sigfunc * func);
    +#endif
    +
    +#include <setjmp.h>
    +
    +#if defined(USE_LONGJMP)
    +#define ap_longjmp(x, y)        longjmp((x), (y))
    +#define ap_setjmp(x)            setjmp(x)
    +#ifndef JMP_BUF
    +#define JMP_BUF jmp_buf
    +#endif
    +#else
    +#define ap_longjmp(x, y)        siglongjmp((x), (y))
    +#define ap_setjmp(x)            sigsetjmp((x), 1)
    +#ifndef JMP_BUF
    +#define JMP_BUF sigjmp_buf
    +#endif
    +#endif
    +
    +#ifdef SELECT_NEEDS_CAST
    +#define ap_select(_a, _b, _c, _d, _e)	\
    +    select((_a), (int *)(_b), (int *)(_c), (int *)(_d), (_e))
    +#else
    +#define ap_select	select
    +#endif
    +
    +#ifdef ULTRIX_BRAIN_DEATH
    +#define ap_fdopen(d,m) fdopen((d), (char *)(m))
    +#else
    +#define ap_fdopen(d,m) fdopen((d), (m))
    +#endif
    +
    +#ifndef ap_inet_addr
    +#define ap_inet_addr inet_addr
    +#endif
    +
    +#ifdef NO_OTHER_CHILD
    +#define NO_RELIABLE_PIPED_LOGS
    +#endif
    +
    +/* When the underlying OS doesn't support exec() of scripts which start
    + * with a HASHBANG (#!) followed by interpreter name and args, define this.
    + */
    +#ifdef NEED_HASHBANG_EMUL
    +extern int ap_execle(const char *filename, const char *arg,...);
    +extern int ap_execve(const char *filename, const char *argv[],
    +                     const char *envp[]);
    +/* ap_execle() is a wrapper function around ap_execve(). */
    +#define execle  ap_execle
    +#define execve(path,argv,envp)  ap_execve(path,argv,envp)
    +#endif
    +
    +/* Finding offsets of elements within structures.
    + * Taken from the X code... they've sweated portability of this stuff
    + * so we don't have to.  Sigh...
    + */
    +
    +#if defined(CRAY) || defined(__arm)
    +#ifdef __STDC__
    +#define XtOffset(p_type,field) _Offsetof(p_type,field)
    +#else
    +#ifdef CRAY2
    +#define XtOffset(p_type,field) \
    +	(sizeof(int)*((unsigned int)&(((p_type)NULL)->field)))
    +
    +#else /* !CRAY2 */
    +
    +#define XtOffset(p_type,field) ((unsigned int)&(((p_type)NULL)->field))
    +
    +#endif /* !CRAY2 */
    +#endif /* __STDC__ */
    +#else /* ! (CRAY || __arm) */
    +
    +#define XtOffset(p_type,field) \
    +	((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
    +
    +#endif /* !CRAY */
    +
    +#ifdef offsetof
    +#define XtOffsetOf(s_type,field) offsetof(s_type,field)
    +#else
    +#define XtOffsetOf(s_type,field) XtOffset(s_type*,field)
    +#endif
    +
    +/* some architectures require size_t * pointers where others require int *
    + * pointers in functions such as accept(), getsockname(), getpeername()
    + */
    +#ifndef NET_SIZE_T
    +#define NET_SIZE_T int
    +#endif
    +
    +/* Linux defines __WCOREDUMP, but doesn't define WCOREDUMP unless __USE_BSD
    + * is in use... we'd prefer to just use WCOREDUMP everywhere.
    + */
    +#if defined(__WCOREDUMP) && !defined(WCOREDUMP)
    +#define WCOREDUMP __WCOREDUMP
    +#endif
    +
    +#ifdef SUNOS_LIB_PROTOTYPES
    +/* Prototypes needed to get a clean compile with gcc -Wall.
    + * Believe it or not, these do have to be declared, at least on SunOS,
    + * because they aren't mentioned in the relevant system headers.
    + * Sun Quality Software.  Gotta love it.  This section is not 
    + * currently (13Nov97) used.
    + */
    +
    +int getopt(int, char **, char *);
    +
    +int strcasecmp(const char *, const char *);
    +int strncasecmp(const char *, const char *, int);
    +int toupper(int);
    +int tolower(int);
    +
    +int printf(char *,...);
    +int fprintf(FILE *, char *,...);
    +int fputs(char *, FILE *);
    +int fread(char *, int, int, FILE *);
    +int fwrite(char *, int, int, FILE *);
    +int fgetc(FILE *);
    +char *fgets(char *s, int, FILE*);
    +int fflush(FILE *);
    +int fclose(FILE *);
    +int ungetc(int, FILE *);
    +int _filbuf(FILE *);	/* !!! */
    +int _flsbuf(unsigned char, FILE *);	/* !!! */
    +int sscanf(char *, char *,...);
    +void setbuf(FILE *, char *);
    +void perror(char *);
    +
    +time_t time(time_t *);
    +int strftime(char *, int, const char *, struct tm *);
    +
    +int initgroups(char *, int);
    +int wait3(int *, int, void *);	/* Close enough for us... */
    +int lstat(const char *, struct stat *);
    +int stat(const char *, struct stat *);
    +int flock(int, int);
    +#ifndef NO_KILLPG
    +int killpg(int, int);
    +#endif
    +int socket(int, int, int);
    +int setsockopt(int, int, int, const char *, int);
    +int listen(int, int);
    +int bind(int, struct sockaddr *, int);
    +int connect(int, struct sockaddr *, int);
    +int accept(int, struct sockaddr *, int *);
    +int shutdown(int, int);
    +
    +int getsockname(int s, struct sockaddr *name, int *namelen);
    +int getpeername(int s, struct sockaddr *name, int *namelen);
    +int gethostname(char *name, int namelen);
    +void syslog(int, char *,...);
    +char *mktemp(char *);
    +
    +long vfprintf(FILE *, const char *, va_list);
    +
    +#endif /* SUNOS_LIB_PROTOTYPES */
    +
    +/* The assumption is that when the functions are missing,
    + * then there's no matching prototype available either.
    + * Declare what is needed exactly as the replacement routines implement it.
    + */
    +#ifdef NEED_STRDUP
    +extern char *strdup (const char *str);
    +#endif
    +#ifdef NEED_STRCASECMP
    +extern int strcasecmp (const char *a, const char *b);
    +#endif
    +#ifdef NEED_STRNCASECMP
    +extern int strncasecmp (const char *a, const char *b, int n);
    +#endif
    +#ifdef NEED_INITGROUPS
    +extern int initgroups(const char *name, gid_t basegid);
    +#endif
    +#ifdef NEED_WAITPID
    +extern int waitpid(pid_t pid, int *statusp, int options);
    +#endif
    +#ifdef NEED_STRERROR
    +extern char *strerror (int err);
    +#endif
    +#ifdef NEED_DIFFTIME
    +extern double difftime(time_t time1, time_t time0);
    +#endif
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_CONF_H */
    diff --git a/APACHE_1_3b7/src/include/buff.h b/APACHE_1_3b7/src/include/buff.h
    new file mode 100644
    index 0000000000..d8b231c11b
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/buff.h
    @@ -0,0 +1,236 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1998 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_BUFF_H
    +#define APACHE_BUFF_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#ifdef B_SFIO
    +#include "sfio.h"
    +#endif
    +
    +#include <stdarg.h>
    +
    +/* Reading is buffered */
    +#define B_RD     (1)
    +/* Writing is buffered */
    +#define B_WR     (2)
    +#define B_RDWR   (3)
    +/* At end of file, or closed stream; no further input allowed */
    +#define B_EOF    (4)
    +/* No further output possible */
    +#define B_EOUT   (8)
    +/* A read error has occurred */
    +#define B_RDERR (16)
    +/* A write error has occurred */
    +#define B_WRERR (32)
    +#ifdef B_ERROR  /* in SVR4: sometimes defined in /usr/include/sys/buf.h */
    +#undef B_ERROR
    +#endif
    +#define B_ERROR (48)
    +/* Use chunked writing */
    +#define B_CHUNK (64)
    +/* bflush() if a read would block */
    +#define B_SAFEREAD (128)
    +/* buffer is a socket */
    +#define B_SOCKET (256)
    +#ifdef CHARSET_EBCDIC
    +#define B_ASCII2EBCDIC 0x40000000  /* Enable conversion for this buffer */
    +#define B_EBCDIC2ASCII 0x80000000  /* Enable conversion for this buffer */
    +#endif /*CHARSET_EBCDIC*/
    +
    +typedef struct buff_struct BUFF;
    +
    +struct buff_struct {
    +    int flags;			/* flags */
    +    unsigned char *inptr;	/* pointer to next location to read */
    +    int incnt;			/* number of bytes left to read from input buffer;
    +				 * always 0 if had a read error  */
    +    int outchunk;		/* location of chunk header when chunking */
    +    int outcnt;			/* number of byte put in output buffer */
    +    unsigned char *inbase;
    +    unsigned char *outbase;
    +    int bufsiz;
    +    void (*error) (BUFF *fb, int op, void *data);
    +    void *error_data;
    +    long int bytes_sent;	/* number of bytes actually written */
    +
    +    ap_pool *pool;
    +
    +/* could also put pointers to the basic I/O routines here */
    +    int fd;			/* the file descriptor */
    +    int fd_in;			/* input file descriptor, if different */
    +#ifdef WIN32
    +    HANDLE hFH;			/* Windows filehandle */
    +#endif
    +
    +    /* transport handle, for RPC binding handle or some such */
    +    void *t_handle;
    +
    +#ifdef B_SFIO
    +    Sfio_t *sf_in;
    +    Sfio_t *sf_out;
    +#endif
    +};
    +
    +#ifdef B_SFIO
    +typedef struct {
    +    Sfdisc_t disc;
    +    BUFF *buff;
    +} apache_sfio;
    +
    +extern Sfdisc_t *bsfio_new(pool *p, BUFF *b);
    +#endif
    +
    +/* Options to bset/getopt */
    +#define BO_BYTECT (1)
    +
    +/* Stream creation and modification */
    +API_EXPORT(BUFF *) ap_bcreate(pool *p, int flags);
    +API_EXPORT(void) ap_bpushfd(BUFF *fb, int fd_in, int fd_out);
    +#ifdef WIN32
    +API_EXPORT(void) ap_bpushh(BUFF *fb, HANDLE hFH);
    +#endif
    +API_EXPORT(int) ap_bsetopt(BUFF *fb, int optname, const void *optval);
    +API_EXPORT(int) ap_bgetopt(BUFF *fb, int optname, void *optval);
    +API_EXPORT(int) ap_bsetflag(BUFF *fb, int flag, int value);
    +API_EXPORT(int) ap_bclose(BUFF *fb);
    +
    +#define bgetflag(fb, flag)	((fb)->flags & (flag))
    +
    +/* Error handling */
    +API_EXPORT(void) ap_bonerror(BUFF *fb, void (*error) (BUFF *, int, void *),
    +			  void *data);
    +
    +/* I/O */
    +API_EXPORT(int) ap_bread(BUFF *fb, void *buf, int nbyte);
    +API_EXPORT(int) ap_bgets(char *s, int n, BUFF *fb);
    +API_EXPORT(int) ap_blookc(char *buff, BUFF *fb);
    +API_EXPORT(int) ap_bskiplf(BUFF *fb);
    +API_EXPORT(int) ap_bwrite(BUFF *fb, const void *buf, int nbyte);
    +API_EXPORT(int) ap_bflush(BUFF *fb);
    +API_EXPORT(int) ap_bputs(const char *x, BUFF *fb);
    +API_EXPORT(int) ap_bvputs(BUFF *fb,...);
    +API_EXPORT_NONSTD(int) ap_bprintf(BUFF *fb, const char *fmt,...)
    +				__attribute__((format(printf,2,3)));
    +API_EXPORT(int) ap_vbprintf(BUFF *fb, const char *fmt, va_list vlist);
    +
    +/* Internal routines */
    +API_EXPORT(int) ap_bflsbuf(int c, BUFF *fb);
    +API_EXPORT(int) ap_bfilbuf(BUFF *fb);
    +
    +#ifndef CHARSET_EBCDIC
    +
    +#define ap_bgetc(fb)   ( ((fb)->incnt == 0) ? ap_bfilbuf(fb) : \
    +		    ((fb)->incnt--, *((fb)->inptr++)) )
    +
    +#define ap_bputc(c, fb) ((((fb)->flags & (B_EOUT|B_WRERR|B_WR)) != B_WR || \
    +		     (fb)->outcnt == (fb)->bufsiz) ? ap_bflsbuf(c, (fb)) : \
    +		     ((fb)->outbase[(fb)->outcnt++] = (c), 0))
    +
    +#else /*CHARSET_EBCDIC*/
    +
    +#define ap_bgetc(fb)   ( ((fb)->incnt == 0) ? ap_bfilbuf(fb) : \
    +		    ((fb)->incnt--, (fb->flags & B_ASCII2EBCDIC)\
    +		    ?os_toebcdic[(unsigned char)*((fb)->inptr++)]:*((fb)->inptr++)) )
    +
    +#define ap_bputc(c, fb) ((((fb)->flags & (B_EOUT|B_WRERR|B_WR)) != B_WR || \
    +		     (fb)->outcnt == (fb)->bufsiz) ? ap_bflsbuf(c, (fb)) : \
    +		     ((fb)->outbase[(fb)->outcnt++] = (fb->flags & B_EBCDIC2ASCII)\
    +		     ?os_toascii[(unsigned char)c]:(c), 0))
    +
    +#endif /*CHARSET_EBCDIC*/
    +struct child_info {
    +#ifdef WIN32
    +    /*
    +     *  These handles are used by ap_call_exec to call 
    +     *  create process with pipe handles.
    +     */
    +    HANDLE hPipeInputRead;
    +    HANDLE hPipeOutputWrite;
    +    HANDLE hPipeErrorWrite;
    +#else
    +    /* 
    +     * We need to put a dummy member in here to avoid compilation
    +     * errors under certain Unix compilers, like SGI's and HPUX's,
    +     * which fail to compile a zero-sized struct.  Of course
    +     * it would be much nicer if there was actually a use for this
    +     * structure under Unix.  Aah the joys of x-platform code.
    +     */
    +    int dummy;
    +#endif
    +};
    +API_EXPORT(int) ap_spawn_child_err_buff(pool *, int (*)(void *, child_info *), void *,
    +					enum kill_conditions, BUFF **pipe_in, BUFF **pipe_out,
    +					BUFF **pipe_err);
    +
    +/* enable non-blocking operations */
    +API_EXPORT(int) ap_bnonblock(BUFF *fb, int direction);
    +/* and get an fd to select() on */
    +API_EXPORT(int) ap_bfileno(BUFF *fb, int direction);
    +
    +/* bflush() if a read now would block, but don't actually read anything */
    +API_EXPORT(void) ap_bhalfduplex(BUFF *fb);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_BUFF_H */
    diff --git a/APACHE_1_3b7/src/include/compat.h b/APACHE_1_3b7/src/include/compat.h
    new file mode 100644
    index 0000000000..06c5963d4d
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/compat.h
    @@ -0,0 +1,410 @@
    +/*
    +**  compat.h -- Apache Backward Compatibility
    +**
    +**  INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED
    +**  BACKWARD COMPATIBILITY TO OLD APACHE RESOURCES.
    +*/
    +
    +#ifndef APACHE_COMPAT_H
    +#define APACHE_COMPAT_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/* 
    + *   Mapping of Apache 1.2 global symbols to the
    + *   namespace conflict free variants used in Apache 1.3
    + */
    +
    +#define MD5Final                       ap_MD5Final
    +#define MD5Init                        ap_MD5Init
    +#define MD5Update                      ap_MD5Update
    +#define acquire_mutex                  ap_acquire_mutex
    +#define add_cgi_vars                   ap_add_cgi_vars
    +#define add_common_vars                ap_add_common_vars
    +#define add_module                     ap_add_module
    +#define add_named_module               ap_add_named_module
    +#define add_per_dir_conf               ap_add_per_dir_conf
    +#define add_per_url_conf               ap_add_per_url_conf
    +#define allow_options                  ap_allow_options
    +#define allow_overrides                ap_allow_overrides
    +#define apapi_get_server_built         ap_get_server_built
    +#define apapi_get_server_version       ap_get_server_version
    +#define aplog_error                    ap_log_error
    +#define append_arrays                  ap_append_arrays
    +#define array_cat                      ap_array_cat
    +#define auth_name                      ap_auth_name
    +#define auth_type                      ap_auth_type
    +#define basic_http_header              ap_basic_http_header
    +#define bclose                         ap_bclose
    +#define bcreate                        ap_bcreate
    +#define bfilbuf                        ap_bfilbuf
    +#define bfileno                        ap_bfileno
    +#define bflsbuf                        ap_bflsbuf
    +#define bflush                         ap_bflush
    +#define bgetc                          ap_bgetc
    +#define bgetopt                        ap_bgetopt
    +#define bgets                          ap_bgets
    +#define bhalfduplex                    ap_bhalfduplex
    +#define bind_address                   ap_bind_address
    +#define block_alarms                   ap_block_alarms
    +#define blookc                         ap_blookc
    +#define bnonblock                      ap_bnonblock
    +#define bonerror                       ap_bonerror
    +#define bprintf                        ap_bprintf
    +#define bpushfd                        ap_bpushfd
    +#define bputc                          ap_bputc
    +#define bputs                          ap_bputs
    +#define bread                          ap_bread
    +#define bsetflag                       ap_bsetflag
    +#define bsetopt                        ap_bsetopt
    +#define bskiplf                        ap_bskiplf
    +#define bvputs                         ap_bvputs
    +#define bwrite                         ap_bwrite
    +#define bytes_in_free_blocks           ap_bytes_in_free_blocks
    +#define bytes_in_pool                  ap_bytes_in_pool
    +#define call_exec                      ap_call_exec
    +#define can_exec                       ap_can_exec
    +#define cfg_closefile                  ap_cfg_closefile
    +#define cfg_getc                       ap_cfg_getc
    +#define cfg_getline                    ap_cfg_getline
    +#define chdir_file                     ap_chdir_file
    +#define check_access                   ap_check_access
    +#define check_alarm                    ap_check_alarm
    +#define check_auth                     ap_check_auth
    +#define check_cmd_context              ap_check_cmd_context
    +#define check_user_id                  ap_check_user_id
    +#define checkmask                      ap_checkmask
    +#define child_exit_modules             ap_child_exit_modules
    +#define child_init_modules             ap_child_init_modules
    +#define child_terminate                ap_child_terminate
    +#define cleanup_for_exec               ap_cleanup_for_exec
    +#define clear_module_list              ap_clear_module_list
    +#define clear_pool                     ap_clear_pool
    +#define clear_table                    ap_clear_table
    +#define close_piped_log                ap_close_piped_log
    +#define construct_server               ap_construct_server
    +#define construct_url                  ap_construct_url
    +#define copy_array                     ap_copy_array
    +#define copy_array_hdr                 ap_copy_array_hdr
    +#define copy_table                     ap_copy_table
    +#define core_reorder_directories       ap_core_reorder_directories
    +#define coredump_dir                   ap_coredump_dir
    +#define count_dirs                     ap_count_dirs
    +#define create_environment             ap_create_environment
    +#define create_mutex                   ap_create_mutex
    +#define create_per_dir_config          ap_create_per_dir_config
    +#define create_request_config          ap_create_request_config
    +#define daemons_limit                  ap_daemons_limit
    +#define daemons_max_free               ap_daemons_max_free
    +#define daemons_min_free               ap_daemons_min_free
    +#define daemons_to_start               ap_daemons_to_start
    +#define day_snames                     ap_day_snames
    +#define default_port_for_request       ap_default_port_for_request
    +#define default_port_for_scheme        ap_default_port_for_scheme
    +#define default_type                   ap_default_type
    +#define destroy_mutex                  ap_destroy_mutex
    +#define destroy_pool                   ap_destroy_pool
    +#define destroy_sub_req                ap_destroy_sub_req
    +#define die                            ap_die
    +#define discard_request_body           ap_discard_request_body
    +#define document_root                  ap_document_root
    +#define dummy_mutex                    ap_dummy_mutex
    +#define each_byterange                 ap_each_byterange
    +#define error_log2stderr               ap_error_log2stderr
    +#define escape_html                    ap_escape_html
    +#define escape_path_segment            ap_escape_path_segment
    +#define escape_shell_cmd               ap_escape_shell_cmd
    +#define excess_requests_per_child      ap_excess_requests_per_child
    +#define exists_scoreboard_image        ap_exists_scoreboard_image
    +#define finalize_request_protocol      ap_finalize_request_protocol
    +#define finalize_sub_req_protocol      ap_finalize_sub_req_protocol
    +#define find_command                   ap_find_command
    +#define find_command_in_modules        ap_find_command_in_modules
    +#define find_last_token                ap_find_last_token
    +#define find_linked_module             ap_find_linked_module
    +#define find_module_name               ap_find_module_name
    +#define find_path_info                 ap_find_path_info
    +#define find_pool                      ap_find_pool
    +#define find_token                     ap_find_token
    +#define find_types                     ap_find_types
    +#define fini_vhost_config              ap_fini_vhost_config
    +#define fnmatch                        ap_fnmatch
    +#define force_library_loading          ap_force_library_loading
    +#define get_basic_auth_pw              ap_get_basic_auth_pw
    +#define get_client_block               ap_get_client_block
    +#define get_gmtoff                     ap_get_gmtoff
    +#define get_local_host                 ap_get_local_host
    +#define get_module_config              ap_get_module_config
    +#define get_remote_host                ap_get_remote_host
    +#define get_remote_logname             ap_get_remote_logname
    +#define get_server_name                ap_get_server_name
    +#define get_server_port                ap_get_server_port
    +#define get_time                       ap_get_time
    +#define get_token                      ap_get_token
    +#define get_virthost_addr              ap_get_virthost_addr
    +#define getparents                     ap_getparents
    +#define getword                        ap_getword
    +#define getword_conf                   ap_getword_conf
    +#define getword_conf_nc                ap_getword_conf_nc
    +#define getword_nc                     ap_getword_nc
    +#define getword_nulls                  ap_getword_nulls
    +#define getword_nulls_nc               ap_getword_nulls_nc
    +#define getword_white                  ap_getword_white
    +#define getword_white_nc               ap_getword_white_nc
    +#define gm_timestr_822                 ap_gm_timestr_822
    +#define gname2id                       ap_gname2id
    +#define group_id                       ap_group_id
    +#define handle_command                 ap_handle_command
    +#define hard_timeout                   ap_hard_timeout
    +#define header_parse                   ap_header_parse
    +#define ht_time                        ap_ht_time
    +#define ind                            ap_ind
    +#define index_of_response              ap_index_of_response
    +#define init_alloc                     ap_init_alloc
    +#define init_modules                   ap_init_modules
    +#define init_vhost_config              ap_init_vhost_config
    +#define init_virtual_host              ap_init_virtual_host
    +#define internal_redirect              ap_internal_redirect
    +#define internal_redirect_handler      ap_internal_redirect_handler
    +#define invoke_handler                 ap_invoke_handler
    +#define is_directory                   ap_is_directory
    +#define is_fnmatch                     ap_is_fnmatch
    +#define is_initial_req                 ap_is_initial_req
    +#define is_matchexp                    ap_is_matchexp
    +#define is_url                         ap_is_url
    +#define keepalive_timeout              ap_keepalive_timeout
    +#define kill_cleanup                   ap_kill_cleanup
    +#define kill_cleanups_for_fd           ap_kill_cleanups_for_fd
    +#define kill_cleanups_for_socket       ap_kill_cleanups_for_socket
    +#define kill_timeout                   ap_kill_timeout
    +#define limit_section                  ap_limit_section
    +#define listenbacklog                  ap_listenbacklog
    +#define listeners                      ap_listeners
    +#define lock_fname                     ap_lock_fname
    +#define log_assert                     ap_log_assert
    +#define log_error                      ap_log_error_old
    +#define log_pid                        ap_log_pid
    +#define log_printf                     ap_log_printf
    +#define log_reason                     ap_log_reason
    +#define log_transaction                ap_log_transaction
    +#define log_unixerr                    ap_log_unixerr
    +#define make_array                     ap_make_array
    +#define make_dirstr                    ap_make_dirstr
    +#define make_dirstr_parent             ap_make_dirstr_parent
    +#define make_dirstr_prefix             ap_make_dirstr_prefix
    +#define make_full_path                 ap_make_full_path
    +#define make_sub_pool                  ap_make_sub_pool
    +#define make_table                     ap_make_table
    +#define matches_request_vhost          ap_matches_request_vhost
    +#define max_requests_per_child         ap_max_requests_per_child
    +#define md5                            ap_md5
    +#define meets_conditions               ap_meets_conditions
    +#define merge_per_dir_configs          ap_merge_per_dir_configs
    +#define month_snames                   ap_month_snames
    +#define no2slash                       ap_no2slash
    +#define note_auth_failure              ap_note_auth_failure
    +#define note_basic_auth_failure        ap_note_basic_auth_failure
    +#define note_cleanups_for_fd           ap_note_cleanups_for_fd
    +#define note_cleanups_for_file         ap_note_cleanups_for_file
    +#define note_cleanups_for_socket       ap_note_cleanups_for_socket
    +#define note_digest_auth_failure       ap_note_digest_auth_failure
    +#define note_subprocess                ap_note_subprocess
    +#define null_cleanup                   ap_null_cleanup
    +#define open_logs                      ap_open_logs
    +#define open_mutex                     ap_open_mutex
    +#define open_piped_log                 ap_open_piped_log
    +#define os_canonical_filename          ap_os_canonical_filename
    +#define os_dl_load                     ap_os_dso_load
    +#define os_dl_unload                   ap_os_dso_unload
    +#define os_dl_sym                      ap_os_dso_sym
    +#define os_dl_error                    ap_os_dso_error
    +#define os_escape_path                 ap_os_escape_path
    +#define os_is_path_absolute            ap_os_is_path_absolute
    +#define overlay_tables                 ap_overlay_tables
    +#define palloc                         ap_palloc
    +#define parseHTTPdate                  ap_parseHTTPdate
    +#define parse_hostinfo_components      ap_parse_hostinfo_components
    +#define parse_htaccess                 ap_parse_htaccess
    +#define parse_uri                      ap_parse_uri
    +#define parse_uri_components           ap_parse_uri_components
    +#define parse_vhost_addrs              ap_parse_vhost_addrs
    +#define pcalloc                        ap_pcalloc
    +#define pcfg_open_custom               ap_pcfg_open_custom
    +#define pcfg_openfile                  ap_pcfg_openfile
    +#define pclosedir                      ap_pclosedir
    +#define pclosef                        ap_pclosef
    +#define pclosesocket                   ap_pclosesocket
    +#define pduphostent                    ap_pduphostent
    +#define pfclose                        ap_pfclose
    +#define pfdopen                        ap_pfdopen
    +#define pfopen                         ap_pfopen
    +#define pgethostbyname                 ap_pgethostbyname
    +#define pid_fname                      ap_pid_fname
    +#define piped_log_read_fd              ap_piped_log_read_fd
    +#define piped_log_write_fd             ap_piped_log_write_fd
    +#define pool_is_ancestor               ap_pool_is_ancestor
    +#define pool_join                      ap_pool_join
    +#define popendir                       ap_popendir
    +#define popenf                         ap_popenf
    +#define pregcomp                       ap_pregcomp
    +#define pregfree                       ap_pregfree
    +#define pregsub                        ap_pregsub
    +#define process_request                ap_process_request
    +#define process_resource_config        ap_process_resource_config
    +#define proxy_add_header               ap_proxy_add_header
    +#define proxy_c2hex                    ap_proxy_c2hex
    +#define proxy_cache_check              ap_proxy_cache_check
    +#define proxy_cache_error              ap_proxy_cache_error
    +#define proxy_cache_tidy               ap_proxy_cache_tidy
    +#define proxy_cache_update             ap_proxy_cache_update
    +#define proxy_canon_netloc             ap_proxy_canon_netloc
    +#define proxy_canonenc                 ap_proxy_canonenc
    +#define proxy_connect_handler          ap_proxy_connect_handler
    +#define proxy_date_canon               ap_proxy_date_canon
    +#define proxy_del_header               ap_proxy_del_header
    +#define proxy_doconnect                ap_proxy_doconnect
    +#define proxy_ftp_canon                ap_proxy_ftp_canon
    +#define proxy_ftp_handler              ap_proxy_ftp_handler
    +#define proxy_garbage_coll             ap_proxy_garbage_coll
    +#define proxy_garbage_init             ap_proxy_garbage_init
    +#define proxy_get_header               ap_proxy_get_header
    +#define proxy_hash                     ap_proxy_hash
    +#define proxy_hex2c                    ap_proxy_hex2c
    +#define proxy_hex2sec                  ap_proxy_hex2sec
    +#define proxy_host2addr                ap_proxy_host2addr
    +#define proxy_http_canon               ap_proxy_http_canon
    +#define proxy_http_handler             ap_proxy_http_handler
    +#define proxy_is_domainname            ap_proxy_is_domainname
    +#define proxy_is_hostname              ap_proxy_is_hostname
    +#define proxy_is_ipaddr                ap_proxy_is_ipaddr
    +#define proxy_is_word                  ap_proxy_is_word
    +#define proxy_liststr                  ap_proxy_liststr
    +#define proxy_log_uerror               ap_proxy_log_uerror
    +#define proxy_read_headers             ap_proxy_read_headers
    +#define proxy_sec2hex                  ap_proxy_sec2hex
    +#define proxy_send_fb                  ap_proxy_send_fb
    +#define proxy_send_headers             ap_proxy_send_headers
    +#define proxyerror                     ap_proxyerror
    +#define psignature                     ap_psignature
    +#define psocket                        ap_psocket
    +#define psprintf                       ap_psprintf
    +#define pstrcat                        ap_pstrcat
    +#define pstrdup                        ap_pstrdup
    +#define pstrndup                       ap_pstrndup
    +#define push_array                     ap_push_array
    +#define pvsprintf                      ap_pvsprintf
    +#define rationalize_mtime              ap_rationalize_mtime
    +#define read_config                    ap_read_config
    +#define read_request                   ap_read_request
    +#define register_cleanup               ap_register_cleanup
    +#define register_other_child           ap_register_other_child
    +#define release_mutex                  ap_release_mutex
    +#define remove_module                  ap_remove_module
    +#define requires                       ap_requires
    +#define reset_timeout                  ap_reset_timeout
    +#define response_code_string           ap_response_code_string
    +#define restart_time                   ap_restart_time
    +#define rfc1413                        ap_rfc1413
    +#define rfc1413_timeout                ap_rfc1413_timeout
    +#define rflush                         ap_rflush
    +#define rind                           ap_rind
    +#define rprintf                        ap_rprintf
    +#define rputc                          ap_rputc
    +#define rputs                          ap_rputs
    +#define run_cleanup                    ap_run_cleanup
    +#define run_fixups                     ap_run_fixups
    +#define run_post_read_request          ap_run_post_read_request
    +#define run_sub_req                    ap_run_sub_req
    +#define rvputs                         ap_rvputs
    +#define rwrite                         ap_rwrite
    +#define satisfies                      ap_satisfies
    +#define scan_script_header_err         ap_scan_script_header_err
    +#define scan_script_header_err_buff    ap_scan_script_header_err_buff
    +#define scoreboard_fname               ap_scoreboard_fname
    +#define scoreboard_image               ap_scoreboard_image
    +#define send_error_response            ap_send_error_response
    +#define send_fb                        ap_send_fb
    +#define send_fb_length                 ap_send_fb_length
    +#define send_fd                        ap_send_fd
    +#define send_fd_length                 ap_send_fd_length
    +#define send_header_field              ap_send_header_field
    +#define send_http_header               ap_send_http_header
    +#define send_http_options              ap_send_http_options
    +#define send_http_trace                ap_send_http_trace
    +#define send_mmap                      ap_send_mmap
    +#define send_size                      ap_send_size
    +#define server_argv0                   ap_server_argv0
    +#define server_confname                ap_server_confname
    +#define server_post_read_config        ap_server_post_read_config
    +#define server_pre_read_config         ap_server_pre_read_config
    +#define server_root                    ap_server_root
    +#define server_root_relative           ap_server_root_relative
    +#define set_byterange                  ap_set_byterange
    +#define set_callback_and_alarm         ap_set_callback_and_alarm
    +#define set_content_length             ap_set_content_length
    +#define set_etag                       ap_set_etag
    +#define set_file_slot                  ap_set_file_slot
    +#define set_flag_slot                  ap_set_flag_slot
    +#define set_keepalive                  ap_set_keepalive
    +#define set_last_modified              ap_set_last_modified
    +#define set_module_config              ap_set_module_config
    +#define set_name_virtual_host          ap_set_name_virtual_host
    +#define set_string_slot                ap_set_string_slot
    +#define set_string_slot_lower          ap_set_string_slot_lower
    +#define set_sub_req_protocol           ap_set_sub_req_protocol
    +#define setup_client_block             ap_setup_client_block
    +#define setup_prelinked_modules        ap_setup_prelinked_modules
    +#define should_client_block            ap_should_client_block
    +#define show_directives                ap_show_directives
    +#define show_modules                   ap_show_modules
    +#define soft_timeout                   ap_soft_timeout
    +#define some_auth_required             ap_some_auth_required
    +#define spawn_child_err                ap_spawn_child_err
    +#define spawn_child_err_buff           ap_spawn_child_err_buff
    +#define srm_command_loop               ap_srm_command_loop
    +#define standalone                     ap_standalone
    +#define start_restart                  ap_start_restart
    +#define start_shutdown                 ap_start_shutdown
    +#define str_tolower                    ap_str_tolower
    +#define strcasecmp_match               ap_strcasecmp_match
    +#define strcmp_match                   ap_strcmp_match
    +#define sub_req_lookup_file            ap_sub_req_lookup_file
    +#define sub_req_lookup_uri             ap_sub_req_lookup_uri
    +#define suexec_enabled                 ap_suexec_enabled
    +#define sync_scoreboard_image          ap_sync_scoreboard_image
    +#define table_add                      ap_table_add
    +#define table_addn                     ap_table_addn
    +#define table_do                       ap_table_do
    +#define table_get                      ap_table_get
    +#define table_merge                    ap_table_merge
    +#define table_mergen                   ap_table_mergen
    +#define table_set                      ap_table_set
    +#define table_setn                     ap_table_setn
    +#define table_unset                    ap_table_unset
    +#define threads_per_child              ap_threads_per_child
    +#define time_process_request           ap_time_process_request
    +#define tm2sec                         ap_tm2sec
    +#define translate_name                 ap_translate_name
    +#define uname2id                       ap_uname2id
    +#define unblock_alarms                 ap_unblock_alarms
    +#define unescape_url                   ap_unescape_url
    +#define unparse_uri_components         ap_unparse_uri_components
    +#define unregister_other_child         ap_unregister_other_child
    +#define update_child_status            ap_update_child_status
    +#define update_mtime                   ap_update_mtime
    +#define update_vhost_from_headers      ap_update_vhost_from_headers
    +#define update_vhost_given_ip          ap_update_vhost_given_ip
    +#define user_id                        ap_user_id
    +#define user_name                      ap_user_name
    +#define util_init                      ap_util_init
    +#define util_uri_init                  ap_util_uri_init
    +#define uudecode                       ap_uudecode
    +#define vbprintf                       ap_vbprintf
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif /* APACHE_COMPAT_H */
    diff --git a/APACHE_1_3b7/src/include/conf.h b/APACHE_1_3b7/src/include/conf.h
    new file mode 100644
    index 0000000000..1e67a5b3f7
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/conf.h
    @@ -0,0 +1,1170 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_CONF_H
    +#define APACHE_CONF_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/*
    + * conf.h: system-dependant #defines and includes...
    + * See PORTING for a listing of what they mean
    + */
    +
    +
    +/* Have to include sys/stat.h before ../os/win32/os.h so we can override
    +stat() properly */
    +#include <sys/types.h>
    +#include <sys/stat.h>
    +
    +#ifdef WIN32
    +/* include process.h first so we can override spawn[lv]e* properly */
    +#include <process.h>
    +#include "../os/win32/os.h"
    +#else
    +#include "os.h"
    +#endif
    +
    +#if !defined(QNX) && !defined(MPE) && !defined(WIN32)
    +#include <sys/param.h>
    +#endif
    +
    +/* Define one of these according to your system. */
    +#if defined(MINT)
    +typedef int rlim_t;
    +#define HAVE_SYS_RESOURCE_H 1
    +#define JMP_BUF sigjmp_buf
    +#define NO_LONG_DOUBLE
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define _BSD_SOURCE
    +#define EAGAIN EWOULDBLOCK
    +int initgroups (char *, int);     
    +char *crypt (const char *pw, const char *salt);
    +int gethostname (char *name, int namelen);
    +
    +#elif defined(MPE)
    +#include <sys/times.h>
    +#define NO_SETSID
    +#define NO_KILLPG
    +#define NO_WRITEV
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define SHM_R 0400  /* Read permission */
    +#define SHM_W 0200  /* Write permission */
    +#define NEED_INITGROUPS
    +#define NEED_STRCASECMP
    +#define NEED_STRDUP
    +#define NEED_STRNCASECMP
    +extern void GETPRIVMODE();
    +extern void GETUSERMODE();
    +extern char *inet_ntoa();
    +#define NO_SLACK
    +#define NO_GETTIMEOFDAY
    +#define S_IEXEC  S_IXUSR
    +#define S_IREAD  S_IRUSR
    +#define S_IWRITE S_IWUSR
    +#define PF_INET  AF_INET
    +
    +#elif defined(SUNOS4)
    +#define HAVE_GMTOFF 1
    +#define HAVE_SYS_RESOURCE_H 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +char *crypt(const char *pw, const char *salt);
    +char *mktemp(char *template);
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#include <sys/time.h>
    +#define NEED_STRERROR
    +typedef int rlim_t;
    +#define memmove(a,b,c) bcopy(b,a,c)
    +#define NO_LINGCLOSE
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define NEED_DIFFTIME
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(SOLARIS2)
    +#undef HAVE_GMTOFF
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SYS_RESOURCE_H 1
    +#define HAVE_DLFCN_H 1
    +#define bzero(a,b) memset(a,0,b)
    +#if !defined(USE_SYSVSEM_SERIALIZED_ACCEPT) && \
    +    !defined(USE_PTHREAD_SERIALIZED_ACCEPT)
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#endif
    +#define NEED_UNION_SEMUN
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +int gethostname(char *name, int namelen);
    +#define HAVE_SYSLOG 1
    +#define SYS_SIGLIST _sys_siglist
    +
    +#elif defined(IRIX)
    +#undef HAVE_GMTOFF
    +/* IRIX has killpg, but it's only in _BSD_COMPAT, so don't use it in case
    + * there's some weird conflict with non-BSD signals */
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#if !defined(USE_FCNTL_SERIALIZED_ACCEPT) && !defined(USE_USLOCK_SERIALIZED_ACCEPT)
    +#define USE_SYSVSEM_SERIALIZED_ACCEPT
    +#endif
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define HAVE_MMAP 1
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +#define HAVE_DLFCN_H 1
    +#define NO_LONG_DOUBLE
    +#define HAVE_BSTRING_H 1
    +#define NO_LINGCLOSE
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(HIUX)
    +#define HAVE_SYS_RESOURCE_H 1
    +#undef HAVE_GMTOFF
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#ifndef _HIUX_SOURCE
    +#define _HIUX_SOURCE
    +#endif
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define SELECT_NEEDS_CAST
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(HPUX) || defined(HPUX10)
    +#define HAVE_SYS_RESOURCE_H 1
    +#undef HAVE_GMTOFF
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#ifndef _HPUX_SOURCE
    +#define _HPUX_SOURCE
    +#endif
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define HAVE_SYSLOG 1
    +#ifndef HPUX10
    +#define SELECT_NEEDS_CAST
    +typedef int rlim_t;
    +#endif
    +
    +#elif defined(HPUX11)
    +#ifndef _HPUX_SOURCE
    +#define _HPUX_SOURCE
    +#endif
    +#define HAVE_SHMGET
    +#define USE_SHMGET_SCOREBOARD
    +#undef  HAVE_GMTOFF
    +#define HAVE_RESOURCE
    +#define HAVE_CRYPT_H
    +#undef  HAVE_SYS_SELECT_H
    +#define HAVE_SYS_RESOURCE_H
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +/* feeling brave?  want to try using POSIX mutexes? */
    +/* #define HAVE_MMAP */
    +/* #define USE_MMAP_SCOREBOARD */
    +/* #define USE_MMAP_FILES */
    +/* #define USE_PTHREAD_SERIALIZED_ACCEPT */
    +#define NO_KILLPG
    +#undef  NO_SETSID
    +#define HAVE_SYSLOG
    +
    +#elif defined(AIX)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SYS_SELECT_H 1
    +#ifndef __ps2__
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_SYSLOG 1
    +#ifndef DEFAULT_GROUP
    +#define DEFAULT_GROUP "nobody"
    +#endif
    +#endif
    +#ifndef DEFAULT_USER
    +#define DEFAULT_USER "nobody"
    +#endif
    +#ifdef NEED_RLIM_T
    +typedef int rlim_t;
    +#endif
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#ifdef USEBCOPY
    +#define memmove(a,b,c) bcopy(b,a,c)
    +#endif
    +#if AIX >= 42
    +#define NET_SIZE_T size_t
    +#endif
    +
    +#elif defined(ULTRIX)
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define ULTRIX_BRAIN_DEATH
    +#define NEED_STRDUP
    +/* If you have Ultrix 4.3, and are using cc, const is broken */
    +#ifndef __ultrix__		/* Hack to check for pre-Ultrix 4.4 cc */
    +#define const			/* Not implemented */
    +#endif
    +
    +#elif defined(OSF1)
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +#define NO_LONG_DOUBLE
    +#define HAVE_SYSLOG 1
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +
    +#elif defined(PARAGON)
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +#define NO_LONG_DOUBLE
    +#define HAVE_SYSLOG 1
    +typedef int rlim_t;
    +
    +#elif defined(SEQUENT)
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#define NO_SETSID
    +#define NEED_STRDUP
    +#define HAVE_SYSLOG 1
    +#define tolower(c) (isupper(c) ? tolower(c) : c)
    +
    +#elif defined(NEXT)
    +typedef unsigned short mode_t;
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#define NO_SETSID
    +#define NEED_STRDUP
    +#define NO_LINGCLOSE
    +#define NO_UNISTD_H
    +#undef _POSIX_SOURCE
    +#ifndef FD_CLOEXEC
    +#define FD_CLOEXEC 1
    +#endif
    +#ifndef S_ISDIR
    +#define S_ISDIR(m)      (((m)&(S_IFMT)) == (S_IFDIR))
    +#endif
    +#ifndef S_ISREG
    +#define S_ISREG(m)      (((m)&(S_IFMT)) == (S_IFREG))
    +#endif
    +#ifndef S_IXUSR
    +#define S_IXUSR 00100
    +#endif
    +#ifndef S_IRGRP
    +#define S_IRGRP 00040
    +#endif
    +#ifndef S_IXGRP
    +#define S_IXGRP 00010
    +#endif
    +#ifndef S_IROTH
    +#define S_IROTH 00004
    +#endif
    +#ifndef S_IXOTH
    +#define S_IXOTH 00001
    +#endif
    +#ifndef S_IRUSR
    +#define S_IRUSR S_IREAD
    +#endif
    +#ifndef S_IWUSR
    +#define S_IWUSR S_IWRITE
    +#endif
    +#ifndef S_IWGRP
    +#define S_IWGRP	000020
    +#endif
    +#ifndef S_IWOTH
    +#define S_IWOTH 000002
    +#ifndef rlim_t
    +typedef int rlim_t;
    +#endif
    +typedef u_long n_long;
    +#endif
    +
    +#define STDIN_FILENO  0
    +#define STDOUT_FILENO 1
    +#define STDERR_FILENO 2
    +#define waitpid(a,b,c) wait4((a) == -1 ? 0 : (a),(union wait *)(b),c,NULL)
    +typedef int pid_t;
    +#define USE_LONGJMP
    +#define NO_USE_SIGACTION
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(LINUX)
    +#define HAVE_DLFCN_H 1
    +
    +#if LINUX > 1
    +#include <features.h>
    +
    +/* libc4 systems probably still work, it probably doesn't define
    + *  __GNU_LIBRARY__
    + * libc5 systems define __GNU_LIBRARY__ == 1, but don't define __GLIBC__
    + * glibc 2.x and later systems define __GNU_LIBRARY__ == 6, but list it as
    + * "deprecated in favour of __GLIBC__"; the value 6 will never be changed.
    + * glibc 1.x systems (i.e. redhat 4.x on sparc/alpha) should have
    + * __GLIBC__ < 2
    + * all glibc based systems need crypt.h
    + */
    +#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
    +#include <crypt.h>
    +#endif
    +
    +/* glibc 2.0.0 through 2.0.4 need size_t * here, where 2.0.5 needs socklen_t *
    + * there's no way to discern between these two libraries.  But using int should
    + * be portable because otherwise these libs would be hopelessly broken with
    + * reams of existing networking code.  We'll use socklen_t * for 2.1.x and
    + * later.
    + *
    + * int works for all the earlier libs, and is picked up by default later.
    + */
    +#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0))
    +#define NET_SIZE_T socklen_t
    +#endif
    +
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define HAVE_MMAP 1
    +#define USE_MMAP_FILES
    +#define HAVE_SYS_RESOURCE_H 1
    +
    +/* glibc 2.1 and later finally define rlim_t */
    +#if !defined(__GLIBC__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)
    +typedef int rlim_t;
    +#endif
    +
    +/* flock is faster ... but hasn't been tested on 1.x systems */
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +
    +#define SYS_SIGLIST	_sys_siglist
    +
    +#else
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#endif
    +
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#undef NEED_STRDUP
    +#include <sys/time.h>
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(SCO)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define NEED_INITGROUPS
    +#define NO_WRITEV
    +#include <sys/time.h>
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(SCO5)
    +
    +#define HAVE_SYS_SELECT_H 1
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_SYS_RESOURCE_H 1
    +#define SecureWare
    +#define HAVE_SYSLOG 1
    +
    +/* Although SCO 5 defines these in <strings.h> (note the "s") they don't have
    +   consts. Sigh. */
    +extern int strcasecmp(const char *, const char *);
    +extern int strncasecmp(const char *, const char *, unsigned);
    +
    +#elif defined(AUX3)
    +/* These are to let -Wall compile more cleanly */
    +extern int strcasecmp(const char *, const char *);
    +extern int strncasecmp(const char *, const char *, unsigned);
    +extern int set42sig(), getopt(), getpeername(), bzero();
    +extern int listen(), bind(), socket(), getsockname();
    +extern int accept(), gethostname(), connect(), lstat();
    +extern int select(), killpg(), shutdown();
    +extern int initgroups(), setsockopt();
    +extern char *shmat();
    +extern int shmctl();
    +extern int shmget();
    +extern char *sbrk();
    +extern char *crypt();
    +#include <sys/time.h>
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define NEED_STRDUP
    +/* fcntl() locking is expensive with NFS */
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +/*
    + * NOTE: If when you run Apache under A/UX and you get a warning
    + * that httpd couldn't move break, then the below value for
    + * MOVEBREAK (64megs) is too large for your setup. Try reducing
    + * to 0x2000000 which is still PLENTY of space. I doubt if
    + * even on heavy systems sbrk() would be called at all...
    + */
    +#define MOVEBREAK		0x4000000
    +#define NO_LINGCLOSE
    +#define NO_SLACK
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(SVR4)
    +#define NO_KILLPG
    +#undef  NO_SETSID
    +#undef NEED_STRDUP
    +#ifndef MPRAS
    +#define NEED_STRCASECMP
    +#ifndef ENCORE
    +#define NEED_STRNCASECMP
    +#endif /* ENCORE */
    +#endif /* MPRAS */
    +#define bzero(a,b) memset(a,0,b)
    +/* A lot of SVR4 systems need this */
    +#ifndef USE_SYSVSEM_SERIALIZED_ACCEPT
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#endif
    +#define HAVE_SYSLOG 1
    +#define NET_SIZE_T size_t
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#ifdef _OSD_POSIX /* BS2000-POSIX mainframe needs initgroups */
    +#define NEED_INITGROUPS
    +#define NEED_HASHBANG_EMUL /* execve() doesn't start shell scripts by default */
    +#undef HAVE_SHMGET
    +#undef USE_SHMGET_SCOREBOARD
    +#undef bzero
    +#endif /*_OSD_POSIX*/
    +
    +#elif defined(UW)
    +#define NO_LINGCLOSE
    +#define NO_KILLPG
    +#undef  NO_SETSID
    +#undef NEED_STRDUP
    +#define NEED_STRCASECMP
    +#define NEED_STRNCASECMP
    +#define bzero(a,b) memset(a,0,b)
    +#define HAVE_RESOURCE 1
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_SHMGET 1
    +#undef USE_SHMGET_SCOREBOARD	/* force use of mmap() scoreboard */
    +#define HAVE_CRYPT_H 1
    +#define HAVE_SYS_SELECT_H 1
    +#define HAVE_SYS_RESOURCE_H 1
    +#include <sys/time.h>
    +#if UW >= 200
    +#define _POSIX_SOURCE
    +#endif
    +#define NET_SIZE_T size_t
    +#define HAVE_SYSLOG 1
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +
    +#elif defined(DGUX)
    +#define NO_KILLPG
    +#undef  NO_SETSID
    +#undef NEED_STRDUP
    +#define NEED_STRCASECMP
    +#define NEED_STRNCASECMP
    +#define bzero(a,b) memset(a,0,b)
    +/* A lot of SVR4 systems need this */
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#define ap_inet_addr inet_network
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(NETBSD)
    +#define HAVE_SYS_RESOURCE_H 1
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SYSLOG 1
    +#ifndef DEFAULT_USER
    +#define DEFAULT_USER "nobody"
    +#endif
    +#ifndef DEFAULT_GROUP
    +#define DEFAULT_GROUP "nogroup"
    +#define HAVE_SHMGET 1
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#endif
    +
    +#elif defined(UTS21)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#define NO_SETSID
    +#define NEED_WAITPID
    +#define NO_OTHER_CHILD
    +#define STDIN_FILENO 0
    +#define STDOUT_FILENO 1
    +#define STDERR_FILENO 2
    +#define HAVE_SYSLOG 1
    +#define strftime(buf,bufsize,fmt,tm)    ascftime(buf,fmt,tm)
    +#include <sys/types.h>
    +
    +#elif defined(APOLLO)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(__FreeBSD__) || defined(__bsdi__)
    +#if defined(__FreeBSD__)
    +#include <osreldate.h>
    +#endif
    +#define HAVE_DLFCN_H 1
    +#define HAVE_SYS_RESOURCE_H 1
    +#define HAVE_GMTOFF 1
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#ifndef DEFAULT_USER
    +#define DEFAULT_USER "nobody"
    +#endif
    +#ifndef DEFAULT_GROUP
    +#define DEFAULT_GROUP "nogroup"
    +#endif
    +#if defined(__bsdi__) || \
    +(defined(__FreeBSD_version) && (__FreeBSD_version < 220000))
    +typedef quad_t rlim_t;
    +#endif
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define HAVE_SYSLOG 1
    +#define SYS_SIGLIST sys_siglist
    +
    +#elif defined(QNX)
    +#ifndef crypt
    +char *crypt(const char *pw, const char *salt);
    +#endif
    +#ifndef initgroups
    +int initgroups(char *, int);
    +#endif
    +#ifndef strncasecmp
    +#define strncasecmp strnicmp
    +#endif
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#define NEED_INITGROUPS
    +#define NEED_SELECT_H
    +#define NEED_PROCESS_H
    +#define HAVE_SYS_SELECT_H 1
    +#include <unix.h>
    +#define HAVE_MMAP 1
    +#define USE_POSIX_SCOREBOARD
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(LYNXOS)
    +#undef HAVE_GMTOFF
    +#define HAVE_RESOURCE 1
    +#undef USE_MMAP_SCOREBOARD
    +#undef USE_SHMGET_SCOREBOARD
    +#undef HAVE_CRYPT_H
    +#undef HAVE_SYS_SELECT_H
    +#define HAVE_SYS_RESOURCE_H 1
    +#undef USE_FCNTL_SERIALIZED_ACCEPT
    +#undef USE_FLOCK_SERIALIZED_ACCEPT
    +#define USE_LONGJMP
    +#undef NO_UNISTD_H
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#undef NO_USE_SIGACTION
    +#undef NO_LINGCLOSE
    +extern char *crypt(char *pw, char *salt);
    +typedef int rlim_t;
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(UXPDS)
    +#undef NEED_STRCASECMP
    +#undef NEED_STRNCASECMP
    +#undef NEED_STRDUP
    +#undef HAVE_GMTOFF
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_RESOURCE 1 
    +#define bzero(a,b) memset(a,0,b)
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_CRYPT_H 1
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(__EMX__)
    +/* Defines required for EMX OS/2 port. */
    +#define NO_KILLPG
    +#define NEED_STRCASECMP
    +#define NEED_STRNCASECMP
    +#define NO_SETSID
    +#define NO_TIMES
    +/* Add some drive name support */
    +#define chdir _chdir2
    +#include <sys/time.h>
    +#define MAXSOCKETS 4096
    +#define USE_OS2_SCOREBOARD
    +#define NO_RELIABLE_PIPED_LOGS
    +
    +#elif defined(__MACHTEN__)
    +typedef int rlim_t;
    +#undef NO_KILLPG
    +#define NO_SETSID
    +#define HAVE_GMTOFF 1
    +#ifndef __MACHTEN_PPC__
    +#ifndef __MACHTEN_68K__
    +#define __MACHTEN_68K__
    +#endif
    +#define USE_FLOCK_SERIALIZED_ACCEPT
    +#define NO_USE_SIGACTION
    +#define JMP_BUF sigjmp_buf
    +#define USE_LONGJMP
    +#undef NEED_STRDUP
    +#else
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#endif
    +
    +/* Convex OS v11 */
    +#elif defined(CONVEXOS11)
    +#undef HAVE_GMTOFF
    +#undef NO_KILLPG
    +#undef NO_SETSID
    +#undef NEED_STRDUP
    +#define HAVE_MMAP 1
    +#define USE_MMAP_SCOREBOARD
    +#define USE_MMAP_FILES
    +#define HAVE_SYSLOG 1
    +
    +#define NO_TIMEZONE
    +#include <stdio.h>
    +#include <sys/types.h>
    +typedef int rlim_t;
    +
    +#elif defined(ISC)
    +#include <net/errno.h>
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#define HAVE_SYSLOG 1
    +
    +#elif defined(NEWSOS)
    +#define HAVE_SYS_RESOURCE_H 1
    +#define HAVE_SHMGET 1
    +#define USE_SHMGET_SCOREBOARD
    +#define USE_LONGJMP
    +#define NO_SETSID
    +#define NO_USE_SIGACTION
    +#define NEED_WAITPID
    +#define NO_OTHER_CHILD
    +#define HAVE_SYSLOG 1
    +#include <sys/time.h>
    +#include <stdlib.h>
    +#include <sys/types.h>
    +typedef int pid_t;
    +typedef int rlim_t;
    +typedef int mode_t;
    +
    +#elif defined(RISCIX)
    +#include <sys/time.h>
    +typedef int rlim_t;
    +#define NO_USE_SIGACTION
    +#define USE_LONGJMP
    +#define NEED_STRCASECMP
    +#define NEED_STRNCASECMP
    +#define NEED_STRDUP
    +
    +#elif defined(BEOS)
    +#include <stddef.h>
    +
    +#define NO_WRITEV
    +#define NO_KILLPG
    +#define NEED_INITGROUPS
    +
    +#define isascii(c)	(!((c) & ~0177))
    +
    +#elif defined(WIN32)
    +
    +/* All windows stuff is now in os/win32/os.h */
    +
    +#else
    +/* Unknown system - Edit these to match */
    +#ifdef BSD
    +#define HAVE_GMTOFF 1
    +#else
    +#undef HAVE_GMTOFF
    +#endif
    +/* NO_KILLPG is set on systems that don't have killpg */
    +#undef NO_KILLPG
    +/* NO_SETSID is set on systems that don't have setsid */
    +#undef NO_SETSID
    +/* NEED_STRDUP is set on stupid systems that don't have strdup. */
    +#undef NEED_STRDUP
    +#endif
    +
    +/* stuff marked API_EXPORT is part of the API, and intended for use
    + * by modules
    + */
    +#ifndef API_EXPORT
    +#define API_EXPORT(type)    type
    +#endif
    +
    +/* Stuff marked API_EXPORT_NONSTD is part of the API, and intended for
    + * use by modules.  The difference between API_EXPORT and
    + * API_EXPORT_NONSTD is that the latter is required for any functions
    + * which use varargs or are used via indirect function call.  This
    + * is to accomodate the two calling conventions in windows dlls.
    + */
    +#ifndef API_EXPORT_NONSTD
    +#define API_EXPORT_NONSTD(type)    type
    +#endif
    +
    +#ifndef MODULE_VAR_EXPORT
    +#define MODULE_VAR_EXPORT
    +#endif
    +#ifndef API_VAR_EXPORT
    +#define API_VAR_EXPORT
    +#endif
    +
    +/* modules should not used functions marked CORE_EXPORT
    + * or CORE_EXPORT_NONSTD */
    +#ifndef CORE_EXPORT
    +#define CORE_EXPORT	API_EXPORT
    +#endif
    +#ifndef CORE_EXPORT_NONSTD
    +#define CORE_EXPORT_NONSTD	API_EXPORT_NONSTD
    +#endif
    +
    +/* So that we can use inline on some critical functions, and use
    + * GNUC attributes (such as to get -Wall warnings for printf-like
    + * functions).  Only do this in gcc 2.7 or later ... it may work
    + * on earlier stuff, but why chance it.
    + *
    + * We've since discovered that the gcc shipped with NeXT systems
    + * as "cc" is completely broken.  It claims to be __GNUC__ and so
    + * on, but it doesn't implement half of the things that __GNUC__
    + * means.  In particular it's missing inline and the __attribute__
    + * stuff.  So we hack around it.  PR#1613. -djg
    + */
    +#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 7 || defined(NEXT)
    +#define ap_inline
    +#define __attribute__(__x)
    +#define ENUM_BITFIELD(e,n,w)  signed int n : w
    +#else
    +#define ap_inline __inline__
    +#define USE_GNU_INLINE
    +#define ENUM_BITFIELD(e,n,w)  e n : w
    +#endif
    +
    +/* Do we have sys/resource.h; assume that BSD does. */
    +#ifndef HAVE_SYS_RESOURCE_H
    +#ifdef BSD
    +#define HAVE_SYS_RESOURCE_H 1
    +#endif
    +#endif /* HAVE_SYS_RESOURCE_H */
    +
    +/*
    + * The particular directory style your system supports. If you have dirent.h
    + * in /usr/include (POSIX) or /usr/include/sys (SYSV), #include 
    + * that file and define DIR_TYPE to be dirent. Otherwise, if you have 
    + * /usr/include/sys/dir.h, define DIR_TYPE to be direct and include that
    + * file. If you have neither, I'm confused.
    + */
    +
    +#include <sys/types.h>
    +#include <stdarg.h>
    +
    +#if !defined(NEXT) && !defined(WIN32)
    +#include <dirent.h>
    +#define DIR_TYPE dirent
    +#elif !defined(WIN32)
    +#include <sys/dir.h>
    +#define DIR_TYPE direct
    +#else
    +#define DIR_TYPE dirent
    +#endif
    +
    +#include <stdio.h>
    +#include <stdlib.h>
    +#include <string.h>
    +#include <ctype.h>
    +#if !defined(MPE) && !defined(WIN32)
    +#include <sys/file.h>
    +#endif
    +#ifndef WIN32
    +#include <sys/socket.h>
    +#ifdef HAVE_SYS_SELECT_H
    +#include <sys/select.h>
    +#endif /* HAVE_SYS_SELECT_H */
    +#include <netinet/in.h>
    +#include <netdb.h>
    +#include <sys/ioctl.h>
    +#if !defined(MPE) && !defined(BEOS)
    +#include <arpa/inet.h>		/* for inet_ntoa */
    +#endif
    +#include <sys/wait.h>
    +#include <pwd.h>
    +#include <grp.h>
    +#include <fcntl.h>
    +#include <limits.h>
    +#define closesocket(s) close(s)
    +#ifndef O_BINARY
    +#define O_BINARY (0)
    +#endif
    +
    +#else /* WIN32 */
    +#include <winsock.h>
    +#include <malloc.h>
    +#include <io.h>
    +#include <fcntl.h>
    +#endif /* ndef WIN32 */
    +
    +#include <time.h>		/* for ctime */
    +#include <signal.h>
    +#include <errno.h>
    +#if !defined(QNX) && !defined(CONVEXOS11) && !defined(NEXT)
    +#include <memory.h>
    +#endif
    +
    +#ifdef NEED_PROCESS_H
    +#include <process.h>
    +#endif
    +
    +#ifdef WIN32
    +#include "../include/hsregex.h"
    +#elif defined(USE_HSREGEX)
    +#include "hsregex.h"
    +#else
    +#include <regex.h>
    +#endif
    +
    +#ifdef HAVE_SYS_RESOURCE_H
    +#include <sys/resource.h>
    +#ifdef SUNOS4
    +int getrlimit(int, struct rlimit *);
    +int setrlimit(int, struct rlimit *);
    +#endif
    +#endif
    +#ifdef USE_MMAP_SCOREBOARD
    +#if !defined(__EMX__) && !defined(WIN32)
    +/* This file is not needed for OS/2 */
    +#include <sys/mman.h>
    +#endif
    +#endif
    +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
    +#define MAP_ANON MAP_ANONYMOUS
    +#endif
    +
    +#if defined(USE_MMAP_FILES) && (defined(NO_MMAP) || !defined(HAVE_MMAP))
    +#undef USE_MMAP_FILES
    +#endif
    +
    +#if defined(USE_MMAP_SCOREBOARD) && (defined(NO_MMAP) || !defined(HAVE_MMAP))
    +#undef USE_MMAP_SCOREBOARD
    +#endif
    +
    +#if defined(USE_SHMGET_SCOREBOARD) && (defined(NO_SHMGET) || !defined(HAVE_SHMGET))
    +#undef USE_SHMGET_SCOREBOARD
    +#endif
    +
    +#ifndef LOGNAME_MAX
    +#define LOGNAME_MAX 25
    +#endif
    +
    +#ifndef NO_UNISTD_H
    +#include <unistd.h>
    +#endif
    +
    +#ifdef ultrix
    +#define ULTRIX_BRAIN_DEATH
    +#endif
    +
    +#ifndef S_ISLNK
    +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
    +#endif
    +
    +#ifndef INADDR_NONE
    +#define INADDR_NONE ((unsigned long) -1)
    +#endif
    +
    +/*
    + * Replace signal function with sigaction equivalent
    + */
    +#ifndef NO_USE_SIGACTION
    +typedef void Sigfunc(int);
    +
    +#if defined(SIG_IGN) && !defined(SIG_ERR)
    +#define SIG_ERR ((Sigfunc *)-1)
    +#endif
    +
    +/*
    + * For some strange reason, QNX defines signal to signal. Eliminate it.
    + */
    +#ifdef signal
    +#undef signal
    +#endif
    +#define signal(s,f)	ap_signal(s,f)
    +Sigfunc *signal(int signo, Sigfunc * func);
    +#endif
    +
    +#include <setjmp.h>
    +
    +#if defined(USE_LONGJMP)
    +#define ap_longjmp(x, y)        longjmp((x), (y))
    +#define ap_setjmp(x)            setjmp(x)
    +#ifndef JMP_BUF
    +#define JMP_BUF jmp_buf
    +#endif
    +#else
    +#define ap_longjmp(x, y)        siglongjmp((x), (y))
    +#define ap_setjmp(x)            sigsetjmp((x), 1)
    +#ifndef JMP_BUF
    +#define JMP_BUF sigjmp_buf
    +#endif
    +#endif
    +
    +#ifdef SELECT_NEEDS_CAST
    +#define ap_select(_a, _b, _c, _d, _e)	\
    +    select((_a), (int *)(_b), (int *)(_c), (int *)(_d), (_e))
    +#else
    +#define ap_select	select
    +#endif
    +
    +#ifdef ULTRIX_BRAIN_DEATH
    +#define ap_fdopen(d,m) fdopen((d), (char *)(m))
    +#else
    +#define ap_fdopen(d,m) fdopen((d), (m))
    +#endif
    +
    +#ifndef ap_inet_addr
    +#define ap_inet_addr inet_addr
    +#endif
    +
    +#ifdef NO_OTHER_CHILD
    +#define NO_RELIABLE_PIPED_LOGS
    +#endif
    +
    +/* When the underlying OS doesn't support exec() of scripts which start
    + * with a HASHBANG (#!) followed by interpreter name and args, define this.
    + */
    +#ifdef NEED_HASHBANG_EMUL
    +extern int ap_execle(const char *filename, const char *arg,...);
    +extern int ap_execve(const char *filename, const char *argv[],
    +                     const char *envp[]);
    +/* ap_execle() is a wrapper function around ap_execve(). */
    +#define execle  ap_execle
    +#define execve(path,argv,envp)  ap_execve(path,argv,envp)
    +#endif
    +
    +/* Finding offsets of elements within structures.
    + * Taken from the X code... they've sweated portability of this stuff
    + * so we don't have to.  Sigh...
    + */
    +
    +#if defined(CRAY) || defined(__arm)
    +#ifdef __STDC__
    +#define XtOffset(p_type,field) _Offsetof(p_type,field)
    +#else
    +#ifdef CRAY2
    +#define XtOffset(p_type,field) \
    +	(sizeof(int)*((unsigned int)&(((p_type)NULL)->field)))
    +
    +#else /* !CRAY2 */
    +
    +#define XtOffset(p_type,field) ((unsigned int)&(((p_type)NULL)->field))
    +
    +#endif /* !CRAY2 */
    +#endif /* __STDC__ */
    +#else /* ! (CRAY || __arm) */
    +
    +#define XtOffset(p_type,field) \
    +	((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL)))
    +
    +#endif /* !CRAY */
    +
    +#ifdef offsetof
    +#define XtOffsetOf(s_type,field) offsetof(s_type,field)
    +#else
    +#define XtOffsetOf(s_type,field) XtOffset(s_type*,field)
    +#endif
    +
    +/* some architectures require size_t * pointers where others require int *
    + * pointers in functions such as accept(), getsockname(), getpeername()
    + */
    +#ifndef NET_SIZE_T
    +#define NET_SIZE_T int
    +#endif
    +
    +/* Linux defines __WCOREDUMP, but doesn't define WCOREDUMP unless __USE_BSD
    + * is in use... we'd prefer to just use WCOREDUMP everywhere.
    + */
    +#if defined(__WCOREDUMP) && !defined(WCOREDUMP)
    +#define WCOREDUMP __WCOREDUMP
    +#endif
    +
    +#ifdef SUNOS_LIB_PROTOTYPES
    +/* Prototypes needed to get a clean compile with gcc -Wall.
    + * Believe it or not, these do have to be declared, at least on SunOS,
    + * because they aren't mentioned in the relevant system headers.
    + * Sun Quality Software.  Gotta love it.  This section is not 
    + * currently (13Nov97) used.
    + */
    +
    +int getopt(int, char **, char *);
    +
    +int strcasecmp(const char *, const char *);
    +int strncasecmp(const char *, const char *, int);
    +int toupper(int);
    +int tolower(int);
    +
    +int printf(char *,...);
    +int fprintf(FILE *, char *,...);
    +int fputs(char *, FILE *);
    +int fread(char *, int, int, FILE *);
    +int fwrite(char *, int, int, FILE *);
    +int fgetc(FILE *);
    +char *fgets(char *s, int, FILE*);
    +int fflush(FILE *);
    +int fclose(FILE *);
    +int ungetc(int, FILE *);
    +int _filbuf(FILE *);	/* !!! */
    +int _flsbuf(unsigned char, FILE *);	/* !!! */
    +int sscanf(char *, char *,...);
    +void setbuf(FILE *, char *);
    +void perror(char *);
    +
    +time_t time(time_t *);
    +int strftime(char *, int, const char *, struct tm *);
    +
    +int initgroups(char *, int);
    +int wait3(int *, int, void *);	/* Close enough for us... */
    +int lstat(const char *, struct stat *);
    +int stat(const char *, struct stat *);
    +int flock(int, int);
    +#ifndef NO_KILLPG
    +int killpg(int, int);
    +#endif
    +int socket(int, int, int);
    +int setsockopt(int, int, int, const char *, int);
    +int listen(int, int);
    +int bind(int, struct sockaddr *, int);
    +int connect(int, struct sockaddr *, int);
    +int accept(int, struct sockaddr *, int *);
    +int shutdown(int, int);
    +
    +int getsockname(int s, struct sockaddr *name, int *namelen);
    +int getpeername(int s, struct sockaddr *name, int *namelen);
    +int gethostname(char *name, int namelen);
    +void syslog(int, char *,...);
    +char *mktemp(char *);
    +
    +long vfprintf(FILE *, const char *, va_list);
    +
    +#endif /* SUNOS_LIB_PROTOTYPES */
    +
    +/* The assumption is that when the functions are missing,
    + * then there's no matching prototype available either.
    + * Declare what is needed exactly as the replacement routines implement it.
    + */
    +#ifdef NEED_STRDUP
    +extern char *strdup (const char *str);
    +#endif
    +#ifdef NEED_STRCASECMP
    +extern int strcasecmp (const char *a, const char *b);
    +#endif
    +#ifdef NEED_STRNCASECMP
    +extern int strncasecmp (const char *a, const char *b, int n);
    +#endif
    +#ifdef NEED_INITGROUPS
    +extern int initgroups(const char *name, gid_t basegid);
    +#endif
    +#ifdef NEED_WAITPID
    +extern int waitpid(pid_t pid, int *statusp, int options);
    +#endif
    +#ifdef NEED_STRERROR
    +extern char *strerror (int err);
    +#endif
    +#ifdef NEED_DIFFTIME
    +extern double difftime(time_t time1, time_t time0);
    +#endif
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_CONF_H */
    diff --git a/APACHE_1_3b7/src/include/explain.h b/APACHE_1_3b7/src/include/explain.h
    new file mode 100644
    index 0000000000..217e999b9f
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/explain.h
    @@ -0,0 +1,44 @@
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#ifndef EXPLAIN
    +#define DEF_Explain
    +#define Explain0(f)
    +#define Explain1(f,a1)
    +#define Explain2(f,a1,a2)
    +#define Explain3(f,a1,a2,a3)
    +#define Explain4(f,a1,a2,a3,a4)
    +#define Explain5(f,a1,a2,a3,a4,a5)
    +#define Explain6(f,a1,a2,a3,a4,a5,a6)
    +#else
    +#include "http_log.h"
    +#define DEF_Explain
    +#define Explain0(f) \
    +        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
    +                    f)
    +#define Explain1(f,a1) \
    +        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
    +                    f,a1)
    +#define Explain2(f,a1,a2) \
    +        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
    +                    f,a1,a2)
    +#define Explain3(f,a1,a2,a3) \
    +        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
    +                    f,a1,a2,a3)
    +#define Explain4(f,a1,a2,a3,a4) \
    +        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
    +                    f,a1,a2,a3,a4)
    +#define Explain5(f,a1,a2,a3,a4,a5)  \
    +        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
    +                    f,a1,a2,a3,a4,a5)
    +#define Explain6(f,a1,a2,a3,a4,a5,a6)   \
    +        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, \
    +                    f,a1,a2,a3,a4,a5,a6)
    +
    +#endif
    +
    +#ifdef __cplusplus
    +}
    +#endif
    diff --git a/APACHE_1_3b7/src/include/fnmatch.h b/APACHE_1_3b7/src/include/fnmatch.h
    new file mode 100644
    index 0000000000..22aea6a97a
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/fnmatch.h
    @@ -0,0 +1,62 @@
    +/*-
    + * Copyright (c) 1992, 1993
    + *	The Regents of the University of California.  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 acknowledgement:
    + *	This product includes software developed by the University of
    + *	California, Berkeley and its contributors.
    + * 4. Neither the name of the University nor the names of its contributors
    + *    may be used to endorse or promote products derived from this software
    + *    without specific prior written permission.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    + * ANY EXPRESS 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 REGENTS OR 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.
    + *
    + *	@(#)fnmatch.h	8.1 (Berkeley) 6/2/93
    + */
    +
    +/* This file has been modified by the Apache Group. */
    +
    +#include "conf.h"
    +
    +#ifndef	_FNMATCH_H_
    +#define	_FNMATCH_H_
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#define	FNM_NOMATCH	1	/* Match failed. */
    +
    +#define	FNM_NOESCAPE	0x01	/* Disable backslash escaping. */
    +#define	FNM_PATHNAME	0x02	/* Slash must be matched by slash. */
    +#define	FNM_PERIOD	0x04	/* Period must be matched by period. */
    +
    +API_EXPORT(int) ap_fnmatch(const char *, const char *, int);
    +
    +/* this function is an Apache addition */
    +API_EXPORT(extern int) ap_is_fnmatch(const char *);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif /* !_FNMATCH_H_ */
    diff --git a/APACHE_1_3b7/src/include/hsregex.h b/APACHE_1_3b7/src/include/hsregex.h
    new file mode 100644
    index 0000000000..54d5b43831
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/hsregex.h
    @@ -0,0 +1,81 @@
    +#ifndef _REGEX_H_
    +#define	_REGEX_H_	/* never again */
    +/* ========= begin header generated by ./mkh ========= */
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/* === regex2.h === */
    +#ifndef API_EXPORT
    +#ifdef WIN32
    +#define API_EXPORT(type)    __declspec(dllexport) type __stdcall
    +#else
    +#define API_EXPORT(type)    type
    +#endif
    +#endif
    +
    +typedef off_t regoff_t;
    +typedef struct {
    +	int re_magic;
    +	size_t re_nsub;		/* number of parenthesized subexpressions */
    +	const char *re_endp;	/* end pointer for REG_PEND */
    +	struct re_guts *re_g;	/* none of your business :-) */
    +} regex_t;
    +typedef struct {
    +	regoff_t rm_so;		/* start of match */
    +	regoff_t rm_eo;		/* end of match */
    +} regmatch_t;
    +
    +
    +/* === regcomp.c === */
    +API_EXPORT(int) regcomp(regex_t *, const char *, int);
    +#define	REG_BASIC	0000
    +#define	REG_EXTENDED	0001
    +#define	REG_ICASE	0002
    +#define	REG_NOSUB	0004
    +#define	REG_NEWLINE	0010
    +#define	REG_NOSPEC	0020
    +#define	REG_PEND	0040
    +#define	REG_DUMP	0200
    +
    +
    +/* === regerror.c === */
    +#define	REG_NOMATCH	 1
    +#define	REG_BADPAT	 2
    +#define	REG_ECOLLATE	 3
    +#define	REG_ECTYPE	 4
    +#define	REG_EESCAPE	 5
    +#define	REG_ESUBREG	 6
    +#define	REG_EBRACK	 7
    +#define	REG_EPAREN	 8
    +#define	REG_EBRACE	 9
    +#define	REG_BADBR	10
    +#define	REG_ERANGE	11
    +#define	REG_ESPACE	12
    +#define	REG_BADRPT	13
    +#define	REG_EMPTY	14
    +#define	REG_ASSERT	15
    +#define	REG_INVARG	16
    +#define	REG_ATOI	255	/* convert name to number (!) */
    +#define	REG_ITOA	0400	/* convert number to name (!) */
    +API_EXPORT(size_t) regerror(int, const regex_t *, char *, size_t);
    +
    +
    +/* === regexec.c === */
    +API_EXPORT(int) regexec(const regex_t *, const char *, size_t, regmatch_t [], int);
    +#define	REG_NOTBOL	00001
    +#define	REG_NOTEOL	00002
    +#define	REG_STARTEND	00004
    +#define	REG_TRACE	00400	/* tracing of execution */
    +#define	REG_LARGE	01000	/* force large representation */
    +#define	REG_BACKR	02000	/* force use of backref code */
    +
    +
    +/* === regfree.c === */
    +API_EXPORT(void) regfree(regex_t *);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +/* ========= end header generated by ./mkh ========= */
    +#endif
    diff --git a/APACHE_1_3b7/src/include/http_conf_globals.h b/APACHE_1_3b7/src/include/http_conf_globals.h
    new file mode 100644
    index 0000000000..341c767c7c
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/http_conf_globals.h
    @@ -0,0 +1,118 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_HTTP_CONF_GLOBALS_H
    +#define APACHE_HTTP_CONF_GLOBALS_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/* 
    + * Process config --- what the process ITSELF is doing
    + */
    +
    +extern int ap_standalone;
    +extern uid_t ap_user_id;
    +extern char *ap_user_name;
    +extern gid_t ap_group_id;
    +#ifdef MULTIPLE_GROUPS
    +extern gid_t group_id_list[NGROUPS_MAX];
    +#endif
    +extern int ap_max_requests_per_child;
    +extern int ap_threads_per_child;
    +extern int ap_excess_requests_per_child;
    +extern struct in_addr ap_bind_address;
    +extern listen_rec *ap_listeners;
    +extern int ap_daemons_to_start;
    +extern int ap_daemons_min_free;
    +extern int ap_daemons_max_free;
    +extern int ap_daemons_limit;
    +extern MODULE_VAR_EXPORT int ap_suexec_enabled;
    +extern int ap_listenbacklog;
    +extern int ap_dump_settings;
    +
    +extern char *ap_pid_fname;
    +extern char *ap_scoreboard_fname;
    +extern char *ap_lock_fname;
    +extern MODULE_VAR_EXPORT char *ap_server_argv0;
    +
    +extern enum server_token_type ap_server_tokens;
    +
    +/* Trying to allocate these in the config pool gets us into some *nasty*
    + * chicken-and-egg problems in http_main.c --- where do you stick them
    + * when pconf gets cleared?  Better to just allocate a little space
    + * statically...
    + */
    +
    +extern API_VAR_EXPORT char ap_server_root[MAX_STRING_LEN];
    +extern char ap_server_confname[MAX_STRING_LEN];
    +
    +/* for -C and -c switches */
    +extern array_header *ap_server_pre_read_config;
    +extern array_header *ap_server_post_read_config;
    +
    +/* We want this to have the least chance of being corrupted if there
    + * is some memory corruption, so we allocate it statically.
    + */
    +extern char ap_coredump_dir[MAX_STRING_LEN];
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_CONF_GLOBALS_H */
    diff --git a/APACHE_1_3b7/src/include/http_config.h b/APACHE_1_3b7/src/include/http_config.h
    new file mode 100644
    index 0000000000..83a2fc578e
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/http_config.h
    @@ -0,0 +1,392 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_HTTP_CONFIG_H
    +#define APACHE_HTTP_CONFIG_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/*
    + * The central data structures around here...
    + */
    +
    +/* Command dispatch structures... */
    +
    +/* Note that for all of these except RAW_ARGS, the config routine is
    + * passed a freshly allocated string which can be modified or stored
    + * or whatever... it's only necessary to do pstrdup() stuff with
    + * RAW_ARGS.
    + */
    +enum cmd_how {
    +    RAW_ARGS,			/* cmd_func parses command line itself */
    +    TAKE1,			/* one argument only */
    +    TAKE2,			/* two arguments only */
    +    ITERATE,			/* one argument, occuring multiple times
    +				 * (e.g., IndexIgnore)
    +				 */
    +    ITERATE2,			/* two arguments, 2nd occurs multiple times
    +				 * (e.g., AddIcon)
    +				 */
    +    FLAG,			/* One of 'On' or 'Off' */
    +    NO_ARGS,			/* No args at all, e.g. </Directory> */
    +    TAKE12,			/* one or two arguments */
    +    TAKE3,			/* three arguments only */
    +    TAKE23,			/* two or three arguments */
    +    TAKE123,			/* one, two or three arguments */
    +    TAKE13			/* one or three arguments */
    +};
    +
    +typedef struct command_struct {
    +    const char *name;		/* Name of this command */
    +    const char *(*func) ();	/* Function invoked */
    +    void *cmd_data;		/* Extra data, for functions which
    +				 * implement multiple commands...
    +				 */
    +    int req_override;		/* What overrides need to be allowed to
    +				 * enable this command.
    +				 */
    +    enum cmd_how args_how;	/* What the command expects as arguments */
    +
    +    const char *errmsg;		/* 'usage' message, in case of syntax errors */
    +} command_rec;
    +
    +/* The allowed locations for a configuration directive are the union of
    + * those indicated by each set bit in the req_override mask.
    + *
    + * (req_override & RSRC_CONF)   => *.conf outside <Directory> or <Location>
    + * (req_override & ACCESS_CONF) => *.conf inside <Directory> or <Location>
    + * (req_override & OR_AUTHCFG)  => *.conf inside <Directory> or <Location>
    + *                                 and .htaccess when AllowOverride AuthConfig
    + * (req_override & OR_LIMIT)    => *.conf inside <Directory> or <Location>
    + *                                 and .htaccess when AllowOverride Limit
    + * (req_override & OR_OPTIONS)  => *.conf anywhere
    + *                                 and .htaccess when AllowOverride Options
    + * (req_override & OR_FILEINFO) => *.conf anywhere
    + *                                 and .htaccess when AllowOverride FileInfo
    + * (req_override & OR_INDEXES)  => *.conf anywhere
    + *                                 and .htaccess when AllowOverride Indexes
    + */
    +#define OR_NONE 0
    +#define OR_LIMIT 1
    +#define OR_OPTIONS 2
    +#define OR_FILEINFO 4
    +#define OR_AUTHCFG 8
    +#define OR_INDEXES 16
    +#define OR_UNSET 32
    +#define ACCESS_CONF 64
    +#define RSRC_CONF 128
    +#define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG|OR_INDEXES)
    +
    +/* This can be returned by a function if they don't wish to handle
    + * a command. Make it something not likely someone will actually use
    + * as an error code.
    + */
    +
    +#define DECLINE_CMD "\a\b"
    +
    +/*
    + * This structure is passed to a command which is being invoked,
    + * to carry a large variety of miscellaneous data which is all of
    + * use to *somebody*...
    + */
    +
    +typedef struct {
    +    void *info;			/* Argument to command from cmd_table */
    +    int override;		/* Which allow-override bits are set */
    +    int limited;		/* Which methods are <Limit>ed */
    +
    +    configfile_t *config_file;	/* Config file structure from pcfg_openfile() */
    +
    +    ap_pool *pool;			/* Pool to allocate new storage in */
    +    struct pool *temp_pool;		/* Pool for scratch memory; persists during
    +				 * configuration, but wiped before the first
    +				 * request is served...
    +				 */
    +    server_rec *server;		/* Server_rec being configured for */
    +    char *path;			/* If configuring for a directory,
    +				 * pathname of that directory.
    +				 * NOPE!  That's what it meant previous to the
    +				 * existance of <Files>, <Location> and regex
    +				 * matching.  Now the only usefulness that can
    +				 * be derived from this field is whether a command
    +				 * is being called in a server context (path == NULL)
    +				 * or being called in a dir context (path != NULL).
    +				 */
    +    const command_rec *cmd;	/* configuration command */
    +    const char *end_token;	/* end token required to end a nested section */
    +} cmd_parms;
    +
    +/* This structure records the existence of handlers in a module... */
    +
    +typedef struct {
    +    const char *content_type;	/* MUST be all lower case */
    +    int (*handler) (request_rec *);
    +} handler_rec;
    +
    +/*
    + * Module structures.  Just about everything is dispatched through
    + * these, directly or indirectly (through the command and handler
    + * tables).
    + */
    +
    +typedef struct module_struct {
    +    int version;		/* API version, *not* module version;
    +				 * check that module is compatible with this
    +				 * version of the server.
    +				 */
    +    int module_index;		/* Index to this modules structures in
    +				 * config vectors.
    +				 */
    +
    +    const char *name;
    +
    +    void *dynamic_load_handle;
    +
    +    struct module_struct *next;
    +
    +    /* init() occurs after config parsing, but before any children are
    +     * forked.
    +     * Modules should not rely on the order in which create_server_config
    +     * and create_dir_config are called.
    +     */
    +#ifdef ULTRIX_BRAIN_DEATH
    +    void (*init) ();
    +    void *(*create_dir_config) ();
    +    void *(*merge_dir_config) ();
    +    void *(*create_server_config) ();
    +    void *(*merge_server_config) ();
    +#else
    +    void (*init) (server_rec *, pool *);
    +    void *(*create_dir_config) (pool *p, char *dir);
    +    void *(*merge_dir_config) (pool *p, void *base_conf, void *new_conf);
    +    void *(*create_server_config) (pool *p, server_rec *s);
    +    void *(*merge_server_config) (pool *p, void *base_conf, void *new_conf);
    +#endif
    +
    +    const command_rec *cmds;
    +    const handler_rec *handlers;
    +
    +    /* Hooks for getting into the middle of server ops...
    +
    +     * translate_handler --- translate URI to filename
    +     * access_checker --- check access by host address, etc.   All of these
    +     *                    run; if all decline, that's still OK.
    +     * check_user_id --- get and validate user id from the HTTP request
    +     * auth_checker --- see if the user (from check_user_id) is OK *here*.
    +     *                  If all of *these* decline, the request is rejected
    +     *                  (as a SERVER_ERROR, since the module which was
    +     *                  supposed to handle this was configured wrong).
    +     * type_checker --- Determine MIME type of the requested entity;
    +     *                  sets content_type, _encoding and _language fields.
    +     * logger --- log a transaction.
    +     * post_read_request --- run right after read_request or internal_redirect,
    +     *                  and not run during any subrequests.
    +     */
    +
    +    int (*translate_handler) (request_rec *);
    +    int (*ap_check_user_id) (request_rec *);
    +    int (*auth_checker) (request_rec *);
    +    int (*access_checker) (request_rec *);
    +    int (*type_checker) (request_rec *);
    +    int (*fixer_upper) (request_rec *);
    +    int (*logger) (request_rec *);
    +    int (*header_parser) (request_rec *);
    +
    +    /* Regardless of the model the server uses for managing "units of
    +     * execution", i.e. multi-process, multi-threaded, hybrids of those,
    +     * there is the concept of a "heavy weight process".  That is, a
    +     * process with its own memory space, file spaces, etc.  This method,
    +     * child_init, is called once for each heavy-weight process before
    +     * any requests are served.  Note that no provision is made yet for
    +     * initialization per light-weight process (i.e. thread).  The
    +     * parameters passed here are the same as those passed to the global
    +     * init method above.
    +     */
    +#ifdef ULTRIX_BRAIN_DEATH
    +    void (*child_init) ();
    +    void (*child_exit) ();
    +#else
    +    void (*child_init) (server_rec *, pool *);
    +    void (*child_exit) (server_rec *, pool *);
    +#endif
    +    int (*post_read_request) (request_rec *);
    +} module;
    +
    +/* Initializer for the first few module slots, which are only
    + * really set up once we start running.  Note that the first word
    + * is a version check; this should allow us to deal with changes to
    + * the API (the server can detect an old-format module, and either
    + * handle it back-compatibly, or at least signal an error).
    + */
    +
    +#define MODULE_MAGIC_NUMBER 19980519
    +#define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER, -1, __FILE__, NULL, NULL
    +
    +/* Generic accessors for other modules to get at their own module-specific
    + * data
    + */
    +
    +API_EXPORT(void *) ap_get_module_config(void *conf_vector, module *m);
    +API_EXPORT(void) ap_set_module_config(void *conf_vector, module *m, void *val);
    +
    +#define ap_get_module_config(v,m)	\
    +    (((void **)(v))[(m)->module_index])
    +#define ap_set_module_config(v,m,val)	\
    +    ((((void **)(v))[(m)->module_index]) = (val))
    +
    +/* Generic command handling function... */
    +
    +API_EXPORT_NONSTD(const char *) ap_set_string_slot(cmd_parms *, char *, char *);
    +API_EXPORT_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *, char *, char *);
    +API_EXPORT_NONSTD(const char *) ap_set_flag_slot(cmd_parms *, char *, int);
    +API_EXPORT_NONSTD(const char *) ap_set_file_slot(cmd_parms *, char *, char *);
    +
    +/* For modules which need to read config files, open logs, etc. ...
    + * this returns the fname argument if it begins with '/'; otherwise
    + * it relativizes it wrt server_root.
    + */
    +
    +API_EXPORT(char *) ap_server_root_relative(pool *p, char *fname);
    +
    +/* Finally, the hook for dynamically loading modules in... */
    +
    +API_EXPORT(void) ap_add_module(module *m);
    +API_EXPORT(void) ap_remove_module(module *m);
    +API_EXPORT(void) ap_add_loaded_module(module *mod);
    +API_EXPORT(void) ap_remove_loaded_module(module *mod);
    +API_EXPORT(int) ap_add_named_module(const char *name);
    +API_EXPORT(void) ap_clear_module_list(void);
    +API_EXPORT(const char *) ap_find_module_name(module *m);
    +API_EXPORT(module *) ap_find_linked_module(const char *name);
    +
    +/* for implementing subconfigs and customized config files */
    +API_EXPORT(const char *) ap_srm_command_loop(cmd_parms *parms, void *config);
    +
    +#ifdef CORE_PRIVATE
    +
    +extern API_VAR_EXPORT module *top_module;
    +
    +extern module *ap_prelinked_modules[];
    +extern module *ap_preloaded_modules[];
    +extern API_VAR_EXPORT module **ap_loaded_modules;
    +
    +/* For http_main.c... */
    +
    +server_rec *ap_read_config(pool *conf_pool, pool *temp_pool, char *config_name);
    +void ap_init_modules(pool *p, server_rec *s);
    +void ap_child_init_modules(pool *p, server_rec *s);
    +void ap_child_exit_modules(pool *p, server_rec *s);
    +void ap_setup_prelinked_modules(void);
    +void ap_show_directives(void);
    +void ap_show_modules(void);
    +
    +/* For http_request.c... */
    +
    +void *ap_create_request_config(pool *p);
    +CORE_EXPORT(void *) ap_create_per_dir_config(pool *p);
    +void *ap_merge_per_dir_configs(pool *p, void *base, void *new);
    +
    +/* For http_core.c... (<Directory> command and virtual hosts) */
    +
    +int ap_parse_htaccess(void **result, request_rec *r, int override,
    +		const char *path, const char *access_name);
    +
    +CORE_EXPORT(const char *) ap_init_virtual_host(pool *p, const char *hostname,
    +				server_rec *main_server, server_rec **);
    +void ap_process_resource_config(server_rec *s, char *fname, pool *p, pool *ptemp);
    +
    +/* check_cmd_context() definitions: */
    +API_EXPORT(const char *) ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden);
    +
    +/* check_cmd_context():                  Forbidden in: */
    +#define  NOT_IN_VIRTUALHOST     0x01 /* <Virtualhost> */
    +#define  NOT_IN_LIMIT           0x02 /* <Limit> */
    +#define  NOT_IN_DIRECTORY       0x04 /* <Directory> */
    +#define  NOT_IN_LOCATION        0x08 /* <Location> */
    +#define  NOT_IN_FILES           0x10 /* <Files> */
    +#define  NOT_IN_DIR_LOC_FILE    (NOT_IN_DIRECTORY|NOT_IN_LOCATION|NOT_IN_FILES) /* <Directory>/<Location>/<Files>*/
    +#define  GLOBAL_ONLY            (NOT_IN_VIRTUALHOST|NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE)
    +
    +
    +/* Module-method dispatchers, also for http_request.c */
    +
    +int ap_translate_name(request_rec *);
    +int ap_check_access(request_rec *);	/* check access on non-auth basis */
    +int ap_check_user_id(request_rec *);	/* obtain valid username from client auth */
    +int ap_check_auth(request_rec *);	/* check (validated) user is authorized here */
    +int ap_find_types(request_rec *);	/* identify MIME type */
    +int ap_run_fixups(request_rec *);	/* poke around for other metainfo, etc.... */
    +int ap_invoke_handler(request_rec *);
    +int ap_log_transaction(request_rec *r);
    +int ap_header_parse(request_rec *);
    +int ap_run_post_read_request(request_rec *);
    +
    +/* for mod_perl */
    +
    +CORE_EXPORT(const command_rec *) ap_find_command(const char *name, const command_rec *cmds);
    +CORE_EXPORT(const command_rec *) ap_find_command_in_modules(const char *cmd_name, module **mod);
    +CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, const char *l);
    +
    +#endif
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_CONFIG_H */
    diff --git a/APACHE_1_3b7/src/include/http_core.h b/APACHE_1_3b7/src/include/http_core.h
    new file mode 100644
    index 0000000000..68d6f1ac3b
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/http_core.h
    @@ -0,0 +1,261 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_HTTP_CORE_H
    +#define APACHE_HTTP_CORE_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/*****************************************************************
    + *
    + * The most basic server code is encapsulated in a single module
    + * known as the core, which is just *barely* functional enough to
    + * serve documents, though not terribly well.
    + *
    + * Largely for NCSA back-compatibility reasons, the core needs to
    + * make pieces of its config structures available to other modules.
    + * The accessors are declared here, along with the interpretation
    + * of one of them (allow_options).
    + */
    +
    +#define OPT_NONE 0
    +#define OPT_INDEXES 1
    +#define OPT_INCLUDES 2
    +#define OPT_SYM_LINKS 4
    +#define OPT_EXECCGI 8
    +#define OPT_UNSET 16
    +#define OPT_INCNOEXEC 32
    +#define OPT_SYM_OWNER 64
    +#define OPT_MULTI 128
    +#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS|OPT_EXECCGI)
    +
    +/* options for get_remote_host() */
    +#define REMOTE_HOST (0)
    +#define REMOTE_NAME (1)
    +#define REMOTE_NOLOOKUP (2)
    +#define REMOTE_DOUBLE_REV (3)
    +
    +#define SATISFY_ALL 0
    +#define SATISFY_ANY 1
    +#define SATISFY_NOSPEC 2
    +
    +API_EXPORT(int) ap_allow_options (request_rec *);
    +API_EXPORT(int) ap_allow_overrides (request_rec *);
    +API_EXPORT(char *) ap_default_type (request_rec *);     
    +API_EXPORT(char *) ap_document_root (request_rec *); /* Don't use this!  If your request went
    +				      * through a Userdir, or something like
    +				      * that, it'll screw you.  But it's
    +				      * back-compatible...
    +				      */
    +API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config, int type);
    +API_EXPORT(const char *) ap_get_remote_logname(request_rec *r);
    +
    +/* Used for constructing self-referencing URLs, and things like SERVER_PORT,
    + * and SERVER_NAME.
    + */
    +API_EXPORT(char *) ap_construct_url(pool *p, const char *uri, const request_rec *r);
    +API_EXPORT(const char *) ap_get_server_name(const request_rec *r);
    +API_EXPORT(unsigned) ap_get_server_port(const request_rec *r);
    +     
    +/* Authentication stuff.  This is one of the places where compatibility
    + * with the old config files *really* hurts; they don't discriminate at
    + * all between different authentication schemes, meaning that we need
    + * to maintain common state for all of them in the core, and make it
    + * available to the other modules through interfaces.
    + */
    +    
    +typedef struct {
    +    int method_mask;
    +    char *requirement;
    +} require_line;
    +     
    +API_EXPORT(char *) ap_auth_type (request_rec *);
    +API_EXPORT(char *) ap_auth_name (request_rec *);     
    +API_EXPORT(int) ap_satisfies (request_rec *r);
    +API_EXPORT(array_header *) ap_requires (request_rec *);    
    +
    +#ifdef CORE_PRIVATE
    +
    +/*
    + * Core is also unlike other modules in being implemented in more than
    + * one file... so, data structures are declared here, even though most of
    + * the code that cares really is in http_core.c.  Also, anothre accessor.
    + */
    +
    +char *ap_response_code_string (request_rec *r, int error_index);
    +
    +extern API_VAR_EXPORT module core_module;
    +
    +/* Per-directory configuration */
    +
    +typedef unsigned char allow_options_t;
    +typedef unsigned char overrides_t;
    +
    +typedef struct {
    +    /* path of the directory/regex/etc.  see also d_is_fnmatch below */
    +    char *d;
    +    /* the number of slashes in d */
    +    unsigned d_components;
    +
    +    /* If (opts & OPT_UNSET) then no absolute assignment to options has
    +     * been made.
    +     * invariant: (opts_add & opts_remove) == 0
    +     * Which said another way means that the last relative (options + or -)
    +     * assignment made to each bit is recorded in exactly one of opts_add
    +     * or opts_remove.
    +     */
    +    allow_options_t opts;
    +    allow_options_t opts_add;
    +    allow_options_t opts_remove;
    +    overrides_t override;
    +    
    +    /* MIME typing --- the core doesn't do anything at all with this,
    +     * but it does know what to slap on a request for a document which
    +     * goes untyped by other mechanisms before it slips out the door...
    +     */
    +    
    +    char *ap_default_type;
    +  
    +    /* Authentication stuff.  Groan... */
    +    
    +    int satisfy;
    +    char *ap_auth_type;
    +    char *ap_auth_name;
    +    array_header *ap_requires;
    +
    +    /* Custom response config. These can contain text or a URL to redirect to.
    +     * if response_code_strings is NULL then there are none in the config,
    +     * if it's not null then it's allocated to sizeof(char*)*RESPONSE_CODES.
    +     * This lets us do quick merges in merge_core_dir_configs().
    +     */
    +  
    +    char **response_code_strings;
    +
    +    /* Hostname resolution etc */
    +#define HOSTNAME_LOOKUP_OFF	0
    +#define HOSTNAME_LOOKUP_ON	1
    +#define HOSTNAME_LOOKUP_DOUBLE	2
    +#define HOSTNAME_LOOKUP_UNSET	3
    +    unsigned int hostname_lookups : 4;
    +
    +    signed int do_rfc1413 : 2;   /* See if client is advertising a username? */
    +
    +    signed int content_md5 : 2;  /* calculate Content-MD5? */
    +
    +    unsigned use_canonical_name : 2; /* bit 0 = on/off, bit 1 = unset/set */
    +
    +    /* since is_fnmatch(conf->d) was being called so frequently in
    +     * directory_walk() and its relatives, this field was created and
    +     * is set to the result of that call.
    +     */
    +    unsigned d_is_fnmatch : 1;
    +
    +    /* System Resource Control */
    +#ifdef RLIMIT_CPU
    +    struct rlimit *limit_cpu;
    +#endif
    +#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
    +    struct rlimit *limit_mem;
    +#endif
    +#ifdef RLIMIT_NPROC
    +    struct rlimit *limit_nproc;
    +#endif
    +
    +    /* logging options */
    +    enum { srv_sig_off, srv_sig_on, srv_sig_withmail } server_signature;
    +    int loglevel;
    +    
    +    /* Access control */
    +    array_header *sec;
    +    regex_t *r;
    +
    +} core_dir_config;
    +
    +/* Per-server core configuration */
    +
    +typedef struct {
    +  
    +    /* Name translations --- we want the core to be able to do *something*
    +     * so it's at least a minimally functional web server on its own (and
    +     * can be tested that way).  But let's keep it to the bare minimum:
    +     */
    +    char *ap_document_root;
    +  
    +    /* Access control */
    +
    +    char *access_name;
    +    array_header *sec;
    +    array_header *sec_url;
    +} core_server_config;
    +
    +/* for http_config.c */
    +void ap_core_reorder_directories(pool *, server_rec *);
    +
    +/* for mod_perl */
    +CORE_EXPORT(void) ap_add_per_dir_conf (server_rec *s, void *dir_config);
    +CORE_EXPORT(void) ap_add_per_url_conf (server_rec *s, void *url_config);
    +CORE_EXPORT_NONSTD(const char *) ap_limit_section (cmd_parms *cmd, void *dummy, const char *arg);
    +
    +#endif
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_CORE_H */
    diff --git a/APACHE_1_3b7/src/include/http_log.h b/APACHE_1_3b7/src/include/http_log.h
    new file mode 100644
    index 0000000000..ece0737157
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/http_log.h
    @@ -0,0 +1,147 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_HTTP_LOG_H
    +#define APACHE_HTTP_LOG_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#ifdef HAVE_SYSLOG
    +#include <syslog.h>
    +
    +#define APLOG_EMERG     LOG_EMERG     /* system is unusable */
    +#define APLOG_ALERT     LOG_ALERT     /* action must be taken immediately */
    +#define APLOG_CRIT      LOG_CRIT      /* critical conditions */
    +#define APLOG_ERR       LOG_ERR       /* error conditions */
    +#define APLOG_WARNING   LOG_WARNING   /* warning conditions */
    +#define APLOG_NOTICE    LOG_NOTICE    /* normal but significant condition */
    +#define APLOG_INFO      LOG_INFO      /* informational */
    +#define APLOG_DEBUG     LOG_DEBUG     /* debug-level messages */
    +
    +#define APLOG_LEVELMASK LOG_PRIMASK   /* mask off the level value */
    +
    +#else
    +
    +#define	APLOG_EMERG	0	/* system is unusable */
    +#define	APLOG_ALERT	1	/* action must be taken immediately */
    +#define	APLOG_CRIT	2	/* critical conditions */
    +#define	APLOG_ERR	3	/* error conditions */
    +#define	APLOG_WARNING	4	/* warning conditions */
    +#define	APLOG_NOTICE	5	/* normal but significant condition */
    +#define	APLOG_INFO	6	/* informational */
    +#define	APLOG_DEBUG	7	/* debug-level messages */
    +
    +#define	APLOG_LEVELMASK	7	/* mask off the level value */
    +
    +#endif
    +
    +#define APLOG_NOERRNO		(APLOG_LEVELMASK + 1)
    +#ifdef WIN32
    +/* Set to indicate that error msg should come from Win32's GetLastError(),
    + * not errno. */
    +#define APLOG_WIN32ERROR	((APLOG_LEVELMASK+1) * 2)
    +#endif
    +
    +#ifndef DEFAULT_LOGLEVEL
    +#define DEFAULT_LOGLEVEL	APLOG_WARNING
    +#endif
    +
    +#define APLOG_MARK	__FILE__,__LINE__
    +
    +void ap_open_logs (server_rec *, pool *p);
    +API_EXPORT(void) ap_log_error(const char *file, int line, int level,
    +			     const server_rec *s, const char *fmt, ...)
    +			    __attribute__((format(printf,5,6)));
    +API_EXPORT(void) ap_error_log2stderr (server_rec *);     
    +
    +void ap_log_pid (pool *p, char *fname);
    +API_EXPORT(void) ap_log_error_old(const char *err, server_rec *s);
    +API_EXPORT(void) ap_log_unixerr(const char *routine, const char *file,
    +			     const char *msg, server_rec *s);
    +API_EXPORT(void) ap_log_printf(const server_rec *s, const char *fmt, ...)
    +			    __attribute__((format(printf,2,3)));
    +API_EXPORT(void) ap_log_reason(const char *reason, const char *fname,
    +			    request_rec *r);
    +
    +typedef struct piped_log {
    +    pool *p;
    +#ifndef NO_RELIABLE_PIPED_LOGS
    +    char *program;
    +    int pid;
    +    int fds[2];
    +#else
    +    FILE *write_f;
    +#endif
    +} piped_log;
    +
    +API_EXPORT(piped_log *) ap_open_piped_log (pool *p, const char *program);
    +API_EXPORT(void) ap_close_piped_log (piped_log *);
    +#ifndef NO_RELIABLE_PIPED_LOGS
    +#define ap_piped_log_read_fd(pl)	((pl)->fds[0])
    +#define ap_piped_log_write_fd(pl)	((pl)->fds[1])
    +#else
    +#define ap_piped_log_read_fd(pl)	(-1)
    +#define ap_piped_log_write_fd(pl)	(fileno((pl)->write_f))
    +#endif
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_LOG_H */
    diff --git a/APACHE_1_3b7/src/include/http_main.h b/APACHE_1_3b7/src/include/http_main.h
    new file mode 100644
    index 0000000000..66e07b9364
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/http_main.h
    @@ -0,0 +1,174 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_HTTP_MAIN_H
    +#define APACHE_HTTP_MAIN_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/*
    + * Routines in http_main.c which other code --- in particular modules ---
    + * may want to call.  Right now, that's limited to timeout handling.
    + * There are two functions which modules can call to trigger a timeout
    + * (with the per-virtual-server timeout duration); these are hard_timeout
    + * and soft_timeout.
    + *
    + * The difference between the two is what happens when the timeout
    + * expires (or earlier than that, if the client connection aborts) ---
    + * a soft_timeout just puts the connection to the client in an
    + * "aborted" state, which will cause http_protocol.c to stop trying to
    + * talk to the client, but otherwise allows the code to continue normally.
    + * hard_timeout(), by contrast, logs the request, and then aborts it
    + * completely --- longjmp()ing out to the accept() loop in http_main.
    + * Any resources tied into the request's resource pool will be cleaned up;
    + * everything that isn't will leak.
    + *
    + * soft_timeout() is recommended as a general rule, because it gives your
    + * code a chance to clean up.  However, hard_timeout() may be the most
    + * convenient way of dealing with timeouts waiting for some external
    + * resource other than the client, if you can live with the restrictions.
    + *
    + * (When a hard timeout is in scope, critical sections can be guarded
    + * with block_alarms() and unblock_alarms() --- these are declared in
    + * alloc.c because they are most often used in conjunction with
    + * routines to allocate something or other, to make sure that the
    + * cleanup does get registered before any alarm is allowed to happen
    + * which might require it to be cleaned up; they * are, however,
    + * implemented in http_main.c).
    + *
    + * NOTE!  It's not "fair" for a hard_timeout to be in scope through calls
    + * across modules.  Your module code really has no idea what other modules may
    + * be present in the server, and they may not take too kindly to having a
    + * longjmp() happen -- it could result in corrupted state.  Heck they may not
    + * even take to kindly to a soft_timeout()... because it can cause EINTR to
    + * happen on pretty much any syscall, and unless all the libraries and modules
    + * in use are known to deal well with EINTR it could cause corruption as well.
    + * But things are likely to do much better with a soft_timeout in scope than a
    + * hard_timeout.
    + * 
    + * A module MAY NOT use a hard_timeout() across * sub_req_lookup_xxx()
    + * functions, or across run_sub_request() functions.  A module SHOULD NOT use a
    + * soft_timeout() in either of these cases, but sometimes there's just no
    + * choice.
    + *
    + * kill_timeout() will disarm either variety of timeout.
    + *
    + * reset_timeout() resets the timeout in progress.
    + */
    +
    +void ap_start_shutdown(void);
    +void ap_start_restart(int);
    +API_EXPORT(void) ap_hard_timeout(char *, request_rec *);
    +void ap_keepalive_timeout(char *, request_rec *);
    +API_EXPORT(void) ap_soft_timeout(char *, request_rec *);
    +API_EXPORT(void) ap_kill_timeout(request_rec *);
    +API_EXPORT(void) ap_reset_timeout(request_rec *);
    +
    +API_EXPORT(void) ap_child_terminate(request_rec *r);
    +API_EXPORT(void) ap_sync_scoreboard_image(void);
    +int ap_update_child_status(int child_num, int status, request_rec *r);
    +void ap_time_process_request(int child_num, int status);
    +unsigned int ap_set_callback_and_alarm(void (*fn) (int), int x);
    +API_EXPORT(int) ap_check_alarm(void);
    +
    +#ifndef NO_OTHER_CHILD
    +/*
    + * register an other_child -- a child which the main loop keeps track of
    + * and knows it is different than the rest of the scoreboard.
    + *
    + * pid is the pid of the child.
    + *
    + * maintenance is a function that is invoked with a reason, the data
    + * pointer passed here, and when appropriate a status result from waitpid().
    + *
    + * write_fd is an fd that is probed for writing by select() if it is ever
    + * unwritable, then maintenance is invoked with reason OC_REASON_UNWRITABLE.
    + * This is useful for log pipe children, to know when they've blocked.  To
    + * disable this feature, use -1 for write_fd.
    + */
    +API_EXPORT(void) ap_register_other_child(int pid,
    +       void (*maintenance) (int reason, void *data, int status), void *data,
    +				      int write_fd);
    +#define OC_REASON_DEATH		0	/* child has died, caller must call
    +					 * unregister still */
    +#define OC_REASON_UNWRITABLE	1	/* write_fd is unwritable */
    +#define OC_REASON_RESTART	2	/* a restart is occuring, perform
    +					 * any necessary cleanup (including
    +					 * sending a special signal to child)
    +					 */
    +#define OC_REASON_UNREGISTER	3	/* unregister has been called, do
    +					 * whatever is necessary (including
    +					 * kill the child) */
    +#define OC_REASON_LOST		4	/* somehow the child exited without
    +					 * us knowing ... buggy os? */
    +
    +/*
    + * unregister an other_child.  Note that the data pointer is used here, and
    + * is assumed to be unique per other_child.  This is because the pid and
    + * write_fd are possibly killed off separately.
    + */
    +API_EXPORT(void) ap_unregister_other_child(void *data);
    +
    +#endif
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_MAIN_H */
    diff --git a/APACHE_1_3b7/src/include/http_protocol.h b/APACHE_1_3b7/src/include/http_protocol.h
    new file mode 100644
    index 0000000000..c08ebc711b
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/http_protocol.h
    @@ -0,0 +1,216 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_HTTP_PROTOCOL_H
    +#define APACHE_HTTP_PROTOCOL_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/*
    + * Prototypes for routines which either talk directly back to the user,
    + * or control the ones that eventually do.
    + */
    +
    +/* Read a request and fill in the fields. */
    +
    +request_rec *ap_read_request(conn_rec *c);
    +
    +/* Send a single HTTP header field */
    +
    +API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r, const char *fieldname,
    +                      const char *fieldval);
    +
    +/* Send the minimal part of an HTTP response header... but modules should be
    + * very careful about using this, and should prefer ap_send_http_header().
    + * Much of the HTTP/1.1 implementation correctness depends on code in
    + * ap_send_http_header().
    + */
    +API_EXPORT(void) ap_basic_http_header(request_rec *r);
    +
    +/* Send the Status-Line and header fields for HTTP response */
    +
    +API_EXPORT(void) ap_send_http_header(request_rec *l);
    +
    +/* Send the response to special method requests */
    +
    +int ap_send_http_trace(request_rec *r);
    +int ap_send_http_options(request_rec *r);
    +
    +/* Finish up stuff after a request */
    +
    +void ap_finalize_request_protocol(request_rec *r);
    +
    +/* Send error back to client... last arg indicates error status in case
    + * we get an error in the process of trying to deal with an ErrorDocument
    + * to handle some other error.  In that case, we print the default report
    + * for the first thing that went wrong, and more briefly report on the
    + * problem with the ErrorDocument.
    + */
    +
    +void ap_send_error_response(request_rec *r, int recursive_error);
    +
    +/* Set last modified header line from the lastmod date of the associated file.
    + * Also, set content length.
    + *
    + * May return an error status, typically USE_LOCAL_COPY (that when the
    + * permit_cache argument is set to one).
    + */
    +
    +API_EXPORT(int) ap_set_content_length(request_rec *r, long length);
    +API_EXPORT(int) ap_set_keepalive(request_rec *r);
    +API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime);
    +API_EXPORT(void) ap_set_etag(request_rec *r);
    +API_EXPORT(void) ap_set_last_modified(request_rec *r);
    +API_EXPORT(int) ap_meets_conditions(request_rec *r);
    +
    +/* Other ways to send stuff at the client.  All of these keep track
    + * of bytes_sent automatically.  This indirection is intended to make
    + * it a little more painless to slide things like HTTP-NG packetization
    + * underneath the main body of the code later.  In the meantime, it lets
    + * us centralize a bit of accounting (bytes_sent).
    + *
    + * These also return the number of bytes written by the call.
    + * They should only be called with a timeout registered, for obvious reaasons.
    + * (Ditto the send_header stuff).
    + */
    +
    +API_EXPORT(long) ap_send_fd(FILE *f, request_rec *r);
    +API_EXPORT(long) ap_send_fd_length(FILE *f, request_rec *r, long length);
    +
    +API_EXPORT(long) ap_send_fb(BUFF *f, request_rec *r);
    +API_EXPORT(long) ap_send_fb_length(BUFF *f, request_rec *r, long length);
    +
    +API_EXPORT(size_t) ap_send_mmap(void *mm, request_rec *r, size_t offset,
    +                             size_t length);
    +
    +/* Hmmm... could macrofy these for now, and maybe forever, though the
    + * definitions of the macros would get a whole lot hairier.
    + */
    +
    +API_EXPORT(int) ap_rputc(int c, request_rec *r);
    +API_EXPORT(int) ap_rputs(const char *str, request_rec *r);
    +API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r);
    +API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...);
    +API_EXPORT_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt,...)
    +				__attribute__((format(printf,2,3)));
    +API_EXPORT(int) ap_rflush(request_rec *r);
    +
    +/*
    + * Index used in custom_responses array for a specific error code
    + * (only use outside protocol.c is in getting them configured).
    + */
    +
    +API_EXPORT(int) ap_index_of_response(int status);
    +
    +/* Reading a block of data from the client connection (e.g., POST arg) */
    +
    +API_EXPORT(int) ap_setup_client_block(request_rec *r, int read_policy);
    +API_EXPORT(int) ap_should_client_block(request_rec *r);
    +API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz);
    +API_EXPORT(int) ap_discard_request_body(request_rec *r);
    +
    +/* Sending a byterange */
    +
    +API_EXPORT(int) ap_set_byterange(request_rec *r);
    +API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length);
    +
    +/* Support for the Basic authentication protocol.  Note that there's
    + * nothing that prevents these from being in mod_auth.c, except that other
    + * modules which wanted to provide their own variants on finding users and
    + * passwords for Basic auth (a fairly common request) would then require
    + * mod_auth to be loaded or they wouldn't work.
    + *
    + * get_basic_auth_pw returns 0 (OK) if it set the 'pw' argument (and assured
    + * a correct value in r->connection->user); otherwise it returns an error
    + * code, either SERVER_ERROR if things are really confused, AUTH_REQUIRED
    + * if no authentication at all seemed to be in use, or DECLINED if there
    + * was authentication but it wasn't Basic (in which case, the caller should
    + * presumably decline as well).
    + *
    + * note_basic_auth_failure arranges for the right stuff to be scribbled on
    + * the HTTP return so that the client knows how to authenticate itself the
    + * next time. As does note_digest_auth_failure for Digest auth.
    + *
    + * note_auth_failure does the same thing, but will call the correct one
    + * based on the authentication type in use.
    + *
    + */
    +
    +API_EXPORT(void) ap_note_auth_failure(request_rec *r);
    +API_EXPORT(void) ap_note_basic_auth_failure(request_rec *r);
    +API_EXPORT(void) ap_note_digest_auth_failure(request_rec *r);
    +API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, char **pw);
    +
    +/*
    + * Setting up the protocol fields for subsidiary requests...
    + * Also, a wrapup function to keep the internal accounting straight.
    + */
    +
    +void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r);
    +void ap_finalize_sub_req_protocol(request_rec *sub_r);
    +
    +/* This is also useful for putting sub_reqs and internal_redirects together */
    +
    +CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_PROTOCOL_H */
    diff --git a/APACHE_1_3b7/src/include/http_request.h b/APACHE_1_3b7/src/include/http_request.h
    new file mode 100644
    index 0000000000..ff38df317b
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/http_request.h
    @@ -0,0 +1,114 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_HTTP_REQUEST_H
    +#define APACHE_HTTP_REQUEST_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/* http_request.c is the code which handles the main line of request
    + * processing, once a request has been read in (finding the right per-
    + * directory configuration, building it if necessary, and calling all
    + * the module dispatch functions in the right order).
    + *
    + * The pieces here which are public to the modules, allow them to learn
    + * how the server would handle some other file or URI, or perhaps even
    + * direct the server to serve that other file instead of the one the
    + * client requested directly.
    + *
    + * There are two ways to do that.  The first is the sub_request mechanism,
    + * which handles looking up files and URIs as adjuncts to some other
    + * request (e.g., directory entries for multiviews and directory listings);
    + * the lookup functions stop short of actually running the request, but
    + * (e.g., for includes), a module may call for the request to be run
    + * by calling run_sub_req.  The space allocated to create sub_reqs can be
    + * reclaimed by calling destroy_sub_req --- be sure to copy anything you care
    + * about which was allocated in its pool elsewhere before doing this.
    + */
    +
    +API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
    +                                             const request_rec *r);
    +API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file,
    +                                              const request_rec *r);
    +API_EXPORT(int) ap_run_sub_req(request_rec *r);
    +API_EXPORT(void) ap_destroy_sub_req(request_rec *r);
    +
    +/*
    + * Then there's the case that you want some other request to be served
    + * as the top-level request INSTEAD of what the client requested directly.
    + * If so, call this from a handler, and then immediately return OK.
    + */
    +
    +API_EXPORT(void) ap_internal_redirect(const char *new_uri, request_rec *);
    +API_EXPORT(void) ap_internal_redirect_handler(const char *new_uri, request_rec *);
    +API_EXPORT(int) ap_some_auth_required(request_rec *r);
    +API_EXPORT(int) ap_is_initial_req(request_rec *r);
    +API_EXPORT(time_t) ap_update_mtime(request_rec *r, time_t dependency_mtime);
    +
    +#ifdef CORE_PRIVATE
    +/* Function called by main.c to handle first-level request */
    +void ap_process_request(request_rec *);
    +void ap_die(int type, request_rec *r);
    +#endif
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_REQUEST_H */
    diff --git a/APACHE_1_3b7/src/include/http_vhost.h b/APACHE_1_3b7/src/include/http_vhost.h
    new file mode 100644
    index 0000000000..7b23381ed7
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/http_vhost.h
    @@ -0,0 +1,95 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_HTTP_VHOST_H
    +#define APACHE_HTTP_VHOST_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/* called before any config is read */
    +void ap_init_vhost_config(pool *p);
    +
    +/* called after the config has been read */
    +void ap_fini_vhost_config(pool *p, server_rec *main_server);
    +
    +/* handle addresses in <VirtualHost> statement */
    +const char *ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s);
    +
    +/* handle NameVirtualHost directive */
    +const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg);
    +
    +/* given an ip address only, give our best guess as to what vhost it is */
    +void ap_update_vhost_given_ip(conn_rec *conn);
    +
    +/* The above is never enough, and this is always called after the headers
    + * have been read.  It may change r->server.
    + */
    +void ap_update_vhost_from_headers(request_rec *r);
    +
    +/* return 1 if the host:port matches any of the aliases of r->server
    + * return 0 otherwise
    + */
    +API_EXPORT(int) ap_matches_request_vhost(request_rec *r, const char *host,
    +    unsigned port);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_VHOST_H */
    diff --git a/APACHE_1_3b7/src/include/httpd.h b/APACHE_1_3b7/src/include/httpd.h
    new file mode 100644
    index 0000000000..ca58e2de17
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/httpd.h
    @@ -0,0 +1,1042 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_HTTPD_H
    +#define APACHE_HTTPD_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/*
    + * httpd.h: header for simple (ha! not anymore) http daemon
    + */
    +
    +/* Headers in which EVERYONE has an interest... */
    +
    +#include "conf.h"
    +#include "alloc.h"
    +#include "buff.h"
    +#include "ap.h"
    +
    +/* ----------------------------- config dir ------------------------------ */
    +
    +/* Define this to be the default server home dir. Most things later in this
    + * file with a relative pathname will have this added.
    + */
    +#ifndef HTTPD_ROOT
    +#ifdef __EMX__
    +/* Set default for OS/2 file system */
    +#define HTTPD_ROOT "/os2httpd"
    +#elif defined(WIN32)
    +/* Set default for Windows file system */
    +#define HTTPD_ROOT "/apache"
    +#else
    +#define HTTPD_ROOT "/usr/local/apache"
    +#endif
    +#endif /* HTTPD_ROOT */
    +
    +/* Default location of documents.  Can be overridden by the DocumentRoot
    + * directive.
    + */
    +#ifndef DOCUMENT_LOCATION
    +#ifdef __EMX__
    +/* Set default for OS/2 file system */
    +#define DOCUMENT_LOCATION  HTTPD_ROOT "/docs"
    +#else
    +#define DOCUMENT_LOCATION  HTTPD_ROOT "/htdocs"
    +#endif
    +#endif /* DOCUMENT_LOCATION */
    +
    +/* Max. number of dynamically loaded modules */
    +#ifndef DYNAMIC_MODULE_LIMIT
    +#define DYNAMIC_MODULE_LIMIT 64
    +#endif
    +
    +/* Default administrator's address */
    +#define DEFAULT_ADMIN "[no address given]"
    +
    +/* 
    + * --------- You shouldn't have to edit anything below this line ----------
    + *
    + * Any modifications to any defaults not defined above should be done in the 
    + * respective config. file. 
    + *
    + */
    +
    +
    +/* -- Internal representation for a HTTP protocol number, e.g., HTTP/1.1 -- */
    +
    +#define HTTP_VERSION(major,minor) (1000*(major)+(minor))
    +
    +
    +/* -------------- Port number for server running standalone --------------- */
    +
    +#define DEFAULT_HTTP_PORT	80
    +#define DEFAULT_HTTPS_PORT	443
    +#define is_default_port(port,r)	((port) == default_port(r))
    +#define http_method(r)	"http"
    +#define	default_port(r)	DEFAULT_HTTP_PORT
    +
    +/* --------- Default user name and group name running standalone ---------- */
    +/* --- These may be specified as numbers by placing a # before a number --- */
    +
    +#ifndef DEFAULT_USER
    +#define DEFAULT_USER "#-1"
    +#endif
    +#ifndef DEFAULT_GROUP
    +#define DEFAULT_GROUP "#-1"
    +#endif
    +
    +/* The name of the log files */
    +#ifndef DEFAULT_XFERLOG
    +#ifdef __EMX__
    +/* Set default for OS/2 file system */
    +#define DEFAULT_XFERLOG "logs/access.log"
    +#else
    +#define DEFAULT_XFERLOG "logs/access_log"
    +#endif
    +#endif /* DEFAULT_XFERLOG */
    +
    +#ifndef DEFAULT_ERRORLOG
    +#ifdef __EMX__
    +/* Set default for OS/2 file system */
    +#define DEFAULT_ERRORLOG "logs/error.log"
    +#else
    +#define DEFAULT_ERRORLOG "logs/error_log"
    +#endif
    +#endif /* DEFAULT_ERRORLOG */
    +
    +#ifndef DEFAULT_PIDLOG
    +#define DEFAULT_PIDLOG "logs/httpd.pid"
    +#endif
    +#ifndef DEFAULT_SCOREBOARD
    +#define DEFAULT_SCOREBOARD "logs/apache_runtime_status"
    +#endif
    +#ifndef DEFAULT_LOCKFILE
    +#define DEFAULT_LOCKFILE "logs/accept.lock"
    +#endif
    +
    +/* Define this to be what your HTML directory content files are called */
    +#ifndef DEFAULT_INDEX
    +#define DEFAULT_INDEX "index.html"
    +#endif
    +
    +/* Define this to 1 if you want fancy indexing, 0 otherwise */
    +#ifndef DEFAULT_INDEXING
    +#define DEFAULT_INDEXING 0
    +#endif
    +
    +/* Define this to be what type you'd like returned for files with unknown */
    +/* suffixes.  MUST be all lower case. */
    +#ifndef DEFAULT_CONTENT_TYPE
    +#define DEFAULT_CONTENT_TYPE "text/plain"
    +#endif
    +
    +/* Define this to be what your per-directory security files are called */
    +#ifndef DEFAULT_ACCESS_FNAME
    +#ifdef __EMX__
    +/* Set default for OS/2 file system */
    +#define DEFAULT_ACCESS_FNAME "htaccess"
    +#else
    +#define DEFAULT_ACCESS_FNAME ".htaccess"
    +#endif
    +#endif /* DEFAULT_ACCESS_FNAME */
    +
    +/* The name of the server config file */
    +#ifndef SERVER_CONFIG_FILE
    +#define SERVER_CONFIG_FILE "conf/httpd.conf"
    +#endif
    +
    +/* The name of the document config file */
    +#ifndef RESOURCE_CONFIG_FILE
    +#define RESOURCE_CONFIG_FILE "conf/srm.conf"
    +#endif
    +
    +/* The name of the MIME types file */
    +#ifndef TYPES_CONFIG_FILE
    +#define TYPES_CONFIG_FILE "conf/mime.types"
    +#endif
    +
    +/* The name of the access file */
    +#ifndef ACCESS_CONFIG_FILE
    +#define ACCESS_CONFIG_FILE "conf/access.conf"
    +#endif
    +
    +/* Whether we should enable rfc1413 identity checking */
    +#ifndef DEFAULT_RFC1413
    +#define DEFAULT_RFC1413 0
    +#endif
    +/* The default directory in user's home dir */
    +#ifndef DEFAULT_USER_DIR
    +#define DEFAULT_USER_DIR "public_html"
    +#endif
    +
    +/* The default path for CGI scripts if none is currently set */
    +#ifndef DEFAULT_PATH
    +#define DEFAULT_PATH "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
    +#endif
    +
    +/* The path to the Bourne shell, for parsed docs */
    +#ifndef SHELL_PATH
    +#if defined(__EMX__) || defined(WIN32)
    +/* Set default for OS/2 file system */
    +#define SHELL_PATH "CMD.EXE"
    +#else
    +#define SHELL_PATH "/bin/sh"
    +#endif
    +#endif /* SHELL_PATH */
    +
    +/* The path to the suExec wrapper, can be overridden in Configuration */
    +#ifndef SUEXEC_BIN
    +#define SUEXEC_BIN  HTTPD_ROOT "/sbin/suexec"
    +#endif
    +
    +/* The default string lengths */
    +#define MAX_STRING_LEN HUGE_STRING_LEN
    +#define HUGE_STRING_LEN 8192
    +
    +/* The timeout for waiting for messages */
    +#ifndef DEFAULT_TIMEOUT
    +#define DEFAULT_TIMEOUT 300
    +#endif
    +
    +/* The timeout for waiting for keepalive timeout until next request */
    +#ifndef DEFAULT_KEEPALIVE_TIMEOUT
    +#define DEFAULT_KEEPALIVE_TIMEOUT 15
    +#endif
    +
    +/* The number of requests to entertain per connection */
    +#ifndef DEFAULT_KEEPALIVE
    +#define DEFAULT_KEEPALIVE 100
    +#endif
    +
    +/* The size of the server's internal read-write buffers */
    +#define IOBUFSIZE 8192
    +
    +/* Number of servers to spawn off by default --- also, if fewer than
    + * this free when the caretaker checks, it will spawn more.
    + */
    +#ifndef DEFAULT_START_DAEMON
    +#define DEFAULT_START_DAEMON 5
    +#endif
    +
    +/* Maximum number of *free* server processes --- more than this, and
    + * they will die off.
    + */
    +
    +#ifndef DEFAULT_MAX_FREE_DAEMON
    +#define DEFAULT_MAX_FREE_DAEMON 10
    +#endif
    +
    +/* Minimum --- fewer than this, and more will be created */
    +
    +#ifndef DEFAULT_MIN_FREE_DAEMON
    +#define DEFAULT_MIN_FREE_DAEMON 5
    +#endif
    +
    +/* Limit on the total --- clients will be locked out if more servers than
    + * this are needed.  It is intended solely to keep the server from crashing
    + * when things get out of hand.
    + *
    + * We keep a hard maximum number of servers, for two reasons --- first off,
    + * in case something goes seriously wrong, we want to stop the fork bomb
    + * short of actually crashing the machine we're running on by filling some
    + * kernel table.  Secondly, it keeps the size of the scoreboard file small
    + * enough that we can read the whole thing without worrying too much about
    + * the overhead.
    + */
    +#ifndef HARD_SERVER_LIMIT
    +#define HARD_SERVER_LIMIT 256
    +#endif
    +
    +/*
    + * Special Apache error codes. These are basically used
    + *  in http_main.c so we can keep track of various errors.
    + *
    + *   APEXIT_OK:
    + *     A normal exit
    + *   APEXIT_INIT:
    + *     A fatal error arising during the server's init sequence
    + *   APEXIT_CHILDINIT:
    + *     The child died during it's init sequence
    + *   APEXIT_CHILDFATAL:
    + *     A fatal error, resulting in the whole server aborting.
    + *     If a child exits with this error, the parent process
    + *     considers this a server-wide fatal error and aborts.
    + *                 
    + */
    +#define APEXIT_OK		0x0
    +#define APEXIT_INIT		0x2
    +#define APEXIT_CHILDINIT	0x3
    +#define APEXIT_CHILDFATAL	0xf
    +
    +/*
    + * (Unix, OS/2 only)
    + * Interval, in microseconds, between scoreboard maintenance.  During
    + * each scoreboard maintenance cycle the parent decides if it needs to
    + * spawn a new child (to meet MinSpareServers requirements), or kill off
    + * a child (to meet MaxSpareServers requirements).  It will only spawn or
    + * kill one child per cycle.  Setting this too low will chew cpu.  The
    + * default is probably sufficient for everyone.  But some people may want
    + * to raise this on servers which aren't dedicated to httpd and where they
    + * don't like the httpd waking up each second to see what's going on.
    + */
    +#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
    +#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
    +#endif
    +
    +/* Number of requests to try to handle in a single process.  If <= 0,
    + * the children don't die off.  That's the default here, since I'm still
    + * interested in finding and stanching leaks.
    + */
    +
    +#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
    +#define DEFAULT_MAX_REQUESTS_PER_CHILD 0
    +#endif
    +
    +#ifndef DEFAULT_THREADS_PER_CHILD
    +#define DEFAULT_THREADS_PER_CHILD 50
    +#endif
    +#ifndef DEFAULT_EXCESS_REQUESTS_PER_CHILD
    +#define DEFAULT_EXCESS_REQUESTS_PER_CHILD 0
    +#endif
    +
    +/* The maximum length of the queue of pending connections, as defined
    + * by listen(2).  Under some systems, it should be increased if you
    + * are experiencing a heavy TCP SYN flood attack.
    + *
    + * It defaults to 511 instead of 512 because some systems store it 
    + * as an 8-bit datatype; 512 truncated to 8-bits is 0, while 511 is 
    + * 255 when truncated.
    + */
    +
    +#ifndef DEFAULT_LISTENBACKLOG
    +#define DEFAULT_LISTENBACKLOG 511
    +#endif
    +
    +/*
    + * The below defines the base string of the Server: header. Additional
    + * tokens can be added via the ap_add_version_component() API call.
    + *
    + * The tokens are listed in order of their significance for identifying the
    + * application.
    + *
    + * "Product tokens should be short and to the point -- use of them for 
    + * advertizing or other non-essential information is explicitly forbidden."
    + *
    + * Example: "Apache/1.1.0 MrWidget/0.1-alpha" 
    + */
    +
    +#define SERVER_BASEVERSION "Apache/1.3b7"	/* SEE COMMENTS ABOVE */
    +#define SERVER_VERSION  SERVER_BASEVERSION
    +enum server_token_type {
    +    SrvTk_MIN,		/* eg: Apache/1.3.0 */
    +    SrvTk_OS,		/* eg: Apache/1.3.0 (UNIX) */
    +    SrvTk_FULL		/* eg: Apache/1.3.0 (UNIX) PHP/3.0 FooBar/1.2b */
    +};
    +
    +API_EXPORT(const char *) ap_get_server_version(void);
    +API_EXPORT(void) ap_add_version_component(const char *component);
    +API_EXPORT(const char *) ap_get_server_built(void);
    +
    +/* Numeric release version identifier: major minor bugfix betaseq
    + * Always increases along the same track as the source branch.
    + */
    +#define APACHE_RELEASE 1030007
    +
    +#define SERVER_PROTOCOL "HTTP/1.1"
    +#ifndef SERVER_SUPPORT
    +#define SERVER_SUPPORT "http://www.apache.org/"
    +#endif
    +
    +#define DECLINED -1		/* Module declines to handle */
    +#define DONE -2			/* Module has served the response completely 
    +				 *  - it's safe to die() with no more output
    +				 */
    +#define OK 0			/* Module has handled this stage. */
    +
    +
    +/* ----------------------- HTTP Status Codes  ------------------------- */
    +
    +#define RESPONSE_CODES 38
    +
    +#define HTTP_CONTINUE                      100
    +#define HTTP_SWITCHING_PROTOCOLS           101
    +#define HTTP_OK                            200
    +#define HTTP_CREATED                       201
    +#define HTTP_ACCEPTED                      202
    +#define HTTP_NON_AUTHORITATIVE             203
    +#define HTTP_NO_CONTENT                    204
    +#define HTTP_RESET_CONTENT                 205
    +#define HTTP_PARTIAL_CONTENT               206
    +#define HTTP_MULTIPLE_CHOICES              300
    +#define HTTP_MOVED_PERMANENTLY             301
    +#define HTTP_MOVED_TEMPORARILY             302
    +#define HTTP_SEE_OTHER                     303
    +#define HTTP_NOT_MODIFIED                  304
    +#define HTTP_USE_PROXY                     305
    +#define HTTP_BAD_REQUEST                   400
    +#define HTTP_UNAUTHORIZED                  401
    +#define HTTP_PAYMENT_REQUIRED              402
    +#define HTTP_FORBIDDEN                     403
    +#define HTTP_NOT_FOUND                     404
    +#define HTTP_METHOD_NOT_ALLOWED            405
    +#define HTTP_NOT_ACCEPTABLE                406
    +#define HTTP_PROXY_AUTHENTICATION_REQUIRED 407
    +#define HTTP_REQUEST_TIME_OUT              408
    +#define HTTP_CONFLICT                      409
    +#define HTTP_GONE                          410
    +#define HTTP_LENGTH_REQUIRED               411
    +#define HTTP_PRECONDITION_FAILED           412
    +#define HTTP_REQUEST_ENTITY_TOO_LARGE      413
    +#define HTTP_REQUEST_URI_TOO_LARGE         414
    +#define HTTP_UNSUPPORTED_MEDIA_TYPE        415
    +#define HTTP_INTERNAL_SERVER_ERROR         500
    +#define HTTP_NOT_IMPLEMENTED               501
    +#define HTTP_BAD_GATEWAY                   502
    +#define HTTP_SERVICE_UNAVAILABLE           503
    +#define HTTP_GATEWAY_TIME_OUT              504
    +#define HTTP_VERSION_NOT_SUPPORTED         505
    +#define HTTP_VARIANT_ALSO_VARIES           506
    +
    +#define DOCUMENT_FOLLOWS    HTTP_OK
    +#define PARTIAL_CONTENT     HTTP_PARTIAL_CONTENT
    +#define MULTIPLE_CHOICES    HTTP_MULTIPLE_CHOICES
    +#define MOVED               HTTP_MOVED_PERMANENTLY
    +#define REDIRECT            HTTP_MOVED_TEMPORARILY
    +#define USE_LOCAL_COPY      HTTP_NOT_MODIFIED
    +#define BAD_REQUEST         HTTP_BAD_REQUEST
    +#define AUTH_REQUIRED       HTTP_UNAUTHORIZED
    +#define FORBIDDEN           HTTP_FORBIDDEN
    +#define NOT_FOUND           HTTP_NOT_FOUND
    +#define METHOD_NOT_ALLOWED  HTTP_METHOD_NOT_ALLOWED
    +#define NOT_ACCEPTABLE      HTTP_NOT_ACCEPTABLE
    +#define LENGTH_REQUIRED     HTTP_LENGTH_REQUIRED
    +#define PRECONDITION_FAILED HTTP_PRECONDITION_FAILED
    +#define SERVER_ERROR        HTTP_INTERNAL_SERVER_ERROR
    +#define NOT_IMPLEMENTED     HTTP_NOT_IMPLEMENTED
    +#define BAD_GATEWAY         HTTP_BAD_GATEWAY
    +#define VARIANT_ALSO_VARIES HTTP_VARIANT_ALSO_VARIES
    +
    +#define is_HTTP_INFO(x)         (((x) >= 100)&&((x) < 200))
    +#define is_HTTP_SUCCESS(x)      (((x) >= 200)&&((x) < 300))
    +#define is_HTTP_REDIRECT(x)     (((x) >= 300)&&((x) < 400))
    +#define is_HTTP_ERROR(x)        (((x) >= 400)&&((x) < 600))
    +#define is_HTTP_CLIENT_ERROR(x) (((x) >= 400)&&((x) < 500))
    +#define is_HTTP_SERVER_ERROR(x) (((x) >= 500)&&((x) < 600))
    +
    +#define status_drops_connection(x) (((x) == HTTP_BAD_REQUEST)           || \
    +                                    ((x) == HTTP_REQUEST_TIME_OUT)      || \
    +                                    ((x) == HTTP_LENGTH_REQUIRED)       || \
    +                                    ((x) == HTTP_REQUEST_ENTITY_TOO_LARGE) || \
    +                                    ((x) == HTTP_REQUEST_URI_TOO_LARGE) || \
    +                                    ((x) == HTTP_INTERNAL_SERVER_ERROR) || \
    +                                    ((x) == HTTP_SERVICE_UNAVAILABLE) || \
    +				    ((x) == HTTP_NOT_IMPLEMENTED))
    +
    +
    +#define METHODS 8
    +#define M_GET 0
    +#define M_PUT 1
    +#define M_POST 2
    +#define M_DELETE 3
    +#define M_CONNECT 4
    +#define M_OPTIONS 5
    +#define M_TRACE 6
    +#define M_INVALID 7
    +
    +#define CGI_MAGIC_TYPE "application/x-httpd-cgi"
    +#define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html"
    +#define INCLUDES_MAGIC_TYPE3 "text/x-server-parsed-html3"
    +#ifdef CHARSET_EBCDIC
    +#define ASCIITEXT_MAGIC_TYPE_PREFIX "text/x-ascii-" /* Text files whose content-type starts with this are passed thru unconverted */
    +#endif /*CHARSET_EBCDIC*/
    +#define MAP_FILE_MAGIC_TYPE "application/x-type-map"
    +#define ASIS_MAGIC_TYPE "httpd/send-as-is"
    +#define DIR_MAGIC_TYPE "httpd/unix-directory"
    +#define STATUS_MAGIC_TYPE "application/x-httpd-status"
    +
    +/* Just in case your linefeed isn't the one the other end is expecting. */
    +#ifndef CHARSET_EBCDIC
    +#define LF 10
    +#define CR 13
    +#else /* CHARSET_EBCDIC */
    +#include "ebcdic.h"
    +/* OSD_POSIX uses the EBCDIC charset. The transition ASCII->EBCDIC is done in
    + * the buff package (bread/bputs/bwrite), so everywhere else, we use
    + * "native EBCDIC" CR and NL characters. These are therefore defined as
    + * '\r' and '\n'.
    + * NB: this is not the whole truth - sometimes \015 and \012 are contained
    + * in literal (EBCDIC!) strings, so these are not converted but passed.
    + */
    +#define CR '\r'
    +#define LF '\n'
    +#endif /* CHARSET_EBCDIC */
    +
    +/* Possible values for request_rec.read_body (set by handling module):
    + *    REQUEST_NO_BODY          Send 413 error if message has any body
    + *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
    + *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
    + *    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
    + */
    +#define REQUEST_NO_BODY          0
    +#define REQUEST_CHUNKED_ERROR    1
    +#define REQUEST_CHUNKED_DECHUNK  2
    +#define REQUEST_CHUNKED_PASS     3
    +
    +/* Things which may vary per file-lookup WITHIN a request ---
    + * e.g., state of MIME config.  Basically, the name of an object, info
    + * about the object, and any other info we may ahve which may need to
    + * change as we go poking around looking for it (e.g., overridden by
    + * .htaccess files).
    + *
    + * Note how the default state of almost all these things is properly
    + * zero, so that allocating it with pcalloc does the right thing without
    + * a whole lot of hairy initialization... so long as we are willing to
    + * make the (fairly) portable assumption that the bit pattern of a NULL
    + * pointer is, in fact, zero.
    + */
    +
    +/* This represents the result of calling htaccess; these are cached for
    + * each request.
    + */
    +struct htaccess_result {
    +    char *dir;			/* the directory to which this applies */
    +    int override;		/* the overrides allowed for the .htaccess file */
    +    void *htaccess;		/* the configuration directives */
    +/* the next one, or NULL if no more; N.B. never change this */
    +    const struct htaccess_result *next;
    +};
    +
    +typedef struct conn_rec conn_rec;
    +typedef struct server_rec server_rec;
    +typedef struct request_rec request_rec;
    +typedef struct listen_rec listen_rec;
    +
    +#include "util_uri.h"
    +
    +struct request_rec {
    +
    +    ap_pool *pool;
    +    conn_rec *connection;
    +    server_rec *server;
    +
    +    request_rec *next;		/* If we wind up getting redirected,
    +				 * pointer to the request we redirected to.
    +				 */
    +    request_rec *prev;		/* If this is an internal redirect,
    +				 * pointer to where we redirected *from*.
    +				 */
    +
    +    request_rec *main;		/* If this is a sub_request (see request.h) 
    +				 * pointer back to the main request.
    +				 */
    +
    +    /* Info about the request itself... we begin with stuff that only
    +     * protocol.c should ever touch...
    +     */
    +
    +    char *the_request;		/* First line of request, so we can log it */
    +    int assbackwards;		/* HTTP/0.9, "simple" request */
    +    int proxyreq;		/* A proxy request (calculated during
    +				 * post_read_request or translate_name) */
    +    int header_only;		/* HEAD request, as opposed to GET */
    +    char *protocol;		/* Protocol, as given to us, or HTTP/0.9 */
    +    int proto_num;		/* Number version of protocol; 1.1 = 1001 */
    +    char *hostname;		/* Host, as set by full URI or Host: */
    +
    +    time_t request_time;	/* When the request started */
    +
    +    char *status_line;		/* Status line, if set by script */
    +    int status;			/* In any case */
    +
    +    /* Request method, two ways; also, protocol, etc..  Outside of protocol.c,
    +     * look, but don't touch.
    +     */
    +
    +    char *method;		/* GET, HEAD, POST, etc. */
    +    int method_number;		/* M_GET, M_POST, etc. */
    +
    +    /*
    +	allowed is a bitvector of the allowed methods.
    +
    +	A handler must ensure that the request method is one that
    +	it is capable of handling.  Generally modules should DECLINE
    +	any request methods they do not handle.  Prior to aborting the
    +	handler like this the handler should set r->allowed to the list
    +	of methods that it is willing to handle.  This bitvector is used
    +	to construct the "Allow:" header required for OPTIONS requests,
    +	and METHOD_NOT_ALLOWED and NOT_IMPLEMENTED status codes.
    +
    +	Since the default_handler deals with OPTIONS, all modules can
    +	usually decline to deal with OPTIONS.  TRACE is always allowed,
    +	modules don't need to set it explicitly.
    +
    +	Since the default_handler will always handle a GET, a
    +	module which does *not* implement GET should probably return
    +	METHOD_NOT_ALLOWED.  Unfortunately this means that a Script GET
    +	handler can't be installed by mod_actions.
    +    */
    +    int allowed;		/* Allowed methods - for 405, OPTIONS, etc */
    +
    +    int sent_bodyct;		/* byte count in stream is for body */
    +    long bytes_sent;		/* body byte count, for easy access */
    +    time_t mtime;		/* Time the resource was last modified */
    +
    +    /* HTTP/1.1 connection-level features */
    +
    +    int chunked;		/* sending chunked transfer-coding */
    +    int byterange;		/* number of byte ranges */
    +    char *boundary;		/* multipart/byteranges boundary */
    +    char *range;		/* The Range: header */
    +    long clength;		/* The "real" content length */
    +
    +    long remaining;		/* bytes left to read */
    +    long read_length;		/* bytes that have been read */
    +    int read_body;		/* how the request body should be read */
    +    int read_chunked;		/* reading chunked transfer-coding */
    +
    +    /* MIME header environments, in and out.  Also, an array containing
    +     * environment variables to be passed to subprocesses, so people can
    +     * write modules to add to that environment.
    +     *
    +     * The difference between headers_out and err_headers_out is that the
    +     * latter are printed even on error, and persist across internal redirects
    +     * (so the headers printed for ErrorDocument handlers will have them).
    +     *
    +     * The 'notes' table is for notes from one module to another, with no
    +     * other set purpose in mind...
    +     */
    +
    +    table *headers_in;
    +    table *headers_out;
    +    table *err_headers_out;
    +    table *subprocess_env;
    +    table *notes;
    +
    +    /* content_type, handler, content_encoding, content_language, and all
    +     * content_languages MUST be lowercased strings.  They may be pointers
    +     * to static strings; they should not be modified in place.
    +     */
    +    char *content_type;		/* Break these out --- we dispatch on 'em */
    +    char *handler;		/* What we *really* dispatch on           */
    +
    +    char *content_encoding;
    +    char *content_language;	/* for back-compat. only -- do not use */
    +    array_header *content_languages;	/* array of (char*) */
    +
    +    int no_cache;
    +    int no_local_copy;
    +
    +    /* What object is being requested (either directly, or via include
    +     * or content-negotiation mapping).
    +     */
    +
    +    char *unparsed_uri;		/* the uri without any parsing performed */
    +    char *uri;			/* the path portion of the URI */
    +    char *filename;
    +    char *path_info;
    +    char *args;			/* QUERY_ARGS, if any */
    +    struct stat finfo;		/* ST_MODE set to zero if no such file */
    +    uri_components parsed_uri;	/* components of uri, dismantled */
    +
    +    /* Various other config info which may change with .htaccess files
    +     * These are config vectors, with one void* pointer for each module
    +     * (the thing pointed to being the module's business).
    +     */
    +
    +    void *per_dir_config;	/* Options set in config files, etc. */
    +    void *request_config;	/* Notes on *this* request */
    +
    +/*
    + * a linked list of the configuration directives in the .htaccess files
    + * accessed by this request.
    + * N.B. always add to the head of the list, _never_ to the end.
    + * that way, a sub request's list can (temporarily) point to a parent's list
    + */
    +    const struct htaccess_result *htaccess;
    +};
    +
    +
    +/* Things which are per connection
    + */
    +
    +struct conn_rec {
    +
    +    ap_pool *pool;
    +    server_rec *server;
    +    server_rec *base_server;	/* Physical vhost this conn come in on */
    +    void *vhost_lookup_data;	/* used by http_vhost.c */
    +
    +    /* Information about the connection itself */
    +
    +    int child_num;		/* The number of the child handling conn_rec */
    +    BUFF *client;		/* Connection to the guy */
    +
    +    /* Who is the client? */
    +
    +    struct sockaddr_in local_addr;	/* local address */
    +    struct sockaddr_in remote_addr;	/* remote address */
    +    char *remote_ip;		/* Client's IP address */
    +    char *remote_host;		/* Client's DNS name, if known.
    +				 * NULL if DNS hasn't been checked,
    +				 * "" if it has and no address was found.
    +				 * N.B. Only access this though
    +				 * get_remote_host() */
    +    char *remote_logname;	/* Only ever set if doing rfc1413 lookups.
    +				 * N.B. Only access this through
    +				 * get_remote_logname() */
    +    char *user;			/* If an authentication check was made,
    +				 * this gets set to the user name.  We assume
    +				 * that there's only one user per connection(!)
    +				 */
    +    char *ap_auth_type;		/* Ditto. */
    +
    +    unsigned aborted:1;		/* Are we still talking? */
    +    signed int keepalive:2;	/* Are we using HTTP Keep-Alive?
    +				 * -1 fatal error, 0 undecided, 1 yes */
    +    unsigned keptalive:1;	/* Did we use HTTP Keep-Alive? */
    +    signed int double_reverse:2;/* have we done double-reverse DNS?
    +				 * -1 yes/failure, 0 not yet, 1 yes/success */
    +    int keepalives;		/* How many times have we used it? */
    +};
    +
    +/* Per-vhost config... */
    +
    +/* The address 255.255.255.255, when used as a virtualhost address,
    + * will become the "default" server when the ip doesn't match other vhosts.
    + */
    +#define DEFAULT_VHOST_ADDR 0xfffffffful
    +
    +typedef struct server_addr_rec server_addr_rec;
    +struct server_addr_rec {
    +    server_addr_rec *next;
    +    struct in_addr host_addr;	/* The bound address, for this server */
    +    unsigned short host_port;	/* The bound port, for this server */
    +    char *virthost;		/* The name given in <VirtualHost> */
    +};
    +
    +struct server_rec {
    +
    +    server_rec *next;
    +
    +    /* description of where the definition came from */
    +    const char *defn_name;
    +    unsigned defn_line_number;
    +
    +    /* Full locations of server config info */
    +
    +    char *srm_confname;
    +    char *access_confname;
    +
    +    /* Contact information */
    +
    +    char *server_admin;
    +    char *server_hostname;
    +    unsigned short port;	/* for redirects, etc. */
    +
    +    /* Log files --- note that transfer log is now in the modules... */
    +
    +    char *error_fname;
    +    FILE *error_log;
    +    int loglevel;
    +
    +    /* Module-specific configuration for server, and defaults... */
    +
    +    int is_virtual;		/* true if this is the virtual server */
    +    void *module_config;	/* Config vector containing pointers to
    +				 * modules' per-server config structures.
    +				 */
    +    void *lookup_defaults;	/* MIME type info, etc., before we start
    +				 * checking per-directory info.
    +				 */
    +    /* Transaction handling */
    +
    +    server_addr_rec *addrs;
    +    int timeout;		/* Timeout, in seconds, before we give up */
    +    int keep_alive_timeout;	/* Seconds we'll wait for another request */
    +    int keep_alive_max;		/* Maximum requests per connection */
    +    int keep_alive;		/* Use persistent connections? */
    +    int send_buffer_size;	/* size of TCP send buffer (in bytes) */
    +
    +    char *path;			/* Pathname for ServerPath */
    +    int pathlen;		/* Length of path */
    +
    +    array_header *names;	/* Normal names for ServerAlias servers */
    +    array_header *wild_names;	/* Wildcarded names for ServerAlias servers */
    +
    +    uid_t server_uid;		/* effective user id when calling exec wrapper */
    +    gid_t server_gid;		/* effective group id when calling exec wrapper */
    +};
    +
    +/* These are more like real hosts than virtual hosts */
    +struct listen_rec {
    +    listen_rec *next;
    +    struct sockaddr_in local_addr;	/* local IP address and port */
    +    int fd;
    +    int used;			/* Only used during restart */
    +/* more stuff here, like which protocol is bound to the port */
    +};
    +
    +/* Prototypes for utilities... util.c.
    + */
    +
    +extern void ap_util_init(void);
    +
    +/* Time */
    +extern API_VAR_EXPORT const char ap_month_snames[12][4];
    +extern API_VAR_EXPORT const char ap_day_snames[7][4];
    +
    +API_EXPORT(struct tm *) ap_get_gmtoff(int *tz);
    +API_EXPORT(char *) ap_get_time(void);
    +API_EXPORT(char *) ap_ht_time(pool *p, time_t t, const char *fmt, int gmt);
    +API_EXPORT(char *) ap_gm_timestr_822(pool *p, time_t t);
    +
    +/* String handling. The *_nc variants allow you to use non-const char **s as
    +   arguments (unfortunately C won't automatically convert a char ** to a const
    +   char **) */
    +
    +API_EXPORT(char *) ap_getword(pool *p, const char **line, char stop);
    +API_EXPORT(char *) ap_getword_nc(pool *p, char **line, char stop);
    +API_EXPORT(char *) ap_getword_white(pool *p, const char **line);
    +API_EXPORT(char *) ap_getword_white_nc(pool *p, char **line);
    +API_EXPORT(char *) ap_getword_nulls(pool *p, const char **line, char stop);
    +API_EXPORT(char *) ap_getword_nulls_nc(pool *p, char **line, char stop);
    +API_EXPORT(char *) ap_getword_conf(pool *p, const char **line);
    +API_EXPORT(char *) ap_getword_conf_nc(pool *p, char **line);
    +
    +API_EXPORT(char *) ap_get_token(pool *p, char **accept_line, int accept_white);
    +API_EXPORT(int) ap_find_token(pool *p, const char *line, const char *tok);
    +API_EXPORT(int) ap_find_last_token(pool *p, const char *line, const char *tok);
    +
    +API_EXPORT(int) ap_is_url(const char *u);
    +API_EXPORT(int) ap_unescape_url(char *url);
    +API_EXPORT(void) ap_no2slash(char *name);
    +API_EXPORT(void) ap_getparents(char *name);
    +API_EXPORT(char *) ap_escape_path_segment(pool *p, const char *s);
    +API_EXPORT(char *) ap_os_escape_path(pool *p, const char *path, int partial);
    +#define escape_uri(ppool,path) ap_os_escape_path(ppool,path,1)
    +API_EXPORT(char *) ap_escape_html(pool *p, const char *s);
    +API_EXPORT(char *) ap_construct_server(pool *p, const char *hostname,
    +				    unsigned port, const request_rec *r);
    +API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *s);
    +
    +API_EXPORT(int) ap_count_dirs(const char *path);
    +API_EXPORT(char *) ap_make_dirstr_prefix(char *d, const char *s, int n);
    +API_EXPORT(char *) ap_make_dirstr_parent(pool *p, const char *s);
    +/* deprecated.  The previous two routines are preferred. */
    +API_EXPORT(char *) ap_make_dirstr(pool *a, const char *s, int n);
    +API_EXPORT(char *) ap_make_full_path(pool *a, const char *dir, const char *f);
    +
    +API_EXPORT(int) ap_is_matchexp(const char *str);
    +API_EXPORT(int) ap_strcmp_match(const char *str, const char *exp);
    +API_EXPORT(int) ap_strcasecmp_match(const char *str, const char *exp);
    +API_EXPORT(char *) ap_uudecode(pool *, const char *);
    +
    +API_EXPORT(char *) ap_pregsub(pool *p, const char *input, const char *source,
    +			   size_t nmatch, regmatch_t pmatch[]);
    +
    +API_EXPORT(void) ap_str_tolower(char *);
    +API_EXPORT(int) ap_ind(const char *, char);	/* Sigh... */
    +API_EXPORT(int) ap_rind(const char *, char);
    +
    +API_EXPORT(char *) ap_escape_quotes (pool *p, const char *instring);
    +
    +/* Common structure for reading of config files / passwd files etc. */
    +typedef struct {
    +    int (*getch) (void *param);	/* a getc()-like function */
    +    void *(*getstr) (void *buf, size_t bufsiz, void *param); /* a fgets()-like function */
    +    int (*close) (void *param);	/* a close hander function */
    +    void *param;		/* the argument passed to getch/getstr/close */
    +    const char *name;		/* the filename / description */
    +    unsigned line_number;	/* current line number, starting at 1 */
    +} configfile_t;
    +
    +/* Common structure that holds the file and pool for ap_pcfg_openfile */
    +typedef struct {
    +    struct pool *pool;
    +    FILE *file;
    +} poolfile_t;
    +
    +/* Open a configfile_t as FILE, return open configfile_t struct pointer */
    +API_EXPORT(configfile_t *) ap_pcfg_openfile(pool *p, const char *name);
    +
    +/* Allocate a configfile_t handle with user defined functions and params */
    +API_EXPORT(configfile_t *) ap_pcfg_open_custom(pool *p, const char *descr,
    +    void *param,
    +    int(*getc_func)(void*),
    +    void *(*gets_func) (void *buf, size_t bufsiz, void *param),
    +    int(*close_func)(void *param));
    +
    +/* Read one line from open configfile_t, strip LF, increase line number */
    +API_EXPORT(int) ap_cfg_getline(char *buf, size_t bufsize, configfile_t *cfp);
    +
    +/* Read one char from open configfile_t, increase line number upon LF */
    +API_EXPORT(int) ap_cfg_getc(configfile_t *cfp);
    +
    +/* Detach from open configfile_t, calling the close handler */
    +API_EXPORT(int) ap_cfg_closefile(configfile_t *cfp);
    +
    +#ifdef NEED_STRERROR
    +char *strerror(int err);
    +#endif
    +
    +/* Misc system hackery */
    +
    +API_EXPORT(uid_t) ap_uname2id(const char *name);
    +API_EXPORT(gid_t) ap_gname2id(const char *name);
    +API_EXPORT(int) ap_is_directory(const char *name);
    +API_EXPORT(int) ap_can_exec(const struct stat *);
    +API_EXPORT(void) ap_chdir_file(const char *file);
    +
    +#ifndef HAVE_CANONICAL_FILENAME
    +#define ap_os_canonical_filename(p,f)  (f)
    +#else
    +API_EXPORT(char *) ap_os_canonical_filename(pool *p, const char *file);
    +#endif
    +
    +#ifdef _OSD_POSIX
    +extern const char *os_set_authfile(pool *p, const char *filename);
    +extern int os_init_job_environment(server_rec *s, const char *user_name);
    +#endif /* _OSD_POSIX */
    +
    +char *ap_get_local_host(pool *);
    +unsigned long ap_get_virthost_addr(const char *hostname, unsigned short *port);
    +
    +extern API_VAR_EXPORT time_t ap_restart_time;
    +
    +/*
    + * Apache tries to keep all of its long term filehandles (such as log files,
    + * and sockets) above this number.  This is to workaround problems in many
    + * third party libraries that are compiled with a small FD_SETSIZE.  There
    + * should be no reason to lower this, because it's only advisory.  If a file
    + * can't be allocated above this number then it will remain in the "slack"
    + * area.
    + *
    + * Only the low slack line is used by default.  If HIGH_SLACK_LINE is defined
    + * then an attempt is also made to keep all non-FILE * files above the high
    + * slack line.  This is to work around a Solaris C library limitation, where it
    + * uses an unsigned char to store the file descriptor.
    + */
    +#ifndef LOW_SLACK_LINE
    +#define LOW_SLACK_LINE	15
    +#endif
    +/* #define HIGH_SLACK_LINE      255 */
    +
    +/*
    + * The ap_slack() function takes a fd, and tries to move it above the indicated
    + * line.  It returns an fd which may or may not have moved above the line, and
    + * never fails.  If the high line was requested and it fails it will also try
    + * the low line.
    + */
    +#ifdef NO_SLACK
    +#define ap_slack(fd,line)   (fd)
    +#else
    +int ap_slack(int fd, int line);
    +#define AP_SLACK_LOW	1
    +#define AP_SLACK_HIGH	2
    +#endif
    +
    +/*
    + * Redefine assert() to something more useful for an Apache...
    + */
    +API_EXPORT(void) ap_log_assert(const char *szExp, const char *szFile, int nLine)
    +			    __attribute__((noreturn));
    +#define ap_assert(exp) (void)( (exp) || (ap_log_assert(#exp, __FILE__, __LINE__), 0) )
    +
    +/* The optimized timeout code only works if we're not MULTITHREAD and we're
    + * also not using a scoreboard file
    + */
    +#if !defined (MULTITHREAD) && \
    +    (defined (USE_MMAP_SCOREBOARD) || defined (USE_SHMGET_SCOREBOARD))
    +#define OPTIMIZE_TIMEOUTS
    +#endif
    +
    +/* A set of flags which indicate places where the server should raise(SIGSTOP).
    + * This is useful for debugging, because you can then attach to that process
    + * with gdb and continue.  This is important in cases where one_process
    + * debugging isn't possible.
    + */
    +#define SIGSTOP_DETACH			1
    +#define SIGSTOP_MAKE_CHILD		2
    +#define SIGSTOP_SPAWN_CHILD		4
    +#define SIGSTOP_PIPED_LOG_SPAWN		8
    +#define SIGSTOP_CGI_CHILD		16
    +
    +#ifdef DEBUG_SIGSTOP
    +extern int raise_sigstop_flags;
    +#define RAISE_SIGSTOP(x)	do { \
    +	if (raise_sigstop_flags & SIGSTOP_##x) raise(SIGSTOP);\
    +    } while (0)
    +#else
    +#define RAISE_SIGSTOP(x)
    +#endif
    +
    +API_EXPORT(extern const char *) ap_psignature(const char *prefix, request_rec *r);
    +
    +/* strtoul does not exist on sunos4. */
    +#ifdef strtoul
    +#undef strtoul
    +#endif
    +#define strtoul strtoul_is_not_a_portable_function_use_strtol_instead
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTPD_H */
    diff --git a/APACHE_1_3b7/src/include/md5.h b/APACHE_1_3b7/src/include/md5.h
    new file mode 100644
    index 0000000000..bf61b4dcd3
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/md5.h
    @@ -0,0 +1,116 @@
    +/*
    + * This is work is derived from material Copyright RSA Data Security, Inc.
    + *
    + * The RSA copyright statement and Licence for that original material is
    + * included below. This is followed by the Apache copyright statement and
    + * licence for the modifications made to that material.
    + */
    +
    +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
    +   rights reserved.
    +
    +   License to copy and use this software is granted provided that it
    +   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
    +   Algorithm" in all material mentioning or referencing this software
    +   or this function.
    +
    +   License is also granted to make and use derivative works provided
    +   that such works are identified as "derived from the RSA Data
    +   Security, Inc. MD5 Message-Digest Algorithm" in all material
    +   mentioning or referencing the derived work.
    +
    +   RSA Data Security, Inc. makes no representations concerning either
    +   the merchantability of this software or the suitability of this
    +   software for any particular purpose. It is provided "as is"
    +   without express or implied warranty of any kind.
    +
    +   These notices must be retained in any copies of any part of this
    +   documentation and/or software.
    + */
    +
    +/* ====================================================================
    + * Copyright (c) 1996-1998 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_MD5_H
    +#define APACHE_MD5_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/* MD5.H - header file for MD5C.C */
    +
    +/* UINT4 defines a four byte word */
    +typedef unsigned int UINT4;
    +
    +/* MD5 context. */
    +typedef struct {
    +    UINT4 state[4];		/* state (ABCD) */
    +    UINT4 count[2];		/* number of bits, modulo 2^64 (lsb first) */
    +    unsigned char buffer[64];	/* input buffer */
    +} AP_MD5_CTX;
    +
    +API_EXPORT(void) ap_MD5Init(AP_MD5_CTX * context);
    +API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input,
    +			   unsigned int inputLen);
    +API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX * context);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_MD5_H */
    diff --git a/APACHE_1_3b7/src/include/multithread.h b/APACHE_1_3b7/src/include/multithread.h
    new file mode 100644
    index 0000000000..bed94638b6
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/multithread.h
    @@ -0,0 +1,65 @@
    +#ifndef APACHE_MULTITHREAD_H
    +#define APACHE_MULTITHREAD_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#define MULTI_OK (0)
    +#define MULTI_TIMEOUT (1)
    +#define MULTI_ERR (2)
    +
    +typedef void mutex;
    +typedef void semaphore;
    +typedef void thread;
    +typedef void event;
    +
    +/*
    + * Ambarish: Need to do the right stuff on multi-threaded unix
    + * I believe this is terribly ugly
    + */
    +#ifdef MULTITHREAD
    +#define APACHE_TLS __declspec( thread )
    +
    +thread *create_thread(void (thread_fn) (void *thread_arg), void *thread_arg);
    +int kill_thread(thread *thread_id);
    +int await_thread(thread *thread_id, int sec_to_wait);
    +void exit_thread(int status);
    +void free_thread(thread *thread_id);
    +
    +API_EXPORT(mutex *) ap_create_mutex(char *name);
    +API_EXPORT(mutex *) ap_open_mutex(char *name);
    +API_EXPORT(int) ap_acquire_mutex(mutex *mutex_id);
    +API_EXPORT(int) ap_release_mutex(mutex *mutex_id);
    +API_EXPORT(void) ap_destroy_mutex(mutex *mutex_id);
    +
    +semaphore *create_semaphore(int initial);
    +int acquire_semaphore(semaphore *semaphore_id);
    +int release_semaphore(semaphore *semaphore_id);
    +void destroy_semaphore(semaphore *semaphore_id);
    +
    +event *create_event(int manual, int initial, char *name);
    +event *open_event(char *name);
    +int acquire_event(event *event_id);
    +int set_event(event *event_id);
    +int reset_event(event *event_id);
    +void destroy_event(event *event_id);
    +
    +#else /* ndef MULTITHREAD */
    +
    +#define APACHE_TLS
    +/* Only define the ones actually used, for now */
    +extern void *ap_dummy_mutex;
    +
    +#define ap_create_mutex(name)	((mutex *)ap_dummy_mutex)
    +#define ap_acquire_mutex(mutex_id)	((int)MULTI_OK)
    +#define ap_release_mutex(mutex_id)	((int)MULTI_OK)
    +#define ap_destroy_mutex(mutex_id)	(0)
    +
    +#endif /* ndef MULTITHREAD */
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif /* !APACHE_MULTITHREAD_H */
    diff --git a/APACHE_1_3b7/src/include/rfc1413.h b/APACHE_1_3b7/src/include/rfc1413.h
    new file mode 100644
    index 0000000000..e84b0c3e35
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/rfc1413.h
    @@ -0,0 +1,71 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1998 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_RFC1413_H
    +#define APACHE_RFC1413_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +extern char *ap_rfc1413(conn_rec *conn, server_rec *srv);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_RFC1413_H */
    diff --git a/APACHE_1_3b7/src/include/scoreboard.h b/APACHE_1_3b7/src/include/scoreboard.h
    new file mode 100644
    index 0000000000..8beb27990e
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/scoreboard.h
    @@ -0,0 +1,173 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_SCOREBOARD_H
    +#define APACHE_SCOREBOARD_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#ifndef WIN32
    +#include <sys/times.h>
    +#endif
    +
    +/* Scoreboard info on a process is, for now, kept very brief --- 
    + * just status value and pid (the latter so that the caretaker process
    + * can properly update the scoreboard when a process dies).  We may want
    + * to eventually add a separate set of long_score structures which would
    + * give, for each process, the number of requests serviced, and info on
    + * the current, or most recent, request.
    + *
    + * Status values:
    + */
    +
    +#define SERVER_DEAD 0
    +#define SERVER_STARTING 1	/* Server Starting up */
    +#define SERVER_READY 2		/* Waiting for connection (or accept() lock) */
    +#define SERVER_BUSY_READ 3	/* Reading a client request */
    +#define SERVER_BUSY_WRITE 4	/* Processing a client request */
    +#define SERVER_BUSY_KEEPALIVE 5	/* Waiting for more requests via keepalive */
    +#define SERVER_BUSY_LOG 6	/* Logging the request */
    +#define SERVER_BUSY_DNS 7	/* Looking up a hostname */
    +#define SERVER_GRACEFUL 8	/* server is gracefully finishing request */
    +#define SERVER_NUM_STATUS 9	/* number of status settings */
    +
    +/* A "virtual time" is simply a counter that indicates that a child is
    + * making progress.  The parent checks up on each child, and when they have
    + * made progress it resets the last_rtime element.  But when the child hasn't
    + * made progress in a time that's roughly timeout_len seconds long, it is
    + * sent a SIGALRM.
    + *
    + * vtime is an optimization that is used only when the scoreboard is in
    + * shared memory (it's not easy/feasible to do it in a scoreboard file).
    + * The essential observation is that timeouts rarely occur, the vast majority
    + * of hits finish before any timeout happens.  So it really sucks to have to
    + * ask the operating system to set up and destroy alarms many times during
    + * a request.
    + */
    +typedef unsigned vtime_t;
    +
    +/* stuff which the children generally write, and the parent mainly reads */
    +typedef struct {
    +#ifdef OPTIMIZE_TIMEOUTS
    +    vtime_t cur_vtime;		/* the child's current vtime */
    +    unsigned short timeout_len;	/* length of the timeout */
    +#endif
    +    unsigned char status;
    +#if defined(STATUS)
    +    unsigned long access_count;
    +    unsigned long bytes_served;
    +    unsigned long my_access_count;
    +    unsigned long my_bytes_served;
    +    unsigned long conn_bytes;
    +    unsigned short conn_count;
    +#if defined(NO_GETTIMEOFDAY)
    +    clock_t start_time;
    +    clock_t stop_time;
    +#else
    +    struct timeval start_time;
    +    struct timeval stop_time;
    +#endif
    +#ifndef NO_TIMES
    +    struct tms times;
    +#endif
    +#ifndef OPTIMIZE_TIMEOUTS
    +    time_t last_used;
    +#endif
    +    char client[32];		/* Keep 'em small... */
    +    char request[64];		/* We just want an idea... */
    +    char vhost[32];		/* What virtual host is being accessed? */
    +#endif
    +} short_score;
    +
    +typedef struct {
    +    int exit_generation;	/* Set by the main process if a graceful
    +				   restart is required */
    +} global_score;
    +
    +/* stuff which the parent generally writes and the children rarely read */
    +typedef struct {
    +    pid_t pid;
    +#ifdef OPTIMIZE_TIMEOUTS
    +    time_t last_rtime;		/* time(0) of the last change */
    +    vtime_t last_vtime;		/* the last vtime the parent has seen */
    +#endif
    +} parent_score;
    +
    +typedef struct {
    +    short_score servers[HARD_SERVER_LIMIT];
    +    parent_score parent[HARD_SERVER_LIMIT];
    +    global_score global;
    +} scoreboard;
    +
    +#define SCOREBOARD_SIZE		sizeof(scoreboard)
    +
    +API_EXPORT(void) ap_sync_scoreboard_image(void);
    +API_EXPORT(int) ap_exists_scoreboard_image(void);
    +
    +API_VAR_EXPORT extern scoreboard *ap_scoreboard_image;
    +
    +/* for time_process_request() in http_main.c */
    +#define START_PREQUEST 1
    +#define STOP_PREQUEST  2
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_SCOREBOARD_H */
    diff --git a/APACHE_1_3b7/src/include/util_date.h b/APACHE_1_3b7/src/include/util_date.h
    new file mode 100644
    index 0000000000..9e53fc30cc
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/util_date.h
    @@ -0,0 +1,85 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1998 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_UTIL_DATE_H
    +#define APAcHE_UTIL_DATE_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/*
    + * util_date.h: prototypes for date parsing utility routines
    + */
    +
    +#ifdef NEWSOS
    +#include <stdlib.h>
    +#include <sys/types.h>
    +#endif
    +#include <time.h>
    +
    +#define BAD_DATE (time_t)0
    +
    +API_EXPORT(int) ap_checkmask(const char *data, const char *mask);
    +API_EXPORT(time_t) ap_tm2sec(const struct tm *t);
    +API_EXPORT(time_t) ap_parseHTTPdate(const char *date);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_UTIL_DATE_H */
    diff --git a/APACHE_1_3b7/src/include/util_md5.h b/APACHE_1_3b7/src/include/util_md5.h
    new file mode 100644
    index 0000000000..1c8f2ced3b
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/util_md5.h
    @@ -0,0 +1,75 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_UTIL_MD5_H
    +#define APACHE_UTIL_MD5_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#include "md5.h"
    +
    +API_EXPORT(char *) ap_md5(pool *a, unsigned char *string);
    +API_EXPORT(char *) ap_md5contextTo64(pool *p, AP_MD5_CTX * context);
    +API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_UTIL_MD5_H */
    diff --git a/APACHE_1_3b7/src/include/util_script.h b/APACHE_1_3b7/src/include/util_script.h
    new file mode 100644
    index 0000000000..da6f691ac0
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/util_script.h
    @@ -0,0 +1,89 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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_UTIL_SCRIPT_H
    +#define APACHE_UTIL_SCRIPT_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#ifndef APACHE_ARG_MAX
    +#ifdef _POSIX_ARG_MAX
    +#define APACHE_ARG_MAX _POSIX_ARG_MAX
    +#else
    +#define APACHE_ARG_MAX 512
    +#endif
    +#endif
    +
    +API_EXPORT(char **) ap_create_environment(pool *p, table *t);
    +API_EXPORT(int) ap_find_path_info(const char *uri, const char *path_info);
    +API_EXPORT(void) ap_add_cgi_vars(request_rec *r);
    +API_EXPORT(void) ap_add_common_vars(request_rec *r);
    +#define scan_script_header(a1,a2) ap_scan_script_header_err(a1,a2,NULL)
    +API_EXPORT(int) ap_scan_script_header_err(request_rec *r, FILE *f, char *buffer);
    +API_EXPORT(int) ap_scan_script_header_err_buff(request_rec *r, BUFF *f,
    +                                            char *buffer);
    +API_EXPORT(void) ap_send_size(size_t size, request_rec *r);
    +API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0, char **env,
    +                          int shellcmd);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_UTIL_SCRIPT_H */
    diff --git a/APACHE_1_3b7/src/include/util_uri.h b/APACHE_1_3b7/src/include/util_uri.h
    new file mode 100644
    index 0000000000..a8e75f1543
    --- /dev/null
    +++ b/APACHE_1_3b7/src/include/util_uri.h
    @@ -0,0 +1,127 @@
    +/* ====================================================================
    + * Copyright (c) 1998 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.
    + *
    + * 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/>.
    + *
    + */
    +
    +/*
    + * util_uri.h: External Interface of util_uri.c
    + */
    +
    +#ifndef UTIL_URI_H
    +#define UTIL_URI_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +typedef struct {
    +    const char *name;
    +    unsigned short default_port;
    +} schemes_t;
    +
    +#define	DEFAULT_FTP_DATA_PORT	20
    +#define	DEFAULT_FTP_PORT	21
    +#define	DEFAULT_GOPHER_PORT	70
    +#define	DEFAULT_NNTP_PORT	119
    +#define	DEFAULT_WAIS_PORT	210
    +#define	DEFAULT_HTTPS_PORT	443
    +#define	DEFAULT_SNEWS_PORT	563
    +#define	DEFAULT_PROSPERO_PORT	1525	/* WARNING: conflict w/Oracle */
    +
    +/* Flags passed to unparse_uri_components(): */
    +#define UNP_OMITSITEPART	(1U<<0)	/* suppress "scheme://user@site:port" */
    +#define	UNP_OMITUSER		(1U<<1)	/* Just omit user */
    +#define	UNP_OMITPASSWORD	(1U<<2)	/* Just omit password */
    +#define	UNP_OMITUSERINFO	(UNP_OMITUSER|UNP_OMITPASSWORD)	/* omit "user:password@" part */
    +#define	UNP_REVEALPASSWORD	(1U<<3)	/* Show plain text password (default: show XXXXXXXX) */
    +
    +typedef struct {
    +    char *scheme;		/* scheme ("http"/"ftp"/...) */
    +    char *hostinfo;             /* combined [user[:password]@]host[:port] */
    +    char *user;			/* user name, as in http://user:passwd@host:port/ */
    +    char *password;		/* password, as in http://user:passwd@host:port/ */
    +    char *hostname;		/* hostname from URI (or from Host: header) */
    +    char *port_str;		/* port string (integer representation is in "port") */
    +    char *path;			/* the request path (or "/" if only scheme://host was given) */
    +    char *query;		/* Everything after a '?' in the path, if present */
    +    char *fragment;		/* Trailing "#fragment" string, if present */
    +
    +    struct hostent *hostent;
    +
    +    unsigned short port;	/* The port number, numeric, valid only if port_str != NULL */
    +    
    +    unsigned is_initialized:1;
    +
    +    unsigned dns_looked_up:1;
    +    unsigned dns_resolved:1;
    +
    +} uri_components;
    +
    +/* util_uri.c */
    +API_EXPORT(unsigned short) ap_default_port_for_scheme(const char *scheme_str);
    +API_EXPORT(unsigned short) ap_default_port_for_request(const request_rec *r);
    +API_EXPORT(struct hostent *) ap_pduphostent(pool *p, struct hostent *hp);
    +API_EXPORT(struct hostent *) ap_pgethostbyname(pool *p, const char *hostname);
    +API_EXPORT(char *) ap_unparse_uri_components(pool *p, const uri_components *uptr,
    +    unsigned flags);
    +API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri, uri_components *uptr);
    +API_EXPORT(int) ap_parse_hostinfo_components(pool *p, const char *hostinfo, uri_components *uptr);
    +/* called by the core in main() */
    +extern void ap_util_uri_init(void);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif /*UTIL_URI_H*/
    diff --git a/APACHE_1_3b7/src/main/.cvsignore b/APACHE_1_3b7/src/main/.cvsignore
    new file mode 100644
    index 0000000000..f8193cb91b
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/.cvsignore
    @@ -0,0 +1,13 @@
    +Makefile
    +uri_delims.h
    +gen_uri_delims
    +test_char.h
    +gen_test_char
    +gen_uri_delims_R
    +gen_test_char_R
    +gen_uri_delims_D
    +gen_uri_delims.ilk
    +gen_uri_delims.pdb
    +gen_test_char_D
    +gen_test_char.ilk
    +gen_test_char.pdb
    diff --git a/APACHE_1_3b7/src/main/.indent.pro b/APACHE_1_3b7/src/main/.indent.pro
    new file mode 100644
    index 0000000000..a9fbe9f9a1
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/.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/APACHE_1_3b7/src/main/Makefile.tmpl b/APACHE_1_3b7/src/main/Makefile.tmpl
    new file mode 100644
    index 0000000000..7bc1711d04
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/Makefile.tmpl
    @@ -0,0 +1,141 @@
    +
    +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
    +LIBS=$(EXTRA_LIBS) $(LIBS1)
    +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
    +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
    +
    +LIB=  libmain.a
    +HEADERS= test_char.h uri_delims.h 
    +
    +OBJS= alloc.o buff.o \
    +      http_config.o http_core.o http_log.o \
    +      http_main.o http_protocol.o http_request.o http_vhost.o \
    +      util.o util_date.o util_script.o util_uri.o util_md5.o \
    +      md5c.o rfc1413.o fnmatch.o
    +
    +.c.o:
    +	$(CC) -c $(INCLUDES) $(CFLAGS) $<
    +
    +all: $(HEADERS) $(LIB)
    +
    +$(LIB): $(OBJS)
    +	rm -f $@
    +	ar cr $@ $(OBJS)
    +	$(RANLIB) $@
    +
    +clean:
    +	rm -f *.o $(LIB) uri_delims.h gen_uri_delims test_char.h gen_test_char
    +
    +distclean: clean
    +	-rm -f Makefile
    +
    +uri_delims.h: gen_uri_delims
    +	./gen_uri_delims >uri_delims.h
    +
    +gen_uri_delims: gen_uri_delims.o
    +	$(CC) $(CFLAGS) $(LDFLAGS) -o gen_uri_delims gen_uri_delims.o $(LIBS)
    +
    +test_char.h: gen_test_char
    +	./gen_test_char >test_char.h
    +
    +gen_test_char: gen_test_char.o
    +	$(CC) $(CFLAGS) $(LDFLAGS) -o gen_test_char gen_test_char.o $(LIBS)
    +
    +# We really don't expect end users to use this rule.  It works only with
    +# gcc, and rebuilds Makefile.tmpl.  You have to re-run Configure after
    +# using it.
    +depend:
    +	cp Makefile.tmpl Makefile.tmpl.bak \
    +	    && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
    +	    && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
    +	    && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
    +	           -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
    +		> Makefile.tmpl \
    +	    && rm Makefile.new
    +
    +#Dependencies
    +
    +$(OBJS): Makefile
    +
    +# DO NOT REMOVE
    +alloc.o: alloc.c $(INCDIR)/httpd.h $(INCDIR)/conf.h $(OSDIR)/os.h \
    + $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/multithread.h $(INCDIR)/http_log.h
    +buff.o: buff.c $(INCDIR)/httpd.h $(INCDIR)/conf.h $(OSDIR)/os.h \
    + $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_main.h $(INCDIR)/http_log.h
    +fnmatch.o: fnmatch.c $(INCDIR)/conf.h $(OSDIR)/os.h \
    + $(INCDIR)/fnmatch.h
    +gen_test_char.o: gen_test_char.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h
    +gen_uri_delims.o: gen_uri_delims.c
    +http_config.o: http_config.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_config.h $(INCDIR)/http_core.h \
    + $(INCDIR)/http_log.h $(INCDIR)/http_request.h \
    + $(INCDIR)/http_conf_globals.h $(INCDIR)/http_vhost.h \
    + $(INCDIR)/explain.h
    +http_core.o: http_core.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_config.h $(INCDIR)/http_core.h \
    + $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
    + $(INCDIR)/http_conf_globals.h $(INCDIR)/http_vhost.h \
    + $(INCDIR)/http_main.h $(INCDIR)/http_log.h $(INCDIR)/rfc1413.h \
    + $(INCDIR)/util_md5.h $(INCDIR)/md5.h $(INCDIR)/scoreboard.h \
    + $(INCDIR)/fnmatch.h
    +http_log.o: http_log.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_config.h $(INCDIR)/http_core.h \
    + $(INCDIR)/http_log.h $(INCDIR)/http_main.h
    +http_main.o: http_main.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_main.h $(INCDIR)/http_log.h \
    + $(INCDIR)/http_config.h $(INCDIR)/http_protocol.h \
    + $(INCDIR)/http_request.h $(INCDIR)/http_conf_globals.h \
    + $(INCDIR)/http_core.h $(INCDIR)/http_vhost.h \
    + $(INCDIR)/util_script.h $(INCDIR)/scoreboard.h \
    + $(INCDIR)/multithread.h $(INCDIR)/explain.h
    +http_protocol.o: http_protocol.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_config.h $(INCDIR)/http_core.h \
    + $(INCDIR)/http_protocol.h $(INCDIR)/http_main.h \
    + $(INCDIR)/http_request.h $(INCDIR)/http_vhost.h \
    + $(INCDIR)/http_log.h $(INCDIR)/util_date.h \
    + $(INCDIR)/http_conf_globals.h
    +http_request.o: http_request.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
    + $(INCDIR)/http_request.h $(INCDIR)/http_core.h \
    + $(INCDIR)/http_protocol.h $(INCDIR)/http_log.h \
    + $(INCDIR)/http_main.h $(INCDIR)/scoreboard.h $(INCDIR)/fnmatch.h
    +http_vhost.o: http_vhost.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
    + $(INCDIR)/http_conf_globals.h $(INCDIR)/http_log.h \
    + $(INCDIR)/http_vhost.h $(INCDIR)/http_protocol.h
    +md5c.o: md5c.c $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/md5.h
    +rfc1413.o: rfc1413.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_log.h $(INCDIR)/rfc1413.h \
    + $(INCDIR)/http_main.h
    +util.o: util.c $(INCDIR)/httpd.h $(INCDIR)/conf.h $(OSDIR)/os.h \
    + $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_conf_globals.h \
    + $(INCDIR)/http_log.h test_char.h
    +util_date.o: util_date.c $(INCDIR)/conf.h $(OSDIR)/os.h \
    + $(INCDIR)/util_date.h
    +util_md5.o: util_md5.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/util_md5.h $(INCDIR)/md5.h
    +util_script.o: util_script.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
    + $(INCDIR)/http_conf_globals.h $(INCDIR)/http_main.h \
    + $(INCDIR)/http_log.h $(INCDIR)/http_protocol.h \
    + $(INCDIR)/http_core.h $(INCDIR)/http_request.h \
    + $(INCDIR)/util_script.h $(INCDIR)/util_date.h
    +util_uri.o: util_uri.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \
    + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h $(INCDIR)/http_log.h \
    + $(INCDIR)/http_conf_globals.h uri_delims.h
    diff --git a/APACHE_1_3b7/src/main/alloc.c b/APACHE_1_3b7/src/main/alloc.c
    new file mode 100644
    index 0000000000..c538aa2c35
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/alloc.c
    @@ -0,0 +1,2314 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +/*
    + * Resource allocation code... the code here is responsible for making
    + * sure that nothing leaks.
    + *
    + * rst --- 4/95 --- 6/95
    + */
    +
    +#include "httpd.h"
    +#include "multithread.h"
    +#include "http_log.h"
    +
    +#include <stdarg.h>
    +
    +/* debugging support, define this to enable code which helps detect re-use
    + * of freed memory and other such nonsense.
    + *
    + * The theory is simple.  The FILL_BYTE (0xa5) is written over all malloc'd
    + * memory as we receive it, and is written over everything that we free up
    + * during a clear_pool.  We check that blocks on the free list always
    + * have the FILL_BYTE in them, and we check during palloc() that the bytes
    + * still have FILL_BYTE in them.  If you ever see garbage URLs or whatnot
    + * containing lots of 0xa5s then you know something used data that's been
    + * freed or uninitialized.
    + */
    +/* #define ALLOC_DEBUG */
    +
    +/* debugging support, if defined all allocations will be done with
    + * malloc and free()d appropriately at the end.  This is intended to be
    + * used with something like Electric Fence or Purify to help detect
    + * memory problems.  Note that if you're using efence then you should also
    + * add in ALLOC_DEBUG.  But don't add in ALLOC_DEBUG if you're using Purify
    + * because ALLOC_DEBUG would hide all the uninitialized read errors that
    + * Purify can diagnose.
    + */
    +/* #define ALLOC_USE_MALLOC */
    +
    +/* Pool debugging support.  This is intended to detect cases where the
    + * wrong pool is used when assigning data to an object in another pool.
    + * In particular, it causes the table_{set,add,merge}n routines to check
    + * that their arguments are safe for the table they're being placed in.
    + * It currently only works with the unix multiprocess model, but could
    + * be extended to others.
    + */
    +/* #define POOL_DEBUG */
    +
    +/* Provide diagnostic information about make_table() calls which are
    + * possibly too small.  This requires a recent gcc which supports
    + * __builtin_return_address().  The error_log output will be a
    + * message such as:
    + *    table_push: table created by 0x804d874 hit limit of 10
    + * Use "l *0x804d874" to find the source that corresponds to.  It
    + * indicates that a table allocated by a call at that address has
    + * possibly too small an initial table size guess.
    + */
    +/* #define MAKE_TABLE_PROFILE */
    +
    +#ifdef POOL_DEBUG
    +#ifdef ALLOC_USE_MALLOC
    +# error "sorry, no support for ALLOC_USE_MALLOC and POOL_DEBUG at the same time"
    +#endif
    +#ifdef MULTITHREAD
    +# error "sorry, no support for MULTITHREAD and POOL_DEBUG at the same time"
    +#endif
    +#endif
    +
    +#ifdef ALLOC_USE_MALLOC
    +#undef BLOCK_MINFREE
    +#undef BLOCK_MINALLOC
    +#define BLOCK_MINFREE	0
    +#define BLOCK_MINALLOC	0
    +#endif
    +
    +/*****************************************************************
    + *
    + * Managing free storage blocks...
    + */
    +
    +union align {
    +    /* Types which are likely to have the longest RELEVANT alignment
    +     * restrictions...
    +     */
    +
    +    char *cp;
    +    void (*f) (void);
    +    long l;
    +    FILE *fp;
    +    double d;
    +};
    +
    +#define CLICK_SZ (sizeof(union align))
    +
    +union block_hdr {
    +    union align a;
    +
    +    /* Actual header... */
    +
    +    struct {
    +	char *endp;
    +	union block_hdr *next;
    +	char *first_avail;
    +#ifdef POOL_DEBUG
    +	union block_hdr *global_next;
    +	struct pool *owning_pool;
    +#endif
    +    } h;
    +};
    +
    +static union block_hdr *block_freelist = NULL;
    +static mutex *alloc_mutex = NULL;
    +static mutex *spawn_mutex = NULL;
    +#ifdef POOL_DEBUG
    +static char *known_stack_point;
    +static int stack_direction;
    +static union block_hdr *global_block_list;
    +#define FREE_POOL	((struct pool *)(-1))
    +#endif
    +
    +#ifdef ALLOC_DEBUG
    +#define FILL_BYTE	((char)(0xa5))
    +
    +#define debug_fill(ptr,size)	((void)memset((ptr), FILL_BYTE, (size)))
    +
    +static ap_inline void debug_verify_filled(const char *ptr,
    +    const char *endp, const char *error_msg)
    +{
    +    for (; ptr < endp; ++ptr) {
    +	if (*ptr != FILL_BYTE) {
    +	    fputs(error_msg, stderr);
    +	    abort();
    +	    exit(1);
    +	}
    +    }
    +}
    +
    +#else
    +#define debug_fill(a,b)
    +#define debug_verify_filled(a,b,c)
    +#endif
    +
    +
    +/* Get a completely new block from the system pool. Note that we rely on
    +   malloc() to provide aligned memory. */
    +
    +static union block_hdr *malloc_block(int size)
    +{
    +    union block_hdr *blok;
    +
    +#ifdef ALLOC_DEBUG
    +    /* make some room at the end which we'll fill and expect to be
    +     * always filled
    +     */
    +    size += CLICK_SZ;
    +#endif
    +    blok = (union block_hdr *) malloc(size + sizeof(union block_hdr));
    +    if (blok == NULL) {
    +	fprintf(stderr, "Ouch!  malloc failed in malloc_block()\n");
    +	exit(1);
    +    }
    +    debug_fill(blok, size + sizeof(union block_hdr));
    +    blok->h.next = NULL;
    +    blok->h.first_avail = (char *) (blok + 1);
    +    blok->h.endp = size + blok->h.first_avail;
    +#ifdef ALLOC_DEBUG
    +    blok->h.endp -= CLICK_SZ;
    +#endif
    +#ifdef POOL_DEBUG
    +    blok->h.global_next = global_block_list;
    +    global_block_list = blok;
    +    blok->h.owning_pool = NULL;
    +#endif
    +
    +    return blok;
    +}
    +
    +
    +
    +#if defined(ALLOC_DEBUG) && !defined(ALLOC_USE_MALLOC)
    +static void chk_on_blk_list(union block_hdr *blok, union block_hdr *free_blk)
    +{
    +    debug_verify_filled(blok->h.endp, blok->h.endp + CLICK_SZ,
    +	"Ouch!  Someone trounced the padding at the end of a block!\n");
    +    while (free_blk) {
    +	if (free_blk == blok) {
    +	    fprintf(stderr, "Ouch!  Freeing free block\n");
    +	    abort();
    +	    exit(1);
    +	}
    +	free_blk = free_blk->h.next;
    +    }
    +}
    +#else
    +#define chk_on_blk_list(_x, _y)
    +#endif
    +
    +/* Free a chain of blocks --- must be called with alarms blocked. */
    +
    +static void free_blocks(union block_hdr *blok)
    +{
    +#ifdef ALLOC_USE_MALLOC
    +    union block_hdr *next;
    +
    +    for (; blok; blok = next) {
    +	next = blok->h.next;
    +	free(blok);
    +    }
    +#else
    +    /* First, put new blocks at the head of the free list ---
    +     * we'll eventually bash the 'next' pointer of the last block
    +     * in the chain to point to the free blocks we already had.
    +     */
    +
    +    union block_hdr *old_free_list;
    +
    +    if (blok == NULL)
    +	return;			/* Sanity check --- freeing empty pool? */
    +
    +    (void) ap_acquire_mutex(alloc_mutex);
    +    old_free_list = block_freelist;
    +    block_freelist = blok;
    +
    +    /*
    +     * Next, adjust first_avail pointers of each block --- have to do it
    +     * sooner or later, and it simplifies the search in new_block to do it
    +     * now.
    +     */
    +
    +    while (blok->h.next != NULL) {
    +	chk_on_blk_list(blok, old_free_list);
    +	blok->h.first_avail = (char *) (blok + 1);
    +	debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
    +#ifdef POOL_DEBUG
    +	blok->h.owning_pool = FREE_POOL;
    +#endif
    +	blok = blok->h.next;
    +    }
    +
    +    chk_on_blk_list(blok, old_free_list);
    +    blok->h.first_avail = (char *) (blok + 1);
    +    debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
    +#ifdef POOL_DEBUG
    +    blok->h.owning_pool = FREE_POOL;
    +#endif
    +
    +    /* Finally, reset next pointer to get the old free blocks back */
    +
    +    blok->h.next = old_free_list;
    +    (void) ap_release_mutex(alloc_mutex);
    +#endif
    +}
    +
    +
    +/* Get a new block, from our own free list if possible, from the system
    + * if necessary.  Must be called with alarms blocked.
    + */
    +
    +static union block_hdr *new_block(int min_size)
    +{
    +    union block_hdr **lastptr = &block_freelist;
    +    union block_hdr *blok = block_freelist;
    +
    +    /* First, see if we have anything of the required size
    +     * on the free list...
    +     */
    +
    +    while (blok != NULL) {
    +	if (min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
    +	    *lastptr = blok->h.next;
    +	    blok->h.next = NULL;
    +	    debug_verify_filled(blok->h.first_avail, blok->h.endp,
    +		"Ouch!  Someone trounced a block on the free list!\n");
    +	    return blok;
    +	}
    +	else {
    +	    lastptr = &blok->h.next;
    +	    blok = blok->h.next;
    +	}
    +    }
    +
    +    /* Nope. */
    +
    +    min_size += BLOCK_MINFREE;
    +    blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC);
    +    return blok;
    +}
    +
    +
    +/* Accounting */
    +
    +static long bytes_in_block_list(union block_hdr *blok)
    +{
    +    long size = 0;
    +
    +    while (blok) {
    +	size += blok->h.endp - (char *) (blok + 1);
    +	blok = blok->h.next;
    +    }
    +
    +    return size;
    +}
    +
    +
    +/*****************************************************************
    + *
    + * Pool internals and management...
    + * NB that subprocesses are not handled by the generic cleanup code,
    + * basically because we don't want cleanups for multiple subprocesses
    + * to result in multiple three-second pauses.
    + */
    +
    +struct process_chain;
    +struct cleanup;
    +
    +static void run_cleanups(struct cleanup *);
    +static void free_proc_chain(struct process_chain *);
    +
    +struct pool {
    +    union block_hdr *first;
    +    union block_hdr *last;
    +    struct cleanup *cleanups;
    +    struct process_chain *subprocesses;
    +    struct pool *sub_pools;
    +    struct pool *sub_next;
    +    struct pool *sub_prev;
    +    struct pool *parent;
    +    char *free_first_avail;
    +#ifdef ALLOC_USE_MALLOC
    +    void *allocation_list;
    +#endif
    +#ifdef POOL_DEBUG
    +    struct pool *joined;
    +#endif
    +};
    +
    +static pool *permanent_pool;
    +
    +/* Each pool structure is allocated in the start of its own first block,
    + * so we need to know how many bytes that is (once properly aligned...).
    + * This also means that when a pool's sub-pool is destroyed, the storage
    + * associated with it is *completely* gone, so we have to make sure it
    + * gets taken off the parent's sub-pool list...
    + */
    +
    +#define POOL_HDR_CLICKS (1 + ((sizeof(struct pool) - 1) / CLICK_SZ))
    +#define POOL_HDR_BYTES (POOL_HDR_CLICKS * CLICK_SZ)
    +
    +API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p)
    +{
    +    union block_hdr *blok;
    +    pool *new_pool;
    +
    +    ap_block_alarms();
    +
    +    (void) ap_acquire_mutex(alloc_mutex);
    +
    +    blok = new_block(POOL_HDR_BYTES);
    +    new_pool = (pool *) blok->h.first_avail;
    +    blok->h.first_avail += POOL_HDR_BYTES;
    +#ifdef POOL_DEBUG
    +    blok->h.owning_pool = new_pool;
    +#endif
    +
    +    memset((char *) new_pool, '\0', sizeof(struct pool));
    +    new_pool->free_first_avail = blok->h.first_avail;
    +    new_pool->first = new_pool->last = blok;
    +
    +    if (p) {
    +	new_pool->parent = p;
    +	new_pool->sub_next = p->sub_pools;
    +	if (new_pool->sub_next)
    +	    new_pool->sub_next->sub_prev = new_pool;
    +	p->sub_pools = new_pool;
    +    }
    +
    +    (void) ap_release_mutex(alloc_mutex);
    +    ap_unblock_alarms();
    +
    +    return new_pool;
    +}
    +
    +#ifdef POOL_DEBUG
    +static void stack_var_init(char *s)
    +{
    +    char t;
    +
    +    if (s < &t) {
    +	stack_direction = 1; /* stack grows up */
    +    }
    +    else {
    +	stack_direction = -1; /* stack grows down */
    +    }
    +}
    +#endif
    +
    +pool *ap_init_alloc(void)
    +{
    +#ifdef POOL_DEBUG
    +    char s;
    +
    +    known_stack_point = &s;
    +    stack_var_init(&s);
    +#endif
    +    alloc_mutex = ap_create_mutex(NULL);
    +    spawn_mutex = ap_create_mutex(NULL);
    +    permanent_pool = ap_make_sub_pool(NULL);
    +
    +    return permanent_pool;
    +}
    +
    +API_EXPORT(void) ap_clear_pool(struct pool *a)
    +{
    +    ap_block_alarms();
    +
    +    (void) ap_acquire_mutex(alloc_mutex);
    +    while (a->sub_pools)
    +	ap_destroy_pool(a->sub_pools);
    +    (void) ap_release_mutex(alloc_mutex);
    +    /* Don't hold the mutex during cleanups. */
    +    run_cleanups(a->cleanups);
    +    a->cleanups = NULL;
    +    free_proc_chain(a->subprocesses);
    +    a->subprocesses = NULL;
    +    free_blocks(a->first->h.next);
    +    a->first->h.next = NULL;
    +
    +    a->last = a->first;
    +    a->first->h.first_avail = a->free_first_avail;
    +    debug_fill(a->first->h.first_avail,
    +	a->first->h.endp - a->first->h.first_avail);
    +
    +#ifdef ALLOC_USE_MALLOC
    +    {
    +	void *c, *n;
    +
    +	for (c = a->allocation_list; c; c = n) {
    +	    n = *(void **)c;
    +	    free(c);
    +	}
    +	a->allocation_list = NULL;
    +    }
    +#endif
    +
    +    ap_unblock_alarms();
    +}
    +
    +API_EXPORT(void) ap_destroy_pool(pool *a)
    +{
    +    ap_block_alarms();
    +    ap_clear_pool(a);
    +
    +    (void) ap_acquire_mutex(alloc_mutex);
    +    if (a->parent) {
    +	if (a->parent->sub_pools == a)
    +	    a->parent->sub_pools = a->sub_next;
    +	if (a->sub_prev)
    +	    a->sub_prev->sub_next = a->sub_next;
    +	if (a->sub_next)
    +	    a->sub_next->sub_prev = a->sub_prev;
    +    }
    +    (void) ap_release_mutex(alloc_mutex);
    +
    +    free_blocks(a->first);
    +    ap_unblock_alarms();
    +}
    +
    +API_EXPORT(long) ap_bytes_in_pool(pool *p)
    +{
    +    return bytes_in_block_list(p->first);
    +}
    +API_EXPORT(long) ap_bytes_in_free_blocks(void)
    +{
    +    return bytes_in_block_list(block_freelist);
    +}
    +
    +/*****************************************************************
    + * POOL_DEBUG support
    + */
    +#ifdef POOL_DEBUG
    +
    +/* the unix linker defines this symbol as the last byte + 1 of
    + * the executable... so it includes TEXT, BSS, and DATA
    + */
    +extern char _end;
    +
    +/* is ptr in the range [lo,hi) */
    +#define is_ptr_in_range(ptr, lo, hi)	\
    +    (((unsigned long)(ptr) - (unsigned long)(lo)) \
    +	< \
    +	(unsigned long)(hi) - (unsigned long)(lo))
    +
    +/* Find the pool that ts belongs to, return NULL if it doesn't
    + * belong to any pool.
    + */
    +API_EXPORT(pool *) ap_find_pool(const void *ts)
    +{
    +    const char *s = ts;
    +    union block_hdr **pb;
    +    union block_hdr *b;
    +
    +    /* short-circuit stuff which is in TEXT, BSS, or DATA */
    +    if (is_ptr_in_range(s, 0, &_end)) {
    +	return NULL;
    +    }
    +    /* consider stuff on the stack to also be in the NULL pool...
    +     * XXX: there's cases where we don't want to assume this
    +     */
    +    if ((stack_direction == -1 && is_ptr_in_range(s, &ts, known_stack_point))
    +	|| (stack_direction == 1 && is_ptr_in_range(s, known_stack_point, &ts))) {
    +	abort();
    +	return NULL;
    +    }
    +    ap_block_alarms();
    +    /* search the global_block_list */
    +    for (pb = &global_block_list; *pb; pb = &b->h.global_next) {
    +	b = *pb;
    +	if (is_ptr_in_range(s, b, b->h.endp)) {
    +	    if (b->h.owning_pool == FREE_POOL) {
    +		fprintf(stderr,
    +		    "Ouch!  find_pool() called on pointer in a free block\n");
    +		abort();
    +		exit(1);
    +	    }
    +	    if (b != global_block_list) {
    +		/* promote b to front of list, this is a hack to speed
    +		 * up the lookup */
    +		*pb = b->h.global_next;
    +		b->h.global_next = global_block_list;
    +		global_block_list = b;
    +	    }
    +	    ap_unblock_alarms();
    +	    return b->h.owning_pool;
    +	}
    +    }
    +    ap_unblock_alarms();
    +    return NULL;
    +}
    +
    +/* return TRUE iff a is an ancestor of b
    + * NULL is considered an ancestor of all pools
    + */
    +API_EXPORT(int) ap_pool_is_ancestor(pool *a, pool *b)
    +{
    +    if (a == NULL) {
    +	return 1;
    +    }
    +    while (a->joined) {
    +	a = a->joined;
    +    }
    +    while (b) {
    +	if (a == b) {
    +	    return 1;
    +	}
    +	b = b->parent;
    +    }
    +    return 0;
    +}
    +
    +/* All blocks belonging to sub will be changed to point to p
    + * instead.  This is a guarantee by the caller that sub will not
    + * be destroyed before p is.
    + */
    +API_EXPORT(void) ap_pool_join(pool *p, pool *sub)
    +{
    +    union block_hdr *b;
    +
    +    /* We could handle more general cases... but this is it for now. */
    +    if (sub->parent != p) {
    +	fprintf(stderr, "pool_join: p is not parent of sub\n");
    +	abort();
    +    }
    +    ap_block_alarms();
    +    while (p->joined) {
    +	p = p->joined;
    +    }
    +    sub->joined = p;
    +    for (b = global_block_list; b; b = b->h.global_next) {
    +	if (b->h.owning_pool == sub) {
    +	    b->h.owning_pool = p;
    +	}
    +    }
    +    ap_unblock_alarms();
    +}
    +#endif
    +
    +/*****************************************************************
    + *
    + * Allocating stuff...
    + */
    +
    +
    +API_EXPORT(void *) ap_palloc(struct pool *a, int reqsize)
    +{
    +#ifdef ALLOC_USE_MALLOC
    +    int size = reqsize + CLICK_SZ;
    +    void *ptr;
    +
    +    ap_block_alarms();
    +    ptr = malloc(size);
    +    if (ptr == NULL) {
    +	fputs("Ouch!  Out of memory!\n", stderr);
    +	exit(1);
    +    }
    +    debug_fill(ptr, size); /* might as well get uninitialized protection */
    +    *(void **)ptr = a->allocation_list;
    +    a->allocation_list = ptr;
    +    ap_unblock_alarms();
    +    return (char *)ptr + CLICK_SZ;
    +#else
    +
    +    /* Round up requested size to an even number of alignment units (core clicks)
    +     */
    +
    +    int nclicks = 1 + ((reqsize - 1) / CLICK_SZ);
    +    int size = nclicks * CLICK_SZ;
    +
    +    /* First, see if we have space in the block most recently
    +     * allocated to this pool
    +     */
    +
    +    union block_hdr *blok = a->last;
    +    char *first_avail = blok->h.first_avail;
    +    char *new_first_avail;
    +
    +    if (reqsize <= 0)
    +	return NULL;
    +
    +    new_first_avail = first_avail + size;
    +
    +    if (new_first_avail <= blok->h.endp) {
    +	debug_verify_filled(first_avail, blok->h.endp,
    +	    "Ouch!  Someone trounced past the end of their allocation!\n");
    +	blok->h.first_avail = new_first_avail;
    +	return (void *) first_avail;
    +    }
    +
    +    /* Nope --- get a new one that's guaranteed to be big enough */
    +
    +    ap_block_alarms();
    +
    +    (void) ap_acquire_mutex(alloc_mutex);
    +
    +    blok = new_block(size);
    +    a->last->h.next = blok;
    +    a->last = blok;
    +#ifdef POOL_DEBUG
    +    blok->h.owning_pool = a;
    +#endif
    +
    +    (void) ap_release_mutex(alloc_mutex);
    +
    +    ap_unblock_alarms();
    +
    +    first_avail = blok->h.first_avail;
    +    blok->h.first_avail += size;
    +
    +    return (void *) first_avail;
    +#endif
    +}
    +
    +API_EXPORT(void *) ap_pcalloc(struct pool *a, int size)
    +{
    +    void *res = ap_palloc(a, size);
    +    memset(res, '\0', size);
    +    return res;
    +}
    +
    +API_EXPORT(char *) ap_pstrdup(struct pool *a, const char *s)
    +{
    +    char *res;
    +    size_t len;
    +
    +    if (s == NULL)
    +	return NULL;
    +    len = strlen(s) + 1;
    +    res = ap_palloc(a, len);
    +    memcpy(res, s, len);
    +    return res;
    +}
    +
    +API_EXPORT(char *) ap_pstrndup(struct pool *a, const char *s, int n)
    +{
    +    char *res;
    +
    +    if (s == NULL)
    +	return NULL;
    +    res = ap_palloc(a, n + 1);
    +    memcpy(res, s, n);
    +    res[n] = '\0';
    +    return res;
    +}
    +
    +API_EXPORT_NONSTD(char *) ap_pstrcat(pool *a,...)
    +{
    +    char *cp, *argp, *res;
    +
    +    /* Pass one --- find length of required string */
    +
    +    int len = 0;
    +    va_list adummy;
    +
    +    va_start(adummy, a);
    +
    +    while ((cp = va_arg(adummy, char *)) != NULL)
    +	     len += strlen(cp);
    +
    +    va_end(adummy);
    +
    +    /* Allocate the required string */
    +
    +    res = (char *) ap_palloc(a, len + 1);
    +    cp = res;
    +    *cp = '\0';
    +
    +    /* Pass two --- copy the argument strings into the result space */
    +
    +    va_start(adummy, a);
    +
    +    while ((argp = va_arg(adummy, char *)) != NULL) {
    +	strcpy(cp, argp);
    +	cp += strlen(argp);
    +    }
    +
    +    va_end(adummy);
    +
    +    /* Return the result string */
    +
    +    return res;
    +}
    +
    +/* ap_psprintf is implemented by writing directly into the current
    + * block of the pool, starting right at first_avail.  If there's
    + * insufficient room, then a new block is allocated and the earlier
    + * output is copied over.  The new block isn't linked into the pool
    + * until all the output is done.
    + *
    + * Note that this is completely safe because nothing else can
    + * allocate in this pool while ap_psprintf is running.  alarms are
    + * blocked, and the only thing outside of alloc.c that's invoked
    + * is ap_vformatter -- which was purposefully written to be
    + * self-contained with no callouts.
    + */
    +
    +struct psprintf_data {
    +    ap_vformatter_buff vbuff;
    +#ifdef ALLOC_USE_MALLOC
    +    char *base;
    +#else
    +    union block_hdr *blok;
    +    int got_a_new_block;
    +#endif
    +};
    +
    +static int psprintf_flush(ap_vformatter_buff *vbuff)
    +{
    +    struct psprintf_data *ps = (struct psprintf_data *)vbuff;
    +#ifdef ALLOC_USE_MALLOC
    +    int size;
    +    char *ptr;
    +
    +    size = (char *)ps->vbuff.curpos - ps->base;
    +    ptr = realloc(ps->base, 2*size);
    +    if (ptr == NULL) {
    +	fputs("Ouch!  Out of memory!\n", stderr);
    +	exit(1);
    +    }
    +    ps->base = ptr;
    +    ps->vbuff.curpos = ptr + size;
    +    ps->vbuff.endpos = ptr + 2*size - 1;
    +    return 0;
    +#else
    +    union block_hdr *blok;
    +    union block_hdr *nblok;
    +    size_t cur_len;
    +    char *strp;
    +
    +    blok = ps->blok;
    +    strp = ps->vbuff.curpos;
    +    cur_len = strp - blok->h.first_avail;
    +
    +    /* must try another blok */
    +    (void) ap_acquire_mutex(alloc_mutex);
    +    nblok = new_block(2 * cur_len);
    +    (void) ap_release_mutex(alloc_mutex);
    +    memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len);
    +    ps->vbuff.curpos = nblok->h.first_avail + cur_len;
    +    /* save a byte for the NUL terminator */
    +    ps->vbuff.endpos = nblok->h.endp - 1;
    +
    +    /* did we allocate the current blok? if so free it up */
    +    if (ps->got_a_new_block) {
    +	debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
    +	(void) ap_acquire_mutex(alloc_mutex);
    +	blok->h.next = block_freelist;
    +	block_freelist = blok;
    +	(void) ap_release_mutex(alloc_mutex);
    +    }
    +    ps->blok = nblok;
    +    ps->got_a_new_block = 1;
    +    /* note that we've deliberately not linked the new block onto
    +     * the pool yet... because we may need to flush again later, and
    +     * we'd have to spend more effort trying to unlink the block.
    +     */
    +    return 0;
    +#endif
    +}
    +
    +API_EXPORT(char *) ap_pvsprintf(pool *p, const char *fmt, va_list ap)
    +{
    +#ifdef ALLOC_USE_MALLOC
    +    struct psprintf_data ps;
    +    void *ptr;
    +
    +    ap_block_alarms();
    +    ps.base = malloc(512);
    +    if (ps.base == NULL) {
    +	fputs("Ouch!  Out of memory!\n", stderr);
    +	exit(1);
    +    }
    +    /* need room at beginning for allocation_list */
    +    ps.vbuff.curpos = ps.base + CLICK_SZ;
    +    ps.vbuff.endpos = ps.base + 511;
    +    ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
    +    *ps.vbuff.curpos++ = '\0';
    +    ptr = ps.base;
    +    /* shrink */
    +    ptr = realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
    +    if (ptr == NULL) {
    +	fputs("Ouch!  Out of memory!\n", stderr);
    +	exit(1);
    +    }
    +    *(void **)ptr = p->allocation_list;
    +    p->allocation_list = ptr;
    +    ap_unblock_alarms();
    +    return (char *)ptr + CLICK_SZ;
    +#else
    +    struct psprintf_data ps;
    +    char *strp;
    +    int size;
    +
    +    ap_block_alarms();
    +    ps.blok = p->last;
    +    ps.vbuff.curpos = ps.blok->h.first_avail;
    +    ps.vbuff.endpos = ps.blok->h.endp - 1;	/* save one for NUL */
    +    ps.got_a_new_block = 0;
    +
    +    ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
    +
    +    strp = ps.vbuff.curpos;
    +    *strp++ = '\0';
    +
    +    size = strp - ps.blok->h.first_avail;
    +    size = (1 + ((size - 1) / CLICK_SZ)) * CLICK_SZ;
    +    strp = ps.blok->h.first_avail;	/* save away result pointer */
    +    ps.blok->h.first_avail += size;
    +
    +    /* have to link the block in if it's a new one */
    +    if (ps.got_a_new_block) {
    +	p->last->h.next = ps.blok;
    +	p->last = ps.blok;
    +#ifdef POOL_DEBUG
    +	ps.blok->h.owning_pool = p;
    +#endif
    +    }
    +    ap_unblock_alarms();
    +
    +    return strp;
    +#endif
    +}
    +
    +API_EXPORT_NONSTD(char *) ap_psprintf(pool *p, const char *fmt, ...)
    +{
    +    va_list ap;
    +    char *res;
    +
    +    va_start(ap, fmt);
    +    res = ap_pvsprintf(p, fmt, ap);
    +    va_end(ap);
    +    return res;
    +}
    +
    +/*****************************************************************
    + *
    + * The 'array' functions...
    + */
    +
    +static void make_array_core(array_header *res, pool *p, int nelts, int elt_size)
    +{
    +    if (nelts < 1)
    +	nelts = 1;		/* Assure sanity if someone asks for
    +				 * array of zero elts.
    +				 */
    +
    +    res->elts = ap_pcalloc(p, nelts * elt_size);
    +
    +    res->pool = p;
    +    res->elt_size = elt_size;
    +    res->nelts = 0;		/* No active elements yet... */
    +    res->nalloc = nelts;	/* ...but this many allocated */
    +}
    +
    +API_EXPORT(array_header *) ap_make_array(pool *p, int nelts, int elt_size)
    +{
    +    array_header *res = (array_header *) ap_palloc(p, sizeof(array_header));
    +
    +    make_array_core(res, p, nelts, elt_size);
    +    return res;
    +}
    +
    +API_EXPORT(void *) ap_push_array(array_header *arr)
    +{
    +    if (arr->nelts == arr->nalloc) {
    +	int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2;
    +	char *new_data;
    +
    +	new_data = ap_pcalloc(arr->pool, arr->elt_size * new_size);
    +
    +	memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size);
    +	arr->elts = new_data;
    +	arr->nalloc = new_size;
    +    }
    +
    +    ++arr->nelts;
    +    return arr->elts + (arr->elt_size * (arr->nelts - 1));
    +}
    +
    +API_EXPORT(void) ap_array_cat(array_header *dst, const array_header *src)
    +{
    +    int elt_size = dst->elt_size;
    +
    +    if (dst->nelts + src->nelts > dst->nalloc) {
    +	int new_size = (dst->nalloc <= 0) ? 1 : dst->nalloc * 2;
    +	char *new_data;
    +
    +	while (dst->nelts + src->nelts > new_size)
    +	    new_size *= 2;
    +
    +	new_data = ap_pcalloc(dst->pool, elt_size * new_size);
    +	memcpy(new_data, dst->elts, dst->nalloc * elt_size);
    +
    +	dst->elts = new_data;
    +	dst->nalloc = new_size;
    +    }
    +
    +    memcpy(dst->elts + dst->nelts * elt_size, src->elts, elt_size * src->nelts);
    +    dst->nelts += src->nelts;
    +}
    +
    +API_EXPORT(array_header *) ap_copy_array(pool *p, const array_header *arr)
    +{
    +    array_header *res = ap_make_array(p, arr->nalloc, arr->elt_size);
    +
    +    memcpy(res->elts, arr->elts, arr->elt_size * arr->nelts);
    +    res->nelts = arr->nelts;
    +    return res;
    +}
    +
    +/* This cute function copies the array header *only*, but arranges
    + * for the data section to be copied on the first push or arraycat.
    + * It's useful when the elements of the array being copied are
    + * read only, but new stuff *might* get added on the end; we have the
    + * overhead of the full copy only where it is really needed.
    + */
    +
    +static ap_inline void copy_array_hdr_core(array_header *res,
    +    const array_header *arr)
    +{
    +    res->elts = arr->elts;
    +    res->elt_size = arr->elt_size;
    +    res->nelts = arr->nelts;
    +    res->nalloc = arr->nelts;	/* Force overflow on push */
    +}
    +
    +API_EXPORT(array_header *) ap_copy_array_hdr(pool *p, const array_header *arr)
    +{
    +    array_header *res = (array_header *) ap_palloc(p, sizeof(array_header));
    +
    +    res->pool = p;
    +    copy_array_hdr_core(res, arr);
    +    return res;
    +}
    +
    +/* The above is used here to avoid consing multiple new array bodies... */
    +
    +API_EXPORT(array_header *) ap_append_arrays(pool *p,
    +					 const array_header *first,
    +					 const array_header *second)
    +{
    +    array_header *res = ap_copy_array_hdr(p, first);
    +
    +    ap_array_cat(res, second);
    +    return res;
    +}
    +
    +
    +/*****************************************************************
    + *
    + * The "table" functions.
    + */
    +
    +/* XXX: if you tweak this you should look at is_empty_table() and table_elts()
    + * in alloc.h */
    +struct table {
    +    /* This has to be first to promote backwards compatibility with
    +     * older modules which cast a table * to an array_header *...
    +     * they should use the table_elts() function for most of the
    +     * cases they do this for.
    +     */
    +    array_header a;
    +#ifdef MAKE_TABLE_PROFILE
    +    void *creator;
    +#endif
    +};
    +
    +#ifdef MAKE_TABLE_PROFILE
    +static table_entry *table_push(table *t)
    +{
    +    if (t->a.nelts == t->a.nalloc) {
    +	fprintf(stderr,
    +	    "table_push: table created by %p hit limit of %u\n",
    +	    t->creator, t->a.nalloc);
    +    }
    +    return (table_entry *) ap_push_array(&t->a);
    +}
    +#else
    +#define table_push(t)	((table_entry *) ap_push_array(&(t)->a))
    +#endif
    +
    +
    +API_EXPORT(table *) ap_make_table(pool *p, int nelts)
    +{
    +    table *t = ap_palloc(p, sizeof(table));
    +
    +    make_array_core(&t->a, p, nelts, sizeof(table_entry));
    +#ifdef MAKE_TABLE_PROFILE
    +    t->creator = __builtin_return_address(0);
    +#endif
    +    return t;
    +}
    +
    +API_EXPORT(table *) ap_copy_table(pool *p, const table *t)
    +{
    +    table *new = ap_palloc(p, sizeof(table));
    +
    +#ifdef POOL_DEBUG
    +    /* we don't copy keys and values, so it's necessary that t->a.pool
    +     * have a life span at least as long as p
    +     */
    +    if (!ap_pool_is_ancestor(t->a.pool, p)) {
    +	fprintf(stderr, "copy_table: t's pool is not an ancestor of p\n");
    +	abort();
    +    }
    +#endif
    +    make_array_core(&new->a, p, t->a.nalloc, sizeof(table_entry));
    +    memcpy(new->a.elts, t->a.elts, t->a.nelts * sizeof(table_entry));
    +    new->a.nelts = t->a.nelts;
    +    return new;
    +}
    +
    +API_EXPORT(void) ap_clear_table(table *t)
    +{
    +    t->a.nelts = 0;
    +}
    +
    +API_EXPORT(char *) ap_table_get(const table *t, const char *key)
    +{
    +    table_entry *elts = (table_entry *) t->a.elts;
    +    int i;
    +
    +    if (key == NULL)
    +	return NULL;
    +
    +    for (i = 0; i < t->a.nelts; ++i)
    +	if (!strcasecmp(elts[i].key, key))
    +	    return elts[i].val;
    +
    +    return NULL;
    +}
    +
    +API_EXPORT(void) ap_table_set(table *t, const char *key, const char *val)
    +{
    +    register int i, j, k;
    +    table_entry *elts = (table_entry *) t->a.elts;
    +    int done = 0;
    +
    +    for (i = 0; i < t->a.nelts; ) {
    +	if (!strcasecmp(elts[i].key, key)) {
    +	    if (!done) {
    +		elts[i].val = ap_pstrdup(t->a.pool, val);
    +		done = 1;
    +		++i;
    +	    }
    +	    else {		/* delete an extraneous element */
    +		for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
    +		    elts[j].key = elts[k].key;
    +		    elts[j].val = elts[k].val;
    +		}
    +		--t->a.nelts;
    +	    }
    +	}
    +	else {
    +	    ++i;
    +	}
    +    }
    +
    +    if (!done) {
    +	elts = (table_entry *) table_push(t);
    +	elts->key = ap_pstrdup(t->a.pool, key);
    +	elts->val = ap_pstrdup(t->a.pool, val);
    +    }
    +}
    +
    +API_EXPORT(void) ap_table_setn(table *t, const char *key, const char *val)
    +{
    +    register int i, j, k;
    +    table_entry *elts = (table_entry *) t->a.elts;
    +    int done = 0;
    +
    +#ifdef POOL_DEBUG
    +    {
    +	if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.pool)) {
    +	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
    +	    abort();
    +	}
    +	if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.pool)) {
    +	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
    +	    abort();
    +	}
    +    }
    +#endif
    +
    +    for (i = 0; i < t->a.nelts; ) {
    +	if (!strcasecmp(elts[i].key, key)) {
    +	    if (!done) {
    +		elts[i].val = (char *)val;
    +		done = 1;
    +		++i;
    +	    }
    +	    else {		/* delete an extraneous element */
    +		for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
    +		    elts[j].key = elts[k].key;
    +		    elts[j].val = elts[k].val;
    +		}
    +		--t->a.nelts;
    +	    }
    +	}
    +	else {
    +	    ++i;
    +	}
    +    }
    +
    +    if (!done) {
    +	elts = (table_entry *) table_push(t);
    +	elts->key = (char *)key;
    +	elts->val = (char *)val;
    +    }
    +}
    +
    +API_EXPORT(void) ap_table_unset(table *t, const char *key)
    +{
    +    register int i, j, k;
    +    table_entry *elts = (table_entry *) t->a.elts;
    +
    +    for (i = 0; i < t->a.nelts;) {
    +	if (!strcasecmp(elts[i].key, key)) {
    +
    +	    /* found an element to skip over
    +	     * there are any number of ways to remove an element from
    +	     * a contiguous block of memory.  I've chosen one that
    +	     * doesn't do a memcpy/bcopy/array_delete, *shrug*...
    +	     */
    +	    for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
    +		elts[j].key = elts[k].key;
    +		elts[j].val = elts[k].val;
    +	    }
    +	    --t->a.nelts;
    +	}
    +	else {
    +	    ++i;
    +	}
    +    }
    +}
    +
    +API_EXPORT(void) ap_table_merge(table *t, const char *key, const char *val)
    +{
    +    table_entry *elts = (table_entry *) t->a.elts;
    +    int i;
    +
    +    for (i = 0; i < t->a.nelts; ++i)
    +	if (!strcasecmp(elts[i].key, key)) {
    +	    elts[i].val = ap_pstrcat(t->a.pool, elts[i].val, ", ", val, NULL);
    +	    return;
    +	}
    +
    +    elts = (table_entry *) table_push(t);
    +    elts->key = ap_pstrdup(t->a.pool, key);
    +    elts->val = ap_pstrdup(t->a.pool, val);
    +}
    +
    +API_EXPORT(void) ap_table_mergen(table *t, const char *key, const char *val)
    +{
    +    table_entry *elts = (table_entry *) t->a.elts;
    +    int i;
    +
    +#ifdef POOL_DEBUG
    +    {
    +	if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.pool)) {
    +	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
    +	    abort();
    +	}
    +	if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.pool)) {
    +	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
    +	    abort();
    +	}
    +    }
    +#endif
    +
    +    for (i = 0; i < t->a.nelts; ++i) {
    +	if (!strcasecmp(elts[i].key, key)) {
    +	    elts[i].val = ap_pstrcat(t->a.pool, elts[i].val, ", ", val, NULL);
    +	    return;
    +	}
    +    }
    +
    +    elts = (table_entry *) table_push(t);
    +    elts->key = (char *)key;
    +    elts->val = (char *)val;
    +}
    +
    +API_EXPORT(void) ap_table_add(table *t, const char *key, const char *val)
    +{
    +    table_entry *elts = (table_entry *) t->a.elts;
    +
    +    elts = (table_entry *) table_push(t);
    +    elts->key = ap_pstrdup(t->a.pool, key);
    +    elts->val = ap_pstrdup(t->a.pool, val);
    +}
    +
    +API_EXPORT(void) ap_table_addn(table *t, const char *key, const char *val)
    +{
    +    table_entry *elts = (table_entry *) t->a.elts;
    +
    +#ifdef POOL_DEBUG
    +    {
    +	if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.pool)) {
    +	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
    +	    abort();
    +	}
    +	if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.pool)) {
    +	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
    +	    abort();
    +	}
    +    }
    +#endif
    +
    +    elts = (table_entry *) table_push(t);
    +    elts->key = (char *)key;
    +    elts->val = (char *)val;
    +}
    +
    +API_EXPORT(table *) ap_overlay_tables(pool *p, const table *overlay, const table *base)
    +{
    +    table *res;
    +
    +#ifdef POOL_DEBUG
    +    /* we don't copy keys and values, so it's necessary that
    +     * overlay->a.pool and base->a.pool have a life span at least
    +     * as long as p
    +     */
    +    if (!ap_pool_is_ancestor(overlay->a.pool, p)) {
    +	fprintf(stderr, "overlay_tables: overlay's pool is not an ancestor of p\n");
    +	abort();
    +    }
    +    if (!ap_pool_is_ancestor(base->a.pool, p)) {
    +	fprintf(stderr, "overlay_tables: base's pool is not an ancestor of p\n");
    +	abort();
    +    }
    +#endif
    +
    +    res = ap_palloc(p, sizeof(table));
    +    /* behave like append_arrays */
    +    res->a.pool = p;
    +    copy_array_hdr_core(&res->a, &overlay->a);
    +    ap_array_cat(&res->a, &base->a);
    +
    +    return res;
    +}
    +
    +/* And now for something completely abstract ...
    +
    + * For each key value given as a vararg:
    + *   run the function pointed to as
    + *     int comp(void *r, char *key, char *value);
    + *   on each valid key-value pair in the table t that matches the vararg key,
    + *   or once for every valid key-value pair if the vararg list is empty,
    + *   until the function returns false (0) or we finish the table.
    + *
    + * Note that we restart the traversal for each vararg, which means that
    + * duplicate varargs will result in multiple executions of the function
    + * for each matching key.  Note also that if the vararg list is empty,
    + * only one traversal will be made and will cut short if comp returns 0.
    + *
    + * Note that the table_get and table_merge functions assume that each key in
    + * the table is unique (i.e., no multiple entries with the same key).  This
    + * function does not make that assumption, since it (unfortunately) isn't
    + * true for some of Apache's tables.
    + *
    + * Note that rec is simply passed-on to the comp function, so that the
    + * caller can pass additional info for the task.
    + */
    +API_EXPORT(void) ap_table_do(int (*comp) (void *, const char *, const char *), void *rec,
    +	      const table *t,...)
    +{
    +    va_list vp;
    +    char *argp;
    +    table_entry *elts = (table_entry *) t->a.elts;
    +    int rv, i;
    +
    +    va_start(vp, t);
    +
    +    argp = va_arg(vp, char *);
    +
    +    do {
    +	for (rv = 1, i = 0; rv && (i < t->a.nelts); ++i) {
    +	    if (elts[i].key && (!argp || !strcasecmp(elts[i].key, argp))) {
    +		rv = (*comp) (rec, elts[i].key, elts[i].val);
    +	    }
    +	}
    +    } while (argp && ((argp = va_arg(vp, char *)) != NULL));
    +
    +    va_end(vp);
    +}
    +
    +/*****************************************************************
    + *
    + * Managing generic cleanups.  
    + */
    +
    +struct cleanup {
    +    void *data;
    +    void (*plain_cleanup) (void *);
    +    void (*child_cleanup) (void *);
    +    struct cleanup *next;
    +};
    +
    +API_EXPORT(void) ap_register_cleanup(pool *p, void *data, void (*plain_cleanup) (void *),
    +				  void (*child_cleanup) (void *))
    +{
    +    struct cleanup *c = (struct cleanup *) ap_palloc(p, sizeof(struct cleanup));
    +    c->data = data;
    +    c->plain_cleanup = plain_cleanup;
    +    c->child_cleanup = child_cleanup;
    +    c->next = p->cleanups;
    +    p->cleanups = c;
    +}
    +
    +API_EXPORT(void) ap_kill_cleanup(pool *p, void *data, void (*cleanup) (void *))
    +{
    +    struct cleanup *c = p->cleanups;
    +    struct cleanup **lastp = &p->cleanups;
    +
    +    while (c) {
    +	if (c->data == data && c->plain_cleanup == cleanup) {
    +	    *lastp = c->next;
    +	    break;
    +	}
    +
    +	lastp = &c->next;
    +	c = c->next;
    +    }
    +}
    +
    +API_EXPORT(void) ap_run_cleanup(pool *p, void *data, void (*cleanup) (void *))
    +{
    +    ap_block_alarms();		/* Run cleanup only once! */
    +    (*cleanup) (data);
    +    ap_kill_cleanup(p, data, cleanup);
    +    ap_unblock_alarms();
    +}
    +
    +static void run_cleanups(struct cleanup *c)
    +{
    +    while (c) {
    +	(*c->plain_cleanup) (c->data);
    +	c = c->next;
    +    }
    +}
    +
    +static void run_child_cleanups(struct cleanup *c)
    +{
    +    while (c) {
    +	(*c->child_cleanup) (c->data);
    +	c = c->next;
    +    }
    +}
    +
    +static void cleanup_pool_for_exec(pool *p)
    +{
    +    run_child_cleanups(p->cleanups);
    +    p->cleanups = NULL;
    +
    +    for (p = p->sub_pools; p; p = p->sub_next)
    +	cleanup_pool_for_exec(p);
    +}
    +
    +API_EXPORT(void) ap_cleanup_for_exec(void)
    +{
    +#ifndef WIN32
    +    /*
    +     * Don't need to do anything on NT, because I
    +     * am actually going to spawn the new process - not
    +     * exec it. All handles that are not inheritable, will
    +     * be automajically closed. The only problem is with
    +     * file handles that are open, but there isn't much
    +     * I can do about that (except if the child decides
    +     * to go out and close them
    +     */
    +    ap_block_alarms();
    +    cleanup_pool_for_exec(permanent_pool);
    +    ap_unblock_alarms();
    +#endif /* ndef WIN32 */
    +}
    +
    +API_EXPORT_NONSTD(void) ap_null_cleanup(void *data)
    +{
    +    /* do nothing cleanup routine */
    +}
    +
    +/*****************************************************************
    + *
    + * Files and file descriptors; these are just an application of the
    + * generic cleanup interface.
    + */
    +
    +static void fd_cleanup(void *fdv)
    +{
    +    close((int) (long) fdv);
    +}
    +
    +API_EXPORT(void) ap_note_cleanups_for_fd(pool *p, int fd)
    +{
    +    ap_register_cleanup(p, (void *) (long) fd, fd_cleanup, fd_cleanup);
    +}
    +
    +API_EXPORT(void) ap_kill_cleanups_for_fd(pool *p, int fd)
    +{
    +    ap_kill_cleanup(p, (void *) (long) fd, fd_cleanup);
    +}
    +
    +API_EXPORT(int) ap_popenf(pool *a, const char *name, int flg, int mode)
    +{
    +    int fd;
    +    int save_errno;
    +
    +    ap_block_alarms();
    +    fd = open(name, flg, mode);
    +    save_errno = errno;
    +    if (fd >= 0) {
    +	fd = ap_slack(fd, AP_SLACK_HIGH);
    +	ap_note_cleanups_for_fd(a, fd);
    +    }
    +    ap_unblock_alarms();
    +    errno = save_errno;
    +    return fd;
    +}
    +
    +API_EXPORT(int) ap_pclosef(pool *a, int fd)
    +{
    +    int res;
    +    int save_errno;
    +
    +    ap_block_alarms();
    +    res = close(fd);
    +    save_errno = errno;
    +    ap_kill_cleanup(a, (void *) (long) fd, fd_cleanup);
    +    ap_unblock_alarms();
    +    errno = save_errno;
    +    return res;
    +}
    +
    +#ifdef WIN32
    +static void h_cleanup(void *fdv)
    +{
    +    CloseHandle((HANDLE) fdv);
    +}
    +
    +API_EXPORT(void) ap_note_cleanups_for_h(pool *p, HANDLE hDevice)
    +{
    +    ap_register_cleanup(p, (void *) hDevice, h_cleanup, h_cleanup);
    +}
    +
    +API_EXPORT(int) ap_pcloseh(pool *a, HANDLE hDevice)
    +{
    +    int res=0;
    +    int save_errno;
    +
    +    ap_block_alarms();
    +    
    +    if (!CloseHandle(hDevice)) {
    +        res = GetLastError();
    +    }
    +    
    +    save_errno = errno;
    +    ap_kill_cleanup(a, (void *) hDevice, h_cleanup);
    +    ap_unblock_alarms();
    +    errno = save_errno;
    +    return res;
    +}
    +#endif
    +
    +/* Note that we have separate plain_ and child_ cleanups for FILE *s,
    + * since fclose() would flush I/O buffers, which is extremely undesirable;
    + * we just close the descriptor.
    + */
    +
    +static void file_cleanup(void *fpv)
    +{
    +    fclose((FILE *) fpv);
    +}
    +static void file_child_cleanup(void *fpv)
    +{
    +    close(fileno((FILE *) fpv));
    +}
    +
    +API_EXPORT(void) ap_note_cleanups_for_file(pool *p, FILE *fp)
    +{
    +    ap_register_cleanup(p, (void *) fp, file_cleanup, file_child_cleanup);
    +}
    +
    +API_EXPORT(FILE *) ap_pfopen(pool *a, const char *name, const char *mode)
    +{
    +    FILE *fd = NULL;
    +    int baseFlag, desc;
    +    int modeFlags = 0;
    +
    +#ifdef WIN32
    +    modeFlags = _S_IREAD | _S_IWRITE;
    +#else
    +    modeFlags = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
    +#endif
    +
    +    ap_block_alarms();
    +
    +    if (*mode == 'a') {
    +	/* Work around faulty implementations of fopen */
    +	baseFlag = (*(mode + 1) == '+') ? O_RDWR : O_WRONLY;
    +	desc = open(name, baseFlag | O_APPEND | O_CREAT,
    +		    modeFlags);
    +	if (desc >= 0) {
    +	    desc = ap_slack(desc, AP_SLACK_LOW);
    +	    fd = ap_fdopen(desc, mode);
    +	}
    +    }
    +    else {
    +	fd = fopen(name, mode);
    +    }
    +
    +    if (fd != NULL)
    +	ap_note_cleanups_for_file(a, fd);
    +    ap_unblock_alarms();
    +    return fd;
    +}
    +
    +API_EXPORT(FILE *) ap_pfdopen(pool *a, int fd, const char *mode)
    +{
    +    FILE *f;
    +
    +    ap_block_alarms();
    +    f = ap_fdopen(fd, mode);
    +    if (f != NULL)
    +	ap_note_cleanups_for_file(a, f);
    +    ap_unblock_alarms();
    +    return f;
    +}
    +
    +
    +API_EXPORT(int) ap_pfclose(pool *a, FILE *fd)
    +{
    +    int res;
    +
    +    ap_block_alarms();
    +    res = fclose(fd);
    +    ap_kill_cleanup(a, (void *) fd, file_cleanup);
    +    ap_unblock_alarms();
    +    return res;
    +}
    +
    +/*
    + * DIR * with cleanup
    + */
    +
    +static void dir_cleanup(void *dv)
    +{
    +    closedir((DIR *) dv);
    +}
    +
    +API_EXPORT(DIR *) ap_popendir(pool *p, const char *name)
    +{
    +    DIR *d;
    +    int save_errno;
    +
    +    ap_block_alarms();
    +    d = opendir(name);
    +    if (d == NULL) {
    +	save_errno = errno;
    +	ap_unblock_alarms();
    +	errno = save_errno;
    +	return NULL;
    +    }
    +    ap_register_cleanup(p, (void *) d, dir_cleanup, dir_cleanup);
    +    ap_unblock_alarms();
    +    return d;
    +}
    +
    +API_EXPORT(void) ap_pclosedir(pool *p, DIR * d)
    +{
    +    ap_block_alarms();
    +    ap_kill_cleanup(p, (void *) d, dir_cleanup);
    +    closedir(d);
    +    ap_unblock_alarms();
    +}
    +
    +/*****************************************************************
    + *
    + * Files and file descriptors; these are just an application of the
    + * generic cleanup interface.
    + */
    +
    +static void socket_cleanup(void *fdv)
    +{
    +    closesocket((int) (long) fdv);
    +}
    +
    +API_EXPORT(void) ap_note_cleanups_for_socket(pool *p, int fd)
    +{
    +    ap_register_cleanup(p, (void *) (long) fd, socket_cleanup, socket_cleanup);
    +}
    +
    +API_EXPORT(void) ap_kill_cleanups_for_socket(pool *p, int sock)
    +{
    +    ap_kill_cleanup(p, (void *) (long) sock, socket_cleanup);
    +}
    +
    +API_EXPORT(int) ap_psocket(pool *p, int domain, int type, int protocol)
    +{
    +    int fd;
    +
    +    ap_block_alarms();
    +    fd = socket(domain, type, protocol);
    +    if (fd == -1) {
    +	int save_errno = errno;
    +	ap_unblock_alarms();
    +	errno = save_errno;
    +	return -1;
    +    }
    +    ap_note_cleanups_for_socket(p, fd);
    +    ap_unblock_alarms();
    +    return fd;
    +}
    +
    +API_EXPORT(int) ap_pclosesocket(pool *a, int sock)
    +{
    +    int res;
    +    int save_errno;
    +
    +    ap_block_alarms();
    +    res = closesocket(sock);
    +#ifdef WIN32
    +    errno = WSAGetLastError();
    +#endif /* WIN32 */
    +    save_errno = errno;
    +    ap_kill_cleanup(a, (void *) (long) sock, socket_cleanup);
    +    ap_unblock_alarms();
    +    errno = save_errno;
    +    return res;
    +}
    +
    +
    +/*
    + * Here's a pool-based interface to POSIX regex's regcomp().
    + * Note that we return regex_t instead of being passed one.
    + * The reason is that if you use an already-used regex_t structure,
    + * the memory that you've already allocated gets forgotten, and
    + * regfree() doesn't clear it. So we don't allow it.
    + */
    +
    +static void regex_cleanup(void *preg)
    +{
    +    regfree((regex_t *) preg);
    +}
    +
    +API_EXPORT(regex_t *) ap_pregcomp(pool *p, const char *pattern, int cflags)
    +{
    +    regex_t *preg = ap_palloc(p, sizeof(regex_t));
    +
    +    if (regcomp(preg, pattern, cflags))
    +	return NULL;
    +
    +    ap_register_cleanup(p, (void *) preg, regex_cleanup, regex_cleanup);
    +
    +    return preg;
    +}
    +
    +
    +API_EXPORT(void) ap_pregfree(pool *p, regex_t * reg)
    +{
    +    ap_block_alarms();
    +    regfree(reg);
    +    ap_kill_cleanup(p, (void *) reg, regex_cleanup);
    +    ap_unblock_alarms();
    +}
    +
    +/*****************************************************************
    + *
    + * More grotty system stuff... subprocesses.  Frump.  These don't use
    + * the generic cleanup interface because I don't want multiple
    + * subprocesses to result in multiple three-second pauses; the
    + * subprocesses have to be "freed" all at once.  If someone comes
    + * along with another resource they want to allocate which has the
    + * same property, we might want to fold support for that into the
    + * generic interface, but for now, it's a special case
    + */
    +
    +struct process_chain {
    +    pid_t pid;
    +    enum kill_conditions kill_how;
    +    struct process_chain *next;
    +};
    +
    +API_EXPORT(void) ap_note_subprocess(pool *a, int pid, enum kill_conditions how)
    +{
    +    struct process_chain *new =
    +    (struct process_chain *) ap_palloc(a, sizeof(struct process_chain));
    +
    +    new->pid = pid;
    +    new->kill_how = how;
    +    new->next = a->subprocesses;
    +    a->subprocesses = new;
    +}
    +
    +#ifdef WIN32
    +#define os_pipe(fds) _pipe(fds, 512, O_BINARY | O_NOINHERIT)
    +#else
    +#define os_pipe(fds) pipe(fds)
    +#endif /* WIN32 */
    +
    +/* for ap_fdopen, to get binary mode */
    +#if defined (__EMX__) || defined (WIN32)
    +#define BINMODE	"b"
    +#else
    +#define BINMODE
    +#endif
    +
    +static int spawn_child_err_core(pool *p, int (*func) (void *, child_info *),
    +				void *data,enum kill_conditions kill_how,
    +				int *pipe_in, int *pipe_out, int *pipe_err)
    +{
    +    int pid;
    +    int in_fds[2];
    +    int out_fds[2];
    +    int err_fds[2];
    +    int save_errno;
    +
    +    if (pipe_in && os_pipe(in_fds) < 0) {
    +	return 0;
    +    }
    +
    +    if (pipe_out && os_pipe(out_fds) < 0) {
    +	save_errno = errno;
    +	if (pipe_in) {
    +	    close(in_fds[0]);
    +	    close(in_fds[1]);
    +	}
    +	errno = save_errno;
    +	return 0;
    +    }
    +
    +    if (pipe_err && os_pipe(err_fds) < 0) {
    +	save_errno = errno;
    +	if (pipe_in) {
    +	    close(in_fds[0]);
    +	    close(in_fds[1]);
    +	}
    +	if (pipe_out) {
    +	    close(out_fds[0]);
    +	    close(out_fds[1]);
    +	}
    +	errno = save_errno;
    +	return 0;
    +    }
    +
    +#ifdef WIN32
    +
    +    {
    +	HANDLE thread_handle;
    +	int hStdIn, hStdOut, hStdErr;
    +	int old_priority;
    +
    +	(void) ap_acquire_mutex(spawn_mutex);
    +	thread_handle = GetCurrentThread();	/* doesn't need to be closed */
    +	old_priority = GetThreadPriority(thread_handle);
    +	SetThreadPriority(thread_handle, THREAD_PRIORITY_HIGHEST);
    +	/* Now do the right thing with your pipes */
    +	if (pipe_in) {
    +	    hStdIn = dup(fileno(stdin));
    +	    if(dup2(in_fds[0], fileno(stdin)))
    +		ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "dup2(stdin) failed");
    +	    close(in_fds[0]);
    +	}
    +	if (pipe_out) {
    +	    hStdOut = dup(fileno(stdout));
    +	    close(fileno(stdout));
    +	    if(dup2(out_fds[1], fileno(stdout)))
    +		ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "dup2(stdout) failed");
    +	    close(out_fds[1]);
    +	}
    +	if (pipe_err) {
    +	    hStdErr = dup(fileno(stderr));
    +	    if(dup2(err_fds[1], fileno(stderr)))
    +		ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "dup2(stdin) failed");
    +	    close(err_fds[1]);
    +	}
    +
    +	pid = (*func) (data, NULL);
    +        if (pid == -1) pid = 0;   /* map Win32 error code onto Unix default */
    +
    +        if (!pid) {
    +	    save_errno = errno;
    +	    close(in_fds[1]);
    +	    close(out_fds[0]);
    +	    close(err_fds[0]);
    +	}
    +
    +	/* restore the original stdin, stdout and stderr */
    +	if (pipe_in) {
    +	    dup2(hStdIn, fileno(stdin));
    +	    close(hStdIn);
    +        }
    +	if (pipe_out) {
    +	    dup2(hStdOut, fileno(stdout));
    +	    close(hStdOut);
    +	}
    +	if (pipe_err) {
    +	    dup2(hStdErr, fileno(stderr));
    +	    close(hStdErr);
    +	}
    +
    +        if (pid) {
    +	    ap_note_subprocess(p, pid, kill_how);
    +	    if (pipe_in) {
    +		*pipe_in = in_fds[1];
    +	    }
    +	    if (pipe_out) {
    +		*pipe_out = out_fds[0];
    +	    }
    +	    if (pipe_err) {
    +		*pipe_err = err_fds[0];
    +	    }
    +	}
    +	SetThreadPriority(thread_handle, old_priority);
    +	(void) ap_release_mutex(spawn_mutex);
    +	/*
    +	 * go on to the end of the function, where you can
    +	 * unblock alarms and return the pid
    +	 */
    +
    +    }
    +#else
    +
    +    if ((pid = fork()) < 0) {
    +	save_errno = errno;
    +	if (pipe_in) {
    +	    close(in_fds[0]);
    +	    close(in_fds[1]);
    +	}
    +	if (pipe_out) {
    +	    close(out_fds[0]);
    +	    close(out_fds[1]);
    +	}
    +	if (pipe_err) {
    +	    close(err_fds[0]);
    +	    close(err_fds[1]);
    +	}
    +	errno = save_errno;
    +	return 0;
    +    }
    +
    +    if (!pid) {
    +	/* Child process */
    +	RAISE_SIGSTOP(SPAWN_CHILD);
    +
    +	if (pipe_out) {
    +	    close(out_fds[0]);
    +	    dup2(out_fds[1], STDOUT_FILENO);
    +	    close(out_fds[1]);
    +	}
    +
    +	if (pipe_in) {
    +	    close(in_fds[1]);
    +	    dup2(in_fds[0], STDIN_FILENO);
    +	    close(in_fds[0]);
    +	}
    +
    +	if (pipe_err) {
    +	    close(err_fds[0]);
    +	    dup2(err_fds[1], STDERR_FILENO);
    +	    close(err_fds[1]);
    +	}
    +
    +	/* HP-UX SIGCHLD fix goes here, if someone will remind me what it is... */
    +	signal(SIGCHLD, SIG_DFL);	/* Was that it? */
    +
    +	func(data, NULL);
    +	exit(1);		/* Should only get here if the exec in func() failed */
    +    }
    +
    +    /* Parent process */
    +
    +    ap_note_subprocess(p, pid, kill_how);
    +
    +    if (pipe_out) {
    +	close(out_fds[1]);
    +	*pipe_out = out_fds[0];
    +    }
    +
    +    if (pipe_in) {
    +	close(in_fds[0]);
    +	*pipe_in = in_fds[1];
    +    }
    +
    +    if (pipe_err) {
    +	close(err_fds[1]);
    +	*pipe_err = err_fds[0];
    +    }
    +#endif /* WIN32 */
    +
    +    return pid;
    +}
    +
    +
    +API_EXPORT(int) ap_spawn_child_err(pool *p, int (*func) (void *, child_info *),
    +				   void *data, enum kill_conditions kill_how,
    +				   FILE **pipe_in, FILE **pipe_out,
    +				   FILE **pipe_err)
    +{
    +    int fd_in, fd_out, fd_err;
    +    int pid, save_errno;
    +
    +    ap_block_alarms();
    +
    +    pid = spawn_child_err_core(p, func, data, kill_how,
    +			       pipe_in ? &fd_in : NULL,
    +			       pipe_out ? &fd_out : NULL,
    +			       pipe_err ? &fd_err : NULL);
    +
    +    if (pid == 0) {
    +	save_errno = errno;
    +	ap_unblock_alarms();
    +	errno = save_errno;
    +	return 0;
    +    }
    +
    +    if (pipe_out) {
    +	*pipe_out = ap_fdopen(fd_out, "r" BINMODE);
    +	if (*pipe_out)
    +	    ap_note_cleanups_for_file(p, *pipe_out);
    +	else
    +	    close(fd_out);
    +    }
    +
    +    if (pipe_in) {
    +	*pipe_in = ap_fdopen(fd_in, "w" BINMODE);
    +	if (*pipe_in)
    +	    ap_note_cleanups_for_file(p, *pipe_in);
    +	else
    +	    close(fd_in);
    +    }
    +
    +    if (pipe_err) {
    +	*pipe_err = ap_fdopen(fd_err, "r" BINMODE);
    +	if (*pipe_err)
    +	    ap_note_cleanups_for_file(p, *pipe_err);
    +	else
    +	    close(fd_err);
    +    }
    +
    +    ap_unblock_alarms();
    +    return pid;
    +}
    +
    +API_EXPORT(int) ap_spawn_child_err_buff(pool *p, int (*func) (void *, child_info *), void *data,
    +					enum kill_conditions kill_how,
    +					BUFF **pipe_in, BUFF **pipe_out, BUFF **pipe_err)
    +{
    +#ifdef WIN32
    +    SECURITY_ATTRIBUTES sa = {0};  
    +    HANDLE hPipeOutputRead  = NULL;
    +    HANDLE hPipeOutputWrite = NULL;
    +    HANDLE hPipeInputRead   = NULL;
    +    HANDLE hPipeInputWrite  = NULL;
    +    HANDLE hPipeErrorRead   = NULL;
    +    HANDLE hPipeErrorWrite  = NULL;
    +    int pid = 0;
    +    child_info info;
    +
    +
    +    ap_block_alarms();
    +
    +    /*
    +     *  First thing to do is to create the pipes that we will use for stdin, stdout, and
    +     *  stderr in the child process.
    +     */      
    +    sa.nLength = sizeof(sa);
    +    sa.bInheritHandle = TRUE;
    +    sa.lpSecurityDescriptor = NULL;
    +
    +
    +    /* Create pipes for standard input/output/error redirection. */
    +    if (pipe_in && !CreatePipe(&hPipeInputRead, &hPipeInputWrite, &sa, 0))
    +	return 0;
    +
    +    if (pipe_out && !CreatePipe(&hPipeOutputRead, &hPipeOutputWrite, &sa, 0)) {
    +	if(pipe_in) {
    +	    CloseHandle(hPipeInputRead);
    +	    CloseHandle(hPipeInputWrite);
    +	}
    +	return 0;
    +    }
    +
    +    if (pipe_err && !CreatePipe(&hPipeErrorRead, &hPipeErrorWrite, &sa, 0)) {
    +	if(pipe_in) {
    +	    CloseHandle(hPipeInputRead);
    +	    CloseHandle(hPipeInputWrite);
    +	}
    +	if(pipe_out) {
    +	    CloseHandle(hPipeOutputRead);
    +	    CloseHandle(hPipeOutputWrite);
    +	}
    +	return 0;
    +    }
    +
    +    /* The script writes stdout to this pipe handle */
    +    info.hPipeOutputWrite = hPipeOutputWrite;  
    +
    +    /* The script reads stdin from this pipe handle */
    +    info.hPipeInputRead = hPipeInputRead;
    +
    +    /* The script writes stderr to this pipe handle */
    +    info.hPipeErrorWrite = hPipeErrorWrite;    
    +     
    +    /*
    +     *  Try to launch the CGI.  Under the covers, this call 
    +     *  will try to pick up the appropriate interpreter if 
    +     *  one is needed.
    +     */
    +    pid = func(data, &info);
    +    if (pid == -1) {
    +        /* Things didn't work, so cleanup */
    +        pid = 0;   /* map Win32 error code onto Unix default */
    +        CloseHandle(hPipeOutputRead);
    +        CloseHandle(hPipeInputWrite);
    +        CloseHandle(hPipeErrorRead);
    +    }
    +    else {
    +        if (pipe_out) {
    +            /*
    +             *  This pipe represents stdout for the script, 
    +             *  so we read from this pipe.
    +             */
    +	    /* Create a read buffer */
    +            *pipe_out = ap_bcreate(p, B_RD);
    +
    +	    /* Setup the cleanup routine for the handle */
    +            ap_note_cleanups_for_h(p, hPipeOutputRead);   
    +
    +	    /* Associate the handle with the new buffer */
    +            ap_bpushh(*pipe_out, hPipeOutputRead);
    +        }
    +        
    +        if (pipe_in) {
    +            /*
    +             *  This pipe represents stdin for the script, so we 
    +             *  write to this pipe.
    +             */
    +	    /* Create a write buffer */
    +            *pipe_in = ap_bcreate(p, B_WR);             
    +
    +	    /* Setup the cleanup routine for the handle */
    +            ap_note_cleanups_for_h(p, hPipeInputWrite);
    +
    +	    /* Associate the handle with the new buffer */
    +            ap_bpushh(*pipe_in, hPipeInputWrite);
    +
    +        }
    +      
    +        if (pipe_err) {
    +            /*
    +             *  This pipe represents stderr for the script, so 
    +             *  we read from this pipe.
    +             */
    +	    /* Create a read buffer */
    +            *pipe_err = ap_bcreate(p, B_RD);
    +
    +	    /* Setup the cleanup routine for the handle */
    +            ap_note_cleanups_for_h(p, hPipeErrorRead);
    +
    +	    /* Associate the handle with the new buffer */
    +            ap_bpushh(*pipe_err, hPipeErrorRead);
    +        }
    +    }  
    +
    +
    +    /*
    +     * Now that handles have been inherited, close them to be safe.
    +     * You don't want to read or write to them accidentally, and we
    +     * sure don't want to have a handle leak.
    +     */
    +    CloseHandle(hPipeOutputWrite);
    +    CloseHandle(hPipeInputRead);
    +    CloseHandle(hPipeErrorWrite);
    +
    +#else
    +    int fd_in, fd_out, fd_err;
    +    int pid, save_errno;
    +
    +    ap_block_alarms();
    +
    +    pid = spawn_child_err_core(p, func, data, kill_how,
    +			       pipe_in ? &fd_in : NULL,
    +			       pipe_out ? &fd_out : NULL,
    +			       pipe_err ? &fd_err : NULL);
    +
    +    if (pid == 0) {
    +	save_errno = errno;
    +	ap_unblock_alarms();
    +	errno = save_errno;
    +	return 0;
    +    }
    +
    +    if (pipe_out) {
    +	*pipe_out = ap_bcreate(p, B_RD);
    +	ap_note_cleanups_for_fd(p, fd_out);
    +	ap_bpushfd(*pipe_out, fd_out, fd_out);
    +    }
    +
    +    if (pipe_in) {
    +	*pipe_in = ap_bcreate(p, B_WR);
    +	ap_note_cleanups_for_fd(p, fd_in);
    +	ap_bpushfd(*pipe_in, fd_in, fd_in);
    +    }
    +
    +    if (pipe_err) {
    +	*pipe_err = ap_bcreate(p, B_RD);
    +	ap_note_cleanups_for_fd(p, fd_err);
    +	ap_bpushfd(*pipe_err, fd_err, fd_err);
    +    }
    +#endif
    +
    +    ap_unblock_alarms();
    +    return pid;
    +}
    +
    +static void free_proc_chain(struct process_chain *procs)
    +{
    +    /* Dispose of the subprocesses we've spawned off in the course of
    +     * whatever it was we're cleaning up now.  This may involve killing
    +     * some of them off...
    +     */
    +
    +    struct process_chain *p;
    +    int need_timeout = 0;
    +    int status;
    +
    +    if (procs == NULL)
    +	return;			/* No work.  Whew! */
    +
    +    /* First, check to see if we need to do the SIGTERM, sleep, SIGKILL
    +     * dance with any of the processes we're cleaning up.  If we've got
    +     * any kill-on-sight subprocesses, ditch them now as well, so they
    +     * don't waste any more cycles doing whatever it is that they shouldn't
    +     * be doing anymore.
    +     */
    +#ifdef WIN32
    +    /* Pick up all defunct processes */
    +    for (p = procs; p; p = p->next) {
    +	if (GetExitCodeProcess((HANDLE) p->pid, &status)) {
    +	    p->kill_how = kill_never;
    +	}
    +    }
    +
    +
    +    for (p = procs; p; p = p->next) {
    +	if (p->kill_how == kill_after_timeout) {
    +	    need_timeout = 1;
    +	}
    +	else if (p->kill_how == kill_always) {
    +	    TerminateProcess((HANDLE) p->pid, 1);
    +	}
    +    }
    +    /* Sleep only if we have to... */
    +
    +    if (need_timeout)
    +	sleep(3);
    +
    +    /* OK, the scripts we just timed out for have had a chance to clean up
    +     * --- now, just get rid of them, and also clean up the system accounting
    +     * goop...
    +     */
    +
    +    for (p = procs; p; p = p->next) {
    +	if (p->kill_how == kill_after_timeout)
    +	    TerminateProcess((HANDLE) p->pid, 1);
    +    }
    +
    +    for (p = procs; p; p = p->next) {
    +	CloseHandle((HANDLE) p->pid);
    +    }
    +#else
    +#ifndef NEED_WAITPID
    +    /* Pick up all defunct processes */
    +    for (p = procs; p; p = p->next) {
    +	if (waitpid(p->pid, (int *) 0, WNOHANG) > 0) {
    +	    p->kill_how = kill_never;
    +	}
    +    }
    +#endif
    +
    +    for (p = procs; p; p = p->next) {
    +	if ((p->kill_how == kill_after_timeout)
    +	    || (p->kill_how == kill_only_once)) {
    +	    /* Subprocess may be dead already.  Only need the timeout if not. */
    +	    if (kill(p->pid, SIGTERM) != -1)
    +		need_timeout = 1;
    +	}
    +	else if (p->kill_how == kill_always) {
    +	    kill(p->pid, SIGKILL);
    +	}
    +    }
    +
    +    /* Sleep only if we have to... */
    +
    +    if (need_timeout)
    +	sleep(3);
    +
    +    /* OK, the scripts we just timed out for have had a chance to clean up
    +     * --- now, just get rid of them, and also clean up the system accounting
    +     * goop...
    +     */
    +
    +    for (p = procs; p; p = p->next) {
    +
    +	if (p->kill_how == kill_after_timeout)
    +	    kill(p->pid, SIGKILL);
    +
    +	if (p->kill_how != kill_never)
    +	    waitpid(p->pid, &status, 0);
    +    }
    +#endif /* WIN32 */
    +}
    diff --git a/APACHE_1_3b7/src/main/buff.c b/APACHE_1_3b7/src/main/buff.c
    new file mode 100644
    index 0000000000..8011a2e6fd
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/buff.c
    @@ -0,0 +1,1563 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1998 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/>.
    + *
    + */
    +
    +#include "httpd.h"
    +#include "http_main.h"
    +#include "http_log.h"
    +
    +#include <errno.h>
    +#include <stdio.h>
    +#include <stdarg.h>
    +#include <string.h>
    +#ifndef NO_WRITEV
    +#include <sys/types.h>
    +#include <sys/uio.h>
    +#endif
    +
    +#ifdef HAVE_BSTRING_H
    +#include <bstring.h>		/* for IRIX, FD_SET calls bzero() */
    +#endif
    +
    +#ifndef DEFAULT_BUFSIZE
    +#define DEFAULT_BUFSIZE (4096)
    +#endif
    +/* This must be enough to represent (DEFAULT_BUFSIZE - 3) in hex,
    + * plus two extra characters.
    + */
    +#ifndef CHUNK_HEADER_SIZE
    +#define CHUNK_HEADER_SIZE (5)
    +#endif
    +
    +
    +/* bwrite()s of greater than this size can result in a large_write() call,
    + * which can result in a writev().  It's a little more work to set up the
    + * writev() rather than copy bytes into the buffer, so we don't do it for small
    + * writes.  This is especially important when chunking (which is a very likely
    + * source of small writes if it's a module using ap_bputc/ap_bputs)...because we
    + * have the expense of actually building two chunks for each writev().
    + */
    +#ifndef LARGE_WRITE_THRESHOLD
    +#define LARGE_WRITE_THRESHOLD 31
    +#endif
    +
    +
    +/*
    + * Buffered I/O routines.
    + * These are a replacement for the stdio routines.
    + * Advantages:
    + *  Known semantics for handling of file-descriptors (on close etc.)
    + *  No problems reading and writing simultanously to the same descriptor
    + *  No limits on the number of open file handles.
    + *  Only uses memory resources; no need to ensure the close routine
    + *  is called.
    + *  Extra code could be inserted between the buffered and un-buffered routines.
    + *  Timeouts could be handled by using select or poll before read or write.
    + *  Extra error handling could be introduced; e.g.
    + *   keep an address to which we should longjump(), or
    + *   keep a stack of routines to call on error.
    + */
    +
    +/* Notes:
    + *  On reading EOF, EOF will set in the flags and no further Input will
    + * be done.
    + *
    + * On an error except for EAGAIN, ERROR will be set in the flags and no
    + * futher I/O will be done
    + */
    +
    +#ifdef WIN32
    +
    +/*
    +  select() sometimes returns 1 even though the write will block. We must work around this.
    +*/
    +
    +int sendwithtimeout(int sock, const char *buf, int len, int flags)
    +{
    +    int iostate = 1;
    +    fd_set fdset;
    +    struct timeval tv;
    +    int err = WSAEWOULDBLOCK;
    +    int rv;
    +    int retry;
    +
    +    if (!(tv.tv_sec = ap_check_alarm()))
    +	return (send(sock, buf, len, flags));
    +
    +    rv = ioctlsocket(sock, FIONBIO, &iostate);
    +    iostate = 0;
    +    if (rv) {
    +	err = WSAGetLastError();
    +	ap_assert(0);
    +    }
    +    rv = send(sock, buf, len, flags);
    +    if (rv == SOCKET_ERROR) {
    +	err = WSAGetLastError();
    +	if (err == WSAEWOULDBLOCK)
    +	    do {
    +		retry=0;
    +
    +		FD_ZERO(&fdset);
    +		FD_SET(sock, &fdset);
    +		tv.tv_usec = 0;
    +		rv = select(FD_SETSIZE, NULL, &fdset, NULL, &tv);
    +		if (rv == SOCKET_ERROR)
    +		    err = WSAGetLastError();
    +		else if (rv == 0) {
    + 		    ioctlsocket(sock, FIONBIO, &iostate);
    +		    if(ap_check_alarm() < 0) {
    +			WSASetLastError(EINTR);	/* Simulate an alarm() */
    +			return (SOCKET_ERROR);
    +		    }
    +		}
    +		else {
    +		    rv = send(sock, buf, len, flags);
    +		    if (rv == SOCKET_ERROR) {
    +		        err = WSAGetLastError();
    +			if(err == WSAEWOULDBLOCK) {
    +			    ap_log_error(APLOG_MARK,APLOG_DEBUG,NULL,
    +				"select claimed we could write, but in fact we couldn't. This is a bug in Windows.");
    +			    retry=1;
    +			    Sleep(100);
    +			}
    +		    }
    +		}
    +	    } while(retry);
    +    }
    +    ioctlsocket(sock, FIONBIO, &iostate);
    +    if (rv == SOCKET_ERROR)
    +	WSASetLastError(err);
    +    return (rv);
    +}
    +
    +
    +int recvwithtimeout(int sock, char *buf, int len, int flags)
    +{
    +    int iostate = 1;
    +    fd_set fdset;
    +    struct timeval tv;
    +    int err = WSAEWOULDBLOCK;
    +    int rv;
    +
    +    if (!(tv.tv_sec = ap_check_alarm()))
    +	return (recv(sock, buf, len, flags));
    +
    +    rv = ioctlsocket(sock, FIONBIO, &iostate);
    +    iostate = 0;
    +    ap_assert(!rv);
    +    rv = recv(sock, buf, len, flags);
    +    if (rv == SOCKET_ERROR) {
    +	err = WSAGetLastError();
    +	if (err == WSAEWOULDBLOCK) {
    +	    FD_ZERO(&fdset);
    +	    FD_SET(sock, &fdset);
    +	    tv.tv_usec = 0;
    +	    rv = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
    +	    if (rv == SOCKET_ERROR)
    +		err = WSAGetLastError();
    +	    else if (rv == 0) {
    +		ioctlsocket(sock, FIONBIO, &iostate);
    +		ap_check_alarm();
    +		WSASetLastError(WSAEWOULDBLOCK);
    +		return (SOCKET_ERROR);
    +	    }
    +	    else {
    +		rv = recv(sock, buf, len, flags);
    +		if (rv == SOCKET_ERROR)
    +		    err = WSAGetLastError();
    +	    }
    +	}
    +    }
    +    ioctlsocket(sock, FIONBIO, &iostate);
    +    if (rv == SOCKET_ERROR)
    +	WSASetLastError(err);
    +    return (rv);
    +}
    +
    +#endif /* WIN32 */
    +
    +
    +/* the lowest level reading primitive */
    +static int ap_read(BUFF *fb, void *buf, int nbyte)
    +{
    +    int rv;
    +    
    +#ifdef WIN32
    +    if (fb->hFH != INVALID_HANDLE_VALUE) {
    +        if (!ReadFile(fb->hFH,buf,nbyte,&rv,NULL))
    +            rv = -1;
    +    }
    +    else
    +#endif
    +	rv = read(fb->fd_in, buf, nbyte);
    +    
    +    return rv;
    +}
    +
    +static ap_inline int buff_read(BUFF *fb, void *buf, int nbyte)
    +{
    +    int rv;
    +
    +#if defined (WIN32)
    +    if (fb->flags & B_SOCKET) {
    +	rv = recvwithtimeout(fb->fd_in, buf, nbyte, 0);
    +	if (rv == SOCKET_ERROR)
    +	    errno = WSAGetLastError();
    +    }
    +    else
    +	rv = ap_read(fb, buf, nbyte);
    +#else
    +    rv = ap_read(fb, buf, nbyte);
    +#endif /* WIN32 */
    +    return rv;
    +}
    +
    +/* the lowest level writing primitive */
    +static int ap_write(BUFF *fb, const void *buf, int nbyte)
    +{
    +    int rv;
    +    
    +#ifdef WIN32
    +    if (fb->hFH != INVALID_HANDLE_VALUE) {
    +        if (!WriteFile(fb->hFH,buf,nbyte,&rv,NULL))
    +          rv = -1;
    +    }
    +    else
    +#endif
    +#if defined (B_SFIO)
    +	rv = sfwrite(fb->sf_out, buf, nbyte);
    +#else
    +	rv = write(fb->fd, buf, nbyte);
    +#endif
    +    
    +    return rv;
    +}
    +
    +static ap_inline int buff_write(BUFF *fb, const void *buf, int nbyte)
    +{
    +    int rv;
    +
    +#if defined(WIN32)
    +    if (fb->flags & B_SOCKET) {
    +	rv = sendwithtimeout(fb->fd, buf, nbyte, 0);
    +	if (rv == SOCKET_ERROR)
    +	    errno = WSAGetLastError();
    +    }
    +    else
    +	rv = ap_write(fb, buf, nbyte);
    +#else
    +    rv = ap_write(fb, buf, nbyte);
    +#endif /* WIN32 */
    +    return rv;
    +}
    +
    +static void doerror(BUFF *fb, int direction)
    +{
    +    int errsave = errno;	/* Save errno to prevent overwriting it below */
    +
    +    fb->flags |= (direction == B_RD ? B_RDERR : B_WRERR);
    +    if (fb->error != NULL)
    +	(*fb->error) (fb, direction, fb->error_data);
    +
    +    errno = errsave;
    +}
    +
    +/* Buffering routines */
    +/*
    + * Create a new buffered stream
    + */
    +API_EXPORT(BUFF *) ap_bcreate(pool *p, int flags)
    +{
    +    BUFF *fb;
    +
    +    fb = ap_palloc(p, sizeof(BUFF));
    +    fb->pool = p;
    +    fb->bufsiz = DEFAULT_BUFSIZE;
    +    fb->flags = flags & (B_RDWR | B_SOCKET);
    +
    +    if (flags & B_RD)
    +	fb->inbase = ap_palloc(p, fb->bufsiz);
    +    else
    +	fb->inbase = NULL;
    +
    +    /* overallocate so that we can put a chunk trailer of CRLF into this
    +     * buffer */
    +    if (flags & B_WR)
    +	fb->outbase = ap_palloc(p, fb->bufsiz + 2);
    +    else
    +	fb->outbase = NULL;
    +
    +#ifdef CHARSET_EBCDIC
    +    fb->flags |= (flags & B_SOCKET) ? (B_EBCDIC2ASCII | B_ASCII2EBCDIC) : 0;
    +#endif /*CHARSET_EBCDIC*/
    +
    +    fb->inptr = fb->inbase;
    +
    +    fb->incnt = 0;
    +    fb->outcnt = 0;
    +    fb->outchunk = -1;
    +    fb->error = NULL;
    +    fb->bytes_sent = 0L;
    +
    +    fb->fd = -1;
    +    fb->fd_in = -1;
    +#ifdef WIN32
    +    fb->hFH = INVALID_HANDLE_VALUE;
    +#endif
    +
    +#ifdef B_SFIO
    +    fb->sf_in = NULL;
    +    fb->sf_out = NULL;
    +    fb->sf_in = sfnew(fb->sf_in, NIL(Void_t *),
    +		      (size_t) SF_UNBOUND, 0, SF_READ);
    +    fb->sf_out = sfnew(fb->sf_out, NIL(Void_t *),
    +		       (size_t) SF_UNBOUND, 1, SF_WRITE);
    +#endif
    +
    +    return fb;
    +}
    +
    +/*
    + * Push some I/O file descriptors onto the stream
    + */
    +API_EXPORT(void) ap_bpushfd(BUFF *fb, int fd_in, int fd_out)
    +{
    +    fb->fd = fd_out;
    +    fb->fd_in = fd_in;
    +}
    +
    +#ifdef WIN32
    +/*
    + * Push some Win32 handles onto the stream.
    + */
    +API_EXPORT(void) ap_bpushh(BUFF *fb, HANDLE hFH)
    +{
    +    fb->hFH = hFH;
    +}
    +#endif
    +
    +API_EXPORT(int) ap_bsetopt(BUFF *fb, int optname, const void *optval)
    +{
    +    if (optname == BO_BYTECT) {
    +	fb->bytes_sent = *(const long int *) optval - (long int) fb->outcnt;;
    +	return 0;
    +    }
    +    else {
    +	errno = EINVAL;
    +	return -1;
    +    }
    +}
    +
    +API_EXPORT(int) ap_bgetopt(BUFF *fb, int optname, void *optval)
    +{
    +    if (optname == BO_BYTECT) {
    +	long int bs = fb->bytes_sent + fb->outcnt;
    +	if (bs < 0L)
    +	    bs = 0L;
    +	*(long int *) optval = bs;
    +	return 0;
    +    }
    +    else {
    +	errno = EINVAL;
    +	return -1;
    +    }
    +}
    +
    +static int bflush_core(BUFF *fb);
    +
    +/*
    + * Start chunked encoding.
    + *
    + * Note that in order for ap_bputc() to be an efficient macro we have to guarantee
    + * that start_chunk() has always been called on the buffer before we leave any
    + * routine in this file.  Said another way, if a routine here uses end_chunk()
    + * and writes something on the wire, then it has to call start_chunk() or set
    + * an error condition before returning.
    + */
    +static void start_chunk(BUFF *fb)
    +{
    +    if (fb->outchunk != -1) {
    +	/* already chunking */
    +	return;
    +    }
    +    if (!(fb->flags & B_WR) || (fb->flags & (B_WRERR | B_EOUT))) {
    +	/* unbuffered writes */
    +	return;
    +    }
    +
    +    /* we need at least the header_len + at least 1 data byte
    +     * remember that we've overallocated fb->outbase so that we can always
    +     * fit the two byte CRLF trailer
    +     */
    +    if (fb->bufsiz - fb->outcnt < CHUNK_HEADER_SIZE + 1) {
    +	bflush_core(fb);
    +    }
    +    fb->outchunk = fb->outcnt;
    +    fb->outcnt += CHUNK_HEADER_SIZE;
    +}
    +
    +
    +/*
    + * end a chunk -- tweak the chunk_header from start_chunk, and add a trailer
    + */
    +static void end_chunk(BUFF *fb)
    +{
    +    int i;
    +    unsigned char *strp;
    +
    +    if (fb->outchunk == -1) {
    +	/* not chunking */
    +	return;
    +    }
    +
    +    if (fb->outchunk + CHUNK_HEADER_SIZE == fb->outcnt) {
    +	/* nothing was written into this chunk, and we can't write a 0 size
    +	 * chunk because that signifies EOF, so just erase it
    +	 */
    +	fb->outcnt = fb->outchunk;
    +	fb->outchunk = -1;
    +	return;
    +    }
    +
    +    /* we know this will fit because of how we wrote it in start_chunk() */
    +    i = ap_snprintf((char *) &fb->outbase[fb->outchunk], CHUNK_HEADER_SIZE,
    +		"%x", fb->outcnt - fb->outchunk - CHUNK_HEADER_SIZE);
    +
    +    /* we may have to tack some trailing spaces onto the number we just wrote
    +     * in case it was smaller than our estimated size.  We've also written
    +     * a \0 into the buffer with ap_snprintf so we might have to put a
    +     * \r back in.
    +     */
    +    strp = &fb->outbase[fb->outchunk + i];
    +    while (i < CHUNK_HEADER_SIZE - 2) {
    +	*strp++ = ' ';
    +	++i;
    +    }
    +    *strp++ = '\015';
    +    *strp = '\012';
    +#ifdef CHARSET_EBCDIC
    +    /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
    +    ebcdic2ascii(&fb->outbase[fb->outchunk], &fb->outbase[fb->outchunk], CHUNK_HEADER_SIZE);
    +#endif /*CHARSET_EBCDIC*/
    +
    +    /* tack on the trailing CRLF, we've reserved room for this */
    +    fb->outbase[fb->outcnt++] = '\015';
    +    fb->outbase[fb->outcnt++] = '\012';
    +
    +    fb->outchunk = -1;
    +}
    +
    +
    +/*
    + * Set a flag on (1) or off (0).
    + */
    +API_EXPORT(int) ap_bsetflag(BUFF *fb, int flag, int value)
    +{
    +    if (value) {
    +	fb->flags |= flag;
    +	if (flag & B_CHUNK) {
    +	    start_chunk(fb);
    +	}
    +    }
    +    else {
    +	fb->flags &= ~flag;
    +	if (flag & B_CHUNK) {
    +	    end_chunk(fb);
    +	}
    +    }
    +    return value;
    +}
    +
    +
    +API_EXPORT(int) ap_bnonblock(BUFF *fb, int direction)
    +{
    +    int fd;
    +
    +    fd = (direction == B_RD) ? fb->fd_in : fb->fd;
    +#if defined(O_NONBLOCK)
    +    return fcntl(fd, F_SETFL, O_NONBLOCK);
    +#elif defined(F_NDELAY)
    +    return fcntl(fd, F_SETFL, F_NDELAY);
    +#else
    +    /* XXXX: this breaks things, but an alternative isn't obvious...*/
    +    return 0;
    +#endif
    +}
    +
    +API_EXPORT(int) ap_bfileno(BUFF *fb, int direction)
    +{
    +    return (direction == B_RD) ? fb->fd_in : fb->fd;
    +}
    +
    +/*
    + * This is called instead of read() everywhere in here.  It implements
    + * the B_SAFEREAD functionality -- which is to force a flush() if a read()
    + * would block.  It also deals with the EINTR errno result from read().
    + * return code is like read() except EINTR is eliminated.
    + */
    +
    +
    +#if !defined (B_SFIO) || defined (WIN32)
    +#define saferead saferead_guts
    +#else
    +static int saferead(BUFF *fb, char *buf, int nbyte)
    +{
    +    return sfread(fb->sf_in, buf, nbyte);
    +}
    +#endif
    +
    +
    +/* note we assume the caller has ensured that fb->fd_in <= FD_SETSIZE */
    +API_EXPORT(void) ap_bhalfduplex(BUFF *fb)
    +{
    +    int rv;
    +    fd_set fds;
    +    struct timeval tv;
    +
    +    if (fb->incnt > 0 || fb->outcnt == 0) {
    +	return;
    +    }
    +    /* test for a block */
    +    do {
    +	FD_ZERO(&fds);
    +	FD_SET(fb->fd_in, &fds);
    +	tv.tv_sec = 0;
    +	tv.tv_usec = 0;
    +	rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv);
    +    } while (rv < 0 && errno == EINTR);
    +    /* treat any error as if it would block as well */
    +    if (rv != 1) {
    +	ap_bflush(fb);
    +    }
    +}
    +
    +static ap_inline int saferead_guts(BUFF *fb, void *buf, int nbyte)
    +{
    +    int rv;
    +
    +    if (fb->flags & B_SAFEREAD) {
    +	ap_bhalfduplex(fb);
    +    }
    +    do {
    +	rv = buff_read(fb, buf, nbyte);
    +    } while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
    +    return (rv);
    +}
    +
    +#ifdef B_SFIO
    +int bsfio_read(Sfio_t * f, char *buf, int nbyte, apache_sfio *disc)
    +{
    +    int rv;
    +    BUFF *fb = disc->buff;
    +
    +    rv = saferead_guts(fb, buf, nbyte);
    +
    +    buf[rv] = '\0';
    +    f->next = 0;
    +
    +    return (rv);
    +}
    +
    +int bsfio_write(Sfio_t * f, char *buf, int nbyte, apache_sfio *disc)
    +{
    +    return ap_write(disc->buff, buf, nbyte);
    +}
    +
    +Sfdisc_t *bsfio_new(pool *p, BUFF *b)
    +{
    +    apache_sfio *disc;
    +
    +    if (!(disc = (apache_sfio *) ap_palloc(p, sizeof(apache_sfio))))
    +	            return (Sfdisc_t *) disc;
    +
    +    disc->disc.readf = (Sfread_f) bsfio_read;
    +    disc->disc.writef = (Sfwrite_f) bsfio_write;
    +    disc->disc.seekf = (Sfseek_f) NULL;
    +    disc->disc.exceptf = (Sfexcept_f) NULL;
    +    disc->buff = b;
    +
    +    return (Sfdisc_t *) disc;
    +}
    +#endif
    +
    +
    +/* A wrapper around saferead which does error checking and EOF checking
    + * yeah, it's confusing, this calls saferead, which calls buff_read...
    + * and then there's the SFIO case.  Note that saferead takes care
    + * of EINTR.
    + */
    +static int read_with_errors(BUFF *fb, void *buf, int nbyte)
    +{
    +    int rv;
    +
    +    rv = saferead(fb, buf, nbyte);
    +    if (rv == 0) {
    +	fb->flags |= B_EOF;
    +    }
    +    else if (rv == -1 && errno != EAGAIN) {
    +	doerror(fb, B_RD);
    +    }
    +    return rv;
    +}
    +
    +/*
    + * Read up to nbyte bytes into buf.
    + * If fewer than byte bytes are currently available, then return those.
    + * Returns 0 for EOF, -1 for error.
    + * NOTE EBCDIC: The readahead buffer _always_ contains *unconverted* data.
    + * Only when the caller retrieves data from the buffer (calls bread)
    + * is a conversion done, if the conversion flag is set at that time.
    + */
    +API_EXPORT(int) ap_bread(BUFF *fb, void *buf, int nbyte)
    +{
    +    int i, nrd;
    +
    +    if (fb->flags & B_RDERR)
    +	return -1;
    +    if (nbyte == 0)
    +	return 0;
    +
    +    if (!(fb->flags & B_RD)) {
    +	/* Unbuffered reading.  First check if there was something in the
    +	 * buffer from before we went unbuffered. */
    +	if (fb->incnt) {
    +	    i = (fb->incnt > nbyte) ? nbyte : fb->incnt;
    +#ifdef CHARSET_EBCDIC
    +	    if (fb->flags & B_ASCII2EBCDIC)
    +		ascii2ebcdic(buf, fb->inptr, i);
    +	    else
    +#endif /*CHARSET_EBCDIC*/
    +	    memcpy(buf, fb->inptr, i);
    +	    fb->incnt -= i;
    +	    fb->inptr += i;
    +	    return i;
    +	}
    +	i = read_with_errors(fb, buf, nbyte);
    +#ifdef CHARSET_EBCDIC
    +	if (i > 0 && bgetflag(fb, B_ASCII2EBCDIC))
    +	    ascii2ebcdic(buf, buf, i);
    +#endif /*CHARSET_EBCDIC*/
    +	return i;
    +    }
    +
    +    nrd = fb->incnt;
    +/* can we fill the buffer */
    +    if (nrd >= nbyte) {
    +#ifdef CHARSET_EBCDIC
    +	if (fb->flags & B_ASCII2EBCDIC)
    +	    ascii2ebcdic(buf, fb->inptr, nbyte);
    +	else
    +#endif /*CHARSET_EBCDIC*/
    +	memcpy(buf, fb->inptr, nbyte);
    +	fb->incnt = nrd - nbyte;
    +	fb->inptr += nbyte;
    +	return nbyte;
    +    }
    +
    +    if (nrd > 0) {
    +#ifdef CHARSET_EBCDIC
    +	if (fb->flags & B_ASCII2EBCDIC)
    +	    ascii2ebcdic(buf, fb->inptr, nrd);
    +	else
    +#endif /*CHARSET_EBCDIC*/
    +	memcpy(buf, fb->inptr, nrd);
    +	nbyte -= nrd;
    +	buf = nrd + (char *) buf;
    +	fb->incnt = 0;
    +    }
    +    if (fb->flags & B_EOF)
    +	return nrd;
    +
    +/* do a single read */
    +    if (nbyte >= fb->bufsiz) {
    +/* read directly into caller's buffer */
    +	i = read_with_errors(fb, buf, nbyte);
    +#ifdef CHARSET_EBCDIC
    +	if (i > 0 && bgetflag(fb, B_ASCII2EBCDIC))
    +	    ascii2ebcdic(buf, buf, i);
    +#endif /*CHARSET_EBCDIC*/
    +	if (i == -1) {
    +	    return nrd ? nrd : -1;
    +	}
    +    }
    +    else {
    +/* read into hold buffer, then memcpy */
    +	fb->inptr = fb->inbase;
    +	i = read_with_errors(fb, fb->inptr, fb->bufsiz);
    +	if (i == -1) {
    +	    return nrd ? nrd : -1;
    +	}
    +	fb->incnt = i;
    +	if (i > nbyte)
    +	    i = nbyte;
    +#ifdef CHARSET_EBCDIC
    +	if (fb->flags & B_ASCII2EBCDIC)
    +	    ascii2ebcdic(buf, fb->inptr, i);
    +	else
    +#endif /*CHARSET_EBCDIC*/
    +	memcpy(buf, fb->inptr, i);
    +	fb->incnt -= i;
    +	fb->inptr += i;
    +    }
    +    return nrd + i;
    +}
    +
    +
    +/*
    + * Reads from the stream into the array pointed to by buff, until
    + * a (CR)LF sequence is read, or end-of-file condition is encountered
    + * or until n-1 bytes have been stored in buff. If a CRLF sequence is
    + * read, it is replaced by a newline character.  The string is then
    + * terminated with a null character.
    + *
    + * Returns the number of bytes stored in buff, or zero on end of
    + * transmission, or -1 on an error.
    + *
    + * Notes:
    + *  If null characters are expected in the data stream, then
    + * buff should not be treated as a null terminated C string; instead
    + * the returned count should be used to determine the length of the
    + * string.
    + *  CR characters in the byte stream not immediately followed by a LF
    + * will be preserved.
    + */
    +API_EXPORT(int) ap_bgets(char *buff, int n, BUFF *fb)
    +{
    +    int i, ch, ct;
    +
    +/* Can't do bgets on an unbuffered stream */
    +    if (!(fb->flags & B_RD)) {
    +	errno = EINVAL;
    +	return -1;
    +    }
    +    if (fb->flags & B_RDERR)
    +	return -1;
    +
    +    ct = 0;
    +    i = 0;
    +    for (;;) {
    +	if (i == fb->incnt) {
    +/* no characters left */
    +	    fb->inptr = fb->inbase;
    +	    fb->incnt = 0;
    +	    if (fb->flags & B_EOF)
    +		break;
    +	    i = read_with_errors(fb, fb->inptr, fb->bufsiz);
    +	    if (i == -1) {
    +		buff[ct] = '\0';
    +		return ct ? ct : -1;
    +	    }
    +	    fb->incnt = i;
    +	    if (i == 0)
    +		break;		/* EOF */
    +	    i = 0;
    +	    continue;		/* restart with the new data */
    +	}
    +
    +	ch = fb->inptr[i++];
    +#ifndef CHARSET_EBCDIC
    +	if (ch == '\012') {	/* got LF */
    +	    if (ct == 0)
    +		buff[ct++] = '\n';
    +/* if just preceeded by CR, replace CR with LF */
    +	    else if (buff[ct - 1] == '\015')
    +		buff[ct - 1] = '\n';
    +	    else if (ct < n - 1)
    +		buff[ct++] = '\n';
    +	    else
    +		i--;		/* no room for LF */
    +	    break;
    +	}
    +#else /* an EBCDIC machine: do the same, but convert to EBCDIC on the fly: */
    +	if (fb->flags & B_ASCII2EBCDIC)
    +	    ch = os_toebcdic[(unsigned char)ch];
    +	if (ch == os_toebcdic['\012']) {  /* got LF */
    +	    if (ct == 0)
    +		buff[ct++] = '\n';
    +/* if just preceeded by CR, replace CR with LF */
    +	    else if (buff[ct - 1] == os_toebcdic['\015'])
    +		buff[ct - 1] = '\n';
    +	    else if (ct < n - 1)
    +		buff[ct++] = '\n';
    +	    else
    +		i--;		/* no room for LF */
    +	    break;
    +	}
    +#endif
    +	if (ct == n - 1) {
    +	    i--;		/* push back ch */
    +	    break;
    +	}
    +
    +	buff[ct++] = ch;
    +    }
    +    fb->incnt -= i;
    +    fb->inptr += i;
    +
    +    buff[ct] = '\0';
    +    return ct;
    +}
    +
    +/*
    + * Looks at the stream fb and places the first character into buff
    + * without removing it from the stream buffer.
    + *
    + * Returns 1 on success, zero on end of transmission, or -1 on an error.
    + *
    + */
    +API_EXPORT(int) ap_blookc(char *buff, BUFF *fb)
    +{
    +    int i;
    +
    +    *buff = '\0';
    +
    +    if (!(fb->flags & B_RD)) {	/* Can't do blookc on an unbuffered stream */
    +	errno = EINVAL;
    +	return -1;
    +    }
    +    if (fb->flags & B_RDERR)
    +	return -1;
    +
    +    if (fb->incnt == 0) {	/* no characters left in stream buffer */
    +	fb->inptr = fb->inbase;
    +	if (fb->flags & B_EOF)
    +	    return 0;
    +
    +	i = read_with_errors(fb, fb->inptr, fb->bufsiz);
    +	if (i <= 0) {
    +	    return i;
    +	}
    +	fb->incnt = i;
    +    }
    +
    +#ifndef CHARSET_EBCDIC
    +    *buff = fb->inptr[0];
    +#else /*CHARSET_EBCDIC*/
    +    *buff = (fb->flags & B_ASCII2EBCDIC)
    +	     ? os_toebcdic[(unsigned char)fb->inptr[0]]
    +	     : fb->inptr[0];
    +#endif /*CHARSET_EBCDIC*/
    +    return 1;
    +}
    +
    +/*
    + * Skip data until a linefeed character is read
    + * Returns 1 on success, 0 if no LF found, or -1 on error
    + */
    +API_EXPORT(int) ap_bskiplf(BUFF *fb)
    +{
    +    unsigned char *x;
    +    int i;
    +
    +/* Can't do bskiplf on an unbuffered stream */
    +    if (!(fb->flags & B_RD)) {
    +	errno = EINVAL;
    +	return -1;
    +    }
    +    if (fb->flags & B_RDERR)
    +	return -1;
    +
    +    for (;;) {
    +	x = (unsigned char *) memchr(fb->inptr, '\012', fb->incnt);
    +	if (x != NULL) {
    +	    x++;
    +	    fb->incnt -= x - fb->inptr;
    +	    fb->inptr = x;
    +	    return 1;
    +	}
    +
    +	fb->inptr = fb->inbase;
    +	fb->incnt = 0;
    +	if (fb->flags & B_EOF)
    +	    return 0;
    +	i = read_with_errors(fb, fb->inptr, fb->bufsiz);
    +	if (i <= 0)
    +	    return i;
    +	fb->incnt = i;
    +    }
    +}
    +
    +/*
    + * Empty the buffer after putting a single character in it
    + */
    +API_EXPORT(int) ap_bflsbuf(int c, BUFF *fb)
    +{
    +    char ss[1];
    +
    +    ss[0] = c;
    +    return ap_bwrite(fb, ss, 1);
    +}
    +
    +/*
    + * Fill the buffer and read a character from it
    + */
    +API_EXPORT(int) ap_bfilbuf(BUFF *fb)
    +{
    +    int i;
    +    char buf[1];
    +
    +    i = ap_bread(fb, buf, 1);
    +    if (i == 0)
    +	errno = 0;		/* no error; EOF */
    +    if (i != 1)
    +	return EOF;
    +    else
    +	return buf[0];
    +}
    +
    +
    +/*
    + * When doing chunked encodings we really have to write everything in the
    + * chunk before proceeding onto anything else.  This routine either writes
    + * nbytes and returns 0 or returns -1 indicating a failure.
    + *
    + * This is *seriously broken* if used on a non-blocking fd.  It will poll.
    + *
    + * Deals with calling doerror and setting bytes_sent.
    + */
    +static int write_it_all(BUFF *fb, const void *buf, int nbyte)
    +{
    +    int i;
    +
    +    if (fb->flags & (B_WRERR | B_EOUT))
    +	return -1;
    +
    +    while (nbyte > 0) {
    +	i = buff_write(fb, buf, nbyte);
    +	if (i < 0) {
    +	    if (errno != EAGAIN && errno != EINTR) {
    +		doerror(fb, B_WR);
    +		return -1;
    +	    }
    +	}
    +	else {
    +	    nbyte -= i;
    +	    buf = i + (const char *) buf;
    +	    fb->bytes_sent += i;
    +	}
    +	if (fb->flags & B_EOUT)
    +	    return -1;
    +    }
    +    return 0;
    +}
    +
    +
    +#ifndef NO_WRITEV
    +/* Similar to previous, but uses writev.  Note that it modifies vec.
    + * return 0 if successful, -1 otherwise.
    + *
    + * Deals with doerror() and bytes_sent.
    + */
    +static int writev_it_all(BUFF *fb, struct iovec *vec, int nvec)
    +{
    +    int i, rv;
    +
    +    /* while it's nice an easy to build the vector and crud, it's painful
    +     * to deal with a partial writev()
    +     */
    +    i = 0;
    +    while (i < nvec) {
    +	do
    +	    rv = writev(fb->fd, &vec[i], nvec - i);
    +	while (rv == -1 && (errno == EINTR || errno == EAGAIN)
    +	       && !(fb->flags & B_EOUT));
    +	if (rv == -1) {
    +	    if (errno != EINTR && errno != EAGAIN) {
    +		doerror(fb, B_WR);
    +	    }
    +	    return -1;
    +	}
    +	fb->bytes_sent += rv;
    +	/* recalculate vec to deal with partial writes */
    +	while (rv > 0) {
    +	    if (rv < vec[i].iov_len) {
    +		vec[i].iov_base = (char *) vec[i].iov_base + rv;
    +		vec[i].iov_len -= rv;
    +		rv = 0;
    +	    }
    +	    else {
    +		rv -= vec[i].iov_len;
    +		++i;
    +	    }
    +	}
    +	if (fb->flags & B_EOUT)
    +	    return -1;
    +    }
    +    /* if we got here, we wrote it all */
    +    return 0;
    +}
    +#endif
    +
    +/* A wrapper for buff_write which deals with error conditions and
    + * bytes_sent.  Also handles non-blocking writes.
    + */
    +static int write_with_errors(BUFF *fb, const void *buf, int nbyte)
    +{
    +    int rv;
    +
    +    do
    +	rv = buff_write(fb, buf, nbyte);
    +    while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
    +    if (rv == -1) {
    +	if (errno != EAGAIN) {
    +	    doerror(fb, B_WR);
    +	}
    +	return -1;
    +    }
    +    else if (rv == 0) {
    +	errno = EAGAIN;
    +	return -1;
    +    }
    +    fb->bytes_sent += rv;
    +    return rv;
    +}
    +
    +
    +/*
    + * A hook to write() that deals with chunking. This is really a protocol-
    + * level issue, but we deal with it here because it's simpler; this is
    + * an interim solution pending a complete rewrite of all this stuff in
    + * 2.0, using something like sfio stacked disciplines or BSD's funopen().
    + *
    + * Can be used on non-blocking descriptors, but only if they're not chunked.
    + * Deals with doerror() and bytes_sent.
    + */
    +static int bcwrite(BUFF *fb, const void *buf, int nbyte)
    +{
    +    char chunksize[16];		/* Big enough for practically anything */
    +#ifndef NO_WRITEV
    +    struct iovec vec[3];
    +#endif
    +
    +    if (fb->flags & (B_WRERR | B_EOUT))
    +	return -1;
    +
    +    if (!(fb->flags & B_CHUNK)) {
    +	return write_with_errors(fb, buf, nbyte);
    +    }
    +
    +#ifdef NO_WRITEV
    +    /* without writev() this has poor performance, too bad */
    +
    +    ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte);
    +#ifdef CHARSET_EBCDIC
    +    /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
    +    ebcdic2ascii(chunksize, chunksize, strlen(chunksize));
    +#endif /*CHARSET_EBCDIC*/
    +    if (write_it_all(fb, chunksize, strlen(chunksize)) == -1)
    +	return -1;
    +    if (write_it_all(fb, buf, nbyte) == -1)
    +	return -1;
    +    if (write_it_all(fb, "\015\012", 2) == -1)
    +	return -1;
    +    return nbyte;
    +#else
    +    vec[0].iov_base = chunksize;
    +    vec[0].iov_len = ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012",
    +				 nbyte);
    +#ifdef CHARSET_EBCDIC
    +    /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
    +    ebcdic2ascii(chunksize, chunksize, strlen(chunksize));
    +#endif /*CHARSET_EBCDIC*/
    +    vec[1].iov_base = (void *) buf;	/* cast is to avoid const warning */
    +    vec[1].iov_len = nbyte;
    +    vec[2].iov_base = "\015\012";
    +    vec[2].iov_len = 2;
    +
    +    return writev_it_all(fb, vec, (sizeof(vec) / sizeof(vec[0]))) ? -1 : nbyte;
    +#endif
    +}
    +
    +
    +#ifndef NO_WRITEV
    +/*
    + * Used to combine the contents of the fb buffer, and a large buffer
    + * passed in.
    + */
    +static int large_write(BUFF *fb, const void *buf, int nbyte)
    +{
    +    struct iovec vec[4];
    +    int nvec;
    +    char chunksize[16];
    +
    +    /* it's easiest to end the current chunk */
    +    if (fb->flags & B_CHUNK) {
    +	end_chunk(fb);
    +    }
    +    nvec = 0;
    +    if (fb->outcnt > 0) {
    +	vec[nvec].iov_base = (void *) fb->outbase;
    +	vec[nvec].iov_len = fb->outcnt;
    +	++nvec;
    +    }
    +    if (fb->flags & B_CHUNK) {
    +	vec[nvec].iov_base = chunksize;
    +	vec[nvec].iov_len = ap_snprintf(chunksize, sizeof(chunksize),
    +					"%x\015\012", nbyte);
    +#ifdef CHARSET_EBCDIC
    +    /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
    +	ebcdic2ascii(chunksize, chunksize, strlen(chunksize));
    +#endif /*CHARSET_EBCDIC*/
    +	++nvec;
    +	vec[nvec].iov_base = (void *) buf;
    +	vec[nvec].iov_len = nbyte;
    +	++nvec;
    +	vec[nvec].iov_base = "\015\012";
    +	vec[nvec].iov_len = 2;
    +	++nvec;
    +    }
    +    else {
    +	vec[nvec].iov_base = (void *) buf;
    +	vec[nvec].iov_len = nbyte;
    +	++nvec;
    +    }
    +
    +    fb->outcnt = 0;
    +    if (writev_it_all(fb, vec, nvec)) {
    +	return -1;
    +    }
    +    else if (fb->flags & B_CHUNK) {
    +	start_chunk(fb);
    +    }
    +    return nbyte;
    +}
    +#endif
    +
    +
    +/*
    + * Write nbyte bytes.
    + * Only returns fewer than nbyte if an error ocurred.
    + * Returns -1 if no bytes were written before the error ocurred.
    + * It is worth noting that if an error occurs, the buffer is in an unknown
    + * state.
    + */
    +API_EXPORT(int) ap_bwrite(BUFF *fb, const void *buf, int nbyte)
    +{
    +    int i, nwr, useable_bufsiz;
    +#ifdef CHARSET_EBCDIC
    +    static char *cbuf = NULL;
    +    static int csize = 0;
    +
    +    if (bgetflag(fb, B_EBCDIC2ASCII)) {
    +        if (nbyte > csize) {
    +            if (cbuf != NULL)
    +                free(cbuf);
    +            cbuf = malloc(csize = nbyte+HUGE_STRING_LEN);
    +            if (cbuf == NULL)
    +                csize = 0;
    +        }
    +        ebcdic2ascii((cbuf) ? cbuf : (void*)buf, buf, nbyte);
    +        buf = (cbuf) ? cbuf : buf;
    +    }
    +#endif /*CHARSET_EBCDIC*/
    +
    +    if (fb->flags & (B_WRERR | B_EOUT))
    +	return -1;
    +    if (nbyte == 0)
    +	return 0;
    +
    +    if (!(fb->flags & B_WR)) {
    +/* unbuffered write -- have to use bcwrite since we aren't taking care
    + * of chunking any other way */
    +	return bcwrite(fb, buf, nbyte);
    +    }
    +
    +#ifndef NO_WRITEV
    +/*
    + * Detect case where we're asked to write a large buffer, and combine our
    + * current buffer with it in a single writev().  Note we don't consider
    + * the case nbyte == 1 because modules which use rputc() loops will cause
    + * us to use writev() too frequently.  In those cases we really should just
    + * start a new buffer.
    + */
    +    if (fb->outcnt > 0 && nbyte > LARGE_WRITE_THRESHOLD
    +	&& nbyte + fb->outcnt >= fb->bufsiz) {
    +	return large_write(fb, buf, nbyte);
    +    }
    +#endif
    +
    +/*
    + * Whilst there is data in the buffer, keep on adding to it and writing it
    + * out
    + */
    +    nwr = 0;
    +    while (fb->outcnt > 0) {
    +/* can we accept some data? */
    +	i = fb->bufsiz - fb->outcnt;
    +	if (i > 0) {
    +	    if (i > nbyte)
    +		i = nbyte;
    +	    memcpy(fb->outbase + fb->outcnt, buf, i);
    +	    fb->outcnt += i;
    +	    nbyte -= i;
    +	    buf = i + (const char *) buf;
    +	    nwr += i;
    +	    if (nbyte == 0)
    +		return nwr;	/* return if none left */
    +	}
    +
    +/* the buffer must be full */
    +	if (fb->flags & B_CHUNK) {
    +	    end_chunk(fb);
    +	    /* it is just too painful to try to re-cram the buffer while
    +	     * chunking
    +	     */
    +	    if (write_it_all(fb, fb->outbase, fb->outcnt) == -1) {
    +		/* we cannot continue after a chunked error */
    +		return -1;
    +	    }
    +	    fb->outcnt = 0;
    +	    break;
    +	}
    +	i = write_with_errors(fb, fb->outbase, fb->outcnt);
    +	if (i <= 0) {
    +	    return nwr ? nwr : -1;
    +	}
    +
    +	/* deal with a partial write */
    +	if (i < fb->outcnt) {
    +	    int j, n = fb->outcnt;
    +	    unsigned char *x = fb->outbase;
    +	    for (j = i; j < n; j++)
    +		x[j - i] = x[j];
    +	    fb->outcnt -= i;
    +	}
    +	else
    +	    fb->outcnt = 0;
    +
    +	if (fb->flags & B_EOUT)
    +	    return -1;
    +    }
    +/* we have emptied the file buffer. Now try to write the data from the
    + * original buffer until there is less than bufsiz left.  Note that we
    + * use bcwrite() to do this for us, it will do the chunking so that
    + * we don't have to dink around building a chunk in our own buffer.
    + *
    + * Note also that bcwrite never does a partial write if we're chunking,
    + * so we're guaranteed to either end in an error state, or make it
    + * out of this loop and call start_chunk() below.
    + *
    + * Remember we may not be able to use the entire buffer if we're
    + * chunking.
    + */
    +    useable_bufsiz = fb->bufsiz;
    +    if (fb->flags & B_CHUNK) useable_bufsiz -= CHUNK_HEADER_SIZE;
    +    while (nbyte >= useable_bufsiz) {
    +	i = bcwrite(fb, buf, nbyte);
    +	if (i <= 0) {
    +	    return nwr ? nwr : -1;
    +	}
    +
    +	buf = i + (const char *) buf;
    +	nwr += i;
    +	nbyte -= i;
    +
    +	if (fb->flags & B_EOUT)
    +	    return -1;
    +    }
    +/* copy what's left to the file buffer */
    +    fb->outcnt = 0;
    +    if (fb->flags & B_CHUNK)
    +	start_chunk(fb);
    +    if (nbyte > 0)
    +	memcpy(fb->outbase + fb->outcnt, buf, nbyte);
    +    fb->outcnt += nbyte;
    +    nwr += nbyte;
    +    return nwr;
    +}
    +
    +
    +static int bflush_core(BUFF *fb)
    +{
    +    int i;
    +
    +    while (fb->outcnt > 0) {
    +	i = write_with_errors(fb, fb->outbase, fb->outcnt);
    +	if (i <= 0)
    +	    return -1;
    +
    +	/*
    +	 * We should have written all the data, but if the fd was in a
    +	 * strange (non-blocking) mode, then we might not have done so.
    +	 */
    +	if (i < fb->outcnt) {
    +	    int j, n = fb->outcnt;
    +	    unsigned char *x = fb->outbase;
    +	    for (j = i; j < n; j++)
    +		x[j - i] = x[j];
    +	}
    +	fb->outcnt -= i;
    +
    +	/* If a soft timeout occurs while flushing, the handler should
    +	 * have set the buffer flag B_EOUT.
    +	 */
    +	if (fb->flags & B_EOUT)
    +	    return -1;
    +    }
    +
    +    return 0;
    +}
    +
    +/*
    + * Flushes the buffered stream.
    + * Returns 0 on success or -1 on error
    + */
    +API_EXPORT(int) ap_bflush(BUFF *fb)
    +{
    +    int ret;
    +
    +    if (!(fb->flags & B_WR) || (fb->flags & B_EOUT))
    +	return 0;
    +
    +    if (fb->flags & B_WRERR)
    +	return -1;
    +
    +    if (fb->flags & B_CHUNK)
    +	end_chunk(fb);
    +
    +    ret = bflush_core(fb);
    +
    +    if (ret == 0 && (fb->flags & B_CHUNK)) {
    +	start_chunk(fb);
    +    }
    +
    +    return ret;
    +}
    +
    +/*
    + * Flushes and closes the file, even if an error occurred.
    + * Discards an data that was not read, or not written by bflush()
    + * Sets the EOF flag to indicate no futher data can be read,
    + * and the EOUT flag to indicate no further data can be written.
    + */
    +API_EXPORT(int) ap_bclose(BUFF *fb)
    +{
    +    int rc1, rc2, rc3;
    +
    +    if (fb->flags & B_WR)
    +	rc1 = ap_bflush(fb);
    +    else
    +	rc1 = 0;
    +#ifdef WIN32
    +    if (fb->flags & B_SOCKET) {
    +	rc2 = ap_pclosesocket(fb->pool, fb->fd);
    +	if (fb->fd_in != fb->fd) {
    +	    rc3 = ap_pclosesocket(fb->pool, fb->fd_in);
    +	}
    +	else {
    +	    rc3 = 0;
    +	}
    +    }
    +    else if (fb->hFH != INVALID_HANDLE_VALUE) {
    +	    rc2 = ap_pcloseh(fb->pool, fb->hFH);
    +	    rc3 = 0;
    +    }
    +    else {
    +#endif
    +	rc2 = ap_pclosef(fb->pool, fb->fd);
    +	if (fb->fd_in != fb->fd) {
    +	    rc3 = ap_pclosef(fb->pool, fb->fd_in);
    +	}
    +	else {
    +	    rc3 = 0;
    +	}
    +#ifdef WIN32
    +    }
    +#endif
    +
    +    fb->inptr = fb->inbase;
    +    fb->incnt = 0;
    +    fb->outcnt = 0;
    +
    +    fb->flags |= B_EOF | B_EOUT;
    +    fb->fd = -1;
    +    fb->fd_in = -1;
    +
    +#ifdef B_SFIO
    +    sfclose(fb->sf_in);
    +    sfclose(fb->sf_out);
    +#endif
    +
    +    if (rc1 != 0)
    +	return rc1;
    +    else if (rc2 != 0)
    +	return rc2;
    +    else
    +	return rc3;
    +}
    +
    +/*
    + * returns the number of bytes written or -1 on error
    + */
    +API_EXPORT(int) ap_bputs(const char *x, BUFF *fb)
    +{
    +    int i, j = strlen(x);
    +    i = ap_bwrite(fb, x, j);
    +    if (i != j)
    +	return -1;
    +    else
    +	return j;
    +}
    +
    +/*
    + * returns the number of bytes written or -1 on error
    + */
    +API_EXPORT_NONSTD(int) ap_bvputs(BUFF *fb,...)
    +{
    +    int i, j, k;
    +    va_list v;
    +    const char *x;
    +
    +    va_start(v, fb);
    +    for (k = 0;;) {
    +	x = va_arg(v, const char *);
    +	if (x == NULL)
    +	    break;
    +	j = strlen(x);
    +	i = ap_bwrite(fb, x, j);
    +	if (i != j) {
    +	    va_end(v);
    +	    return -1;
    +	}
    +	k += i;
    +    }
    +
    +    va_end(v);
    +
    +    return k;
    +}
    +
    +API_EXPORT(void) ap_bonerror(BUFF *fb, void (*error) (BUFF *, int, void *),
    +			  void *data)
    +{
    +    fb->error = error;
    +    fb->error_data = data;
    +}
    +
    +struct bprintf_data {
    +    ap_vformatter_buff vbuff;
    +    BUFF *fb;
    +};
    +
    +static int bprintf_flush(ap_vformatter_buff *vbuff)
    +{
    +    struct bprintf_data *b = (struct bprintf_data *)vbuff;
    +    BUFF *fb = b->fb;
    +
    +#ifdef CHARSET_EBCDIC
    +    /* Characters were pushed into the buffer without conversion. Do it now */
    +    if (fb->flags & B_EBCDIC2ASCII)
    +        ebcdic2ascii(&fb->outbase[fb->outcnt],
    +		     &fb->outbase[fb->outcnt],
    +		     b->vbuff.curpos - (char *)&fb->outbase[fb->outcnt]);
    +#endif /*CHARSET_EBCDIC*/
    +    fb->outcnt += b->vbuff.curpos - (char *)&fb->outbase[fb->outcnt];
    +    if (fb->outcnt == fb->bufsiz) {
    +	if (ap_bflush(fb)) {
    +	    return -1;
    +	}
    +    }
    +    vbuff->curpos = (char *)&fb->outbase[fb->outcnt];
    +    vbuff->endpos = (char *)&fb->outbase[fb->bufsiz];
    +    return 0;
    +}
    +
    +API_EXPORT_NONSTD(int) ap_bprintf(BUFF *fb, const char *fmt, ...)
    +{
    +    va_list ap;
    +    int res;
    +    struct bprintf_data b;
    +
    +    b.vbuff.curpos = (char *)&fb->outbase[fb->outcnt];
    +    b.vbuff.endpos = (char *)&fb->outbase[fb->bufsiz];
    +    b.fb = fb;
    +    va_start(ap, fmt);
    +    res = ap_vformatter(bprintf_flush, &b.vbuff, fmt, ap);
    +    va_end(ap);
    +    if (res != -1) {
    +#ifdef CHARSET_EBCDIC
    +	/* Characters were pushed into the buffer without conversion. Do it now */
    +	if (fb->flags & B_EBCDIC2ASCII)
    +	    ebcdic2ascii(&fb->outbase[fb->outcnt],
    +			 &fb->outbase[fb->outcnt],
    +			 b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt]);
    +#endif /*CHARSET_EBCDIC*/
    +	fb->outcnt += b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt];
    +    }
    +    return res;
    +}
    +
    +API_EXPORT(int) ap_vbprintf(BUFF *fb, const char *fmt, va_list ap)
    +{
    +    struct bprintf_data b;
    +    int res;
    +
    +    b.vbuff.curpos = (char *)&fb->outbase[fb->outcnt];
    +    b.vbuff.endpos = (char *)&fb->outbase[fb->bufsiz];
    +    b.fb = fb;
    +    res = ap_vformatter(bprintf_flush, &b.vbuff, fmt, ap);
    +    if (res != -1) {
    +#ifdef CHARSET_EBCDIC
    +	/* Characters were pushed into the buffer without conversion. Do it now */
    +	if (fb->flags & B_EBCDIC2ASCII)
    +	    ebcdic2ascii(&fb->outbase[fb->outcnt],
    +			 &fb->outbase[fb->outcnt],
    +			 b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt]);
    +#endif /*CHARSET_EBCDIC*/
    +	fb->outcnt += b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt];
    +    }
    +    return res;
    +}
    diff --git a/APACHE_1_3b7/src/main/fnmatch.c b/APACHE_1_3b7/src/main/fnmatch.c
    new file mode 100644
    index 0000000000..3856226468
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/fnmatch.c
    @@ -0,0 +1,213 @@
    +/*
    + * Copyright (c) 1989, 1993, 1994
    + *      The Regents of the University of California.  All rights reserved.
    + *
    + * This code is derived from software contributed to Berkeley by
    + * Guido van Rossum.
    + *
    + * 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 acknowledgement:
    + *      This product includes software developed by the University of
    + *      California, Berkeley and its contributors.
    + * 4. Neither the name of the University nor the names of its contributors
    + *    may be used to endorse or promote products derived from this software
    + *    without specific prior written permission.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    + * ANY EXPRESS 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 REGENTS OR 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.
    + */
    +
    +#if defined(LIBC_SCCS) && !defined(lint)
    +static char sccsid[] = "@(#)fnmatch.c	8.2 (Berkeley) 4/16/94";
    +#endif /* LIBC_SCCS and not lint */
    +
    +/*
    + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
    + * Compares a filename or pathname to a pattern.
    + */
    +
    +#include "conf.h"
    +#include "fnmatch.h"
    +#include <string.h>
    +
    +#define	EOS	'\0'
    +
    +static const char *rangematch(const char *, int, int);
    +
    +API_EXPORT(int) ap_fnmatch(pattern, string, flags)
    +     const char *pattern, *string;
    +     int flags;
    +{
    +    const char *stringstart;
    +    char c, test;
    +
    +    for (stringstart = string;;)
    +	switch (c = *pattern++) {
    +	case EOS:
    +	    return (*string == EOS ? 0 : FNM_NOMATCH);
    +	case '?':
    +	    if (*string == EOS)
    +		return (FNM_NOMATCH);
    +	    if (*string == '/' && (flags & FNM_PATHNAME))
    +		return (FNM_NOMATCH);
    +	    if (*string == '.' && (flags & FNM_PERIOD) &&
    +		(string == stringstart ||
    +		 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
    +		return (FNM_NOMATCH);
    +	    ++string;
    +	    break;
    +	case '*':
    +	    c = *pattern;
    +	    /* Collapse multiple stars. */
    +	    while (c == '*')
    +		c = *++pattern;
    +
    +	    if (*string == '.' && (flags & FNM_PERIOD) &&
    +		(string == stringstart ||
    +		 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
    +		return (FNM_NOMATCH);
    +
    +	    /* Optimize for pattern with * at end or before /. */
    +	    if (c == EOS) {
    +		if (flags & FNM_PATHNAME) {
    +		    return (strchr(string, '/') == NULL ?
    +			    0 : FNM_NOMATCH);
    +		}
    +		else {
    +		    return (0);
    +		}
    +	    }
    +	    else if (c == '/' && flags & FNM_PATHNAME) {
    +		if ((string = strchr(string, '/')) == NULL)
    +		    return (FNM_NOMATCH);
    +		break;
    +	    }
    +
    +	    /* General case, use recursion. */
    +	    while ((test = *string) != EOS) {
    +		if (!ap_fnmatch(pattern, string, flags & ~FNM_PERIOD))
    +		    return (0);
    +		if (test == '/' && flags & FNM_PATHNAME)
    +		    break;
    +		++string;
    +	    }
    +	    return (FNM_NOMATCH);
    +	case '[':
    +	    if (*string == EOS)
    +		return (FNM_NOMATCH);
    +	    if (*string == '/' && flags & FNM_PATHNAME)
    +		return (FNM_NOMATCH);
    +	    if (*string == '.' && (flags & FNM_PERIOD) &&
    +		(string == stringstart ||
    +		((flags & FNM_PATHNAME) && *(string - 1) == '/')))
    +		    return (FNM_NOMATCH);
    +	    if ((pattern =
    +		 rangematch(pattern, *string, flags)) == NULL)
    +		return (FNM_NOMATCH);
    +	    ++string;
    +	    break;
    +	case '\\':
    +	    if (!(flags & FNM_NOESCAPE)) {
    +		if ((c = *pattern++) == EOS) {
    +		    c = '\\';
    +		    --pattern;
    +		}
    +	    }
    +	    /* FALLTHROUGH */
    +	    default:
    +		if (c != *string++)
    +		return (FNM_NOMATCH);
    +	    break;
    +	}
    +    /* NOTREACHED */
    +}
    +
    +static const char *
    +     rangematch(pattern, test, flags)
    +     const char *pattern;
    +     int test, flags;
    +{
    +    int negate, ok;
    +    char c, c2;
    +
    +    /*
    +     * A bracket expression starting with an unquoted circumflex
    +     * character produces unspecified results (IEEE 1003.2-1992,
    +     * 3.13.2).  This implementation treats it like '!', for
    +     * consistency with the regular expression syntax.
    +     * J.T. Conklin (conklin@ngai.kaleida.com)
    +     */
    +    if ((negate = (*pattern == '!' || *pattern == '^')))
    +	++pattern;
    +
    +    for (ok = 0; (c = *pattern++) != ']';) {
    +	if (c == '\\' && !(flags & FNM_NOESCAPE))
    +	    c = *pattern++;
    +	if (c == EOS)
    +	    return (NULL);
    +	if (*pattern == '-'
    +	    && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
    +	    pattern += 2;
    +	    if (c2 == '\\' && !(flags & FNM_NOESCAPE))
    +		c2 = *pattern++;
    +	    if (c2 == EOS)
    +		return (NULL);
    +	    if (c <= test && test <= c2)
    +		ok = 1;
    +	}
    +	else if (c == test)
    +	    ok = 1;
    +    }
    +    return (ok == negate ? NULL : pattern);
    +}
    +
    +
    +/* This function is an Apache addition */
    +/* return non-zero if pattern has any glob chars in it */
    +API_EXPORT(int) ap_is_fnmatch(const char *pattern)
    +{
    +    int nesting;
    +
    +    nesting = 0;
    +    while (*pattern) {
    +	switch (*pattern) {
    +	case '?':
    +	case '*':
    +	    return 1;
    +
    +	case '\\':
    +	    if (*pattern++ == '\0') {
    +		return 0;
    +	    }
    +	    break;
    +
    +	case '[':	/* '[' is only a glob if it has a matching ']' */
    +	    ++nesting;
    +	    break;
    +
    +	case ']':
    +	    if (nesting)
    +		return 1;
    +	    break;
    +	}
    +	++pattern;
    +    }
    +    return 0;
    +}
    diff --git a/APACHE_1_3b7/src/main/gen_test_char.c b/APACHE_1_3b7/src/main/gen_test_char.c
    new file mode 100644
    index 0000000000..c72a3b5237
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/gen_test_char.c
    @@ -0,0 +1,62 @@
    +/* we need some of the portability definitions... for strchr */
    +#include "httpd.h"
    +
    +/* A bunch of functions in util.c scan strings looking for certain characters.
    + * To make that more efficient we encode a lookup table.
    + */
    +#define T_ESCAPE_SHELL_CMD	(0x01)
    +#define T_ESCAPE_PATH_SEGMENT	(0x02)
    +#define T_OS_ESCAPE_PATH	(0x04)
    +#define T_HTTP_TOKEN_STOP	(0x08)
    +
    +int main(int argc, char *argv[])
    +{
    +    unsigned c;
    +    unsigned char flags;
    +
    +    printf(
    +"/* this file is automatically generated by gen_test_char, do not edit */\n"
    +"#define T_ESCAPE_SHELL_CMD	(%u)\n"
    +"#define T_ESCAPE_PATH_SEGMENT	(%u)\n"
    +"#define T_OS_ESCAPE_PATH	(%u)\n"
    +"#define T_HTTP_TOKEN_STOP	(%u)\n"
    +"\n"
    +"static const unsigned char test_char_table[256] = {\n"
    +"    0,",
    +	T_ESCAPE_SHELL_CMD,
    +	T_ESCAPE_PATH_SEGMENT,
    +	T_OS_ESCAPE_PATH,
    +	T_HTTP_TOKEN_STOP);
    +
    +    /* we explicitly dealt with NUL above
    +     * in case some strchr() do bogosity with it */
    +
    +    for (c = 1; c < 256; ++c) {
    +	flags = 0;
    +	if (c % 20 == 0)
    +	    printf("\n    ");
    +
    +	/* escape_shell_cmd */
    +	if (strchr("&;`'\"|*?~<>^()[]{}$\\\n", c)) {
    +	    flags |= T_ESCAPE_SHELL_CMD;
    +	}
    +
    +	if (!isalnum(c) && !strchr("$-_.+!*'(),:@&=~", c)) {
    +	    flags |= T_ESCAPE_PATH_SEGMENT;
    +	}
    +
    +	if (!isalnum(c) && !strchr("$-_.+!*'(),:@&=/~", c)) {
    +	    flags |= T_OS_ESCAPE_PATH;
    +	}
    +
    +	/* these are the "tspecials" from RFC2068 */
    +	if (iscntrl(c) || strchr(" \t()<>@,;:\\/[]?={}", c)) {
    +	    flags |= T_HTTP_TOKEN_STOP;
    +	}
    +	printf("%u%c", flags, (c < 255) ? ',' : ' ');
    +
    +    }
    +    printf("\n};\n");
    +
    +    return 0;
    +}
    diff --git a/APACHE_1_3b7/src/main/gen_test_char.dsp b/APACHE_1_3b7/src/main/gen_test_char.dsp
    new file mode 100644
    index 0000000000..c2630ce9d1
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/gen_test_char.dsp
    @@ -0,0 +1,105 @@
    +# Microsoft Developer Studio Project File - Name="gen_test_char" - Package Owner=<4>
    +# Microsoft Developer Studio Generated Build File, Format Version 5.00
    +# ** DO NOT EDIT **
    +
    +# TARGTYPE "Win32 (x86) Console Application" 0x0103
    +
    +CFG=gen_test_char - Win32 Debug
    +!MESSAGE This is not a valid makefile. To build this project using NMAKE,
    +!MESSAGE use the Export Makefile command and run
    +!MESSAGE 
    +!MESSAGE NMAKE /f "gen_test_char.mak".
    +!MESSAGE 
    +!MESSAGE You can specify a configuration when running NMAKE
    +!MESSAGE by defining the macro CFG on the command line. For example:
    +!MESSAGE 
    +!MESSAGE NMAKE /f "gen_test_char.mak" CFG="gen_test_char - Win32 Debug"
    +!MESSAGE 
    +!MESSAGE Possible choices for configuration are:
    +!MESSAGE 
    +!MESSAGE "gen_test_char - Win32 Release" (based on\
    + "Win32 (x86) Console Application")
    +!MESSAGE "gen_test_char - Win32 Debug" (based on\
    + "Win32 (x86) Console Application")
    +!MESSAGE 
    +
    +# Begin Project
    +# PROP Scc_ProjName ""
    +# PROP Scc_LocalPath ""
    +CPP=cl.exe
    +RSC=rc.exe
    +
    +!IF  "$(CFG)" == "gen_test_char - Win32 Release"
    +
    +# PROP BASE Use_MFC 0
    +# PROP BASE Use_Debug_Libraries 0
    +# PROP BASE Output_Dir "gen_test"
    +# PROP BASE Intermediate_Dir "gen_test"
    +# PROP BASE Target_Dir ""
    +# PROP Use_MFC 0
    +# PROP Use_Debug_Libraries 0
    +# PROP Output_Dir ""
    +# PROP Intermediate_Dir "gen_test_char_R"
    +# PROP Ignore_Export_Lib 0
    +# PROP Target_Dir ""
    +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    +# ADD BASE RSC /l 0x809 /d "NDEBUG"
    +# ADD RSC /l 0x809 /d "NDEBUG"
    +BSC32=bscmake.exe
    +# ADD BASE BSC32 /nologo
    +# ADD BSC32 /nologo
    +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:console /machine:I386
    +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386
    +# Begin Special Build Tool
    +SOURCE=$(InputPath)
    +PostBuild_Desc=Create test_char.h
    +PostBuild_Cmds=.\gen_test_char > test_char.h
    +# End Special Build Tool
    +
    +!ELSEIF  "$(CFG)" == "gen_test_char - Win32 Debug"
    +
    +# PROP BASE Use_MFC 0
    +# PROP BASE Use_Debug_Libraries 1
    +# PROP BASE Output_Dir "gen_tes0"
    +# PROP BASE Intermediate_Dir "gen_tes0"
    +# PROP BASE Target_Dir ""
    +# PROP Use_MFC 0
    +# PROP Use_Debug_Libraries 1
    +# PROP Output_Dir ""
    +# PROP Intermediate_Dir "gen_test_char_D"
    +# PROP Ignore_Export_Lib 0
    +# PROP Target_Dir ""
    +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    +# ADD BASE RSC /l 0x809 /d "_DEBUG"
    +# ADD RSC /l 0x809 /d "_DEBUG"
    +BSC32=bscmake.exe
    +# ADD BASE BSC32 /nologo
    +# ADD BSC32 /nologo
    +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:console /debug /machine:I386 /pdbtype:sept
    +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
    +# Begin Special Build Tool
    +SOURCE=$(InputPath)
    +PostBuild_Desc=Create test_char.h
    +PostBuild_Cmds=.\gen_test_char > test_char.h
    +# End Special Build Tool
    +
    +!ENDIF 
    +
    +# Begin Target
    +
    +# Name "gen_test_char - Win32 Release"
    +# Name "gen_test_char - Win32 Debug"
    +# Begin Group "Source Files"
    +
    +# PROP Default_Filter ""
    +# Begin Source File
    +
    +SOURCE=.\gen_test_char.c
    +# End Source File
    +# End Group
    +# End Target
    +# End Project
    diff --git a/APACHE_1_3b7/src/main/gen_test_char.mak b/APACHE_1_3b7/src/main/gen_test_char.mak
    new file mode 100644
    index 0000000000..14d5558b09
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/gen_test_char.mak
    @@ -0,0 +1,236 @@
    +# Microsoft Developer Studio Generated NMAKE File, Based on gen_test_char.dsp
    +!IF "$(CFG)" == ""
    +CFG=gen_test_char - Win32 Debug
    +!MESSAGE No configuration specified. Defaulting to gen_test_char - Win32 Debug.
    +!ENDIF 
    +
    +!IF "$(CFG)" != "gen_test_char - Win32 Release" && "$(CFG)" !=\
    + "gen_test_char - Win32 Debug"
    +!MESSAGE Invalid configuration "$(CFG)" specified.
    +!MESSAGE You can specify a configuration when running NMAKE
    +!MESSAGE by defining the macro CFG on the command line. For example:
    +!MESSAGE 
    +!MESSAGE NMAKE /f "gen_test_char.mak" CFG="gen_test_char - Win32 Debug"
    +!MESSAGE 
    +!MESSAGE Possible choices for configuration are:
    +!MESSAGE 
    +!MESSAGE "gen_test_char - Win32 Release" (based on\
    + "Win32 (x86) Console Application")
    +!MESSAGE "gen_test_char - Win32 Debug" (based on\
    + "Win32 (x86) Console Application")
    +!MESSAGE 
    +!ERROR An invalid configuration is specified.
    +!ENDIF 
    +
    +!IF "$(OS)" == "Windows_NT"
    +NULL=
    +!ELSE 
    +NULL=nul
    +!ENDIF 
    +
    +CPP=cl.exe
    +RSC=rc.exe
    +
    +!IF  "$(CFG)" == "gen_test_char - Win32 Release"
    +
    +OUTDIR=.
    +INTDIR=.\gen_test_char_R
    +# Begin Custom Macros
    +OutDir=.
    +# End Custom Macros
    +
    +!IF "$(RECURSE)" == "0" 
    +
    +ALL : "$(OUTDIR)\gen_test_char.exe"
    +
    +!ELSE 
    +
    +ALL : "$(OUTDIR)\gen_test_char.exe"
    +
    +!ENDIF 
    +
    +CLEAN :
    +	-@erase "$(INTDIR)\gen_test_char.obj"
    +	-@erase "$(INTDIR)\vc50.idb"
    +	-@erase "$(OUTDIR)\gen_test_char.exe"
    +
    +"$(INTDIR)" :
    +    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
    +
    +CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D\
    + "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\gen_test_char.pch" /YX /Fo"$(INTDIR)\\"\
    + /Fd"$(INTDIR)\\" /FD /c 
    +CPP_OBJS=.\gen_test_char_R/
    +CPP_SBRS=.
    +BSC32=bscmake.exe
    +BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_test_char.bsc" 
    +BSC32_SBRS= \
    +	
    +LINK32=link.exe
    +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
    + advapi32.lib shell32.lib /nologo /subsystem:console /incremental:no\
    + /pdb:"$(OUTDIR)\gen_test_char.pdb" /machine:I386\
    + /out:"$(OUTDIR)\gen_test_char.exe" 
    +LINK32_OBJS= \
    +	"$(INTDIR)\gen_test_char.obj"
    +
    +"$(OUTDIR)\gen_test_char.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
    +    $(LINK32) @<<
    +  $(LINK32_FLAGS) $(LINK32_OBJS)
    +<<
    +
    +SOURCE=$(InputPath)
    +PostBuild_Desc=Create test_char.h
    +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
    +
    +ALL : $(DS_POSTBUILD_DEP)
    +
    +# Begin Custom Macros
    +OutDir=.
    +# End Custom Macros
    +
    +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\gen_test_char.exe"
    +   .\gen_test_char > test_char.h
    +	echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
    +
    +!ELSEIF  "$(CFG)" == "gen_test_char - Win32 Debug"
    +
    +OUTDIR=.
    +INTDIR=.\gen_test_char_D
    +# Begin Custom Macros
    +OutDir=.
    +# End Custom Macros
    +
    +!IF "$(RECURSE)" == "0" 
    +
    +ALL : "$(OUTDIR)\gen_test_char.exe"
    +
    +!ELSE 
    +
    +ALL : "$(OUTDIR)\gen_test_char.exe"
    +
    +!ENDIF 
    +
    +CLEAN :
    +	-@erase "$(INTDIR)\gen_test_char.obj"
    +	-@erase "$(INTDIR)\vc50.idb"
    +	-@erase "$(INTDIR)\vc50.pdb"
    +	-@erase "$(OUTDIR)\gen_test_char.exe"
    +	-@erase "$(OUTDIR)\gen_test_char.ilk"
    +	-@erase "$(OUTDIR)\gen_test_char.pdb"
    +
    +"$(INTDIR)" :
    +    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
    +
    +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D\
    + "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\gen_test_char.pch" /YX\
    + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
    +CPP_OBJS=.\gen_test_char_D/
    +CPP_SBRS=.
    +BSC32=bscmake.exe
    +BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_test_char.bsc" 
    +BSC32_SBRS= \
    +	
    +LINK32=link.exe
    +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
    + advapi32.lib shell32.lib /nologo /subsystem:console /incremental:yes\
    + /pdb:"$(OUTDIR)\gen_test_char.pdb" /debug /machine:I386\
    + /out:"$(OUTDIR)\gen_test_char.exe" /pdbtype:sept 
    +LINK32_OBJS= \
    +	"$(INTDIR)\gen_test_char.obj"
    +
    +"$(OUTDIR)\gen_test_char.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
    +    $(LINK32) @<<
    +  $(LINK32_FLAGS) $(LINK32_OBJS)
    +<<
    +
    +SOURCE=$(InputPath)
    +PostBuild_Desc=Create test_char.h
    +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
    +
    +ALL : $(DS_POSTBUILD_DEP)
    +
    +# Begin Custom Macros
    +OutDir=.
    +# End Custom Macros
    +
    +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\gen_test_char.exe"
    +   .\gen_test_char > test_char.h
    +	echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
    +
    +!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) $< 
    +<<
    +
    +
    +!IF "$(CFG)" == "gen_test_char - Win32 Release" || "$(CFG)" ==\
    + "gen_test_char - Win32 Debug"
    +SOURCE=.\gen_test_char.c
    +
    +!IF  "$(CFG)" == "gen_test_char - Win32 Release"
    +
    +DEP_CPP_GEN_T=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\buff.h"\
    +	"..\include\conf.h"\
    +	"..\include\hsregex.h"\
    +	"..\include\httpd.h"\
    +	"..\include\util_uri.h"\
    +	"..\os\win32\os.h"\
    +	"..\os\win32\readdir.h"\
    +	
    +
    +"$(INTDIR)\gen_test_char.obj" : $(SOURCE) $(DEP_CPP_GEN_T) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "gen_test_char - Win32 Debug"
    +
    +DEP_CPP_GEN_T=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\buff.h"\
    +	"..\include\conf.h"\
    +	"..\include\hsregex.h"\
    +	"..\include\httpd.h"\
    +	"..\include\util_uri.h"\
    +	"..\os\win32\os.h"\
    +	"..\os\win32\readdir.h"\
    +	
    +
    +"$(INTDIR)\gen_test_char.obj" : $(SOURCE) $(DEP_CPP_GEN_T) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +
    +!ENDIF 
    +
    diff --git a/APACHE_1_3b7/src/main/gen_uri_delims.c b/APACHE_1_3b7/src/main/gen_uri_delims.c
    new file mode 100644
    index 0000000000..15a73fbc7a
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/gen_uri_delims.c
    @@ -0,0 +1,31 @@
    +#include <stdio.h>
    +
    +/* generate a table of 256 values, where certain characters are
    + * marked "interesting"... for the uri parsing process.
    + */
    +
    +int main(int argc, char *argv[])
    +{
    +    int i;
    +    char *value;
    +
    +    printf("/* this file is automatically generated by "
    +	    "gen_uri_delims, do not edit */\n");
    +    printf("static const unsigned char uri_delims[256] = {");
    +    for (i = 0; i < 256; ++i) {
    +	if (i % 20 == 0)
    +	    printf("\n    ");
    +	switch (i) {
    +	case ':': 	value = "T_COLON";	break;
    +	case '/': 	value = "T_SLASH";	break;
    +	case '?': 	value = "T_QUESTION";	break;
    +	case '#': 	value = "T_HASH";	break;
    +	case '\0': 	value = "T_NUL";	break;
    +	default:	value = "0";		break;
    +	}
    +	printf("%s%c", value, (i < 255) ? ',' : ' ');
    +    }
    +    printf("\n};\n");
    +
    +    return 0;
    +}
    diff --git a/APACHE_1_3b7/src/main/gen_uri_delims.dsp b/APACHE_1_3b7/src/main/gen_uri_delims.dsp
    new file mode 100644
    index 0000000000..566dd83e27
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/gen_uri_delims.dsp
    @@ -0,0 +1,105 @@
    +# Microsoft Developer Studio Project File - Name="gen_uri_delims" - Package Owner=<4>
    +# Microsoft Developer Studio Generated Build File, Format Version 5.00
    +# ** DO NOT EDIT **
    +
    +# TARGTYPE "Win32 (x86) Console Application" 0x0103
    +
    +CFG=gen_uri_delims - Win32 Debug
    +!MESSAGE This is not a valid makefile. To build this project using NMAKE,
    +!MESSAGE use the Export Makefile command and run
    +!MESSAGE 
    +!MESSAGE NMAKE /f "gen_uri_delims.mak".
    +!MESSAGE 
    +!MESSAGE You can specify a configuration when running NMAKE
    +!MESSAGE by defining the macro CFG on the command line. For example:
    +!MESSAGE 
    +!MESSAGE NMAKE /f "gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Debug"
    +!MESSAGE 
    +!MESSAGE Possible choices for configuration are:
    +!MESSAGE 
    +!MESSAGE "gen_uri_delims - Win32 Release" (based on\
    + "Win32 (x86) Console Application")
    +!MESSAGE "gen_uri_delims - Win32 Debug" (based on\
    + "Win32 (x86) Console Application")
    +!MESSAGE 
    +
    +# Begin Project
    +# PROP Scc_ProjName ""
    +# PROP Scc_LocalPath ""
    +CPP=cl.exe
    +RSC=rc.exe
    +
    +!IF  "$(CFG)" == "gen_uri_delims - 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 ""
    +# PROP Intermediate_Dir "gen_uri_delims_R"
    +# PROP Ignore_Export_Lib 0
    +# PROP Target_Dir ""
    +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    +# ADD BASE RSC /l 0x809 /d "NDEBUG"
    +# ADD RSC /l 0x809 /d "NDEBUG"
    +BSC32=bscmake.exe
    +# ADD BASE BSC32 /nologo
    +# ADD BSC32 /nologo
    +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:console /machine:I386
    +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386
    +# Begin Special Build Tool
    +SOURCE=$(InputPath)
    +PostBuild_Desc=Create uri_delims.h
    +PostBuild_Cmds=.\gen_uri_delims > uri_delims.h
    +# End Special Build Tool
    +
    +!ELSEIF  "$(CFG)" == "gen_uri_delims - 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 ""
    +# PROP Intermediate_Dir "gen_uri_delims_D"
    +# PROP Ignore_Export_Lib 0
    +# PROP Target_Dir ""
    +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    +# ADD BASE RSC /l 0x809 /d "_DEBUG"
    +# ADD RSC /l 0x809 /d "_DEBUG"
    +BSC32=bscmake.exe
    +# ADD BASE BSC32 /nologo
    +# ADD BSC32 /nologo
    +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:console /debug /machine:I386 /pdbtype:sept
    +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
    +# Begin Special Build Tool
    +SOURCE=$(InputPath)
    +PostBuild_Desc=Create uri_delims.h
    +PostBuild_Cmds=.\gen_uri_delims > uri_delims.h
    +# End Special Build Tool
    +
    +!ENDIF 
    +
    +# Begin Target
    +
    +# Name "gen_uri_delims - Win32 Release"
    +# Name "gen_uri_delims - Win32 Debug"
    +# Begin Group "Source Files"
    +
    +# PROP Default_Filter ""
    +# Begin Source File
    +
    +SOURCE=.\gen_uri_delims.c
    +# End Source File
    +# End Group
    +# End Target
    +# End Project
    diff --git a/APACHE_1_3b7/src/main/gen_uri_delims.mak b/APACHE_1_3b7/src/main/gen_uri_delims.mak
    new file mode 100644
    index 0000000000..63ec6dca9c
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/gen_uri_delims.mak
    @@ -0,0 +1,204 @@
    +# Microsoft Developer Studio Generated NMAKE File, Based on gen_uri_delims.dsp
    +!IF "$(CFG)" == ""
    +CFG=gen_uri_delims - Win32 Debug
    +!MESSAGE No configuration specified. Defaulting to gen_uri_delims - Win32\
    + Debug.
    +!ENDIF 
    +
    +!IF "$(CFG)" != "gen_uri_delims - Win32 Release" && "$(CFG)" !=\
    + "gen_uri_delims - Win32 Debug"
    +!MESSAGE Invalid configuration "$(CFG)" specified.
    +!MESSAGE You can specify a configuration when running NMAKE
    +!MESSAGE by defining the macro CFG on the command line. For example:
    +!MESSAGE 
    +!MESSAGE NMAKE /f "gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Debug"
    +!MESSAGE 
    +!MESSAGE Possible choices for configuration are:
    +!MESSAGE 
    +!MESSAGE "gen_uri_delims - Win32 Release" (based on\
    + "Win32 (x86) Console Application")
    +!MESSAGE "gen_uri_delims - Win32 Debug" (based on\
    + "Win32 (x86) Console Application")
    +!MESSAGE 
    +!ERROR An invalid configuration is specified.
    +!ENDIF 
    +
    +!IF "$(OS)" == "Windows_NT"
    +NULL=
    +!ELSE 
    +NULL=nul
    +!ENDIF 
    +
    +CPP=cl.exe
    +RSC=rc.exe
    +
    +!IF  "$(CFG)" == "gen_uri_delims - Win32 Release"
    +
    +OUTDIR=.
    +INTDIR=.\gen_uri_delims_R
    +# Begin Custom Macros
    +OutDir=.
    +# End Custom Macros
    +
    +!IF "$(RECURSE)" == "0" 
    +
    +ALL : "$(OUTDIR)\gen_uri_delims.exe"
    +
    +!ELSE 
    +
    +ALL : "$(OUTDIR)\gen_uri_delims.exe"
    +
    +!ENDIF 
    +
    +CLEAN :
    +	-@erase "$(INTDIR)\gen_uri_delims.obj"
    +	-@erase "$(INTDIR)\vc50.idb"
    +	-@erase "$(OUTDIR)\gen_uri_delims.exe"
    +
    +"$(INTDIR)" :
    +    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
    +
    +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D\
    + "_MBCS" /Fp"$(INTDIR)\gen_uri_delims.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\
    + /FD /c 
    +CPP_OBJS=.\gen_uri_delims_R/
    +CPP_SBRS=.
    +BSC32=bscmake.exe
    +BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_uri_delims.bsc" 
    +BSC32_SBRS= \
    +	
    +LINK32=link.exe
    +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
    + advapi32.lib shell32.lib /nologo /subsystem:console /incremental:no\
    + /pdb:"$(OUTDIR)\gen_uri_delims.pdb" /machine:I386\
    + /out:"$(OUTDIR)\gen_uri_delims.exe" 
    +LINK32_OBJS= \
    +	"$(INTDIR)\gen_uri_delims.obj"
    +
    +"$(OUTDIR)\gen_uri_delims.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
    +    $(LINK32) @<<
    +  $(LINK32_FLAGS) $(LINK32_OBJS)
    +<<
    +
    +SOURCE=$(InputPath)
    +PostBuild_Desc=Create uri_delims.h
    +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
    +
    +ALL : $(DS_POSTBUILD_DEP)
    +
    +# Begin Custom Macros
    +OutDir=.
    +# End Custom Macros
    +
    +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\gen_uri_delims.exe"
    +   .\gen_uri_delims > uri_delims.h
    +	echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
    +
    +!ELSEIF  "$(CFG)" == "gen_uri_delims - Win32 Debug"
    +
    +OUTDIR=.
    +INTDIR=.\gen_uri_delims_D
    +# Begin Custom Macros
    +OutDir=.
    +# End Custom Macros
    +
    +!IF "$(RECURSE)" == "0" 
    +
    +ALL : "$(OUTDIR)\gen_uri_delims.exe"
    +
    +!ELSE 
    +
    +ALL : "$(OUTDIR)\gen_uri_delims.exe"
    +
    +!ENDIF 
    +
    +CLEAN :
    +	-@erase "$(INTDIR)\gen_uri_delims.obj"
    +	-@erase "$(INTDIR)\vc50.idb"
    +	-@erase "$(INTDIR)\vc50.pdb"
    +	-@erase "$(OUTDIR)\gen_uri_delims.exe"
    +	-@erase "$(OUTDIR)\gen_uri_delims.ilk"
    +	-@erase "$(OUTDIR)\gen_uri_delims.pdb"
    +
    +"$(INTDIR)" :
    +    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
    +
    +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
    + /D "_MBCS" /Fp"$(INTDIR)\gen_uri_delims.pch" /YX /Fo"$(INTDIR)\\"\
    + /Fd"$(INTDIR)\\" /FD /c 
    +CPP_OBJS=.\gen_uri_delims_D/
    +CPP_SBRS=.
    +BSC32=bscmake.exe
    +BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_uri_delims.bsc" 
    +BSC32_SBRS= \
    +	
    +LINK32=link.exe
    +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
    + advapi32.lib shell32.lib /nologo /subsystem:console /incremental:yes\
    + /pdb:"$(OUTDIR)\gen_uri_delims.pdb" /debug /machine:I386\
    + /out:"$(OUTDIR)\gen_uri_delims.exe" /pdbtype:sept 
    +LINK32_OBJS= \
    +	"$(INTDIR)\gen_uri_delims.obj"
    +
    +"$(OUTDIR)\gen_uri_delims.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
    +    $(LINK32) @<<
    +  $(LINK32_FLAGS) $(LINK32_OBJS)
    +<<
    +
    +SOURCE=$(InputPath)
    +PostBuild_Desc=Create uri_delims.h
    +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep
    +
    +ALL : $(DS_POSTBUILD_DEP)
    +
    +# Begin Custom Macros
    +OutDir=.
    +# End Custom Macros
    +
    +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\gen_uri_delims.exe"
    +   .\gen_uri_delims > uri_delims.h
    +	echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)"
    +
    +!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) $< 
    +<<
    +
    +
    +!IF "$(CFG)" == "gen_uri_delims - Win32 Release" || "$(CFG)" ==\
    + "gen_uri_delims - Win32 Debug"
    +SOURCE=.\gen_uri_delims.c
    +
    +"$(INTDIR)\gen_uri_delims.obj" : $(SOURCE) "$(INTDIR)"
    +
    +
    +
    +!ENDIF 
    +
    diff --git a/APACHE_1_3b7/src/main/http_config.c b/APACHE_1_3b7/src/main/http_config.c
    new file mode 100644
    index 0000000000..b6e9db1886
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/http_config.c
    @@ -0,0 +1,1604 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +/*
    + * http_config.c: once was auxillary functions for reading httpd's config
    + * file and converting filenames into a namespace
    + *
    + * Rob McCool 
    + * 
    + * Wall-to-wall rewrite for Apache... commands which are part of the
    + * server core can now be found next door in "http_core.c".  Now contains
    + * general command loop, and functions which do bookkeeping for the new
    + * Apache config stuff (modules and configuration vectors).
    + *
    + * rst
    + *
    + */
    +
    +#define CORE_PRIVATE
    +
    +#include "httpd.h"
    +#include "http_config.h"
    +#include "http_core.h"
    +#include "http_log.h"		/* for errors in parse_htaccess */
    +#include "http_request.h"	/* for default_handler (see invoke_handler) */
    +#include "http_conf_globals.h"	/* Sigh... */
    +#include "http_vhost.h"
    +#include "explain.h"
    +
    +DEF_Explain
    +
    +/****************************************************************
    + *
    + * We begin with the functions which deal with the linked list
    + * of modules which control just about all of the server operation.
    + */
    +
    +/* total_modules is the number of modules that have been linked
    + * into the server.
    + */
    +static int total_modules = 0;
    +/* dynamic_modules is the number of modules that have been added
    + * after the pre-loaded ones have been set up. It shouldn't be larger
    + * than DYNAMIC_MODULE_LIMIT.
    + */
    +static int dynamic_modules = 0;
    +API_VAR_EXPORT module *top_module = NULL;
    +API_VAR_EXPORT module **ap_loaded_modules;
    +
    +typedef int (*handler_func) (request_rec *);
    +typedef void *(*dir_maker_func) (pool *, char *);
    +typedef void *(*merger_func) (pool *, void *, void *);
    +
    +/* Dealing with config vectors.  These are associated with per-directory,
    + * per-server, and per-request configuration, and have a void* pointer for
    + * each modules.  The nature of the structure pointed to is private to the
    + * module in question... the core doesn't (and can't) know.  However, there
    + * are defined interfaces which allow it to create instances of its private
    + * per-directory and per-server structures, and to merge the per-directory
    + * structures of a directory and its subdirectory (producing a new one in
    + * which the defaults applying to the base directory have been properly
    + * overridden).
    + */
    +
    +#ifndef ap_get_module_config
    +API_EXPORT(void *) ap_get_module_config(void *conf_vector, module *m)
    +{
    +    void **confv = (void **) conf_vector;
    +    return confv[m->module_index];
    +}
    +#endif
    +
    +#ifndef ap_set_module_config
    +API_EXPORT(void) ap_set_module_config(void *conf_vector, module *m, void *val)
    +{
    +    void **confv = (void **) conf_vector;
    +    confv[m->module_index] = val;
    +}
    +#endif
    +
    +static void *create_empty_config(pool *p)
    +{
    +    void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) *
    +				    (total_modules + DYNAMIC_MODULE_LIMIT));
    +    return (void *) conf_vector;
    +}
    +
    +static void *create_default_per_dir_config(pool *p)
    +{
    +    void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
    +    module *modp;
    +
    +    for (modp = top_module; modp; modp = modp->next) {
    +	dir_maker_func df = modp->create_dir_config;
    +
    +	if (df)
    +	    conf_vector[modp->module_index] = (*df) (p, NULL);
    +    }
    +
    +    return (void *) conf_vector;
    +}
    +
    +void *
    +     ap_merge_per_dir_configs(pool *p, void *base, void *new)
    +{
    +    void **conf_vector = (void **) ap_palloc(p, sizeof(void *) * total_modules);
    +    void **base_vector = (void **) base;
    +    void **new_vector = (void **) new;
    +    module *modp;
    +
    +    for (modp = top_module; modp; modp = modp->next) {
    +	merger_func df = modp->merge_dir_config;
    +	int i = modp->module_index;
    +
    +	if (df && new_vector[i])
    +	    conf_vector[i] = (*df) (p, base_vector[i], new_vector[i]);
    +	else
    +	    conf_vector[i] = new_vector[i] ? new_vector[i] : base_vector[i];
    +    }
    +
    +    return (void *) conf_vector;
    +}
    +
    +static void *create_server_config(pool *p, server_rec *s)
    +{
    +    void **conf_vector = (void **) ap_pcalloc(p, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
    +    module *modp;
    +
    +    for (modp = top_module; modp; modp = modp->next) {
    +	if (modp->create_server_config)
    +	    conf_vector[modp->module_index] = (*modp->create_server_config) (p, s);
    +    }
    +
    +    return (void *) conf_vector;
    +}
    +
    +static void merge_server_configs(pool *p, void *base, void *virt)
    +{
    +    /* Can reuse the 'virt' vector for the spine of it, since we don't
    +     * have to deal with the moral equivalent of .htaccess files here...
    +     */
    +
    +    void **base_vector = (void **) base;
    +    void **virt_vector = (void **) virt;
    +    module *modp;
    +
    +    for (modp = top_module; modp; modp = modp->next) {
    +	merger_func df = modp->merge_server_config;
    +	int i = modp->module_index;
    +
    +	if (!virt_vector[i])
    +	    virt_vector[i] = base_vector[i];
    +	else if (df)
    +	    virt_vector[i] = (*df) (p, base_vector[i], virt_vector[i]);
    +    }
    +}
    +
    +void *ap_create_request_config(pool *p)
    +{
    +    return create_empty_config(p);
    +}
    +
    +CORE_EXPORT(void *) ap_create_per_dir_config(pool *p)
    +{
    +    return create_empty_config(p);
    +}
    +
    +#ifdef EXPLAIN
    +
    +struct {
    +    int offset;
    +    char *method;
    +} aMethods[] =
    +
    +{
    +#define m(meth)	{ XtOffsetOf(module,meth),#meth }
    +    m(translate_handler),
    +    m(ap_check_user_id),
    +    m(auth_checker),
    +    m(type_checker),
    +    m(fixer_upper),
    +    m(logger),
    +    { -1, "?" },
    +#undef m
    +};
    +
    +char *ShowMethod(module *modp, int offset)
    +{
    +    int n;
    +    static char buf[200];
    +
    +    for (n = 0; aMethods[n].offset >= 0; ++n)
    +	if (aMethods[n].offset == offset)
    +	    break;
    +    ap_snprintf(buf, sizeof(buf), "%s:%s", modp->name, aMethods[n].method);
    +    return buf;
    +}
    +#else
    +#define ShowMethod(modp,offset)
    +#endif
    +
    +/****************************************************************
    + *
    + * Dispatch through the modules to find handlers for various phases
    + * of request handling.  These are invoked by http_request.c to actually
    + * do the dirty work of slogging through the module structures.
    + */
    +
    +/*
    + * Optimized run_method routines.  The observation here is that many modules
    + * have NULL for most of the methods.  So we build optimized lists of
    + * everything.  If you think about it, this is really just like a sparse array
    + * implementation to avoid scanning the zero entries.
    + */
    +static const int method_offsets[] =
    +{
    +    XtOffsetOf(module, translate_handler),
    +    XtOffsetOf(module, ap_check_user_id),
    +    XtOffsetOf(module, auth_checker),
    +    XtOffsetOf(module, access_checker),
    +    XtOffsetOf(module, type_checker),
    +    XtOffsetOf(module, fixer_upper),
    +    XtOffsetOf(module, logger),
    +    XtOffsetOf(module, header_parser),
    +    XtOffsetOf(module, post_read_request)
    +};
    +#define NMETHODS	(sizeof (method_offsets)/sizeof (method_offsets[0]))
    +
    +static struct {
    +    int translate_handler;
    +    int ap_check_user_id;
    +    int auth_checker;
    +    int access_checker;
    +    int type_checker;
    +    int fixer_upper;
    +    int logger;
    +    int header_parser;
    +    int post_read_request;
    +} offsets_into_method_ptrs;
    +
    +/*
    + * This is just one big array of method_ptrs.  It's constructed such that,
    + * for example, method_ptrs[ offsets_into_method_ptrs.logger ] is the first
    + * logger function.  You go one-by-one from there until you hit a NULL.
    + * This structure was designed to hopefully maximize cache-coolness.
    + */
    +static handler_func *method_ptrs;
    +
    +/* routine to reconstruct all these shortcuts... called after every
    + * add_module.
    + * XXX: this breaks if modules dink with their methods pointers
    + */
    +static void build_method_shortcuts(void)
    +{
    +    module *modp;
    +    int how_many_ptrs;
    +    int i;
    +    int next_ptr;
    +    handler_func fp;
    +
    +    if (method_ptrs) {
    +	/* free up any previous set of method_ptrs */
    +	free(method_ptrs);
    +    }
    +
    +    /* first we count how many functions we have */
    +    how_many_ptrs = 0;
    +    for (modp = top_module; modp; modp = modp->next) {
    +	for (i = 0; i < NMETHODS; ++i) {
    +	    if (*(handler_func *) (method_offsets[i] + (char *) modp)) {
    +		++how_many_ptrs;
    +	    }
    +	}
    +    }
    +    method_ptrs = malloc((how_many_ptrs + NMETHODS) * sizeof(handler_func));
    +    next_ptr = 0;
    +    for (i = 0; i < NMETHODS; ++i) {
    +	/* XXX: This is an itsy bit presumptuous about the alignment
    +	 * constraints on offsets_into_method_ptrs.  I can't remember if
    +	 * ANSI says this has to be true... -djg */
    +	((int *) &offsets_into_method_ptrs)[i] = next_ptr;
    +	for (modp = top_module; modp; modp = modp->next) {
    +	    fp = *(handler_func *) (method_offsets[i] + (char *) modp);
    +	    if (fp) {
    +		method_ptrs[next_ptr++] = fp;
    +	    }
    +	}
    +	method_ptrs[next_ptr++] = NULL;
    +    }
    +}
    +
    +
    +static int run_method(request_rec *r, int offset, int run_all)
    +{
    +    int i;
    +
    +    for (i = offset; method_ptrs[i]; ++i) {
    +	handler_func mod_handler = method_ptrs[i];
    +
    +	if (mod_handler) {
    +	    int result;
    +
    +	    result = (*mod_handler) (r);
    +
    +	    if (result != DECLINED && (!run_all || result != OK))
    +		return result;
    +	}
    +    }
    +
    +    return run_all ? OK : DECLINED;
    +}
    +
    +int ap_translate_name(request_rec *r)
    +{
    +    return run_method(r, offsets_into_method_ptrs.translate_handler, 0);
    +}
    +
    +int ap_check_access(request_rec *r)
    +{
    +    return run_method(r, offsets_into_method_ptrs.access_checker, 1);
    +}
    +
    +int ap_find_types(request_rec *r)
    +{
    +    return run_method(r, offsets_into_method_ptrs.type_checker, 0);
    +}
    +
    +int ap_run_fixups(request_rec *r)
    +{
    +    return run_method(r, offsets_into_method_ptrs.fixer_upper, 1);
    +}
    +
    +int ap_log_transaction(request_rec *r)
    +{
    +    return run_method(r, offsets_into_method_ptrs.logger, 1);
    +}
    +
    +int ap_header_parse(request_rec *r)
    +{
    +    return run_method(r, offsets_into_method_ptrs.header_parser, 1);
    +}
    +
    +int ap_run_post_read_request(request_rec *r)
    +{
    +    return run_method(r, offsets_into_method_ptrs.post_read_request, 1);
    +}
    +
    +/* Auth stuff --- anything that defines one of these will presumably
    + * want to define something for the other.  Note that check_auth is
    + * separate from check_access to make catching some config errors easier.
    + */
    +
    +int ap_check_user_id(request_rec *r)
    +{
    +    return run_method(r, offsets_into_method_ptrs.ap_check_user_id, 0);
    +}
    +
    +int ap_check_auth(request_rec *r)
    +{
    +    return run_method(r, offsets_into_method_ptrs.auth_checker, 0);
    +}
    +
    +/*
    + * For speed/efficiency we generate a compact list of all the handlers
    + * and wildcard handlers.  This means we won't have to scan the entire
    + * module list looking for handlers... where we'll find a whole whack
    + * of NULLs.
    + */
    +typedef struct {
    +    handler_rec hr;
    +    size_t len;
    +} fast_handler_rec;
    +
    +static fast_handler_rec *handlers;
    +static fast_handler_rec *wildhandlers;
    +
    +static void init_handlers(pool *p)
    +{
    +    module *modp;
    +    int nhandlers = 0;
    +    int nwildhandlers = 0;
    +    const handler_rec *handp;
    +    fast_handler_rec *ph, *pw;
    +    char *starp;
    +
    +    for (modp = top_module; modp; modp = modp->next) {
    +	if (!modp->handlers)
    +	    continue;
    +	for (handp = modp->handlers; handp->content_type; ++handp) {
    +	    if (strchr(handp->content_type, '*')) {
    +                nwildhandlers ++;
    +            } else {
    +                nhandlers ++;
    +            }
    +        }
    +    }
    +    ph = handlers = ap_palloc(p, sizeof(*ph)*(nhandlers + 1));
    +    pw = wildhandlers = ap_palloc(p, sizeof(*pw)*(nwildhandlers + 1));
    +    for (modp = top_module; modp; modp = modp->next) {
    +	if (!modp->handlers)
    +	    continue;
    +	for (handp = modp->handlers; handp->content_type; ++handp) {
    +	    if ((starp = strchr(handp->content_type, '*'))) {
    +                pw->hr.content_type = handp->content_type;
    +                pw->hr.handler = handp->handler;
    +		pw->len = starp - handp->content_type;
    +                pw ++;
    +            } else {
    +                ph->hr.content_type = handp->content_type;
    +                ph->hr.handler = handp->handler;
    +		ph->len = strlen(handp->content_type);
    +                ph ++;
    +            }
    +        }
    +    }
    +    pw->hr.content_type = NULL;
    +    pw->hr.handler = NULL;
    +    ph->hr.content_type = NULL;
    +    ph->hr.handler = NULL;
    +}
    +
    +int ap_invoke_handler(request_rec *r)
    +{
    +    fast_handler_rec *handp;
    +    char *handler, *p;
    +    size_t handler_len;
    +
    +    if (r->handler) {
    +	handler = r->handler;
    +	handler_len = strlen(handler);
    +    }
    +    else {
    +	handler = r->content_type ? r->content_type : ap_default_type(r);
    +	if ((p = strchr(handler, ';')) != NULL) { /* MIME type arguments */
    +	    while (p > handler && p[-1] == ' ')
    +		--p;		/* strip trailing spaces */
    +	    handler_len = p - handler;
    +	}
    +	else {
    +	    handler_len = strlen(handler);
    +	}
    +    }
    +
    +    /* Pass one --- direct matches */
    +
    +    for (handp = handlers; handp->hr.content_type; ++handp) {
    +	if (handler_len == handp->len
    +	    && !strncmp(handler, handp->hr.content_type, handler_len)) {
    +            int result = (*handp->hr.handler) (r);
    +
    +            if (result != DECLINED)
    +                return result;
    +        }
    +    }
    +
    +    /* Pass two --- wildcard matches */
    +
    +    for (handp = wildhandlers; handp->hr.content_type; ++handp) {
    +	if (handler_len >= handp->len
    +	    && !strncmp(handler, handp->hr.content_type, handp->len)) {
    +             int result = (*handp->hr.handler) (r);
    +
    +             if (result != DECLINED)
    +                 return result;
    +         }
    +    }
    +
    +    return NOT_IMPLEMENTED;
    +}
    +
    +/* One-time setup for precompiled modules --- NOT to be done on restart */
    +
    +API_EXPORT(void) ap_add_module(module *m)
    +{
    +    /* This could be called from an AddModule httpd.conf command,
    +     * after the file has been linked and the module structure within it
    +     * teased out...
    +     */
    +
    +    /* At some point, we may want to offer back-compatibility for
    +     * loading modules that are for older versions of Apache. For now,
    +     * though, we don't.
    +     */
    +
    +    if (m->version != MODULE_MAGIC_NUMBER) {
    +	fprintf(stderr, "httpd: module \"%s\" is not compatible with this "
    +		"version of Apache.\n", m->name);
    +	fprintf(stderr, "Please contact the author for the correct version.\n");
    +	exit(1);
    +    }
    +
    +    if (m->next == NULL) {
    +	m->next = top_module;
    +	top_module = m;
    +    }
    +    if (m->module_index == -1) {
    +	m->module_index = total_modules++;
    +	dynamic_modules++;
    +
    +	if (dynamic_modules > DYNAMIC_MODULE_LIMIT) {
    +	    fprintf(stderr, "httpd: module \"%s\" could not be loaded, because"
    +		    " the dynamic\n", m->name);
    +	    fprintf(stderr, "module limit was reached. Please increase "
    +		    "DYNAMIC_MODULE_LIMIT and recompile.\n");
    +	    exit(1);
    +	}
    +    }
    +
    +    /* Some C compilers put a complete path into __FILE__, but we want
    +     * only the filename (e.g. mod_includes.c). So check for path
    +     * components (Unix and DOS), and remove them.
    +     */
    +
    +    if (strrchr(m->name, '/'))
    +	m->name = 1 + strrchr(m->name, '/');
    +    if (strrchr(m->name, '\\'))
    +	m->name = 1 + strrchr(m->name, '\\');
    +
    +#ifdef _OSD_POSIX /* __FILE__="*POSIX(/home/martin/apache/src/modules/standard/mod_info.c)" */
    +    /* We cannot fix the string in-place, because it's const */
    +    if (m->name[strlen(m->name)-1]==')') {
    +	char *tmp = strdup(m->name);	/* FIXME:memory leak, albeit a small one */
    +	tmp[strlen(tmp)-1] = '\0';
    +	m->name = tmp;
    +    }
    +#endif /*_OSD_POSIX*/
    +}
    +
    +/* 
    + * remove_module undoes what add_module did. There are some caveats:
    + * when the module is removed, its slot is lost so all the current
    + * per-dir and per-server configurations are invalid. So we should
    + * only ever call this function when you are invalidating almost
    + * all our current data. I.e. when doing a restart.
    + */
    +
    +API_EXPORT(void) ap_remove_module(module *m)
    +{
    +    module *modp;
    +
    +    modp = top_module;
    +    if (modp == m) {
    +	/* We are the top module, special case */
    +	top_module = modp->next;
    +    }
    +    else {
    +	/* Not the top module, find use. When found modp will
    +	 * point to the module _before_ us in the list
    +	 */
    +
    +	while (modp && modp->next != m) {
    +	    modp = modp->next;
    +	}
    +	if (!modp) {
    +	    /* Uh-oh, this module doesn't exist */
    +	    ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
    +		"Cannot remove module %s: not found in module list",
    +		m->name);
    +	    return;
    +	}
    +	/* Eliminate us from the module list */
    +	modp->next = modp->next->next;
    +    }
    +
    +    m->module_index = -1;	/* simulate being unloaded, should
    +				 * be unnecessary */
    +    dynamic_modules--;
    +}
    +
    +API_EXPORT(void) ap_add_loaded_module(module *mod)
    +{
    +    module **m;
    +
    +    /* 
    +     *  Add module pointer to top of chained module list 
    +     */
    +    ap_add_module(mod);
    +
    +    /* 
    +     *  And module pointer to list of loaded modules 
    +     *
    +     *  Notes: 1. ap_add_module() would already complain if no more space
    +     *            exists for adding a dynamically loaded module
    +     *         2. ap_add_module() accepts double-inclusion, so we have
    +     *            to accept this, too.
    +     */
    +    for (m = ap_loaded_modules; *m != NULL; m++)
    +        ;
    +    *m++ = mod;
    +    *m = NULL;
    +}
    +
    +API_EXPORT(void) ap_remove_loaded_module(module *mod)
    +{
    +    module **m;
    +    module **m2;
    +    int done;
    +
    +    /* 
    +     *  Remove module pointer from chained module list 
    +     */
    +    ap_remove_module(mod);
    +
    +    /* 
    +     *  Remove module pointer from list of loaded modules
    +     *
    +     *  Note: 1. We cannot determine if the module was successfully
    +     *           removed by ap_remove_module().
    +     *        2. We have not to complain explicity when the module
    +     *           is not found because ap_remove_module() did it
    +     *           for us already.
    +     */
    +    for (m = m2 = ap_loaded_modules, done = 0; *m2 != NULL; m2++) {
    +        if (*m2 == mod && done == 0)
    +            done = 1;
    +        else
    +            *m++ = *m2;
    +    }
    +    *m = NULL;
    +}
    +
    +void ap_setup_prelinked_modules()
    +{
    +    module **m;
    +    module **m2;
    +
    +    /*
    +     *  Initialise total_modules variable and module indices
    +     */
    +    total_modules = 0;
    +    for (m = ap_preloaded_modules; *m != NULL; m++)
    +        (*m)->module_index = total_modules++;
    +
    +    /* 
    +     *  Initialise list of loaded modules
    +     */
    +    ap_loaded_modules = (module **)malloc(
    +        sizeof(module *)*(total_modules+DYNAMIC_MODULE_LIMIT+1));
    +    for (m = ap_preloaded_modules, m2 = ap_loaded_modules; *m != NULL; )
    +        *m2++ = *m++;
    +    *m2 = NULL;
    +
    +    /*
    +     *   Initialize chain of linked (=activate) modules
    +     */
    +    for (m = ap_prelinked_modules; *m != NULL; m++)
    +        ap_add_module(*m);
    +}
    +
    +API_EXPORT(const char *) ap_find_module_name(module *m)
    +{
    +    return m->name;
    +}
    +
    +API_EXPORT(module *) ap_find_linked_module(const char *name)
    +{
    +    module *modp;
    +
    +    for (modp = top_module; modp; modp = modp->next) {
    +	if (strcmp(modp->name, name) == 0)
    +	    return modp;
    +    }
    +    return NULL;
    +}
    +
    +/* Add a named module.  Returns 1 if module found, 0 otherwise.  */
    +API_EXPORT(int) ap_add_named_module(const char *name)
    +{
    +    module *modp;
    +    int i = 0;
    +
    +    for (modp = ap_loaded_modules[i]; modp; modp = ap_loaded_modules[++i]) {
    +	if (strcmp(modp->name, name) == 0) {
    +	    /* Only add modules that are not already enabled.  */
    +	    if (modp->next == NULL) {
    +		ap_add_module(modp);
    +	    }
    +	    return 1;
    +	}
    +    }
    +
    +    return 0;
    +}
    +
    +/* Clear the internal list of modules, in preparation for starting over. */
    +API_EXPORT(void) ap_clear_module_list()
    +{
    +    module **m = &top_module;
    +    module **next_m;
    +
    +    while (*m) {
    +	next_m = &((*m)->next);
    +	*m = NULL;
    +	m = next_m;
    +    }
    +
    +    /* This is required; so we add it always.  */
    +    ap_add_named_module("http_core.c");
    +}
    +
    +/*****************************************************************
    + *
    + * Resource, access, and .htaccess config files now parsed by a common
    + * command loop.
    + *
    + * Let's begin with the basics; parsing the line and
    + * invoking the function...
    + */
    +
    +static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
    +			    void *mconfig, const char *args)
    +{
    +    char *w, *w2, *w3;
    +    const char *errmsg;
    +
    +    if ((parms->override & cmd->req_override) == 0)
    +	return ap_pstrcat(parms->pool, cmd->name, " not allowed here", NULL);
    +
    +    parms->info = cmd->cmd_data;
    +    parms->cmd = cmd;
    +
    +    switch (cmd->args_how) {
    +    case RAW_ARGS:
    +	return ((const char *(*)(cmd_parms *, void *, const char *))
    +		(cmd->func)) (parms, mconfig, args);
    +
    +    case NO_ARGS:
    +	if (*args != 0)
    +	    return ap_pstrcat(parms->pool, cmd->name, " takes no arguments",
    +			   NULL);
    +
    +	return ((const char *(*)(cmd_parms *, void *))
    +		(cmd->func)) (parms, mconfig);
    +
    +    case TAKE1:
    +	w = ap_getword_conf(parms->pool, &args);
    +
    +	if (*w == '\0' || *args != 0)
    +	    return ap_pstrcat(parms->pool, cmd->name, " takes one argument",
    +			    cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
    +
    +	return ((const char *(*)(cmd_parms *, void *, const char *))
    +		(cmd->func)) (parms, mconfig, w);
    +
    +    case TAKE2:
    +
    +	w = ap_getword_conf(parms->pool, &args);
    +	w2 = ap_getword_conf(parms->pool, &args);
    +
    +	if (*w == '\0' || *w2 == '\0' || *args != 0)
    +	    return ap_pstrcat(parms->pool, cmd->name, " takes two arguments",
    +			    cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
    +
    +	return ((const char *(*)(cmd_parms *, void *, const char *,
    +			const char *)) (cmd->func)) (parms, mconfig, w, w2);
    +
    +    case TAKE12:
    +
    +	w = ap_getword_conf(parms->pool, &args);
    +	w2 = ap_getword_conf(parms->pool, &args);
    +
    +	if (*w == '\0' || *args != 0)
    +	    return ap_pstrcat(parms->pool, cmd->name, " takes 1-2 arguments",
    +			    cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
    +
    +	return ((const char *(*)(cmd_parms *, void *, const char *,
    +			    const char *)) (cmd->func)) (parms, mconfig, w,
    +							    *w2 ? w2 : NULL);
    +
    +    case TAKE3:
    +
    +	w = ap_getword_conf(parms->pool, &args);
    +	w2 = ap_getword_conf(parms->pool, &args);
    +	w3 = ap_getword_conf(parms->pool, &args);
    +
    +	if (*w == '\0' || *w2 == '\0' || *w3 == '\0' || *args != 0)
    +	    return ap_pstrcat(parms->pool, cmd->name, " takes three arguments",
    +			    cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
    +
    +	return ((const char *(*)(cmd_parms *, void *, const char *,
    +			    const char *, const char *)) (cmd->func)) (parms,
    +							mconfig, w, w2, w3);
    +
    +    case TAKE23:
    +
    +	w = ap_getword_conf(parms->pool, &args);
    +	w2 = ap_getword_conf(parms->pool, &args);
    +	w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
    +
    +	if (*w == '\0' || *w2 == '\0' || *args != 0)
    +	    return ap_pstrcat(parms->pool, cmd->name,
    +			    " takes two or three arguments",
    +			    cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
    +
    +	return ((const char *(*)(cmd_parms *, void *, const char *,
    +			    const char *, const char *)) (cmd->func)) (parms,
    +							mconfig, w, w2, w3);
    +
    +    case TAKE123:
    +
    +	w = ap_getword_conf(parms->pool, &args);
    +	w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
    +	w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
    +
    +	if (*w == '\0' || *args != 0)
    +	    return ap_pstrcat(parms->pool, cmd->name,
    +			    " takes one, two or three arguments",
    +			    cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
    +
    +	return ((const char *(*)(cmd_parms *, void *, const char *,
    +			    const char *, const char *)) (cmd->func)) (parms,
    +							mconfig, w, w2, w3);
    +
    +    case TAKE13:
    +
    +	w = ap_getword_conf(parms->pool, &args);
    +	w2 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
    +	w3 = *args ? ap_getword_conf(parms->pool, &args) : NULL;
    +
    +	if (*w == '\0' || (*w2 && !w3) || *args != 0)
    +	    return ap_pstrcat(parms->pool, cmd->name,
    +			    " takes one or three arguments",
    +			    cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
    +
    +	return ((const char *(*)(cmd_parms *, void *, const char *,
    +			    const char *, const char *)) (cmd->func)) (parms,
    +							mconfig, w, w2, w3);
    +
    +    case ITERATE:
    +
    +	while (*(w = ap_getword_conf(parms->pool, &args)) != '\0')
    +	if   ((errmsg = ((const char *(*)(cmd_parms *, void *,
    +			const char *)) (cmd->func)) (parms, mconfig, w)))
    +		    return errmsg;
    +
    +	return NULL;
    +
    +    case ITERATE2:
    +
    +	w = ap_getword_conf(parms->pool, &args);
    +
    +	if (*w == '\0' || *args == 0)
    +	    return ap_pstrcat(parms->pool, cmd->name,
    +			    " requires at least two arguments",
    +			    cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL);
    +
    +
    +	while (*(w2 = ap_getword_conf(parms->pool, &args)) != '\0')
    +	    if   ((errmsg = ((const char *(*)(cmd_parms *, void *,
    +			    const char *, const char *)) (cmd->func)) (parms,
    +							    mconfig, w, w2)))
    +			return errmsg;
    +
    +	return NULL;
    +
    +    case FLAG:
    +
    +	w = ap_getword_conf(parms->pool, &args);
    +
    +	if (*w == '\0' || (strcasecmp(w, "on") && strcasecmp(w, "off")))
    +	    return ap_pstrcat(parms->pool, cmd->name, " must be On or Off",
    +			    NULL);
    +
    +	return ((const char *(*)(cmd_parms *, void *, int))
    +		(cmd->func)) (parms, mconfig, strcasecmp(w, "off") != 0);
    +
    +    default:
    +
    +	return ap_pstrcat(parms->pool, cmd->name,
    +		    " is improperly configured internally (server bug)",
    +			NULL);
    +    }
    +}
    +
    +CORE_EXPORT(const command_rec *) ap_find_command(const char *name, const command_rec *cmds)
    +{
    +    while (cmds->name)
    +	if (!strcasecmp(name, cmds->name))
    +	    return cmds;
    +	else
    +	    ++cmds;
    +
    +    return NULL;
    +}
    +
    +CORE_EXPORT(const command_rec *) ap_find_command_in_modules(const char *cmd_name, module **mod)
    +{
    +    const command_rec *cmdp;
    +    module *modp;
    +
    +    for (modp = *mod; modp; modp = modp->next)
    +	if (modp->cmds && (cmdp = ap_find_command(cmd_name, modp->cmds))) {
    +	    *mod = modp;
    +	    return cmdp;
    +	}
    +
    +    return NULL;
    +}
    +
    +CORE_EXPORT(const char *) ap_handle_command(cmd_parms *parms, void *config, const char *l)
    +{
    +    const char *args, *cmd_name, *retval;
    +    const command_rec *cmd;
    +    module *mod = top_module;
    +
    +    if ((l[0] == '#') || (!l[0]))
    +	return NULL;
    +
    +    args = l;
    +    cmd_name = ap_getword_conf(parms->temp_pool, &args);
    +    if (*cmd_name == '\0')
    +	return NULL;
    +
    +    do {
    +	if (!(cmd = ap_find_command_in_modules(cmd_name, &mod))) {
    +            errno = EINVAL;
    +            return ap_pstrcat(parms->pool, "Invalid command '", cmd_name,
    +                           "', perhaps mis-spelled or defined by a module "
    +                           "not included in the server configuration", NULL);
    +	}
    +	else {
    +	    void *mconfig = ap_get_module_config(config, mod);
    +	    void *sconfig =
    +		ap_get_module_config(parms->server->module_config, mod);
    +
    +	    if (!mconfig && mod->create_dir_config) {
    +		mconfig = (*mod->create_dir_config) (parms->pool, parms->path);
    +		ap_set_module_config(config, mod, mconfig);
    +	    }
    +
    +	    if (!sconfig && mod->create_server_config) {
    +		sconfig =
    +		    (*mod->create_server_config) (parms->pool, parms->server);
    +		ap_set_module_config(parms->server->module_config, mod, sconfig);
    +	    }
    +
    +	    retval = invoke_cmd(cmd, parms, mconfig, args);
    +	    mod = mod->next;	/* Next time around, skip this one */
    +	}
    +    } while (retval && !strcmp(retval, DECLINE_CMD));
    +
    +    return retval;
    +}
    +
    +API_EXPORT(const char *) ap_srm_command_loop(cmd_parms *parms, void *config)
    +{
    +    char l[MAX_STRING_LEN];
    +
    +    while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {
    +	const char *errmsg = ap_handle_command(parms, config, l);
    +        if (errmsg) {
    +	    return errmsg;
    +	}
    +    }
    +
    +    return NULL;
    +}
    +
    +/*
    + * Generic command functions...
    + */
    +
    +API_EXPORT_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd,
    +						char *struct_ptr, char *arg)
    +{
    +    /* This one's pretty generic... */
    +
    +    int offset = (int) (long) cmd->info;
    +    *(char **) (struct_ptr + offset) = arg;
    +    return NULL;
    +}
    +
    +API_EXPORT_NONSTD(const char *) ap_set_string_slot_lower(cmd_parms *cmd,
    +						char *struct_ptr, char *arg)
    +{
    +    /* This one's pretty generic... */
    +
    +    int offset = (int) (long) cmd->info;
    +    ap_str_tolower(arg);
    +    *(char **) (struct_ptr + offset) = arg;
    +    return NULL;
    +}
    +
    +API_EXPORT_NONSTD(const char *) ap_set_flag_slot(cmd_parms *cmd,
    +					      char *struct_ptr, int arg)
    +{
    +    /* This one's pretty generic too... */
    +
    +    int offset = (int) (long) cmd->info;
    +    *(int *) (struct_ptr + offset) = arg ? 1 : 0;
    +    return NULL;
    +}
    +
    +API_EXPORT_NONSTD(const char *) ap_set_file_slot(cmd_parms *cmd, char *struct_ptr, char *arg)
    +{
    +    /* Prepend server_root to relative arg.
    +       This allows .htaccess to be independent of server_root,
    +       so the server can be moved or mirrored with less pain.  */
    +    char *p;
    +    int offset = (int) (long) cmd->info;
    +    if (ap_os_is_path_absolute(arg))
    +	p = arg;
    +    else
    +	p = ap_make_full_path(cmd->pool, ap_server_root, arg);
    +    *(char **) (struct_ptr + offset) = p;
    +    return NULL;
    +}
    +
    +/*****************************************************************
    + *
    + * Reading whole config files...
    + */
    +
    +static cmd_parms default_parms =
    +{NULL, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL};
    +
    +API_EXPORT(char *) ap_server_root_relative(pool *p, char *file)
    +{
    +    if(ap_os_is_path_absolute(file))
    +	return file;
    +    return ap_make_full_path(p, ap_server_root, file);
    +}
    +
    +
    +/* This structure and the following functions are needed for the
    + * table-based config file reading. They are passed to the
    + * cfg_open_custom() routine.
    + */
    +
    +/* Structure to be passed to cfg_open_custom(): it contains an
    + * index which is incremented from 0 to nelts on each call to
    + * cfg_getline() (which in turn calls arr_elts_getstr())
    + * and an array_header pointer for the string array.
    + */
    +typedef struct {
    +    array_header *array;
    +    int curr_idx;
    +} arr_elts_param_t;
    +
    +
    +/* arr_elts_getstr() returns the next line from the string array. */
    +static void *arr_elts_getstr(void *buf, size_t bufsiz, void *param)
    +{
    +    arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
    +
    +    /* End of array reached? */
    +    if (++arr_param->curr_idx > arr_param->array->nelts)
    +        return NULL;
    +
    +    /* return the line */
    +    ap_cpystrn(buf, ((char **) arr_param->array->elts)[arr_param->curr_idx - 1], bufsiz);
    +
    +    return buf;
    +}
    +
    +
    +/* arr_elts_close(): dummy close routine (makes sure no more lines can be read) */
    +static int arr_elts_close(void *param)
    +{
    +    arr_elts_param_t *arr_param = (arr_elts_param_t *) param;
    +    arr_param->curr_idx = arr_param->array->nelts;
    +    return 0;
    +}
    +
    +static void process_command_config(server_rec *s, array_header *arr, pool *p,
    +				    pool *ptemp)
    +{
    +    const char *errmsg;
    +    cmd_parms parms;
    +    arr_elts_param_t arr_parms;
    +
    +    arr_parms.curr_idx = 0;
    +    arr_parms.array = arr;
    +
    +    parms = default_parms;
    +    parms.pool = p;
    +    parms.temp_pool = ptemp;
    +    parms.server = s;
    +    parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
    +    parms.config_file = ap_pcfg_open_custom(p, "-c/-C directives",
    +                                         &arr_parms, NULL,
    +                                         arr_elts_getstr, arr_elts_close);
    +
    +    errmsg = ap_srm_command_loop(&parms, s->lookup_defaults);
    +
    +    if (errmsg) {
    +        fprintf(stderr, "Syntax error in -C/-c directive:\n%s\n", errmsg);
    +        exit(1);
    +    }
    +
    +    ap_cfg_closefile(parms.config_file);
    +}
    +
    +void ap_process_resource_config(server_rec *s, char *fname, pool *p, pool *ptemp)
    +{
    +    const char *errmsg;
    +    cmd_parms parms;
    +    struct stat finfo;
    +
    +    fname = ap_server_root_relative(p, fname);
    +
    +    if (!(strcmp(fname, ap_server_root_relative(p, RESOURCE_CONFIG_FILE))) ||
    +	!(strcmp(fname, ap_server_root_relative(p, ACCESS_CONFIG_FILE)))) {
    +	if (stat(fname, &finfo) == -1)
    +	    return;
    +    }
    +
    +    /* don't require conf/httpd.conf if we have a -C or -c switch */
    +    if((ap_server_pre_read_config->nelts || ap_server_post_read_config->nelts) &&
    +       !(strcmp(fname, ap_server_root_relative(p, SERVER_CONFIG_FILE)))) {
    +	if (stat(fname, &finfo) == -1)
    +	    return;
    +    }
    +
    +    /* GCC's initialization extensions are soooo nice here... */
    +
    +    parms = default_parms;
    +    parms.pool = p;
    +    parms.temp_pool = ptemp;
    +    parms.server = s;
    +    parms.override = (RSRC_CONF | OR_ALL) & ~(OR_AUTHCFG | OR_LIMIT);
    +
    +    if (!(parms.config_file = ap_pcfg_openfile(p,fname))) {
    +	perror("fopen");
    +	fprintf(stderr, "httpd: could not open document config file %s\n",
    +		fname);
    +	exit(1);
    +    }
    +
    +    errmsg = ap_srm_command_loop(&parms, s->lookup_defaults);
    +
    +    if (errmsg) {
    +	fprintf(stderr, "Syntax error on line %d of %s:\n",
    +		parms.config_file->line_number, fname);
    +	fprintf(stderr, "%s\n", errmsg);
    +	exit(1);
    +    }
    +
    +    ap_cfg_closefile(parms.config_file);
    +}
    +
    +
    +int ap_parse_htaccess(void **result, request_rec *r, int override,
    +		   const char *d, const char *access_name)
    +{
    +    configfile_t *f = NULL;
    +    cmd_parms parms;
    +    const char *errmsg;
    +    char *filename = NULL;
    +    const struct htaccess_result *cache;
    +    struct htaccess_result *new;
    +    void *dc;
    +
    +/* firstly, search cache */
    +    for (cache = r->htaccess; cache != NULL; cache = cache->next)
    +	if (cache->override == override && strcmp(cache->dir, d) == 0) {
    +	    if (cache->htaccess != NULL)
    +		*result = cache->htaccess;
    +	    return OK;
    +	}
    +
    +    parms = default_parms;
    +    parms.override = override;
    +    parms.pool = r->pool;
    +    parms.temp_pool = r->pool;
    +    parms.server = r->server;
    +    parms.path = ap_pstrdup(r->pool, d);
    +
    +    /* loop through the access names and find the first one */
    +    while (!f && access_name[0]) {
    +	char *w = ap_getword_conf(r->pool, &access_name);
    +	filename = ap_make_full_path(r->pool, d, w);
    +	f = ap_pcfg_openfile(r->pool, filename);
    +    }
    +    if (f) {
    +	dc = ap_create_per_dir_config(r->pool);
    +
    +	parms.config_file = f;
    +
    +	errmsg = ap_srm_command_loop(&parms, dc);
    +
    +	ap_cfg_closefile(f);
    +
    +	if (errmsg) {
    +	    ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, r->server, "%s: %s",
    +                        filename, errmsg);
    +            return HTTP_INTERNAL_SERVER_ERROR;
    +	}
    +
    +	*result = dc;
    +    }
    +    else {
    +	if (errno == ENOENT || errno == ENOTDIR)
    +	    dc = NULL;
    +	else {
    +	    ap_log_error(APLOG_MARK, APLOG_CRIT, r->server,
    +			"%s pcfg_openfile: unable to check htaccess file, ensure it is readable",
    +			filename);
    +	    return HTTP_FORBIDDEN;
    +	}
    +    }
    +
    +/* cache it */
    +    new = ap_palloc(r->pool, sizeof(struct htaccess_result));
    +    new->dir = parms.path;
    +    new->override = override;
    +    new->htaccess = dc;
    +/* add to head of list */
    +    new->next = r->htaccess;
    +    r->htaccess = new;
    +
    +    return OK;
    +}
    +
    +
    +CORE_EXPORT(const char *) ap_init_virtual_host(pool *p, const char *hostname,
    +			      server_rec *main_server, server_rec **ps)
    +{
    +    server_rec *s = (server_rec *) ap_pcalloc(p, sizeof(server_rec));
    +
    +#ifdef RLIMIT_NOFILE
    +    struct rlimit limits;
    +
    +    getrlimit(RLIMIT_NOFILE, &limits);
    +    if (limits.rlim_cur < limits.rlim_max) {
    +	limits.rlim_cur += 2;
    +	if (setrlimit(RLIMIT_NOFILE, &limits) < 0) {
    +	    perror("setrlimit(RLIMIT_NOFILE)");
    +	    fprintf(stderr, "Cannot exceed hard limit for open files");
    +	}
    +    }
    +#endif
    +
    +    s->server_admin = NULL;
    +    s->server_hostname = NULL;
    +    s->error_fname = NULL;
    +    s->srm_confname = NULL;
    +    s->access_confname = NULL;
    +    s->timeout = 0;
    +    s->keep_alive_timeout = 0;
    +    s->keep_alive = -1;
    +    s->keep_alive_max = -1;
    +    s->error_log = main_server->error_log;
    +    s->loglevel = main_server->loglevel;
    +    /* useful default, otherwise we get a port of 0 on redirects */
    +    s->port = main_server->port;
    +    s->next = NULL;
    +
    +    s->is_virtual = 1;
    +    s->names = ap_make_array(p, 4, sizeof(char **));
    +    s->wild_names = ap_make_array(p, 4, sizeof(char **));
    +
    +    s->module_config = create_empty_config(p);
    +    s->lookup_defaults = ap_create_per_dir_config(p);
    +
    +    s->server_uid = ap_user_id;
    +    s->server_gid = ap_group_id;
    +
    +    *ps = s;
    +
    +    return ap_parse_vhost_addrs(p, hostname, s);
    +}
    +
    +
    +static void fixup_virtual_hosts(pool *p, server_rec *main_server)
    +{
    +    server_rec *virt;
    +
    +    for (virt = main_server->next; virt; virt = virt->next) {
    +	merge_server_configs(p, main_server->module_config,
    +			     virt->module_config);
    +
    +	virt->lookup_defaults =
    +	    ap_merge_per_dir_configs(p, main_server->lookup_defaults,
    +				  virt->lookup_defaults);
    +
    +	if (virt->server_admin == NULL)
    +	    virt->server_admin = main_server->server_admin;
    +
    +	if (virt->srm_confname == NULL)
    +	    virt->srm_confname = main_server->srm_confname;
    +
    +	if (virt->access_confname == NULL)
    +	    virt->access_confname = main_server->access_confname;
    +
    +	if (virt->timeout == 0)
    +	    virt->timeout = main_server->timeout;
    +
    +	if (virt->keep_alive_timeout == 0)
    +	    virt->keep_alive_timeout = main_server->keep_alive_timeout;
    +
    +	if (virt->keep_alive == -1)
    +	    virt->keep_alive = main_server->keep_alive;
    +
    +	if (virt->keep_alive_max == -1)
    +	    virt->keep_alive_max = main_server->keep_alive_max;
    +
    +	if (virt->send_buffer_size == 0)
    +	    virt->send_buffer_size = main_server->send_buffer_size;
    +
    +	/* XXX: this is really something that should be dealt with by a
    +	 * post-config api phase */
    +	ap_core_reorder_directories(p, virt);
    +    }
    +    ap_core_reorder_directories(p, main_server);
    +}
    +
    +/*****************************************************************
    + *
    + * Getting *everything* configured... 
    + */
    +
    +static void init_config_globals(pool *p)
    +{
    +    /* ServerRoot, server_confname set in httpd.c */
    +
    +    ap_standalone = 1;
    +    ap_user_name = DEFAULT_USER;
    +    ap_user_id = ap_uname2id(DEFAULT_USER);
    +    ap_group_id = ap_gname2id(DEFAULT_GROUP);
    +    ap_daemons_to_start = DEFAULT_START_DAEMON;
    +    ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
    +    ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
    +    ap_daemons_limit = HARD_SERVER_LIMIT;
    +    ap_pid_fname = DEFAULT_PIDLOG;
    +    ap_scoreboard_fname = DEFAULT_SCOREBOARD;
    +    ap_lock_fname = DEFAULT_LOCKFILE;
    +    ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
    +    ap_bind_address.s_addr = htonl(INADDR_ANY);
    +    ap_listeners = NULL;
    +    ap_listenbacklog = DEFAULT_LISTENBACKLOG;
    +
    +    /* Global virtual host hash bucket pointers.  Init to null. */
    +    ap_init_vhost_config(p);
    +
    +    ap_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
    +}
    +
    +static server_rec *init_server_config(pool *p)
    +{
    +    server_rec *s = (server_rec *) ap_pcalloc(p, sizeof(server_rec));
    +
    +    s->port = 0;
    +    s->server_admin = DEFAULT_ADMIN;
    +    s->server_hostname = NULL;
    +    s->error_fname = DEFAULT_ERRORLOG;
    +    s->error_log = stderr;
    +    s->loglevel = DEFAULT_LOGLEVEL;
    +    s->srm_confname = RESOURCE_CONFIG_FILE;
    +    s->access_confname = ACCESS_CONFIG_FILE;
    +    s->timeout = DEFAULT_TIMEOUT;
    +    s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
    +    s->keep_alive_max = DEFAULT_KEEPALIVE;
    +    s->keep_alive = 1;
    +    s->next = NULL;
    +    s->addrs = ap_pcalloc(p, sizeof(server_addr_rec));
    +    /* NOT virtual host; don't match any real network interface */
    +    s->addrs->host_addr.s_addr = htonl(INADDR_ANY);
    +    s->addrs->host_port = 0;	/* matches any port */
    +    s->addrs->virthost = "";	/* must be non-NULL */
    +    s->names = s->wild_names = NULL;
    +
    +    s->module_config = create_server_config(p, s);
    +    s->lookup_defaults = create_default_per_dir_config(p);
    +
    +    return s;
    +}
    +
    +
    +static void default_listeners(pool *p, server_rec *s)
    +{
    +    listen_rec *new;
    +
    +    if (ap_listeners != NULL) {
    +	return;
    +    }
    +    /* allocate a default listener */
    +    new = ap_pcalloc(p, sizeof(listen_rec));
    +    new->local_addr.sin_family = AF_INET;
    +    new->local_addr.sin_addr = ap_bind_address;
    +    new->local_addr.sin_port = htons(s->port ? s->port : DEFAULT_HTTP_PORT);
    +    new->fd = -1;
    +    new->used = 0;
    +    new->next = NULL;
    +    ap_listeners = new;
    +}
    +
    +
    +server_rec *ap_read_config(pool *p, pool *ptemp, char *confname)
    +{
    +    server_rec *s = init_server_config(p);
    +
    +    init_config_globals(p);
    +
    +    /* All server-wide config files now have the SAME syntax... */
    +
    +    process_command_config(s, ap_server_pre_read_config, p, ptemp);
    +
    +    ap_process_resource_config(s, confname, p, ptemp);
    +    ap_process_resource_config(s, s->srm_confname, p, ptemp);
    +    ap_process_resource_config(s, s->access_confname, p, ptemp);
    +
    +    process_command_config(s, ap_server_post_read_config, p, ptemp);
    +
    +    fixup_virtual_hosts(p, s);
    +    default_listeners(p, s);
    +    ap_fini_vhost_config(p, s);
    +
    +    return s;
    +}
    +
    +
    +void ap_init_modules(pool *p, server_rec *s)
    +{
    +    module *m;
    +
    +    for (m = top_module; m; m = m->next)
    +	if (m->init)
    +	    (*m->init) (s, p);
    +    build_method_shortcuts();
    +    init_handlers(p);
    +}
    +
    +void ap_child_init_modules(pool *p, server_rec *s)
    +{
    +    module *m;
    +
    +    for (m = top_module; m; m = m->next)
    +	if (m->child_init)
    +	    (*m->child_init) (s, p);
    +}
    +
    +void ap_child_exit_modules(pool *p, server_rec *s)
    +{
    +    module *m;
    +
    +#ifdef SIGHUP
    +    signal(SIGHUP, SIG_IGN);
    +#endif
    +#ifdef SIGUSR1
    +    signal(SIGUSR1, SIG_IGN);
    +#endif
    +
    +    for (m = top_module; m; m = m->next)
    +	if (m->child_exit)
    +	    (*m->child_exit) (s, p);
    +
    +}
    +
    +/********************************************************************
    + * Configuration directives are restricted in terms of where they may
    + * appear in the main configuration files and/or .htaccess files according
    + * to the bitmask req_override in the command_rec structure.
    + * If any of the overrides set in req_override are also allowed in the
    + * context in which the command is read, then the command is allowed.
    + * The context is determined as follows:
    + *
    + *    inside *.conf --> override = (RSRC_CONF|OR_ALL)&~(OR_AUTHCFG|OR_LIMIT);
    + *    within <Directory> or <Location> --> override = OR_ALL|ACCESS_CONF;
    + *    within .htaccess --> override = AllowOverride for current directory;
    + *
    + * the result is, well, a rather confusing set of possibilities for when
    + * a particular directive is allowed to be used.  This procedure prints
    + * in English where the given (pc) directive can be used.
    + */
    +static void show_overrides(const command_rec *pc, module *pm)
    +{
    +    int n = 0;
    +
    +    printf("\tAllowed in *.conf ");
    +    if ((pc->req_override & (OR_OPTIONS | OR_FILEINFO | OR_INDEXES)) ||
    +	((pc->req_override & RSRC_CONF) &&
    +	 ((pc->req_override & (ACCESS_CONF | OR_AUTHCFG | OR_LIMIT)))))
    +	printf("anywhere");
    +    else if (pc->req_override & RSRC_CONF)
    +	printf("only outside <Directory> or <Location>");
    +    else
    +	printf("only inside <Directory> or <Location>");
    +
    +    /* Warn if the directive is allowed inside <Directory> or .htaccess
    +     * but module doesn't support per-dir configuration */
    +
    +    if ((pc->req_override & (OR_ALL | ACCESS_CONF)) && !pm->create_dir_config)
    +	printf(" [no per-dir config]");
    +
    +    if (pc->req_override & OR_ALL) {
    +	printf(" and in .htaccess\n\twhen AllowOverride");
    +
    +	if ((pc->req_override & OR_ALL) == OR_ALL)
    +	    printf(" isn't None");
    +	else {
    +	    printf(" includes ");
    +
    +	    if (pc->req_override & OR_AUTHCFG) {
    +		if (n++)
    +		    printf(" or ");
    +		printf("AuthConfig");
    +	    }
    +	    if (pc->req_override & OR_LIMIT) {
    +		if (n++)
    +		    printf(" or ");
    +		printf("Limit");
    +	    }
    +	    if (pc->req_override & OR_OPTIONS) {
    +		if (n++)
    +		    printf(" or ");
    +		printf("Options");
    +	    }
    +	    if (pc->req_override & OR_FILEINFO) {
    +		if (n++)
    +		    printf(" or ");
    +		printf("FileInfo");
    +	    }
    +	    if (pc->req_override & OR_INDEXES) {
    +		if (n++)
    +		    printf(" or ");
    +		printf("Indexes");
    +	    }
    +	}
    +    }
    +    printf("\n");
    +}
    +
    +/* Show the preloaded configuration directives, the help string explaining
    + * the directive arguments, in what module they are handled, and in
    + * what parts of the configuration they are allowed.  Used for httpd -h.
    + */
    +void ap_show_directives()
    +{
    +    const command_rec *pc;
    +    int n;
    +
    +    for (n = 0; ap_loaded_modules[n]; ++n)
    +	for (pc = ap_loaded_modules[n]->cmds; pc && pc->name; ++pc) {
    +	    printf("%s (%s)\n", pc->name, ap_loaded_modules[n]->name);
    +	    if (pc->errmsg)
    +		printf("\t%s\n", pc->errmsg);
    +	    show_overrides(pc, ap_loaded_modules[n]);
    +	}
    +}
    +
    +/* Show the preloaded module names.  Used for httpd -l. */
    +void ap_show_modules()
    +{
    +    int n;
    +
    +    printf("Compiled-in modules:\n");
    +    for (n = 0; ap_loaded_modules[n]; ++n)
    +	printf("  %s\n", ap_loaded_modules[n]->name);
    +}
    diff --git a/APACHE_1_3b7/src/main/http_core.c b/APACHE_1_3b7/src/main/http_core.c
    new file mode 100644
    index 0000000000..16b22ef3b8
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/http_core.c
    @@ -0,0 +1,2269 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +#define CORE_PRIVATE
    +#include "httpd.h"
    +#include "http_config.h"
    +#include "http_core.h"
    +#include "http_protocol.h"	/* For index_of_response().  Grump. */
    +#include "http_request.h"
    +#include "http_conf_globals.h"
    +#include "http_vhost.h"
    +#include "http_main.h"		/* For the default_handler below... */
    +#include "http_log.h"
    +#include "rfc1413.h"
    +#include "util_md5.h"
    +#include "scoreboard.h"
    +#include "fnmatch.h"
    +
    +#ifdef USE_MMAP_FILES
    +#include <sys/mman.h>
    +
    +/* mmap support for static files based on ideas from John Heidemann's
    + * patch against 1.0.5.  See
    + * <http://www.isi.edu/~johnh/SOFTWARE/APACHE/index.html>.
    + */
    +
    +/* Files have to be at least this big before they're mmap()d.  This is to deal
    + * with systems where the expense of doing an mmap() and an munmap() outweighs
    + * the benefit for small files.  It shouldn't be set lower than 1.
    + */
    +#ifndef MMAP_THRESHOLD
    +#ifdef SUNOS4
    +#define MMAP_THRESHOLD		(8*1024)
    +#else
    +#define MMAP_THRESHOLD		1
    +#endif
    +#endif
    +#endif
    +
    +/* Server core module... This module provides support for really basic
    + * server operations, including options and commands which control the
    + * operation of other modules.  Consider this the bureaucracy module.
    + *
    + * The core module also defines handlers, etc., do handle just enough
    + * to allow a server with the core module ONLY to actually serve documents
    + * (though it slaps DefaultType on all of 'em); this was useful in testing,
    + * but may not be worth preserving.
    + *
    + * This file could almost be mod_core.c, except for the stuff which affects
    + * the http_conf_globals.
    + */
    +
    +static void *create_core_dir_config (pool *a, char *dir)
    +{
    +    core_dir_config *conf =
    +      (core_dir_config *)ap_pcalloc(a, sizeof(core_dir_config));
    +  
    +    if (!dir || dir[strlen(dir) - 1] == '/') conf->d = dir;
    +    else if (strncmp(dir,"proxy:",6)==0) conf->d = ap_pstrdup (a, dir);
    +    else conf->d = ap_pstrcat (a, dir, "/", NULL);
    +    conf->d_is_fnmatch = conf->d ? (ap_is_fnmatch (conf->d) != 0) : 0;
    +    conf->d_components = conf->d ? ap_count_dirs (conf->d) : 0;
    +
    +    conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
    +    conf->opts_add = conf->opts_remove = OPT_NONE;
    +    conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
    +
    +    conf->content_md5 = 2;
    +
    +    conf->use_canonical_name = 1 | 2;	/* 2 = unset, default on */
    +
    +    conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
    +    conf->do_rfc1413 = DEFAULT_RFC1413 | 2;  /* set bit 1 to indicate default */
    +    conf->satisfy = SATISFY_NOSPEC;
    +
    +#ifdef RLIMIT_CPU
    +    conf->limit_cpu = NULL;
    +#endif
    +#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
    +    conf->limit_mem = NULL;
    +#endif
    +#ifdef RLIMIT_NPROC
    +    conf->limit_nproc = NULL;
    +#endif
    +
    +    conf->sec = ap_make_array (a, 2, sizeof(void *));
    +
    +    return (void *)conf;
    +}
    +
    +static void *merge_core_dir_configs (pool *a, void *basev, void *newv)
    +{
    +    core_dir_config *base = (core_dir_config *)basev;
    +    core_dir_config *new = (core_dir_config *)newv;
    +    core_dir_config *conf =
    +      (core_dir_config *)ap_palloc (a, sizeof(core_dir_config));
    +    int i;
    +  
    +    memcpy ((char *)conf, (const char *)base, sizeof(core_dir_config));
    +    if( base->response_code_strings ) {
    +	conf->response_code_strings = ap_palloc(a,
    +	    sizeof(*conf->response_code_strings) * RESPONSE_CODES );
    +	memcpy( conf->response_code_strings, base->response_code_strings,
    +	    sizeof(*conf->response_code_strings) * RESPONSE_CODES );
    +    }
    +    
    +    conf->d = new->d;
    +    conf->d_is_fnmatch = new->d_is_fnmatch;
    +    conf->d_components = new->d_components;
    +    conf->r = new->r;
    +    
    +    if (new->opts & OPT_UNSET) {
    +	/* there was no explicit setting of new->opts, so we merge
    +	 * preserve the invariant (opts_add & opts_remove) == 0
    +	 */
    +	conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
    +	conf->opts_remove = (conf->opts_remove & ~new->opts_add) | new->opts_remove;
    +	conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
    +        if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES))
    +          conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
    +    }
    +    else {
    +	/* otherwise we just copy, because an explicit opts setting
    +	 * overrides all earlier +/- modifiers
    +	 */
    +	conf->opts = new->opts;
    +	conf->opts_add = new->opts_add;
    +	conf->opts_remove = new->opts_remove;
    +    }
    +
    +    if (!(new->override & OR_UNSET)) conf->override = new->override;
    +    if (new->ap_default_type) conf->ap_default_type = new->ap_default_type;
    +    
    +    if (new->ap_auth_type) conf->ap_auth_type = new->ap_auth_type;
    +    if (new->ap_auth_name) conf->ap_auth_name = new->ap_auth_name;
    +    if (new->ap_requires) conf->ap_requires = new->ap_requires;
    +
    +    if( new->response_code_strings ) {
    +	if( conf->response_code_strings == NULL ) {
    +	    conf->response_code_strings = ap_palloc(a,
    +		sizeof(*conf->response_code_strings) * RESPONSE_CODES );
    +	    memcpy( conf->response_code_strings, new->response_code_strings,
    +		sizeof(*conf->response_code_strings) * RESPONSE_CODES );
    +	} else {
    +	    for (i = 0; i < RESPONSE_CODES; ++i)
    +		if (new->response_code_strings[i] != NULL)
    +		conf->response_code_strings[i] = new->response_code_strings[i];
    +	}
    +    }
    +    if (new->hostname_lookups != HOSTNAME_LOOKUP_UNSET)
    +	conf->hostname_lookups = new->hostname_lookups;
    +    if ((new->do_rfc1413 & 2) == 0) conf->do_rfc1413 = new->do_rfc1413;
    +    if ((new->content_md5 & 2) == 0) conf->content_md5 = new->content_md5;
    +    if ((new->use_canonical_name & 2) == 0) {
    +	conf->use_canonical_name = new->use_canonical_name;
    +    }
    +
    +#ifdef RLIMIT_CPU
    +    if (new->limit_cpu) conf->limit_cpu = new->limit_cpu;
    +#endif
    +#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
    +    if (new->limit_mem) conf->limit_mem = new->limit_mem;
    +#endif
    +#ifdef RLIMIT_NPROC    
    +    if (new->limit_nproc) conf->limit_nproc = new->limit_nproc;
    +#endif
    +
    +    conf->sec = ap_append_arrays (a, base->sec, new->sec);
    +
    +    if (new->satisfy != SATISFY_NOSPEC) conf->satisfy = new->satisfy;
    +    return (void*)conf;
    +}
    +
    +static void *create_core_server_config (pool *a, server_rec *s)
    +{
    +    core_server_config *conf =
    +      (core_server_config *)ap_pcalloc(a, sizeof(core_server_config));
    +    int is_virtual = s->is_virtual;
    +  
    +    conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
    +    conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
    +    conf->sec = ap_make_array (a, 40, sizeof(void *));
    +    conf->sec_url = ap_make_array (a, 40, sizeof(void *));
    +    
    +    return (void *)conf;
    +}
    +
    +static void *merge_core_server_configs (pool *p, void *basev, void *virtv)
    +{
    +    core_server_config *base = (core_server_config *)basev;
    +    core_server_config *virt = (core_server_config *)virtv;
    +    core_server_config *conf = 
    +	(core_server_config *)ap_pcalloc(p, sizeof(core_server_config));
    +
    +    *conf = *virt;
    +    if (!conf->access_name) conf->access_name = base->access_name;
    +    if (!conf->ap_document_root) conf->ap_document_root = base->ap_document_root;
    +    conf->sec = ap_append_arrays (p, base->sec, virt->sec);
    +    conf->sec_url = ap_append_arrays (p, base->sec_url, virt->sec_url);
    +
    +    return conf;
    +}
    +
    +/* Add per-directory configuration entry (for <directory> section);
    + * these are part of the core server config.
    + */
    +
    +CORE_EXPORT(void) ap_add_per_dir_conf (server_rec *s, void *dir_config)
    +{
    +    core_server_config *sconf = ap_get_module_config (s->module_config,
    +						   &core_module);
    +    void **new_space = (void **) ap_push_array (sconf->sec);
    +    
    +    *new_space = dir_config;
    +}
    +
    +CORE_EXPORT(void) ap_add_per_url_conf (server_rec *s, void *url_config)
    +{
    +    core_server_config *sconf = ap_get_module_config (s->module_config,
    +						   &core_module);
    +    void **new_space = (void **) ap_push_array (sconf->sec_url);
    +    
    +    *new_space = url_config;
    +}
    +
    +static void add_file_conf (core_dir_config *conf, void *url_config)
    +{
    +    void **new_space = (void **) ap_push_array (conf->sec);
    +    
    +    *new_space = url_config;
    +}
    +
    +/* core_reorder_directories reorders the directory sections such that the
    + * 1-component sections come first, then the 2-component, and so on, finally
    + * followed by the "special" sections.  A section is "special" if it's a regex,
    + * or if it doesn't start with / -- consider proxy: matching.  All movements
    + * are in-order to preserve the ordering of the sections from the config files.
    + * See directory_walk().
    + */
    +
    +#if defined(__EMX__) || defined(WIN32)
    +#define IS_SPECIAL(entry_core)	\
    +    ((entry_core)->r != NULL \
    +	|| ((entry_core)->d[0] != '/' && (entry_core)->d[1] != ':'))
    +#else
    +#define IS_SPECIAL(entry_core)	\
    +    ((entry_core)->r != NULL || (entry_core)->d[0] != '/')
    +#endif
    +
    +/* We need to do a stable sort, qsort isn't stable.  So to make it stable
    + * we'll be maintaining the original index into the list, and using it
    + * as the minor key during sorting.  The major key is the number of
    + * components (where a "special" section has infinite components).
    + */
    +struct reorder_sort_rec {
    +    void *elt;
    +    int orig_index;
    +};
    +
    +static int reorder_sorter (const void *va, const void *vb)
    +{
    +    const struct reorder_sort_rec *a = va;
    +    const struct reorder_sort_rec *b = vb;
    +    core_dir_config *core_a;
    +    core_dir_config *core_b;
    +
    +    core_a = (core_dir_config *)ap_get_module_config (a->elt, &core_module);
    +    core_b = (core_dir_config *)ap_get_module_config (b->elt, &core_module);
    +    if (IS_SPECIAL(core_a)) {
    +	if (!IS_SPECIAL(core_b)) {
    +	    return 1;
    +	}
    +    } else if (IS_SPECIAL(core_b)) {
    +	return -1;
    +    } else {
    +	/* we know they're both not special */
    +	if (core_a->d_components < core_b->d_components) {
    +	    return -1;
    +	} else if (core_a->d_components > core_b->d_components) {
    +	    return 1;
    +	}
    +    }
    +    /* Either they're both special, or they're both not special and have the
    +     * same number of components.  In any event, we now have to compare
    +     * the minor key. */
    +    return a->orig_index - b->orig_index;
    +}
    +
    +void ap_core_reorder_directories (pool *p, server_rec *s)
    +{
    +    core_server_config *sconf;
    +    array_header *sec;
    +    struct reorder_sort_rec *sortbin;
    +    int nelts;
    +    void **elts;
    +    int i;
    +
    +    /* XXX: we are about to waste some ram ... we will build a new array
    +     * and we need some scratch space to do it.  The old array and the
    +     * scratch space are never freed.
    +     */
    +    sconf = ap_get_module_config (s->module_config, &core_module);
    +    sec = sconf->sec;
    +    nelts = sec->nelts;
    +    elts = (void **)sec->elts;
    +
    +    /* build our sorting space */
    +    sortbin = ap_palloc (p, sec->nelts * sizeof (*sortbin));
    +    for (i = 0; i < nelts; ++i) {
    +	sortbin[i].orig_index = i;
    +	sortbin[i].elt = elts[i];
    +    }
    +
    +    qsort (sortbin, nelts, sizeof (*sortbin), reorder_sorter);
    +
    +    /* and now build a new array */
    +    sec = ap_make_array (p, nelts, sizeof (void *));
    +    for (i = 0; i < nelts; ++i) {
    +	*(void **)ap_push_array (sec) = sortbin[i].elt;
    +    }
    +
    +    sconf->sec = sec;
    +}
    +
    +/*****************************************************************
    + *
    + * There are some elements of the core config structures in which
    + * other modules have a legitimate interest (this is ugly, but necessary
    + * to preserve NCSA back-compatibility).  So, we have a bunch of accessors
    + * here...
    + */
    +
    +API_EXPORT(int) ap_allow_options (request_rec *r)
    +{
    +    core_dir_config *conf = 
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); 
    +
    +    return conf->opts; 
    +} 
    +
    +API_EXPORT(int) ap_allow_overrides (request_rec *r) 
    +{ 
    +    core_dir_config *conf = 
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); 
    +
    +    return conf->override; 
    +} 
    +
    +API_EXPORT(char *) ap_auth_type (request_rec *r)
    +{
    +    core_dir_config *conf = 
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); 
    +
    +    return conf->ap_auth_type;
    +}
    +
    +API_EXPORT(char *) ap_auth_name (request_rec *r)
    +{
    +    core_dir_config *conf = 
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); 
    +
    +    return conf->ap_auth_name;
    +}
    +
    +API_EXPORT(char *) ap_default_type (request_rec *r)
    +{
    +    core_dir_config *conf = 
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); 
    +
    +    return conf->ap_default_type ? conf->ap_default_type : DEFAULT_CONTENT_TYPE;
    +}
    +
    +API_EXPORT(char *) ap_document_root (request_rec *r) /* Don't use this!!! */
    +{
    +    core_server_config *conf = 
    +      (core_server_config *)ap_get_module_config(r->server->module_config,
    +					      &core_module); 
    +
    +    return conf->ap_document_root;
    +}
    +
    +API_EXPORT(array_header *) ap_requires (request_rec *r)
    +{
    +    core_dir_config *conf = 
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); 
    +
    +    return conf->ap_requires;
    +}
    +
    +API_EXPORT(int) ap_satisfies (request_rec *r)
    +{
    +    core_dir_config *conf =
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
    +
    +    return conf->satisfy;
    +}
    +
    +/* Should probably just get rid of this... the only code that cares is
    + * part of the core anyway (and in fact, it isn't publicised to other
    + * modules).
    + */
    +
    +char *ap_response_code_string (request_rec *r, int error_index)
    +{
    +    core_dir_config *conf = 
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); 
    +
    +    if( conf->response_code_strings == NULL ) {
    +	return NULL;
    +    }
    +    return conf->response_code_strings[error_index];
    +}
    +
    +
    +/* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
    +static ap_inline void do_double_reverse (conn_rec *conn)
    +{
    +    struct hostent *hptr;
    +
    +    if (conn->double_reverse) {
    +	/* already done */
    +	return;
    +    }
    +    if (conn->remote_host == NULL || conn->remote_host[0] == '\0') {
    +	/* single reverse failed, so don't bother */
    +	conn->double_reverse = -1;
    +	return;
    +    }
    +    hptr = gethostbyname(conn->remote_host);
    +    if (hptr) {
    +	char **haddr;
    +
    +	for (haddr = hptr->h_addr_list; *haddr; haddr++) {
    +	    if (((struct in_addr *)(*haddr))->s_addr
    +		== conn->remote_addr.sin_addr.s_addr) {
    +		conn->double_reverse = 1;
    +		return;
    +	    }
    +	}
    +    }
    +    conn->double_reverse = -1;
    +}
    +
    +API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config, int type)
    +{
    +    struct in_addr *iaddr;
    +    struct hostent *hptr;
    +    int hostname_lookups;
    +#ifdef STATUS
    +    int old_stat = SERVER_DEAD;	/* we shouldn't ever be in this state */
    +#endif
    +
    +    /* If we haven't checked the host name, and we want to */
    +    if (dir_config) {
    +	hostname_lookups =
    +	    ((core_dir_config *)ap_get_module_config(dir_config, &core_module))
    +		->hostname_lookups;
    +	if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
    +	    hostname_lookups = HOSTNAME_LOOKUP_OFF;
    +	}
    +    } else {
    +	/* the default */
    +	hostname_lookups = HOSTNAME_LOOKUP_OFF;
    +    }
    +
    +    if (type != REMOTE_NOLOOKUP
    +	&& conn->remote_host == NULL
    +	&& (type == REMOTE_DOUBLE_REV
    +	    || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
    +#ifdef STATUS
    +	old_stat = ap_update_child_status(conn->child_num, SERVER_BUSY_DNS,
    +					    (request_rec*)NULL);
    +#endif /* STATUS */
    +	iaddr = &(conn->remote_addr.sin_addr);
    +	hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
    +	if (hptr != NULL) {
    +	    conn->remote_host = ap_pstrdup(conn->pool, (void *)hptr->h_name);
    +	    ap_str_tolower (conn->remote_host);
    +	   
    +	    if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
    +		do_double_reverse (conn);
    +		if (conn->double_reverse != 1) {
    +		    conn->remote_host = NULL;
    +		}
    +	    }
    +	}
    +	/* if failed, set it to the NULL string to indicate error */
    +	if (conn->remote_host == NULL) conn->remote_host = "";
    +    }
    +    if (type == REMOTE_DOUBLE_REV) {
    +	do_double_reverse (conn);
    +	if (conn->double_reverse == -1) {
    +	    return NULL;
    +	}
    +    }
    +#ifdef STATUS
    +    if (old_stat != SERVER_DEAD) {
    +	(void)ap_update_child_status(conn->child_num,old_stat,(request_rec*)NULL);
    +    }
    +#endif /* STATUS */
    +
    +/*
    + * Return the desired information; either the remote DNS name, if found,
    + * or either NULL (if the hostname was requested) or the IP address
    + * (if any identifier was requested).
    + */
    +    if (conn->remote_host != NULL && conn->remote_host[0] != '\0')
    +	return conn->remote_host;
    +    else
    +    {
    +	if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) return NULL;
    +	else return conn->remote_ip;
    +    }
    +}
    +
    +API_EXPORT(const char *) ap_get_remote_logname(request_rec *r)
    +{
    +    core_dir_config *dir_conf;
    +
    +    if (r->connection->remote_logname != NULL)
    +	return r->connection->remote_logname;
    +
    +/* If we haven't checked the identity, and we want to */
    +    dir_conf = (core_dir_config *)
    +	ap_get_module_config(r->per_dir_config, &core_module);
    +
    +    if (dir_conf->do_rfc1413 & 1)
    +	return ap_rfc1413(r->connection, r->server);
    +    else
    +	return NULL;
    +}
    +
    +/* There are two options regarding what the "name" of a server is.  The
    + * "canonical" name as defined by ServerName and Port, or the "client's
    + * name" as supplied by a possible Host: header or full URI.  We never
    + * trust the port passed in the client's headers, we always use the
    + * port of the actual socket.
    + */
    +API_EXPORT(const char *) ap_get_server_name(const request_rec *r)
    +{
    +    core_dir_config *d =
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
    +    
    +    if (d->use_canonical_name & 1) {
    +	return r->server->server_hostname;
    +    }
    +    return r->hostname ? r->hostname : r->server->server_hostname;
    +}
    +
    +API_EXPORT(unsigned) ap_get_server_port(const request_rec *r)
    +{
    +    unsigned port;
    +    core_dir_config *d =
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
    +    
    +    port = r->server->port ? r->server->port : default_port(r);
    +
    +    if (d->use_canonical_name & 1) {
    +	return port;
    +    }
    +    return r->hostname ? ntohs(r->connection->local_addr.sin_port)
    +			: port;
    +}
    +
    +API_EXPORT(char *) ap_construct_url(pool *p, const char *uri, const request_rec *r)
    +{
    +    unsigned port;
    +    const char *host;
    +    core_dir_config *d =
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
    +
    +    if (d->use_canonical_name & 1) {
    +	port = r->server->port ? r->server->port : default_port(r);
    +	host = r->server->server_hostname;
    +    }
    +    else {
    +        if (r->hostname)
    +            port = ntohs(r->connection->local_addr.sin_port);
    +        else if (r->server->port)
    +            port = r->server->port;
    +        else
    +            port = default_port(r);
    +
    +	host = r->hostname ? r->hostname : r->server->server_hostname;
    +    }
    +    if (is_default_port(port, r)) {
    +	return ap_pstrcat(p, http_method(r), "://", host, uri, NULL);
    +    }
    +    return ap_psprintf(p, "%s://%s:%u%s", http_method(r), host, port, uri);
    +}
    +
    +/*****************************************************************
    + *
    + * Commands... this module handles almost all of the NCSA httpd.conf
    + * commands, but most of the old srm.conf is in the the modules.
    + */
    +
    +static const char end_directory_section[] = "</Directory>";
    +static const char end_directorymatch_section[] = "</DirectoryMatch>";
    +static const char end_location_section[] = "</Location>";
    +static const char end_locationmatch_section[] = "</LocationMatch>";
    +static const char end_files_section[] = "</Files>";
    +static const char end_filesmatch_section[] = "</FilesMatch>";
    +static const char end_virtualhost_section[] = "</VirtualHost>";
    +static const char end_ifmodule_section[] = "</IfModule>";
    +
    +
    +API_EXPORT(const char *) ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
    +{
    +    const char *gt = (cmd->cmd->name[0] == '<'
    +		   && cmd->cmd->name[strlen(cmd->cmd->name)-1] != '>') ? ">" : "";
    +
    +    if ((forbidden & NOT_IN_VIRTUALHOST) && cmd->server->is_virtual)
    +	return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
    +		       " cannot occur within <VirtualHost> section", NULL);
    +
    +    if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1)
    +	return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
    +		       " cannot occur within <Limit> section", NULL);
    +
    +    if ((forbidden & NOT_IN_DIR_LOC_FILE) == NOT_IN_DIR_LOC_FILE && cmd->path != NULL)
    +	return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
    +		       " cannot occur within <Directory/Location/Files> section", NULL);
    +    
    +    if (((forbidden & NOT_IN_DIRECTORY) && (cmd->end_token == end_directory_section
    +	    || cmd->end_token == end_directorymatch_section)) ||
    +	((forbidden & NOT_IN_LOCATION) && (cmd->end_token == end_location_section
    +	    || cmd->end_token == end_locationmatch_section)) ||
    +	((forbidden & NOT_IN_FILES) && (cmd->end_token == end_files_section
    +	    || cmd->end_token == end_filesmatch_section)))
    +	
    +	return ap_pstrcat(cmd->pool, cmd->cmd->name, gt,
    +		       " cannot occur within <", cmd->end_token+2,
    +		       " section", NULL);
    +
    +    return NULL;
    +}
    +
    +static const char *set_access_name (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    void *sconf = cmd->server->module_config;
    +    core_server_config *conf = ap_get_module_config (sconf, &core_module);
    +
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    conf->access_name = ap_pstrdup(cmd->pool, arg);
    +    return NULL;
    +}
    +
    +static const char *set_document_root (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    void *sconf = cmd->server->module_config;
    +    core_server_config *conf = ap_get_module_config (sconf, &core_module);
    +  
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    arg=ap_os_canonical_filename (cmd->pool, arg);
    +    if (!ap_is_directory (arg)) {
    +	if (cmd->server->is_virtual) {
    +	    fprintf (stderr, "Warning: DocumentRoot [%s] does not exist\n", arg);
    +	}
    +	else {
    +	    return "DocumentRoot must be a directory";
    +	}
    +    }
    +    
    +    conf->ap_document_root = arg;
    +    return NULL;
    +}
    +
    +static const char *set_error_document (cmd_parms *cmd, core_dir_config *conf,
    +				char *line)
    +{
    +    int error_number, index_number, idx500;
    +    char *w;
    +                
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    /* 1st parameter should be a 3 digit number, which we recognize;
    +     * convert it into an array index
    +     */
    +  
    +    w = ap_getword_conf_nc (cmd->pool, &line);
    +    error_number = atoi(w);
    +
    +    idx500 = ap_index_of_response(HTTP_INTERNAL_SERVER_ERROR);
    +
    +    if (error_number == HTTP_INTERNAL_SERVER_ERROR)
    +        index_number = idx500;
    +    else if ((index_number = ap_index_of_response(error_number)) == idx500)
    +        return ap_pstrcat(cmd->pool, "Unsupported HTTP response code ", w, NULL);
    +                
    +    /* Store it... */
    +
    +    if( conf->response_code_strings == NULL ) {
    +	conf->response_code_strings = ap_pcalloc(cmd->pool,
    +	    sizeof(*conf->response_code_strings) * RESPONSE_CODES );
    +    }
    +    conf->response_code_strings[index_number] = ap_pstrdup (cmd->pool, line);
    +
    +    return NULL;
    +}
    +
    +/* access.conf commands...
    + *
    + * The *only* thing that can appear in access.conf at top level is a
    + * <Directory> section.  NB we need to have a way to cut the srm_command_loop
    + * invoked by dirsection (i.e., <Directory>) short when </Directory> is seen.
    + * We do that by returning an error, which dirsection itself recognizes and
    + * discards as harmless.  Cheesy, but it works.
    + */
    +
    +static const char *set_override (cmd_parms *cmd, core_dir_config *d, const char *l)
    +{
    +    char *w;
    +  
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    +    if (err != NULL) {
    +        return err;
    +    }
    +
    +    d->override = OR_NONE;
    +    while(l[0]) {
    +        w = ap_getword_conf (cmd->pool, &l);
    +	if(!strcasecmp(w,"Limit"))
    +	    d->override |= OR_LIMIT;
    +	else if(!strcasecmp(w,"Options"))
    +	    d->override |= OR_OPTIONS;
    +	else if(!strcasecmp(w,"FileInfo"))
    +            d->override |= OR_FILEINFO;
    +	else if(!strcasecmp(w,"AuthConfig"))
    +	    d->override |= OR_AUTHCFG;
    +	else if(!strcasecmp(w,"Indexes"))
    +            d->override |= OR_INDEXES;
    +	else if(!strcasecmp(w,"None"))
    +	    d->override = OR_NONE;
    +	else if(!strcasecmp(w,"All")) 
    +	    d->override = OR_ALL;
    +	else 
    +	    return ap_pstrcat (cmd->pool, "Illegal override option ", w, NULL);
    +	d->override &= ~OR_UNSET;
    +    }
    +
    +    return NULL;
    +}
    +
    +static const char *set_options (cmd_parms *cmd, core_dir_config *d, const char *l)
    +{
    +    allow_options_t opt;
    +    int first = 1;
    +    char action;
    +
    +    while(l[0]) {
    +        char *w = ap_getword_conf(cmd->pool, &l);
    +	action = '\0';
    +
    +	if (*w == '+' || *w == '-')
    +	    action = *(w++);
    +	else if (first) {
    +  	    d->opts = OPT_NONE;
    +            first = 0;
    +        }
    +	    
    +	if(!strcasecmp(w,"Indexes"))
    +	    opt = OPT_INDEXES;
    +	else if(!strcasecmp(w,"Includes"))
    +	    opt = OPT_INCLUDES;
    +	else if(!strcasecmp(w,"IncludesNOEXEC"))
    +	    opt = (OPT_INCLUDES | OPT_INCNOEXEC);
    +	else if(!strcasecmp(w,"FollowSymLinks"))
    +	    opt = OPT_SYM_LINKS;
    +	else if(!strcasecmp(w,"SymLinksIfOwnerMatch"))
    +	    opt = OPT_SYM_OWNER;
    +	else if(!strcasecmp(w,"execCGI"))
    +	    opt = OPT_EXECCGI;
    +	else if (!strcasecmp(w,"MultiViews"))
    +	    opt = OPT_MULTI;
    +	else if (!strcasecmp(w,"RunScripts")) /* AI backcompat. Yuck */
    +	    opt = OPT_MULTI|OPT_EXECCGI;
    +	else if(!strcasecmp(w,"None")) 
    +	    opt = OPT_NONE;
    +	else if(!strcasecmp(w,"All")) 
    +	    opt = OPT_ALL;
    +	else 
    +	    return ap_pstrcat (cmd->pool, "Illegal option ", w, NULL);
    +
    +	/* we ensure the invariant (d->opts_add & d->opts_remove) == 0 */
    +	if (action == '-') {
    +	    d->opts_remove |= opt;
    +	    d->opts_add &= ~opt;
    +	    d->opts &= ~opt;
    +	}
    +	else if (action == '+') {
    +	    d->opts_add |= opt;
    +	    d->opts_remove &= ~opt;
    +	    d->opts |= opt;
    +	}
    +	else {
    +	    d->opts |= opt;
    +	}
    +    }
    +
    +    return NULL;
    +}
    +
    +static const char *satisfy (cmd_parms *cmd, core_dir_config *c, char *arg)
    +{
    +    if(!strcasecmp(arg,"all"))
    +        c->satisfy = SATISFY_ALL;
    +    else if(!strcasecmp(arg,"any"))
    +        c->satisfy = SATISFY_ANY;
    +    else
    +        return "Satisfy either 'any' or 'all'.";
    +    return NULL;
    +}
    +
    +static const char *require (cmd_parms *cmd, core_dir_config *c, char *arg)
    +{
    +    require_line *r;
    +  
    +    if (!c->ap_requires)
    +        c->ap_requires = ap_make_array (cmd->pool, 2, sizeof(require_line));
    +    
    +    r = (require_line *)ap_push_array (c->ap_requires);
    +    r->requirement = ap_pstrdup (cmd->pool, arg);
    +    r->method_mask = cmd->limited;
    +    return NULL;
    +}
    +
    +CORE_EXPORT_NONSTD(const char *) ap_limit_section (cmd_parms *cmd, void *dummy, const char *arg)
    +{
    +    const char *limited_methods = ap_getword(cmd->pool,&arg,'>');
    +    int limited = 0;
    +  
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    /* XXX: NB: Currently, we have no way of checking
    +     * whether <Limit> sections are closed properly.
    +     * (If we would add a srm_command_loop() here we might...)
    +     */
    +    
    +    while(limited_methods[0]) {
    +        char *method = ap_getword_conf (cmd->pool, &limited_methods);
    +	if(!strcasecmp(method,"GET")) limited |= (1 << M_GET);
    +	else if(!strcasecmp(method,"PUT")) limited |= (1 << M_PUT);
    +	else if(!strcasecmp(method,"POST")) limited |= (1 << M_POST);
    +	else if(!strcasecmp(method,"DELETE")) limited |= (1 << M_DELETE);
    +        else if(!strcasecmp(method,"CONNECT")) limited |= (1 << M_CONNECT);
    +	else if(!strcasecmp(method,"OPTIONS")) limited |= (1 << M_OPTIONS);
    +	else return "unknown method in <Limit>";
    +    }
    +
    +    cmd->limited = limited;
    +    return NULL;
    +}
    +
    +static const char *endlimit_section (cmd_parms *cmd, void *dummy, void *dummy2)
    +{
    +    if (cmd->limited == -1) return "</Limit> unexpected";
    +    
    +    cmd->limited = -1;
    +    return NULL;
    +}
    +
    +/*
    + * When a section is not closed properly when end-of-file is reached,
    + * then an error message should be printed:
    + */
    +static const char *missing_endsection (cmd_parms *cmd, int nest)
    +{
    +    if (nest < 2)
    +	return ap_psprintf(cmd->pool, "Missing %s directive at end-of-file",
    +		    cmd->end_token);
    +    return ap_psprintf(cmd->pool, "%d missing %s directives at end-of-file",
    +		    nest, cmd->end_token);
    +}
    +
    +/* We use this in <DirectoryMatch> and <FilesMatch>, to ensure that 
    + * people don't get bitten by wrong-cased regex matches
    + */
    +
    +#ifdef WIN32
    +#define USE_ICASE REG_ICASE
    +#else
    +#define USE_ICASE 0
    +#endif
    +
    +static const char *end_nested_section(cmd_parms *cmd, void *dummy)
    +{
    +    if (cmd->end_token == NULL) {
    +	return ap_pstrcat(cmd->pool, cmd->cmd->name,
    +	    " without matching <", cmd->cmd->name + 2, " section", NULL);
    +    }
    +    if (cmd->cmd->name != cmd->end_token) {
    +	return ap_pstrcat(cmd->pool, "Expected ", cmd->end_token, " but saw ",
    +	    cmd->cmd->name, NULL);
    +    }
    +    return cmd->end_token;
    +}
    +
    +static const char *dirsection (cmd_parms *cmd, void *dummy, const char *arg)
    +{
    +    const char *errmsg;
    +    char *endp = strrchr (arg, '>');
    +    int old_overrides = cmd->override;
    +    char *old_path = cmd->path;
    +    core_dir_config *conf;
    +    void *new_dir_conf = ap_create_per_dir_config (cmd->pool);
    +    regex_t *r = NULL;
    +    const char *old_end_token;
    +    const command_rec *thiscmd = cmd->cmd;
    +
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    if (endp) *endp = '\0';
    +
    +    cmd->path = ap_getword_conf (cmd->pool, &arg);
    +#ifdef __EMX__
    +    /* Fix OS/2 HPFS filename case problem. */
    +    cmd->path = strlwr(cmd->path);
    +#endif    
    +    cmd->override = OR_ALL|ACCESS_CONF;
    +
    +    if (thiscmd->cmd_data) { /* <DirectoryMatch> */
    +	r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
    +    }
    +    else if (!strcmp(cmd->path, "~")) {
    +	cmd->path = ap_getword_conf (cmd->pool, &arg);
    +	r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
    +    }
    +    else {
    +	/* Ensure that the pathname is canonical */
    +	cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
    +    }
    +
    +    old_end_token = cmd->end_token;
    +    cmd->end_token = thiscmd->cmd_data ? end_directorymatch_section : end_directory_section;
    +    errmsg = ap_srm_command_loop (cmd, new_dir_conf);
    +    if (errmsg == NULL) {
    +	errmsg = missing_endsection(cmd, 1);
    +    }
    +    cmd->end_token = old_end_token;
    +    if (errmsg != (thiscmd->cmd_data ? end_directorymatch_section : end_directory_section))
    +	return errmsg;
    +
    +    conf = (core_dir_config *)ap_get_module_config(new_dir_conf, &core_module);
    +    conf->r = r;
    +
    +    ap_add_per_dir_conf (cmd->server, new_dir_conf);
    +
    +    if (*arg != '\0')
    +	return ap_pstrcat (cmd->pool, "Multiple ", thiscmd->name,
    +			"> arguments not (yet) supported.", NULL);
    +
    +    cmd->path = old_path;
    +    cmd->override = old_overrides;
    +
    +    return NULL;
    +}
    +
    +static const char *urlsection (cmd_parms *cmd, void *dummy, const char *arg)
    +{
    +    const char *errmsg;
    +    char *endp = strrchr (arg, '>');
    +    int old_overrides = cmd->override;
    +    char *old_path = cmd->path;
    +    core_dir_config *conf;
    +    regex_t *r = NULL;
    +    const char *old_end_token;
    +    const command_rec *thiscmd = cmd->cmd;
    +
    +    void *new_url_conf = ap_create_per_dir_config (cmd->pool);
    +
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    if (endp) *endp = '\0';
    +
    +    cmd->path = ap_getword_conf (cmd->pool, &arg);
    +    cmd->override = OR_ALL|ACCESS_CONF;
    +
    +    if (thiscmd->cmd_data) { /* <LocationMatch> */
    +	r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
    +    }
    +    else if (!strcmp(cmd->path, "~")) {
    +	cmd->path = ap_getword_conf (cmd->pool, &arg);
    +	r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED);
    +    }
    +
    +    old_end_token = cmd->end_token;
    +    cmd->end_token = thiscmd->cmd_data ? end_locationmatch_section : end_location_section;
    +    errmsg = ap_srm_command_loop (cmd, new_url_conf);
    +    if (errmsg == NULL) {
    +	errmsg = missing_endsection(cmd, 1);
    +    }
    +    cmd->end_token = old_end_token;
    +    if (errmsg != (thiscmd->cmd_data ? end_locationmatch_section : end_location_section))
    +	return errmsg;
    +
    +    conf = (core_dir_config *)ap_get_module_config(new_url_conf, &core_module);
    +    conf->d = ap_pstrdup(cmd->pool, cmd->path);	/* No mangling, please */
    +    conf->d_is_fnmatch = ap_is_fnmatch( conf->d ) != 0;
    +    conf->r = r;
    +
    +    ap_add_per_url_conf (cmd->server, new_url_conf);
    +    
    +    if (*arg != '\0')
    +	return ap_pstrcat (cmd->pool, "Multiple ", thiscmd->name,
    +			"> arguments not (yet) supported.", NULL);
    +
    +    cmd->path = old_path;
    +    cmd->override = old_overrides;
    +
    +    return NULL;
    +}
    +
    +static const char *filesection (cmd_parms *cmd, core_dir_config *c, const char *arg)
    +{
    +    const char *errmsg;
    +    char *endp = strrchr (arg, '>');
    +    int old_overrides = cmd->override;
    +    char *old_path = cmd->path;
    +    core_dir_config *conf;
    +    regex_t *r = NULL;
    +    const char *old_end_token;
    +    const command_rec *thiscmd = cmd->cmd;
    +
    +    void *new_file_conf = ap_create_per_dir_config (cmd->pool);
    +
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT | NOT_IN_LOCATION);
    +    if (err != NULL) return err;
    +
    +    if (endp) *endp = '\0';
    +
    +    cmd->path = ap_getword_conf (cmd->pool, &arg);
    +    /* Only if not an .htaccess file */
    +    if (!old_path)
    +	cmd->override = OR_ALL|ACCESS_CONF;
    +
    +    if (thiscmd->cmd_data) { /* <FilesMatch> */
    +        r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
    +    }
    +    else if (!strcmp(cmd->path, "~")) {
    +	cmd->path = ap_getword_conf (cmd->pool, &arg);
    +	r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
    +    }
    +    else {
    +	/* Ensure that the pathname is canonical */
    +	cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
    +    }
    +
    +    old_end_token = cmd->end_token;
    +    cmd->end_token = thiscmd->cmd_data ? end_filesmatch_section : end_files_section;
    +    errmsg = ap_srm_command_loop (cmd, new_file_conf);
    +    if (errmsg == NULL) {
    +	errmsg = missing_endsection(cmd, 1);
    +    }
    +    cmd->end_token = old_end_token;
    +    if (errmsg != (thiscmd->cmd_data ? end_filesmatch_section : end_files_section))
    +	return errmsg;
    +
    +    conf = (core_dir_config *)ap_get_module_config(new_file_conf, &core_module);
    +    conf->d = cmd->path;
    +    conf->d_is_fnmatch = ap_is_fnmatch(conf->d) != 0;
    +    conf->r = r;
    +
    +    add_file_conf (c, new_file_conf);
    +
    +    if (*arg != '\0')
    +	return ap_pstrcat (cmd->pool, "Multiple ", thiscmd->name,
    +			"> arguments not (yet) supported.", NULL);
    +
    +    cmd->path = old_path;
    +    cmd->override = old_overrides;
    +
    +    return NULL;
    +}
    +
    +/* XXX: NB: Currently, we have no way of checking
    + * whether <IfModule> sections are closed properly.
    + * Extra (redundant, unpaired) </IfModule> directives are
    + * simply silently ignored.
    + */
    +static const char *end_ifmod (cmd_parms *cmd, void *dummy) {
    +    return NULL;
    +}
    +
    +static const char *start_ifmod (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    char *endp = strrchr (arg, '>');
    +    char l[MAX_STRING_LEN];
    +    int not = (arg[0] == '!');
    +    module *found;
    +    int nest = 1;
    +
    +    if (endp) *endp = '\0';
    +    if (not) arg++;
    +
    +    found = ap_find_linked_module(arg);
    +
    +    if ((!not && found) || (not && !found))
    +      return NULL;
    +
    +    while (nest && !(ap_cfg_getline (l, MAX_STRING_LEN, cmd->config_file))) {
    +        if (!strncasecmp(l, "<IfModule", 9))
    +	  nest++;
    +	if (!strcasecmp(l, "</IfModule>"))
    +	  nest--;
    +    }
    +
    +    if (nest) {
    +	cmd->end_token = end_ifmodule_section;
    +	return missing_endsection(cmd, nest);
    +    }
    +    return NULL;
    +}
    +
    +/* httpd.conf commands... beginning with the <VirtualHost> business */
    +
    +static const char *virtualhost_section (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    server_rec *main_server = cmd->server, *s;
    +    const char *errmsg;
    +    char *endp = strrchr (arg, '>');
    +    pool *p = cmd->pool, *ptemp = cmd->temp_pool;
    +    const char *old_end_token;
    +
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    if (endp) *endp = '\0';
    +    
    +    /* FIXME: There's another feature waiting to happen here -- since you
    +	can now put multiple addresses/names on a single <VirtualHost>
    +	you might want to use it to group common definitions and then
    +	define other "subhosts" with their individual differences.  But
    +	personally I'd rather just do it with a macro preprocessor. -djg */
    +    if (main_server->is_virtual)
    +	return "<VirtualHost> doesn't nest!";
    +    
    +    errmsg = ap_init_virtual_host (p, arg, main_server, &s);
    +    if (errmsg)
    +	return errmsg;
    +
    +    s->next = main_server->next;
    +    main_server->next = s;
    +
    +    s->defn_name = cmd->config_file->name;
    +    s->defn_line_number = cmd->config_file->line_number;
    +
    +    old_end_token = cmd->end_token;
    +    cmd->end_token = end_virtualhost_section;
    +    cmd->server = s;
    +    errmsg = ap_srm_command_loop (cmd, s->lookup_defaults);
    +    cmd->server = main_server;
    +    if (errmsg == NULL) {
    +	errmsg = missing_endsection(cmd, 1);
    +    }
    +    cmd->end_token = old_end_token;
    +
    +    if (s->srm_confname)
    +	ap_process_resource_config (s, s->srm_confname, p, ptemp);
    +
    +    if (s->access_confname)
    +	ap_process_resource_config (s, s->access_confname, p, ptemp);
    +    
    +    if (errmsg == end_virtualhost_section)
    +	return NULL;
    +    return errmsg;
    +}
    +
    +static const char *set_server_alias(cmd_parms *cmd, void *dummy, const char *arg)
    +{
    +    if (!cmd->server->names)
    +	return "ServerAlias only used in <VirtualHost>";
    +    while (*arg) {
    +	char **item, *name = ap_getword_conf(cmd->pool, &arg);
    +	if (ap_is_matchexp(name))
    +	    item = (char **) ap_push_array(cmd->server->wild_names);
    +	else
    +	    item = (char **) ap_push_array(cmd->server->names);
    +	*item = name;
    +    }
    +    return NULL;
    +}
    +
    +static const char *add_module_command (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    if (!ap_add_named_module(arg))
    +	return ap_pstrcat(cmd->pool, "Cannot add module via name '", arg, 
    +			  "': not in list of loaded modules", NULL);
    +    return NULL;
    +}
    +
    +static const char *clear_module_list_command (cmd_parms *cmd, void *dummy)
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_clear_module_list ();
    +    return NULL;
    +}
    +
    +static const char *set_server_string_slot (cmd_parms *cmd, void *dummy,
    +		                                   char *arg)
    +{
    +    /* This one's pretty generic... */
    +  
    +    int offset = (int)(long)cmd->info;
    +    char *struct_ptr = (char *)cmd->server;
    +    
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    *(char **)(struct_ptr + offset) = arg;
    +    return NULL;
    +}
    +
    +static const char *server_type (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    if (!strcasecmp (arg, "inetd")) ap_standalone = 0;
    +    else if (!strcasecmp (arg, "standalone")) ap_standalone = 1;
    +    else return "ServerType must be either 'inetd' or 'standalone'";
    +
    +    return NULL;
    +}
    +
    +static const char *server_port (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    int port;
    +
    +    if (err != NULL) 
    +	return err;
    +    port = atoi(arg);
    +    if (port <= 0 || port >= 65536) /* 65536 == 1<<16 */
    +	return ap_pstrcat(cmd->temp_pool, "The port number \"", arg, 
    +		       "\" is outside the appropriate range (i.e. 1..65535).",
    +		       NULL);
    +    cmd->server->port = port;
    +    return NULL;
    +}
    +
    +static const char *set_signature_flag (cmd_parms *cmd, core_dir_config *d, 
    +		                               char *arg)
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    if (strcasecmp(arg, "On") == 0)
    +	d->server_signature = srv_sig_on;
    +    else if (strcasecmp(arg, "Off") == 0)
    +	d->server_signature = srv_sig_off;
    +    else if (strcasecmp(arg, "EMail") == 0)
    +	d->server_signature = srv_sig_withmail;
    +    else
    +	return "ServerSignature: use one of: off | on | email";
    +    return NULL;
    +}
    +
    +static const char *set_send_buffer_size (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    int s = atoi (arg);
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    if (s < 512 && s != 0) {
    +        return "SendBufferSize must be >= 512 bytes, or 0 for system default.";
    +    }
    +    cmd->server->send_buffer_size = s;
    +    return NULL;
    +}
    +
    +static const char *set_user (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    if (!cmd->server->is_virtual) {
    +	ap_user_name = arg;
    +	cmd->server->server_uid = ap_user_id = ap_uname2id(arg);
    +    }
    +    else {
    +	if (ap_suexec_enabled)
    +	    cmd->server->server_uid = ap_uname2id(arg);
    +	else {
    +	    cmd->server->server_uid = ap_user_id;
    +	    fprintf(stderr,
    +		"Warning: User directive in <VirtualHost> "
    +		"requires SUEXEC wrapper.\n");
    +	}
    +    }
    +#if !defined (BIG_SECURITY_HOLE) && !defined (__EMX__)
    +    if (cmd->server->server_uid == 0) {
    +	fprintf (stderr,
    +"Error:\tApache has not been designed to serve pages while running\n"
    +"\tas root.  There are known race conditions that will allow any\n"
    +"\tlocal user to read any file on the system.  Should you still\n"
    +"\tdesire to serve pages as root then add -DBIG_SECURITY_HOLE to\n"
    +"\tthe EXTRA_CFLAGS line in your src/Configuration file and rebuild\n"
    +"\tthe server.  It is strongly suggested that you instead modify the\n"
    +"\tUser directive in your httpd.conf file to list a non-root user.\n");
    +	exit (1);
    +    }
    +#endif
    +
    +    return NULL;
    +}
    +
    +static const char *set_group (cmd_parms *cmd, void *dummy, char *arg)
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    if (!cmd->server->is_virtual)
    +	cmd->server->server_gid = ap_group_id = ap_gname2id(arg);
    +    else {
    +	if (ap_suexec_enabled)
    +	    cmd->server->server_gid = ap_gname2id(arg);
    +	else {
    +	    cmd->server->server_gid = ap_group_id;
    +	    fprintf(stderr,
    +		    "Warning: Group directive in <VirtualHost> requires SUEXEC wrapper.\n");
    +	}
    +    }
    +
    +    return NULL;
    +}
    +
    +static const char *set_server_root (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    if (!ap_is_directory (arg)) return "ServerRoot must be a valid directory";
    +    ap_cpystrn (ap_server_root, ap_os_canonical_filename(cmd->pool, arg), sizeof(ap_server_root));
    +    return NULL;
    +}
    +
    +static const char *set_timeout (cmd_parms *cmd, void *dummy, char *arg) {
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    cmd->server->timeout = atoi (arg);
    +    return NULL;
    +}
    +
    +static const char *set_keep_alive_timeout (cmd_parms *cmd, void *dummy,
    +		                                   char *arg)
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    cmd->server->keep_alive_timeout = atoi (arg);
    +    return NULL;
    +}
    +
    +static const char *set_keep_alive (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    /* We've changed it to On/Off, but used to use numbers
    +     * so we accept anything but "Off" or "0" as "On"
    +     */
    +    if (!strcasecmp(arg, "off") || !strcmp(arg, "0"))
    +	cmd->server->keep_alive = 0;
    +    else
    +	cmd->server->keep_alive = 1;
    +    return NULL;
    +}
    +
    +static const char *set_keep_alive_max (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    cmd->server->keep_alive_max = atoi (arg);
    +    return NULL;
    +}
    +
    +static const char *set_pidfile (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    if (cmd->server->is_virtual)
    +	return "PidFile directive not allowed in <VirtualHost>";
    +    ap_pid_fname = arg;
    +    return NULL;
    +}
    +
    +static const char *set_scoreboard (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_scoreboard_fname = arg;
    +    return NULL;
    +}
    +
    +static const char *set_lockfile (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_lock_fname = arg;
    +    return NULL;
    +}
    +
    +static const char *set_idcheck (cmd_parms *cmd, core_dir_config *d, int arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    d->do_rfc1413 = arg != 0;
    +    return NULL;
    +}
    +
    +static const char *set_hostname_lookups (cmd_parms *cmd, core_dir_config *d,
    +		                                 char *arg)
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    if (!strcasecmp (arg, "on")) {
    +	d->hostname_lookups = HOSTNAME_LOOKUP_ON;
    +    } else if (!strcasecmp (arg, "off")) {
    +	d->hostname_lookups = HOSTNAME_LOOKUP_OFF;
    +    } else if (!strcasecmp (arg, "double")) {
    +	d->hostname_lookups = HOSTNAME_LOOKUP_DOUBLE;
    +    } else {
    +	return "parameter must be 'on', 'off', or 'double'";
    +    }
    +    return NULL;
    +}
    +
    +static const char *set_serverpath (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    cmd->server->path = arg;
    +    cmd->server->pathlen = strlen (arg);
    +    return NULL;
    +}
    +
    +static const char *set_content_md5 (cmd_parms *cmd, core_dir_config *d, int arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +    d->content_md5 = arg != 0;
    +    return NULL;
    +}
    +
    +static const char *set_use_canonical_name (cmd_parms *cmd, core_dir_config *d, 
    +		                                   int arg)
    +{
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
    +
    +    if (err != NULL)
    +	return err;
    +    
    +    d->use_canonical_name = arg != 0;
    +    return NULL;
    +}
    +
    +static const char *set_daemons_to_start (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_daemons_to_start = atoi (arg);
    +    return NULL;
    +}
    +
    +static const char *set_min_free_servers (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_daemons_min_free = atoi (arg);
    +    if (ap_daemons_min_free <= 0) {
    +       fprintf(stderr, "WARNING: detected MinSpareServers set to non-positive.\n");
    +       fprintf(stderr, "Resetting to 1 to avoid almost certain Apache failure.\n");
    +       fprintf(stderr, "Please read the documentation.\n");
    +       ap_daemons_min_free = 1;
    +    }
    +       
    +    return NULL;
    +}
    +
    +static const char *set_max_free_servers (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_daemons_max_free = atoi (arg);
    +    return NULL;
    +}
    +
    +static const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_daemons_limit = atoi (arg);
    +    if (ap_daemons_limit > HARD_SERVER_LIMIT) {
    +       fprintf(stderr, "WARNING: MaxClients of %d exceeds compile time limit "
    +           "of %d servers,\n", ap_daemons_limit, HARD_SERVER_LIMIT);
    +       fprintf(stderr, " lowering MaxClients to %d.  To increase, please "
    +           "see the\n", HARD_SERVER_LIMIT);
    +       fprintf(stderr, " HARD_SERVER_LIMIT define in src/httpd.h.\n");
    +       ap_daemons_limit = HARD_SERVER_LIMIT;
    +    } else if (ap_daemons_limit < 1) {
    +	fprintf (stderr, "WARNING: Require MaxClients > 0, setting to 1\n");
    +	ap_daemons_limit = 1;
    +    }
    +    return NULL;
    +}
    +
    +static const char *set_max_requests (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_max_requests_per_child = atoi (arg);
    +    return NULL;
    +}
    +
    +static const char *set_threads (cmd_parms *cmd, void *dummy, char *arg) {
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_threads_per_child = atoi (arg);
    +#ifdef WIN32
    +    if(ap_threads_per_child > 64)
    +	return "Can't have more than 64 threads in Windows (for now)";
    +#endif
    +
    +    return NULL;
    +}
    +
    +static const char *set_excess_requests (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_excess_requests_per_child = atoi (arg);
    +    return NULL;
    +}
    +
    +
    +#if defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC) || defined(RLIMIT_AS)
    +static void set_rlimit(cmd_parms *cmd, struct rlimit **plimit, const char *arg,
    +                       const char * arg2, int type)
    +{
    +    char *str;
    +    struct rlimit *limit;
    +    /* If your platform doesn't define rlim_t then typedef it in conf.h */
    +    rlim_t cur = 0;
    +    rlim_t max = 0;
    +
    +    *plimit = (struct rlimit *)ap_pcalloc(cmd->pool,sizeof **plimit);
    +    limit = *plimit;
    +    if ((getrlimit(type, limit)) != 0)	{
    +	*plimit = NULL;
    +	ap_log_error(APLOG_MARK, APLOG_ERR, cmd->server,
    +		    "%s: getrlimit failed", cmd->cmd->name);
    +	return;
    +    }
    +
    +    if ((str = ap_getword_conf(cmd->pool, &arg))) {
    +	if (!strcasecmp(str, "max")) {
    +	    cur = limit->rlim_max;
    +	}
    +	else {
    +	    cur = atol(str);
    +	}
    +    }
    +    else {
    +	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
    +		    "Invalid parameters for %s", cmd->cmd->name);
    +	return;
    +    }
    +    
    +    if (arg2 && (str = ap_getword_conf(cmd->pool, &arg2)))
    +	max = atol(str);
    +
    +    /* if we aren't running as root, cannot increase max */
    +    if (geteuid()) {
    +	limit->rlim_cur = cur;
    +	if (max)
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
    +			"Must be uid 0 to raise maximum %s", cmd->cmd->name);
    +    }
    +    else {
    +	if (cur)
    +	    limit->rlim_cur = cur;
    +	if (max)
    +	    limit->rlim_max = max;
    +    }
    +}
    +#endif
    +
    +#if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
    +static const char *no_set_limit (cmd_parms *cmd, core_dir_config *conf,
    +				 char *arg, char *arg2)
    +{
    +    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, cmd->server,
    +		"%s not supported on this platform", cmd->cmd->name);
    +    return NULL;
    +}
    +#endif
    +
    +#ifdef RLIMIT_CPU
    +static const char *set_limit_cpu (cmd_parms *cmd, core_dir_config *conf, 
    +	                          char *arg, char *arg2)
    +{
    +    set_rlimit(cmd,&conf->limit_cpu,arg,arg2,RLIMIT_CPU);
    +    return NULL;
    +}
    +#endif
    +
    +#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
    +static const char *set_limit_mem (cmd_parms *cmd, core_dir_config *conf, 
    +	                          char *arg, char * arg2)
    +{
    +#if defined(RLIMIT_AS)
    +    set_rlimit(cmd,&conf->limit_mem,arg,arg2,RLIMIT_AS);
    +#elif defined(RLIMIT_DATA)
    +    set_rlimit(cmd,&conf->limit_mem,arg,arg2,RLIMIT_DATA);
    +#elif defined(RLIMIT_VMEM)
    +    set_rlimit(cmd,&conf->limit_mem,arg,arg2,RLIMIT_VMEM);
    +#endif
    +    return NULL;
    +}
    +#endif
    +
    +#ifdef RLIMIT_NPROC
    +static const char *set_limit_nproc (cmd_parms *cmd, core_dir_config *conf,  
    +	                            char *arg, char * arg2)
    +{
    +    set_rlimit(cmd,&conf->limit_nproc,arg,arg2,RLIMIT_NPROC);
    +    return NULL;
    +}
    +#endif
    +
    +static const char *set_bind_address (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ap_bind_address.s_addr = ap_get_virthost_addr (arg, NULL);
    +    return NULL;
    +}
    +
    +static const char *set_listener(cmd_parms *cmd, void *dummy, char *ips)
    +{
    +    listen_rec *new;
    +    char *ports;
    +    unsigned short port;
    +
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    ports=strchr(ips, ':');
    +    if (ports != NULL)
    +    {
    +	if (ports == ips) return "Missing IP address";
    +	else if (ports[1] == '\0')
    +	    return "Address must end in :<port-number>";
    +	*(ports++) = '\0';
    +    } else
    +	ports = ips;
    +
    +    new=ap_pcalloc(cmd->pool, sizeof(listen_rec));
    +    new->local_addr.sin_family = AF_INET;
    +    if (ports == ips) /* no address */
    +	new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    +    else
    +	new->local_addr.sin_addr.s_addr = ap_get_virthost_addr(ips, NULL);
    +    port=atoi(ports);
    +    if(!port)
    +	return "Port must be numeric";
    +    new->local_addr.sin_port = htons(port);
    +    new->fd = -1;
    +    new->used = 0;
    +    new->next = ap_listeners;
    +    ap_listeners = new;
    +    return NULL;
    +}
    +
    +static const char *set_listenbacklog (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    int b;
    +
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    b = atoi (arg);
    +    if (b < 1) return "ListenBacklog must be > 0";
    +    ap_listenbacklog = b;
    +    return NULL;
    +}
    +
    +static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    struct stat finfo;
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    arg = ap_server_root_relative(cmd->pool, arg);
    +    if ((stat(arg, &finfo) == -1) || !S_ISDIR(finfo.st_mode)) {
    +	return ap_pstrcat(cmd->pool, "CoreDumpDirectory ", arg, 
    +	    " does not exist or is not a directory", NULL);
    +    }
    +    ap_cpystrn(ap_coredump_dir, arg, sizeof(ap_coredump_dir));
    +    return NULL;
    +}
    +
    +static const char *include_config (cmd_parms *cmd, void *dummy, char *name)
    +{
    +    name = ap_server_root_relative(cmd->pool, name);
    +    
    +    ap_process_resource_config(cmd->server, name, cmd->pool, cmd->temp_pool);
    +
    +    return NULL;
    +}
    +
    +static const char *set_loglevel (cmd_parms *cmd, void *dummy, const char *arg) 
    +{
    +   char *str;
    +    
    +    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
    +    if (err != NULL) return err;
    +
    +   if ((str = ap_getword_conf(cmd->pool, &arg))) {
    +       if (!strcasecmp(str, "emerg"))
    +	   cmd->server->loglevel = APLOG_EMERG;
    +       else if (!strcasecmp(str, "alert"))
    +	   cmd->server->loglevel = APLOG_ALERT;
    +       else if (!strcasecmp(str, "crit"))
    +	   cmd->server->loglevel = APLOG_CRIT;
    +       else if (!strcasecmp(str, "error"))
    +	   cmd->server->loglevel = APLOG_ERR;
    +       else if (!strcasecmp(str, "warn"))
    +	   cmd->server->loglevel = APLOG_WARNING;
    +       else if (!strcasecmp(str, "notice"))
    +	   cmd->server->loglevel = APLOG_NOTICE;
    +       else if (!strcasecmp(str, "info"))
    +	   cmd->server->loglevel = APLOG_INFO;
    +       else if (!strcasecmp(str, "debug"))
    +	   cmd->server->loglevel = APLOG_DEBUG;
    +       else
    +           return "LogLevel requires level keyword: one of emerg/alert/crit/error/warn/notice/info/debug";
    +   }
    +   else
    +       return "LogLevel requires level keyword";
    +   
    +   return NULL;
    +}
    +
    +API_EXPORT(const char *) ap_psignature(const char *prefix, request_rec *r)
    +{
    +    char sport[20];
    +    core_dir_config *conf =
    +    (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module);
    +
    +    if (conf->server_signature == srv_sig_off)
    +	return "";
    +
    +    ap_snprintf(sport, sizeof sport, "%u", (unsigned) ap_get_server_port(r));
    +
    +    if (conf->server_signature == srv_sig_withmail) {
    +	return ap_pstrcat(r->pool, prefix, "<ADDRESS>" SERVER_BASEVERSION
    +	     " Server at <A HREF=\"mailto:", r->server->server_admin, "\">",
    +		       ap_get_server_name(r), "</A> Port ", sport,
    +		       "</ADDRESS>\n", NULL);
    +    }
    +    return ap_pstrcat(r->pool, prefix, "<ADDRESS>" SERVER_BASEVERSION
    +	     " Server at ", ap_get_server_name(r), " Port ", sport,
    +		   "</ADDRESS>\n", NULL);
    +}
    +
    +/*
    + * Load an authorisation realm into our location configuration, applying the
    + * usual rules that apply to realms.
    + */
    +static const char *set_authname(cmd_parms *cmd, void *mconfig, char *word1)
    +{
    +    core_dir_config *aconfig = (core_dir_config *)mconfig;
    +
    +    aconfig->ap_auth_name = ap_escape_quotes(cmd->pool, word1);
    +    return NULL;
    +}
    +
    +#ifdef _OSD_POSIX /* BS2000 Logon Passwd file */
    +static const char *set_bs2000_authfile (cmd_parms *cmd, void *dummy, char *name)
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    return os_set_authfile(cmd->pool, name);
    +}
    +#endif /*_OSD_POSIX*/
    +
    +/*
    + * Handle a request to include the server's OS platform in the Server
    + * response header field (the AddVersionPlatform directive).  Unfortunately
    + * this requires a new global in order to communicate the setting back to
    + * http_main so it can insert the information in the right place in the
    + * string.
    + */
    +
    +static const char *set_serv_tokens (cmd_parms *cmd, void *dummy, char *arg) 
    +{
    +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    +    if (err != NULL) return err;
    +
    +    if (!strcasecmp(arg, "OS"))
    +        ap_server_tokens = SrvTk_OS;
    +    else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal"))
    +        ap_server_tokens = SrvTk_MIN;
    +    else
    +        ap_server_tokens = SrvTk_FULL;
    +    return NULL;
    +}
    +
    +/* Note --- ErrorDocument will now work from .htaccess files.  
    + * The AllowOverride of Fileinfo allows webmasters to turn it off
    + */
    +
    +static const command_rec core_cmds[] = {
    +
    +/* Old access config file commands */
    +
    +{ "<Directory", dirsection, NULL, RSRC_CONF, RAW_ARGS,
    +  "Container for directives affecting resources located in the specified "
    +  "directories" },
    +{ end_directory_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <Directory>" },
    +{ "<Location", urlsection, NULL, RSRC_CONF, RAW_ARGS, "Container for directives affecting resources accessed through the specified URL paths" },
    +{ end_location_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <Location>" },
    +{ "<VirtualHost", virtualhost_section, NULL, RSRC_CONF, RAW_ARGS, "Container to map directives to a particular virtual host, takes one or more host addresses" },
    +{ end_virtualhost_section, end_nested_section, NULL, RSRC_CONF, NO_ARGS, "Marks end of <VirtualHost>" },
    +{ "<Files", filesection, NULL, OR_ALL, RAW_ARGS, "Container for directives affecting files matching specified patterns" },
    +{ end_files_section, end_nested_section, NULL, OR_ALL, NO_ARGS, "Marks end of <Files>" },
    +{ "<Limit", ap_limit_section, NULL, OR_ALL, RAW_ARGS, "Container for authentication directives when accessed using specified HTTP methods" },
    +{ "</Limit>", endlimit_section, NULL, OR_ALL, NO_ARGS, "Marks end of <Limit>" },
    +{ "<IfModule", start_ifmod, NULL, OR_ALL, RAW_ARGS, "Container for directives based on existance of specified modules" },
    +{ end_ifmodule_section, end_ifmod, NULL, OR_ALL, NO_ARGS, "Marks end of <IfModule>" },
    +{ "<DirectoryMatch", dirsection, (void*)1, RSRC_CONF, RAW_ARGS, "Container for directives affecting resources located in the specified directories" },
    +{ end_directorymatch_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <DirectoryMatch>" },
    +{ "<LocationMatch", urlsection, (void*)1, RSRC_CONF, RAW_ARGS, "Container for directives affecting resources accessed through the specified URL paths" },
    +{ end_locationmatch_section, end_nested_section, NULL, ACCESS_CONF, NO_ARGS, "Marks end of <LocationMatch>" },
    +{ "<FilesMatch", filesection, (void*)1, OR_ALL, RAW_ARGS, "Container for directives affecting files matching specified patterns" },
    +{ end_filesmatch_section, end_nested_section, NULL, OR_ALL, NO_ARGS, "Marks end of <FilesMatch>" },
    +{ "AuthType", ap_set_string_slot, (void*)XtOffsetOf(core_dir_config, ap_auth_type),
    +    OR_AUTHCFG, TAKE1, "An HTTP authorization type (e.g., \"Basic\")" },
    +{ "AuthName", set_authname, NULL, OR_AUTHCFG, TAKE1,
    +    "The authentication realm (e.g. \"Members Only\")" },
    +{ "Require", require, NULL, OR_AUTHCFG, RAW_ARGS, "Selects which authenticated users or groups may access a protected space" },
    +{ "Satisfy", satisfy, NULL, OR_AUTHCFG, TAKE1,
    +    "access policy if both allow and require used ('all' or 'any')" },    
    +
    +/* Old resource config file commands */
    +  
    +{ "AccessFileName", set_access_name, NULL, RSRC_CONF, RAW_ARGS, "Name(s) of per-directory config files (default: .htaccess)" },
    +{ "DocumentRoot", set_document_root, NULL, RSRC_CONF, TAKE1, "Root directory of the document tree"  },
    +{ "ErrorDocument", set_error_document, NULL, OR_FILEINFO, RAW_ARGS, "Change responses for HTTP errors" },
    +{ "AllowOverride", set_override, NULL, ACCESS_CONF, RAW_ARGS, "Controls what groups of directives can be configured by per-directory config files" },
    +{ "Options", set_options, NULL, OR_OPTIONS, RAW_ARGS, "Set a number of attributes for a given directory" },
    +{ "DefaultType", ap_set_string_slot,
    +    (void*)XtOffsetOf (core_dir_config, ap_default_type),
    +    OR_FILEINFO, TAKE1, "the default MIME type for untypable files" },
    +
    +/* Old server config file commands */
    +
    +{ "ServerType", server_type, NULL, RSRC_CONF, TAKE1,"'inetd' or 'standalone'"},
    +{ "Port", server_port, NULL, RSRC_CONF, TAKE1, "A TCP port number"},
    +{ "HostnameLookups", set_hostname_lookups, NULL, ACCESS_CONF|RSRC_CONF, TAKE1, "\"on\" to enable, \"off\" to disable reverse DNS lookups, or \"double\" to enable double-reverse DNS lookups" },
    +{ "User", set_user, NULL, RSRC_CONF, TAKE1, "Effective user id for this server"},
    +{ "Group", set_group, NULL, RSRC_CONF, TAKE1, "Effective group id for this server"},
    +{ "ServerAdmin", set_server_string_slot,
    +  (void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF, TAKE1,
    +  "The email address of the server administrator" },
    +{ "ServerName", set_server_string_slot,
    +  (void *)XtOffsetOf (server_rec, server_hostname), RSRC_CONF, TAKE1,
    +  "The hostname of the server" },
    +{ "ServerSignature", set_signature_flag, NULL, ACCESS_CONF|RSRC_CONF, TAKE1,
    +  "En-/disable server signature (on|off|email)" },
    +{ "ServerRoot", set_server_root, NULL, RSRC_CONF, TAKE1, "Common directory of server-related files (logs, confs, etc)" },
    +{ "ErrorLog", set_server_string_slot,
    +  (void *)XtOffsetOf (server_rec, error_fname), RSRC_CONF, TAKE1,
    +  "The filename of the error log" },
    +{ "PidFile", set_pidfile, NULL, RSRC_CONF, TAKE1,
    +    "A file for logging the server process ID"},
    +{ "ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF, TAKE1,
    +    "A file for Apache to maintain runtime process management information"},
    +{ "LockFile", set_lockfile, NULL, RSRC_CONF, TAKE1,
    +    "The lockfile used when Apache needs to lock the accept() call"},
    +{ "AccessConfig", set_server_string_slot,
    +  (void *)XtOffsetOf (server_rec, access_confname), RSRC_CONF, TAKE1,
    +  "The filename of the access config file" },
    +{ "ResourceConfig", set_server_string_slot,
    +  (void *)XtOffsetOf (server_rec, srm_confname), RSRC_CONF, TAKE1,
    +  "The filename of the resource config file" },
    +{ "ServerAlias", set_server_alias, NULL, RSRC_CONF, RAW_ARGS,
    +  "A name or names alternately used to access the server" },
    +{ "ServerPath", set_serverpath, NULL, RSRC_CONF, TAKE1,
    +  "The pathname the server can be reached at" },
    +{ "Timeout", set_timeout, NULL, RSRC_CONF, TAKE1, "Timeout duration (sec)"},
    +{ "KeepAliveTimeout", set_keep_alive_timeout, NULL, RSRC_CONF, TAKE1, "Keep-Alive timeout duration (sec)"},
    +{ "MaxKeepAliveRequests", set_keep_alive_max, NULL, RSRC_CONF, TAKE1, "Maximum number of Keep-Alive requests per connection, or 0 for infinite" },
    +{ "KeepAlive", set_keep_alive, NULL, RSRC_CONF, TAKE1, "Whether persistent connections should be On or Off" },
    +{ "IdentityCheck", set_idcheck, NULL, RSRC_CONF|ACCESS_CONF, FLAG, "Enable identd (RFC 1413) user lookups - SLOW" },
    +{ "ContentDigest", set_content_md5, NULL, RSRC_CONF|ACCESS_CONF|OR_AUTHCFG, FLAG, "whether or not to send a Content-MD5 header with each request" },
    +{ "UseCanonicalName", set_use_canonical_name, NULL, RSRC_CONF|ACCESS_CONF|OR_AUTHCFG, FLAG, "whether or not to always use the canonical ServerName : Port when constructing URLs" },
    +{ "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1, "Number of child processes launched at server startup" },
    +{ "MinSpareServers", set_min_free_servers, NULL, RSRC_CONF, TAKE1, "Minimum number of idle children, to handle request spikes" },
    +{ "MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF, TAKE1, "Maximum number of idle children" },
    +{ "MaxServers", set_max_free_servers, NULL, RSRC_CONF, TAKE1, "Deprecated equivalent to MaxSpareServers" },
    +{ "ServersSafetyLimit", set_server_limit, NULL, RSRC_CONF, TAKE1, "Deprecated equivalent to MaxClients" },
    +{ "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1, "Maximum number of children alive at the same time" },
    +{ "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1, "Maximum number of requests a particular child serves before dying." },
    +{ "RLimitCPU",
    +#ifdef RLIMIT_CPU
    + set_limit_cpu, (void*)XtOffsetOf(core_dir_config, limit_cpu),
    +#else
    + no_set_limit, NULL,
    +#endif
    +      OR_ALL, TAKE12, "soft/hard limits for max CPU usage in seconds" },
    +{ "RLimitMEM",
    +#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined (RLIMIT_AS)
    + set_limit_mem, (void*)XtOffsetOf(core_dir_config, limit_mem),
    +#else
    + no_set_limit, NULL,
    +#endif
    +      OR_ALL, TAKE12, "soft/hard limits for max memory usage per process" },
    +{ "RLimitNPROC",
    +#ifdef RLIMIT_NPROC
    + set_limit_nproc, (void*)XtOffsetOf(core_dir_config, limit_nproc),
    +#else
    + no_set_limit, NULL,
    +#endif
    +      OR_ALL, TAKE12, "soft/hard limits for max number of processes per uid" },
    +{ "BindAddress", set_bind_address, NULL, RSRC_CONF, TAKE1,
    +  "'*', a numeric IP address, or the name of a host with a unique IP address"},
    +{ "Listen", set_listener, NULL, RSRC_CONF, TAKE1,
    +      "a port number or a numeric IP address and a port number"},
    +{ "SendBufferSize", set_send_buffer_size, NULL, RSRC_CONF, TAKE1, "send buffer size in bytes"},
    +{ "AddModule", add_module_command, NULL, RSRC_CONF, ITERATE,
    +  "the name of a module" },
    +{ "ClearModuleList", clear_module_list_command, NULL, RSRC_CONF, NO_ARGS, NULL },
    +{ "ThreadsPerChild", set_threads, NULL, RSRC_CONF, TAKE1, "Number of threads a child creates" },
    +{ "ExcessRequestsPerChild", set_excess_requests, NULL, RSRC_CONF, TAKE1, "Maximum number of requests a particular child serves after it is ready to die." },
    +{ "ListenBacklog", set_listenbacklog, NULL, RSRC_CONF, TAKE1, "maximum length of the queue of pending connections, as used by listen(2)" },
    +{ "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, TAKE1, "The location of the directory Apache changes to before dumping core" },
    +{ "Include", include_config, NULL, RSRC_CONF, TAKE1, "config file to be included" },
    +{ "LogLevel", set_loglevel, NULL, RSRC_CONF, TAKE1, "set level of verbosity in error logging" },
    +{ "NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, TAKE1,
    +  "a numeric ip address:port, or the name of a host" },
    +#ifdef _OSD_POSIX
    +{ "BS2000AuthFile", set_bs2000_authfile, NULL, RSRC_CONF, TAKE1,
    +  "server User's bs2000 logon password file (read-protected)" },
    +#endif
    +{ "ServerTokens", set_serv_tokens, NULL, RSRC_CONF, TAKE1,
    +  "Determine tokens displayed in the Server: header - Min(imal), OS or Full" },
    +{ NULL },
    +};
    +
    +/*****************************************************************
    + *
    + * Core handlers for various phases of server operation...
    + */
    +
    +static int core_translate (request_rec *r)
    +{
    +    void *sconf = r->server->module_config;
    +    core_server_config *conf = ap_get_module_config (sconf, &core_module);
    +  
    +    if (r->proxyreq) return HTTP_FORBIDDEN;
    +    if ((r->uri[0] != '/') && strcmp(r->uri, "*")) {
    +	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
    +		    "Invalid URI in request %s", r->the_request);
    +	return BAD_REQUEST;
    +    }
    +    
    +    if (r->server->path &&
    +	!strncmp(r->uri, r->server->path, r->server->pathlen) &&
    +	(r->server->path[r->server->pathlen - 1] == '/' ||
    +	 r->uri[r->server->pathlen] == '/' ||
    +	 r->uri[r->server->pathlen] == '\0'))
    +      r->filename = ap_pstrcat (r->pool, conf->ap_document_root,
    +			     (r->uri + r->server->pathlen), NULL);
    +    else
    +      r->filename = ap_pstrcat (r->pool, conf->ap_document_root, r->uri, NULL);
    +
    +    return OK;
    +}
    +
    +static int do_nothing (request_rec *r) { return OK; }
    +
    +#ifdef USE_MMAP_FILES
    +struct mmap {
    +    void *mm;
    +    size_t length;
    +};
    +
    +static void mmap_cleanup (void *mmv)
    +{
    +    struct mmap *mmd = mmv;
    +
    +    munmap(mmd->mm, mmd->length);
    +}
    +#endif
    +
    +/*
    + * Default handler for MIME types without other handlers.  Only GET
    + * and OPTIONS at this point... anyone who wants to write a generic
    + * handler for PUT or POST is free to do so, but it seems unwise to provide
    + * any defaults yet... So, for now, we assume that this will always be
    + * the last handler called and return 405 or 501.
    + */
    +
    +static int default_handler (request_rec *r)
    +{
    +    core_dir_config *d =
    +      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
    +    int rangestatus, errstatus;
    +    FILE *f;
    +#ifdef USE_MMAP_FILES
    +    caddr_t mm;
    +#endif
    +
    +    if (r->handler) {
    +	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
    +	    r->server, "handler \"%s\" not found, using default "
    +	    "handler for: %s", r->handler, r->filename);
    +    }
    +
    +    /* This handler has no use for a request body (yet), but we still
    +     * need to read and discard it if the client sent one.
    +     */
    +    if ((errstatus = ap_discard_request_body(r)) != OK)
    +        return errstatus;
    +
    +    r->allowed |= (1 << M_GET) | (1 << M_OPTIONS);
    +
    +    if (r->method_number == M_INVALID) {
    +	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
    +		    "Invalid method in request %s", r->the_request);
    +	return NOT_IMPLEMENTED;
    +    }
    +    if (r->method_number == M_OPTIONS) return ap_send_http_options(r);
    +    if (r->method_number == M_PUT) return METHOD_NOT_ALLOWED;
    +
    +    if (r->finfo.st_mode == 0 || (r->path_info && *r->path_info)) {
    +	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r->server, 
    +                    "File does not exist: %s", r->path_info ? 
    +                    ap_pstrcat(r->pool, r->filename, r->path_info, NULL)
    +		    : r->filename);
    +	return NOT_FOUND;
    +    }
    +    if (r->method_number != M_GET) return METHOD_NOT_ALLOWED;
    +	
    +#if defined(__EMX__) || defined(WIN32)
    +    /* Need binary mode for OS/2 */
    +    f = ap_pfopen (r->pool, r->filename, "rb");
    +#else
    +    f = ap_pfopen (r->pool, r->filename, "r");
    +#endif
    +
    +    if (f == NULL) {
    +        ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
    +		    "file permissions deny server access: %s", r->filename);
    +        return FORBIDDEN;
    +    }
    +	
    +    ap_update_mtime (r, r->finfo.st_mtime);
    +    ap_set_last_modified(r);
    +    ap_set_etag(r);
    +    ap_table_setn(r->headers_out, "Accept-Ranges", "bytes");
    +    if (((errstatus = ap_meets_conditions(r)) != OK)
    +	|| (errstatus = ap_set_content_length (r, r->finfo.st_size))) {
    +	    return errstatus;
    +    }
    +
    +#ifdef USE_MMAP_FILES
    +    ap_block_alarms();
    +    if ((r->finfo.st_size >= MMAP_THRESHOLD)
    +	&& ( !r->header_only || (d->content_md5 & 1))) {
    +	/* we need to protect ourselves in case we die while we've got the
    + 	 * file mmapped */
    +	mm = mmap (NULL, r->finfo.st_size, PROT_READ, MAP_PRIVATE,
    +		    fileno(f), 0);
    +	if (mm == (caddr_t)-1) {
    +	    ap_log_error(APLOG_MARK, APLOG_CRIT, r->server,
    +			"default_handler: mmap failed: %s", r->filename);
    +	}
    +    } else {
    +	mm = (caddr_t)-1;
    +    }
    +
    +    if (mm == (caddr_t)-1) {
    +	ap_unblock_alarms();
    +#endif
    +
    +	if (d->content_md5 & 1) {
    +	    ap_table_setn(r->headers_out, "Content-MD5", ap_md5digest(r->pool, f));
    +	}
    +
    +	rangestatus = ap_set_byterange(r);
    +#ifdef CHARSET_EBCDIC
    +	/* 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.
    +	 */
    +        ap_checkconv(r);
    +#endif /*CHARSET_EBCDIC*/
    +
    +	ap_send_http_header (r);
    +	
    +	if (!r->header_only) {
    +	    if (!rangestatus)
    +		ap_send_fd (f, r);
    +	    else {
    +		long offset, length;
    +		while (ap_each_byterange(r, &offset, &length)) {
    +		    fseek(f, offset, SEEK_SET);
    +		    ap_send_fd_length(f, r, length);
    +		}
    +	    }
    +	}
    +
    +#ifdef USE_MMAP_FILES
    +    } else {
    +	struct mmap *mmd;
    +
    +	mmd = ap_palloc (r->pool, sizeof (*mmd));
    +	mmd->mm = mm;
    +	mmd->length = r->finfo.st_size;
    +	ap_register_cleanup (r->pool, (void *)mmd, mmap_cleanup, mmap_cleanup);
    +	ap_unblock_alarms();
    +
    +	if (d->content_md5 & 1) {
    +	    AP_MD5_CTX context;
    +	    
    +	    ap_MD5Init(&context);
    +	    ap_MD5Update(&context, (void *)mm, r->finfo.st_size);
    +	    ap_table_setn(r->headers_out, "Content-MD5",
    +		ap_md5contextTo64(r->pool, &context));
    +	}
    +
    +	rangestatus = ap_set_byterange(r);
    +	ap_send_http_header (r);
    +	
    +	if (!r->header_only) {
    +	    if (!rangestatus)
    +		ap_send_mmap (mm, r, 0, r->finfo.st_size);
    +	    else {
    +		long offset, length;
    +		while (ap_each_byterange(r, &offset, &length)) {
    +		    ap_send_mmap(mm, r, offset, length);
    +		}
    +	    }
    +	}
    +    }
    +#endif
    +
    +    ap_pfclose(r->pool, f);
    +    return OK;
    +}
    +
    +static const handler_rec core_handlers[] = {
    +{ "*/*", default_handler },
    +{ NULL }
    +};
    +
    +API_VAR_EXPORT module core_module = {
    +   STANDARD_MODULE_STUFF,
    +   NULL,			/* initializer */
    +   create_core_dir_config,	/* create per-directory config structure */
    +   merge_core_dir_configs,	/* merge per-directory config structures */
    +   create_core_server_config,	/* create per-server config structure */
    +   merge_core_server_configs,	/* merge per-server config structures */
    +   core_cmds,			/* command table */
    +   core_handlers,		/* handlers */
    +   core_translate,		/* translate_handler */
    +   NULL,			/* check_user_id */
    +   NULL,			/* check auth */
    +   do_nothing,			/* check access */
    +   do_nothing,			/* type_checker */
    +   NULL,			/* pre-run fixups */
    +   NULL,			/* logger */
    +   NULL,			/* header parser */
    +   NULL,			/* child_init */
    +   NULL,			/* child_exit */
    +   NULL				/* post_read_request */
    +};
    diff --git a/APACHE_1_3b7/src/main/http_log.c b/APACHE_1_3b7/src/main/http_log.c
    new file mode 100644
    index 0000000000..2190b32970
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/http_log.c
    @@ -0,0 +1,673 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +/*
    + * http_log.c: Dealing with the logs and errors
    + * 
    + * Rob McCool
    + * 
    + */
    +
    +
    +#define CORE_PRIVATE
    +#include "httpd.h"
    +#include "http_config.h"
    +#include "http_core.h"
    +#include "http_log.h"
    +#include "http_main.h"
    +
    +#include <stdarg.h>
    +
    +typedef struct {
    +	char	*t_name;
    +	int	t_val;
    +} TRANS;
    +
    +#ifdef HAVE_SYSLOG
    +
    +static const TRANS facilities[] = {
    +    {"auth",	LOG_AUTH},
    +#ifdef LOG_AUTHPRIV
    +    {"authpriv",LOG_AUTHPRIV},
    +#endif
    +#ifdef LOG_CRON
    +    {"cron", 	LOG_CRON},
    +#endif
    +#ifdef LOG_DAEMON
    +    {"daemon",	LOG_DAEMON},
    +#endif
    +#ifdef LOG_FTP
    +    {"ftp",	LOG_FTP},
    +#endif
    +#ifdef LOG_KERN
    +    {"kern",	LOG_KERN},
    +#endif
    +#ifdef LOG_LPR
    +    {"lpr",	LOG_LPR},
    +#endif
    +#ifdef LOG_MAIL
    +    {"mail",	LOG_MAIL},
    +#endif
    +#ifdef LOG_NEWS
    +    {"news",	LOG_NEWS},
    +#endif
    +#ifdef LOG_SYSLOG
    +    {"syslog",	LOG_SYSLOG},
    +#endif
    +#ifdef LOG_USER
    +    {"user",	LOG_USER},
    +#endif
    +#ifdef LOG_UUCP
    +    {"uucp",	LOG_UUCP},
    +#endif
    +#ifdef LOG_LOCAL0
    +    {"local0",	LOG_LOCAL0},
    +#endif
    +#ifdef LOG_LOCAL1
    +    {"local1",	LOG_LOCAL1},
    +#endif
    +#ifdef LOG_LOCAL2
    +    {"local2",	LOG_LOCAL2},
    +#endif
    +#ifdef LOG_LOCAL3
    +    {"local3",	LOG_LOCAL3},
    +#endif
    +#ifdef LOG_LOCAL4
    +    {"local4",	LOG_LOCAL4},
    +#endif
    +#ifdef LOG_LOCAL5
    +    {"local5",	LOG_LOCAL5},
    +#endif
    +#ifdef LOG_LOCAL6
    +    {"local6",	LOG_LOCAL6},
    +#endif
    +#ifdef LOG_LOCAL7
    +    {"local7",	LOG_LOCAL7},
    +#endif
    +    {NULL,		-1},
    +};
    +#endif
    +
    +static const TRANS priorities[] = {
    +    {"emerg",	APLOG_EMERG},
    +    {"alert",	APLOG_ALERT},
    +    {"crit",	APLOG_CRIT},
    +    {"error",	APLOG_ERR},
    +    {"warn",	APLOG_WARNING},
    +    {"notice",	APLOG_NOTICE},
    +    {"info",	APLOG_INFO},
    +    {"debug",	APLOG_DEBUG},
    +    {NULL,	-1},
    +};
    +
    +static int error_log_child (void *cmd, child_info *pinfo)
    +{
    +    /* Child process code for 'ErrorLog "|..."';
    +     * may want a common framework for this, since I expect it will
    +     * be common for other foo-loggers to want this sort of thing...
    +     */
    +    int child_pid = 0;
    +
    +    ap_cleanup_for_exec();
    +#ifdef SIGHUP
    +    /* No concept of a child process on Win32 */
    +    signal (SIGHUP, SIG_IGN);
    +#endif /* ndef SIGHUP */
    +#if defined(WIN32)
    +    child_pid = spawnl (_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    +    return(child_pid);
    +#elif defined(__EMX__)
    +    /* For OS/2 we need to use a '/' */
    +    execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    +#else    
    +    execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
    +#endif    
    +    exit (1);
    +    /* NOT REACHED */
    +    return(child_pid);
    +}
    +
    +static void open_error_log (server_rec *s, pool *p)
    +{
    +    char *fname;
    +
    +    if (*s->error_fname == '|') {
    +	FILE *dummy;
    +
    +	if (!spawn_child (p, error_log_child, (void *)(s->error_fname+1),
    +			  kill_after_timeout, &dummy, NULL)) {
    +	    perror ("spawn_child");
    +	    fprintf (stderr, "Couldn't fork child for ErrorLog process\n");
    +	    exit (1);
    +	}
    +
    +	s->error_log = dummy;
    +    }
    +
    +#ifdef HAVE_SYSLOG
    +    else if (!strncasecmp(s->error_fname, "syslog", 6)) {
    +	if ((fname = strchr(s->error_fname, ':'))) {
    +	    const TRANS *fac;
    +
    +	    fname++;
    +	    for (fac = facilities; fac->t_name; fac++) {
    +		if (!strcasecmp(fname, fac->t_name)) {
    +		    openlog("httpd", LOG_NDELAY|LOG_CONS|LOG_PID, fac->t_val);
    +		    s->error_log = NULL;
    +		    return;
    +		}
    +	    }
    +	}
    +	else
    +	    openlog("httpd", LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
    +
    +	s->error_log = NULL;
    +    }
    +#endif
    +    else {
    +	fname = ap_server_root_relative (p, s->error_fname);
    +        if(!(s->error_log = ap_pfopen(p, fname, "a"))) {
    +            perror("fopen");
    +            fprintf(stderr,"httpd: could not open error log file %s.\n", fname);
    +            exit(1);
    +	}
    +    }
    +}
    +
    +void ap_open_logs (server_rec *s_main, pool *p)
    +{
    +    server_rec *virt, *q;
    +    int replace_stderr;
    +
    +    open_error_log (s_main, p);
    +
    +    replace_stderr = 1;
    +    if (s_main->error_log) {
    +	/* replace stderr with this new log */
    +	fflush(stderr);
    +	if (dup2(fileno(s_main->error_log), 2) == -1) {
    +	    ap_log_error(APLOG_MARK, APLOG_CRIT, s_main,
    +		"unable to replace stderr with error_log");
    +	} else {
    +	    replace_stderr = 0;
    +	}
    +    }
    +    /* note that stderr may still need to be replaced with something
    +     * because it points to the old error log, or back to the tty
    +     * of the submitter.
    +     */
    +    if (replace_stderr && freopen("/dev/null", "w", stderr) == NULL) {
    +	ap_log_error(APLOG_MARK, APLOG_CRIT, s_main,
    +	    "unable to replace stderr with /dev/null");
    +    }
    +
    +    for (virt = s_main->next; virt; virt = virt->next) {
    +	if (virt->error_fname)
    +	{
    +	    for (q=s_main; q != virt; q = q->next)
    +		if (q->error_fname != NULL &&
    +		    strcmp(q->error_fname, virt->error_fname) == 0)
    +		    break;
    +	    if (q == virt) open_error_log (virt, p);
    +	    else virt->error_log = q->error_log;
    +	}
    +	else
    +	    virt->error_log = s_main->error_log;
    +    }
    +}
    +
    +API_EXPORT(void) ap_error_log2stderr (server_rec *s) {
    +    if(fileno(s->error_log) != STDERR_FILENO)
    +        dup2(fileno(s->error_log),STDERR_FILENO);
    +}
    +
    +API_EXPORT(void) ap_log_error (const char *file, int line, int level,
    +			      const server_rec *s, const char *fmt, ...)
    +{
    +    va_list args;
    +    char errstr[MAX_STRING_LEN];
    +    size_t len;
    +    int save_errno = errno;
    +    FILE *logf;
    +
    +    if (s == NULL) {
    +	/*
    +	 * If we are doing stderr logging (startup), don't log messages that are
    +	 * above the default server log level unless it is a startup/shutdown
    +	 * notice
    +	 */
    +	if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) &&
    +	    ((level & APLOG_LEVELMASK) > DEFAULT_LOGLEVEL))
    +	    return;
    +	logf = stderr;
    +    }
    +    else if (s->error_log) {
    +	/*
    +	 * If we are doing normal logging, don't log messages that are
    +	 * above the server log level unless it is a startup/shutdown notice
    +	 */
    +	if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) &&
    +	    ((level & APLOG_LEVELMASK) > s->loglevel))
    +	    return;
    +	logf = s->error_log;
    +    }
    +    else {
    +	/*
    +	 * If we are doing syslog logging, don't log messages that are
    +	 * above the server log level (including a startup/shutdown notice)
    +	 */
    +	if ((level & APLOG_LEVELMASK) > s->loglevel)
    +	    return;
    +	logf = NULL;
    +    }
    +
    +    if (logf) {
    +	len = ap_snprintf(errstr, sizeof(errstr), "[%s] ", ap_get_time());
    +    } else {
    +	len = 0;
    +    }
    +
    +    len += ap_snprintf(errstr + len, sizeof(errstr) - len,
    +	    "[%s] ", priorities[level & APLOG_LEVELMASK].t_name);
    +
    +    if (file && (level & APLOG_LEVELMASK) == APLOG_DEBUG) {
    +#ifdef _OSD_POSIX
    +	char tmp[256];
    +	char *e = strrchr(file, '/');
    +
    +	/* In OSD/POSIX, the compiler returns for __FILE__
    +	 * a string like: __FILE__="*POSIX(/usr/include/stdio.h)"
    +	 * (it even returns an absolute path for sources in
    +	 * the current directory). Here we try to strip this
    +	 * down to the basename.
    +	 */
    +	if (e != NULL && e[1] != '\0') {
    +	    ap_snprintf(tmp, sizeof(tmp), "%s", &e[1]);
    +	    e = &tmp[strlen(tmp)-1];
    +	    if (*e == ')')
    +		*e = '\0';
    +	    file = tmp;
    +	}
    +#endif /*_OSD_POSIX*/
    +	len += ap_snprintf(errstr + len, sizeof(errstr) - len,
    +		"%s(%d): ", file, line);
    +    }
    +    if (!(level & APLOG_NOERRNO)
    +	&& (save_errno != 0)
    +#ifdef WIN32
    +	&& !(level & APLOG_WIN32ERROR)
    +#endif
    +	) {
    +	len += ap_snprintf(errstr + len, sizeof(errstr) - len,
    +		"(%d)%s: ", save_errno, strerror(save_errno));
    +    }
    +#ifdef WIN32
    +    if (level & APLOG_WIN32ERROR) {
    +	int nChars;
    +	int nErrorCode;
    +
    +	nErrorCode = GetLastError();
    +	len += ap_snprintf(errstr + len, sizeof(errstr) - len,
    +	    "(%d)", nErrorCode);
    +
    +	nChars = FormatMessage( 
    +	    FORMAT_MESSAGE_FROM_SYSTEM,
    +	    NULL,
    +	    nErrorCode,
    +	    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    +	    (LPTSTR) errstr + len,
    +	    sizeof(errstr) - len,
    +	    NULL 
    +	);
    +	len += nChars;
    +	if (nChars == 0) {
    +	    /* Um, error occurred, but we can't recurse to log it again
    +	     * (and it would probably only fail anyway), so lets just
    +	     * log the numeric value.
    +	     */
    +	    nErrorCode = GetLastError();
    +	    len += ap_snprintf(errstr + len, sizeof(errstr) - len,
    +		"(FormatMessage failed with code %d): ", nErrorCode);
    +	}
    +	else {
    +	    /* FormatMessage put the message in the buffer, but it may
    +	     * have appended a newline (\r\n). So remove it and use
    +	     * ": " instead like the Unix errors. The error may also
    +	     * end with a . before the return - if so, trash it.
    +	     */
    +	    if (len > 1 && errstr[len-2] == '\r' && errstr[len-1] == '\n') {
    +		if (len > 2 && errstr[len-3] == '.')
    +		    len--;
    +		errstr[len-2] = ':';
    +		errstr[len-1] = ' ';
    +	    }
    +	}
    +    }
    +#endif
    +
    +    va_start(args, fmt);
    +    len += ap_vsnprintf(errstr + len, sizeof(errstr) - len, fmt, args);
    +    va_end(args);
    +
    +    /* NULL if we are logging to syslog */
    +    if (logf) {
    +	fputs(errstr, logf);
    +	fputc('\n', logf);
    +	fflush(logf);
    +    }
    +#ifdef HAVE_SYSLOG
    +    else {
    +	syslog(level & APLOG_LEVELMASK, "%s", errstr);
    +    }
    +#endif
    +}
    +    
    +
    +void ap_log_pid (pool *p, char *fname)
    +{
    +    FILE *pid_file;
    +
    +    if (!fname) return;
    +    fname = ap_server_root_relative (p, fname);
    +    if(!(pid_file = fopen(fname,"w"))) {
    +	perror("fopen");
    +        fprintf(stderr,"httpd: could not log pid to file %s\n", fname);
    +        exit(1);
    +    }
    +    fprintf(pid_file,"%ld\n",(long)getpid());
    +    fclose(pid_file);
    +}
    +
    +API_EXPORT(void) ap_log_error_old (const char *err, server_rec *s)
    +{
    +    ap_log_error(APLOG_MARK, APLOG_ERR, s, err);
    +}
    +
    +API_EXPORT(void) ap_log_unixerr (const char *routine, const char *file,
    +			      const char *msg, server_rec *s)
    +{
    +    ap_log_error(file, 0, APLOG_ERR, s, msg);
    +}
    +
    +API_EXPORT(void) ap_log_printf (const server_rec *s, const char *fmt, ...)
    +{
    +    char buf[MAX_STRING_LEN];
    +    va_list args;
    +    
    +    va_start(args, fmt);
    +    ap_vsnprintf(buf, sizeof(buf), fmt, args);
    +    ap_log_error(APLOG_MARK, APLOG_ERR, s, buf);
    +    va_end(args);
    +}
    +
    +API_EXPORT(void) ap_log_reason (const char *reason, const char *file, request_rec *r) 
    +{
    +    ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
    +		"access to %s failed for %s, reason: %s",
    +		file,
    +		ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME),
    +		reason);
    +}
    +
    +API_EXPORT(void) ap_log_assert (const char *szExp, const char *szFile, int nLine)
    +{
    +    fprintf(stderr, "[%s] file %s, line %d, assertion \"%s\" failed\n",
    +	    ap_get_time(), szFile, nLine, szExp);
    +#ifndef WIN32
    +    /* unix assert does an abort leading to a core dump */
    +    abort();
    +#else
    +    exit(1);
    +#endif
    +}
    +
    +/* piped log support */
    +
    +#ifndef NO_RELIABLE_PIPED_LOGS
    +/* forward declaration */
    +static void piped_log_maintenance (int reason, void *data, int status);
    +
    +static int piped_log_spawn (piped_log *pl)
    +{
    +    int pid;
    +
    +    ap_block_alarms();
    +    pid = fork();
    +    if (pid == 0) {
    +	/* XXX: this needs porting to OS2 and WIN32 */
    +	/* XXX: need to check what open fds the logger is actually passed,
    +	 * XXX: and CGIs for that matter ... cleanup_for_exec *should*
    +	 * XXX: close all the relevant stuff, but hey, it could be broken. */
    +	RAISE_SIGSTOP(PIPED_LOG_SPAWN);
    +	/* we're now in the child */
    +	close (STDIN_FILENO);
    +	dup2 (pl->fds[0], STDIN_FILENO);
    +
    +	ap_cleanup_for_exec ();
    +	signal (SIGCHLD, SIG_DFL);	/* for HPUX */
    +	signal (SIGHUP, SIG_IGN);
    +	execl (SHELL_PATH, SHELL_PATH, "-c", pl->program, NULL);
    +	fprintf (stderr,
    +	    "piped_log_spawn: unable to exec %s -c '%s': %s\n",
    +	    SHELL_PATH, pl->program, strerror (errno));
    +	exit (1);
    +    }
    +    if (pid == -1) {
    +	fprintf (stderr,
    +	    "piped_log_spawn: unable to fork(): %s\n", strerror (errno));
    +	ap_unblock_alarms ();
    +	return -1;
    +    }
    +    ap_unblock_alarms();
    +    pl->pid = pid;
    +    ap_register_other_child (pid, piped_log_maintenance, pl, pl->fds[1]);
    +    return 0;
    +}
    +
    +
    +static void piped_log_maintenance (int reason, void *data, int status)
    +{
    +    piped_log *pl = data;
    +
    +    switch (reason) {
    +    case OC_REASON_DEATH:
    +    case OC_REASON_LOST:
    +	pl->pid = -1;
    +	ap_unregister_other_child (pl);
    +	if (pl->program == NULL) {
    +	    /* during a restart */
    +	    break;
    +	}
    +	if (piped_log_spawn (pl) == -1) {
    +	    /* what can we do?  This could be the error log we're having
    +	     * problems opening up... */
    +	    fprintf (stderr,
    +		"piped_log_maintenance: unable to respawn '%s': %s\n",
    +		pl->program, strerror (errno));
    +	}
    +	break;
    +    
    +    case OC_REASON_UNWRITABLE:
    +	if (pl->pid != -1) {
    +	    kill (pl->pid, SIGTERM);
    +	}
    +	break;
    +    
    +    case OC_REASON_RESTART:
    +	pl->program = NULL;
    +	if (pl->pid != -1) {
    +	    kill (pl->pid, SIGTERM);
    +	}
    +	break;
    +
    +    case OC_REASON_UNREGISTER:
    +	break;
    +    }
    +}
    +
    +
    +static void piped_log_cleanup (void *data)
    +{
    +    piped_log *pl = data;
    +
    +    if (pl->pid != -1) {
    +	kill (pl->pid, SIGTERM);
    +    }
    +    ap_unregister_other_child (pl);
    +    close (pl->fds[0]);
    +    close (pl->fds[1]);
    +}
    +
    +
    +static void piped_log_cleanup_for_exec (void *data)
    +{
    +    piped_log *pl = data;
    +
    +    close (pl->fds[0]);
    +    close (pl->fds[1]);
    +}
    +
    +
    +API_EXPORT(piped_log *) ap_open_piped_log (pool *p, const char *program)
    +{
    +    piped_log *pl;
    +
    +    pl = ap_palloc (p, sizeof (*pl));
    +    pl->p = p;
    +    pl->program = ap_pstrdup (p, program);
    +    pl->pid = -1;
    +    ap_block_alarms ();
    +    if (pipe (pl->fds) == -1) {
    +	int save_errno = errno;
    +	ap_unblock_alarms();
    +	errno = save_errno;
    +	return NULL;
    +    }
    +    ap_register_cleanup (p, pl, piped_log_cleanup, piped_log_cleanup_for_exec);
    +    if (piped_log_spawn (pl) == -1) {
    +	int save_errno = errno;
    +	ap_kill_cleanup (p, pl, piped_log_cleanup);
    +	close (pl->fds[0]);
    +	close (pl->fds[1]);
    +	ap_unblock_alarms ();
    +	errno = save_errno;
    +	return NULL;
    +    }
    +    ap_unblock_alarms ();
    +    return pl;
    +}
    +
    +API_EXPORT(void) ap_close_piped_log (piped_log *pl)
    +{
    +    ap_block_alarms ();
    +    piped_log_cleanup (pl);
    +    ap_kill_cleanup (pl->p, pl, piped_log_cleanup);
    +    ap_unblock_alarms ();
    +}
    +
    +#else
    +static int piped_log_child (void *cmd)
    +{
    +    /* Child process code for 'TransferLog "|..."';
    +     * may want a common framework for this, since I expect it will
    +     * be common for other foo-loggers to want this sort of thing...
    +     */
    +    int child_pid = 1;
    +
    +    ap_cleanup_for_exec();
    +#ifdef SIGHUP
    +    signal (SIGHUP, SIG_IGN);
    +#endif
    +#if defined(WIN32)
    +    child_pid = spawnl (_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    +    return(child_pid);
    +#elif defined(__EMX__)
    +    /* For OS/2 we need to use a '/' */
    +    execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    +#else
    +    execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
    +#endif
    +    perror ("exec");
    +    fprintf (stderr, "Exec of shell for logging failed!!!\n");
    +    return(child_pid);
    +}
    +
    +
    +API_EXPORT(piped_log *) ap_open_piped_log (pool *p, const char *program)
    +{
    +    piped_log *pl;
    +    FILE *dummy;
    +
    +    if (!spawn_child (p, piped_log_child, (void *)program,
    +		kill_after_timeout, &dummy, NULL)) {
    +	perror ("spawn_child");
    +	fprintf (stderr, "Couldn't fork child for piped log process\n");
    +	exit (1);
    +    }
    +    pl = ap_palloc (p, sizeof (*pl));
    +    pl->p = p;
    +    pl->write_f = dummy;
    +
    +    return pl;
    +}
    +
    +
    +API_EXPORT(void) ap_close_piped_log (piped_log *pl)
    +{
    +    ap_pfclose (pl->p, pl->write_f);
    +}
    +#endif
    diff --git a/APACHE_1_3b7/src/main/http_main.c b/APACHE_1_3b7/src/main/http_main.c
    new file mode 100644
    index 0000000000..98c9e0e252
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/http_main.c
    @@ -0,0 +1,5618 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +/*
    + * httpd.c: simple http daemon for answering WWW file requests
    + *
    + * 
    + * 03-21-93  Rob McCool wrote original code (up to NCSA HTTPd 1.3)
    + * 
    + * 03-06-95  blong
    + *  changed server number for child-alone processes to 0 and changed name
    + *   of processes
    + *
    + * 03-10-95  blong
    + *      Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu) 
    + *      including set group before fork, and call gettime before to fork
    + *      to set up libraries.
    + *
    + * 04-14-95  rst / rh
    + *      Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
    + *      Apache server, and also to have child processes do accept() directly.
    + *
    + * April-July '95 rst
    + *      Extensive rework for Apache.
    + */
    +
    +#ifndef SHARED_CORE_BOOTSTRAP
    +#ifndef SHARED_CORE_TIESTATIC
    +
    +#ifdef SHARED_CORE
    +#define REALMAIN ap_main
    +#else
    +#define REALMAIN main
    +#endif
    +
    +#define CORE_PRIVATE
    +
    +#include "httpd.h"
    +#include "http_main.h"
    +#include "http_log.h"
    +#include "http_config.h"	/* for read_config */
    +#include "http_protocol.h"	/* for read_request */
    +#include "http_request.h"	/* for process_request */
    +#include "http_conf_globals.h"
    +#include "http_core.h"		/* for get_remote_host */
    +#include "http_vhost.h"
    +#include "util_script.h"	/* to force util_script.c linking */
    +#include "util_uri.h"
    +#include "scoreboard.h"
    +#include "multithread.h"
    +#include <sys/stat.h>
    +#ifdef USE_SHMGET_SCOREBOARD
    +#include <sys/types.h>
    +#include <sys/ipc.h>
    +#include <sys/shm.h>
    +#endif
    +#ifdef SecureWare
    +#include <sys/security.h>
    +#include <sys/audit.h>
    +#include <prot.h>
    +#endif
    +#ifdef WIN32
    +#include "../os/win32/getopt.h"
    +#elif !defined(BEOS)
    +#include <netinet/tcp.h>
    +#endif
    +
    +#ifdef HAVE_BSTRING_H
    +#include <bstring.h>		/* for IRIX, FD_SET calls bzero() */
    +#endif
    +
    +#ifdef MULTITHREAD
    +/* special debug stuff -- PCS */
    +
    +/* Set this non-zero if you are prepared to put up with more than one log entry per second */
    +#define SEVERELY_VERBOSE	    0
    +
    +  /* APD1() to APD5() are macros to help us debug. They can either
    +   * log to the screen or the error_log file. In release builds, these
    +   * macros do nothing. In debug builds, they send messages at priority
    +   * "debug" to the error log file, or if DEBUG_TO_CONSOLE is defined,
    +   * to the console.
    +   */
    +
    +# ifdef _DEBUG
    +#  ifndef DEBUG_TO_CONSOLE
    +#   define APD1(a) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a)
    +#   define APD2(a,b) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b)
    +#   define APD3(a,b,c) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b,c)
    +#   define APD4(a,b,c,d) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b,c,d)
    +#   define APD5(a,b,c,d,e) ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,server_conf,a,b,c,d,e)
    +#  else
    +#   define APD1(a) printf("%s\n",a)
    +#   define APD2(a,b) do { printf(a,b);putchar('\n'); } while(0);
    +#   define APD3(a,b,c) do { printf(a,b,c);putchar('\n'); } while(0);
    +#   define APD4(a,b,c,d) do { printf(a,b,c,d);putchar('\n'); } while(0);
    +#   define APD5(a,b,c,d,e) do { printf(a,b,c,d,e);putchar('\n'); } while(0);
    +#  endif
    +# else /* !_DEBUG */
    +#  define APD1(a) 
    +#  define APD2(a,b) 
    +#  define APD3(a,b,c) 
    +#  define APD4(a,b,c,d) 
    +#  define APD5(a,b,c,d,e) 
    +# endif /* _DEBUG */
    +#endif /* MULTITHREAD */
    +
    +/* This next function is never used. It is here to ensure that if we
    + * make all the modules into shared libraries that core httpd still
    + * includes the full Apache API. Without this function the objects in
    + * main/util_script.c would not be linked into a minimal httpd.
    + * And the extra prototype is to make gcc -Wmissing-prototypes quiet.
    + */
    +extern void ap_force_library_loading(void);
    +void ap_force_library_loading(void) {
    +    ap_add_cgi_vars(NULL);
    +}
    +
    +#include "explain.h"
    +
    +#if !defined(max)
    +#define max(a,b)        (a > b ? a : b)
    +#endif
    +
    +#ifdef WIN32
    +#include "../os/win32/service.h"
    +#include "../os/win32/registry.h"
    +#endif
    +
    +
    +#ifdef MINT
    +long _stksize = 32768;
    +#endif
    +
    +#ifdef USE_OS2_SCOREBOARD
    +    /* Add MMAP style functionality to OS/2 */
    +#define INCL_DOSMEMMGR
    +#include <os2.h>
    +#include <umalloc.h>
    +#include <stdio.h>
    +caddr_t create_shared_heap(const char *, size_t);
    +caddr_t get_shared_heap(const char *);
    +#endif
    +
    +DEF_Explain
    +
    +/* Defining GPROF when compiling uses the moncontrol() function to
    + * disable gprof profiling in the parent, and enable it only for
    + * request processing in children (or in one_process mode).  It's
    + * absolutely required to get useful gprof results under linux
    + * because the profile itimers and such are disabled across a
    + * fork().  It's probably useful elsewhere as well.
    + */
    +#ifdef GPROF
    +extern void moncontrol(int);
    +#define MONCONTROL(x) moncontrol(x)
    +#else
    +#define MONCONTROL(x)
    +#endif
    +
    +#ifndef MULTITHREAD
    +/* this just need to be anything non-NULL */
    +void *ap_dummy_mutex = &ap_dummy_mutex;
    +#endif
    +
    +/*
    + * Actual definitions of config globals... here because this is
    + * for the most part the only code that acts on 'em.  (Hmmm... mod_main.c?)
    + */
    +
    +int ap_standalone;
    +uid_t ap_user_id;
    +char *ap_user_name;
    +gid_t ap_group_id;
    +#ifdef MULTIPLE_GROUPS
    +gid_t group_id_list[NGROUPS_MAX];
    +#endif
    +int ap_max_requests_per_child;
    +int ap_threads_per_child;
    +int ap_excess_requests_per_child;
    +char *ap_pid_fname;
    +char *ap_scoreboard_fname;
    +char *ap_lock_fname;
    +char *ap_server_argv0;
    +struct in_addr ap_bind_address;
    +int ap_daemons_to_start;
    +int ap_daemons_min_free;
    +int ap_daemons_max_free;
    +int ap_daemons_limit;
    +time_t ap_restart_time;
    +int ap_suexec_enabled = 0;
    +int ap_listenbacklog;
    +int ap_dump_settings;
    +
    +/*
    + * The max child slot ever assigned, preserved across restarts.  Necessary
    + * to deal with MaxClients changes across SIGUSR1 restarts.  We use this
    + * value to optimize routines that have to scan the entire scoreboard.
    + */
    +static int max_daemons_limit = -1;
    +
    +/*
    + * During config time, listeners is treated as a NULL-terminated list.
    + * child_main previously would start at the beginning of the list each time
    + * through the loop, so a socket early on in the list could easily starve out
    + * sockets later on in the list.  The solution is to start at the listener
    + * after the last one processed.  But to do that fast/easily in child_main it's
    + * way more convenient for listeners to be a ring that loops back on itself.
    + * The routine setup_listeners() is called after config time to both open up
    + * the sockets and to turn the NULL-terminated list into a ring that loops back
    + * on itself.
    + *
    + * head_listener is used by each child to keep track of what they consider
    + * to be the "start" of the ring.  It is also set by make_child to ensure
    + * that new children also don't starve any sockets.
    + *
    + * Note that listeners != NULL is ensured by read_config().
    + */
    +listen_rec *ap_listeners;
    +static listen_rec *head_listener;
    +
    +API_VAR_EXPORT char ap_server_root[MAX_STRING_LEN];
    +char ap_server_confname[MAX_STRING_LEN];
    +char ap_coredump_dir[MAX_STRING_LEN];
    +
    +array_header *ap_server_pre_read_config;
    +array_header *ap_server_post_read_config;
    +
    +/* *Non*-shared http_main globals... */
    +
    +static server_rec *server_conf;
    +static JMP_BUF APACHE_TLS jmpbuffer;
    +static int sd;
    +static fd_set listenfds;
    +static int listenmaxfd;
    +static pid_t pgrp;
    +
    +/* one_process --- debugging mode variable; can be set from the command line
    + * with the -X flag.  If set, this gets you the child_main loop running
    + * in the process which originally started up (no detach, no make_child),
    + * which is a pretty nice debugging environment.  (You'll get a SIGHUP
    + * early in standalone_main; just continue through.  This is the server
    + * trying to kill off any child processes which it might have lying
    + * around --- Apache doesn't keep track of their pids, it just sends
    + * SIGHUP to the process group, ignoring it in the root process.
    + * Continue through and you'll be fine.).
    + */
    +
    +static int one_process = 0;
    +
    +/* set if timeouts are to be handled by the children and not by the parent.
    + * i.e. child_timeouts = !standalone || one_process.
    + */
    +static int child_timeouts;
    +
    +#ifdef DEBUG_SIGSTOP
    +int raise_sigstop_flags;
    +#endif
    +
    +#ifndef NO_OTHER_CHILD
    +/* used to maintain list of children which aren't part of the scoreboard */
    +typedef struct other_child_rec other_child_rec;
    +struct other_child_rec {
    +    other_child_rec *next;
    +    int pid;
    +    void (*maintenance) (int, void *, int);
    +    void *data;
    +    int write_fd;
    +};
    +static other_child_rec *other_children;
    +#endif
    +
    +static pool *pconf;		/* Pool for config stuff */
    +static pool *ptrans;		/* Pool for per-transaction stuff */
    +static pool *pchild;		/* Pool for httpd child stuff */
    +static pool *pcommands;	/* Pool for -C and -c switches */
    +
    +static int APACHE_TLS my_pid;	/* it seems silly to call getpid all the time */
    +#ifndef MULTITHREAD
    +static int my_child_num;
    +#endif
    +
    +scoreboard *ap_scoreboard_image = NULL;
    +
    +/*
    + * Pieces for managing the contents of the Server response header
    + * field.
    + */
    +static char *server_version = NULL;
    +static int version_locked = 0;
    +
    +/* Global, alas, so http_core can talk to us */
    +enum server_token_type ap_server_tokens = SrvTk_FULL;
    +
    +/*
    + * This routine is called when the pconf pool is vacuumed.  It resets the
    + * server version string to a known value and [re]enables modifications
    + * (which are disabled by configuration completion).
    + */
    +static void reset_version(void *dummy)
    +{
    +    version_locked = 0;
    +    ap_server_tokens = SrvTk_FULL;
    +    server_version = NULL;
    +}
    +
    +API_EXPORT(const char *) ap_get_server_version()
    +{
    +    return (server_version ? server_version : SERVER_BASEVERSION);
    +}
    +
    +API_EXPORT(void) ap_add_version_component(const char *component)
    +{
    +    if (! version_locked) {
    +        /*
    +         * If the version string is null, register our cleanup to reset the
    +         * pointer on pool destruction. We also know that, if NULL,
    +	 * we are adding the original SERVER_BASEVERSION string.
    +         */
    +        if (server_version == NULL) {
    +	    ap_register_cleanup(pconf, NULL, (void (*)(void *))reset_version, 
    +				ap_null_cleanup);
    +	    server_version = ap_pstrdup(pconf, component);
    +	}
    +	else {
    +	    /*
    +	     * Tack the given component identifier to the end of
    +	     * the existing string.
    +	     */
    +	    server_version = ap_pstrcat(pconf, server_version, " ",
    +					component, NULL);
    +	}
    +    }
    +}
    +
    +/*
    + * This routine adds the real server base identity to the version string,
    + * and then locks out changes until the next reconfig.
    + */
    +static void ap_set_version()
    +{
    +    if (ap_server_tokens == SrvTk_MIN) {
    +	ap_add_version_component(SERVER_BASEVERSION);
    +    }
    +    else {
    +	ap_add_version_component(SERVER_BASEVERSION " (" PLATFORM ")");
    +    }
    +    /*
    +     * Lock the server_version string if we're not displaying
    +     * the full set of tokens
    +     */
    +    if (ap_server_tokens != SrvTk_FULL) {
    +	version_locked++;
    +    }
    +}
    +
    +static APACHE_TLS int volatile exit_after_unblock = 0;
    +
    +/* a clean exit from a child with proper cleanup */
    +static void __attribute__((noreturn)) clean_child_exit(int code)
    +{
    +    if (pchild) {
    +	ap_child_exit_modules(pchild, server_conf);
    +	ap_destroy_pool(pchild);
    +    }
    +    exit(code);
    +}
    +
    +#if defined(USE_FCNTL_SERIALIZED_ACCEPT) || defined(USE_FLOCK_SERIALIZED_ACCEPT)
    +static void expand_lock_fname(pool *p)
    +{
    +    /* XXXX possibly bogus cast */
    +    ap_lock_fname = ap_psprintf(p, "%s.%lu",
    +	ap_server_root_relative(p, ap_lock_fname), (unsigned long)getpid());
    +}
    +#endif
    +
    +#if defined (USE_USLOCK_SERIALIZED_ACCEPT)
    +
    +#include <ulocks.h>
    +
    +static ulock_t uslock = NULL;
    +
    +#define accept_mutex_child_init(x)
    +
    +static void accept_mutex_init(pool *p)
    +{
    +    ptrdiff_t old;
    +    usptr_t *us;
    +
    +
    +    /* default is 8, allocate enough for all the children plus the parent */
    +    if ((old = usconfig(CONF_INITUSERS, HARD_SERVER_LIMIT + 1)) == -1) {
    +	perror("usconfig(CONF_INITUSERS)");
    +	exit(-1);
    +    }
    +
    +    if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) {
    +	perror("usconfig(CONF_LOCKTYPE)");
    +	exit(-1);
    +    }
    +    if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) {
    +	perror("usconfig(CONF_ARENATYPE)");
    +	exit(-1);
    +    }
    +    if ((us = usinit("/dev/zero")) == NULL) {
    +	perror("usinit");
    +	exit(-1);
    +    }
    +
    +    if ((uslock = usnewlock(us)) == NULL) {
    +	perror("usnewlock");
    +	exit(-1);
    +    }
    +}
    +
    +static void accept_mutex_on()
    +{
    +    switch (ussetlock(uslock)) {
    +    case 1:
    +	/* got lock */
    +	break;
    +    case 0:
    +	fprintf(stderr, "didn't get lock\n");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    case -1:
    +	perror("ussetlock");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +}
    +
    +static void accept_mutex_off()
    +{
    +    if (usunsetlock(uslock) == -1) {
    +	perror("usunsetlock");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +}
    +
    +#elif defined (USE_PTHREAD_SERIALIZED_ACCEPT)
    +
    +/* This code probably only works on Solaris ... but it works really fast
    + * on Solaris.  Note that pthread mutexes are *NOT* released when a task
    + * dies ... the task has to free it itself.  So we block signals and
    + * try to be nice about releasing the mutex.
    + */
    +
    +#include <pthread.h>
    +
    +static pthread_mutex_t *accept_mutex = (void *)(caddr_t) -1;
    +static int have_accept_mutex;
    +static sigset_t accept_block_mask;
    +static sigset_t accept_previous_mask;
    +
    +static void accept_mutex_child_cleanup(void *foo)
    +{
    +    if (accept_mutex != (void *)(caddr_t)-1
    +	&& have_accept_mutex) {
    +	pthread_mutex_unlock(accept_mutex);
    +    }
    +}
    +
    +static void accept_mutex_child_init(pool *p)
    +{
    +    ap_register_cleanup(p, NULL, accept_mutex_child_cleanup, ap_null_cleanup);
    +}
    +
    +static void accept_mutex_cleanup(void *foo)
    +{
    +    if (accept_mutex != (void *)(caddr_t)-1
    +	&& munmap((caddr_t) accept_mutex, sizeof(*accept_mutex))) {
    +	perror("munmap");
    +    }
    +    accept_mutex = (void *)(caddr_t)-1;
    +}
    +
    +static void accept_mutex_init(pool *p)
    +{
    +    pthread_mutexattr_t mattr;
    +    int fd;
    +
    +    fd = open("/dev/zero", O_RDWR);
    +    if (fd == -1) {
    +	perror("open(/dev/zero)");
    +	exit(APEXIT_INIT);
    +    }
    +    accept_mutex = (pthread_mutex_t *) mmap((caddr_t) 0, sizeof(*accept_mutex),
    +				 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    +    if (accept_mutex == (void *) (caddr_t) - 1) {
    +	perror("mmap");
    +	exit(APEXIT_INIT);
    +    }
    +    close(fd);
    +    if ((errno = pthread_mutexattr_init(&mattr))) {
    +	perror("pthread_mutexattr_init");
    +	exit(APEXIT_INIT);
    +    }
    +    if ((errno = pthread_mutexattr_setpshared(&mattr,
    +						PTHREAD_PROCESS_SHARED))) {
    +	perror("pthread_mutexattr_setpshared");
    +	exit(APEXIT_INIT);
    +    }
    +    if ((errno = pthread_mutex_init(accept_mutex, &mattr))) {
    +	perror("pthread_mutex_init");
    +	exit(APEXIT_INIT);
    +    }
    +    sigfillset(&accept_block_mask);
    +    sigdelset(&accept_block_mask, SIGHUP);
    +    sigdelset(&accept_block_mask, SIGTERM);
    +    sigdelset(&accept_block_mask, SIGUSR1);
    +    ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
    +}
    +
    +static void accept_mutex_on()
    +{
    +    int err;
    +
    +    if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
    +	perror("sigprocmask(SIG_BLOCK)");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +    if ((err = pthread_mutex_lock(accept_mutex))) {
    +	errno = err;
    +	perror("pthread_mutex_lock");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +    have_accept_mutex = 1;
    +}
    +
    +static void accept_mutex_off()
    +{
    +    int err;
    +
    +    if ((err = pthread_mutex_unlock(accept_mutex))) {
    +	errno = err;
    +	perror("pthread_mutex_unlock");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +    /* There is a slight race condition right here... if we were to die right
    +     * now, we'd do another pthread_mutex_unlock.  Now, doing that would let
    +     * another process into the mutex.  pthread mutexes are designed to be
    +     * fast, as such they don't have protection for things like testing if the
    +     * thread owning a mutex is actually unlocking it (or even any way of
    +     * testing who owns the mutex).
    +     *
    +     * If we were to unset have_accept_mutex prior to releasing the mutex
    +     * then the race could result in the server unable to serve hits.  Doing
    +     * it this way means that the server can continue, but an additional
    +     * child might be in the critical section ... at least it's still serving
    +     * hits.
    +     */
    +    have_accept_mutex = 0;
    +    if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
    +	perror("sigprocmask(SIG_SETMASK)");
    +	clean_child_exit(1);
    +    }
    +}
    +
    +#elif defined (USE_SYSVSEM_SERIALIZED_ACCEPT)
    +
    +#include <sys/types.h>
    +#include <sys/ipc.h>
    +#include <sys/sem.h>
    +
    +#ifdef NEED_UNION_SEMUN
    +/* it makes no sense, but this isn't defined on solaris */
    +union semun {
    +    long val;
    +    struct semid_ds *buf;
    +    ushort *array;
    +};
    +
    +#endif
    +
    +static int sem_id = -1;
    +static struct sembuf op_on;
    +static struct sembuf op_off;
    +
    +/* We get a random semaphore ... the lame sysv semaphore interface
    + * means we have to be sure to clean this up or else we'll leak
    + * semaphores.
    + */
    +static void accept_mutex_cleanup(void *foo)
    +{
    +    union semun ick;
    +
    +    if (sem_id < 0)
    +	return;
    +    /* this is ignored anyhow */
    +    ick.val = 0;
    +    semctl(sem_id, 0, IPC_RMID, ick);
    +}
    +
    +#define accept_mutex_child_init(x)
    +
    +static void accept_mutex_init(pool *p)
    +{
    +    union semun ick;
    +    struct semid_ds buf;
    +
    +    /* acquire the semaphore */
    +    sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
    +    if (sem_id < 0) {
    +	perror("semget");
    +	exit(APEXIT_INIT);
    +    }
    +    ick.val = 1;
    +    if (semctl(sem_id, 0, SETVAL, ick) < 0) {
    +	perror("semctl(SETVAL)");
    +	exit(APEXIT_INIT);
    +    }
    +    if (!getuid()) {
    +	/* restrict it to use only by the appropriate user_id ... not that this
    +	 * stops CGIs from acquiring it and dinking around with it.
    +	 */
    +	buf.sem_perm.uid = ap_user_id;
    +	buf.sem_perm.gid = ap_group_id;
    +	buf.sem_perm.mode = 0600;
    +	ick.buf = &buf;
    +	if (semctl(sem_id, 0, IPC_SET, ick) < 0) {
    +	    perror("semctl(IPC_SET)");
    +	    exit(APEXIT_INIT);
    +	}
    +    }
    +    ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
    +
    +    /* pre-initialize these */
    +    op_on.sem_num = 0;
    +    op_on.sem_op = -1;
    +    op_on.sem_flg = SEM_UNDO;
    +    op_off.sem_num = 0;
    +    op_off.sem_op = 1;
    +    op_off.sem_flg = SEM_UNDO;
    +}
    +
    +static void accept_mutex_on()
    +{
    +    if (semop(sem_id, &op_on, 1) < 0) {
    +	perror("accept_mutex_on");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +}
    +
    +static void accept_mutex_off()
    +{
    +    if (semop(sem_id, &op_off, 1) < 0) {
    +	perror("accept_mutex_off");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +}
    +
    +#elif defined(USE_FCNTL_SERIALIZED_ACCEPT)
    +static struct flock lock_it;
    +static struct flock unlock_it;
    +
    +static int lock_fd = -1;
    +
    +#define accept_mutex_child_init(x)
    +
    +/*
    + * Initialize mutex lock.
    + * Must be safe to call this on a restart.
    + */
    +static void accept_mutex_init(pool *p)
    +{
    +
    +    lock_it.l_whence = SEEK_SET;	/* from current point */
    +    lock_it.l_start = 0;		/* -"- */
    +    lock_it.l_len = 0;			/* until end of file */
    +    lock_it.l_type = F_WRLCK;		/* set exclusive/write lock */
    +    lock_it.l_pid = 0;			/* pid not actually interesting */
    +    unlock_it.l_whence = SEEK_SET;	/* from current point */
    +    unlock_it.l_start = 0;		/* -"- */
    +    unlock_it.l_len = 0;		/* until end of file */
    +    unlock_it.l_type = F_UNLCK;		/* set exclusive/write lock */
    +    unlock_it.l_pid = 0;		/* pid not actually interesting */
    +
    +    expand_lock_fname(p);
    +    lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644);
    +    if (lock_fd == -1) {
    +	perror("open");
    +	fprintf(stderr, "Cannot open lock file: %s\n", ap_lock_fname);
    +	exit(APEXIT_INIT);
    +    }
    +    unlink(ap_lock_fname);
    +}
    +
    +static void accept_mutex_on(void)
    +{
    +    int ret;
    +
    +    while ((ret = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR) {
    +	/* nop */
    +    }
    +
    +    if (ret < 0) {
    +	ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
    +		    "fcntl: F_SETLKW: Error getting accept lock, exiting!  "
    +		    "Perhaps you need to use the LockFile directive to place "
    +		    "your lock file on a local disk!");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +}
    +
    +static void accept_mutex_off(void)
    +{
    +    int ret;
    +
    +    while ((ret = fcntl(lock_fd, F_SETLKW, &unlock_it)) < 0 && errno == EINTR) {
    +	/* nop */
    +    }
    +    if (ret < 0) {
    +	ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
    +		    "fcntl: F_SETLKW: Error freeing accept lock, exiting!  "
    +		    "Perhaps you need to use the LockFile directive to place "
    +		    "your lock file on a local disk!");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +}
    +
    +#elif defined(USE_FLOCK_SERIALIZED_ACCEPT)
    +
    +static int lock_fd = -1;
    +
    +static void accept_mutex_cleanup(void *foo)
    +{
    +    unlink(ap_lock_fname);
    +}
    +
    +/*
    + * Initialize mutex lock.
    + * Done by each child at it's birth
    + */
    +static void accept_mutex_child_init(pool *p)
    +{
    +
    +    lock_fd = ap_popenf(p, ap_lock_fname, O_WRONLY, 0600);
    +    if (lock_fd == -1) {
    +	ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
    +		    "Child cannot open lock file: %s\n", ap_lock_fname);
    +	clean_child_exit(APEXIT_CHILDINIT);
    +    }
    +}
    +
    +/*
    + * Initialize mutex lock.
    + * Must be safe to call this on a restart.
    + */
    +static void accept_mutex_init(pool *p)
    +{
    +    expand_lock_fname(p);
    +    unlink(ap_lock_fname);
    +    lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600);
    +    if (lock_fd == -1) {
    +	ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
    +		    "Parent cannot open lock file: %s\n", ap_lock_fname);
    +	exit(APEXIT_INIT);
    +    }
    +    ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
    +}
    +
    +static void accept_mutex_on(void)
    +{
    +    int ret;
    +
    +    while ((ret = flock(lock_fd, LOCK_EX)) < 0 && errno == EINTR)
    +	continue;
    +
    +    if (ret < 0) {
    +	ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
    +		    "flock: LOCK_EX: Error getting accept lock. Exiting!");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +}
    +
    +static void accept_mutex_off(void)
    +{
    +    if (flock(lock_fd, LOCK_UN) < 0) {
    +	ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
    +		    "flock: LOCK_UN: Error freeing accept lock. Exiting!");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +}
    +
    +#else
    +/* Default --- no serialization.  Other methods *could* go here,
    + * as #elifs...
    + */
    +#if !defined(MULTITHREAD)
    +/* Multithreaded systems don't complete between processes for
    + * the sockets. */
    +#define NO_SERIALIZED_ACCEPT
    +#define accept_mutex_child_init(x)
    +#define accept_mutex_init(x)
    +#define accept_mutex_on()
    +#define accept_mutex_off()
    +#endif
    +#endif
    +
    +/* On some architectures it's safe to do unserialized accept()s in the single
    + * Listen case.  But it's never safe to do it in the case where there's
    + * multiple Listen statements.  Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    + * when it's safe in the single Listen case.
    + */
    +#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +#define SAFE_ACCEPT(stmt) do {if(ap_listeners->next != ap_listeners) {stmt;}} while(0)
    +#else
    +#define SAFE_ACCEPT(stmt) do {stmt;} while(0)
    +#endif
    +
    +static void usage(char *bin)
    +{
    +    char pad[MAX_STRING_LEN];
    +    unsigned i;
    +
    +    for (i = 0; i < strlen(bin); i++)
    +	pad[i] = ' ';
    +    pad[i] = '\0';
    +#ifdef SHARED_CORE
    +    fprintf(stderr, "Usage: %s [-L directory] [-d directory] [-f file]\n", bin);
    +#else
    +    fprintf(stderr, "Usage: %s [-d directory] [-f file]\n", bin);
    +#endif
    +    fprintf(stderr, "       %s [-C \"directive\"] [-c \"directive\"]\n", pad);
    +    fprintf(stderr, "       %s [-v] [-V] [-h] [-l] [-S]\n", pad);
    +    fprintf(stderr, "Options:\n");
    +#ifdef SHARED_CORE
    +    fprintf(stderr, "  -L directory     : specify an alternate location for shared object files\n");
    +#endif
    +    fprintf(stderr, "  -d directory     : specify an alternate initial ServerRoot\n");
    +    fprintf(stderr, "  -f file          : specify an alternate ServerConfigFile\n");
    +    fprintf(stderr, "  -C \"directive\"   : process directive before reading config files\n");
    +    fprintf(stderr, "  -c \"directive\"   : process directive after  reading config files\n");
    +    fprintf(stderr, "  -v               : show version number\n");
    +    fprintf(stderr, "  -V               : show compile settings\n");
    +    fprintf(stderr, "  -h               : list available configuration directives\n");
    +    fprintf(stderr, "  -l               : list compiled-in modules\n");
    +    fprintf(stderr, "  -S               : show parsed settings (currently only vhost settings)\n");
    +    exit(1);
    +}
    +
    +/*****************************************************************
    + *
    + * Timeout handling.  DISTINCTLY not thread-safe, but all this stuff
    + * has to change for threads anyway.  Note that this code allows only
    + * one timeout in progress at a time...
    + */
    +
    +static APACHE_TLS conn_rec *volatile current_conn;
    +static APACHE_TLS request_rec *volatile timeout_req;
    +static APACHE_TLS const char *volatile timeout_name = NULL;
    +static APACHE_TLS int volatile alarms_blocked = 0;
    +static APACHE_TLS int volatile alarm_pending = 0;
    +
    +static void timeout(int sig)
    +{				/* Also called on SIGPIPE */
    +    void *dirconf;
    +
    +    signal(SIGPIPE, SIG_IGN);	/* Block SIGPIPE */
    +    if (alarms_blocked) {
    +	alarm_pending = 1;
    +	return;
    +    }
    +    if (exit_after_unblock) {
    +	clean_child_exit(0);
    +    }
    +
    +    if (!current_conn) {
    +	ap_longjmp(jmpbuffer, 1);
    +    }
    +
    +    if (timeout_req != NULL)
    +	dirconf = timeout_req->per_dir_config;
    +    else
    +	dirconf = current_conn->server->lookup_defaults;
    +    if (!current_conn->keptalive) {
    +	if (sig == SIGPIPE) {
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
    +			current_conn->server,
    +			"%s client stopped connection before %s completed",
    +			ap_get_remote_host(current_conn, dirconf, REMOTE_NAME),
    +			timeout_name ? timeout_name : "request");
    +	}
    +	else {
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
    +			current_conn->server,
    +			"%s timed out for %s",
    +			timeout_name ? timeout_name : "request",
    +			ap_get_remote_host(current_conn, dirconf, REMOTE_NAME));
    +	}
    +    }
    +
    +    if (timeout_req) {
    +	/* Someone has asked for this transaction to just be aborted
    +	 * if it times out...
    +	 */
    +
    +	request_rec *log_req = timeout_req;
    +
    +	while (log_req->main || log_req->prev) {
    +	    /* Get back to original request... */
    +	    if (log_req->main)
    +		log_req = log_req->main;
    +	    else
    +		log_req = log_req->prev;
    +	}
    +
    +	if (!current_conn->keptalive)
    +	    ap_log_transaction(log_req);
    +
    +	ap_bsetflag(timeout_req->connection->client, B_EOUT, 1);
    +	ap_bclose(timeout_req->connection->client);
    +
    +	if (!ap_standalone)
    +	    exit(0);
    +
    +	ap_longjmp(jmpbuffer, 1);
    +    }
    +    else {			/* abort the connection */
    +	ap_bsetflag(current_conn->client, B_EOUT, 1);
    +	current_conn->aborted = 1;
    +    }
    +}
    +
    +/*
    + * These two called from alloc.c to protect its critical sections...
    + * Note that they can nest (as when destroying the sub_pools of a pool
    + * which is itself being cleared); we have to support that here.
    + */
    +
    +API_EXPORT(void) ap_block_alarms()
    +{
    +    ++alarms_blocked;
    +}
    +
    +API_EXPORT(void) ap_unblock_alarms()
    +{
    +    --alarms_blocked;
    +    if (alarms_blocked == 0) {
    +	if (exit_after_unblock) {
    +	    /* We have a couple race conditions to deal with here, we can't
    +	     * allow a timeout that comes in this small interval to allow
    +	     * the child to jump back to the main loop.  Instead we block
    +	     * alarms again, and then note that exit_after_unblock is
    +	     * being dealt with.  We choose this way to solve this so that
    +	     * the common path through unblock_alarms() is really short.
    +	     */
    +	    ++alarms_blocked;
    +	    exit_after_unblock = 0;
    +	    clean_child_exit(0);
    +	}
    +	if (alarm_pending) {
    +	    alarm_pending = 0;
    +	    timeout(0);
    +	}
    +    }
    +}
    +
    +
    +static APACHE_TLS void (*volatile alarm_fn) (int) = NULL;
    +#ifdef WIN32
    +static APACHE_TLS unsigned int alarm_expiry_time = 0;
    +#endif /* WIN32 */
    +
    +#ifndef WIN32
    +static void alrm_handler(int sig)
    +{
    +    if (alarm_fn) {
    +	(*alarm_fn) (sig);
    +    }
    +}
    +#endif
    +
    +unsigned int ap_set_callback_and_alarm(void (*fn) (int), int x)
    +{
    +    unsigned int old;
    +
    +#ifdef WIN32
    +    old = alarm_expiry_time;
    +    if (old)
    +	old -= time(0);
    +    if (x == 0) {
    +	alarm_fn = NULL;
    +	alarm_expiry_time = 0;
    +    }
    +    else {
    +	alarm_fn = fn;
    +	alarm_expiry_time = time(NULL) + x;
    +    }
    +#else
    +    if (x) {
    +	alarm_fn = fn;
    +    }
    +#ifndef OPTIMIZE_TIMEOUTS
    +    old = alarm(x);
    +#else
    +    if (child_timeouts) {
    +	old = alarm(x);
    +    }
    +    else {
    +	/* Just note the timeout in our scoreboard, no need to call the system.
    +	 * We also note that the virtual time has gone forward.
    +	 */
    +	old = ap_scoreboard_image->servers[my_child_num].timeout_len;
    +	ap_scoreboard_image->servers[my_child_num].timeout_len = x;
    +	++ap_scoreboard_image->servers[my_child_num].cur_vtime;
    +    }
    +#endif
    +#endif
    +    return (old);
    +}
    +
    +
    +#ifdef WIN32
    +API_EXPORT(int) ap_check_alarm(void)
    +{
    +    if (alarm_expiry_time) {
    +	unsigned int t;
    +
    +	t = time(NULL);
    +	if (t >= alarm_expiry_time) {
    +	    alarm_expiry_time = 0;
    +	    (*alarm_fn) (0);
    +	    return (-1);
    +	}
    +	else {
    +	    return (alarm_expiry_time - t);
    +	}
    +    }
    +    else
    +	return (0);
    +}
    +#endif /* WIN32 */
    +
    +
    +
    +/* reset_timeout (request_rec *) resets the timeout in effect,
    + * as long as it hasn't expired already.
    + */
    +
    +API_EXPORT(void) ap_reset_timeout(request_rec *r)
    +{
    +    int i;
    +
    +    if (timeout_name) {		/* timeout has been set */
    +	i = ap_set_callback_and_alarm(alarm_fn, r->server->timeout);
    +	if (i == 0)		/* timeout already expired, so set it back to 0 */
    +	    ap_set_callback_and_alarm(alarm_fn, 0);
    +    }
    +}
    +
    +
    +
    +
    +void ap_keepalive_timeout(char *name, request_rec *r)
    +{
    +    unsigned int to;
    +
    +    timeout_req = r;
    +    timeout_name = name;
    +
    +    if (r->connection->keptalive)
    +	to = r->server->keep_alive_timeout;
    +    else
    +	to = r->server->timeout;
    +    ap_set_callback_and_alarm(timeout, to);
    +
    +}
    +
    +API_EXPORT(void) ap_hard_timeout(char *name, request_rec *r)
    +{
    +    timeout_req = r;
    +    timeout_name = name;
    +
    +    ap_set_callback_and_alarm(timeout, r->server->timeout);
    +
    +}
    +
    +API_EXPORT(void) ap_soft_timeout(char *name, request_rec *r)
    +{
    +    timeout_name = name;
    +
    +    ap_set_callback_and_alarm(timeout, r->server->timeout);
    +
    +}
    +
    +API_EXPORT(void) ap_kill_timeout(request_rec *dummy)
    +{
    +    ap_set_callback_and_alarm(NULL, 0);
    +    timeout_req = NULL;
    +    timeout_name = NULL;
    +}
    +
    +
    +/*
    + * More machine-dependent networking gooo... on some systems,
    + * you've got to be *really* sure that all the packets are acknowledged
    + * before closing the connection, since the client will not be able
    + * to see the last response if their TCP buffer is flushed by a RST
    + * packet from us, which is what the server's TCP stack will send
    + * if it receives any request data after closing the connection.
    + *
    + * In an ideal world, this function would be accomplished by simply
    + * setting the socket option SO_LINGER and handling it within the
    + * server's TCP stack while the process continues on to the next request.
    + * Unfortunately, it seems that most (if not all) operating systems
    + * block the server process on close() when SO_LINGER is used.
    + * For those that don't, see USE_SO_LINGER below.  For the rest,
    + * we have created a home-brew lingering_close.
    + *
    + * Many operating systems tend to block, puke, or otherwise mishandle
    + * calls to shutdown only half of the connection.  You should define
    + * NO_LINGCLOSE in conf.h if such is the case for your system.
    + */
    +#ifndef MAX_SECS_TO_LINGER
    +#define MAX_SECS_TO_LINGER 30
    +#endif
    +
    +#ifdef USE_SO_LINGER
    +#define NO_LINGCLOSE		/* The two lingering options are exclusive */
    +
    +static void sock_enable_linger(int s)
    +{
    +    struct linger li;
    +
    +    li.l_onoff = 1;
    +    li.l_linger = MAX_SECS_TO_LINGER;
    +
    +    if (setsockopt(s, SOL_SOCKET, SO_LINGER,
    +		   (char *) &li, sizeof(struct linger)) < 0) {
    +	ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
    +	            "setsockopt: (SO_LINGER)");
    +	/* not a fatal error */
    +    }
    +}
    +
    +#else
    +#define sock_enable_linger(s)	/* NOOP */
    +#endif /* USE_SO_LINGER */
    +
    +#ifndef NO_LINGCLOSE
    +
    +/* Special version of timeout for lingering_close */
    +
    +static void lingerout(int sig)
    +{
    +    if (alarms_blocked) {
    +	alarm_pending = 1;
    +	return;
    +    }
    +
    +    if (!current_conn) {
    +	ap_longjmp(jmpbuffer, 1);
    +    }
    +    ap_bsetflag(current_conn->client, B_EOUT, 1);
    +    current_conn->aborted = 1;
    +}
    +
    +static void linger_timeout(void)
    +{
    +    timeout_name = "lingering close";
    +
    +    ap_set_callback_and_alarm(lingerout, MAX_SECS_TO_LINGER);
    +}
    +
    +/* Since many clients will abort a connection instead of closing it,
    + * attempting to log an error message from this routine will only
    + * confuse the webmaster.  There doesn't seem to be any portable way to
    + * distinguish between a dropped connection and something that might be
    + * worth logging.
    + */
    +static void lingering_close(request_rec *r)
    +{
    +    char dummybuf[512];
    +    struct timeval tv;
    +    fd_set lfds;
    +    int select_rv;
    +    int lsd;
    +
    +    /* Prevent a slow-drip client from holding us here indefinitely */
    +
    +    linger_timeout();
    +
    +    /* Send any leftover data to the client, but never try to again */
    +
    +    if (ap_bflush(r->connection->client) == -1) {
    +	ap_kill_timeout(r);
    +	ap_bclose(r->connection->client);
    +	return;
    +    }
    +    ap_bsetflag(r->connection->client, B_EOUT, 1);
    +
    +    /* Close our half of the connection --- send the client a FIN */
    +
    +    lsd = r->connection->client->fd;
    +
    +    if ((shutdown(lsd, 1) != 0) || r->connection->aborted) {
    +	ap_kill_timeout(r);
    +	ap_bclose(r->connection->client);
    +	return;
    +    }
    +
    +    /* Set up to wait for readable data on socket... */
    +
    +    FD_ZERO(&lfds);
    +
    +    /* Wait for readable data or error condition on socket;
    +     * slurp up any data that arrives...  We exit when we go for an
    +     * interval of tv length without getting any more data, get an error
    +     * from select(), get an error or EOF on a read, or the timer expires.
    +     */
    +
    +    do {
    +	/* We use a 2 second timeout because current (Feb 97) browsers
    +	 * fail to close a connection after the server closes it.  Thus,
    +	 * to avoid keeping the child busy, we are only lingering long enough
    +	 * for a client that is actively sending data on a connection.
    +	 * This should be sufficient unless the connection is massively
    +	 * losing packets, in which case we might have missed the RST anyway.
    +	 * These parameters are reset on each pass, since they might be
    +	 * changed by select.
    +	 */
    +	FD_SET(lsd, &lfds);
    +	tv.tv_sec = 2;
    +	tv.tv_usec = 0;
    +
    +	select_rv = ap_select(lsd + 1, &lfds, NULL, NULL, &tv);
    +
    +    } while ((select_rv > 0) &&
    +             (read(lsd, dummybuf, sizeof dummybuf) > 0));
    +
    +    /* Should now have seen final ack.  Safe to finally kill socket */
    +
    +    ap_bclose(r->connection->client);
    +
    +    ap_kill_timeout(r);
    +}
    +#endif /* ndef NO_LINGCLOSE */
    +
    +/*****************************************************************
    + * dealing with other children
    + */
    +
    +#ifndef NO_OTHER_CHILD
    +API_EXPORT(void) ap_register_other_child(int pid,
    +		       void (*maintenance) (int reason, void *, int status),
    +			  void *data, int write_fd)
    +{
    +    other_child_rec *ocr;
    +
    +    ocr = ap_palloc(pconf, sizeof(*ocr));
    +    ocr->pid = pid;
    +    ocr->maintenance = maintenance;
    +    ocr->data = data;
    +    ocr->write_fd = write_fd;
    +    ocr->next = other_children;
    +    other_children = ocr;
    +}
    +
    +/* note that since this can be called by a maintenance function while we're
    + * scanning the other_children list, all scanners should protect themself
    + * by loading ocr->next before calling any maintenance function.
    + */
    +API_EXPORT(void) ap_unregister_other_child(void *data)
    +{
    +    other_child_rec **pocr, *nocr;
    +
    +    for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
    +	if ((*pocr)->data == data) {
    +	    nocr = (*pocr)->next;
    +	    (*(*pocr)->maintenance) (OC_REASON_UNREGISTER, (*pocr)->data, -1);
    +	    *pocr = nocr;
    +	    /* XXX: um, well we've just wasted some space in pconf ? */
    +	    return;
    +	}
    +    }
    +}
    +
    +/* test to ensure that the write_fds are all still writable, otherwise
    + * invoke the maintenance functions as appropriate */
    +static void probe_writable_fds(void)
    +{
    +    fd_set writable_fds;
    +    int fd_max;
    +    other_child_rec *ocr, *nocr;
    +    struct timeval tv;
    +    int rc;
    +
    +    if (other_children == NULL)
    +	return;
    +
    +    fd_max = 0;
    +    FD_ZERO(&writable_fds);
    +    do {
    +	for (ocr = other_children; ocr; ocr = ocr->next) {
    +	    if (ocr->write_fd == -1)
    +		continue;
    +	    FD_SET(ocr->write_fd, &writable_fds);
    +	    if (ocr->write_fd > fd_max) {
    +		fd_max = ocr->write_fd;
    +	    }
    +	}
    +	if (fd_max == 0)
    +	    return;
    +
    +	tv.tv_sec = 0;
    +	tv.tv_usec = 0;
    +	rc = ap_select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
    +    } while (rc == -1 && errno == EINTR);
    +
    +    if (rc == -1) {
    +	/* XXX: uhh this could be really bad, we could have a bad file
    +	 * descriptor due to a bug in one of the maintenance routines */
    +	ap_log_unixerr("probe_writable_fds", "select",
    +		    "could not probe writable fds", server_conf);
    +	return;
    +    }
    +    if (rc == 0)
    +	return;
    +
    +    for (ocr = other_children; ocr; ocr = nocr) {
    +	nocr = ocr->next;
    +	if (ocr->write_fd == -1)
    +	    continue;
    +	if (FD_ISSET(ocr->write_fd, &writable_fds))
    +	    continue;
    +	(*ocr->maintenance) (OC_REASON_UNWRITABLE, ocr->data, -1);
    +    }
    +}
    +
    +/* possibly reap an other_child, return 0 if yes, -1 if not */
    +static int reap_other_child(int pid, int status)
    +{
    +    other_child_rec *ocr, *nocr;
    +
    +    for (ocr = other_children; ocr; ocr = nocr) {
    +	nocr = ocr->next;
    +	if (ocr->pid != pid)
    +	    continue;
    +	ocr->pid = -1;
    +	(*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
    +	return 0;
    +    }
    +    return -1;
    +}
    +#endif
    +
    +/*****************************************************************
    + *
    + * Dealing with the scoreboard... a lot of these variables are global
    + * only to avoid getting clobbered by the longjmp() that happens when
    + * a hard timeout expires...
    + *
    + * We begin with routines which deal with the file itself... 
    + */
    +
    +#ifdef MULTITHREAD
    +/*
    + * In the multithreaded mode, have multiple threads - not multiple
    + * processes that need to talk to each other. Just use a simple
    + * malloc. But let the routines that follow, think that you have
    + * shared memory (so they use memcpy etc.)
    + */
    +
    +static void reinit_scoreboard(pool *p)
    +{
    +    ap_assert(!ap_scoreboard_image);
    +    ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
    +    memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
    +}
    +
    +void cleanup_scoreboard()
    +{
    +    ap_assert(ap_scoreboard_image);
    +    free(ap_scoreboard_image);
    +    ap_scoreboard_image = NULL;
    +}
    +
    +API_EXPORT(void) ap_sync_scoreboard_image()
    +{
    +}
    +
    +
    +#else /* MULTITHREAD */
    +#if defined(USE_OS2_SCOREBOARD)
    +
    +/* The next two routines are used to access shared memory under OS/2.  */
    +/* This requires EMX v09c to be installed.                           */
    +
    +caddr_t create_shared_heap(const char *name, size_t size)
    +{
    +    ULONG rc;
    +    void *mem;
    +    Heap_t h;
    +
    +    rc = DosAllocSharedMem(&mem, name, size,
    +			   PAG_COMMIT | PAG_READ | PAG_WRITE);
    +    if (rc != 0)
    +	return NULL;
    +    h = _ucreate(mem, size, !_BLOCK_CLEAN, _HEAP_REGULAR | _HEAP_SHARED,
    +		 NULL, NULL);
    +    if (h == NULL)
    +	DosFreeMem(mem);
    +    return (caddr_t) h;
    +}
    +
    +caddr_t get_shared_heap(const char *Name)
    +{
    +
    +    PVOID BaseAddress;		/* Pointer to the base address of
    +				   the shared memory object */
    +    ULONG AttributeFlags;	/* Flags describing characteristics
    +				   of the shared memory object */
    +    APIRET rc;			/* Return code */
    +
    +    /* Request read and write access to */
    +    /*   the shared memory object       */
    +    AttributeFlags = PAG_WRITE | PAG_READ;
    +
    +    rc = DosGetNamedSharedMem(&BaseAddress, Name, AttributeFlags);
    +
    +    if (rc != 0) {
    +	printf("DosGetNamedSharedMem error: return code = %ld", rc);
    +	return 0;
    +    }
    +
    +    return BaseAddress;
    +}
    +
    +static void setup_shared_mem(pool *p)
    +{
    +    caddr_t m;
    +
    +    char errstr[MAX_STRING_LEN];
    +    int rc;
    +
    +    m = (caddr_t) create_shared_heap("\\SHAREMEM\\SCOREBOARD", SCOREBOARD_SIZE);
    +    if (m == 0) {
    +	fprintf(stderr, "httpd: Could not create OS/2 Shared memory pool.\n");
    +	exit(APEXIT_INIT);
    +    }
    +
    +    rc = _uopen((Heap_t) m);
    +    if (rc != 0) {
    +	fprintf(stderr, "httpd: Could not uopen() newly created OS/2 Shared memory pool.\n");
    +    }
    +    ap_scoreboard_image = (scoreboard *) m;
    +    ap_scoreboard_image->global.exit_generation = 0;
    +}
    +
    +static void reopen_scoreboard(pool *p)
    +{
    +    caddr_t m;
    +    int rc;
    +
    +    m = (caddr_t) get_shared_heap("\\SHAREMEM\\SCOREBOARD");
    +    if (m == 0) {
    +	fprintf(stderr, "httpd: Could not find existing OS/2 Shared memory pool.\n");
    +	exit(APEXIT_INIT);
    +    }
    +
    +    rc = _uopen((Heap_t) m);
    +    ap_scoreboard_image = (scoreboard *) m;
    +}
    +
    +#elif defined(USE_POSIX_SCOREBOARD)
    +/* 
    + * POSIX 1003.4 style
    + *
    + * Note 1: 
    + * As of version 4.23A, shared memory in QNX must reside under /dev/shmem,
    + * where no subdirectories allowed.
    + *
    + * POSIX shm_open() and shm_unlink() will take care about this issue,
    + * but to avoid confusion, I suggest to redefine scoreboard file name
    + * in httpd.conf to cut "logs/" from it. With default setup actual name
    + * will be "/dev/shmem/logs.apache_status". 
    + * 
    + * If something went wrong and Apache did not unlinked this object upon
    + * exit, you can remove it manually, using "rm -f" command.
    + * 
    + * Note 2:
    + * <sys/mman.h> in QNX defines MAP_ANON, but current implementation 
    + * does NOT support BSD style anonymous mapping. So, the order of 
    + * conditional compilation is important: 
    + * this #ifdef section must be ABOVE the next one (BSD style).
    + *
    + * I tested this stuff and it works fine for me, but if it provides 
    + * trouble for you, just comment out USE_MMAP_SCOREBOARD in QNX section
    + * of conf.h
    + *
    + * June 5, 1997, 
    + * Igor N. Kovalenko -- infoh@mail.wplus.net
    + */
    +
    +static void cleanup_shared_mem(void *d)
    +{
    +    shm_unlink(ap_scoreboard_fname);
    +}
    +
    +static void setup_shared_mem(pool *p)
    +{
    +    caddr_t m;
    +    int fd;
    +
    +    fd = shm_open(ap_scoreboard_fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    +    if (fd == -1) {
    +	perror("httpd: could not open(create) scoreboard");
    +	exit(APEXIT_INIT);
    +    }
    +    if (ltrunc(fd, (off_t) SCOREBOARD_SIZE, SEEK_SET) == -1) {
    +	perror("httpd: could not ltrunc scoreboard");
    +	shm_unlink(ap_scoreboard_fname);
    +	exit(APEXIT_INIT);
    +    }
    +    if ((m = (caddr_t) mmap((caddr_t) 0,
    +			    (size_t) SCOREBOARD_SIZE, PROT_READ | PROT_WRITE,
    +			    MAP_SHARED, fd, (off_t) 0)) == (caddr_t) - 1) {
    +	perror("httpd: cannot mmap scoreboard");
    +	shm_unlink(ap_scoreboard_fname);
    +	exit(APEXIT_INIT);
    +    }
    +    close(fd);
    +    ap_register_cleanup(p, NULL, cleanup_shared_mem, ap_null_cleanup);
    +    ap_scoreboard_image = (scoreboard *) m;
    +    ap_scoreboard_image->global.exit_generation = 0;
    +}
    +
    +static void reopen_scoreboard(pool *p)
    +{
    +}
    +
    +#elif defined(USE_MMAP_SCOREBOARD)
    +
    +static void setup_shared_mem(pool *p)
    +{
    +    caddr_t m;
    +
    +#if defined(MAP_ANON) || defined(MAP_FILE)
    +/* BSD style */
    +#ifdef CONVEXOS11
    +    /*
    +     * 9-Aug-97 - Jeff Venters (venters@convex.hp.com)
    +     * ConvexOS maps address space as follows:
    +     *   0x00000000 - 0x7fffffff : Kernel
    +     *   0x80000000 - 0xffffffff : User
    +     * Start mmapped area 1GB above start of text.
    +     *
    +     * Also, the length requires a pointer as the actual length is
    +     * returned (rounded up to a page boundary).
    +     */
    +    {
    +	unsigned len = SCOREBOARD_SIZE;
    +
    +	m = mmap((caddr_t) 0xC0000000, &len,
    +		 PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, NOFD, 0);
    +    }
    +#else
    +    m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
    +	     PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
    +#endif
    +    if (m == (caddr_t) - 1) {
    +	perror("mmap");
    +	fprintf(stderr, "httpd: Could not mmap memory\n");
    +	exit(APEXIT_INIT);
    +    }
    +#else
    +/* Sun style */
    +    int fd;
    +
    +    fd = open("/dev/zero", O_RDWR);
    +    if (fd == -1) {
    +	perror("open");
    +	fprintf(stderr, "httpd: Could not open /dev/zero\n");
    +	exit(APEXIT_INIT);
    +    }
    +    m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
    +	     PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    +    if (m == (caddr_t) - 1) {
    +	perror("mmap");
    +	fprintf(stderr, "httpd: Could not mmap /dev/zero\n");
    +	exit(APEXIT_INIT);
    +    }
    +    close(fd);
    +#endif
    +    ap_scoreboard_image = (scoreboard *) m;
    +    ap_scoreboard_image->global.exit_generation = 0;
    +}
    +
    +static void reopen_scoreboard(pool *p)
    +{
    +}
    +
    +#elif defined(USE_SHMGET_SCOREBOARD)
    +static key_t shmkey = IPC_PRIVATE;
    +static int shmid = -1;
    +
    +static void setup_shared_mem(pool *p)
    +{
    +    struct shmid_ds shmbuf;
    +#ifdef MOVEBREAK
    +    char *obrk;
    +#endif
    +
    +    if ((shmid = shmget(shmkey, SCOREBOARD_SIZE, IPC_CREAT | SHM_R | SHM_W)) == -1) {
    +#ifdef LINUX
    +	if (errno == ENOSYS) {
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
    +		    "httpd: Your kernel was built without CONFIG_SYSVIPC\n"
    +		    "httpd: please consult the Apache FAQ for details\n");
    +	}
    +#endif
    +	ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf,
    +		    "could not call shmget");
    +	exit(APEXIT_INIT);
    +    }
    +
    +    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
    +		"created shared memory segment #%d", shmid);
    +
    +#ifdef MOVEBREAK
    +    /*
    +     * Some SysV systems place the shared segment WAY too close
    +     * to the dynamic memory break point (sbrk(0)). This severely
    +     * limits the use of malloc/sbrk in the program since sbrk will
    +     * refuse to move past that point.
    +     *
    +     * To get around this, we move the break point "way up there",
    +     * attach the segment and then move break back down. Ugly
    +     */
    +    if ((obrk = sbrk(MOVEBREAK)) == (char *) -1) {
    +	ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
    +	    "sbrk() could not move break");
    +    }
    +#endif
    +
    +#define BADSHMAT	((scoreboard *)(-1))
    +    if ((ap_scoreboard_image = (scoreboard *) shmat(shmid, 0, 0)) == BADSHMAT) {
    +	ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "shmat error");
    +	/*
    +	 * We exit below, after we try to remove the segment
    +	 */
    +    }
    +    else {			/* only worry about permissions if we attached the segment */
    +	if (shmctl(shmid, IPC_STAT, &shmbuf) != 0) {
    +	    ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
    +		"shmctl() could not stat segment #%d", shmid);
    +	}
    +	else {
    +	    shmbuf.shm_perm.uid = ap_user_id;
    +	    shmbuf.shm_perm.gid = ap_group_id;
    +	    if (shmctl(shmid, IPC_SET, &shmbuf) != 0) {
    +		ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
    +		    "shmctl() could not set segment #%d", shmid);
    +	    }
    +	}
    +    }
    +    /*
    +     * We must avoid leaving segments in the kernel's
    +     * (small) tables.
    +     */
    +    if (shmctl(shmid, IPC_RMID, NULL) != 0) {
    +	ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
    +		"shmctl: IPC_RMID: could not remove shared memory segment #%d",
    +		shmid);
    +    }
    +    if (ap_scoreboard_image == BADSHMAT)	/* now bailout */
    +	exit(APEXIT_INIT);
    +
    +#ifdef MOVEBREAK
    +    if (obrk == (char *) -1)
    +	return;			/* nothing else to do */
    +    if (sbrk(-(MOVEBREAK)) == (char *) -1) {
    +	ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
    +	    "sbrk() could not move break back");
    +    }
    +#endif
    +    ap_scoreboard_image->global.exit_generation = 0;
    +}
    +
    +static void reopen_scoreboard(pool *p)
    +{
    +}
    +
    +#else
    +#define SCOREBOARD_FILE
    +static scoreboard _scoreboard_image;
    +static int scoreboard_fd = -1;
    +
    +/* XXX: things are seriously screwed if we ever have to do a partial
    + * read or write ... we could get a corrupted scoreboard
    + */
    +static int force_write(int fd, void *buffer, int bufsz)
    +{
    +    int rv, orig_sz = bufsz;
    +
    +    do {
    +	rv = write(fd, buffer, bufsz);
    +	if (rv > 0) {
    +	    buffer = (char *) buffer + rv;
    +	    bufsz -= rv;
    +	}
    +    } while ((rv > 0 && bufsz > 0) || (rv == -1 && errno == EINTR));
    +
    +    return rv < 0 ? rv : orig_sz - bufsz;
    +}
    +
    +static int force_read(int fd, void *buffer, int bufsz)
    +{
    +    int rv, orig_sz = bufsz;
    +
    +    do {
    +	rv = read(fd, buffer, bufsz);
    +	if (rv > 0) {
    +	    buffer = (char *) buffer + rv;
    +	    bufsz -= rv;
    +	}
    +    } while ((rv > 0 && bufsz > 0) || (rv == -1 && errno == EINTR));
    +
    +    return rv < 0 ? rv : orig_sz - bufsz;
    +}
    +
    +static void cleanup_scoreboard_file(void *foo)
    +{
    +    unlink(ap_scoreboard_fname);
    +}
    +
    +void reopen_scoreboard(pool *p)
    +{
    +    if (scoreboard_fd != -1)
    +	ap_pclosef(p, scoreboard_fd);
    +
    +    scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0666);
    +    if (scoreboard_fd == -1) {
    +	perror(ap_scoreboard_fname);
    +	fprintf(stderr, "Cannot open scoreboard file:\n");
    +	clean_child_exit(1);
    +    }
    +}
    +#endif
    +
    +/* Called by parent process */
    +static void reinit_scoreboard(pool *p)
    +{
    +    int exit_gen = 0;
    +    if (ap_scoreboard_image)
    +	exit_gen = ap_scoreboard_image->global.exit_generation;
    +
    +#ifndef SCOREBOARD_FILE
    +    if (ap_scoreboard_image == NULL) {
    +	setup_shared_mem(p);
    +    }
    +    memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
    +    ap_scoreboard_image->global.exit_generation = exit_gen;
    +#else
    +    ap_scoreboard_image = &_scoreboard_image;
    +    ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
    +
    +    scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0644);
    +    if (scoreboard_fd == -1) {
    +	perror(ap_scoreboard_fname);
    +	fprintf(stderr, "Cannot open scoreboard file:\n");
    +	exit(APEXIT_INIT);
    +    }
    +    ap_register_cleanup(p, NULL, cleanup_scoreboard_file, ap_null_cleanup);
    +
    +    memset((char *) ap_scoreboard_image, 0, sizeof(*ap_scoreboard_image));
    +    ap_scoreboard_image->global.exit_generation = exit_gen;
    +    force_write(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
    +#endif
    +}
    +
    +/* Routines called to deal with the scoreboard image
    + * --- note that we do *not* need write locks, since update_child_status
    + * only updates a *single* record in place, and only one process writes to
    + * a given scoreboard slot at a time (either the child process owning that
    + * slot, or the parent, noting that the child has died).
    + *
    + * As a final note --- setting the score entry to getpid() is always safe,
    + * since when the parent is writing an entry, it's only noting SERVER_DEAD
    + * anyway.
    + */
    +
    +ap_inline void ap_sync_scoreboard_image(void)
    +{
    +#ifdef SCOREBOARD_FILE
    +    lseek(scoreboard_fd, 0L, 0);
    +    force_read(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
    +#endif
    +}
    +
    +#endif /* MULTITHREAD */
    +
    +API_EXPORT(int) ap_exists_scoreboard_image(void)
    +{
    +    return (ap_scoreboard_image ? 1 : 0);
    +}
    +
    +static ap_inline void put_scoreboard_info(int child_num,
    +				       short_score *new_score_rec)
    +{
    +#ifdef SCOREBOARD_FILE
    +    lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
    +    force_write(scoreboard_fd, new_score_rec, sizeof(short_score));
    +#endif
    +}
    +
    +/* a clean exit from the parent with proper cleanup */
    +static void __attribute__((noreturn)) clean_parent_exit(int code)
    +{
    +    /* Clear the pool - including any registered cleanups */
    +    ap_destroy_pool(pconf);
    +    exit(code);
    +}
    +
    +int ap_update_child_status(int child_num, int status, request_rec *r)
    +{
    +    int old_status;
    +    short_score *ss;
    +
    +    if (child_num < 0)
    +	return -1;
    +
    +    ap_sync_scoreboard_image();
    +    ss = &ap_scoreboard_image->servers[child_num];
    +    old_status = ss->status;
    +    ss->status = status;
    +#ifdef OPTIMIZE_TIMEOUTS
    +    ++ss->cur_vtime;
    +#endif
    +
    +#if defined(STATUS)
    +#ifndef OPTIMIZE_TIMEOUTS
    +    ss->last_used = time(NULL);
    +#endif
    +    if (status == SERVER_READY || status == SERVER_DEAD) {
    +	/*
    +	 * Reset individual counters
    +	 */
    +	if (status == SERVER_DEAD) {
    +	    ss->my_access_count = 0L;
    +	    ss->my_bytes_served = 0L;
    +	}
    +	ss->conn_count = (unsigned short) 0;
    +	ss->conn_bytes = (unsigned long) 0;
    +    }
    +    if (r) {
    +	conn_rec *c = r->connection;
    +	ap_cpystrn(ss->client, ap_get_remote_host(c, r->per_dir_config,
    +			      REMOTE_NOLOOKUP), sizeof(ss->client));
    +    if (r->the_request == NULL) {
    +		ap_cpystrn(ss->request, "NULL", sizeof(ss->request));
    +	} else if (r->parsed_uri.password == NULL) {
    +		ap_cpystrn(ss->request, r->the_request, sizeof(ss->request));
    +	} else {
    +	    /* Don't reveal the password in the server-status view */
    +		ap_cpystrn(ss->request, ap_pstrcat(r->pool, r->method, " ",
    +					   ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD),
    +					   r->assbackwards ? NULL : " ", r->protocol, NULL),
    +				   sizeof(ss->request));
    +	}
    +	ap_cpystrn(ss->vhost, r->server->server_hostname, sizeof(ss->vhost));
    +    }
    +#endif
    +
    +    put_scoreboard_info(child_num, ss);
    +
    +    return old_status;
    +}
    +
    +static void update_scoreboard_global(void)
    +{
    +#ifdef SCOREBOARD_FILE
    +    lseek(scoreboard_fd,
    +	  (char *) &ap_scoreboard_image->global -(char *) ap_scoreboard_image, 0);
    +    force_write(scoreboard_fd, &ap_scoreboard_image->global,
    +		sizeof ap_scoreboard_image->global);
    +#endif
    +}
    +
    +#if defined(STATUS)
    +void ap_time_process_request(int child_num, int status)
    +{
    +    short_score *ss;
    +#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES)
    +    struct tms tms_blk;
    +#endif
    +
    +    if (child_num < 0)
    +	return;
    +
    +    ap_sync_scoreboard_image();
    +    ss = &ap_scoreboard_image->servers[child_num];
    +
    +    if (status == START_PREQUEST) {
    +#if defined(NO_GETTIMEOFDAY)
    +#ifndef NO_TIMES
    +	if ((ss->start_time = times(&tms_blk)) == -1)
    +#endif /* NO_TIMES */
    +	    ss->start_time = (clock_t) 0;
    +#else
    +	if (gettimeofday(&ss->start_time, (struct timezone *) 0) < 0)
    +	    ss->start_time.tv_sec =
    +		ss->start_time.tv_usec = 0L;
    +#endif
    +    }
    +    else if (status == STOP_PREQUEST) {
    +#if defined(NO_GETTIMEOFDAY)
    +#ifndef NO_TIMES
    +	if ((ss->stop_time = times(&tms_blk)) == -1)
    +#endif
    +	    ss->stop_time = ss->start_time = (clock_t) 0;
    +#else
    +	if (gettimeofday(&ss->stop_time, (struct timezone *) 0) < 0)
    +	    ss->stop_time.tv_sec =
    +		ss->stop_time.tv_usec =
    +		ss->start_time.tv_sec =
    +		ss->start_time.tv_usec = 0L;
    +#endif
    +
    +    }
    +
    +    put_scoreboard_info(child_num, ss);
    +}
    +
    +static void increment_counts(int child_num, request_rec *r)
    +{
    +    long int bs = 0;
    +    short_score *ss;
    +
    +    ap_sync_scoreboard_image();
    +    ss = &ap_scoreboard_image->servers[child_num];
    +
    +    if (r->sent_bodyct)
    +	ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
    +
    +#ifndef NO_TIMES
    +    times(&ss->times);
    +#endif
    +    ss->access_count++;
    +    ss->my_access_count++;
    +    ss->conn_count++;
    +    ss->bytes_served += (unsigned long) bs;
    +    ss->my_bytes_served += (unsigned long) bs;
    +    ss->conn_bytes += (unsigned long) bs;
    +
    +    put_scoreboard_info(child_num, ss);
    +}
    +
    +#endif
    +
    +
    +static int find_child_by_pid(int pid)
    +{
    +    int i;
    +
    +    for (i = 0; i < max_daemons_limit; ++i)
    +	if (ap_scoreboard_image->parent[i].pid == pid)
    +	    return i;
    +
    +    return -1;
    +}
    +
    +static void reclaim_child_processes(int terminate)
    +{
    +#ifndef MULTITHREAD
    +    int i, status;
    +    long int waittime = 1024 * 16;	/* in usecs */
    +    struct timeval tv;
    +    int waitret, tries;
    +    int not_dead_yet;
    +#ifndef NO_OTHER_CHILD
    +    other_child_rec *ocr, *nocr;
    +#endif
    +
    +    ap_sync_scoreboard_image();
    +
    +    for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
    +	/* don't want to hold up progress any more than 
    +	 * necessary, but we need to allow children a few moments to exit.
    +	 * Set delay with an exponential backoff.
    +	 */
    +	tv.tv_sec = waittime / 1000000;
    +	tv.tv_usec = waittime % 1000000;
    +	waittime = waittime * 4;
    +	ap_select(0, NULL, NULL, NULL, &tv);
    +
    +	/* now see who is done */
    +	not_dead_yet = 0;
    +	for (i = 0; i < max_daemons_limit; ++i) {
    +	    int pid = ap_scoreboard_image->parent[i].pid;
    +
    +	    if (pid == my_pid || pid == 0)
    +		continue;
    +
    +	    waitret = waitpid(pid, &status, WNOHANG);
    +	    if (waitret == pid || waitret == -1) {
    +		ap_scoreboard_image->parent[i].pid = 0;
    +		continue;
    +	    }
    +	    ++not_dead_yet;
    +	    switch (tries) {
    +	    case 1:     /*  16ms */
    +	    case 2:     /*  82ms */
    +		break;
    +	    case 3:     /* 344ms */
    +		/* perhaps it missed the SIGHUP, lets try again */
    +		ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
    +			    server_conf,
    +		    "child process %d did not exit, sending another SIGHUP",
    +			    pid);
    +		kill(pid, SIGHUP);
    +		waittime = 1024 * 16;
    +		break;
    +	    case 4:     /*  16ms */
    +	    case 5:     /*  82ms */
    +	    case 6:     /* 344ms */
    +		break;
    +	    case 7:     /* 1.4sec */
    +		/* ok, now it's being annoying */
    +		ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
    +			    server_conf,
    +		   "child process %d still did not exit, sending a SIGTERM",
    +			    pid);
    +		kill(pid, SIGTERM);
    +		break;
    +	    case 8:     /*  6 sec */
    +		/* die child scum */
    +		ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
    +		   "child process %d still did not exit, sending a SIGKILL",
    +			    pid);
    +		kill(pid, SIGKILL);
    +		break;
    +	    case 9:     /* 14 sec */
    +		/* gave it our best shot, but alas...  If this really 
    +		 * is a child we are trying to kill and it really hasn't
    +		 * exited, we will likely fail to bind to the port
    +		 * after the restart.
    +		 */
    +		ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
    +			    "could not make child process %d exit, "
    +			    "attempting to continue anyway", pid);
    +		break;
    +	    }
    +	}
    +#ifndef NO_OTHER_CHILD
    +	for (ocr = other_children; ocr; ocr = nocr) {
    +	    nocr = ocr->next;
    +	    if (ocr->pid == -1)
    +		continue;
    +
    +	    waitret = waitpid(ocr->pid, &status, WNOHANG);
    +	    if (waitret == ocr->pid) {
    +		ocr->pid = -1;
    +		(*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
    +	    }
    +	    else if (waitret == 0) {
    +		(*ocr->maintenance) (OC_REASON_RESTART, ocr->data, -1);
    +		++not_dead_yet;
    +	    }
    +	    else if (waitret == -1) {
    +		/* uh what the heck? they didn't call unregister? */
    +		ocr->pid = -1;
    +		(*ocr->maintenance) (OC_REASON_LOST, ocr->data, -1);
    +	    }
    +	}
    +#endif
    +	if (!not_dead_yet) {
    +	    /* nothing left to wait for */
    +	    break;
    +	}
    +    }
    +#endif /* ndef MULTITHREAD */
    +}
    +
    +
    +#if defined(BROKEN_WAIT) || defined(NEED_WAITPID)
    +/*
    +   Some systems appear to fail to deliver dead children to wait() at times.
    +   This sorts them out. In fact, this may have been caused by a race condition
    +   in wait_or_timeout(). But this routine is still useful for systems with no
    +   waitpid().
    + */
    +int reap_children(void)
    +{
    +    int status, n;
    +    int ret = 0;
    +
    +    for (n = 0; n < max_daemons_limit; ++n) {
    +	if (ap_scoreboard_image->servers[n].status != SERVER_DEAD
    +	    && waitpid(ap_scoreboard_image->parent[n].pid, &status, WNOHANG)
    +	    == -1
    +	    && errno == ECHILD) {
    +	    ap_sync_scoreboard_image();
    +	    ap_update_child_status(n, SERVER_DEAD, NULL);
    +	    ret = 1;
    +	}
    +    }
    +    return ret;
    +}
    +#endif
    +
    +/* Finally, this routine is used by the caretaker process to wait for
    + * a while...
    + */
    +
    +/* number of calls to wait_or_timeout between writable probes */
    +#ifndef INTERVAL_OF_WRITABLE_PROBES
    +#define INTERVAL_OF_WRITABLE_PROBES 10
    +#endif
    +static int wait_or_timeout_counter;
    +
    +static int wait_or_timeout(int *status)
    +{
    +#ifdef WIN32
    +#define MAXWAITOBJ MAXIMUM_WAIT_OBJECTS
    +    HANDLE h[MAXWAITOBJ];
    +    int e[MAXWAITOBJ];
    +    int round, pi, hi, rv, err;
    +    for (round = 0; round <= (HARD_SERVER_LIMIT - 1) / MAXWAITOBJ + 1; round++) {
    +	hi = 0;
    +	for (pi = round * MAXWAITOBJ;
    +	     (pi < (round + 1) * MAXWAITOBJ) && (pi < HARD_SERVER_LIMIT);
    +	     pi++) {
    +	    if (ap_scoreboard_image->servers[pi].status != SERVER_DEAD) {
    +		e[hi] = pi;
    +		h[hi++] = (HANDLE) ap_scoreboard_image->parent[pi].pid;
    +	    }
    +
    +	}
    +	if (hi > 0) {
    +	    rv = WaitForMultipleObjects(hi, h, FALSE, 10000);
    +	    if (rv == -1)
    +		err = GetLastError();
    +	    if ((WAIT_OBJECT_0 <= (unsigned int) rv) && ((unsigned int) rv < (WAIT_OBJECT_0 + hi)))
    +		return (ap_scoreboard_image->parent[e[rv - WAIT_OBJECT_0]].pid);
    +	    else if ((WAIT_ABANDONED_0 <= (unsigned int) rv) && ((unsigned int) rv < (WAIT_ABANDONED_0 + hi)))
    +		return (ap_scoreboard_image->parent[e[rv - WAIT_ABANDONED_0]].pid);
    +
    +	}
    +    }
    +    return (-1);
    +
    +#else /* WIN32 */
    +    struct timeval tv;
    +    int ret;
    +
    +    ++wait_or_timeout_counter;
    +    if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
    +	wait_or_timeout_counter = 0;
    +#ifndef NO_OTHER_CHILD
    +	probe_writable_fds();
    +#endif
    +    }
    +    ret = waitpid(-1, status, WNOHANG);
    +    if (ret == -1 && errno == EINTR) {
    +	return -1;
    +    }
    +    if (ret > 0) {
    +	return ret;
    +    }
    +    tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000;
    +    tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
    +    ap_select(0, NULL, NULL, NULL, &tv);
    +    return -1;
    +#endif /* WIN32 */
    +}
    +
    +
    +#if defined(NSIG)
    +#define NumSIG NSIG
    +#elif defined(_NSIG)
    +#define NumSIG _NSIG
    +#elif defined(__NSIG)
    +#define NumSIG __NSIG
    +#else
    +#define NumSIG 32   /* for 1998's unixes, this is still a good assumption */
    +#endif
    +
    +#ifdef SYS_SIGLIST /* platform has sys_siglist[] */
    +#define INIT_SIGLIST()  /*nothing*/
    +#else /* platform has no sys_siglist[], define our own */
    +#define SYS_SIGLIST ap_sys_siglist
    +#define INIT_SIGLIST() siglist_init();
    +
    +const char *ap_sys_siglist[NumSIG];
    +
    +static void siglist_init(void)
    +{
    +    int sig;
    +
    +    ap_sys_siglist[0] = "Signal 0";
    +#ifdef SIGHUP
    +    ap_sys_siglist[SIGHUP] = "Hangup";
    +#endif
    +#ifdef SIGINT
    +    ap_sys_siglist[SIGINT] = "Interrupt";
    +#endif
    +#ifdef SIGQUIT
    +    ap_sys_siglist[SIGQUIT] = "Quit";
    +#endif
    +#ifdef SIGILL
    +    ap_sys_siglist[SIGILL] = "Illegal instruction";
    +#endif
    +#ifdef SIGTRAP
    +    ap_sys_siglist[SIGTRAP] = "Trace/BPT trap";
    +#endif
    +#ifdef SIGIOT
    +    ap_sys_siglist[SIGIOT] = "IOT instruction";
    +#endif
    +#ifdef SIGABRT
    +    ap_sys_siglist[SIGABRT] = "Abort";
    +#endif
    +#ifdef SIGEMT
    +    ap_sys_siglist[SIGEMT] = "Emulator trap";
    +#endif
    +#ifdef SIGFPE
    +    ap_sys_siglist[SIGFPE] = "Arithmetic exception";
    +#endif
    +#ifdef SIGKILL
    +    ap_sys_siglist[SIGKILL] = "Killed";
    +#endif
    +#ifdef SIGBUS
    +    ap_sys_siglist[SIGBUS] = "Bus error";
    +#endif
    +#ifdef SIGSEGV
    +    ap_sys_siglist[SIGSEGV] = "Segmentation fault";
    +#endif
    +#ifdef SIGSYS
    +    ap_sys_siglist[SIGSYS] = "Bad system call";
    +#endif
    +#ifdef SIGPIPE
    +    ap_sys_siglist[SIGPIPE] = "Broken pipe";
    +#endif
    +#ifdef SIGALRM
    +    ap_sys_siglist[SIGALRM] = "Alarm clock";
    +#endif
    +#ifdef SIGTERM
    +    ap_sys_siglist[SIGTERM] = "Terminated";
    +#endif
    +#ifdef SIGUSR1
    +    ap_sys_siglist[SIGUSR1] = "User defined signal 1";
    +#endif
    +#ifdef SIGUSR2
    +    ap_sys_siglist[SIGUSR2] = "User defined signal 2";
    +#endif
    +#ifdef SIGCLD
    +    ap_sys_siglist[SIGCLD] = "Child status change";
    +#endif
    +#ifdef SIGCHLD
    +    ap_sys_siglist[SIGCHLD] = "Child status change";
    +#endif
    +#ifdef SIGPWR
    +    ap_sys_siglist[SIGPWR] = "Power-fail restart";
    +#endif
    +#ifdef SIGWINCH
    +    ap_sys_siglist[SIGWINCH] = "Window changed";
    +#endif
    +#ifdef SIGURG
    +    ap_sys_siglist[SIGURG] = "urgent socket condition";
    +#endif
    +#ifdef SIGPOLL
    +    ap_sys_siglist[SIGPOLL] = "Pollable event occurred";
    +#endif
    +#ifdef SIGIO
    +    ap_sys_siglist[SIGIO] = "socket I/O possible";
    +#endif
    +#ifdef SIGSTOP
    +    ap_sys_siglist[SIGSTOP] = "Stopped (signal)";
    +#endif
    +#ifdef SIGTSTP
    +    ap_sys_siglist[SIGTSTP] = "Stopped";
    +#endif
    +#ifdef SIGCONT
    +    ap_sys_siglist[SIGCONT] = "Continued";
    +#endif
    +#ifdef SIGTTIN
    +    ap_sys_siglist[SIGTTIN] = "Stopped (tty input)";
    +#endif
    +#ifdef SIGTTOU
    +    ap_sys_siglist[SIGTTOU] = "Stopped (tty output)";
    +#endif
    +#ifdef SIGVTALRM
    +    ap_sys_siglist[SIGVTALRM] = "virtual timer expired";
    +#endif
    +#ifdef SIGPROF
    +    ap_sys_siglist[SIGPROF] = "profiling timer expired";
    +#endif
    +#ifdef SIGXCPU
    +    ap_sys_siglist[SIGXCPU] = "exceeded cpu limit";
    +#endif
    +#ifdef SIGXFSZ
    +    ap_sys_siglist[SIGXFSZ] = "exceeded file size limit";
    +#endif
    +    for (sig=0; sig < sizeof(ap_sys_siglist)/sizeof(ap_sys_siglist[0]); ++sig)
    +        if (ap_sys_siglist[sig] == NULL)
    +            ap_sys_siglist[sig] = "";
    +}
    +#endif /* platform has sys_siglist[] */
    +
    +
    +/* handle all varieties of core dumping signals */
    +static void sig_coredump(int sig)
    +{
    +    chdir(ap_coredump_dir);
    +    signal(sig, SIG_DFL);
    +#ifndef WIN32
    +    kill(getpid(), sig);
    +#else
    +    raise(sig);
    +#endif
    +    /* At this point we've got sig blocked, because we're still inside
    +     * the signal handler.  When we leave the signal handler it will
    +     * be unblocked, and we'll take the signal... and coredump or whatever
    +     * is appropriate for this particular Unix.  In addition the parent
    +     * will see the real signal we received -- whereas if we called
    +     * abort() here, the parent would only see SIGABRT.
    +     */
    +}
    +
    +/*****************************************************************
    + * Connection structures and accounting...
    + */
    +
    +static void just_die(int sig)
    +{				/* SIGHUP to child process??? */
    +    /* if alarms are blocked we have to wait to die otherwise we might
    +     * end up with corruption in alloc.c's internal structures */
    +    if (alarms_blocked) {
    +	exit_after_unblock = 1;
    +    }
    +    else {
    +	clean_child_exit(0);
    +    }
    +}
    +
    +static int volatile usr1_just_die = 1;
    +static int volatile deferred_die;
    +
    +static void usr1_handler(int sig)
    +{
    +    if (usr1_just_die) {
    +	just_die(sig);
    +    }
    +    deferred_die = 1;
    +}
    +
    +/* volatile just in case */
    +static int volatile shutdown_pending;
    +static int volatile restart_pending;
    +static int volatile is_graceful;
    +static int volatile generation;
    +
    +#ifdef WIN32
    +/*
    + * signal_parent() tells the parent process to wake up and do something.
    + * Once woken it will look at shutdown_pending and restart_pending to decide
    + * what to do. If neither variable is set, it will do a shutdown. This function
    + * if called by start_shutdown() or start_restart() in the parent's process
    + * space, so that the variables get set. However it can also be called 
    + * by child processes to force the parent to exit in an emergency.
    + */
    +
    +static void signal_parent(void)
    +{
    +    HANDLE e;
    +    /* after updating the shutdown_pending or restart flags, we need
    +     * to wake up the parent process so it can see the changes. The
    +     * parent will normally be waiting for either a child process
    +     * to die, or for a signal on the "spache-signal" event. So set the
    +     * "apache-signal" event here.
    +     */
    +
    +    if (one_process) {
    +	return;
    +    }
    +
    +    APD1("*** SIGNAL_PARENT SET ***");
    +
    +    e = OpenEvent(EVENT_ALL_ACCESS, FALSE, "apache-signal");
    +    if (!e) {
    +	/* Um, problem, can't signal the main loop, which means we can't
    +	 * signal ourselves to die. Ignore for now...
    +	 */
    +	ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
    +	    "OpenEvent on apache-signal event");
    +	return;
    +    }
    +    if (SetEvent(e) == 0) {
    +	/* Same problem as above */
    +	ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
    +	    "SetEvent on apache-signal event");
    +	return;
    +    }
    +    CloseHandle(e);
    +}
    +#endif
    +
    +/*
    + * start_shutdown() and start_restart(), below, are a first stab at
    + * functions to initiate shutdown or restart without relying on signals. 
    + * Previously this was initiated in sig_term() and restart() signal handlers, 
    + * but we want to be able to start a shutdown/restart from other sources --
    + * e.g. on Win32, from the service manager. Now the service manager can
    + * call start_shutdown() or start_restart() as appropiate. 
    + *
    + * These should only be called from the parent process itself, since the
    + * parent process will use the shutdown_pending and restart_pending variables
    + * to determine whether to shutdown or restart. The child process should
    + * call signal_parent() directly to tell the parent to die -- this will
    + * cause neither of those variable to be set, which the parent will
    + * assume means something serious is wrong (which it will be, for the
    + * child to force an exit) and so do an exit anyway.
    + */
    +
    +void ap_start_shutdown(void)
    +{
    +    if (shutdown_pending == 1) {
    +	/* Um, is this _probably_ not an error, if the user has
    +	 * tried to do a shutdown twice quickly, so we won't
    +	 * worry about reporting it.
    +	 */
    +	return;
    +    }
    +    shutdown_pending = 1;
    +
    +#ifdef WIN32
    +    signal_parent();	    /* get the parent process to wake up */
    +#endif
    +}
    +
    +/* do a graceful restart if graceful == 1 */
    +void ap_start_restart(int graceful)
    +{
    +    if (restart_pending == 1) {
    +	/* Probably not an error - don't bother reporting it */
    +	return;
    +    }
    +    restart_pending = 1;
    +    is_graceful = graceful;
    +
    +#ifdef WIN32
    +    signal_parent();	    /* get the parent process to wake up */
    +#endif /* WIN32 */
    +}
    +
    +static void sig_term(int sig)
    +{
    +    ap_start_shutdown();
    +}
    +
    +static void restart(int sig)
    +{
    +#ifndef WIN32
    +    ap_start_restart(sig == SIGUSR1);
    +#else
    +    ap_start_restart(1);
    +#endif
    +}
    +
    +static void set_signals(void)
    +{
    +#ifndef NO_USE_SIGACTION
    +    struct sigaction sa;
    +
    +    sigemptyset(&sa.sa_mask);
    +    sa.sa_flags = 0;
    +
    +    if (!one_process) {
    +	sa.sa_handler = sig_coredump;
    +#if defined(SA_ONESHOT)
    +	sa.sa_flags = SA_ONESHOT;
    +#elif defined(SA_RESETHAND)
    +	sa.sa_flags = SA_RESETHAND;
    +#endif
    +	if (sigaction(SIGSEGV, &sa, NULL) < 0)
    +	    ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGSEGV)");
    +#ifdef SIGBUS
    +	if (sigaction(SIGBUS, &sa, NULL) < 0)
    +	    ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGBUS)");
    +#endif
    +#ifdef SIGABORT
    +	if (sigaction(SIGABORT, &sa, NULL) < 0)
    +	    ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGABORT)");
    +#endif
    +#ifdef SIGABRT
    +	if (sigaction(SIGABRT, &sa, NULL) < 0)
    +	    ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGABRT)");
    +#endif
    +	sa.sa_flags = 0;
    +    }
    +    sa.sa_handler = sig_term;
    +    if (sigaction(SIGTERM, &sa, NULL) < 0)
    +	ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGTERM)");
    +#ifdef SIGINT
    +    if (sigaction(SIGINT, &sa, NULL) < 0)
    +        ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGINT)");
    +#endif
    +#ifdef SIGXCPU
    +    sa.sa_handler = SIG_DFL;
    +    if (sigaction(SIGXCPU, &sa, NULL) < 0)
    +	ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGXCPU)");
    +#endif
    +#ifdef SIGXFSZ
    +    sa.sa_handler = SIG_DFL;
    +    if (sigaction(SIGXFSZ, &sa, NULL) < 0)
    +	ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGXFSZ)");
    +#endif
    +
    +    /* we want to ignore HUPs and USR1 while we're busy processing one */
    +    sigaddset(&sa.sa_mask, SIGHUP);
    +    sigaddset(&sa.sa_mask, SIGUSR1);
    +    sa.sa_handler = restart;
    +    if (sigaction(SIGHUP, &sa, NULL) < 0)
    +	ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGHUP)");
    +    if (sigaction(SIGUSR1, &sa, NULL) < 0)
    +	ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "sigaction(SIGUSR1)");
    +#else
    +    if (!one_process) {
    +	signal(SIGSEGV, sig_coredump);
    +#ifdef SIGBUS
    +	signal(SIGBUS, sig_coredump);
    +#endif /* SIGBUS */
    +#ifdef SIGABORT
    +	signal(SIGABORT, sig_coredump);
    +#endif /* SIGABORT */
    +#ifdef SIGABRT
    +	signal(SIGABRT, sig_coredump);
    +#endif /* SIGABRT */
    +#ifdef SIGXCPU
    +	signal(SIGXCPU, SIG_DFL);
    +#endif /* SIGXCPU */
    +#ifdef SIGXFSZ
    +	signal(SIGXFSZ, SIG_DFL);
    +#endif /* SIGXFSZ */
    +    }
    +
    +    signal(SIGTERM, sig_term);
    +#ifdef SIGHUP
    +    signal(SIGHUP, restart);
    +#endif /* SIGHUP */
    +#ifdef SIGUSR1
    +    signal(SIGUSR1, restart);
    +#endif /* SIGUSR1 */
    +#endif
    +}
    +
    +
    +/*****************************************************************
    + * Here follows a long bunch of generic server bookkeeping stuff...
    + */
    +
    +static void detach(void)
    +{
    +#if !defined(WIN32)
    +    int x;
    +
    +    chdir("/");
    +#if !defined(MPE) && !defined(__EMX__)
    +/* Don't detach for MPE because child processes can't survive the death of
    +   the parent. */
    +    if ((x = fork()) > 0)
    +	exit(0);
    +    else if (x == -1) {
    +	perror("fork");
    +	fprintf(stderr, "httpd: unable to fork new process\n");
    +	exit(1);
    +    }
    +    RAISE_SIGSTOP(DETACH);
    +#endif
    +#ifndef NO_SETSID
    +    if ((pgrp = setsid()) == -1) {
    +	perror("setsid");
    +	fprintf(stderr, "httpd: setsid failed\n");
    +	exit(1);
    +    }
    +#elif defined(NEXT) || defined(NEWSOS)
    +    if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) {
    +	perror("setpgrp");
    +	fprintf(stderr, "httpd: setpgrp or getpgrp failed\n");
    +	exit(1);
    +    }
    +#elif defined(__EMX__)
    +    /* OS/2 don't support process group IDs */
    +    pgrp = getpid();
    +#elif defined(MPE)
    +    /* MPE uses negative pid for process group */
    +    pgrp = -getpid();
    +#else
    +    if ((pgrp = setpgrp(getpid(), 0)) == -1) {
    +	perror("setpgrp");
    +	fprintf(stderr, "httpd: setpgrp failed\n");
    +	exit(1);
    +    }
    +#endif
    +
    +    /* close out the standard file descriptors */
    +    if (freopen("/dev/null", "r", stdin) == NULL) {
    +	fprintf(stderr, "httpd: unable to replace stdin with /dev/null: %s\n",
    +		strerror(errno));
    +	/* continue anyhow -- note we can't close out descriptor 0 because we
    +	 * have nothing to replace it with, and if we didn't have a descriptor
    +	 * 0 the next file would be created with that value ... leading to
    +	 * havoc.
    +	 */
    +    }
    +    if (freopen("/dev/null", "w", stdout) == NULL) {
    +	fprintf(stderr, "httpd: unable to replace stdout with /dev/null: %s\n",
    +		strerror(errno));
    +    }
    +    /* stderr is a tricky one, we really want it to be the error_log,
    +     * but we haven't opened that yet.  So leave it alone for now and it'll
    +     * be reopened moments later.
    +     */
    +#endif /* ndef WIN32 */
    +}
    +
    +/* Set group privileges.
    + *
    + * Note that we use the username as set in the config files, rather than
    + * the lookup of to uid --- the same uid may have multiple passwd entries,
    + * with different sets of groups for each.
    + */
    +
    +static void set_group_privs(void)
    +{
    +#ifndef WIN32
    +    if (!geteuid()) {
    +	char *name;
    +
    +	/* Get username if passed as a uid */
    +
    +	if (ap_user_name[0] == '#') {
    +	    struct passwd *ent;
    +	    uid_t uid = atoi(&ap_user_name[1]);
    +
    +	    if ((ent = getpwuid(uid)) == NULL) {
    +		ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
    +			 "getpwuid: couldn't determine user name from uid %u, "
    +			 "you probably need to modify the User directive",
    +			 (unsigned)uid);
    +		clean_child_exit(APEXIT_CHILDFATAL);
    +	    }
    +
    +	    name = ent->pw_name;
    +	}
    +	else
    +	    name = ap_user_name;
    +
    +#ifndef __EMX__
    +	/* OS/2 dosen't support groups. */
    +
    +	/* Reset `groups' attributes. */
    +
    +	if (initgroups(name, ap_group_id) == -1) {
    +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
    +			"initgroups: unable to set groups for User %s "
    +			"and Group %u", name, (unsigned)ap_group_id);
    +	    clean_child_exit(APEXIT_CHILDFATAL);
    +	}
    +#ifdef MULTIPLE_GROUPS
    +	if (getgroups(NGROUPS_MAX, group_id_list) == -1) {
    +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
    +			"getgroups: unable to get group list");
    +	    clean_child_exit(APEXIT_CHILDFATAL);
    +	}
    +#endif
    +	if (setgid(ap_group_id) == -1) {
    +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
    +			"setgid: unable to set group id to Group %u",
    +			(unsigned)ap_group_id);
    +	    clean_child_exit(APEXIT_CHILDFATAL);
    +	}
    +#endif
    +    }
    +#endif /* ndef WIN32 */
    +}
    +
    +/* check to see if we have the 'suexec' setuid wrapper installed */
    +static int init_suexec(void)
    +{
    +#ifndef WIN32
    +    struct stat wrapper;
    +
    +    if ((stat(SUEXEC_BIN, &wrapper)) != 0)
    +	return (ap_suexec_enabled);
    +
    +    if ((wrapper.st_mode & S_ISUID) && wrapper.st_uid == 0) {
    +	ap_suexec_enabled = 1;
    +	fprintf(stderr, "Configuring Apache for use with suexec wrapper.\n");
    +    }
    +#endif /* ndef WIN32 */
    +    return (ap_suexec_enabled);
    +}
    +
    +/*****************************************************************
    + * Connection structures and accounting...
    + */
    +
    +
    +static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
    +			     const struct sockaddr_in *remaddr,
    +			     const struct sockaddr_in *saddr,
    +			     int child_num)
    +{
    +    conn_rec *conn = (conn_rec *) ap_pcalloc(p, sizeof(conn_rec));
    +
    +    /* Got a connection structure, so initialize what fields we can
    +     * (the rest are zeroed out by pcalloc).
    +     */
    +
    +    conn->child_num = child_num;
    +
    +    conn->pool = p;
    +    conn->local_addr = *saddr;
    +    conn->server = server; /* just a guess for now */
    +    ap_update_vhost_given_ip(conn);
    +    conn->base_server = conn->server;
    +    conn->client = inout;
    +
    +    conn->remote_addr = *remaddr;
    +    conn->remote_ip = ap_pstrdup(conn->pool,
    +			      inet_ntoa(conn->remote_addr.sin_addr));
    +
    +    return conn;
    +}
    +
    +#if defined(TCP_NODELAY) && !defined(MPE)
    +static void sock_disable_nagle(int s)
    +{
    +    /* The Nagle algorithm says that we should delay sending partial
    +     * packets in hopes of getting more data.  We don't want to do
    +     * this; we are not telnet.  There are bad interactions between
    +     * persistent connections and Nagle's algorithm that have very severe
    +     * performance penalties.  (Failing to disable Nagle is not much of a
    +     * problem with simple HTTP.)
    +     *
    +     * In spite of these problems, failure here is not a shooting offense.
    +     */
    +    int just_say_no = 1;
    +
    +    if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no,
    +		   sizeof(int)) < 0) {
    +	ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
    +		    "setsockopt: (TCP_NODELAY)");
    +    }
    +}
    +
    +#else
    +#define sock_disable_nagle(s)	/* NOOP */
    +#endif
    +
    +
    +static int make_sock(pool *p, const struct sockaddr_in *server)
    +{
    +    int s;
    +    int one = 1;
    +    char addr[512];
    +
    +    if (server->sin_addr.s_addr != htonl(INADDR_ANY))
    +	ap_snprintf(addr, sizeof(addr), "address %s port %d",
    +		inet_ntoa(server->sin_addr), ntohs(server->sin_port));
    +    else
    +	ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
    +
    +    /* note that because we're about to slack we don't use psocket */
    +    ap_block_alarms();
    +    if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
    +	ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
    +		    "make_sock: failed to get a socket for %s", addr);
    +	ap_unblock_alarms();
    +	exit(1);
    +    }
    +
    +    /* Solaris (probably versions 2.4, 2.5, and 2.5.1 with various levels
    +     * of tcp patches) has some really weird bugs where if you dup the
    +     * socket now it breaks things across SIGHUP restarts.  It'll either
    +     * be unable to bind, or it won't respond.
    +     */
    +#if defined (SOLARIS2) && SOLARIS2 < 260
    +#define WORKAROUND_SOLARIS_BUG
    +#endif
    +
    +    /* PR#1282 Unixware 1.x appears to have the same problem as solaris */
    +#if defined (UW) && UW < 200
    +#define WORKAROUND_SOLARIS_BUG
    +#endif
    +
    +#ifndef WORKAROUND_SOLARIS_BUG
    +    s = ap_slack(s, AP_SLACK_HIGH);
    +
    +    ap_note_cleanups_for_socket(p, s);	/* arrange to close on exec or restart */
    +#endif
    +
    +#ifndef MPE
    +/* MPE does not support SO_REUSEADDR and SO_KEEPALIVE */
    +#ifndef _OSD_POSIX
    +    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int)) < 0) {
    +	ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
    +		    "make_sock: for %s, setsockopt: (SO_REUSEADDR)", addr);
    +	close(s);
    +	ap_unblock_alarms();
    +	return -1;
    +    }
    +#endif /*_OSD_POSIX*/
    +    one = 1;
    +#ifndef BEOS
    +/* BeOS does not support SO_KEEPALIVE */
    +    if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(int)) < 0) {
    +	ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
    +		    "make_sock: for %s, setsockopt: (SO_KEEPALIVE)", addr);
    +	close(s);
    +	ap_unblock_alarms();
    +	return -1;
    +    }
    +#endif
    +#endif
    +
    +    sock_disable_nagle(s);
    +    sock_enable_linger(s);
    +
    +    /*
    +     * To send data over high bandwidth-delay connections at full
    +     * speed we must force the TCP window to open wide enough to keep the
    +     * pipe full.  The default window size on many systems
    +     * is only 4kB.  Cross-country WAN connections of 100ms
    +     * at 1Mb/s are not impossible for well connected sites.
    +     * If we assume 100ms cross-country latency,
    +     * a 4kB buffer limits throughput to 40kB/s.
    +     *
    +     * To avoid this problem I've added the SendBufferSize directive
    +     * to allow the web master to configure send buffer size.
    +     *
    +     * The trade-off of larger buffers is that more kernel memory
    +     * is consumed.  YMMV, know your customers and your network!
    +     *
    +     * -John Heidemann <johnh@isi.edu> 25-Oct-96
    +     *
    +     * If no size is specified, use the kernel default.
    +     */
    +#ifndef BEOS			/* BeOS does not support SO_SNDBUF */
    +    if (server_conf->send_buffer_size) {
    +	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
    +		(char *) &server_conf->send_buffer_size, sizeof(int)) < 0) {
    +	    ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
    +			"make_sock: failed to set SendBufferSize for %s, "
    +			"using default", addr);
    +	    /* not a fatal error */
    +	}
    +    }
    +#endif
    +
    +#ifdef MPE
    +/* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */
    +    if (ntohs(server->sin_port) < 1024)
    +	GETPRIVMODE();
    +#endif
    +    if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
    +	ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
    +	    "make_sock: could not bind to %s", addr);
    +#ifdef MPE
    +	if (ntohs(server->sin_port) < 1024)
    +	    GETUSERMODE();
    +#endif
    +	close(s);
    +	ap_unblock_alarms();
    +	exit(1);
    +    }
    +#ifdef MPE
    +    if (ntohs(server->sin_port) < 1024)
    +	GETUSERMODE();
    +#endif
    +
    +    if (listen(s, ap_listenbacklog) == -1) {
    +	ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
    +	    "make_sock: unable to listen for connections on %s", addr);
    +	close(s);
    +	ap_unblock_alarms();
    +	exit(1);
    +    }
    +
    +#ifdef WORKAROUND_SOLARIS_BUG
    +    s = ap_slack(s, AP_SLACK_HIGH);
    +
    +    ap_note_cleanups_for_socket(p, s);	/* arrange to close on exec or restart */
    +#endif
    +    ap_unblock_alarms();
    +
    +#ifndef WIN32
    +    /* protect various fd_sets */
    +    if (s >= FD_SETSIZE) {
    +	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
    +	    "make_sock: problem listening on %s, filedescriptor (%u) "
    +	    "larger than FD_SETSIZE (%u) "
    +	    "found, you probably need to rebuild Apache with a "
    +	    "larger FD_SETSIZE", addr, s, FD_SETSIZE);
    +	close(s);
    +	return -1;
    +    }
    +#endif
    +
    +    return s;
    +}
    +
    +
    +/*
    + * During a restart we keep track of the old listeners here, so that we
    + * can re-use the sockets.  We have to do this because we won't be able
    + * to re-open the sockets ("Address already in use").
    + *
    + * Unlike the listeners ring, old_listeners is a NULL terminated list.
    + *
    + * copy_listeners() makes the copy, find_listener() finds an old listener
    + * and close_unused_listener() cleans up whatever wasn't used.
    + */
    +static listen_rec *old_listeners;
    +
    +/* unfortunately copy_listeners may be called before listeners is a ring */
    +static void copy_listeners(pool *p)
    +{
    +    listen_rec *lr;
    +
    +    ap_assert(old_listeners == NULL);
    +    if (ap_listeners == NULL) {
    +	return;
    +    }
    +    lr = ap_listeners;
    +    do {
    +	listen_rec *nr = malloc(sizeof *nr);
    +	if (nr == NULL) {
    +	    fprintf(stderr, "Ouch!  malloc failed in copy_listeners()\n");
    +	    exit(1);
    +	}
    +	*nr = *lr;
    +	ap_kill_cleanups_for_socket(p, nr->fd);
    +	nr->next = old_listeners;
    +	ap_assert(!nr->used);
    +	old_listeners = nr;
    +	lr = lr->next;
    +    } while (lr && lr != ap_listeners);
    +}
    +
    +
    +static int find_listener(listen_rec *lr)
    +{
    +    listen_rec *or;
    +
    +    for (or = old_listeners; or; or = or->next) {
    +	if (!memcmp(&or->local_addr, &lr->local_addr, sizeof(or->local_addr))) {
    +	    or->used = 1;
    +	    return or->fd;
    +	}
    +    }
    +    return -1;
    +}
    +
    +
    +static void close_unused_listeners(void)
    +{
    +    listen_rec *or, *next;
    +
    +    for (or = old_listeners; or; or = next) {
    +	next = or->next;
    +	if (!or->used)
    +	    closesocket(or->fd);
    +	free(or);
    +    }
    +    old_listeners = NULL;
    +}
    +
    +
    +/* open sockets, and turn the listeners list into a singly linked ring */
    +static void setup_listeners(pool *p)
    +{
    +    listen_rec *lr;
    +    int fd;
    +
    +    listenmaxfd = -1;
    +    FD_ZERO(&listenfds);
    +    lr = ap_listeners;
    +    for (;;) {
    +	fd = find_listener(lr);
    +	if (fd < 0) {
    +	    fd = make_sock(p, &lr->local_addr);
    +	}
    +	else {
    +	    ap_note_cleanups_for_socket(p, fd);
    +	}
    +	if (fd >= 0) {
    +	    FD_SET(fd, &listenfds);
    +	    if (fd > listenmaxfd)
    +		listenmaxfd = fd;
    +	}
    +	lr->fd = fd;
    +	if (lr->next == NULL)
    +	    break;
    +	lr = lr->next;
    +    }
    +    /* turn the list into a ring */
    +    lr->next = ap_listeners;
    +    head_listener = ap_listeners;
    +    close_unused_listeners();
    +
    +#ifdef NO_SERIALIZED_ACCEPT
    +    /* warn them about the starvation problem if they're using multiple
    +     * sockets
    +     */
    +    if (ap_listeners->next != ap_listeners) {
    +	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, NULL,
    +		    "You cannot use multiple Listens safely on your system, "
    +		    "proceeding anyway.  See src/PORTING, search for "
    +		    "SERIALIZED_ACCEPT.");
    +    }
    +#endif
    +}
    +
    +
    +/*
    + * Find a listener which is ready for accept().  This advances the
    + * head_listener global.
    + */
    +static ap_inline listen_rec *find_ready_listener(fd_set * main_fds)
    +{
    +    listen_rec *lr;
    +
    +    lr = head_listener;
    +    do {
    +	if (FD_ISSET(lr->fd, main_fds)) {
    +	    head_listener = lr->next;
    +	    return (lr);
    +	}
    +	lr = lr->next;
    +    } while (lr != head_listener);
    +    return NULL;
    +}
    +
    +
    +#ifdef WIN32
    +static int s_iInitCount = 0;
    +
    +static int AMCSocketInitialize(void)
    +{
    +    int iVersionRequested;
    +    WSADATA wsaData;
    +    int err;
    +
    +    if (s_iInitCount > 0) {
    +	s_iInitCount++;
    +	return (0);
    +    }
    +    else if (s_iInitCount < 0)
    +	return (s_iInitCount);
    +
    +    /* s_iInitCount == 0. Do the initailization */
    +    iVersionRequested = MAKEWORD(1, 1);
    +    err = WSAStartup((WORD) iVersionRequested, &wsaData);
    +    if (err) {
    +	s_iInitCount = -1;
    +	return (s_iInitCount);
    +    }
    +    if (LOBYTE(wsaData.wVersion) != 1 ||
    +	HIBYTE(wsaData.wVersion) != 1) {
    +	s_iInitCount = -2;
    +	WSACleanup();
    +	return (s_iInitCount);
    +    }
    +
    +    s_iInitCount++;
    +    return (s_iInitCount);
    +
    +}
    +
    +
    +static void AMCSocketCleanup(void)
    +{
    +    if (--s_iInitCount == 0)
    +	WSACleanup();
    +    return;
    +}
    +#endif
    +
    +static void show_compile_settings(void)
    +{
    +    printf("Server version: %s\n", ap_get_server_version());
    +    printf("Server built:   %s\n", ap_get_server_built());
    +    printf("Server's Module Magic Number: %u\n", MODULE_MAGIC_NUMBER);
    +    printf("Server compiled with....\n");
    +#ifdef BIG_SECURITY_HOLE
    +    printf(" -D BIG_SECURITY_HOLE\n");
    +#endif
    +#ifdef SECURITY_HOLE_PASS_AUTHORIZATION
    +    printf(" -D SECURITY_HOLE_PASS_AUTHORIZATION\n");
    +#endif
    +#ifdef HTTPD_ROOT
    +    printf(" -D HTTPD_ROOT=\"" HTTPD_ROOT "\"\n");
    +#endif
    +#ifdef HAVE_MMAP
    +    printf(" -D HAVE_MMAP\n");
    +#endif
    +#ifdef HAVE_SHMGET
    +    printf(" -D HAVE_SHMGET\n");
    +#endif
    +#ifdef USE_MMAP_SCOREBOARD
    +    printf(" -D USE_MMAP_SCOREBOARD\n");
    +#endif
    +#ifdef USE_SHMGET_SCOREBOARD
    +    printf(" -D USE_SHMGET_SCOREBOARD\n");
    +#endif
    +#ifdef USE_OS2_SCOREBOARD
    +    printf(" -D USE_OS2_SCOREBOARD\n");
    +#endif
    +#ifdef USE_POSIX_SCOREBOARD
    +    printf(" -D USE_POSIX_SCOREBOARD\n");
    +#endif
    +#ifdef USE_MMAP_FILES
    +    printf(" -D USE_MMAP_FILES\n");
    +#ifdef MMAP_SEGMENT_SIZE
    +	printf(" -D MMAP_SEGMENT_SIZE=%ld\n",(long)MMAP_SEGMENT_SIZE);
    +#endif
    +#endif /*USE_MMAP_FILES*/
    +#ifdef NO_WRITEV
    +    printf(" -D NO_WRITEV\n");
    +#endif
    +#ifdef NO_LINGCLOSE
    +    printf(" -D NO_LINGCLOSE\n");
    +#endif
    +#ifdef USE_FCNTL_SERIALIZED_ACCEPT
    +    printf(" -D USE_FCNTL_SERIALIZED_ACCEPT\n");
    +#endif
    +#ifdef USE_FLOCK_SERIALIZED_ACCEPT
    +    printf(" -D USE_FLOCK_SERIALIZED_ACCEPT\n");
    +#endif
    +#ifdef USE_USLOCK_SERIALIZED_ACCEPT
    +    printf(" -D USE_USLOCK_SERIALIZED_ACCEPT\n");
    +#endif
    +#ifdef USE_SYSVSEM_SERIALIZED_ACCEPT
    +    printf(" -D USE_SYSVSEM_SERIALIZED_ACCEPT\n");
    +#endif
    +#ifdef USE_PTHREAD_SERIALIZED_ACCEPT
    +    printf(" -D USE_PTHREAD_SERIALIZED_ACCEPT\n");
    +#endif
    +#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +    printf(" -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT\n");
    +#endif
    +#ifdef NO_OTHER_CHILD
    +    printf(" -D NO_OTHER_CHILD\n");
    +#endif
    +#ifdef NO_RELIABLE_PIPED_LOGS
    +    printf(" -D NO_RELIABLE_PIPED_LOGS\n");
    +#endif
    +#ifdef BUFFERED_LOGS
    +    printf(" -D BUFFERED_LOGS\n");
    +#ifdef PIPE_BUF
    +	printf(" -D PIPE_BUF=%ld\n",(long)PIPE_BUF);
    +#endif
    +#endif
    +#ifdef MULTITHREAD
    +    printf(" -D MULTITHREAD\n");
    +#endif
    +#ifdef CHARSET_EBCDIC
    +    printf(" -D CHARSET_EBCDIC\n");
    +#endif
    +#ifdef NEED_HASHBANG_EMUL
    +    printf(" -D NEED_HASHBANG_EMUL\n");
    +#endif
    +#ifdef SHARED_CORE
    +    printf(" -D SHARED_CORE\n");
    +#endif
    +}
    +
    +
    +/* Some init code that's common between win32 and unix... well actually
    + * some of it is #ifdef'd but was duplicated before anyhow.  This stuff
    + * is still a mess.
    + */
    +static void common_init(void)
    +{
    +    INIT_SIGLIST()
    +#ifdef AUX3
    +    (void) set42sig();
    +#endif
    +
    +#ifdef SecureWare
    +    if (set_auth_parameters(argc, argv) < 0)
    +	perror("set_auth_parameters");
    +    if (getluid() < 0)
    +	if (setluid(getuid()) < 0)
    +	    perror("setluid");
    +    if (setreuid(0, 0) < 0)
    +	perror("setreuid");
    +#endif
    +
    +#ifdef WIN32
    +    /* Initialize the stupid sockets */
    +    AMCSocketInitialize();
    +#endif /* WIN32 */
    +
    +    pconf = ap_init_alloc();
    +    ptrans = ap_make_sub_pool(pconf);
    +
    +    ap_util_init();
    +    ap_util_uri_init();
    +
    +    pcommands = ap_make_sub_pool(NULL);
    +    ap_server_pre_read_config  = ap_make_array(pcommands, 1, sizeof(char *));
    +    ap_server_post_read_config = ap_make_array(pcommands, 1, sizeof(char *));
    +}
    +
    +#ifndef MULTITHREAD
    +/*****************************************************************
    + * Child process main loop.
    + * The following vars are static to avoid getting clobbered by longjmp();
    + * they are really private to child_main.
    + */
    +
    +static int srv;
    +static int csd;
    +static int dupped_csd;
    +static int requests_this_child;
    +static fd_set main_fds;
    +
    +API_EXPORT(void) ap_child_terminate(request_rec *r)
    +{
    +    r->connection->keepalive = 0;
    +    requests_this_child = ap_max_requests_per_child = 1;
    +}
    +
    +static void child_main(int child_num_arg)
    +{
    +    NET_SIZE_T clen;
    +    struct sockaddr sa_server;
    +    struct sockaddr sa_client;
    +    listen_rec *lr;
    +
    +    /* All of initialization is a critical section, we don't care if we're
    +     * told to HUP or USR1 before we're done initializing.  For example,
    +     * we could be half way through child_init_modules() when a restart
    +     * signal arrives, and we'd have no real way to recover gracefully
    +     * and exit properly.
    +     *
    +     * I suppose a module could take forever to initialize, but that would
    +     * be either a broken module, or a broken configuration (i.e. network
    +     * problems, file locking problems, whatever). -djg
    +     */
    +    ap_block_alarms();
    +
    +    my_pid = getpid();
    +    csd = -1;
    +    dupped_csd = -1;
    +    my_child_num = child_num_arg;
    +    requests_this_child = 0;
    +
    +    /* Get a sub pool for global allocations in this child, so that
    +     * we can have cleanups occur when the child exits.
    +     */
    +    pchild = ap_make_sub_pool(pconf);
    +
    +    /* needs to be done before we switch UIDs so we have permissions */
    +    reopen_scoreboard(pchild);
    +    SAFE_ACCEPT(accept_mutex_child_init(pchild));
    +
    +    set_group_privs();
    +#ifdef MPE
    +    /* Only try to switch if we're running as MANAGER.SYS */
    +    if (geteuid() == 1 && ap_user_id > 1) {
    +	GETPRIVMODE();
    +	if (setuid(ap_user_id) == -1) {
    +	    GETUSERMODE();
    +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
    +			"setuid: unable to change uid");
    +	    exit(1);
    +	}
    +	GETUSERMODE();
    +    }
    +#else
    +    /* Only try to switch if we're running as root */
    +    if (!geteuid() && (
    +#ifdef _OSD_POSIX
    +	os_init_job_environment(server_conf, ap_user_name) != 0 || 
    +#endif
    +	setuid(ap_user_id) == -1)) {
    +	ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
    +		    "setuid: unable to change uid");
    +	clean_child_exit(APEXIT_CHILDFATAL);
    +    }
    +#endif
    +
    +    ap_child_init_modules(pchild, server_conf);
    +
    +    /* done with the initialization critical section */
    +    ap_unblock_alarms();
    +
    +    (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
    +
    +    /*
    +     * Setup the jump buffers so that we can return here after
    +     * a signal or a timeout (yeah, I know, same thing).
    +     */
    +    ap_setjmp(jmpbuffer);
    +#ifndef __EMX__
    +#ifdef SIGURG
    +    signal(SIGURG, timeout);
    +#endif
    +#endif
    +    signal(SIGPIPE, timeout);
    +    signal(SIGALRM, alrm_handler);
    +
    +#ifdef __EMX__
    +/* Stop Ctrl-C/Ctrl-Break signals going to child processes */
    +    {
    +        unsigned long ulTimes;
    +        DosSetSignalExceptionFocus(0, &ulTimes);
    +    }
    +#endif
    +
    +    while (1) {
    +	BUFF *conn_io;
    +	request_rec *r;
    +
    +	/* Prepare to receive a SIGUSR1 due to graceful restart so that
    +	 * we can exit cleanly.  Since we're between connections right
    +	 * now it's the right time to exit, but we might be blocked in a
    +	 * system call when the graceful restart request is made. */
    +	usr1_just_die = 1;
    +	signal(SIGUSR1, usr1_handler);
    +
    +	/*
    +	 * (Re)initialize this child to a pre-connection state.
    +	 */
    +
    +	ap_kill_timeout(0);	/* Cancel any outstanding alarms. */
    +	timeout_req = NULL;	/* No request in progress */
    +	current_conn = NULL;
    +
    +	ap_clear_pool(ptrans);
    +
    +	ap_sync_scoreboard_image();
    +	if (ap_scoreboard_image->global.exit_generation >= generation) {
    +	    clean_child_exit(0);
    +	}
    +
    +#ifndef WIN32
    +	if ((ap_max_requests_per_child > 0
    +	     && ++requests_this_child >= ap_max_requests_per_child)) {
    +	    clean_child_exit(0);
    +	}
    +#else
    +	++requests_this_child;
    +#endif
    +
    +	(void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
    +
    +	/*
    +	 * Wait for an acceptable connection to arrive.
    +	 */
    +
    +	/* Lock around "accept", if necessary */
    +	SAFE_ACCEPT(accept_mutex_on());
    +
    +	for (;;) {
    +	    if (ap_listeners->next != ap_listeners) {
    +		/* more than one socket */
    +		memcpy(&main_fds, &listenfds, sizeof(fd_set));
    +		srv = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, NULL);
    +
    +		if (srv < 0 && errno != EINTR) {
    +		    /* Single Unix documents select as returning errnos
    +		     * EBADF, EINTR, and EINVAL... and in none of those
    +		     * cases does it make sense to continue.  In fact
    +		     * on Linux 2.0.x we seem to end up with EFAULT
    +		     * occasionally, and we'd loop forever due to it.
    +		     */
    +		    ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)");
    +		    clean_child_exit(1);
    +		}
    +
    +		if (srv <= 0)
    +		    continue;
    +
    +		lr = find_ready_listener(&main_fds);
    +		if (lr == NULL)
    +		    continue;
    +		sd = lr->fd;
    +	    }
    +	    else {
    +		/* only one socket, just pretend we did the other stuff */
    +		sd = ap_listeners->fd;
    +	    }
    +
    +	    /* if we accept() something we don't want to die, so we have to
    +	     * defer the exit
    +	     */
    +	    deferred_die = 0;
    +	    usr1_just_die = 0;
    +	    for (;;) {
    +		clen = sizeof(sa_client);
    +		csd = accept(sd, &sa_client, &clen);
    +		if (csd >= 0 || errno != EINTR)
    +		    break;
    +		if (deferred_die) {
    +		    /* we didn't get a socket, and we were told to die */
    +		    clean_child_exit(0);
    +		}
    +	    }
    +
    +	    if (csd >= 0)
    +		break;		/* We have a socket ready for reading */
    +	    else {
    +
    +		/* Our old behaviour here was to continue after accept()
    +		 * errors.  But this leads us into lots of troubles
    +		 * because most of the errors are quite fatal.  For
    +		 * example, EMFILE can be caused by slow descriptor
    +		 * leaks (say in a 3rd party module, or libc).  It's
    +		 * foolish for us to continue after an EMFILE.  We also
    +		 * seem to tickle kernel bugs on some platforms which
    +		 * lead to never-ending loops here.  So it seems best
    +		 * to just exit in most cases.
    +		 */
    +                switch (errno) {
    +#ifdef EPROTO
    +		    /* EPROTO on certain older kernels really means
    +		     * ECONNABORTED, so we need to ignore it for them.
    +		     * See discussion in new-httpd archives nh.9701
    +		     * search for EPROTO.
    +		     *
    +		     * Also see nh.9603, search for EPROTO:
    +		     * There is potentially a bug in Solaris 2.x x<6,
    +		     * and other boxes that implement tcp sockets in
    +		     * userland (i.e. on top of STREAMS).  On these
    +		     * systems, EPROTO can actually result in a fatal
    +		     * loop.  See PR#981 for example.  It's hard to
    +		     * handle both uses of EPROTO.
    +		     */
    +                case EPROTO:
    +#endif
    +#ifdef ECONNABORTED
    +                case ECONNABORTED:
    +#endif
    +		    /* Linux generates the rest of these, other tcp
    +		     * stacks (i.e. bsd) tend to hide them behind
    +		     * getsockopt() interfaces.  They occur when
    +		     * the net goes sour or the client disconnects
    +		     * after the three-way handshake has been done
    +		     * in the kernel but before userland has picked
    +		     * up the socket.
    +		     */
    +#ifdef ECONNRESET
    +                case ECONNRESET:
    +#endif
    +#ifdef ETIMEDOUT
    +                case ETIMEDOUT:
    +#endif
    +#ifdef EHOSTUNREACH
    +		case EHOSTUNREACH:
    +#endif
    +#ifdef ENETUNREACH
    +		case ENETUNREACH:
    +#endif
    +                    break;
    +
    +		default:
    +		    ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
    +				"accept: (client socket)");
    +		    clean_child_exit(1);
    +		}
    +	    }
    +
    +	    /* go around again, safe to die */
    +	    usr1_just_die = 1;
    +	    if (deferred_die) {
    +		/* ok maybe not, see ya later */
    +		clean_child_exit(0);
    +	    }
    +	    /* or maybe we missed a signal, you never know on systems
    +	     * without reliable signals
    +	     */
    +	    ap_sync_scoreboard_image();
    +	    if (ap_scoreboard_image->global.exit_generation >= generation) {
    +		clean_child_exit(0);
    +	    }
    +	}
    +
    +	SAFE_ACCEPT(accept_mutex_off());	/* unlock after "accept" */
    +
    +	/* We've got a socket, let's at least process one request off the
    +	 * socket before we accept a graceful restart request.
    +	 */
    +	signal(SIGUSR1, SIG_IGN);
    +
    +	ap_note_cleanups_for_fd(ptrans, csd);
    +
    +	/* protect various fd_sets */
    +	if (csd >= FD_SETSIZE) {
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
    +		"[csd] filedescriptor (%u) larger than FD_SETSIZE (%u) "
    +		"found, you probably need to rebuild Apache with a "
    +		"larger FD_SETSIZE", csd, FD_SETSIZE);
    +	    continue;
    +	}
    +
    +	/*
    +	 * We now have a connection, so set it up with the appropriate
    +	 * socket options, file descriptors, and read/write buffers.
    +	 */
    +
    +	clen = sizeof(sa_server);
    +	if (getsockname(csd, &sa_server, &clen) < 0) {
    +	    ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "getsockname");
    +	    continue;
    +	}
    +
    +	sock_disable_nagle(csd);
    +
    +	(void) ap_update_child_status(my_child_num, SERVER_BUSY_READ,
    +				   (request_rec *) NULL);
    +
    +	conn_io = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
    +
    +#ifdef B_SFIO
    +	(void) sfdisc(conn_io->sf_in, SF_POPDISC);
    +	sfdisc(conn_io->sf_in, bsfio_new(conn_io->pool, conn_io));
    +	sfsetbuf(conn_io->sf_in, NULL, 0);
    +
    +	(void) sfdisc(conn_io->sf_out, SF_POPDISC);
    +	sfdisc(conn_io->sf_out, bsfio_new(conn_io->pool, conn_io));
    +	sfsetbuf(conn_io->sf_out, NULL, 0);
    +#endif
    +
    +	dupped_csd = csd;
    +#if defined(NEED_DUPPED_CSD)
    +	if ((dupped_csd = dup(csd)) < 0) {
    +	    ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
    +			"dup: couldn't duplicate csd");
    +	    dupped_csd = csd;	/* Oh well... */
    +	}
    +	ap_note_cleanups_for_fd(ptrans, dupped_csd);
    +
    +	/* protect various fd_sets */
    +	if (dupped_csd >= FD_SETSIZE) {
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
    +		"[dupped_csd] filedescriptor (%u) larger than FD_SETSIZE (%u) "
    +		"found, you probably need to rebuild Apache with a "
    +		"larger FD_SETSIZE", dupped_csd, FD_SETSIZE);
    +	    continue;
    +	}
    +#endif
    +	ap_bpushfd(conn_io, csd, dupped_csd);
    +
    +	current_conn = new_connection(ptrans, server_conf, conn_io,
    +				          (struct sockaddr_in *) &sa_client,
    +				          (struct sockaddr_in *) &sa_server,
    +				          my_child_num);
    +
    +	/*
    +	 * Read and process each request found on our connection
    +	 * until no requests are left or we decide to close.
    +	 */
    +
    +	while ((r = ap_read_request(current_conn)) != NULL) {
    +
    +	    /* read_request_line has already done a
    +	     * signal (SIGUSR1, SIG_IGN);
    +	     */
    +
    +	    (void) ap_update_child_status(my_child_num, SERVER_BUSY_WRITE, r);
    +
    +	    ap_process_request(r);
    +
    +#if defined(STATUS)
    +	    increment_counts(my_child_num, r);
    +#endif
    +
    +	    if (!current_conn->keepalive || current_conn->aborted)
    +		break;
    +
    +	    ap_destroy_pool(r->pool);
    +	    (void) ap_update_child_status(my_child_num, SERVER_BUSY_KEEPALIVE,
    +				       (request_rec *) NULL);
    +
    +	    ap_sync_scoreboard_image();
    +	    if (ap_scoreboard_image->global.exit_generation >= generation) {
    +		ap_bclose(conn_io);
    +		clean_child_exit(0);
    +	    }
    +
    +	    /* In case we get a graceful restart while we're blocked
    +	     * waiting for the request.
    +	     *
    +	     * XXX: This isn't perfect, we might actually read the
    +	     * request and then just die without saying anything to
    +	     * the client.  This can be fixed by using deferred_die
    +	     * but you have to teach buff.c about it so that it can handle
    +	     * the EINTR properly.
    +	     *
    +	     * In practice though browsers (have to) expect keepalive
    +	     * connections to close before receiving a response because
    +	     * of network latencies and server timeouts.
    +	     */
    +	    usr1_just_die = 1;
    +	    signal(SIGUSR1, usr1_handler);
    +	}
    +
    +	/*
    +	 * Close the connection, being careful to send out whatever is still
    +	 * in our buffers.  If possible, try to avoid a hard close until the
    +	 * client has ACKed our FIN and/or has stopped sending us data.
    +	 */
    +
    +#ifdef NO_LINGCLOSE
    +	ap_bclose(conn_io);	/* just close it */
    +#else
    +	if (r && r->connection
    +	    && !r->connection->aborted
    +	    && r->connection->client
    +	    && (r->connection->client->fd >= 0)) {
    +
    +	    lingering_close(r);
    +	}
    +	else {
    +	    ap_bsetflag(conn_io, B_EOUT, 1);
    +	    ap_bclose(conn_io);
    +	}
    +#endif
    +    }
    +}
    +
    +static int make_child(server_rec *s, int slot, time_t now)
    +{
    +    int pid;
    +
    +    if (slot + 1 > max_daemons_limit) {
    +	max_daemons_limit = slot + 1;
    +    }
    +
    +    if (one_process) {
    +	signal(SIGHUP, just_die);
    +	signal(SIGINT, just_die);
    +	signal(SIGQUIT, SIG_DFL);
    +	signal(SIGTERM, just_die);
    +	child_main(slot);
    +    }
    +
    +    /* avoid starvation */
    +    head_listener = head_listener->next;
    +
    +    Explain1("Starting new child in slot %d", slot);
    +    (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);
    +
    +    if ((pid = fork()) == -1) {
    +	ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process");
    +
    +	/* fork didn't succeed. Fix the scoreboard or else
    +	 * it will say SERVER_STARTING forever and ever
    +	 */
    +	(void) ap_update_child_status(slot, SERVER_DEAD, (request_rec *) NULL);
    +
    +	/* In case system resources are maxxed out, we don't want
    +	   Apache running away with the CPU trying to fork over and
    +	   over and over again. */
    +	sleep(10);
    +
    +	return -1;
    +    }
    +
    +    if (!pid) {
    +#if defined(AIX) && (AIX >= 41)
    +/* by default AIX binds to a single processor
    + * this bit unbinds children which will then bind to another cpu
    + */
    +#include <sys/processor.h>
    +	int status = bindprocessor(BINDPROCESS, (int)getpid(), 
    +				   PROCESSOR_CLASS_ANY);
    +	if (status != OK) {
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
    +			"processor unbind failed %d\n", status);
    +	}
    +#endif
    +	RAISE_SIGSTOP(MAKE_CHILD);
    +	MONCONTROL(1);
    +	/* Disable the restart signal handlers and enable the just_die stuff.
    +	 * Note that since restart() just notes that a restart has been
    +	 * requested there's no race condition here.
    +	 */
    +	signal(SIGHUP, just_die);
    +	signal(SIGUSR1, just_die);
    +	signal(SIGTERM, just_die);
    +	child_main(slot);
    +    }
    +
    +#ifdef OPTIMIZE_TIMEOUTS
    +    ap_scoreboard_image->parent[slot].last_rtime = now;
    +#endif
    +    ap_scoreboard_image->parent[slot].pid = pid;
    +#ifdef SCOREBOARD_FILE
    +    lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[slot]), 0);
    +    force_write(scoreboard_fd, &ap_scoreboard_image->parent[slot],
    +		sizeof(parent_score));
    +#endif
    +
    +    return 0;
    +}
    +
    +
    +/* start up a bunch of children */
    +static void startup_children(int number_to_start)
    +{
    +    int i;
    +    time_t now = time(0);
    +
    +    for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
    +	if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
    +	    continue;
    +	}
    +	if (make_child(server_conf, i, now) < 0) {
    +	    break;
    +	}
    +	--number_to_start;
    +    }
    +}
    +
    +
    +/*
    + * idle_spawn_rate is the number of children that will be spawned on the
    + * next maintenance cycle if there aren't enough idle servers.  It is
    + * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
    + * without the need to spawn.
    + */
    +static int idle_spawn_rate = 1;
    +#ifndef MAX_SPAWN_RATE
    +#define MAX_SPAWN_RATE	(32)
    +#endif
    +static int hold_off_on_exponential_spawning;
    +
    +static void perform_idle_server_maintenance(void)
    +{
    +    int i;
    +    int to_kill;
    +    int idle_count;
    +    short_score *ss;
    +    time_t now = time(0);
    +    int free_length;
    +    int free_slots[MAX_SPAWN_RATE];
    +    int last_non_dead;
    +    int total_non_dead;
    +
    +    /* initialize the free_list */
    +    free_length = 0;
    +
    +    to_kill = -1;
    +    idle_count = 0;
    +    last_non_dead = -1;
    +    total_non_dead = 0;
    +
    +    ap_sync_scoreboard_image();
    +    for (i = 0; i < ap_daemons_limit; ++i) {
    +	int status;
    +
    +	if (i >= max_daemons_limit && free_length == idle_spawn_rate)
    +	    break;
    +	ss = &ap_scoreboard_image->servers[i];
    +	status = ss->status;
    +	if (status == SERVER_DEAD) {
    +	    /* try to keep children numbers as low as possible */
    +	    if (free_length < idle_spawn_rate) {
    +		free_slots[free_length] = i;
    +		++free_length;
    +	    }
    +	}
    +	else {
    +	    /* We consider a starting server as idle because we started it
    +	     * at least a cycle ago, and if it still hasn't finished starting
    +	     * then we're just going to swamp things worse by forking more.
    +	     * So we hopefully won't need to fork more if we count it.
    +	     * This depends on the ordering of SERVER_READY and SERVER_STARTING.
    +	     */
    +	    if (status <= SERVER_READY) {
    +		++ idle_count;
    +		/* always kill the highest numbered child if we have to...
    +		 * no really well thought out reason ... other than observing
    +		 * the server behaviour under linux where lower numbered children
    +		 * tend to service more hits (and hence are more likely to have
    +		 * their data in cpu caches).
    +		 */
    +		to_kill = i;
    +	    }
    +
    +	    ++total_non_dead;
    +	    last_non_dead = i;
    +#ifdef OPTIMIZE_TIMEOUTS
    +	    if (ss->timeout_len) {
    +		/* if it's a live server, with a live timeout then
    +		 * start checking its timeout */
    +		parent_score *ps = &ap_scoreboard_image->parent[i];
    +		if (ss->cur_vtime != ps->last_vtime) {
    +		    /* it has made progress, so update its last_rtime,
    +		     * last_vtime */
    +		    ps->last_rtime = now;
    +		    ps->last_vtime = ss->cur_vtime;
    +		}
    +		else if (ps->last_rtime + ss->timeout_len < now) {
    +		    /* no progress, and the timeout length has been exceeded */
    +		    ss->timeout_len = 0;
    +		    kill(ps->pid, SIGALRM);
    +		}
    +	    }
    +#endif
    +	}
    +    }
    +    max_daemons_limit = last_non_dead + 1;
    +    if (idle_count > ap_daemons_max_free) {
    +	/* kill off one child... we use SIGUSR1 because that'll cause it to
    +	 * shut down gracefully, in case it happened to pick up a request
    +	 * while we were counting
    +	 */
    +	kill(ap_scoreboard_image->parent[to_kill].pid, SIGUSR1);
    +	idle_spawn_rate = 1;
    +    }
    +    else if (idle_count < ap_daemons_min_free) {
    +	/* terminate the free list */
    +	if (free_length == 0) {
    +	    /* only report this condition once */
    +	    static int reported = 0;
    +
    +	    if (!reported) {
    +		ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
    +			    "server reached MaxClients setting, consider"
    +			    " raising the MaxClients setting");
    +		reported = 1;
    +	    }
    +	    idle_spawn_rate = 1;
    +	}
    +	else {
    +	    if (idle_spawn_rate >= 8) {
    +		ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
    +		    "server seems busy, (you may need "
    +		    "to increase StartServers, or Min/MaxSpareServers), "
    +		    "spawning %d children, there are %d idle, and "
    +		    "%d total children", idle_spawn_rate,
    +		    idle_count, total_non_dead);
    +	    }
    +	    for (i = 0; i < free_length; ++i) {
    +		make_child(server_conf, free_slots[i], now);
    +	    }
    +	    /* the next time around we want to spawn twice as many if this
    +	     * wasn't good enough, but not if we've just done a graceful
    +	     */
    +	    if (hold_off_on_exponential_spawning) {
    +		--hold_off_on_exponential_spawning;
    +	    }
    +	    else if (idle_spawn_rate < MAX_SPAWN_RATE) {
    +		idle_spawn_rate *= 2;
    +	    }
    +	}
    +    }
    +    else {
    +	idle_spawn_rate = 1;
    +    }
    +}
    +
    +
    +static void process_child_status(int pid, int status)
    +{
    +    /* Child died... if it died due to a fatal error,
    +	* we should simply bail out.
    +	*/
    +    if ((WIFEXITED(status)) &&
    +	WEXITSTATUS(status) == APEXIT_CHILDFATAL) {
    +	ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server_conf,
    +			"Child %d returned a Fatal error... \n"
    +			"Apache is exiting!",
    +			pid);
    +	exit(APEXIT_CHILDFATAL);
    +    }
    +    if (WIFSIGNALED(status)) {
    +	switch (WTERMSIG(status)) {
    +	case SIGTERM:
    +	case SIGHUP:
    +	case SIGUSR1:
    +	case SIGKILL:
    +	    break;
    +	default:
    +#ifdef SYS_SIGLIST
    +#ifdef WCOREDUMP
    +	    if (WCOREDUMP(status)) {
    +		ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
    +		    server_conf,
    +		    "httpd: child pid %d exit signal %s (%d), "
    +		    "possible coredump in %s",
    +		    pid, (WTERMSIG(status) >= NumSIG) ? "" : 
    +		    SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status),
    +		    ap_coredump_dir);
    +	    }
    +	    else {
    +#endif
    +		ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
    +		    server_conf,
    +		    "httpd: child pid %d exit signal %s (%d)",
    +		    pid, SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status));
    +#ifdef WCOREDUMP
    +	    }
    +#endif
    +#else
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
    +		server_conf,
    +		"httpd: child pid %d exit signal %d",
    +		pid, WTERMSIG(status));
    +#endif
    +	}
    +    }
    +}
    +
    +
    +/*****************************************************************
    + * Executive routines.
    + */
    +
    +#ifndef STANDALONE_MAIN
    +#define STANDALONE_MAIN standalone_main
    +
    +static void standalone_main(int argc, char **argv)
    +{
    +    int remaining_children_to_start;
    +
    +#ifdef __EMX__
    +    printf("%s \n", ap_get_server_version());
    +#endif
    +
    +    ap_standalone = 1;
    +
    +    is_graceful = 0;
    +    ++generation;
    +
    +    if (!one_process) {
    +	detach();
    +    }
    +    else {
    +	MONCONTROL(1);
    +    }
    +
    +    my_pid = getpid();
    +
    +    do {
    +	copy_listeners(pconf);
    +	if (!is_graceful) {
    +	    ap_restart_time = time(NULL);
    +	}
    +#ifdef SCOREBOARD_FILE
    +	else if (scoreboard_fd != -1) {
    +	    ap_kill_cleanup(pconf, NULL, cleanup_scoreboard_file);
    +	    ap_kill_cleanups_for_fd(pconf, scoreboard_fd);
    +	}
    +#endif
    +	ap_clear_pool(pconf);
    +	ptrans = ap_make_sub_pool(pconf);
    +
    +	server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
    +	setup_listeners(pconf);
    +	ap_open_logs(server_conf, pconf);
    +	ap_log_pid(pconf, ap_pid_fname);
    +	ap_set_version();	/* create our server_version string */
    +	ap_init_modules(pconf, server_conf);
    +	version_locked++;	/* no more changes to server_version */
    +	SAFE_ACCEPT(accept_mutex_init(pconf));
    +	if (!is_graceful) {
    +	    reinit_scoreboard(pconf);
    +	}
    +#ifdef SCOREBOARD_FILE
    +	else {
    +	    ap_scoreboard_fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
    +	    ap_note_cleanups_for_fd(pconf, scoreboard_fd);
    +	}
    +#endif
    +
    +	set_signals();
    +
    +	if (ap_daemons_max_free < ap_daemons_min_free + 1)	/* Don't thrash... */
    +	    ap_daemons_max_free = ap_daemons_min_free + 1;
    +
    +	/* If we're doing a graceful_restart then we're going to see a lot
    +	 * of children exiting immediately when we get into the main loop
    +	 * below (because we just sent them SIGUSR1).  This happens pretty
    +	 * rapidly... and for each one that exits we'll start a new one until
    +	 * we reach at least daemons_min_free.  But we may be permitted to
    +	 * start more than that, so we'll just keep track of how many we're
    +	 * supposed to start up without the 1 second penalty between each fork.
    +	 */
    +	remaining_children_to_start = ap_daemons_to_start;
    +	if (remaining_children_to_start > ap_daemons_limit) {
    +	    remaining_children_to_start = ap_daemons_limit;
    +	}
    +	if (!is_graceful) {
    +	    startup_children(remaining_children_to_start);
    +	    remaining_children_to_start = 0;
    +	}
    +	else {
    +	    /* give the system some time to recover before kicking into
    +	     * exponential mode */
    +	    hold_off_on_exponential_spawning = 10;
    +	}
    +
    +	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
    +		    "%s configured -- resuming normal operations",
    +		    ap_get_server_version());
    +	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf,
    +		    "Server built: %s", ap_get_server_built());
    +	restart_pending = shutdown_pending = 0;
    +
    +	while (!restart_pending && !shutdown_pending) {
    +	    int child_slot;
    +	    int status;
    +	    int pid = wait_or_timeout(&status);
    +
    +	    /* XXX: if it takes longer than 1 second for all our children
    +	     * to start up and get into IDLE state then we may spawn an
    +	     * extra child
    +	     */
    +	    if (pid >= 0) {
    +		process_child_status(pid, status);
    +		/* non-fatal death... note that it's gone in the scoreboard. */
    +		ap_sync_scoreboard_image();
    +		child_slot = find_child_by_pid(pid);
    +		Explain2("Reaping child %d slot %d", pid, child_slot);
    +		if (child_slot >= 0) {
    +		    (void) ap_update_child_status(child_slot, SERVER_DEAD,
    +					       (request_rec *) NULL);
    +		    if (remaining_children_to_start
    +			&& child_slot < ap_daemons_limit) {
    +			/* we're still doing a 1-for-1 replacement of dead
    +			 * children with new children
    +			 */
    +			make_child(server_conf, child_slot, time(0));
    +			--remaining_children_to_start;
    +		    }
    +#ifndef NO_OTHER_CHILD
    +		}
    +		else if (reap_other_child(pid, status) == 0) {
    +		    /* handled */
    +#endif
    +		}
    +		else if (is_graceful) {
    +		    /* Great, we've probably just lost a slot in the
    +		     * scoreboard.  Somehow we don't know about this
    +		     * child.
    +		     */
    +		    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
    +				"long lost child came home! (pid %d)", pid);
    +		}
    +		/* Don't perform idle maintenance when a child dies,
    +		 * only do it when there's a timeout.  Remember only a
    +		 * finite number of children can die, and it's pretty
    +		 * pathological for a lot to die suddenly.
    +		 */
    +		continue;
    +	    }
    +	    else if (remaining_children_to_start) {
    +		/* we hit a 1 second timeout in which none of the previous
    +		 * generation of children needed to be reaped... so assume
    +		 * they're all done, and pick up the slack if any is left.
    +		 */
    +		startup_children(remaining_children_to_start);
    +		remaining_children_to_start = 0;
    +		/* In any event we really shouldn't do the code below because
    +		 * few of the servers we just started are in the IDLE state
    +		 * yet, so we'd mistakenly create an extra server.
    +		 */
    +		continue;
    +	    }
    +
    +	    perform_idle_server_maintenance();
    +	}
    +
    +	if (shutdown_pending) {
    +	    /* Time to gracefully shut down:
    +	     * Kill child processes, tell them to call child_exit, etc...
    +	     */
    +	    if (ap_killpg(pgrp, SIGTERM) < 0) {
    +		ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGTERM");
    +	    }
    +	    reclaim_child_processes(1);		/* Start with SIGTERM */
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
    +			"httpd: caught SIGTERM, shutting down");
    +
    +	    clean_parent_exit(0);
    +	}
    +
    +	/* we've been told to restart */
    +	signal(SIGHUP, SIG_IGN);
    +	signal(SIGUSR1, SIG_IGN);
    +
    +	if (one_process) {
    +	    /* not worth thinking about */
    +	    clean_parent_exit(0);
    +	}
    +
    +	if (is_graceful) {
    +#ifndef SCOREBOARD_FILE
    +	    int i;
    +#endif
    +
    +	    /* USE WITH CAUTION:  Graceful restarts are not known to work
    +	     * in various configurations on the architectures we support. */
    +	    ap_scoreboard_image->global.exit_generation = generation;
    +	    update_scoreboard_global();
    +
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
    +			"SIGUSR1 received.  Doing graceful restart");
    +
    +	    /* kill off the idle ones */
    +	    if (ap_killpg(pgrp, SIGUSR1) < 0) {
    +		ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGUSR1");
    +	    }
    +#ifndef SCOREBOARD_FILE
    +	    /* This is mostly for debugging... so that we know what is still
    +	     * gracefully dealing with existing request.  But we can't really
    +	     * do it if we're in a SCOREBOARD_FILE because it'll cause
    +	     * corruption too easily.
    +	     */
    +	    ap_sync_scoreboard_image();
    +	    for (i = 0; i < ap_daemons_limit; ++i) {
    +		if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
    +		    ap_scoreboard_image->servers[i].status = SERVER_GRACEFUL;
    +		}
    +	    }
    +#endif
    +	}
    +	else {
    +	    /* Kill 'em off */
    +	    if (ap_killpg(pgrp, SIGHUP) < 0) {
    +		ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGHUP");
    +	    }
    +	    reclaim_child_processes(0);		/* Not when just starting up */
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
    +			"SIGHUP received.  Attempting to restart");
    +	}
    +	++generation;
    +    } while (restart_pending);
    +
    +    /*add_common_vars(NULL);*/
    +}				/* standalone_main */
    +#else
    +/* prototype */
    +void STANDALONE_MAIN(int argc, char **argv);
    +#endif /* STANDALONE_MAIN */
    +
    +extern char *optarg;
    +extern int optind;
    +
    +int REALMAIN(int argc, char *argv[])
    +{
    +    int c;
    +
    +#ifdef SOCKS
    +    SOCKSinit(argv[0]);
    +#endif
    +
    +    MONCONTROL(0);
    +
    +    common_init();
    +    
    +    ap_server_argv0 = argv[0];
    +    ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root));
    +    ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname));
    +
    +    ap_setup_prelinked_modules();
    +
    +    while ((c = getopt(argc, argv,
    +				    "C:c:Xd:f:vVhlL:S"
    +#ifdef DEBUG_SIGSTOP
    +				    "Z:"
    +#endif
    +			)) != -1) {
    +	char **new;
    +	switch (c) {
    +	case 'c':
    +	    new = (char **)ap_push_array(ap_server_post_read_config);
    +	    *new = ap_pstrdup(pcommands, optarg);
    +	    break;
    +	case 'C':
    +	    new = (char **)ap_push_array(ap_server_pre_read_config);
    +	    *new = ap_pstrdup(pcommands, optarg);
    +	    break;
    +	case 'd':
    +	    ap_cpystrn(ap_server_root, optarg, sizeof(ap_server_root));
    +	    break;
    +	case 'f':
    +	    ap_cpystrn(ap_server_confname, optarg, sizeof(ap_server_confname));
    +	    break;
    +	case 'v':
    +	    ap_set_version();
    +	    printf("Server version: %s\n", ap_get_server_version());
    +	    printf("Server built:   %s\n", ap_get_server_built());
    +	    exit(0);
    +	case 'V':
    +	    ap_set_version();
    +	    show_compile_settings();
    +	    exit(0);
    +	case 'h':
    +	    ap_show_directives();
    +	    exit(0);
    +	case 'l':
    +	    ap_show_modules();
    +	    exit(0);
    +	case 'X':
    +	    ++one_process;	/* Weird debugging mode. */
    +	    break;
    +#ifdef DEBUG_SIGSTOP
    +	case 'Z':
    +	    raise_sigstop_flags = atoi(optarg);
    +	    break;
    +#endif
    +#ifdef SHARED_CORE
    +	case 'L':
    +	    /* just ignore this option here, because it has only
    +	     * effect when SHARED_CORE is used and then it was
    +	     * already handled in the Shared Core Bootstrap
    +	     * program.
    +	     */
    +	    break;
    +#endif
    +	case 'S':
    +	    ap_dump_settings = 1;
    +	    break;
    +	case '?':
    +	    usage(argv[0]);
    +	}
    +    }
    +
    +    ap_suexec_enabled = init_suexec();
    +    server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
    +
    +    child_timeouts = !ap_standalone || one_process;
    +
    +    if (ap_standalone) {
    +	ap_open_logs(server_conf, pconf);
    +	ap_set_version();
    +	ap_init_modules(pconf, server_conf);
    +	version_locked++;
    +	STANDALONE_MAIN(argc, argv);
    +    }
    +    else {
    +	conn_rec *conn;
    +	request_rec *r;
    +	struct sockaddr sa_server, sa_client;
    +	BUFF *cio;
    +	NET_SIZE_T l;
    +
    +	/* Yes this is called twice. */
    +	ap_init_modules(pconf, server_conf);
    +	ap_open_logs(server_conf, pconf);
    +	ap_init_modules(pconf, server_conf);
    +	set_group_privs();
    +
    +#ifdef MPE
    +	/* Only try to switch if we're running as MANAGER.SYS */
    +	if (geteuid() == 1 && ap_user_id > 1) {
    +	    GETPRIVMODE();
    +	    if (setuid(ap_user_id) == -1) {
    +		GETUSERMODE();
    +		ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
    +			    "setuid: unable to change uid");
    +		exit(1);
    +	    }
    +	    GETUSERMODE();
    +	}
    +#else
    +	/* Only try to switch if we're running as root */
    +	if (!geteuid() && setuid(ap_user_id) == -1) {
    +	    ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
    +			"setuid: unable to change uid");
    +	    exit(1);
    +	}
    +#endif
    +	if (ap_setjmp(jmpbuffer)) {
    +	    exit(0);
    +	}
    +
    +	l = sizeof(sa_client);
    +	if ((getpeername(fileno(stdin), &sa_client, &l)) < 0) {
    +/* get peername will fail if the input isn't a socket */
    +	    perror("getpeername");
    +	    memset(&sa_client, '\0', sizeof(sa_client));
    +	}
    +
    +	l = sizeof(sa_server);
    +	if (getsockname(fileno(stdin), &sa_server, &l) < 0) {
    +	    perror("getsockname");
    +	    fprintf(stderr, "Error getting local address\n");
    +	    exit(1);
    +	}
    +	server_conf->port = ntohs(((struct sockaddr_in *) &sa_server)->sin_port);
    +	cio = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
    +#ifdef MPE
    +/* HP MPE 5.5 inetd only passes the incoming socket as stdin (fd 0), whereas
    +   HPUX inetd passes the incoming socket as stdin (fd 0) and stdout (fd 1).
    +   Go figure.  SR 5003355016 has been submitted to request that the existing
    +   functionality be documented, and then to enhance the functionality to be
    +   like HPUX. */
    +
    +	cio->fd = fileno(stdin);
    +#else
    +	cio->fd = fileno(stdout);
    +#endif
    +	cio->fd_in = fileno(stdin);
    +	conn = new_connection(ptrans, server_conf, cio,
    +			          (struct sockaddr_in *) &sa_client,
    +			          (struct sockaddr_in *) &sa_server, -1);
    +	r = ap_read_request(conn);
    +	if (r)
    +	    ap_process_request(r);	/* else premature EOF (ignore) */
    +
    +	while (r && conn->keepalive && !conn->aborted) {
    +	    ap_destroy_pool(r->pool);
    +	    r = ap_read_request(conn);
    +	    if (r)
    +		ap_process_request(r);
    +	}
    +
    +	ap_bclose(cio);
    +    }
    +    exit(0);
    +}
    +
    +#else /* ndef MULTITHREAD */
    +
    +
    +/**********************************************************************
    + * Multithreaded implementation
    + *
    + * This code is fairly specific to Win32.
    + *
    + * The model used to handle requests is a set of threads. One "main"
    + * thread listens for new requests. When something becomes
    + * available, it does a select and places the newly available socket
    + * onto a list of "jobs" (add_job()). Then any one of a fixed number
    + * of "worker" threads takes the top job off the job list with
    + * remove_job() and handles that connection to completion. After
    + * the connection has finished the thread is free to take another
    + * job from the job list.
    + *
    + * In the code, the "main" thread is running within the worker_main()
    + * function. The first thing this function does is create the
    + * worker threads, which operate in the child_sub_main() function. The
    + * main thread then goes into a loop within worker_main() where they
    + * do a select() on the listening sockets. The select times out once
    + * per second so that the thread can check for an "exit" signal
    + * from the parent process (see below). If this signal is set, the 
    + * thread can exit, but only after it has accepted all incoming
    + * connections already in the listen queue (since Win32 appears
    + * to through away listened but unaccepted connections when a 
    + * process dies).
    + *
    + * Because the main and worker threads exist within a single process
    + * they are vulnerable to crashes or memory leaks (crashes can also
    + * be caused within modules, of course). There also needs to be a 
    + * mechanism to perform restarts and shutdowns. This is done by
    + * creating the main & worker threads within a subprocess. A
    + * main process (the "parent process") creates one (or more) 
    + * processes to do the work, then the parent sits around waiting
    + * for the working process to die, in which case it starts a new
    + * one. The parent process also handles restarts (by creating
    + * a new working process then signalling the previous working process 
    + * exit ) and shutdowns (by signalling the working process to exit).
    + * The parent process operates within the master_main() function. This
    + * process also handles requests from the service manager (NT only).
    + *
    + * Signalling between the parent and working process uses a Win32
    + * event. Each child has a unique name for the event, which is
    + * passed to it with the -c argument when the child is spawned. The
    + * parent sets (signals) this event to tell the child to die.
    + * At present all children do a graceful die - they finish all
    + * current jobs _and_ empty the listen queue before they exit.
    + * A non-graceful die would need a second event.
    + *
    + * The code below starts with functions at the lowest level -
    + * worker threads, and works up to the top level - the main()
    + * function of the parent process.
    + *
    + * The scoreboard (in process memory) contains details of the worker
    + * threads (within the active working process). There is no shared
    + * "scoreboard" between processes, since only one is ever active
    + * at once (or at most, two, when one has been told to shutdown but
    + * is processes outstanding requests, and a new one has been started).
    + * This is controlled by a "start_mutex" which ensures only one working
    + * process is active at once.
    + **********************************************************************/
    +
    +/* The code protected by #ifdef UNGRACEFUL_RESTARTS/#endif sections
    + * could implement a sort-of ungraceful restart for Win32. instead of
    + * graceful restarts. 
    + *
    + * However it does not work too well because it does not intercept a
    + * connection already in progress (in child_sub_main()). We'd have to
    + * get that to poll on the exit event. 
    + */
    +
    +/*
    + * Definition of jobs, shared by main and worker threads.
    + */
    +
    +typedef struct joblist_s {
    +    struct joblist_s *next;
    +    int sock;
    +} joblist;
    +
    +/*
    + * Globals common to main and worker threads. This structure is not
    + * used by the parent process.
    + */
    +
    +typedef struct globals_s {
    +#ifdef UNGRACEFUL_RESTART
    +    HANDLE thread_exit_event;
    +#else
    +    int exit_now;
    +#endif
    +    semaphore *jobsemaphore;
    +    joblist *jobhead;
    +    joblist *jobtail;
    +    mutex *jobmutex;
    +    int jobcount;
    +} globals;
    +
    +globals allowed_globals =
    +{0, NULL, NULL, NULL, 0};
    +
    +/*
    + * add_job()/remove_job() - add or remove an accepted socket from the
    + * list of sockets connected to clients. allowed_globals.jobmutex protects
    + * against multiple concurrent access to the linked list of jobs.
    + */
    +
    +void add_job(int sock)
    +{
    +    joblist *new_job;
    +
    +    ap_assert(allowed_globals.jobmutex);
    +    /* TODO: If too many jobs in queue, sleep, check for problems */
    +    ap_acquire_mutex(allowed_globals.jobmutex);
    +    new_job = (joblist *) malloc(sizeof(joblist));
    +    new_job->next = NULL;
    +    new_job->sock = sock;
    +    if (allowed_globals.jobtail != NULL)
    +	allowed_globals.jobtail->next = new_job;
    +    allowed_globals.jobtail = new_job;
    +    if (!allowed_globals.jobhead)
    +	allowed_globals.jobhead = new_job;
    +    allowed_globals.jobcount++;
    +    release_semaphore(allowed_globals.jobsemaphore);
    +    ap_release_mutex(allowed_globals.jobmutex);
    +}
    +
    +int remove_job()
    +{
    +    joblist *job;
    +    int sock;
    +
    +#ifdef UNGRACEFUL_RESTART
    +    HANDLE hObjects[2];
    +    int rv;
    +
    +    hObjects[0] = allowed_globals.jobsemaphore;
    +    hObjects[1] = allowed_globals.thread_exit_event;
    +
    +    rv = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
    +    ap_assert(rv != WAIT_FAILED);
    +    if (rv == WAIT_OBJECT_0 + 1) {
    +	/* thread_exit_now */
    +	APD1("thread got exit now event");
    +	return -1;
    +    }
    +    /* must be semaphore */
    +#else
    +    acquire_semaphore(allowed_globals.jobsemaphore);
    +#endif
    +    ap_assert(allowed_globals.jobmutex);
    +
    +#ifdef UNGRACEFUL_RESTART
    +    if (!allowed_globals.jobhead) {
    +#else
    +    ap_acquire_mutex(allowed_globals.jobmutex);
    +    if (allowed_globals.exit_now && !allowed_globals.jobhead) {
    +#endif
    +	ap_release_mutex(allowed_globals.jobmutex);
    +	return (-1);
    +    }
    +    job = allowed_globals.jobhead;
    +    ap_assert(job);
    +    allowed_globals.jobhead = job->next;
    +    if (allowed_globals.jobhead == NULL)
    +	allowed_globals.jobtail = NULL;
    +    ap_release_mutex(allowed_globals.jobmutex);
    +    sock = job->sock;
    +    free(job);
    +    return (sock);
    +}
    +
    +/*
    + * child_sub_main() - this is the main loop for the worker threads
    + *
    + * Each thread runs within this function. They wait within remove_job()
    + * for a job to become available, then handle all the requests on that
    + * connection until it is closed, then return to remove_job().
    + *
    + * The worker thread will exit when it removes a job which contains
    + * socket number -1. This provides a graceful thread exit, since
    + * it will never exit during a connection.
    + *
    + * This code in this function is basically equivalent to the child_main()
    + * from the multi-process (Unix) environment, except that we
    + *
    + *  - do not call child_init_modules (child init API phase)
    + *  - block in remove_job, and when unblocked we have an already
    + *    accepted socket, instead of blocking on a mutex or select().
    + */
    +
    +static void child_sub_main(int child_num)
    +{
    +    NET_SIZE_T clen;
    +    struct sockaddr sa_server;
    +    struct sockaddr sa_client;
    +    pool *ptrans;
    +    int requests_this_child = 0;
    +    int csd = -1;
    +    int dupped_csd = -1;
    +    int srv = 0;
    +
    +    ptrans = ap_make_sub_pool(pconf);
    +
    +    (void) ap_update_child_status(child_num, SERVER_READY, (request_rec *) NULL);
    +
    +    /*
    +     * Setup the jump buffers so that we can return here after
    +     * a signal or a timeout (yeah, I know, same thing).
    +     */
    +#if defined(USE_LONGJMP)
    +    setjmp(jmpbuffer);
    +#else
    +    sigsetjmp(jmpbuffer, 1);
    +#endif
    +#ifdef SIGURG
    +    signal(SIGURG, timeout);
    +#endif
    +
    +    while (1) {
    +	BUFF *conn_io;
    +	request_rec *r;
    +
    +	/*
    +	 * (Re)initialize this child to a pre-connection state.
    +	 */
    +
    +	ap_set_callback_and_alarm(NULL, 0);	/* Cancel any outstanding alarms. */
    +	timeout_req = NULL;	/* No request in progress */
    +	current_conn = NULL;
    +#ifdef SIGPIPE
    +	signal(SIGPIPE, timeout);
    +#endif
    +
    +	ap_clear_pool(ptrans);
    +
    +	(void) ap_update_child_status(child_num, SERVER_READY, (request_rec *) NULL);
    +
    +	/* Get job from the job list. This will block until a job is ready.
    +	 * If -1 is returned then the main thread wants us to exit.
    +	 */
    +	csd = remove_job();
    +	if (csd == -1)
    +	    break;		/* time to exit */
    +	requests_this_child++;
    +
    +	ap_note_cleanups_for_socket(ptrans, csd);
    +
    +	/*
    +	 * We now have a connection, so set it up with the appropriate
    +	 * socket options, file descriptors, and read/write buffers.
    +	 */
    +
    +	clen = sizeof(sa_server);
    +	if (getsockname(csd, &sa_server, &clen) < 0) {
    +	    ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "getsockname");
    +	    continue;
    +	}
    +	clen = sizeof(sa_client);
    +	if ((getpeername(csd, &sa_client, &clen)) < 0) {
    +	    /* get peername will fail if the input isn't a socket */
    +	    perror("getpeername");
    +	    memset(&sa_client, '\0', sizeof(sa_client));
    +	}
    +
    +	sock_disable_nagle(csd);
    +
    +	(void) ap_update_child_status(child_num, SERVER_BUSY_READ,
    +				   (request_rec *) NULL);
    +
    +	conn_io = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
    +	dupped_csd = csd;
    +#if defined(NEED_DUPPED_CSD)
    +	if ((dupped_csd = dup(csd)) < 0) {
    +	    ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
    +			"dup: couldn't duplicate csd");
    +	    dupped_csd = csd;	/* Oh well... */
    +	}
    +	ap_note_cleanups_for_socket(ptrans, dupped_csd);
    +#endif
    +	ap_bpushfd(conn_io, csd, dupped_csd);
    +
    +	current_conn = new_connection(ptrans, server_conf, conn_io,
    +				          (struct sockaddr_in *) &sa_client,
    +				          (struct sockaddr_in *) &sa_server,
    +				          child_num);
    +
    +	/*
    +	 * Read and process each request found on our connection
    +	 * until no requests are left or we decide to close.
    +	 */
    +
    +	while ((r = ap_read_request(current_conn)) != NULL) {
    +	    (void) ap_update_child_status(child_num, SERVER_BUSY_WRITE, r);
    +
    +	    ap_process_request(r);
    +
    +#if defined(STATUS)
    +	    increment_counts(child_num, r);
    +#endif
    +
    +	    if (!current_conn->keepalive || current_conn->aborted)
    +		break;
    +
    +	    ap_destroy_pool(r->pool);
    +	    (void) ap_update_child_status(child_num, SERVER_BUSY_KEEPALIVE,
    +				       (request_rec *) NULL);
    +
    +	    ap_sync_scoreboard_image();
    +	}
    +
    +	/*
    +	 * Close the connection, being careful to send out whatever is still
    +	 * in our buffers.  If possible, try to avoid a hard close until the
    +	 * client has ACKed our FIN and/or has stopped sending us data.
    +	 */
    +	ap_kill_cleanups_for_socket(ptrans, csd);
    +
    +#ifdef NO_LINGCLOSE
    +	ap_bclose(conn_io);	/* just close it */
    +#else
    +	if (r && r->connection
    +	    && !r->connection->aborted
    +	    && r->connection->client
    +	    && (r->connection->client->fd >= 0)) {
    +
    +	    lingering_close(r);
    +	}
    +	else {
    +	    ap_bsetflag(conn_io, B_EOUT, 1);
    +	    ap_bclose(conn_io);
    +	}
    +#endif
    +    }
    +    ap_destroy_pool(ptrans);
    +    (void) ap_update_child_status(child_num, SERVER_DEAD, NULL);
    +}
    +
    +
    +void child_main(int child_num_arg)
    +{
    +    /*
    +     * Only reason for this function, is to pass in
    +     * arguments to child_sub_main() on its stack so
    +     * that longjump doesn't try to corrupt its local
    +     * variables and I don't need to make those
    +     * damn variables static/global
    +     */
    +    child_sub_main(child_num_arg);
    +}
    +
    +
    +
    +void cleanup_thread(thread **handles, int *thread_cnt, int thread_to_clean)
    +{
    +    int i;
    +
    +    free_thread(handles[thread_to_clean]);
    +    for (i = thread_to_clean; i < ((*thread_cnt) - 1); i++)
    +	handles[i] = handles[i + 1];
    +    (*thread_cnt)--;
    +}
    +
    +/*****************************************************************
    + * Executive routines.
    + */
    +
    +extern void main_control_server(void *); /* in hellop.c */
    +
    +event *exit_event;
    +mutex *start_mutex;
    +
    +#define MAX_SELECT_ERRORS 100
    +
    +void worker_main()
    +{
    +    /*
    +     * I am writing this stuff specifically for NT.
    +     * have pulled out a lot of the restart and
    +     * graceful restart stuff, because that is only
    +     * useful on Unix (not sure it even makes sense
    +     * in a multi-threaded env.
    +     */
    +    int nthreads;
    +    fd_set main_fds;
    +    int srv;
    +    int clen;
    +    int csd;
    +    struct sockaddr_in sa_client;
    +    int total_jobs = 0;
    +    thread **child_handles;
    +    int rv;
    +    time_t end_time;
    +    int i;
    +    struct timeval tv;
    +    int wait_time = 1;
    +    int start_exit = 0;
    +    int start_mutex_released = 0;
    +    int max_jobs_per_exe;
    +    int max_jobs_after_exit_request;
    +    HANDLE hObjects[2];
    +    int count_select_errors = 0;
    +    pool *pchild;
    +
    +    pchild = ap_make_sub_pool(pconf);
    +
    +    ap_standalone = 1;
    +    sd = -1;
    +    nthreads = ap_threads_per_child;
    +    max_jobs_after_exit_request = ap_excess_requests_per_child;
    +    max_jobs_per_exe = ap_max_requests_per_child;
    +    if (nthreads <= 0)
    +	nthreads = 40;
    +    if (max_jobs_per_exe <= 0)
    +	max_jobs_per_exe = 0;
    +    if (max_jobs_after_exit_request <= 0)
    +	max_jobs_after_exit_request = max_jobs_per_exe / 10;
    +
    +    if (!one_process)
    +	detach();
    +
    +    my_pid = getpid();
    +
    +    ++generation;
    +
    +    copy_listeners(pconf);
    +    ap_restart_time = time(NULL);
    +
    +    reinit_scoreboard(pconf);
    +
    +    //ap_acquire_mutex(start_mutex);
    +    hObjects[0] = (HANDLE)start_mutex;
    +    hObjects[1] = (HANDLE)exit_event;
    +    rv = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
    +    if (rv == WAIT_FAILED) {
    +	ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_WIN32ERROR, server_conf,
    +	    "Waiting for start_mutex or exit_event -- process will exit");
    +
    +	ap_destroy_pool(pchild);
    +	cleanup_scoreboard();
    +	exit(0);
    +    }
    +    if (rv == WAIT_OBJECT_0 + 1) {
    +	/* exit event signalled - exit now */
    +	ap_destroy_pool(pchild);
    +	cleanup_scoreboard();
    +	exit(0);
    +    }
    +    /* start_mutex obtained, continue into the select() loop */
    +
    +    setup_listeners(pconf);
    +    if (listenmaxfd == -1) {
    +	/* Help, no sockets were made, better log something and exit */
    +	ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_NOERRNO, NULL,
    +		    "No sockets were created for listening");
    +
    +	signal_parent();	/* tell parent to die */
    +
    +	ap_destroy_pool(pchild);
    +	cleanup_scoreboard();
    +	exit(0);
    +    }
    +    set_signals();
    +
    +    /*
    +     * - Initialize allowed_globals
    +     * - Create the thread table
    +     * - Spawn off threads
    +     * - Create listen socket set (done above)
    +     * - loop {
    +     *       wait for request
    +     *       create new job
    +     *   } while (!time to exit)
    +     * - Close all listeners
    +     * - Wait for all threads to complete
    +     * - Exit
    +     */
    +
    +    ap_child_init_modules(pconf, server_conf);
    +
    +    allowed_globals.jobsemaphore = create_semaphore(0);
    +    allowed_globals.jobmutex = ap_create_mutex(NULL);
    +
    +    /* spawn off the threads */
    +    child_handles = (thread *) alloca(nthreads * sizeof(int));
    +    {
    +	int i;
    +
    +	for (i = 0; i < nthreads; i++) {
    +	    child_handles[i] = create_thread((void (*)(void *)) child_main, (void *) i);
    +	}
    +	if (nthreads > max_daemons_limit) {
    +	    max_daemons_limit = nthreads;
    +	}
    +    }
    +
    +    while (1) {
    +#if SEVERELY_VERBOSE
    +	APD4("child PID %d: thread_main total_jobs=%d start_exit=%d",
    +		my_pid, total_jobs, start_exit);
    +#endif
    +	if ((max_jobs_per_exe && (total_jobs > max_jobs_per_exe) && !start_exit)) {
    +	    start_exit = 1;
    +	    wait_time = 1;
    +	    ap_release_mutex(start_mutex);
    +	    start_mutex_released = 1;
    +	    APD2("process PID %d: start mutex released\n", my_pid);
    +	}
    +	if (!start_exit) {
    +	    rv = WaitForSingleObject(exit_event, 0);
    +	    ap_assert((rv == WAIT_TIMEOUT) || (rv == WAIT_OBJECT_0));
    +	    if (rv == WAIT_OBJECT_0) {
    +		APD1("child: exit event signalled, exiting");
    +		start_exit = 1;
    +		/* Lets not break yet - we may have threads to clean up */
    +		/* break;*/
    +	    }
    +	    rv = WaitForMultipleObjects(nthreads, child_handles, 0, 0);
    +	    ap_assert(rv != WAIT_FAILED);
    +	    if (rv != WAIT_TIMEOUT) {
    +		rv = rv - WAIT_OBJECT_0;
    +		ap_assert((rv >= 0) && (rv < nthreads));
    +		cleanup_thread(child_handles, &nthreads, rv);
    +		break;
    +	    }
    +	}
    +
    +#if 0
    +	/* Um, this made us exit before all the connections in our
    +	 * listen queue were dealt with. 
    +	 */
    +	if (start_exit && max_jobs_after_exit_request && (count_down-- < 0))
    +	    break;
    +#endif
    +	tv.tv_sec = wait_time;
    +	tv.tv_usec = 0;
    +
    +	memcpy(&main_fds, &listenfds, sizeof(fd_set));
    +	srv = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);
    +#ifdef WIN32
    +	if (srv == SOCKET_ERROR) {
    +	    /* Map the Win32 error into a standard Unix error condition */
    +	    errno = WSAGetLastError();
    +	    srv = -1;
    +	}
    +#endif /* WIN32 */
    +
    +	if (srv < 0) {
    +	    /* Error occurred - if EINTR, loop around with problem */
    +	    if (errno != EINTR) {
    +		/* A "real" error occurred, log it and increment the count of
    +		 * select errors. This count is used to ensure we don't go into
    +		 * a busy loop of continuour errors.
    +		 */
    +		ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)");
    +		count_select_errors++;
    +		if (count_select_errors > MAX_SELECT_ERRORS) {
    +		    ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server_conf,
    +			"Too many errors in select loop. Child process exiting.");
    +		    break;
    +		}
    +	    }
    +	    continue;
    +	}
    +	count_select_errors = 0;    /* reset count of errors */
    +	if (srv == 0) {
    +	    if (start_exit)
    +		break;
    +	    else
    +		continue;
    +	}
    +
    +	{
    +	    listen_rec *lr;
    +
    +	    lr = find_ready_listener(&main_fds);
    +	    if (lr != NULL) {
    +		sd = lr->fd;
    +	    }
    +	}
    +	do {
    +	    clen = sizeof(sa_client);
    +	    csd = accept(sd, (struct sockaddr *) &sa_client, &clen);
    +#ifdef WIN32
    +	    if (csd == INVALID_SOCKET) {
    +		csd = -1;
    +		errno = WSAGetLastError();
    +	    }
    +#endif /* WIN32 */
    +	} while (csd < 0 && errno == EINTR);
    +
    +	if (csd < 0) {
    +#if defined(EPROTO) && defined(ECONNABORTED)
    +	    if ((errno != EPROTO) && (errno != ECONNABORTED))
    +#elif defined(EPROTO)
    +	    if (errno != EPROTO)
    +#elif defined(ECONNABORTED)
    +	    if (errno != ECONNABORTED)
    +#endif
    +		ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
    +			    "accept: (client socket)");
    +	}
    +	else {
    +	    add_job(csd);
    +	    total_jobs++;
    +	}
    +    }
    +      
    +    APD2("process PID %d exiting", my_pid);
    +
    +    /* Get ready to shutdown and exit */
    +    allowed_globals.exit_now = 1;
    +    if (!start_mutex_released) {
    +	ap_release_mutex(start_mutex);
    +    }
    +
    +#ifdef UNGRACEFUL_RESTART
    +    SetEvent(allowed_globals.thread_exit_event);
    +#else
    +    for (i = 0; i < nthreads; i++) {
    +	add_job(-1);
    +    }
    +#endif
    +
    +    APD2("process PID %d waiting for worker threads to exit", my_pid);
    +    /* Wait for all your children */
    +    end_time = time(NULL) + 180;
    +    while (nthreads) {
    +	rv = WaitForMultipleObjects(nthreads, child_handles, 0, (end_time - time(NULL)) * 1000);
    +	if (rv != WAIT_TIMEOUT) {
    +	    rv = rv - WAIT_OBJECT_0;
    +	    ap_assert((rv >= 0) && (rv < nthreads));
    +	    cleanup_thread(child_handles, &nthreads, rv);
    +	    continue;
    +	}
    +	break;
    +    }
    +
    +    APD2("process PID %d killing remaining worker threads", my_pid);
    +    for (i = 0; i < nthreads; i++) {
    +	kill_thread(child_handles[i]);
    +	free_thread(child_handles[i]);
    +    }
    +#ifdef UNGRACEFUL_RESTART
    +    ap_assert(CloseHandle(allowed_globals.thread_exit_event));
    +#endif
    +    destroy_semaphore(allowed_globals.jobsemaphore);
    +    ap_destroy_mutex(allowed_globals.jobmutex);
    +
    +    ap_child_exit_modules(pconf, server_conf);
    +    ap_destroy_pool(pchild);
    +
    +    cleanup_scoreboard();
    +
    +    APD2("process PID %d exited", my_pid);
    +    exit(0);
    +}				/* standalone_main */
    +
    +/* Spawn a child Apache process. The child process has the command
    + * line arguments from argc and argv[], plus a -Z argument giving the
    + * name of an event. The child should open and poll or wait on this
    + * event. When it is signalled, the child should die.  prefix is a
    + * prefix string for the event name.
    + * 
    + * The child_num argument on entry contains a serial number for this
    + * child (used to create a unique event name). On exit, this number
    + * will have been incremented by one, ready for the next call.
    + *
    + * On exit, the value pointed to be *ev will contain the event created
    + * to signal the new child process.
    + *
    + * The return value is the handle to the child process if successful,
    + * else -1. If -1 is returned the error will already have been logged
    + * by ap_log_error(). 
    + */
    +
    +int create_event_and_spawn(int argc, char **argv, event **ev, int *child_num, char *prefix)
    +{
    +    char buf[40], mod[200];
    +    int i, rv;
    +    char **pass_argv = (char **) alloca(sizeof(char *) * (argc + 3));
    +
    +    ap_snprintf(buf, sizeof(buf), "%s_%d", prefix, ++(*child_num));
    +    _flushall();
    +    *ev = CreateEvent(NULL, TRUE, FALSE, buf);
    +    if (!*ev) {
    +	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
    +	    "could not create event for child process");
    +	return -1;
    +    }
    +    APD2("create_event_and_spawn(): created process kill event %s", buf);
    +
    +    pass_argv[0] = argv[0];
    +    pass_argv[1] = "-Z";
    +    pass_argv[2] = buf;
    +    for (i = 1; i < argc; i++) {
    +	pass_argv[i + 2] = argv[i];
    +    }
    +    pass_argv[argc + 2] = NULL;
    +
    +    rv = GetModuleFileName(NULL, mod, sizeof(mod));
    +    if (rv == sizeof(mod)) {
    +	/* mod[] was not big enough for our pathname */
    +	ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
    +	    "Internal error: path to Apache process too long");
    +	return -1;
    +    }
    +    if (rv == 0) {
    +	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
    +	    "GetModuleFileName() for current process");
    +	return -1;
    +    }
    +    rv = spawnv(_P_NOWAIT, mod, pass_argv);
    +    if (rv == -1) {
    +	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL,
    +	    "spawn of child process %s failed", mod);
    +	return -1;
    +    }
    +
    +    return rv;
    +}
    +
    +/**********************************************************************
    + * master_main - this is the parent (main) process. We create a
    + * child process to do the work, then sit around waiting for either
    + * the child to exit, or a restart or exit signal. If the child dies,
    + * we just respawn a new one. If we have a shutdown or graceful restart,
    + * tell the child to die when it is ready. If it is a non-graceful
    + * restart, force the child to die immediately.
    + **********************************************************************/
    +
    +#define MAX_PROCESSES 50 /* must be < MAX_WAIT_OBJECTS-1 */
    +
    +void cleanup_process(HANDLE *handles, HANDLE *events, int position, int *processes)
    +{
    +    int i;
    +    int handle = 0;
    +
    +    CloseHandle(handles[position]);
    +    CloseHandle(events[position]);
    +
    +    handle = (int)handles[position];
    +
    +    for (i = position; i < (*processes)-1; i++) {
    +	handles[i] = handles[i + 1];
    +	events[i] = events[i + 1];
    +    }
    +    (*processes)--;
    +
    +    APD4("cleanup_processes: removed child in slot %d handle %d, max=%d", position, handle, *processes);
    +}
    +
    +int create_process(HANDLE *handles, HANDLE *events, int *processes, int *child_num, char *kill_event_name, int argc, char **argv)
    +{
    +    int i = *processes;
    +    HANDLE kill_event;
    +    int child_handle;
    +
    +    child_handle = create_event_and_spawn(argc, argv, &kill_event, child_num, kill_event_name);
    +    if (child_handle <= 0) {
    +	return -1;
    +    }
    +    handles[i] = (HANDLE)child_handle;
    +    events[i] = kill_event;
    +    (*processes)++;
    +
    +    APD4("create_processes: created child in slot %d handle %d, max=%d", 
    +	(*processes)-1, handles[(*processes)-1], *processes);
    +
    +    return 0;
    +}
    +
    +int master_main(int argc, char **argv)
    +{
    +    int nchild = ap_daemons_to_start;
    +    event **ev;
    +    int *child;
    +    int child_num = 0;
    +    int rv, cld;
    +    char buf[100];
    +    int i;
    +    time_t tmstart;
    +    HANDLE signal_event;	/* used to signal shutdown/restart to parent */
    +    HANDLE process_handles[MAX_PROCESSES];
    +    HANDLE process_kill_events[MAX_PROCESSES];
    +    int current_live_processes = 0; /* number of child process we know about */
    +    int processes_to_create = 0;    /* number of child processes to create */
    +    pool *pparent = NULL;  /* pool for the parent process. Cleaned on each restart */
    +
    +    nchild = 1;	    /* only allowed one child process for current generation */
    +    processes_to_create = nchild;
    +
    +    is_graceful = 0;
    +    ++generation;
    +
    +    signal_event = OpenEvent(EVENT_ALL_ACCESS, FALSE, "apache-signal");
    +    if (!signal_event) {
    +	ap_log_error(APLOG_MARK, APLOG_EMERG|APLOG_WIN32ERROR, server_conf,
    +		    "Cannot open apache-signal event");
    +	exit(1);
    +    }
    +
    +    sprintf(buf, "Apache%d", getpid());
    +    start_mutex = ap_create_mutex(buf);
    +    ev = (event **) alloca(sizeof(event *) * nchild);
    +    child = (int *) alloca(sizeof(int) * (nchild+1));
    +
    +    while (processes_to_create--) {
    +	service_set_status(SERVICE_START_PENDING);
    +	if (create_process(process_handles, process_kill_events, 
    +	    ¤t_live_processes, &child_num, buf, argc, argv) < 0) {
    +	    goto die_now;
    +	}
    +    }
    +
    +    service_set_status(SERVICE_RUNNING);
    +
    +    restart_pending = shutdown_pending = 0;
    +
    +    do { /* restart-pending */
    +	if (!is_graceful) {
    +	    ap_restart_time = time(NULL);
    +	}
    +	ap_clear_pool(pconf);
    +	pparent = ap_make_sub_pool(pconf);
    +
    +	server_conf = ap_read_config(pconf, pparent, ap_server_confname);
    +	ap_open_logs(server_conf, pconf);
    +	ap_set_version();
    +	ap_init_modules(pconf, server_conf);
    +	version_locked++;
    +	if (!is_graceful)
    +	    reinit_scoreboard(pconf);
    +
    +	restart_pending = shutdown_pending = 0;
    +
    +	/* Wait for either a child process to die, or for the stop_event
    +	 * to be signalled by the service manager or rpc server */
    +	while (1) {
    +	    /* Next line will block forever until either a child dies, or we
    +	     * get signalled on the "apache-signal" event (e.g. if the user is
    +	     * requesting a shutdown/restart)
    +	     */
    +	    if (current_live_processes == 0) {
    +		/* Shouldn't happen, but better safe than sorry */
    +		ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, server_conf,
    + 			"master_main: no child processes alive! creating one");
    +		if (create_process(process_handles, process_kill_events, 
    +		    ¤t_live_processes, &child_num, buf, argc, argv) < 0) {
    +		    goto die_now;
    +		}
    +		if (processes_to_create) {
    +		    processes_to_create--;
    +		}
    +	    }
    +	    process_handles[current_live_processes] = signal_event;
    +	    rv = WaitForMultipleObjects(current_live_processes+1, (HANDLE *)process_handles, 
    +			FALSE, INFINITE);
    +	    if (rv == WAIT_FAILED) {
    +		/* Something serious is wrong */
    +		ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_WIN32ERROR, server_conf,
    +		    "WaitForMultipeObjects on process handles and apache-signal -- doing shutdown");
    +		shutdown_pending = 1;
    +		break;
    +	    }
    +	    ap_assert(rv != WAIT_TIMEOUT);
    +	    cld = rv - WAIT_OBJECT_0;
    +	    APD4("main process: wait finished, cld=%d handle %d (max=%d)", cld, process_handles[cld], current_live_processes);
    +	    if (cld == current_live_processes) {
    +		/* stop_event is signalled, we should exit now */
    +		if (ResetEvent(signal_event) == 0)
    +		    APD1("main process: *** ERROR: ResetEvent(stop_event) failed ***");
    +		APD3("main process: stop_event signalled: shutdown_pending=%d, restart_pending=%d",
    +		    shutdown_pending, restart_pending);
    +		break;
    +	    }
    +	    ap_assert(cld < current_live_processes);
    +	    cleanup_process(process_handles, process_kill_events, cld, ¤t_live_processes);
    +	    APD2("main_process: child in slot %d died", rv);
    +	    if (processes_to_create) {
    +		create_process(process_handles, process_kill_events, ¤t_live_processes, &child_num, buf, argc, argv);
    +		processes_to_create--;
    +	    }
    +	}
    +	if (!shutdown_pending && !restart_pending) {
    +	    ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO, server_conf,
    +		"master_main: no shutdown or restart variables set -- doing shutdown");
    +	    shutdown_pending = 1;
    +	}
    +	if (shutdown_pending) {
    +	    /* tell all child processes to die */
    +	    for (i = 0; i < current_live_processes; i++) {
    +		APD3("main process: signalling child #%d handle %d to die", i, process_handles[i]);
    +		if (SetEvent(process_kill_events[i]) == 0)
    +		    ap_log_error(APLOG_MARK,APLOG_WIN32ERROR, server_conf,
    +			"SetEvent for child process in slot #%d", i);
    +	    }
    +
    +	    break;
    +	}
    +	if (restart_pending) {
    +	    int children_to_kill = current_live_processes;
    +
    +	    APD1("--- Doing graceful restart ---");
    +
    +	    processes_to_create = nchild;
    +	    for (i = 0; i < nchild; ++i) {
    +		if (current_live_processes >= MAX_PROCESSES)
    +		    break;
    +		create_process(process_handles, process_kill_events, ¤t_live_processes, &child_num, buf, argc, argv);
    +		processes_to_create--;
    +	    }
    +	    for (i = 0; i < children_to_kill; i++) {
    +		APD3("main process: signalling child #%d handle %d to die", i, process_handles[i]);
    +		if (SetEvent(process_kill_events[i]) == 0)
    +		    ap_log_error(APLOG_MARK,APLOG_WIN32ERROR, server_conf,
    + 			"SetEvent for child process in slot #%d", i);
    +	    }
    +	}
    +	++generation;
    +    } while (restart_pending);
    +
    +    /* If we dropped out of the loop we definitly want to die completely. We need to
    +     * make sure we wait for all the child process to exit first.
    +     */
    +
    +    APD2("*** main process shutdown, processes=%d ***", current_live_processes);
    +
    +die_now:
    +    CloseHandle(signal_event);
    +
    +    tmstart = time(NULL);
    +    while (current_live_processes && ((tmstart+60) > time(NULL))) {
    +	service_set_status(SERVICE_STOP_PENDING);
    +	rv = WaitForMultipleObjects(current_live_processes, (HANDLE *)process_handles, FALSE, 2000);
    +	if (rv == WAIT_TIMEOUT)
    +	    continue;
    +	ap_assert(rv != WAIT_FAILED);
    +	cld = rv - WAIT_OBJECT_0;
    +	ap_assert(rv < current_live_processes);
    +	APD4("main_process: child in #%d handle %d died, left=%d", 
    +	    rv, process_handles[rv], current_live_processes);
    +	cleanup_process(process_handles, process_kill_events, cld, ¤t_live_processes);
    +    }
    +    for (i = 0; i < current_live_processes; i++) {
    +	ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, server_conf,
    + 	    "forcing termination of child #%d (handle %d)", i, process_handles[i]);
    +	TerminateProcess((HANDLE) process_handles[i], 1);
    +    }
    +    service_set_status(SERVICE_STOPPED);
    +
    +    if (pparent) {
    +	ap_destroy_pool(pparent);
    +    }
    +
    +    ap_destroy_mutex(start_mutex);
    +    return (0);
    +}
    +
    +#ifdef WIN32
    +__declspec(dllexport)
    +     int apache_main(int argc, char *argv[])
    +#else
    +int REALMAIN(int argc, char *argv[]) 
    +#endif
    +{
    +    int c;
    +    int child = 0;
    +    char *cp;
    +    int run_as_service = 1;
    +    int install = 0;
    +    
    +    common_init();
    +
    +    ap_server_argv0 = argv[0];
    +
    +    /* Get the serverroot from the registry, if it exists. This can be
    +     * overridden by a command line -d argument.
    +     */
    +    if (ap_registry_get_server_root(pconf, ap_server_root, sizeof(ap_server_root)) < 0) {
    +	/* The error has already been logged. Actually it won't have been,
    +	 * because we haven't read the config files to find out where our 
    +	 * error log is. But we can't just ignore the error since we might
    +	 * end up using totally the wrong server root.
    +	 */
    +	exit(1);
    +    }
    +
    +    if (!*ap_server_root) {
    +	ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root));
    +    }
    +    ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname));
    +
    +    ap_setup_prelinked_modules();
    +
    +    while ((c = getopt(argc, argv, "C:c:Xd:f:vVhlZ:iusS")) != -1) {
    +        char **new;
    +	switch (c) {
    +	case 'c':
    +	    new = (char **)ap_push_array(ap_server_post_read_config);
    +	    *new = ap_pstrdup(pcommands, optarg);
    +	    break;
    +	case 'C':
    +	    new = (char **)ap_push_array(ap_server_pre_read_config);
    +	    *new = ap_pstrdup(pcommands, optarg);
    +	    break;
    +#ifdef WIN32
    +	case 'Z':
    +	    exit_event = open_event(optarg);
    +	    APD2("child: opened process event %s", optarg);
    +	    cp = strchr(optarg, '_');
    +	    ap_assert(cp);
    +	    *cp = 0;
    +	    start_mutex = ap_open_mutex(optarg);
    +	    child = 1;
    +	    break;
    +	case 'i':
    +	    install = 1;
    +	    break;
    +	case 'u':
    +	    install = -1;
    +	    break;
    +	case 's':
    +	    run_as_service = 0;
    +	    break;
    +	case 'S':
    +	    ap_dump_settings = 1;
    +	    break;
    +#endif /* WIN32 */
    +	case 'd':
    +	    ap_cpystrn(ap_server_root, ap_os_canonical_filename(pconf, optarg), sizeof(ap_server_root));
    +	    break;
    +	case 'f':
    +	    ap_cpystrn(ap_server_confname, ap_os_canonical_filename(pconf, optarg), sizeof(ap_server_confname));
    +	    break;
    +	case 'v':
    +	    ap_set_version();
    +	    printf("Server version: %s\n", ap_get_server_version());
    +	    printf("Server built:   %s\n", ap_get_server_built());
    +	    exit(0);
    +	case 'V':
    +	    ap_set_version();
    +	    show_compile_settings();
    +	    exit(0);
    +	case 'h':
    +	    ap_show_directives();
    +	    exit(0);
    +	case 'l':
    +	    ap_show_modules();
    +	    exit(0);
    +	case 'X':
    +	    ++one_process;	/* Weird debugging mode. */
    +	    break;
    +	case '?':
    +	    usage(argv[0]);
    +	}
    +    }
    +
    +    if (!child && run_as_service) {
    +	service_cd();
    +    }
    +
    +    server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
    +    if (!child) {
    +	ap_log_pid(pconf, ap_pid_fname);
    +    }
    +    ap_set_version();
    +    ap_init_modules(pconf, server_conf);
    +    ap_suexec_enabled = init_suexec();
    +    version_locked++;
    +    ap_open_logs(server_conf, pconf);
    +    set_group_privs();
    +
    +#ifdef __EMX__
    +    printf("%s \n", ap_get_server_version());
    +#endif
    +#ifdef WIN32
    +    if (!child) {
    +	printf("%s \n", ap_get_server_version());
    +    }
    +#endif
    +
    +    if (one_process && !exit_event)
    +	exit_event = create_event(0, 0, NULL);
    +    if (one_process && !start_mutex)
    +	start_mutex = ap_create_mutex(NULL);
    +    /*
    +     * In the future, the main will spawn off a couple
    +     * of children and monitor them. As soon as a child
    +     * exits, it spawns off a new one
    +     */
    +    if (child || one_process) {
    +	if (!exit_event || !start_mutex)
    +	    exit(-1);
    +	worker_main();
    +	ap_destroy_mutex(start_mutex);
    +	destroy_event(exit_event);
    +    }
    +    else {
    +	service_main(master_main, argc, argv,
    +			"Apache", install, run_as_service);
    +    }
    +
    +    return (0);
    +}
    +
    +#endif /* ndef MULTITHREAD */
    +
    +#else  /* ndef SHARED_CORE_TIESTATIC */
    +
    +/*
    +**  Standalone Tie Program for Shared Core support
    +**
    +**  It's purpose is to tie the static libraries and 
    +**  the shared core library under link-time and  
    +**  passing execution control to the real main function
    +**  in the shared core library under run-time.
    +*/
    +
    +int main(int argc, char *argv[]) 
    +{
    +    extern int ap_main(int argc, char *argv[]);
    +    return ap_main(argc, argv);
    +}
    +
    +#endif /* ndef SHARED_CORE_TIESTATIC */
    +#else  /* ndef SHARED_CORE_BOOTSTRAP */
    +
    +/*
    +**  Standalone Bootstrap Program for Shared Core support
    +**
    +**  It's purpose is to initialise the LD_LIBRARY_PATH
    +**  environment variable therewith the Unix loader is able
    +**  to start the Standalone Tie Program (see above)
    +**  and then replacing itself with this program by
    +**  immediately passing execution to it.
    +*/
    +
    +#include <stdio.h>
    +#include <stdlib.h>
    +#include <string.h>
    +
    +#include "conf.h"
    +#include "httpd.h"
    +
    +#define VARNAME "LD_LIBRARY_PATH"
    +
    +#ifndef SHARED_CORE_DIR 
    +#define SHARED_CORE_DIR HTTPD_ROOT "/libexec"
    +#endif
    +
    +#ifndef SHARED_CORE_EXECUTABLE_PROGRAM
    +#define SHARED_CORE_EXECUTABLE_PROGRAM "libhttpd.ep"
    +#endif
    +
    +int main(int argc, char *argv[], char *envp[]) 
    +{
    +    extern char *optarg;
    +    extern int optind;
    +    char prog[MAX_STRING_LEN];
    +    char llp_buf[MAX_STRING_LEN];
    +    char **llp_slot;
    +    char *llp_existing;
    +    char *llp_dir;
    +    char **envpnew;
    +    int c, i, l;
    +
    +    /* 
    +     * parse argument line, 
    +     * but only handle the -L option 
    +     */
    +    llp_dir = SHARED_CORE_DIR;
    +    while ((c = getopt(argc, argv, "C:c:Xd:f:vVhlL:Z:")) != -1) {
    +	switch (c) {
    +	case 'C':
    +	case 'c':
    +	case 'X':
    +	case 'd':
    +	case 'f':
    +	case 'v':
    +	case 'V':
    +	case 'h':
    +	case 'l':
    +	case 'Z':
    +	case '?':
    +	    break;
    +	case 'L':
    +	    llp_dir = strdup(optarg);
    +	    break;
    +	}
    +    }
    +
    +    /* 
    +     * create path to SHARED_CORE_EXECUTABLE_PROGRAM
    +     */
    +    sprintf(prog, "%s/%s", llp_dir, SHARED_CORE_EXECUTABLE_PROGRAM);
    +
    +    /* 
    +     * adjust process environment therewith the Unix loader 
    +     * is able to start the SHARED_CORE_EXECUTABLE_PROGRAM.
    +     */
    +    llp_slot = NULL;
    +    llp_existing = NULL;
    +    l = strlen(VARNAME);
    +    for (i = 0; envp[i] != NULL; i++) {
    +	if (strncmp(envp[i], VARNAME "=", l+1) == 0) {
    +	    llp_slot = &envp[i];
    +	    llp_existing = strchr(envp[i], '=') + 1;
    +	}
    +    }
    +    if (llp_slot == NULL) {
    +	envpnew = (char **)malloc(sizeof(char *)*(i + 2));
    +	memcpy(envpnew, envp, sizeof(char *)*i);
    +	envp = envpnew;
    +	llp_slot = &envp[i++];
    +	envp[i] = NULL;
    +    }
    +    if (llp_existing != NULL)
    +	 sprintf(llp_buf, "%s=%s:%s", VARNAME, llp_dir, llp_existing);
    +    else
    +	 sprintf(llp_buf, "%s=%s", VARNAME, llp_dir);
    +    *llp_slot = strdup(llp_buf);
    +
    +    /* 
    +     * finally replace our process with 
    +     * the SHARED_CORE_EXECUTABLE_PROGRAM
    +     */
    +    if (execve(prog, argv, envp) == -1) {
    +	fprintf(stderr, 
    +		"httpd: Unable to exec Shared Core Executable Program `%s'\n",
    +		prog);
    +	return 1;
    +    }
    +    else
    +	return 0;
    +}
    +
    +#endif /* ndef SHARED_CORE_BOOTSTRAP */
    +
    diff --git a/APACHE_1_3b7/src/main/http_protocol.c b/APACHE_1_3b7/src/main/http_protocol.c
    new file mode 100644
    index 0000000000..a894c3fcc5
    --- /dev/null
    +++ b/APACHE_1_3b7/src/main/http_protocol.c
    @@ -0,0 +1,2183 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1998 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/>.
    + *
    + */
    +
    +/*
    + * http_protocol.c --- routines which directly communicate with the client.
    + *
    + * Code originally by Rob McCool; much redone by Robert S. Thau
    + * and the Apache Group.
    + */
    +
    +#define CORE_PRIVATE
    +#include "httpd.h"
    +#include "http_config.h"
    +#include "http_core.h"
    +#include "http_protocol.h"
    +#include "http_main.h"
    +#include "http_request.h"
    +#include "http_vhost.h"
    +#include "http_log.h"           /* For errors detected in basic auth common
    +                                 * support code... */
    +#include "util_date.h"          /* For parseHTTPdate and BAD_DATE */
    +#include <stdarg.h>
    +#include "http_conf_globals.h"
    +
    +#define SET_BYTES_SENT(r) \
    +  do { if (r->sent_bodyct) \
    +          ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
    +  } while (0)
    +
    +
    +static int parse_byterange(char *range, long clength, long *start, long *end)
    +{
    +    char *dash = strchr(range, '-');
    +
    +    if (!dash)
    +        return 0;
    +
    +    if ((dash == range)) {
    +        /* In the form "-5" */
    +        *start = clength - atol(dash + 1);
    +        *end = clength - 1;
    +    }
    +    else {
    +        *dash = '\0';
    +        dash++;
    +        *start = atol(range);
    +        if (*dash)
    +            *end = atol(dash);
    +        else                    /* "5-" */
    +            *end = clength - 1;
    +    }
    +
    +    if (*start < 0)
    +	*start = 0;
    +
    +    if (*end >= clength)
    +        *end = clength - 1;
    +
    +    if (*start > *end)
    +	return 0;
    +
    +    return (*start > 0 || *end < clength - 1);
    +}
    +
    +static int internal_byterange(int, long *, request_rec *, char **, long *,
    +                              long *);
    +
    +API_EXPORT(int) ap_set_byterange(request_rec *r)
    +{
    +    char *range, *if_range, *match;
    +    long range_start, range_end;
    +
    +    if (!r->clength || r->assbackwards)
    +        return 0;
    +
    +    /* Check for Range request-header (HTTP/1.1) or Request-Range for
    +     * backwards-compatibility with second-draft Luotonen/Franks
    +     * byte-ranges (e.g. Netscape Navigator 2-3).
    +     *
    +     * We support this form, with Request-Range, and (farther down) we
    +     * send multipart/x-byteranges instead of multipart/byteranges for
    +     * Request-Range based requests to work around a bug in Netscape
    +     * Navigator 2-3 and MSIE 3.
    +     */
    +
    +    if (!(range = ap_table_get(r->headers_in, "Range")))
    +        range = ap_table_get(r->headers_in, "Request-Range");
    +
    +    if (!range || strncasecmp(range, "bytes=", 6)) {
    +        return 0;
    +    }
    +
    +    /* Check the If-Range header for Etag or Date */
    +
    +    if ((if_range = ap_table_get(r->headers_in, "If-Range"))) {
    +        if (if_range[0] == '"') {
    +            if (!(match = ap_table_get(r->headers_out, "Etag")) ||
    +                (strcasecmp(if_range, match) != 0))
    +                return 0;
    +        }
    +        else if (!(match = ap_table_get(r->headers_out, "Last-Modified")) ||
    +                 (strcasecmp(if_range, match) != 0))
    +            return 0;
    +    }
    +
    +    if (!strchr(range, ',')) {
    +        /* A single range */
    +        if (!parse_byterange(ap_pstrdup(r->pool, range + 6), r->clength,
    +                             &range_start, &range_end))
    +            return 0;
    +
    +        r->byterange = 1;
    +
    +        ap_table_setn(r->headers_out, "Content-Range",
    +	    ap_psprintf(r->pool, "bytes %ld-%ld/%ld",
    +		range_start, range_end, r->clength));
    +        ap_table_setn(r->headers_out, "Content-Length",
    +	    ap_psprintf(r->pool, "%ld", range_end - range_start + 1));
    +    }
    +    else {
    +        /* a multiple range */
    +        char *r_range = ap_pstrdup(r->pool, range + 6);
    +        long tlength = 0;
    +
    +        r->byterange = 2;
    +        r->boundary = ap_psprintf(r->pool, "%lx%lx",
    +				r->request_time, (long) getpid());
    +        while (internal_byterange(0, &tlength, r, &r_range, NULL, NULL));
    +        ap_table_setn(r->headers_out, "Content-Length",
    +	    ap_psprintf(r->pool, "%ld", tlength));
    +    }
    +
    +    r->status = PARTIAL_CONTENT;
    +    r->range = range + 6;
    +
    +    return 1;
    +}
    +
    +API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length)
    +{
    +    return internal_byterange(1, NULL, r, &r->range, offset, length);
    +}
    +
    +/* If this function is called with realreq=1, it will spit out
    + * the correct headers for a byterange chunk, and set offset and
    + * length to the positions they should be.
    + *
    + * If it is called with realreq=0, it will add to tlength the length
    + * it *would* have used with realreq=1.
    + *
    + * Either case will return 1 if it should be called again, and 0
    + * when done.
    + */
    +static int internal_byterange(int realreq, long *tlength, request_rec *r,
    +                              char **r_range, long *offset, long *length)
    +{
    +    long range_start, range_end;
    +    char *range;
    +
    +    if (!**r_range) {
    +        if (r->byterange > 1) {
    +            if (realreq)
    +                ap_rvputs(r, "\015\012--", r->boundary, "--\015\012", NULL);
    +            else
    +                *tlength += 4 + strlen(r->boundary) + 4;
    +        }
    +        return 0;
    +    }
    +
    +    range = ap_getword_nc(r->pool, r_range, ',');
    +    if (!parse_byterange(range, r->clength, &range_start, &range_end))
    +        /* Skip this one */
    +        return internal_byterange(realreq, tlength, r, r_range, offset,
    +                                  length);
    +
    +    if (r->byterange > 1) {
    +        char *ct = r->content_type ? r->content_type : ap_default_type(r);
    +        char ts[MAX_STRING_LEN];
    +
    +        ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", range_start, range_end,
    +                    r->clength);
    +        if (realreq)
    +            ap_rvputs(r, "\015\012--", r->boundary, "\015\012Content-type: ",
    +                   ct, "\015\012Content-range: bytes ", ts, "\015\012\015\012",
    +                   NULL);
    +        else
    +            *tlength += 4 + strlen(r->boundary) + 16 + strlen(ct) + 23 +
    +                        strlen(ts) + 4;
    +    }
    +
    +    if (realreq) {
    +        *offset = range_start;
    +        *length = range_end - range_start + 1;
    +    }
    +    else {
    +        *tlength += range_end - range_start + 1;
    +    }
    +    return 1;
    +}
    +
    +API_EXPORT(int) ap_set_content_length(request_rec *r, long clength)
    +{
    +    r->clength = clength;
    +    ap_table_setn(r->headers_out, "Content-Length", ap_psprintf(r->pool, "%ld", clength));
    +    return 0;
    +}
    +
    +API_EXPORT(int) ap_set_keepalive(request_rec *r)
    +{
    +    int ka_sent = 0;
    +    int wimpy = ap_find_token(r->pool,
    +                           ap_table_get(r->headers_out, "Connection"), "close");
    +    char *conn = ap_table_get(r->headers_in, "Connection");
    +
    +    /* The following convoluted conditional determines whether or not
    +     * the current connection should remain persistent after this response
    +     * (a.k.a. HTTP Keep-Alive) and whether or not the output message
    +     * body should use the HTTP/1.1 chunked transfer-coding.  In English,
    +     *
    +     *   IF  we have not marked this connection as errored;
    +     *   and the response body has a defined length due to the status code
    +     *       being 304 or 204, the request method being HEAD, already
    +     *       having defined Content-Length or Transfer-Encoding: chunked, or
    +     *       the request version being HTTP/1.1 and thus capable of being set
    +     *       as chunked [we know the (r->chunked = 1) side-effect is ugly];
    +     *   and the server configuration enables keep-alive;
    +     *   and the server configuration has a reasonable inter-request timeout;
    +     *   and there is no maximum # requests or the max hasn't been reached;
    +     *   and the response status does not require a close;
    +     *   and the response generator has not already indicated close;
    +     *   and the client did not request non-persistence (Connection: close);
    +     *   and    we haven't been configured to ignore the buggy twit
    +     *       or they're a buggy twit coming through a HTTP/1.1 proxy
    +     *   and    the client is requesting an HTTP/1.0-style keep-alive
    +     *       or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
    +     *   THEN we can be persistent, which requires more headers be output.
    +     *
    +     * Note that the condition evaluation order is extremely important.
    +     */
    +    if ((r->connection->keepalive != -1) &&
    +        ((r->status == HTTP_NOT_MODIFIED) ||
    +         (r->status == HTTP_NO_CONTENT) ||
    +         r->header_only ||
    +         ap_table_get(r->headers_out, "Content-Length") ||
    +         ap_find_last_token(r->pool,
    +                         ap_table_get(r->headers_out, "Transfer-Encoding"),
    +                         "chunked") ||
    +         ((r->proto_num >= HTTP_VERSION(1,1)) && (r->chunked = 1))) &&
    +        r->server->keep_alive &&
    +        (r->server->keep_alive_timeout > 0) &&
    +        ((r->server->keep_alive_max == 0) ||
    +         (r->server->keep_alive_max > r->connection->keepalives)) &&
    +        !status_drops_connection(r->status) &&
    +        !wimpy &&
    +        !ap_find_token(r->pool, conn, "close") &&
    +        (!ap_table_get(r->subprocess_env, "nokeepalive") ||
    +         ap_table_get(r->headers_in, "Via")) &&
    +        ((ka_sent = ap_find_token(r->pool, conn, "keep-alive")) ||
    +         (r->proto_num >= HTTP_VERSION(1,1)))
    +       ) {
    +        int left = r->server->keep_alive_max - r->connection->keepalives;
    +
    +        r->connection->keepalive = 1;
    +        r->connection->keepalives++;
    +
    +        /* If they sent a Keep-Alive token, send one back */
    +        if (ka_sent) {
    +            if (r->server->keep_alive_max)
    +		ap_table_setn(r->headers_out, "Keep-Alive",
    +		    ap_psprintf(r->pool, "timeout=%d, max=%d",
    +                            r->server->keep_alive_timeout, left));
    +            else
    +		ap_table_setn(r->headers_out, "Keep-Alive",
    +		    ap_psprintf(r->pool, "timeout=%d",
    +                            r->server->keep_alive_timeout));
    +            ap_table_mergen(r->headers_out, "Connection", "Keep-Alive");
    +        }
    +
    +        return 1;
    +    }
    +
    +    /* Otherwise, we need to indicate that we will be closing this
    +     * connection immediately after the current response.
    +     *
    +     * We only really need to send "close" to HTTP/1.1 clients, but we
    +     * always send it anyway, because a broken proxy may identify itself
    +     * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
    +     * to a HTTP/1.1 client. Better safe than sorry.
    +     */
    +    if (!wimpy)
    +	ap_table_mergen(r->headers_out, "Connection", "close");
    +
    +    r->connection->keepalive = 0;
    +
    +    return 0;
    +}
    +
    +/*
    + * Return the latest rational time from a request/mtime (modification time)
    + * pair.  We return the mtime unless it's in the future, in which case we
    + * return the current time.  We use the request time as a reference in order
    + * to limit the number of calls to time().  We don't check for futurosity
    + * unless the mtime is at least as new as the reference.
    + */
    +API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime)
    +{
    +    time_t now;
    +
    +    /* For all static responses, it's almost certain that the file was
    +     * last modified before the beginning of the request.  So there's
    +     * no reason to call time(NULL) again.  But if the response has been
    +     * created on demand, then it might be newer than the time the request
    +     * started.  In this event we really have to call time(NULL) again
    +     * so that we can give the clients the most accurate Last-Modified.  If we
    +     * were given a time in the future, we return the current time - the
    +     * Last-Modified can't be in the future.
    +     */
    +    now = (mtime < r->request_time) ? r->request_time : time(NULL);
    +    return (mtime > now) ? now : mtime;
    +}
    +
    +API_EXPORT(int) ap_meets_conditions(request_rec *r)
    +{
    +    char *etag = ap_table_get(r->headers_out, "ETag");
    +    char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
    +    time_t mtime;
    +
    +    /* Check for conditional requests --- note that we only want to do
    +     * this if we are successful so far and we are not processing a
    +     * subrequest or an ErrorDocument.
    +     *
    +     * The order of the checks is important, since ETag checks are supposed
    +     * to be more accurate than checks relative to the modification time.
    +     * However, not all documents are guaranteed to *have* ETags, and some
    +     * might have Last-Modified values w/o ETags, so this gets a little
    +     * complicated.
    +     */
    +
    +    if (!is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
    +        return OK;
    +    }
    +
    +    mtime = (r->mtime != 0) ? r->mtime : time(NULL);
    +
    +    /* If an If-Match request-header field was given
    +     * AND if our ETag does not match any of the entity tags in that field
    +     * AND the field value is not "*" (meaning match anything), then
    +     *     respond with a status of 412 (Precondition Failed).
    +     */
    +    if ((if_match = ap_table_get(r->headers_in, "If-Match")) != NULL) {
    +        if ((etag == NULL) ||
    +            ((if_match[0] != '*') && !ap_find_token(r->pool, if_match, etag))) {
    +            return HTTP_PRECONDITION_FAILED;
    +        }
    +    }
    +    else {
    +        /* Else if a valid If-Unmodified-Since request-header field was given
    +         * AND the requested resource has been modified since the time
    +         * specified in this field, then the server MUST
    +         *     respond with a status of 412 (Precondition Failed).
    +         */
    +        if_unmodified = ap_table_get(r->headers_in, "If-Unmodified-Since");
    +        if (if_unmodified != NULL) {
    +            time_t ius = ap_parseHTTPdate(if_unmodified);
    +
    +            if ((ius != BAD_DATE) && (mtime > ius)) {
    +                return HTTP_PRECONDITION_FAILED;
    +            }
    +        }
    +    }
    +
    +    /* If an If-None-Match request-header field was given
    +     * AND if our ETag matches any of the entity tags in that field
    +     * OR if the field value is "*" (meaning match anything), then
    +     *    if the request method was GET or HEAD, the server SHOULD
    +     *       respond with a 304 (Not Modified) response.
    +     *    For all other request methods, the server MUST
    +     *       respond with a status of 412 (Precondition Failed).
    +     */
    +    if_nonematch = ap_table_get(r->headers_in, "If-None-Match");
    +    if (if_nonematch != NULL) {
    +        int rstatus;
    +
    +        if ((if_nonematch[0] == '*')
    +            || ((etag != NULL) && ap_find_token(r->pool, if_nonematch, etag))) {
    +            rstatus = (r->method_number == M_GET) ? HTTP_NOT_MODIFIED
    +                                                  : HTTP_PRECONDITION_FAILED;
    +            return rstatus;
    +        }
    +    }
    +    /* Else if a valid If-Modified-Since request-header field was given
    +     * AND it is a GET or HEAD request
    +     * AND the requested resource has not been modified since the time
    +     * specified in this field, then the server MUST
    +     *    respond with a status of 304 (Not Modified).
    +     * A date later than the server's current request time is invalid.
    +     */
    +    else if ((r->method_number == M_GET)
    +             && ((if_modified_since =
    +                  ap_table_get(r->headers_in, "If-Modified-Since")) != NULL)) {
    +        time_t ims = ap_parseHTTPdate(if_modified_since);
    +
    +        if ((ims >= mtime) && (ims <= r->request_time)) {
    +            return HTTP_NOT_MODIFIED;
    +        }
    +    }
    +    return OK;
    +}
    +
    +/*
    + * Construct an entity tag (ETag) from resource information.  If it's a real
    + * file, build in some of the file characteristics.  If the modification time
    + * is newer than (request-time minus 1 second), mark the ETag as weak - it
    + * could be modified again in as short an interval.  We rationalize the
    + * modification time we're given to keep it from being in the future.
    + */
    +API_EXPORT(void) ap_set_etag(request_rec *r)
    +{
    +    char *etag;
    +    char *weak;
    +
    +    /*
    +     * Make an ETag header out of various pieces of information. We use
    +     * the last-modified date and, if we have a real file, the
    +     * length and inode number - note that this doesn't have to match
    +     * the content-length (i.e. includes), it just has to be unique
    +     * for the file.
    +     *
    +     * If the request was made within a second of the last-modified date,
    +     * we send a weak tag instead of a strong one, since it could
    +     * be modified again later in the second, and the validation
    +     * would be incorrect.
    +     */
    +    
    +    weak = (r->request_time - r->mtime > 1) ? "" : "W/";
    +
    +    if (r->finfo.st_mode != 0) {
    +	etag = ap_psprintf(r->pool,
    +		    "%s\"%lx-%lx-%lx\"", weak,
    +                    (unsigned long) r->finfo.st_ino,
    +                    (unsigned long) r->finfo.st_size,
    +                    (unsigned long) r->mtime);
    +    }
    +    else {
    +        etag = ap_psprintf(r->pool, "%s\"%lx\"", weak,
    +                    (unsigned long) r->mtime);
    +    }
    +
    +    ap_table_setn(r->headers_out, "ETag", etag);
    +}
    +
    +/*
    + * This function sets the Last-Modified output header field to the value
    + * of the mtime field in the request structure - rationalized to keep it from
    + * being in the future.
    + */
    +API_EXPORT(void) ap_set_last_modified(request_rec *r)
    +{
    +    time_t mod_time = ap_rationalize_mtime(r, r->mtime);
    +
    +    ap_table_setn(r->headers_out, "Last-Modified",
    +              ap_gm_timestr_822(r->pool, mod_time));
    +}
    +
    +/* Get a line of protocol input, including any continuation lines
    + * caused by MIME folding (or broken clients) if fold != 0, and place it
    + * in the buffer s, of size n bytes, without the ending newline.
    + *
    + * Returns -1 on error, or the length of s.
    + *
    + * Note: Because bgets uses 1 char for newline and 1 char for NUL,
    + *       the most we can get is (n - 2) actual characters if it
    + *       was ended by a newline, or (n - 1) characters if the line
    + *       length exceeded (n - 1).  So, if the result == (n - 1),
    + *       then the actual input line exceeded the buffer length,
    + *       and it would be a good idea for the caller to puke 400 or 414.
    + */
    +static int getline(char *s, int n, BUFF *in, int fold)
    +{
    +    char *pos, next;
    +    int retval;
    +    int total = 0;
    +
    +    pos = s;
    +
    +    do {
    +        retval = ap_bgets(pos, n, in);     /* retval == -1 if error, 0 if EOF */
    +
    +        if (retval <= 0)
    +            return ((retval < 0) && (total == 0)) ? -1 : total;
    +
    +        /* retval is the number of characters read, not including NUL      */
    +
    +        n -= retval;            /* Keep track of how much of s is full     */
    +        pos += (retval - 1);    /* and where s ends                        */
    +        total += retval;        /* and how long s has become               */
    +
    +        if (*pos == '\n') {     /* Did we get a full line of input?        */
    +            *pos = '\0';
    +            --total;
    +            ++n;
    +        }
    +        else
    +            return total;       /* if not, input line exceeded buffer size */
    +
    +        /* Continue appending if line folding is desired and
    +         * the last line was not empty and we have room in the buffer and
    +         * the next line begins with a continuation character.
    +         */
    +    } while (fold && (retval != 1) && (n > 1)
    +                  && (ap_blookc(&next, in) == 1)
    +                  && ((next == ' ') || (next == '\t')));
    +
    +    return total;
    +}
    +
    +/* parse_uri: break apart the uri
    + * Side Effects:
    + * - sets r->args to rest after '?' (or NULL if no '?')
    + * - sets r->uri to request uri (without r->args part)
    + * - sets r->hostname (if not set already) from request (scheme://host:port)
    + */
    +CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri)
    +{
    +    int status = HTTP_OK;
    +
    +    r->unparsed_uri = ap_pstrdup(r->pool, uri);
    +
    +    if (r->method_number == M_CONNECT) {
    +	status = ap_parse_hostinfo_components(r->pool, uri, &r->parsed_uri);
    +    } else {
    +	/* Simple syntax Errors in URLs are trapped by parse_uri_components(). */
    +	status = ap_parse_uri_components(r->pool, uri, &r->parsed_uri);
    +    }
    +
    +    if (is_HTTP_SUCCESS(status)) {
    +	/* if it has a scheme we may need to do absoluteURI vhost stuff */
    +	if (r->parsed_uri.scheme
    +	    && !strcasecmp(r->parsed_uri.scheme, http_method(r))) {
    +	    r->hostname = r->parsed_uri.hostname;
    +	} else if (r->method_number == M_CONNECT) {
    +	    r->hostname = r->parsed_uri.hostname;
    +	}
    +	r->args = r->parsed_uri.query;
    +	r->uri = r->parsed_uri.path ? r->parsed_uri.path
    +				    : ap_pstrdup(r->pool, "/");
    +#if defined(__EMX__) || defined(WIN32)
    +	/* Handle path translations for OS/2 and plug security hole.
    +	 * This will prevent "http://www.wherever.com/..\..\/" from
    +	 * returning a directory for the root drive.
    +	 */
    +	{
    +	    char *x;
    +
    +	    for (x = r->uri; (x = strchr(x, '\\')) != NULL; )
    +		*x = '/';
    +#ifndef WIN32   /* for OS/2 only: */
    +	    /* Fix OS/2 HPFS filename case problem. */
    +	    ap_str_tolower(r->uri);
    +#endif
    +	}
    +#endif  /* __EMX__ || WIN32 */
    +    }
    +    else {
    +	r->args = NULL;
    +	r->hostname = NULL;
    +	r->status = status;             /* set error status */
    +	r->uri = ap_pstrdup(r->pool, uri);
    +    }
    +}
    +
    +static int read_request_line(request_rec *r)
    +{
    +    char l[HUGE_STRING_LEN];
    +    const char *ll = l, *uri;
    +    conn_rec *conn = r->connection;
    +    int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
    +    int len;
    +
    +    /* Read past empty lines until we get a real request line,
    +     * a read error, the connection closes (EOF), or we timeout.
    +     *
    +     * We skip empty lines because browsers have to tack a CRLF on to the end
    +     * of POSTs to support old CERN webservers.  But note that we may not
    +     * have flushed any previous response completely to the client yet.
    +     * We delay the flush as long as possible so that we can improve
    +     * performance for clients that are pipelining requests.  If a request
    +     * is pipelined then we won't block during the (implicit) read() below.
    +     * If the requests aren't pipelined, then the client is still waiting
    +     * for the final buffer flush from us, and we will block in the implicit
    +     * read().  B_SAFEREAD ensures that the BUFF layer flushes if it will
    +     * have to block during a read.
    +     */
    +    ap_bsetflag(conn->client, B_SAFEREAD, 1);
    +    while ((len = getline(l, HUGE_STRING_LEN, conn->client, 0)) <= 0) {
    +        if ((len < 0) || bgetflag(conn->client, B_EOF)) {
    +            ap_bsetflag(conn->client, B_SAFEREAD, 0);
    +            return 0;
    +        }
    +    }
    +    /* we've probably got something to do, ignore graceful restart requests */
    +#ifdef SIGUSR1
    +    signal(SIGUSR1, SIG_IGN);
    +#endif                          /* SIGUSR1 */
    +    ap_bsetflag(conn->client, B_SAFEREAD, 0);
    +    if (len == (HUGE_STRING_LEN - 1)) {
    +        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
    +                    "request failed for %s, reason: URI too long",
    +            ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME));
    +	/* hack to deal with the HTTP_REQUEST_TIME_OUT setting up above: */
    +	if (r->status == HTTP_REQUEST_TIME_OUT)
    +	  r->status = HTTP_OK;
    +	r->request_time = time(NULL);
    +	ap_die (HTTP_REQUEST_URI_TOO_LARGE, r);
    +        return 0;
    +    }
    +
    +    r->request_time = time(NULL);
    +    r->the_request = ap_pstrdup(r->pool, l);
    +    r->method = ap_getword_white(r->pool, &ll);
    +    uri = ap_getword_white(r->pool, &ll);
    +
    +    /* Provide quick information about the request method as soon as known */
    +    if (!strcmp(r->method, "HEAD")) {
    +        r->header_only = 1;
    +        r->method_number = M_GET;
    +    }
    +    else if (!strcmp(r->method, "GET"))
    +        r->method_number = M_GET;
    +    else if (!strcmp(r->method, "POST"))
    +        r->method_number = M_POST;
    +    else if (!strcmp(r->method, "PUT"))
    +        r->method_number = M_PUT;
    +    else if (!strcmp(r->method, "DELETE"))
    +        r->method_number = M_DELETE;
    +    else if (!strcmp(r->method, "CONNECT"))
    +        r->method_number = M_CONNECT;
    +    else if (!strcmp(r->method, "OPTIONS"))
    +        r->method_number = M_OPTIONS;
    +    else if (!strcmp(r->method, "TRACE"))
    +        r->method_number = M_TRACE;
    +    else
    +        r->method_number = M_INVALID;   /* Will eventually croak. */
    +
    +    ap_parse_uri(r, uri);
    +
    +    r->assbackwards = (ll[0] == '\0');
    +    r->protocol = ap_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9");
    +    if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor)
    +      && minor < HTTP_VERSION(1,0))	/* don't allow HTTP/0.1000 */
    +	r->proto_num = HTTP_VERSION(major, minor);
    +    else
    +	r->proto_num = HTTP_VERSION(1,0);
    +
    +    return 1;
    +}
    +
    +static void get_mime_headers(request_rec *r)
    +{
    +    conn_rec *c = r->connection;
    +    int len;
    +    char *value;
    +    char field[MAX_STRING_LEN];
    +
    +    /*
    +     * Read header lines until we get the empty separator line, a read error,
    +     * the connection closes (EOF), or we timeout. Should we also check for
    +     * overflow (len == MAX_STRING_LEN-1)?
    +     */
    +    while ((len = getline(field, MAX_STRING_LEN, c->client, 1)) > 0) {
    +        char *copy = ap_palloc(r->pool, len + 1);
    +        memcpy(copy, field, len + 1);
    +	
    +	if (!(value = strchr(copy, ':'))) {     /* Find the colon separator */
    +	  /* if there's none, this request is screwed up.
    +	   * a hack to deal with how we set HTTP_REQUEST_TIME_OUT earlier.*/
    +	  if (r->status == HTTP_REQUEST_TIME_OUT)
    +	    r->status = HTTP_OK;
    +	  
    +	  ap_die (HTTP_BAD_REQUEST, r);
    +	  return;
    +	}
    +
    +        *value = '\0';
    +        ++value;
    +        while (isspace(*value))
    +            ++value;            /* Skip to start of value   */
    +
    +        ap_table_mergen(r->headers_in, copy, value);
    +
    +	/* the header was too long; at the least we should skip extra data */
    +	if (len >= MAX_STRING_LEN - 1) { 
    +	  char junk[MAX_STRING_LEN];     
    +	  while ((len = getline(junk, MAX_STRING_LEN, c->client, 1))
    +		 >= MAX_STRING_LEN - 1)   /* soak up the extra data */
    +	    ;
    +	  if (len == 0) /* time to exit the larger loop as well */
    +	    break;
    +	}
    +    }
    +}
    +
    +request_rec *ap_read_request(conn_rec *conn)
    +{
    +    request_rec *r;
    +    int access_status;
    +    pool *p;
    +
    +    p = ap_make_sub_pool(conn->pool);
    +    r = ap_pcalloc(p, sizeof(request_rec));
    +    r->pool            = p;
    +    r->connection      = conn;
    +    conn->server       = conn->base_server;
    +    r->server          = conn->server;
    +
    +    conn->keptalive    = conn->keepalive == 1;
    +    conn->keepalive    = 0;
    +
    +    conn->user         = NULL;
    +    conn->ap_auth_type    = NULL;
    +
    +    r->headers_in      = ap_make_table(r->pool, 50);
    +    r->subprocess_env  = ap_make_table(r->pool, 50);
    +    r->headers_out     = ap_make_table(r->pool, 12);
    +    r->err_headers_out = ap_make_table(r->pool, 5);
    +    r->notes           = ap_make_table(r->pool, 5);
    +
    +    r->request_config  = ap_create_request_config(r->pool);
    +    r->per_dir_config  = r->server->lookup_defaults;
    +
    +    r->sent_bodyct     = 0;                      /* bytect isn't for body */
    +
    +    r->read_length     = 0;
    +    r->read_body       = REQUEST_NO_BODY;
    +
    +    r->status          = HTTP_REQUEST_TIME_OUT;  /* Until we get a request */
    +    r->the_request     = NULL;
    +
    +    /* Get the request... */
    +
    +#ifdef CHARSET_EBCDIC
    +    ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 1);
    +#endif /* CHARSET_EBCDIC */
    +    ap_keepalive_timeout("read request line", r);
    +    if (!read_request_line(r)) {
    +        ap_kill_timeout(r);
    +	if (r->status != HTTP_REQUEST_TIME_OUT)  /* we must have had an error.*/
    +	    ap_log_transaction(r);
    +        return NULL;
    +    }
    +    if (!r->assbackwards) {
    +        ap_hard_timeout("read request headers", r);
    +        get_mime_headers(r);
    +        if (r->status != HTTP_REQUEST_TIME_OUT) {/* we must have had an error.*/
    +	    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
    +		         "request failed for %s: error reading the headers",
    +		         ap_get_remote_host(r->connection, r->per_dir_config, 
    +					    REMOTE_NAME));
    +	    ap_log_transaction(r);
    +	    return NULL;
    +	}
    +
    +    }
    +    ap_kill_timeout(r);
    +
    +    r->status = HTTP_OK;                         /* Until further notice. */
    +
    +    /* update what we think the virtual host is based on the headers we've
    +     * now read
    +     */
    +    ap_update_vhost_from_headers(r);
    +
    +    /* we may have switched to another server */
    +    r->per_dir_config = r->server->lookup_defaults;
    +
    +    conn->keptalive = 0;        /* We now have a request to play with */
    +
    +    if ((access_status = ap_run_post_read_request(r))) {
    +        ap_die(access_status, r);
    +	ap_log_transaction(r);
    +
    +        return NULL;
    +    }
    +
    +    return r;
    +}
    +
    +/*
    + * A couple of other functions which initialize some of the fields of
    + * a request structure, as appropriate for adjuncts of one kind or another
    + * to a request in progress.  Best here, rather than elsewhere, since
    + * *someone* has to set the protocol-specific fields...
    + */
    +
    +void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r)
    +{
    +    rnew->the_request     = r->the_request;  /* Keep original request-line */
    +
    +    rnew->assbackwards    = 1;   /* Don't send headers from this. */
    +    rnew->no_local_copy   = 1;   /* Don't try to send USE_LOCAL_COPY for a
    +                                  * fragment. */
    +    rnew->method          = "GET";
    +    rnew->method_number   = M_GET;
    +    rnew->protocol        = "INCLUDED";
    +
    +    rnew->status          = HTTP_OK;
    +
    +    rnew->headers_in      = r->headers_in;
    +    rnew->subprocess_env  = ap_copy_table(rnew->pool, r->subprocess_env);
    +    rnew->headers_out     = ap_make_table(rnew->pool, 5);
    +    rnew->err_headers_out = ap_make_table(rnew->pool, 5);
    +    rnew->notes           = ap_make_table(rnew->pool, 5);
    +
    +    rnew->read_length     = r->read_length;
    +    rnew->read_body       = REQUEST_NO_BODY;
    +
    +    rnew->main = (request_rec *) r;
    +}
    +
    +void ap_finalize_sub_req_protocol(request_rec *sub)
    +{
    +    SET_BYTES_SENT(sub->main);
    +}
    +
    +/*
    + * Support for the Basic authentication protocol, and a bit for Digest.
    + */
    +
    +API_EXPORT(void) ap_note_auth_failure(request_rec *r)
    +{
    +    if (!strcasecmp(ap_auth_type(r), "Basic"))
    +        ap_note_basic_auth_failure(r);
    +    else if (!strcasecmp(ap_auth_type(r), "Digest"))
    +        ap_note_digest_auth_failure(r);
    +}
    +
    +API_EXPORT(void) ap_note_basic_auth_failure(request_rec *r)
    +{
    +    if (strcasecmp(ap_auth_type(r), "Basic"))
    +        ap_note_auth_failure(r);
    +    else
    +        ap_table_setn(r->err_headers_out,
    +                  r->proxyreq ? "Proxy-Authenticate" : "WWW-Authenticate",
    +                  ap_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r), "\"",
    +                          NULL));
    +}
    +
    +API_EXPORT(void) ap_note_digest_auth_failure(request_rec *r)
    +{
    +    ap_table_setn(r->err_headers_out,
    +	    r->proxyreq ? "Proxy-Authenticate" : "WWW-Authenticate",
    +	    ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%lu\"",
    +		ap_auth_name(r), r->request_time));
    +}
    +
    +API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, char **pw)
    +{
    +    const char *auth_line = ap_table_get(r->headers_in,
    +                                      r->proxyreq ? "Proxy-Authorization"
    +                                                  : "Authorization");
    +    char *t;
    +
    +    if (!(t = ap_auth_type(r)) || strcasecmp(t, "Basic"))
    +        return DECLINED;
    +
    +    if (!ap_auth_name(r)) {
    +        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
    +		    r->server, "need AuthName: %s", r->uri);
    +        return SERVER_ERROR;
    +    }
    +
    +    if (!auth_line) {
    +        ap_note_basic_auth_failure(r);
    +        return AUTH_REQUIRED;
    +    }
    +
    +    if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) {
    +        /* Client tried to authenticate using wrong auth scheme */
    +        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
    +                    "client used wrong authentication scheme: %s", r->uri);
    +        ap_note_basic_auth_failure(r);
    +        return AUTH_REQUIRED;
    +    }
    +
    +    t = ap_uudecode(r->pool, auth_line);
    +    /* Note that this allocation has to be made from r->connection->pool
    +     * because it has the lifetime of the connection.  The other allocations
    +     * are temporary and can be tossed away any time.
    +     */
    +    r->connection->user = ap_getword_nulls_nc (r->connection->pool, &t, ':');
    +    r->connection->ap_auth_type = "Basic";
    +
    +    *pw = t;
    +
    +    return OK;
    +}
    +
    +/* New Apache routine to map status codes into array indicies
    + *  e.g.  100 -> 0,  101 -> 1,  200 -> 2 ...
    + * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
    + * and must be listed in order.
    + */
    +
    +static char *status_lines[] = {
    +    "100 Continue",
    +    "101 Switching Protocols",
    +#define LEVEL_200  2
    +    "200 OK",
    +    "201 Created",
    +    "202 Accepted",
    +    "203 Non-Authoritative Information",
    +    "204 No Content",
    +    "205 Reset Content",
    +    "206 Partial Content",
    +#define LEVEL_300  9
    +    "300 Multiple Choices",
    +    "301 Moved Permanently",
    +    "302 Moved Temporarily",
    +    "303 See Other",
    +    "304 Not Modified",
    +    "305 Use Proxy",
    +#define LEVEL_400 15
    +    "400 Bad Request",
    +    "401 Authorization Required",
    +    "402 Payment Required",
    +    "403 Forbidden",
    +    "404 Not Found",
    +    "405 Method Not Allowed",
    +    "406 Not Acceptable",
    +    "407 Proxy Authentication Required",
    +    "408 Request Time-out",
    +    "409 Conflict",
    +    "410 Gone",
    +    "411 Length Required",
    +    "412 Precondition Failed",
    +    "413 Request Entity Too Large",
    +    "414 Request-URI Too Large",
    +    "415 Unsupported Media Type",
    +#define LEVEL_500 31
    +    "500 Internal Server Error",
    +    "501 Method Not Implemented",
    +    "502 Bad Gateway",
    +    "503 Service Temporarily Unavailable",
    +    "504 Gateway Time-out",
    +    "505 HTTP Version Not Supported",
    +    "506 Variant Also Varies"
    +};
    +
    +/* The index is found by its offset from the x00 code of each level.
    + * Although this is fast, it will need to be replaced if some nutcase
    + * decides to define a high-numbered code before the lower numbers.
    + * If that sad event occurs, replace the code below with a linear search
    + * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
    + */
    +API_EXPORT(int) ap_index_of_response(int status)
    +{
    +    static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
    +    LEVEL_500, RESPONSE_CODES};
    +    int i, pos;
    +
    +    if (status < 100)           /* Below 100 is illegal for HTTP status */
    +        return LEVEL_500;
    +
    +    for (i = 0; i < 5; i++) {
    +        status -= 100;
    +        if (status < 100) {
    +            pos = (status + shortcut[i]);
    +            if (pos < shortcut[i + 1])
    +                return pos;
    +            else
    +                return LEVEL_500;       /* status unknown (falls in gap) */
    +        }
    +    }
    +    return LEVEL_500;           /* 600 or above is also illegal */
    +}
    +
    +/* Send a single HTTP header field to the client.  Note that this function
    + * is used in calls to table_do(), so their interfaces are co-dependent.
    + * In other words, don't change this one without checking table_do in alloc.c.
    + * It returns true unless there was a write error of some kind.
    + */
    +API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r,
    +    const char *fieldname, const char *fieldval)
    +{
    +    return (0 < ap_bvputs(r->connection->client,
    +                       fieldname, ": ", fieldval, "\015\012", NULL));
    +}
    +
    +API_EXPORT(void) ap_basic_http_header(request_rec *r)
    +{
    +    char *protocol;
    +#ifdef CHARSET_EBCDIC
    +    int convert = bgetflag(r->connection->client, B_EBCDIC2ASCII);
    +#endif /*CHARSET_EBCDIC*/
    +
    +    if (r->assbackwards)
    +        return;
    +
    +    if (!r->status_line)
    +        r->status_line = status_lines[ap_index_of_response(r->status)];
    +
    +    /* mod_proxy is only HTTP/1.0, so avoid sending HTTP/1.1 error response;
    +     * kluge around broken browsers when indicated by force-response-1.0
    +     */
    +    if (r->proxyreq
    +        || (r->proto_num == HTTP_VERSION(1,0)
    +            && ap_table_get(r->subprocess_env, "force-response-1.0"))) {
    +
    +        protocol = "HTTP/1.0";
    +        r->connection->keepalive = -1;
    +    }
    +    else
    +        protocol = SERVER_PROTOCOL;
    +
    +#ifdef CHARSET_EBCDIC
    +    ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1);
    +#endif /*CHARSET_EBCDIC*/
    +
    +    /* Output the HTTP/1.x Status-Line and the Date and Server fields */
    +
    +    ap_bvputs(r->connection->client,
    +           protocol, " ", r->status_line, "\015\012", NULL);
    +
    +    ap_send_header_field(r, "Date", ap_gm_timestr_822(r->pool, r->request_time));
    +    ap_send_header_field(r, "Server", ap_get_server_version());
    +
    +    ap_table_unset(r->headers_out, "Date");        /* Avoid bogosity */
    +    ap_table_unset(r->headers_out, "Server");
    +#ifdef CHARSET_EBCDIC
    +    if (!convert)
    +        ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert);
    +#endif /*CHARSET_EBCDIC*/
    +}
    +
    +/* Navigator versions 2.x, 3.x and 4.0 betas up to and including 4.0b2
    + * have a header parsing bug.  If the terminating \r\n occur starting
    + * at offset 256, 257 or 258 of output then it will not properly parse
    + * the headers.  Curiously it doesn't exhibit this problem at 512, 513.
    + * We are guessing that this is because their initial read of a new request
    + * uses a 256 byte buffer, and subsequent reads use a larger buffer.
    + * So the problem might exist at different offsets as well.
    + *
    + * This should also work on keepalive connections assuming they use the
    + * same small buffer for the first read of each new request.
    + *
    + * At any rate, we check the bytes written so far and, if we are about to
    + * tickle the bug, we instead insert a bogus padding header.  Since the bug
    + * manifests as a broken image in Navigator, users blame the server.  :(
    + * It is more expensive to check the User-Agent than it is to just add the
    + * bytes, so we haven't used the BrowserMatch feature here.
    + */
    +static void terminate_header(BUFF *client)
    +{
    +    long int bs;
    +
    +    ap_bgetopt(client, BO_BYTECT, &bs);
    +    if (bs >= 255 && bs <= 257)
    +        ap_bputs("X-Pad: avoid browser bug\015\012", client);
    +
    +    ap_bputs("\015\012", client);  /* Send the terminating empty line */
    +}
    +
    +/* Build the Allow field-value from the request handler method mask.
    + * Note that we always allow TRACE, since it is handled below.
    + */
    +static char *make_allow(request_rec *r)
    +{
    +    return 2 + ap_pstrcat(r->pool,
    +                       (r->allowed & (1 << M_GET)) ? ", GET, HEAD" : "",
    +                       (r->allowed & (1 << M_POST)) ? ", POST" : "",
    +                       (r->allowed & (1 << M_PUT)) ? ", PUT" : "",
    +                       (r->allowed & (1 << M_DELETE)) ? ", DELETE" : "",
    +                       (r->allowed & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
    +                       ", TRACE",
    +                       NULL);
    +}
    +
    +int ap_send_http_trace(request_rec *r)
    +{
    +    int rv;
    +
    +    /* Get the original request */
    +    while (r->prev)
    +        r = r->prev;
    +
    +    if ((rv = ap_setup_client_block(r, REQUEST_NO_BODY)))
    +        return rv;
    +
    +    ap_hard_timeout("send TRACE", r);
    +
    +    r->content_type = "message/http";
    +    ap_send_http_header(r);
    +
    +    /* Now we recreate the request, and echo it back */
    +
    +    ap_rvputs(r, r->the_request, "\015\012", NULL);
    +
    +    ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
    +             (void *) r, r->headers_in, NULL);
    +    ap_bputs("\015\012", r->connection->client);
    +
    +    ap_kill_timeout(r);
    +    return OK;
    +}
    +
    +int ap_send_http_options(request_rec *r)
    +{
    +    const long int zero = 0L;
    +
    +    if (r->assbackwards)
    +        return DECLINED;
    +
    +    ap_hard_timeout("send OPTIONS", r);
    +
    +    ap_basic_http_header(r);
    +
    +    ap_table_setn(r->headers_out, "Content-Length", "0");
    +    ap_table_setn(r->headers_out, "Allow", make_allow(r));
    +    ap_set_keepalive(r);
    +
    +    ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
    +             (void *) r, r->headers_out, NULL);
    +
    +    terminate_header(r->connection->client);
    +
    +    ap_kill_timeout(r);
    +    ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
    +
    +    return OK;
    +}
    +
    +/*
    + * Here we try to be compatible with clients that want multipart/x-byteranges
    + * instead of multipart/byteranges (also see above), as per HTTP/1.1. We
    + * look for the Request-Range header (e.g. Netscape 2 and 3) as an indication
    + * that the browser supports an older protocol. We also check User-Agent
    + * for Microsoft Internet Explorer 3, which needs this as well.
    + */
    +static int use_range_x(request_rec *r)
    +{
    +    char *ua;
    +    return (ap_table_get(r->headers_in, "Request-Range") ||
    +            ((ua = ap_table_get(r->headers_in, "User-Agent"))
    +             && strstr(ua, "MSIE 3")));
    +}
    +
    +API_EXPORT(void) ap_send_http_header(request_rec *r)
    +{
    +    int i;
    +    const long int zero = 0L;
    +#ifdef CHARSET_EBCDIC
    +    int convert = bgetflag(r->connection->client, B_EBCDIC2ASCII);
    +#endif /*CHARSET_EBCDIC*/
    +
    +    if (r->assbackwards) {
    +        if (!r->main)
    +            ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
    +        r->sent_bodyct = 1;
    +        return;
    +    }
    +
    +    /*
    +     * Now that we are ready to send a response, we need to combine the two
    +     * header field tables into a single table.  If we don't do this, our
    +     * later attempts to set or unset a given fieldname might be bypassed.
    +     */
    +    if (!is_empty_table(r->err_headers_out))
    +        r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
    +                                        r->headers_out);
    +
    +    ap_hard_timeout("send headers", r);
    +
    +    ap_basic_http_header(r);
    +
    +#ifdef CHARSET_EBCDIC
    +    ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1);
    +#endif /*CHARSET_EBCDIC*/
    +
    +    ap_set_keepalive(r);
    +
    +    if (r->chunked) {
    +        ap_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
    +        ap_table_unset(r->headers_out, "Content-Length");
    +    }
    +
    +    if (r->byterange > 1)
    +        ap_table_setn(r->headers_out, "Content-Type",
    +                  ap_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
    +                          "byteranges; boundary=", r->boundary, NULL));
    +    else if (r->content_type)
    +        ap_table_setn(r->headers_out, "Content-Type", r->content_type);
    +    else
    +        ap_table_setn(r->headers_out, "Content-Type", ap_default_type(r));
    +
    +    if (r->content_encoding)
    +        ap_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
    +
    +    if (r->content_languages && r->content_languages->nelts) {
    +        for (i = 0; i < r->content_languages->nelts; ++i) {
    +            ap_table_mergen(r->headers_out, "Content-Language",
    +                        ((char **) (r->content_languages->elts))[i]);
    +        }
    +    }
    +    else if (r->content_language)
    +        ap_table_setn(r->headers_out, "Content-Language", r->content_language);
    +
    +    /*
    +     * Control cachability for non-cachable responses if not already set by
    +     * some other part of the server configuration.
    +     */
    +    if (r->no_cache && !ap_table_get(r->headers_out, "Expires"))
    +        ap_table_addn(r->headers_out, "Expires",
    +                  ap_gm_timestr_822(r->pool, r->request_time));
    +
    +    /* Send the entire table of header fields, terminated by an empty line. */
    +
    +    ap_table_do((int (*) (void *, const char *, const char *)) ap_send_header_field,
    +             (void *) r, r->headers_out, NULL);
    +
    +    terminate_header(r->connection->client);
    +
    +    ap_kill_timeout(r);
    +
    +    ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
    +    r->sent_bodyct = 1;         /* Whatever follows is real body stuff... */
    +
    +    /* Set buffer flags for the body */
    +    if (r->chunked)
    +        ap_bsetflag(r->connection->client, B_CHUNK, 1);
    +#ifdef CHARSET_EBCDIC
    +    if (!convert)
    +        ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert);
    +#endif /*CHARSET_EBCDIC*/
    +}
    +
    +/* finalize_request_protocol is called at completion of sending the
    + * response.  It's sole purpose is to send the terminating protocol
    + * information for any wrappers around the response message body
    + * (i.e., transfer encodings).  It should have been named finalize_response.
    + */
    +void ap_finalize_request_protocol(request_rec *r)
    +{
    +    if (r->chunked && !r->connection->aborted) {
    +        /*
    +         * Turn off chunked encoding --- we can only do this once.
    +         */
    +        r->chunked = 0;
    +        ap_bsetflag(r->connection->client, B_CHUNK, 0);
    +
    +        ap_soft_timeout("send ending chunk", r);
    +        ap_bputs("0\015\012", r->connection->client);
    +        /* If we had footer "headers", we'd send them now */
    +        ap_bputs("\015\012", r->connection->client);
    +        ap_kill_timeout(r);
    +    }
    +}
    +
    +/* Here we deal with getting the request message body from the client.
    + * Whether or not the request contains a body is signaled by the presence
    + * of a non-zero Content-Length or by a Transfer-Encoding: chunked.
    + *
    + * Note that this is more complicated than it was in Apache 1.1 and prior
    + * versions, because chunked support means that the module does less.
    + *
    + * The proper procedure is this:
    + *
    + * 1. Call setup_client_block() near the beginning of the request
    + *    handler. This will set up all the necessary properties, and will
    + *    return either OK, or an error code. If the latter, the module should
    + *    return that error code. The second parameter selects the policy to
    + *    apply if the request message indicates a body, and how a chunked
    + *    transfer-coding should be interpreted. Choose one of
    + *
    + *    REQUEST_NO_BODY          Send 413 error if message has any body
    + *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
    + *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
    + *    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
    + *
    + *    In order to use the last two options, the caller MUST provide a buffer
    + *    large enough to hold a chunk-size line, including any extensions.
    + *
    + * 2. When you are ready to read a body (if any), call should_client_block().
    + *    This will tell the module whether or not to read input. If it is 0,
    + *    the module should assume that there is no message body to read.
    + *    This step also sends a 100 Continue response to HTTP/1.1 clients,
    + *    so should not be called until the module is *definitely* ready to
    + *    read content. (otherwise, the point of the 100 response is defeated).
    + *    Never call this function more than once.
    + *
    + * 3. Finally, call get_client_block in a loop. Pass it a buffer and its size.
    + *    It will put data into the buffer (not necessarily a full buffer), and
    + *    return the length of the input block. When it is done reading, it will
    + *    return 0 if EOF, or -1 if there was an error.
    + *    If an error occurs on input, we force an end to keepalive.
    + */
    +
    +API_EXPORT(int) ap_setup_client_block(request_rec *r, int read_policy)
    +{
    +    char *tenc = ap_table_get(r->headers_in, "Transfer-Encoding");
    +    char *lenp = ap_table_get(r->headers_in, "Content-Length");
    +
    +    r->read_body = read_policy;
    +    r->read_chunked = 0;
    +    r->remaining = 0;
    +
    +    if (tenc) {
    +        if (strcasecmp(tenc, "chunked")) {
    +            ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
    +                        "Unknown Transfer-Encoding %s", tenc);
    +            return HTTP_NOT_IMPLEMENTED;
    +        }
    +        if (r->read_body == REQUEST_CHUNKED_ERROR) {
    +            ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
    +                        "chunked Transfer-Encoding forbidden: %s", r->uri);
    +            return (lenp) ? HTTP_BAD_REQUEST : HTTP_LENGTH_REQUIRED;
    +        }
    +
    +        r->read_chunked = 1;
    +    }
    +    else if (lenp) {
    +        char *pos = lenp;
    +
    +        while (isdigit(*pos) || isspace(*pos))
    +            ++pos;
    +        if (*pos != '\0') {
    +            ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
    +                        "Invalid Content-Length %s", lenp);
    +            return HTTP_BAD_REQUEST;
    +        }
    +
    +        r->remaining = atol(lenp);
    +    }
    +
    +    if ((r->read_body == REQUEST_NO_BODY) &&
    +        (r->read_chunked || (r->remaining > 0))) {
    +        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
    +                    "%s with body is not allowed for %s", r->method, r->uri);
    +        return HTTP_REQUEST_ENTITY_TOO_LARGE;
    +    }
    +
    +    return OK;
    +}
    +
    +API_EXPORT(int) ap_should_client_block(request_rec *r)
    +{
    +    /* First check if we have already read the request body */
    +
    +    if (r->read_length || (!r->read_chunked && (r->remaining <= 0)))
    +        return 0;
    +
    +    if (r->proto_num >= HTTP_VERSION(1,1)) {
    +        /* sending 100 Continue interim response */
    +        ap_bvputs(r->connection->client,
    +               SERVER_PROTOCOL, " ", status_lines[0], "\015\012\015\012",
    +               NULL);
    +        ap_bflush(r->connection->client);
    +    }
    +
    +    return 1;
    +}
    +
    +static long get_chunk_size(char *b)
    +{
    +    long chunksize = 0;
    +
    +    while (isxdigit(*b)) {
    +        int xvalue = 0;
    +
    +        if (*b >= '0' && *b <= '9')
    +            xvalue = *b - '0';
    +        else if (*b >= 'A' && *b <= 'F')
    +            xvalue = *b - 'A' + 0xa;
    +        else if (*b >= 'a' && *b <= 'f')
    +            xvalue = *b - 'a' + 0xa;
    +
    +        chunksize = (chunksize << 4) | xvalue;
    +        ++b;
    +    }
    +
    +    return chunksize;
    +}
    +
    +/* get_client_block is called in a loop to get the request message body.
    + * This is quite simple if the client includes a content-length
    + * (the normal case), but gets messy if the body is chunked. Note that
    + * r->remaining is used to maintain state across calls and that
    + * r->read_length is the total number of bytes given to the caller
    + * across all invocations.  It is messy because we have to be careful not
    + * to read past the data provided by the client, since these reads block.
    + * Returns 0 on End-of-body, -1 on error or premature chunk end.
    + *
    + * Reading the chunked encoding requires a buffer size large enough to
    + * hold a chunk-size line, including any extensions. For now, we'll leave
    + * that to the caller, at least until we can come up with a better solution.
    + */
    +API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
    +{
    +    int c;
    +    long len_read, len_to_read;
    +    long chunk_start = 0;
    +
    +    if (!r->read_chunked) {     /* Content-length read */
    +        len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
    +        len_read = ap_bread(r->connection->client, buffer, len_to_read);
    +        if (len_read <= 0) {
    +            if (len_read < 0)
    +                r->connection->keepalive = -1;
    +            return len_read;
    +        }
    +        r->read_length += len_read;
    +        r->remaining -= len_read;
    +        return len_read;
    +    }
    +
    +    /*
    +     * Handle chunked reading Note: we are careful to shorten the input
    +     * bufsiz so that there will always be enough space for us to add a CRLF
    +     * (if necessary).
    +     */
    +    if (r->read_body == REQUEST_CHUNKED_PASS)
    +        bufsiz -= 2;
    +    if (bufsiz <= 0)
    +        return -1;              /* Cannot read chunked with a small buffer */
    +
    +    if (r->remaining == 0) {    /* Start of new chunk */
    +
    +        chunk_start = getline(buffer, bufsiz, r->connection->client, 0);
    +        if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
    +            || !isxdigit(*buffer)) {
    +            r->connection->keepalive = -1;
    +            return -1;
    +        }
    +
    +        len_to_read = get_chunk_size(buffer);
    +
    +        if (len_to_read == 0) { /* Last chunk indicated, get footers */
    +            if (r->read_body == REQUEST_CHUNKED_DECHUNK) {
    +                get_mime_headers(r);
    +                ap_snprintf(buffer, bufsiz, "%ld", r->read_length);
    +                ap_table_unset(r->headers_in, "Transfer-Encoding");
    +                ap_table_setn(r->headers_in, "Content-Length",
    +                    ap_pstrdup(r->pool, buffer));
    +                return 0;
    +            }
    +            r->remaining = -1;  /* Indicate footers in-progress */
    +        }
    +        else {
    +            r->remaining = len_to_read;
    +        }
    +        if (r->read_body == REQUEST_CHUNKED_PASS) {
    +            buffer[chunk_start++] = CR; /* Restore chunk-size line end  */
    +            buffer[chunk_start++] = LF;
    +            buffer += chunk_start;      /* and pass line on to caller   */
    +            bufsiz -= chunk_start;
    +        }
    +        else {
    +            /* REQUEST_CHUNKED_DECHUNK -- do not include the length of the
    +             * header in the return value
    +             */
    +            chunk_start = 0;
    +        }
    +    }
    +                                /* When REQUEST_CHUNKED_PASS, we are */
    +    if (r->remaining == -1) {   /* reading footers until empty line  */
    +        len_read = chunk_start;
    +
    +        while ((bufsiz > 1) && ((len_read =
    +                  getline(buffer, bufsiz, r->connection->client, 1)) > 0)) {
    +
    +            if (len_read != (bufsiz - 1)) {
    +                buffer[len_read++] = CR;        /* Restore footer line end  */
    +                buffer[len_read++] = LF;
    +            }
    +            chunk_start += len_read;
    +            buffer += len_read;
    +            bufsiz -= len_read;
    +        }
    +        if (len_read < 0) {
    +            r->connection->keepalive = -1;
    +            return -1;
    +        }
    +
    +        if (len_read == 0) {    /* Indicates an empty line */
    +            buffer[0] = CR;
    +            buffer[1] = LF;
    +            chunk_start += 2;
    +            r->remaining = -2;
    +        }
    +        r->read_length += chunk_start;
    +        return chunk_start;
    +    }
    +                                /* When REQUEST_CHUNKED_PASS, we     */
    +    if (r->remaining == -2) {   /* finished footers when last called */
    +        r->remaining = 0;       /* so now we must signal EOF         */
    +        return 0;
    +    }
    +
    +    /* Otherwise, we are in the midst of reading a chunk of data */
    +
    +    len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
    +
    +    len_read = ap_bread(r->connection->client, buffer, len_to_read);
    +    if (len_read <= 0) {
    +        r->connection->keepalive = -1;
    +        return -1;
    +    }
    +
    +    r->remaining -= len_read;
    +
    +    if (r->remaining == 0) {    /* End of chunk, get trailing CRLF */
    +        if ((c = ap_bgetc(r->connection->client)) == CR) {
    +            c = ap_bgetc(r->connection->client);
    +        }
    +        if (c != LF) {
    +            r->connection->keepalive = -1;
    +            return -1;
    +        }
    +        if (r->read_body == REQUEST_CHUNKED_PASS) {
    +            buffer[len_read++] = CR;
    +            buffer[len_read++] = LF;
    +        }
    +    }
    +    r->read_length += (chunk_start + len_read);
    +
    +    return (chunk_start + len_read);
    +}
    +
    +/* In HTTP/1.1, any method can have a body.  However, most GET handlers
    + * wouldn't know what to do with a request body if they received one.
    + * This helper routine tests for and reads any message body in the request,
    + * simply discarding whatever it receives.  We need to do this because
    + * failing to read the request body would cause it to be interpreted
    + * as the next request on a persistent connection.
    + *
    + * Since we return an error status if the request is malformed, this
    + * routine should be called at the beginning of a no-body handler, e.g.,
    + *
    + *    if ((retval = discard_request_body(r)) != OK)
    + *        return retval;
    + */
    +API_EXPORT(int) ap_discard_request_body(request_rec *r)
    +{
    +    int rv;
    +
    +    if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_PASS)))
    +        return rv;
    +
    +    if (ap_should_client_block(r)) {
    +        char dumpbuf[HUGE_STRING_LEN];
    +
    +        ap_hard_timeout("reading request body", r);
    +        while ((rv = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
    +            continue;
    +        ap_kill_timeout(r);
    +
    +        if (rv < 0)
    +            return HTTP_BAD_REQUEST;
    +    }
    +    return OK;
    +}
    +
    +/*
    + * Send the body of a response to the client.
    + */
    +API_EXPORT(long) ap_send_fd(FILE *f, request_rec *r)
    +{
    +    return ap_send_fd_length(f, r, -1);
    +}
    +
    +API_EXPORT(long) ap_send_fd_length(FILE *f, request_rec *r, long length)
    +{
    +    char buf[IOBUFSIZE];
    +    long total_bytes_sent = 0;
    +    register int n, w, o, len;
    +
    +    if (length == 0)
    +        return 0;
    +
    +    ap_soft_timeout("send body", r);
    +
    +    while (!r->connection->aborted) {
    +        if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
    +            len = length - total_bytes_sent;
    +        else
    +            len = IOBUFSIZE;
    +
    +        while ((n = fread(buf, sizeof(char), len, f)) < 1
    +               && ferror(f) && errno == EINTR && !r->connection->aborted)
    +            continue;
    +
    +        if (n < 1) {
    +            break;
    +        }
    +        o = 0;
    +
    +        while (n && !r->connection->aborted) {
    +            w = ap_bwrite(r->connection->client, &buf[o], n);
    +            if (w > 0) {
    +                ap_reset_timeout(r);   /* reset timeout after successful write */
    +		total_bytes_sent += w;
    +                n -= w;
    +                o += w;
    +            }
    +            else if (w < 0) {
    +                if (r->connection->aborted)
    +                    break;
    +                else if (errno == EAGAIN)
    +                    continue;
    +                else {
    +                    ap_log_error(APLOG_MARK, APLOG_INFO, r->server,
    +                     "%s client stopped connection before send body completed",
    +                                ap_get_remote_host(r->connection,
    +                                                r->per_dir_config,
    +                                                REMOTE_NAME));
    +                    ap_bsetflag(r->connection->client, B_EOUT, 1);
    +                    r->connection->aborted = 1;
    +                    break;
    +                }
    +            }
    +        }
    +    }
    +
    +    ap_kill_timeout(r);
    +    SET_BYTES_SENT(r);
    +    return total_bytes_sent;
    +}
    +
    +/*
    + * Send the body of a response to the client.
    + */
    +API_EXPORT(long) ap_send_fb(BUFF *fb, request_rec *r)
    +{
    +    return ap_send_fb_length(fb, r, -1);
    +}
    +
    +API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
    +{
    +    char buf[IOBUFSIZE];
    +    long total_bytes_sent = 0;
    +    register int n, w, o, len, fd;
    +    fd_set fds;
    +
    +    if (length == 0)
    +        return 0;
    +
    +    /* Make fb unbuffered and non-blocking */
    +    ap_bsetflag(fb, B_RD, 0);
    +    ap_bnonblock(fb, B_RD);
    +    fd = ap_bfileno(fb, B_RD);
    +#ifndef WIN32
    +    if (fd >= FD_SETSIZE) {
    +	ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
    +	    "send body: filedescriptor (%u) larger than FD_SETSIZE (%u) "
    +	    "found, you probably need to rebuild Apache with a "
    +	    "larger FD_SETSIZE", fd, FD_SETSIZE);
    +	return 0;
    +    }
    +#endif
    +
    +    ap_soft_timeout("send body", r);
    +
    +    FD_ZERO(&fds);
    +    while (!r->connection->aborted) {
    +        if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
    +            len = length - total_bytes_sent;
    +        else
    +            len = IOBUFSIZE;
    +
    +        do {
    +            n = ap_bread(fb, buf, len);
    +            if (n >= 0 || r->connection->aborted)
    +                break;
    +            if (n < 0 && errno != EAGAIN)
    +                break;
    +            /* we need to block, so flush the output first */
    +            ap_bflush(r->connection->client);
    +            if (r->connection->aborted)
    +                break;
    +            FD_SET(fd, &fds);
    +            /*
    +             * we don't care what select says, we might as well loop back
    +             * around and try another read
    +             */
    +            ap_select(fd + 1, &fds, NULL, NULL, NULL);
    +        } while (!r->connection->aborted);
    +
    +        if (n < 1 || r->connection->aborted) {
    +            break;
    +        }
    +
    +        o = 0;
    +        total_bytes_sent += n;
    +
    +        while (n && !r->connection->aborted) {
    +            w = ap_bwrite(r->connection->client, &buf[o], n);
    +            if (w > 0) {
    +                ap_reset_timeout(r);       /* reset timeout after successful
    +                                         * write */
    +                n -= w;
    +                o += w;
    +            }
    +            else if (w < 0) {
    +                if (r->connection->aborted)
    +                    break;
    +                else if (errno == EAGAIN)
    +                    continue;
    +                else {
    +                    ap_log_error(APLOG_MARK, APLOG_INFO, r->server,
    +                     "%s client stopped connection before send body completed",
    +                                ap_get_remote_host(r->connection,
    +                                                r->per_dir_config,
    +                                                REMOTE_NAME));
    +                    ap_bsetflag(r->connection->client, B_EOUT, 1);
    +                    r->connection->aborted = 1;
    +                    break;
    +                }
    +            }
    +        }
    +    }
    +
    +    ap_kill_timeout(r);
    +    SET_BYTES_SENT(r);
    +    return total_bytes_sent;
    +}
    +
    +
    +
    +/* The code writes MMAP_SEGMENT_SIZE bytes at a time.  This is due to Apache's
    + * timeout model, which is a timeout per-write rather than a time for the
    + * entire transaction to complete.  Essentially this should be small enough
    + * so that in one Timeout period, your slowest clients should be reasonably
    + * able to receive this many bytes.
    + *
    + * To take advantage of zero-copy TCP under Solaris 2.6 this should be a
    + * multiple of 16k.  (And you need a SunATM2.0 network card.)
    + */
    +#ifndef MMAP_SEGMENT_SIZE
    +#define MMAP_SEGMENT_SIZE       32768
    +#endif
    +
    +/* send data from an in-memory buffer */
    +API_EXPORT(size_t) ap_send_mmap(void *mm, request_rec *r, size_t offset,
    +                             size_t length)
    +{
    +    size_t total_bytes_sent = 0;
    +    int n, w;
    +
    +    if (length == 0)
    +        return 0;
    +
    +    ap_soft_timeout("send mmap", r);
    +
    +    length += offset;
    +    while (!r->connection->aborted && offset < length) {
    +        if (length - offset > MMAP_SEGMENT_SIZE) {
    +            n = MMAP_SEGMENT_SIZE;
    +        }
    +        else {
    +            n = length - offset;
    +        }
    +
    +        while (n && !r->connection->aborted) {
    +            w = ap_bwrite(r->connection->client, (char *) mm + offset, n);
    +            if (w > 0) {
    +                ap_reset_timeout(r);   /* reset timeout after successful write */
    +                total_bytes_sent += w;
    +                n -= w;
    +                offset += w;
    +            }
    +            else if (w < 0) {
    +                if (r->connection->aborted)
    +                    break;
    +                else if (errno == EAGAIN)
    +                    continue;
    +                else {
    +                    ap_log_error(APLOG_MARK, APLOG_INFO, r->server,
    +                     "%s client stopped connection before send mmap completed",
    +                                ap_get_remote_host(r->connection,
    +                                                r->per_dir_config,
    +                                                REMOTE_NAME));
    +                    ap_bsetflag(r->connection->client, B_EOUT, 1);
    +                    r->connection->aborted = 1;
    +                    break;
    +                }
    +            }
    +        }
    +    }
    +
    +    ap_kill_timeout(r);
    +    SET_BYTES_SENT(r);
    +    return total_bytes_sent;
    +}
    +
    +API_EXPORT(int) ap_rputc(int c, request_rec *r)
    +{
    +    if (r->connection->aborted)
    +        return EOF;
    +    ap_bputc(c, r->connection->client);
    +    SET_BYTES_SENT(r);
    +    return c;
    +}
    +
    +API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
    +{
    +    int rcode;
    +
    +    if (r->connection->aborted)
    +        return EOF;
    +    rcode = ap_bputs(str, r->connection->client);
    +    SET_BYTES_SENT(r);
    +    return rcode;
    +}
    +
    +API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
    +{
    +    int n;
    +    if (r->connection->aborted)
    +        return EOF;
    +    n = ap_bwrite(r->connection->client, buf, nbyte);
    +    SET_BYTES_SENT(r);
    +    return n;
    +}
    +
    +API_EXPORT(int) ap_rprintf(request_rec *r, const char *fmt,...)
    +{
    +    va_list vlist;
    +    int n;
    +
    +    if (r->connection->aborted)
    +        return EOF;
    +    va_start(vlist, fmt);
    +    n = ap_vbprintf(r->connection->client, fmt, vlist);
    +    va_end(vlist);
    +    SET_BYTES_SENT(r);
    +    return n;
    +}
    +
    +API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
    +{
    +    va_list args;
    +    int i, j, k;
    +    const char *x;
    +    BUFF *fb = r->connection->client;
    +
    +    if (r->connection->aborted)
    +        return EOF;
    +
    +    va_start(args, r);
    +    for (k = 0;;) {
    +        x = va_arg(args, const char *);
    +        if (x == NULL)
    +            break;
    +        j = strlen(x);
    +        i = ap_bwrite(fb, x, j);
    +        if (i != j) {
    +            va_end(args);
    +            return -1;
    +        }
    +        k += i;
    +    }
    +    va_end(args);
    +
    +    SET_BYTES_SENT(r);
    +    return k;
    +}
    +
    +API_EXPORT(int) ap_rflush(request_rec *r)
    +{
    +    return ap_bflush(r->connection->client);
    +}
    +
    +/* We should have named this send_canned_response, since it is used for any
    + * response that can be generated by the server from the request record.
    + * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
    + * and 5xx (server error) messages that have not been redirected to another
    + * handler via the ErrorDocument feature.
    + */
    +void ap_send_error_response(request_rec *r, int recursive_error)
    +{
    +    BUFF *fd = r->connection->client;
    +    int status = r->status;
    +    int idx = ap_index_of_response(status);
    +    char *custom_response;
    +    char *location = ap_table_get(r->headers_out, "Location");
    +
    +    /* We need to special-case the handling of 204 and 304 responses,
    +     * since they have specific HTTP requirements and do not include a
    +     * message body.  Note that being assbackwards here is not an option.
    +     */
    +    if (status == HTTP_NOT_MODIFIED) {
    +        if (!is_empty_table(r->err_headers_out))
    +            r->headers_out = ap_overlay_tables(r->pool, r->err_headers_out,
    +                                            r->headers_out);
    +        ap_hard_timeout("send 304", r);
    +
    +        ap_basic_http_header(r);
    +        ap_set_keepalive(r);
    +
    +        ap_table_do((int (*)(void *, const char *, const char *))ap_send_header_field,
    +                 (void *) r, r->headers_out,
    +                 "Connection",
    +                 "Keep-Alive",
    +                 "ETag",
    +                 "Content-Location",
    +                 "Expires",
    +                 "Cache-Control",
    +                 "Vary",
    +                 "Warning",
    +                 "WWW-Authenticate",
    +                 "Proxy-Authenticate",
    +                 NULL);
    +
    +        terminate_header(r->connection->client);
    +
    +        ap_kill_timeout(r);
    +        return;
    +    }
    +
    +    if (status == HTTP_NO_CONTENT) {
    +        ap_send_http_header(r);
    +        ap_finalize_request_protocol(r);
    +        return;
    +    }
    +
    +    if (!r->assbackwards) {
    +        table *tmp = r->headers_out;
    +
    +        /* For all HTTP/1.x responses for which we generate the message,
    +         * we need to avoid inheriting the "normal status" header fields
    +         * that may have been set by the request handler before the
    +         * error or redirect, except for Location on external redirects.
    +         */
    +        r->headers_out = r->err_headers_out;
    +        r->err_headers_out = tmp;
    +        ap_clear_table(r->err_headers_out);
    +
    +        if (location && *location
    +            && (is_HTTP_REDIRECT(status) || status == HTTP_CREATED))
    +            ap_table_setn(r->headers_out, "Location", location);
    +
    +        r->content_language = NULL;
    +        r->content_languages = NULL;
    +        r->content_encoding = NULL;
    +        r->clength = 0;
    +        r->content_type = "text/html";
    +
    +        if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED))
    +            ap_table_setn(r->headers_out, "Allow", make_allow(r));
    +
    +        ap_send_http_header(r);
    +
    +        if (r->header_only) {
    +            ap_finalize_request_protocol(r);
    +            return;
    +        }
    +    }
    +
    +    ap_hard_timeout("send error body", r);
    +
    +    if ((custom_response = ap_response_code_string(r, idx))) {
    +        /*
    +         * We have a custom response output. This should only be
    +         * a text-string to write back. But if the ErrorDocument
    +         * was a local redirect and the requested resource failed
    +         * for any reason, the custom_response will still hold the
    +         * redirect URL. We don't really want to output this URL
    +         * as a text message, so first check the custom response
    +         * string to ensure that it is a text-string (using the
    +         * same test used in ap_die(), i.e. does it start with a ").
    +         * If it doesn't, we've got a recursive error, so find
    +         * the original error and output that as well.
    +         */
    +        if (custom_response[0] == '\"') {
    +            ap_bputs(custom_response + 1, fd);
    +            ap_kill_timeout(r);
    +            ap_finalize_request_protocol(r);
    +            return;
    +        }
    +        /*
    +         * Redirect failed, so get back the original error
    +         */
    +        while (r->prev && (r->prev->status != HTTP_OK))
    +            r = r->prev;
    +    }
    +    {
    +        char *title = status_lines[idx];
    +        /* folks decided they didn't want the error code in the H1 text */
    +
    +        char *h1 = 4 + status_lines[idx];
    +
    +        ap_bvputs(fd, "<HTML><HEAD>\n<TITLE>", title,
    +               "\n\n

    ", h1, "

    \n", + NULL); + + switch (status) { + case REDIRECT: + case MOVED: + ap_bvputs(fd, "The document has moved pool, location), "\">here.

    \n", NULL); + break; + case HTTP_SEE_OTHER: + ap_bvputs(fd, "The answer to your request is located pool, location), "\">here.

    \n", NULL); + break; + case HTTP_USE_PROXY: + ap_bvputs(fd, "This resource is only accessible through the proxy\n", + ap_escape_html(r->pool, location), "
    \nYou will need to ", + "configure your client to use that proxy.

    \n", NULL); + break; + case HTTP_PROXY_AUTHENTICATION_REQUIRED: + case AUTH_REQUIRED: + ap_bputs("This server could not verify that you\n", fd); + ap_bputs("are authorized to access the document you\n", fd); + ap_bputs("requested. Either you supplied the wrong\n", fd); + ap_bputs("credentials (e.g., bad password), or your\n", fd); + ap_bputs("browser doesn't understand how to supply\n", fd); + ap_bputs("the credentials required.

    \n", fd); + break; + case BAD_REQUEST: + ap_bputs("Your browser sent a request that\n", fd); + ap_bputs("this server could not understand.

    \n", fd); + break; + case HTTP_FORBIDDEN: + ap_bvputs(fd, "You don't have permission to access ", + ap_escape_html(r->pool, r->uri), "\non this server.

    \n", + NULL); + break; + case NOT_FOUND: + ap_bvputs(fd, "The requested URL ", ap_escape_html(r->pool, r->uri), + " was not found on this server.

    \n", NULL); + break; + case METHOD_NOT_ALLOWED: + ap_bvputs(fd, "The requested method ", r->method, " is not allowed " + "for the URL ", ap_escape_html(r->pool, r->uri), + ".

    \n", NULL); + break; + case NOT_ACCEPTABLE: + ap_bvputs(fd, + "An appropriate representation of the requested resource ", + ap_escape_html(r->pool, r->uri), + " could not be found on this server.

    \n", NULL); + /* fall through */ + case MULTIPLE_CHOICES: + { + char *list; + if ((list = ap_table_get(r->notes, "variant-list"))) + ap_bputs(list, fd); + } + break; + case LENGTH_REQUIRED: + ap_bvputs(fd, "A request of the requested method ", r->method, + " requires a valid Content-length.

    \n", NULL); + break; + case PRECONDITION_FAILED: + ap_bvputs(fd, "The precondition on the request for the URL ", + ap_escape_html(r->pool, r->uri), " evaluated to false.

    \n", + NULL); + break; + case NOT_IMPLEMENTED: + ap_bvputs(fd, ap_escape_html(r->pool, r->method), " to ", + ap_escape_html(r->pool, r->uri), " not supported.

    \n", NULL); + break; + case BAD_GATEWAY: + ap_bputs("The proxy server received an invalid\015\012", fd); + ap_bputs("response from an upstream server.

    \015\012", fd); + break; + case VARIANT_ALSO_VARIES: + ap_bvputs(fd, "A variant for the requested entity ", + ap_escape_html(r->pool, r->uri), " is itself a ", + "transparently negotiable resource.

    \n", NULL); + break; + case HTTP_REQUEST_TIME_OUT: + ap_bputs("I'm tired of waiting for your request.\n", fd); + break; + case HTTP_GONE: + ap_bvputs(fd, "The requested resource
    ", + ap_escape_html(r->pool, r->uri), + "
    \nis no longer available on this server ", + "and there is no forwarding address.\n", + "Please remove all references to this resource.\n", NULL); + break; + case HTTP_REQUEST_ENTITY_TOO_LARGE: + ap_bvputs(fd, "The requested resource
    ", + ap_escape_html(r->pool, r->uri), "
    \n", + "does not allow request data with ", r->method, + " requests, or the amount of data provided in\n", + "the request exceeds the capacity limit.\n", NULL); + break; + case HTTP_REQUEST_URI_TOO_LARGE: + ap_bputs("The requested URL's length exceeds the capacity\n", fd); + ap_bputs("limit for this server.\n", fd); + break; + case HTTP_UNSUPPORTED_MEDIA_TYPE: + ap_bputs("The supplied request data is not in a format\n", fd); + ap_bputs("acceptable for processing by this resource.\n", fd); + break; + case HTTP_SERVICE_UNAVAILABLE: + ap_bputs("The server is temporarily unable to service your\n", fd); + ap_bputs("request due to maintenance downtime or capacity\n", fd); + ap_bputs("problems. Please try again later.\n", fd); + break; + case HTTP_GATEWAY_TIME_OUT: + ap_bputs("The proxy server did not receive a timely response\n", fd); + ap_bputs("from the upstream server.

    \n", fd); + break; + default: /* HTTP_INTERNAL_SERVER_ERROR */ + ap_bputs("The server encountered an internal error or\n", fd); + ap_bputs("misconfiguration and was unable to complete\n", fd); + ap_bputs("your request.

    \n", fd); + ap_bputs("Please contact the server administrator,\n ", fd); + ap_bputs(ap_escape_html(r->pool, r->server->server_admin), fd); + ap_bputs(" and inform them of the time the error occurred,\n", fd); + ap_bputs("and anything you might have done that may have\n", fd); + ap_bputs("caused the error.

    \n", fd); + break; + } + + if (recursive_error) { + ap_bvputs(fd, "

    Additionally, a ", + status_lines[ap_index_of_response(recursive_error)], + "\nerror was encountered while trying to use an " + "ErrorDocument to handle the request.\n", NULL); + } + ap_bputs(ap_psignature("


    \n", r), fd); + ap_bputs("\n", fd); + } + ap_kill_timeout(r); + ap_finalize_request_protocol(r); +} diff --git a/APACHE_1_3b7/src/main/http_request.c b/APACHE_1_3b7/src/main/http_request.c new file mode 100644 index 0000000000..4b5c328d50 --- /dev/null +++ b/APACHE_1_3b7/src/main/http_request.c @@ -0,0 +1,1326 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_request.c: functions to get and process requests + * + * Rob McCool 3/21/93 + * + * Thoroughly revamped by rst for Apache. NB this file reads + * best from the bottom up. + * + */ + +#define CORE_PRIVATE +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_log.h" +#include "http_main.h" +#include "scoreboard.h" +#include "fnmatch.h" + +/***************************************************************** + * + * Getting and checking directory configuration. Also checks the + * FollowSymlinks and FollowSymOwner stuff, since this is really the + * only place that can happen (barring a new mid_dir_walk callout). + * + * We can't do it as an access_checker module function which gets + * called with the final per_dir_config, since we could have a directory + * with FollowSymLinks disabled, which contains a symlink to another + * with a .htaccess file which turns FollowSymLinks back on --- and + * access in such a case must be denied. So, whatever it is that + * checks FollowSymLinks needs to know the state of the options as + * they change, all the way down. + */ + +/* + * We don't want people able to serve up pipes, or unix sockets, or other + * scary things. Note that symlink tests are performed later. + */ +static int check_safe_file(request_rec *r) +{ + if (r->finfo.st_mode == 0 /* doesn't exist */ + || S_ISDIR(r->finfo.st_mode) + || S_ISREG(r->finfo.st_mode) + || S_ISLNK(r->finfo.st_mode)) { + return OK; + } + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "object is not a file, directory or symlink: %s", + r->filename); + return HTTP_FORBIDDEN; +} + + +static int check_symlinks(char *d, int opts) +{ +#if defined(__EMX__) || defined(WIN32) + /* OS/2 doesn't have symlinks */ + return OK; +#else + struct stat lfi, fi; + char *lastp; + int res; + + if (opts & OPT_SYM_LINKS) + return OK; + + /* + * Strip trailing '/', if any, off what we're checking; trailing slashes + * make some systems follow symlinks to directories even in lstat(). + * After we've done the lstat, put it back. Also, don't bother checking + * '/' at all... + * + * Note that we don't have to worry about multiple slashes here because of + * no2slash() below... + */ + + lastp = d + strlen(d) - 1; + if (lastp == d) + return OK; /* Root directory, '/' */ + + if (*lastp == '/') + *lastp = '\0'; + else + lastp = NULL; + + res = lstat(d, &lfi); + + if (lastp) + *lastp = '/'; + + /* + * Note that we don't reject accesses to nonexistent files (multiviews or + * the like may cons up a way to run the transaction anyway)... + */ + + if (!(res >= 0) || !S_ISLNK(lfi.st_mode)) + return OK; + + /* OK, it's a symlink. May still be OK with OPT_SYM_OWNER */ + + if (!(opts & OPT_SYM_OWNER)) + return HTTP_FORBIDDEN; + + if (stat(d, &fi) < 0) + return HTTP_FORBIDDEN; + + return (fi.st_uid == lfi.st_uid) ? OK : HTTP_FORBIDDEN; + +#endif +} + +/* Dealing with the file system to get PATH_INFO + */ +static int get_path_info(request_rec *r) +{ + char *cp; + char *path = r->filename; + char *end = &path[strlen(path)]; + char *last_cp = NULL; + int rv; +#ifdef WIN32 + char buf[5]; +#endif + + if (r->finfo.st_mode) { + /* assume path_info already set */ + return OK; + } + +#ifdef WIN32 + /* If the path is x:/, then convert it to x:/., coz that's what stat needs to work properly */ + if(strlen(path) == 3 && path[1] == ':') { + strcpy(buf,path); + buf[3]='.'; + buf[4]='\0'; + path=buf; + end=buf+4; + } +#endif + + /* Advance over trailing slashes ... NOT part of filename */ + + for (cp = end; cp > path && cp[-1] == '/'; --cp) + continue; + + + while (cp > path) { + + /* See if the pathname ending here exists... */ + + *cp = '\0'; + + errno = 0; + rv = stat(path, &r->finfo); + + if (cp != end) + *cp = '/'; + + if (!rv) { + + /* + * Aha! Found something. If it was a directory, we will search + * contents of that directory for a multi_match, so the PATH_INFO + * argument starts with the component after that. + */ + + if (S_ISDIR(r->finfo.st_mode) && last_cp) { + r->finfo.st_mode = 0; /* No such file... */ + cp = last_cp; + } + + r->path_info = ap_pstrdup(r->pool, cp); + *cp = '\0'; + return OK; + } +#if defined(ENOENT) && defined(ENOTDIR) + else if (errno == ENOENT || errno == ENOTDIR) { + last_cp = cp; + + while (--cp > path && *cp != '/') + continue; + + while (cp > path && cp[-1] == '/') + --cp; + } + else { +#if defined(EACCES) + if (errno != EACCES) +#endif + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "access to %s failed for %s", r->uri, + ap_get_remote_host(r->connection, r->per_dir_config, + REMOTE_NOLOOKUP)); + return HTTP_FORBIDDEN; + } +#else +#error ENOENT || ENOTDIR not defined; please see the +#error comments at this line in the source for a workaround. + /* + * If ENOENT || ENOTDIR is not defined in one of the your OS's + * include files, Apache does not know how to check to see why the + * stat() of the index file failed; there are cases where it can fail + * even though the file exists. This means that it is possible for + * someone to get a directory listing of a directory even though + * there is an index (eg. index.html) file in it. If you do not have + * a problem with this, delete the above #error lines and start the + * compile again. If you need to do this, please submit a bug report + * from http://www.apache.org/bug_report.html letting us know that + * you needed to do this. Please be sure to include the operating + * system you are using. + */ + else { + last_cp = cp; + + while (--cp > path && *cp != '/') + continue; + + while (cp > path && cp[-1] == '/') + --cp; + } +#endif /* ENOENT && ENOTDIR */ + } + return OK; +} + +static int directory_walk(request_rec *r) +{ + core_server_config *sconf = ap_get_module_config(r->server->module_config, + &core_module); + void *per_dir_defaults = r->server->lookup_defaults; + void **sec = (void **) sconf->sec->elts; + int num_sec = sconf->sec->nelts; + char *test_filename; + char *test_dirname; + int res; + unsigned i, num_dirs; + int j, test_filename_len; + + /* + * Are we dealing with a file? If not, we can (hopefuly) safely assume we + * have a handler that doesn't require one, but for safety's sake, and so + * we have something find_types() can get something out of, fake one. But + * don't run through the directory entries. + */ + + if (r->filename == NULL) { + r->filename = ap_pstrdup(r->pool, r->uri); + r->finfo.st_mode = 0; /* Not really a file... */ + r->per_dir_config = per_dir_defaults; + + return OK; + } + + /* + * Go down the directory hierarchy. Where we have to check for symlinks, + * do so. Where a .htaccess file has permission to override anything, + * try to find one. If either of these things fails, we could poke + * around, see why, and adjust the lookup_rec accordingly --- this might + * save us a call to get_path_info (with the attendant stat()s); however, + * for the moment, that's not worth the trouble. + * + * Fake filenames (i.e. proxy:) only match Directory sections. + */ + + if (!ap_os_is_path_absolute(r->filename)) + { + void *this_conf, *entry_config; + core_dir_config *entry_core; + char *entry_dir; + + for (j = 0; j < num_sec; ++j) { + + entry_config = sec[j]; + + entry_core = (core_dir_config *) + ap_get_module_config(entry_config, &core_module); + entry_dir = entry_core->d; + + this_conf = NULL; + if (entry_core->r) { + if (!regexec(entry_core->r, r->filename, 0, NULL, 0)) + this_conf = entry_config; + } + else if (entry_core->d_is_fnmatch) { + if (!ap_fnmatch(entry_dir, r->filename, 0)) + this_conf = entry_config; + } + else if (!strncmp(r->filename, entry_dir, strlen(entry_dir))) + this_conf = entry_config; + + if (this_conf) + per_dir_defaults = ap_merge_per_dir_configs(r->pool, + per_dir_defaults, + this_conf); + } + + r->per_dir_config = per_dir_defaults; + + return OK; + } + + r->filename = ap_os_canonical_filename(r->pool, r->filename); + test_filename = ap_pstrdup(r->pool, r->filename); + + ap_no2slash(test_filename); + num_dirs = ap_count_dirs(test_filename); + + res = get_path_info(r); + if (res != OK) { + return res; + } + + if ((res = check_safe_file(r))) { + return res; + } + + test_filename_len = strlen(test_filename); + if (test_filename[test_filename_len - 1] == '/') + --num_dirs; + + if (S_ISDIR(r->finfo.st_mode)) + ++num_dirs; + + /* + * We will use test_dirname as scratch space while we build directory + * names during the walk. Profiling shows directory_walk to be a busy + * function so we try to avoid allocating lots of extra memory here. + * We need 2 extra bytes, one for trailing \0 and one because + * make_dirstr_prefix will add potentially one extra /. + */ + test_dirname = ap_palloc(r->pool, test_filename_len + 2); + + /* j keeps track of which section we're on, see core_reorder_directories */ + j = 0; + for (i = 1; i <= num_dirs; ++i) { + int overrides_here; + core_dir_config *core_dir = (core_dir_config *) + ap_get_module_config(per_dir_defaults, &core_module); + + /* + * XXX: this could be made faster by only copying the next component + * rather than copying the entire thing all over. + */ + ap_make_dirstr_prefix(test_dirname, test_filename, i); + + /* + * Do symlink checks first, because they are done with the + * permissions appropriate to the *parent* directory... + */ + + if ((res = check_symlinks(test_dirname, core_dir->opts))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Symbolic link not allowed: %s", test_dirname); + return res; + } + + /* + * Begin *this* level by looking for matching sections + * from access.conf. + */ + + for (; j < num_sec; ++j) { + void *entry_config = sec[j]; + core_dir_config *entry_core; + char *entry_dir; + void *this_conf; + + entry_core = (core_dir_config *) + ap_get_module_config(entry_config, &core_module); + entry_dir = entry_core->d; + + if (entry_core->r + || !ap_os_is_path_absolute(entry_dir) + || entry_core->d_components > i) + break; + + this_conf = NULL; + if (entry_core->d_is_fnmatch) { + if (!ap_fnmatch(entry_dir, test_dirname, FNM_PATHNAME)) { + this_conf = entry_config; + } + } + else if (!strcmp(test_dirname, entry_dir)) + this_conf = entry_config; + + if (this_conf) { + per_dir_defaults = ap_merge_per_dir_configs(r->pool, + per_dir_defaults, + this_conf); + core_dir = (core_dir_config *) + ap_get_module_config(per_dir_defaults, &core_module); + } + } + overrides_here = core_dir->override; + + /* If .htaccess files are enabled, check for one. */ + + if (overrides_here) { + void *htaccess_conf = NULL; + + res = ap_parse_htaccess(&htaccess_conf, r, overrides_here, + ap_pstrdup(r->pool, test_dirname), + sconf->access_name); + if (res) + return res; + + if (htaccess_conf) + per_dir_defaults = + ap_merge_per_dir_configs(r->pool, per_dir_defaults, + htaccess_conf); + } + } + + /* + * There's two types of IS_SPECIAL sections (see http_core.c), and we've + * already handled the proxy:-style stuff. Now we'll deal with the + * regexes. + */ + for (; j < num_sec; ++j) { + void *entry_config = sec[j]; + core_dir_config *entry_core; + + entry_core = (core_dir_config *) + ap_get_module_config(entry_config, &core_module); + + if (entry_core->r) { + if (!regexec(entry_core->r, test_dirname, 0, NULL, REG_NOTEOL)) { + per_dir_defaults = + ap_merge_per_dir_configs(r->pool, per_dir_defaults, + entry_config); + } + } + } + r->per_dir_config = per_dir_defaults; + + /* + * Symlink permissions are determined by the parent. If the request is + * for a directory then applying the symlink test here would use the + * permissions of the directory as opposed to its parent. Consider a + * symlink pointing to a dir with a .htaccess disallowing symlinks. If + * you access /symlink (or /symlink/) you would get a 403 without this + * S_ISDIR test. But if you accessed /symlink/index.html, for example, + * you would *not* get the 403. + */ + if (!S_ISDIR(r->finfo.st_mode) + && (res = check_symlinks(r->filename, ap_allow_options(r)))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Symbolic link not allowed: %s", r->filename); + return res; + } + return OK; /* Can only "fail" if access denied by the + * symlink goop. */ +} + +static int location_walk(request_rec *r) +{ + core_server_config *sconf = ap_get_module_config(r->server->module_config, + &core_module); + void *per_dir_defaults = r->per_dir_config; + void **url = (void **) sconf->sec_url->elts; + int len, num_url = sconf->sec_url->nelts; + char *test_location; + void *this_conf, *entry_config; + core_dir_config *entry_core; + char *entry_url; + int j; + + if (!num_url) { + return OK; + } + + /* Location and LocationMatch differ on their behaviour w.r.t. multiple + * slashes. Location matches multiple slashes with a single slash, + * LocationMatch doesn't. An exception, for backwards brokenness is + * absoluteURIs... in which case neither match multiple slashes. + */ + if (r->uri[0] != '/') { + test_location = r->uri; + } + else { + test_location = ap_pstrdup(r->pool, r->uri); + ap_no2slash(test_location); + } + + /* Go through the location entries, and check for matches. */ + + /* we apply the directive sections in some order; + * should really try them with the most general first. + */ + for (j = 0; j < num_url; ++j) { + + entry_config = url[j]; + + entry_core = (core_dir_config *) + ap_get_module_config(entry_config, &core_module); + entry_url = entry_core->d; + + len = strlen(entry_url); + + this_conf = NULL; + + if (entry_core->r) { + if (!regexec(entry_core->r, r->uri, 0, NULL, 0)) + this_conf = entry_config; + } + else if (entry_core->d_is_fnmatch) { + if (!ap_fnmatch(entry_url, test_location, FNM_PATHNAME)) { + this_conf = entry_config; + } + } + else if (!strncmp(test_location, entry_url, len) && + (entry_url[len - 1] == '/' || + test_location[len] == '/' || test_location[len] == '\0')) + this_conf = entry_config; + + if (this_conf) + per_dir_defaults = ap_merge_per_dir_configs(r->pool, + per_dir_defaults, this_conf); + } + r->per_dir_config = per_dir_defaults; + + return OK; +} + +static int file_walk(request_rec *r) +{ + core_dir_config *conf = ap_get_module_config(r->per_dir_config, &core_module); + void *per_dir_defaults = r->per_dir_config; + void **file = (void **) conf->sec->elts; + int num_files = conf->sec->nelts; + char *test_file; + + /* get the basename */ + test_file = strrchr(r->filename, '/'); + if (test_file == NULL) { + test_file = r->filename; + } + else { + ++test_file; + } + + /* Go through the file entries, and check for matches. */ + + if (num_files) { + void *this_conf, *entry_config; + core_dir_config *entry_core; + char *entry_file; + int j; + + /* we apply the directive sections in some order; + * should really try them with the most general first. + */ + for (j = 0; j < num_files; ++j) { + + entry_config = file[j]; + + entry_core = (core_dir_config *) + ap_get_module_config(entry_config, &core_module); + entry_file = entry_core->d; + + this_conf = NULL; + + if (entry_core->r) { + if (!regexec(entry_core->r, test_file, 0, NULL, 0)) + this_conf = entry_config; + } + else if (entry_core->d_is_fnmatch) { + if (!ap_fnmatch(entry_file, test_file, FNM_PATHNAME)) { + this_conf = entry_config; + } + } + else if (!strcmp(test_file, entry_file)) { + this_conf = entry_config; + } + + if (this_conf) + per_dir_defaults = ap_merge_per_dir_configs(r->pool, + per_dir_defaults, + this_conf); + } + r->per_dir_config = per_dir_defaults; + } + return OK; +} + +/***************************************************************** + * + * The sub_request mechanism. + * + * Fns to look up a relative URI from, e.g., a map file or SSI document. + * These do all access checks, etc., but don't actually run the transaction + * ... use run_sub_req below for that. Also, be sure to use destroy_sub_req + * as appropriate if you're likely to be creating more than a few of these. + * (An early Apache version didn't destroy the sub_reqs used in directory + * indexing. The result, when indexing a directory with 800-odd files in + * it, was massively excessive storage allocation). + * + * Note more manipulation of protocol-specific vars in the request + * structure... + */ + +static request_rec *make_sub_request(const request_rec *r) +{ + pool *rrp = ap_make_sub_pool(r->pool); + request_rec *rr = ap_pcalloc(rrp, sizeof(request_rec)); + + rr->pool = rrp; + return rr; +} + +API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file, + const request_rec *r) +{ + request_rec *rnew; + int res; + char *udir; + + rnew = make_sub_request(r); + rnew->request_time = r->request_time; + rnew->connection = r->connection; + rnew->server = r->server; + rnew->request_config = ap_create_request_config(rnew->pool); + rnew->htaccess = r->htaccess; + rnew->per_dir_config = r->server->lookup_defaults; + + ap_set_sub_req_protocol(rnew, r); + + if (new_file[0] == '/') + ap_parse_uri(rnew, new_file); + else { + udir = ap_make_dirstr_parent(rnew->pool, r->uri); + udir = escape_uri(rnew->pool, udir); /* re-escape it */ + ap_parse_uri(rnew, ap_make_full_path(rnew->pool, udir, new_file)); + } + + res = ap_unescape_url(rnew->uri); + if (res) { + rnew->status = res; + return rnew; + } + + ap_getparents(rnew->uri); + + if ((res = location_walk(rnew))) { + rnew->status = res; + return rnew; + } + + res = ap_translate_name(rnew); + if (res) { + rnew->status = res; + return rnew; + } + + /* + * We could be clever at this point, and avoid calling directory_walk, + * etc. However, we'd need to test that the old and new filenames contain + * the same directory components, so it would require duplicating the + * start of translate_name. Instead we rely on the cache of .htaccess + * results. + * + * NB: directory_walk() clears the per_dir_config, so we don't inherit + * from location_walk() above + */ + + if ((res = directory_walk(rnew)) + || (res = file_walk(rnew)) + || (res = location_walk(rnew)) + || ((ap_satisfies(rnew) == SATISFY_ALL + || ap_satisfies(rnew) == SATISFY_NOSPEC) + ? ((res = ap_check_access(rnew)) + || (ap_some_auth_required(rnew) + && ((res = ap_check_user_id(rnew)) + || (res = ap_check_auth(rnew))))) + : ((res = ap_check_access(rnew)) + && (!ap_some_auth_required(rnew) + || ((res = ap_check_user_id(rnew)) + || (res = ap_check_auth(rnew))))) + ) + || (res = ap_find_types(rnew)) + || (res = ap_run_fixups(rnew)) + ) { + rnew->status = res; + } + return rnew; +} + +API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file, + const request_rec *r) +{ + request_rec *rnew; + int res; + char *fdir; + + rnew = make_sub_request(r); + rnew->request_time = r->request_time; + rnew->connection = r->connection; + rnew->server = r->server; + rnew->request_config = ap_create_request_config(rnew->pool); + rnew->htaccess = r->htaccess; + + ap_set_sub_req_protocol(rnew, r); + fdir = ap_make_dirstr_parent(rnew->pool, r->filename); + + /* + * Check for a special case... if there are no '/' characters in new_file + * at all, then we are looking at a relative lookup in the same + * directory. That means we won't have to redo directory_walk, and we may + * not even have to redo access checks. + */ + + if (strchr(new_file, '/') == NULL) { + char *udir = ap_make_dirstr_parent(rnew->pool, r->uri); + + rnew->uri = ap_make_full_path(rnew->pool, udir, new_file); + rnew->filename = ap_make_full_path(rnew->pool, fdir, new_file); + ap_parse_uri(rnew, rnew->uri); /* fill in parsed_uri values */ + if (stat(rnew->filename, &rnew->finfo) < 0) { + rnew->finfo.st_mode = 0; + } + + if ((res = check_safe_file(rnew))) { + rnew->status = res; + return rnew; + } + + rnew->per_dir_config = r->per_dir_config; + + /* + * no matter what, if it's a subdirectory, we need to re-run + * directory_walk + */ + if (S_ISDIR(rnew->finfo.st_mode)) { + res = directory_walk(rnew); + if (!res) { + res = file_walk(rnew); + } + } + else { + if ((res = check_symlinks(rnew->filename, ap_allow_options(rnew)))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, rnew->server, + "Symbolic link not allowed: %s", rnew->filename); + rnew->status = res; + return rnew; + } + /* + * do a file_walk, if it doesn't change the per_dir_config then + * we know that we don't have to redo all the access checks + */ + if ((res = file_walk(rnew))) { + rnew->status = res; + return rnew; + } + if (rnew->per_dir_config == r->per_dir_config) { + if ((res = ap_find_types(rnew)) || (res = ap_run_fixups(rnew))) { + rnew->status = res; + } + return rnew; + } + } + } + else { + /* XXX: @@@: What should be done with the parsed_uri values? */ + ap_parse_uri(rnew, new_file); /* fill in parsed_uri values */ + /* + * XXX: this should be set properly like it is in the same-dir case + * but it's actually sometimes to impossible to do it... because the + * file may not have a uri associated with it -djg + */ + rnew->uri = "INTERNALLY GENERATED file-relative req"; + rnew->filename = ((new_file[0] == '/') ? + ap_pstrdup(rnew->pool, new_file) : + ap_make_full_path(rnew->pool, fdir, new_file)); + rnew->per_dir_config = r->server->lookup_defaults; + res = directory_walk(rnew); + if (!res) { + res = file_walk(rnew); + } + } + + if (res + || ((ap_satisfies(rnew) == SATISFY_ALL + || ap_satisfies(rnew) == SATISFY_NOSPEC) + ? ((res = ap_check_access(rnew)) + || (ap_some_auth_required(rnew) + && ((res = ap_check_user_id(rnew)) + || (res = ap_check_auth(rnew))))) + : ((res = ap_check_access(rnew)) + && (!ap_some_auth_required(rnew) + || ((res = ap_check_user_id(rnew)) + || (res = ap_check_auth(rnew))))) + ) + || (res = ap_find_types(rnew)) + || (res = ap_run_fixups(rnew)) + ) { + rnew->status = res; + } + return rnew; +} + +API_EXPORT(int) ap_run_sub_req(request_rec *r) +{ + int retval = ap_invoke_handler(r); + ap_finalize_sub_req_protocol(r); + return retval; +} + +API_EXPORT(void) ap_destroy_sub_req(request_rec *r) +{ + /* Reclaim the space */ + ap_destroy_pool(r->pool); +} + +/***************************************************************** + * + * Mainline request processing... + */ + +void ap_die(int type, request_rec *r) +{ + int error_index = ap_index_of_response(type); + char *custom_response = ap_response_code_string(r, error_index); + int recursive_error = 0; + + if (type == DONE) { + ap_finalize_request_protocol(r); + return; + } + + /* + * The following takes care of Apache redirects to custom response URLs + * Note that if we are already dealing with the response to some other + * error condition, we just report on the original error, and give up on + * any attempt to handle the other thing "intelligently"... + */ + + if (r->status != HTTP_OK) { + recursive_error = type; + + while (r->prev && (r->prev->status != HTTP_OK)) + r = r->prev; /* Get back to original error */ + + type = r->status; + custom_response = NULL; /* Do NOT retry the custom thing! */ + } + + r->status = type; + + /* + * This test is done here so that none of the auth modules needs to know + * about proxy authentication. They treat it like normal auth, and then + * we tweak the status. + */ + if (r->status == AUTH_REQUIRED && r->proxyreq) { + r->status = HTTP_PROXY_AUTHENTICATION_REQUIRED; + } + + /* + * If we want to keep the connection, be sure that the request body + * (if any) has been read. + */ + if ((r->status != HTTP_NOT_MODIFIED) && (r->status != HTTP_NO_CONTENT) + && !status_drops_connection(r->status) + && r->connection && (r->connection->keepalive != -1)) { + + (void) ap_discard_request_body(r); + } + + /* + * Two types of custom redirects --- plain text, and URLs. Plain text has + * a leading '"', so the URL code, here, is triggered on its absence + */ + + if (custom_response && custom_response[0] != '"') { + + if (ap_is_url(custom_response)) { + /* + * The URL isn't local, so lets drop through the rest of this + * apache code, and continue with the usual REDIRECT handler. + * But note that the client will ultimately see the wrong + * status... + */ + r->status = REDIRECT; + ap_table_setn(r->headers_out, "Location", custom_response); + } + else if (custom_response[0] == '/') { + r->no_local_copy = 1; /* Do NOT send USE_LOCAL_COPY for + * error documents! */ + /* + * This redirect needs to be a GET no matter what the original + * method was. + */ + ap_table_setn(r->subprocess_env, "REQUEST_METHOD", r->method); + r->method = ap_pstrdup(r->pool, "GET"); + r->method_number = M_GET; + ap_internal_redirect(custom_response, r); + return; + } + else { + /* + * Dumb user has given us a bad url to redirect to --- fake up + * dying with a recursive server error... + */ + recursive_error = SERVER_ERROR; + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid error redirection directive: %s", + custom_response); + } + } + ap_send_error_response(r, recursive_error); +} + +static void decl_die(int status, char *phase, request_rec *r) +{ + if (status == DECLINED) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, r->server, + "configuration error: couldn't %s: %s", phase, r->uri); + ap_die(SERVER_ERROR, r); + } + else + ap_die(status, r); +} + +API_EXPORT(int) ap_some_auth_required(request_rec *r) +{ + /* Is there a require line configured for the type of *this* req? */ + + array_header *reqs_arr = ap_requires(r); + require_line *reqs; + int i; + + if (!reqs_arr) + return 0; + + reqs = (require_line *) reqs_arr->elts; + + for (i = 0; i < reqs_arr->nelts; ++i) + if (reqs[i].method_mask & (1 << r->method_number)) + return 1; + + return 0; +} + +static void process_request_internal(request_rec *r) +{ + int access_status; + + /* + * Kluge to be reading the assbackwards field outside of protocol.c, but + * we've got to check for this sort of nonsense somewhere... + */ + + if (r->assbackwards && r->header_only) { + /* + * Client asked for headers only with HTTP/0.9, which doesn't send + * headers! Have to dink things even to make sure the error message + * comes through... + */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "client sent illegal HTTP/0.9 request: %s", r->uri); + r->header_only = 0; + ap_die(BAD_REQUEST, r); + return; + } + + if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1,1))) || + ((r->proto_num == HTTP_VERSION(1,1)) && !ap_table_get(r->headers_in, "Host"))) { + /* + * Client sent us a HTTP/1.1 or later request without telling us the + * hostname, either with a full URL or a Host: header. We therefore + * need to (as per the 1.1 spec) send an error. As a special case, + * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain + * a Host: header, and the server MUST respond with 400 if it doesn't. + */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "client sent HTTP/1.1 request without hostname (see RFC2068 section 9, and 14.23): %s", r->uri); + ap_die(BAD_REQUEST, r); + return; + } + + /* Ignore embedded %2F's in path for proxy requests */ + if (!r->proxyreq && r->parsed_uri.path) { + access_status = ap_unescape_url(r->parsed_uri.path); + if (access_status) { + ap_die(access_status, r); + return; + } + } + + ap_getparents(r->uri); /* OK --- shrinking transformations... */ + + if ((access_status = location_walk(r))) { + ap_die(access_status, r); + return; + } + + if ((access_status = ap_translate_name(r))) { + decl_die(access_status, "translate", r); + return; + } + + if (!r->proxyreq) { + /* + * We don't want TRACE to run through the normal handler set, we + * handle it specially. + */ + if (r->method_number == M_TRACE) { + if ((access_status = ap_send_http_trace(r))) + ap_die(access_status, r); + else + ap_finalize_request_protocol(r); + return; + } + } + + if (r->proto_num > HTTP_VERSION(1,0) && ap_table_get(r->subprocess_env, "downgrade-1.0")) { + r->proto_num = HTTP_VERSION(1,0); + } + + /* + * NB: directory_walk() clears the per_dir_config, so we don't inherit + * from location_walk() above + */ + + if ((access_status = directory_walk(r))) { + ap_die(access_status, r); + return; + } + + if ((access_status = file_walk(r))) { + ap_die(access_status, r); + return; + } + + if ((access_status = location_walk(r))) { + ap_die(access_status, r); + return; + } + + if ((access_status = ap_header_parse(r))) { + ap_die(access_status, r); + return; + } + + switch (ap_satisfies(r)) { + case SATISFY_ALL: + case SATISFY_NOSPEC: + if ((access_status = ap_check_access(r)) != 0) { + decl_die(access_status, "check access", r); + return; + } + if (ap_some_auth_required(r)) { + if (((access_status = ap_check_user_id(r)) != 0) || !ap_auth_type(r)) { + decl_die(access_status, ap_auth_type(r) + ? "check user. No user file?" + : "perform authentication. AuthType not set!", r); + return; + } + if (((access_status = ap_check_auth(r)) != 0) || !ap_auth_type(r)) { + decl_die(access_status, ap_auth_type(r) + ? "check access. No groups file?" + : "perform authentication. AuthType not set!", r); + return; + } + } + break; + case SATISFY_ANY: + if (((access_status = ap_check_access(r)) != 0) || !ap_auth_type(r)) { + if (!ap_some_auth_required(r)) { + decl_die(access_status, ap_auth_type(r) + ? "check access" + : "perform authentication. AuthType not set!", r); + return; + } + if (((access_status = ap_check_user_id(r)) != 0) || !ap_auth_type(r)) { + decl_die(access_status, ap_auth_type(r) + ? "check user. No user file?" + : "perform authentication. AuthType not set!", r); + return; + } + if (((access_status = ap_check_auth(r)) != 0) || !ap_auth_type(r)) { + decl_die(access_status, ap_auth_type(r) + ? "check access. No groups file?" + : "perform authentication. AuthType not set!", r); + return; + } + } + break; + } + + if (! (r->proxyreq + && r->parsed_uri.scheme != NULL + && strcmp(r->parsed_uri.scheme, "http") == 0) ) { + if ((access_status = ap_find_types(r)) != 0) { + decl_die(access_status, "find types", r); + return; + } + } + + if ((access_status = ap_run_fixups(r)) != 0) { + ap_die(access_status, r); + return; + } + + if ((access_status = ap_invoke_handler(r)) != 0) { + ap_die(access_status, r); + return; + } + + /* Take care of little things that need to happen when we're done */ + ap_finalize_request_protocol(r); +} + +void ap_process_request(request_rec *r) +{ +#ifdef STATUS + int old_stat; + + ap_time_process_request(r->connection->child_num, START_PREQUEST); +#endif + + process_request_internal(r); + +#ifdef STATUS + old_stat = ap_update_child_status(r->connection->child_num, + SERVER_BUSY_LOG, r); +#endif + + /* + * We want to flush the last packet if this isn't a pipelining connection + * *before* we start into logging. Suppose that the logging causes a DNS + * lookup to occur, which may have a high latency. If we hold off on + * this packet, then it'll appear like the link is stalled when really + * it's the application that's stalled. + */ + ap_bhalfduplex(r->connection->client); + ap_log_transaction(r); + +#ifdef STATUS + (void) ap_update_child_status(r->connection->child_num, old_stat, r); + ap_time_process_request(r->connection->child_num, STOP_PREQUEST); +#endif +} + +static table *rename_original_env(pool *p, table *t) +{ + array_header *env_arr = table_elts(t); + table_entry *elts = (table_entry *) env_arr->elts; + table *new = ap_make_table(p, env_arr->nalloc); + int i; + + for (i = 0; i < env_arr->nelts; ++i) { + if (!elts[i].key) + continue; + ap_table_setn(new, ap_pstrcat(p, "REDIRECT_", elts[i].key, NULL), + elts[i].val); + } + + return new; +} + +static request_rec *internal_internal_redirect(const char *new_uri, request_rec *r) +{ + int access_status; + request_rec *new = (request_rec *) ap_pcalloc(r->pool, sizeof(request_rec)); + + new->connection = r->connection; + new->server = r->server; + new->pool = r->pool; + + /* + * A whole lot of this really ought to be shared with http_protocol.c... + * another missing cleanup. It's particularly inappropriate to be + * setting header_only, etc., here. + */ + + new->method = r->method; + new->method_number = r->method_number; + ap_parse_uri(new, new_uri); + new->request_config = ap_create_request_config(r->pool); + new->per_dir_config = r->server->lookup_defaults; + + new->prev = r; + r->next = new; + + /* Inherit the rest of the protocol info... */ + + new->the_request = r->the_request; + + new->allowed = r->allowed; + + new->status = r->status; + new->assbackwards = r->assbackwards; + new->header_only = r->header_only; + new->protocol = r->protocol; + new->proto_num = r->proto_num; + new->hostname = r->hostname; + new->request_time = r->request_time; + new->main = r->main; + + new->headers_in = r->headers_in; + new->headers_out = ap_make_table(r->pool, 12); + new->err_headers_out = r->err_headers_out; + new->subprocess_env = rename_original_env(r->pool, r->subprocess_env); + new->notes = ap_make_table(r->pool, 5); + + new->htaccess = r->htaccess; + new->no_cache = r->no_cache; + new->no_local_copy = r->no_local_copy; + new->read_length = r->read_length; /* We can only read it once */ + + ap_table_setn(new->subprocess_env, "REDIRECT_STATUS", + ap_psprintf(r->pool, "%d", r->status)); + + /* + * XXX: hmm. This is because mod_setenvif and mod_unique_id really need + * to do their thing on internal redirects as well. Perhaps this is a + * misnamed function. + */ + if ((access_status = ap_run_post_read_request(new))) { + ap_die(access_status, new); + return NULL; + } + + return new; +} + +API_EXPORT(void) ap_internal_redirect(const char *new_uri, request_rec *r) +{ + request_rec *new = internal_internal_redirect(new_uri, r); + process_request_internal(new); +} + +/* This function is designed for things like actions or CGI scripts, when + * using AddHandler, and you want to preserve the content type across + * an internal redirect. + */ +API_EXPORT(void) ap_internal_redirect_handler(const char *new_uri, request_rec *r) +{ + request_rec *new = internal_internal_redirect(new_uri, r); + if (r->handler) + new->content_type = r->content_type; + process_request_internal(new); +} + +/* + * Is it the initial main request, which we only get *once* per HTTP request? + */ +API_EXPORT(int) ap_is_initial_req(request_rec *r) +{ + return + (r->main == NULL) /* otherwise, this is a sub-request */ + && + (r->prev == NULL); /* otherwise, this is an internal redirect */ +} + +/* + * Function to set the r->mtime field to the specified value if it's later + * than what's already there. + */ +API_EXPORT(time_t) ap_update_mtime(request_rec *r, time_t dependency_mtime) +{ + if (r->mtime < dependency_mtime) { + r->mtime = dependency_mtime; + } + return r->mtime; +} diff --git a/APACHE_1_3b7/src/main/http_vhost.c b/APACHE_1_3b7/src/main/http_vhost.c new file mode 100644 index 0000000000..f0dbd1f9a5 --- /dev/null +++ b/APACHE_1_3b7/src/main/http_vhost.c @@ -0,0 +1,917 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_vhost.c: functions pertaining to virtual host addresses + * (configuration and run-time) + */ + +#define CORE_PRIVATE +#include "httpd.h" +#include "http_config.h" +#include "http_conf_globals.h" +#include "http_log.h" +#include "http_vhost.h" +#include "http_protocol.h" + +/* + * After all the definitions there's an explanation of how it's all put + * together. + */ + +/* meta-list of name-vhosts. Each server_rec can be in possibly multiple + * lists of name-vhosts. + */ +typedef struct name_chain name_chain; +struct name_chain { + name_chain *next; + server_addr_rec *sar; /* the record causing it to be in + * this chain (needed for port comparisons) */ + server_rec *server; /* the server to use on a match */ +}; + +/* meta-list of ip addresses. Each server_rec can be in possibly multiple + * hash chains since it can have multiple ips. + */ +typedef struct ipaddr_chain ipaddr_chain; +struct ipaddr_chain { + ipaddr_chain *next; + server_addr_rec *sar; /* the record causing it to be in + * this chain (need for both ip addr and port + * comparisons) */ + server_rec *server; /* the server to use if this matches */ + name_chain *names; /* if non-NULL then a list of name-vhosts + * sharing this address */ +}; + +/* This defines the size of the hash table used for hashing ip addresses + * of virtual hosts. It must be a power of two. + */ +#ifndef IPHASH_TABLE_SIZE +#define IPHASH_TABLE_SIZE 256 +#endif + +/* A (n) bucket hash table, each entry has a pointer to a server rec and + * a pointer to the other entries in that bucket. Each individual address, + * even for virtualhosts with multiple addresses, has an entry in this hash + * table. There are extra buckets for _default_, and name-vhost entries. + * + * Note that after config time this is constant, so it is thread-safe. + */ +static ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE]; + +/* dump out statistics about the hash function */ +/* #define IPHASH_STATISTICS */ + +/* list of the _default_ servers */ +static ipaddr_chain *default_list; + +/* list of the NameVirtualHost addresses */ +static server_addr_rec *name_vhost_list; +static server_addr_rec **name_vhost_list_tail; + +/* + * How it's used: + * + * The ip address determines which chain in iphash_table is interesting, then + * a comparison is done down that chain to find the first ipaddr_chain whose + * sar matches the address:port pair. + * + * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost. + * + * Otherwise it's a name-vhost list, and the default is the server in the + * ipaddr_chain record. We tuck away the ipaddr_chain record in the + * conn_rec field vhost_lookup_data. Later on after the headers we get a + * second chance, and we use the name_chain to figure out what name-vhost + * matches the headers. + * + * If there was no ip address match in the iphash_table then do a lookup + * in the default_list. + * + * How it's put together ... well you should be able to figure that out + * from how it's used. Or something like that. + */ + + +/* called at the beginning of the config */ +void ap_init_vhost_config(pool *p) +{ + memset(iphash_table, 0, sizeof(iphash_table)); + default_list = NULL; + name_vhost_list = NULL; + name_vhost_list_tail = &name_vhost_list; +} + + +/* + * Parses a host of the form
    [:port] + * paddr is used to create a list in the order of input + * **paddr is the ->next pointer of the last entry (or s->addrs) + * *paddr is the variable used to keep track of **paddr between calls + * port is the default port to assume + */ +static const char *get_addresses(pool *p, char *w, server_addr_rec ***paddr, + unsigned port) +{ + struct hostent *hep; + unsigned long my_addr; + server_addr_rec *sar; + char *t; + int i, is_an_ip_addr; + + if (*w == 0) + return NULL; + + t = strchr(w, ':'); + if (t) { + if (strcmp(t + 1, "*") == 0) { + port = 0; + } + else if ((i = atoi(t + 1))) { + port = i; + } + else { + return ":port must be numeric"; + } + *t = 0; + } + + is_an_ip_addr = 0; + if (strcmp(w, "*") == 0) { + my_addr = htonl(INADDR_ANY); + is_an_ip_addr = 1; + } + else if (strcasecmp(w, "_default_") == 0 + || strcmp(w, "255.255.255.255") == 0) { + my_addr = DEFAULT_VHOST_ADDR; + is_an_ip_addr = 1; + } + else if ((my_addr = ap_inet_addr(w)) != INADDR_NONE) { + is_an_ip_addr = 1; + } + if (is_an_ip_addr) { + sar = ap_pcalloc(p, sizeof(server_addr_rec)); + **paddr = sar; + *paddr = &sar->next; + sar->host_addr.s_addr = my_addr; + sar->host_port = port; + sar->virthost = ap_pstrdup(p, w); + if (t != NULL) + *t = ':'; + return NULL; + } + + hep = gethostbyname(w); + + if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "Cannot resolve host name %s --- ignoring!", w); + if (t != NULL) + *t = ':'; + return NULL; + } + + for (i = 0; hep->h_addr_list[i]; ++i) { + sar = ap_pcalloc(p, sizeof(server_addr_rec)); + **paddr = sar; + *paddr = &sar->next; + sar->host_addr = *(struct in_addr *) hep->h_addr_list[i]; + sar->host_port = port; + sar->virthost = ap_pstrdup(p, w); + } + + if (t != NULL) + *t = ':'; + return NULL; +} + + +/* parse the addresses */ +const char *ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s) +{ + server_addr_rec **addrs; + const char *err; + + /* start the list of addreses */ + addrs = &s->addrs; + while (hostname[0]) { + err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port); + if (err) { + *addrs = NULL; + return err; + } + } + /* terminate the list */ + *addrs = NULL; + if (s->addrs) { + if (s->addrs->host_port) { + /* override the default port which is inherited from main_server */ + s->port = s->addrs->host_port; + } + } + return NULL; +} + + +const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg) +{ + /* use whatever port the main server has at this point */ + return get_addresses(cmd->pool, arg, &name_vhost_list_tail, + cmd->server->port); +} + + +/* hash table statistics, keep this in here for the beta period so + * we can find out if the hash function is ok + */ +#ifdef IPHASH_STATISTICS +static int iphash_compare(const void *a, const void *b) +{ + return (*(const int *) b - *(const int *) a); +} + + +static void dump_iphash_statistics(server_rec *main_s) +{ + unsigned count[IPHASH_TABLE_SIZE]; + int i; + ipaddr_chain *src; + unsigned total; + char buf[HUGE_STRING_LEN]; + char *p; + + total = 0; + for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { + count[i] = 0; + for (src = iphash_table[i]; src; src = src->next) { + ++count[i]; + if (i < IPHASH_TABLE_SIZE) { + /* don't count the slop buckets in the total */ + ++total; + } + } + } + qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare); + p = buf + ap_snprintf(buf, sizeof(buf), + "iphash: total hashed = %u, avg chain = %u, " + "chain lengths (count x len):", + total, total / IPHASH_TABLE_SIZE); + total = 1; + for (i = 1; i < IPHASH_TABLE_SIZE; ++i) { + if (count[i - 1] != count[i]) { + p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u", + total, count[i - 1]); + total = 1; + } + else { + ++total; + } + } + p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u", + total, count[IPHASH_TABLE_SIZE - 1]); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf); +} +#endif + + +/* This hashing function is designed to get good distribution in the cases + * where the server is handling entire "networks" of servers. i.e. a + * whack of /24s. This is probably the most common configuration for + * ISPs with large virtual servers. + * + * NOTE: This function is symmetric (i.e. collapses all 4 octets + * into one), so machine byte order (big/little endianness) does not matter. + * + * Hash function provided by David Hankins. + */ +static ap_inline unsigned hash_inaddr(unsigned key) +{ + key ^= (key >> 16); + return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE; +} + + + +static ipaddr_chain *new_ipaddr_chain(pool *p, + server_rec *s, server_addr_rec *sar) +{ + ipaddr_chain *new; + + new = ap_palloc(p, sizeof(*new)); + new->names = NULL; + new->server = s; + new->sar = sar; + new->next = NULL; + return new; +} + + +static name_chain *new_name_chain(pool *p, server_rec *s, server_addr_rec *sar) +{ + name_chain *new; + + new = ap_palloc(p, sizeof(*new)); + new->server = s; + new->sar = sar; + new->next = NULL; + return new; +} + + +static ap_inline ipaddr_chain *find_ipaddr(struct in_addr *server_ip, + unsigned port) +{ + unsigned bucket; + ipaddr_chain *trav; + unsigned addr; + + /* scan the hash table for an exact match first */ + addr = server_ip->s_addr; + bucket = hash_inaddr(addr); + for (trav = iphash_table[bucket]; trav; trav = trav->next) { + server_addr_rec *sar = trav->sar; + if ((sar->host_addr.s_addr == addr) + && (sar->host_port == 0 || sar->host_port == port + || port == 0)) { + return trav; + } + } + return NULL; +} + + +static ipaddr_chain *find_default_server(unsigned port) +{ + server_addr_rec *sar; + ipaddr_chain *trav; + + for (trav = default_list; trav; trav = trav->next) { + sar = trav->sar; + if (sar->host_port == 0 || sar->host_port == port) { + /* match! */ + return trav; + } + } + return NULL; +} + + +static void dump_vhost_config(FILE *f) +{ + int i; + ipaddr_chain *ic; + name_chain *nc; + char buf[MAX_STRING_LEN]; + + fprintf(f, "VirtualHost configuration:\n"); + for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { + for (ic = iphash_table[i]; ic; ic = ic->next) { + if (ic->sar->host_port == 0) { + ap_snprintf(buf, sizeof(buf), "%pA:*", &ic->sar->host_addr); + } + else { + ap_snprintf(buf, sizeof(buf), "%pA:%u", &ic->sar->host_addr, + ic->sar->host_port); + } + if (ic->names == NULL) { + fprintf(f, "%-22s %s (%s:%u)\n", buf, + ic->server->server_hostname, ic->server->defn_name, + ic->server->defn_line_number); + continue; + } + fprintf(f, "%-22s is a NameVirtualHost\n" + "%22s default server %s (%s:%u)\n", + buf, "", ic->server->server_hostname, + ic->server->defn_name, ic->server->defn_line_number); + for (nc = ic->names; nc; nc = nc->next) { + if (nc->sar->host_port) { + fprintf(f, "%22s port %u ", "", nc->sar->host_port); + } + else { + fprintf(f, "%22s port * ", ""); + } + fprintf(f, "namevhost %s (%s:%u)\n", + nc->server->server_hostname, + nc->server->defn_name, + nc->server->defn_line_number); + } + } + } + if (default_list) { + fprintf(f, "_default_ servers:\n"); + for (ic = default_list; ic; ic = ic->next) { + if (ic->sar->host_port == 0) { + fprintf(f, "port * "); + } + else { + fprintf(f, "port %u ", ic->sar->host_port); + } + fprintf(f, "server %s (%s:%u)\n", + ic->server->server_hostname, ic->server->defn_name, + ic->server->defn_line_number); + } + } +} + +/* compile the tables and such we need to do the run-time vhost lookups */ +void ap_fini_vhost_config(pool *p, server_rec *main_s) +{ + server_addr_rec *sar; + int has_default_vhost_addr; + server_rec *s; + int i; + ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE]; + + /* terminate the name_vhost list */ + *name_vhost_list_tail = NULL; + + /* Main host first */ + s = main_s; + + if (!s->server_hostname) { + s->server_hostname = ap_get_local_host(p); + } + + /* initialize the tails */ + for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { + iphash_table_tail[i] = &iphash_table[i]; + } + + /* The first things to go into the hash table are the NameVirtualHosts + * Since name_vhost_list is in the same order that the directives + * occured in the config file, we'll copy it in that order. + */ + for (sar = name_vhost_list; sar; sar = sar->next) { + unsigned bucket = hash_inaddr(sar->host_addr.s_addr); + ipaddr_chain *new = new_ipaddr_chain(p, NULL, sar); + + *iphash_table_tail[bucket] = new; + iphash_table_tail[bucket] = &new->next; + + /* Notice that what we've done is insert an ipaddr_chain with + * both server and names NULL. Remember that. + */ + } + + /* The next things to go into the hash table are the virtual hosts + * themselves. They're listed off of main_s->next in the reverse + * order they occured in the config file, so we insert them at + * the iphash_table_tail but don't advance the tail. + */ + + for (s = main_s->next; s; s = s->next) { + has_default_vhost_addr = 0; + for (sar = s->addrs; sar; sar = sar->next) { + ipaddr_chain *ic; + + if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR + || sar->host_addr.s_addr == INADDR_ANY) { + /* add it to default bucket for each appropriate sar + * since we need to do a port test + */ + ipaddr_chain *other; + + other = find_default_server(sar->host_port); + if (other && other->sar->host_port != 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, main_s, + "_default_ VirtualHost overlap on port %u," + " the first has precedence", sar->host_port); + } + has_default_vhost_addr = 1; + ic = new_ipaddr_chain(p, s, sar); + ic->next = default_list; + default_list = ic; + } + else { + /* see if it matches something we've already got */ + ic = find_ipaddr(&sar->host_addr, sar->host_port); + + /* the first time we encounter a NameVirtualHost address + * ic->server will be NULL, on subsequent encounters + * ic->names will be non-NULL. + */ + if (ic && (ic->names || ic->server == NULL)) { + name_chain *nc = new_name_chain(p, s, sar); + nc->next = ic->names; + ic->names = nc; + ic->server = s; + if (sar->host_port != ic->sar->host_port) { + /* one of the two is a * port, the other isn't */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s, + "VirtualHost %s:%u -- mixing * " + "ports and non-* ports with " + "a NameVirtualHost address is not supported," + " proceeding with undefined results", + sar->virthost, sar->host_port); + } + } + else if (ic) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, main_s, + "VirtualHost %s:%u overlaps with " + "VirtualHost %s:%u, the first has precedence, " + "perhaps you need a NameVirtualHost directive", + sar->virthost, sar->host_port, + ic->sar->virthost, ic->sar->host_port); + ic->sar = sar; + ic->server = s; + } + else { + unsigned bucket = hash_inaddr(sar->host_addr.s_addr); + + ic = new_ipaddr_chain(p, s, sar); + ic->next = *iphash_table_tail[bucket]; + *iphash_table_tail[bucket] = ic; + } + } + } + + /* Ok now we want to set up a server_hostname if the user was + * silly enough to forget one. + * XXX: This is silly we should just crash and burn. + */ + if (!s->server_hostname) { + if (has_default_vhost_addr) { + s->server_hostname = main_s->server_hostname; + } + else if (!s->addrs) { + /* what else can we do? at this point this vhost has + no configured name, probably because they used + DNS in the VirtualHost statement. It's disabled + anyhow by the host matching code. -djg */ + s->server_hostname = + ap_pstrdup(p, "bogus_host_without_forward_dns"); + } + else { + struct hostent *h; + + if ((h = gethostbyaddr((char *) &(s->addrs->host_addr), + sizeof(struct in_addr), AF_INET))) { + s->server_hostname = ap_pstrdup(p, (char *) h->h_name); + } + else { + /* again, what can we do? They didn't specify a + ServerName, and their DNS isn't working. -djg */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s, + "Failed to resolve server name " + "for %s (check DNS) -- or specify an explicit " + "ServerName", + inet_ntoa(s->addrs->host_addr)); + s->server_hostname = + ap_pstrdup(p, "bogus_host_without_reverse_dns"); + } + } + } + } + + /* now go through and delete any NameVirtualHosts that didn't have any + * hosts associated with them. Lamers. + */ + for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { + ipaddr_chain **pic = &iphash_table[i]; + + while (*pic) { + ipaddr_chain *ic = *pic; + + if (ic->server == NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, main_s, + "NameVirtualHost %s:%u has no VirtualHosts", + ic->sar->virthost, ic->sar->host_port); + *pic = ic->next; + } + else if (ic->names == NULL) { + /* if server != NULL and names == NULL then we're done + * looking at NameVirtualHosts + */ + break; + } + else { + pic = &ic->next; + } + } + } + +#ifdef IPHASH_STATISTICS + dump_iphash_statistics(main_s); +#endif + if (ap_dump_settings) { + dump_vhost_config(stderr); + } +} + + +/***************************************************************************** + * run-time vhost matching functions + */ + +/* Remove :port and optionally a single trailing . from the hostname, this + * canonicalizes it somewhat. + */ +static void fix_hostname(request_rec *r) +{ + const char *hostname = r->hostname; + char *host = ap_getword(r->pool, &hostname, ':'); /* get rid of port */ + size_t l; + + /* trim a trailing . */ + l = strlen(host); + if (l > 0 && host[l-1] == '.') { + host[l-1] = '\0'; + } + + r->hostname = host; +} + + +/* return 1 if host matches ServerName or ServerAliases */ +static int matches_aliases(server_rec *s, const char *host) +{ + int i; + array_header *names; + + /* match ServerName */ + if (!strcasecmp(host, s->server_hostname)) { + return 1; + } + + /* search all the aliases from ServerAlias directive */ + names = s->names; + if (names) { + char **name = (char **) names->elts; + for (i = 0; i < names->nelts; ++i) { + if(!name[i]) continue; + if (!strcasecmp(host, name[i])) + return 1; + } + } + names = s->wild_names; + if (names) { + char **name = (char **) names->elts; + for (i = 0; i < names->nelts; ++i) { + if(!name[i]) continue; + if (!ap_strcasecmp_match(host, name[i])) + return 1; + } + } + return 0; +} + + +/* Suppose a request came in on the same socket as this r, and included + * a header "Host: host:port", would it map to r->server? It's more + * than just that though. When we do the normal matches for each request + * we don't even bother considering Host: etc on non-namevirtualhosts, + * we just call it a match. But here we require the host:port to match + * the ServerName and/or ServerAliases. + */ +API_EXPORT(int) ap_matches_request_vhost(request_rec *r, const char *host, + unsigned port) +{ + server_rec *s; + server_addr_rec *sar; + + s = r->server; + + /* search all the values */ + /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing + * consider: + * + * NameVirtualHost 10.1.1.1 + * + * ServerName v1 + * + * + * ServerName v2 + * + * + * Suppose r->server is v2, and we're asked to match "10.1.1.1". We'll say + * "yup it's v2", when really it isn't... if a request came in for 10.1.1.1 + * it would really go to v1. + */ + for (sar = s->addrs; sar; sar = sar->next) { + if ((sar->host_port == 0 || port == sar->host_port) + && !strcasecmp(host, sar->virthost)) { + return 1; + } + } + + /* the Port has to match now, because the rest don't have ports associated + * with them. */ + if (port != s->port) { + return 0; + } + + return matches_aliases(s, host); +} + + +static void check_hostalias(request_rec *r) +{ + /* + * Even if the request has a Host: header containing a port we ignore + * that port. We always use the physical port of the socket. There + * are a few reasons for this: + * + * - the default of 80 or 443 for SSL is easier to handle this way + * - there is less of a possibility of a security problem + * - it simplifies the data structure + * - the client may have no idea that a proxy somewhere along the way + * translated the request to another ip:port + * - except for the addresses from the VirtualHost line, none of the other + * names we'll match have ports associated with them + */ + const char *host = r->hostname; + unsigned port = ntohs(r->connection->local_addr.sin_port); + server_rec *s; + server_rec *last_s; + name_chain *src; + + last_s = NULL; + + /* Recall that the name_chain is a list of server_addr_recs, some of + * whose ports may not match. Also each server may appear more than + * once in the chain -- specifically, it will appear once for each + * address from its VirtualHost line which matched. We only want to + * do the full ServerName/ServerAlias comparisons once for each + * server, fortunately we know that all the VirtualHost addresses for + * a single server are adjacent to each other. + */ + + for (src = r->connection->vhost_lookup_data; src; src = src->next) { + server_addr_rec *sar; + + /* We only consider addresses on the name_chain which have a matching + * port + */ + sar = src->sar; + if (sar->host_port != 0 && port != sar->host_port) { + continue; + } + + s = src->server; + + /* does it match the virthost from the sar? */ + if (!strcasecmp(host, sar->virthost)) { + goto found; + } + + if (s == last_s) { + /* we've already done ServerName and ServerAlias checks for this + * vhost + */ + continue; + } + last_s = s; + + if (matches_aliases(s, host)) { + goto found; + } + } + return; + +found: + /* s is the first matching server, we're done */ + r->server = r->connection->server = s; +} + + +static void check_serverpath(request_rec *r) +{ + server_rec *s; + server_rec *last_s; + name_chain *src; + unsigned port = ntohs(r->connection->local_addr.sin_port); + + /* + * This is in conjunction with the ServerPath code in http_core, so we + * get the right host attached to a non- Host-sending request. + * + * See the comment in check_hostalias about how each vhost can be + * listed multiple times. + */ + + last_s = NULL; + for (src = r->connection->vhost_lookup_data; src; src = src->next) { + /* We only consider addresses on the name_chain which have a matching + * port + */ + if (src->sar->host_port != 0 && port != src->sar->host_port) { + continue; + } + + s = src->server; + if (s == last_s) { + continue; + } + last_s = s; + + if (s->path && !strncmp(r->uri, s->path, s->pathlen) && + (s->path[s->pathlen - 1] == '/' || + r->uri[s->pathlen] == '/' || + r->uri[s->pathlen] == '\0')) { + r->server = r->connection->server = s; + return; + } + } +} + + +void ap_update_vhost_from_headers(request_rec *r) +{ + /* must set this for HTTP/1.1 support */ + if (r->hostname || (r->hostname = ap_table_get(r->headers_in, "Host"))) { + fix_hostname(r); + } + /* check if we tucked away a name_chain */ + if (r->connection->vhost_lookup_data) { + if (r->hostname) + check_hostalias(r); + else + check_serverpath(r); + } +} + + +/* Called for a new connection which has a known local_addr. Note that the + * new connection is assumed to have conn->server == main server. + */ +void ap_update_vhost_given_ip(conn_rec *conn) +{ + ipaddr_chain *trav; + unsigned port = ntohs(conn->local_addr.sin_port); + + /* scan the hash table for an exact match first */ + trav = find_ipaddr(&conn->local_addr.sin_addr, port); + if (trav) { + /* save the name_chain for later in case this is a name-vhost */ + conn->vhost_lookup_data = trav->names; + conn->server = trav->server; + return; + } + + /* There's certainly no name-vhosts with this address, they would have + * been matched above. + */ + conn->vhost_lookup_data = NULL; + + /* maybe there's a default server matching this port */ + trav = find_default_server(port); + if (trav) { + conn->server = trav->server; + } + + /* otherwise we're stuck with just the main server */ +} diff --git a/APACHE_1_3b7/src/main/md5c.c b/APACHE_1_3b7/src/main/md5c.c new file mode 100644 index 0000000000..72ee3fea66 --- /dev/null +++ b/APACHE_1_3b7/src/main/md5c.c @@ -0,0 +1,392 @@ +/* + * This is work is derived from material Copyright RSA Data Security, Inc. + * + * The RSA copyright statement and Licence for that original material is + * included below. This is followed by the Apache copyright statement and + * licence for the modifications made to that material. + */ + +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD5 Message-Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD5 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + */ + +/* ==================================================================== + * Copyright (c) 1996-1998 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 . + * + */ + +#include + +#include "conf.h" +#include "md5.h" +#ifdef CHARSET_EBCDIC +#include "ebcdic.h" +#endif /*CHARSET_EBCDIC*/ + +/* Constants for MD5Transform routine. + */ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform(UINT4 state[4], const unsigned char block[64]); +static void Encode(unsigned char *output, const UINT4 *input, + unsigned int len); +static void Decode(UINT4 *output, const unsigned char *input, + unsigned int len); + +static unsigned char PADDING[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +API_EXPORT(void) ap_MD5Init(AP_MD5_CTX * context) +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +API_EXPORT(void) ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input, + unsigned int inputLen) +{ + unsigned int i, idx, partLen; + + /* Compute number of bytes mod 64 */ + idx = (unsigned int) ((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3)) + context->count[1]++; + context->count[1] += (UINT4) inputLen >> 29; + + partLen = 64 - idx; + + /* Transform as many times as possible. */ +#ifndef CHARSET_EBCDIC + if (inputLen >= partLen) { + memcpy(&context->buffer[idx], input, partLen); + MD5Transform(context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform(context->state, &input[i]); + + idx = 0; + } + else + i = 0; + + /* Buffer remaining input */ + memcpy(&context->buffer[idx], &input[i], inputLen - i); +#else /*CHARSET_EBCDIC*/ + if (inputLen >= partLen) { + ebcdic2ascii_strictly(&context->buffer[idx], input, partLen); + MD5Transform(context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) { + unsigned char inp_tmp[64]; + ebcdic2ascii_strictly(inp_tmp, &input[i], 64); + MD5Transform(context->state, inp_tmp); + } + + idx = 0; + } + else + i = 0; + + /* Buffer remaining input */ + ebcdic2ascii_strictly(&context->buffer[idx], &input[i], inputLen - i); +#endif /*CHARSET_EBCDIC*/ +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +API_EXPORT(void) ap_MD5Final(unsigned char digest[16], AP_MD5_CTX * context) +{ + unsigned char bits[8]; + unsigned int idx, padLen; + + + /* Save number of bits */ + Encode(bits, context->count, 8); + +#ifdef CHARSET_EBCDIC + /* XXX: @@@: In order to make this no more complex than necessary, + * this kludge converts the bits[] array using the ascii-to-ebcdic + * table, because the following ap_MD5Update() re-translates + * its input (ebcdic-to-ascii). + * Otherwise, we would have to pass a "conversion" flag to ap_MD5Update() + */ + ascii2ebcdic(bits,bits,8); + + /* Since everything is converted to ascii within ap_MD5Update(), + * the initial 0x80 (PADDING[0]) must be stored as 0x20 + */ + PADDING[0] = os_toebcdic[0x80]; +#endif /*CHARSET_EBCDIC*/ + + /* Pad out to 56 mod 64. */ + idx = (unsigned int) ((context->count[0] >> 3) & 0x3f); + padLen = (idx < 56) ? (56 - idx) : (120 - idx); + ap_MD5Update(context, PADDING, padLen); + + /* Append length (before padding) */ + ap_MD5Update(context, bits, 8); + + /* Store state in digest */ + Encode(digest, context->state, 16); + + /* Zeroize sensitive information. */ + memset(context, 0, sizeof(*context)); +} + +/* MD5 basic transformation. Transforms state based on block. */ +static void MD5Transform(UINT4 state[4], const unsigned char block[64]) +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode(x, block, 64); + + /* Round 1 */ + FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset(x, 0, sizeof(x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void Encode(unsigned char *output, const UINT4 *input, unsigned int len) +{ + unsigned int i, j; + UINT4 k; + + for (i = 0, j = 0; j < len; i++, j += 4) { + k = input[i]; + output[j] = (unsigned char) (k & 0xff); + output[j + 1] = (unsigned char) ((k >> 8) & 0xff); + output[j + 2] = (unsigned char) ((k >> 16) & 0xff); + output[j + 3] = (unsigned char) ((k >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void Decode(UINT4 *output, const unsigned char *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | + (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24); +} diff --git a/APACHE_1_3b7/src/main/rfc1413.c b/APACHE_1_3b7/src/main/rfc1413.c new file mode 100644 index 0000000000..1cd6c660e8 --- /dev/null +++ b/APACHE_1_3b7/src/main/rfc1413.c @@ -0,0 +1,239 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * rfc1413() speaks a common subset of the RFC 1413, AUTH, TAP and IDENT + * protocols. The code queries an RFC 1413 etc. compatible daemon on a remote + * host to look up the owner of a connection. The information should not be + * used for authentication purposes. This routine intercepts alarm signals. + * + * Diagnostics are reported through syslog(3). + * + * Author: Wietse Venema, Eindhoven University of Technology, + * The Netherlands. + */ + +/* Some small additions for Apache --- ditch the "sccsid" var if + * compiling with gcc (it *has* changed), include conf.h for the + * prototypes it defines on at least one system (SunlOSs) which has + * them missing from the standard header files, and one minor change + * below (extra parens around assign "if (foo = bar) ..." to shut up + * gcc -Wall). + */ + +/* Rewritten by David Robinson */ + +#include "httpd.h" /* for server_rec, conn_rec, ap_longjmp, etc. */ +#include "http_log.h" /* for aplog_error */ +#include "rfc1413.h" +#include "http_main.h" /* set_callback_and_alarm */ + +/* Local stuff. */ +/* Semi-well-known port */ +#define RFC1413_PORT 113 +/* maximum allowed length of userid */ +#define RFC1413_USERLEN 512 +/* rough limit on the amount of data we accept. */ +#define RFC1413_MAXDATA 1000 + +#ifndef RFC1413_TIMEOUT +#define RFC1413_TIMEOUT 30 +#endif +#define ANY_PORT 0 /* Any old port will do */ +#define FROM_UNKNOWN "unknown" + +int ap_rfc1413_timeout = RFC1413_TIMEOUT; /* Global so it can be changed */ + +static JMP_BUF timebuf; + +/* bind_connect - bind both ends of a socket */ +/* Ambarish fix this. Very broken */ +static int get_rfc1413(int sock, const struct sockaddr_in *our_sin, + const struct sockaddr_in *rmt_sin, + char user[RFC1413_USERLEN+1], server_rec *srv) +{ + struct sockaddr_in rmt_query_sin, our_query_sin; + unsigned int rmt_port, our_port; + int i; + char *cp; + char buffer[RFC1413_MAXDATA + 1]; + int buflen; + + /* + * Bind the local and remote ends of the query socket to the same + * IP addresses as the connection under investigation. We go + * through all this trouble because the local or remote system + * might have more than one network address. The RFC1413 etc. + * client sends only port numbers; the server takes the IP + * addresses from the query socket. + */ + + our_query_sin = *our_sin; + our_query_sin.sin_port = htons(ANY_PORT); + rmt_query_sin = *rmt_sin; + rmt_query_sin.sin_port = htons(RFC1413_PORT); + + if (bind(sock, (struct sockaddr *) &our_query_sin, + sizeof(struct sockaddr_in)) < 0) { + ap_log_error(APLOG_MARK, APLOG_CRIT, srv, + "bind: rfc1413: Error binding to local port"); + return -1; + } + +/* + * errors from connect usually imply the remote machine doesn't support + * the service + */ + if (connect(sock, (struct sockaddr *) &rmt_query_sin, + sizeof(struct sockaddr_in)) < 0) + return -1; + +/* send the data */ + buflen = ap_snprintf(buffer, sizeof(buffer), "%u,%u\r\n", ntohs(rmt_sin->sin_port), + ntohs(our_sin->sin_port)); + + /* send query to server. Handle short write. */ + i = 0; + while(i < strlen(buffer)) { + int j; + j = write(sock, buffer+i, (strlen(buffer+i))); + if (j < 0 && errno != EINTR) { + ap_log_error(APLOG_MARK, APLOG_CRIT, srv, + "write: rfc1413: error sending request"); + return -1; + } + else if (j > 0) { + i+=j; + } + } + + /* + * Read response from server. - the response should be newline + * terminated according to rfc - make sure it doesn't stomp it's + * way out of the buffer. + */ + + i = 0; + memset(buffer, 0, sizeof(buffer)); + while((cp = strchr(buffer, '\n')) == NULL && i < sizeof(buffer) - 1) { + int j; + j = read(sock, buffer+i, (sizeof(buffer) - 1) - i); + if (j < 0 && errno != EINTR) { + ap_log_error(APLOG_MARK, APLOG_CRIT, srv, + "read: rfc1413: error reading response"); + return -1; + } + else if (j > 0) { + i+=j; + } + } + +/* RFC1413_USERLEN = 512 */ + if (sscanf(buffer, "%u , %u : USERID :%*[^:]:%512s", &rmt_port, &our_port, + user) != 3 || ntohs(rmt_sin->sin_port) != rmt_port + || ntohs(our_sin->sin_port) != our_port) + return -1; + + /* + * Strip trailing carriage return. It is part of the + * protocol, not part of the data. + */ + + if ((cp = strchr(user, '\r'))) + *cp = '\0'; + + return 0; +} + +/* ident_timeout - handle timeouts */ +static void ident_timeout(int sig) +{ + ap_longjmp(timebuf, sig); +} + +/* rfc1413 - return remote user name, given socket structures */ +char *ap_rfc1413(conn_rec *conn, server_rec *srv) +{ + static char user[RFC1413_USERLEN + 1]; /* XXX */ + static char *result; + static int sock; + + result = FROM_UNKNOWN; + + sock = ap_psocket(conn->pool, AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock < 0) { + ap_log_error(APLOG_MARK, APLOG_CRIT, srv, + "socket: rfc1413: error creating socket"); + conn->remote_logname = result; + } + + /* + * Set up a timer so we won't get stuck while waiting for the server. + */ + if (ap_setjmp(timebuf) == 0) { + ap_set_callback_and_alarm(ident_timeout, ap_rfc1413_timeout); + + if (get_rfc1413(sock, &conn->local_addr, &conn->remote_addr, user, srv) >= 0) + result = user; + + ap_set_callback_and_alarm(NULL, 0); + } + ap_pclosesocket(conn->pool, sock); + conn->remote_logname = result; + + return conn->remote_logname; +} diff --git a/APACHE_1_3b7/src/main/util.c b/APACHE_1_3b7/src/main/util.c new file mode 100644 index 0000000000..5a44397a1b --- /dev/null +++ b/APACHE_1_3b7/src/main/util.c @@ -0,0 +1,1742 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * util.c: string utility things + * + * 3/21/93 Rob McCool + * 1995-96 Many changes by the Apache Group + * + */ + +/* Debugging aid: + * #define DEBUG to trace all cfg_open*()/cfg_closefile() calls + * #define DEBUG_CFG_LINES to trace every line read from the config files + */ + +#include "httpd.h" +#include "http_conf_globals.h" /* for user_id & group_id */ +#include "http_log.h" +#if defined(SUNOS4) +/* stdio.h has been read in conf.h already. Add missing prototypes here: */ +extern int fgetc(FILE *); +extern char *fgets(char *s, int, FILE*); +extern int fclose(FILE *); +#endif + +/* A bunch of functions in util.c scan strings looking for certain characters. + * To make that more efficient we encode a lookup table. The test_char_table + * is generated automatically by gen_test_char.c. + */ +#include "test_char.h" + +/* we assume the folks using this ensure 0 <= c < 256... which means + * you need a cast to (unsigned char) first, you can't just plug a + * char in here and get it to work, because if char is signed then it + * will first be sign extended. + */ +#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f)) + +void ap_util_init(void) +{ + /* nothing to do... previously there was run-time initialization of + * test_char_table here + */ +} + + +API_VAR_EXPORT const char ap_month_snames[12][4] = +{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; +API_VAR_EXPORT const char ap_day_snames[7][4] = +{ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +API_EXPORT(char *) ap_get_time() +{ + time_t t; + char *time_string; + + t = time(NULL); + time_string = ctime(&t); + time_string[strlen(time_string) - 1] = '\0'; + return (time_string); +} + +API_EXPORT(char *) ap_ht_time(pool *p, time_t t, const char *fmt, int gmt) +{ + char ts[MAX_STRING_LEN]; + char tf[MAX_STRING_LEN]; + struct tm *tms; + + tms = (gmt ? gmtime(&t) : localtime(&t)); + if(gmt) { + /* Convert %Z to "GMT" and %z to "+0000"; + * on hosts that do not have a time zone string in struct tm, + * strftime must assume its argument is local time. + */ + const char *f; + char *strp; + for(strp = tf, f = fmt; strp < tf + sizeof(tf) - 6 && (*strp = *f) + ; f++, strp++) { + if (*f != '%') continue; + switch (f[1]) { + case '%': + *++strp = *++f; + break; + case 'Z': + *strp++ = 'G'; + *strp++ = 'M'; + *strp = 'T'; + f++; + break; + case 'z': /* common extension */ + *strp++ = '+'; + *strp++ = '0'; + *strp++ = '0'; + *strp++ = '0'; + *strp = '0'; + f++; + break; + } + } + *strp = '\0'; + fmt = tf; + } + + /* check return code? */ + strftime(ts, MAX_STRING_LEN, fmt, tms); + ts[MAX_STRING_LEN - 1] = '\0'; + return ap_pstrdup(p, ts); +} + +API_EXPORT(char *) ap_gm_timestr_822(pool *p, time_t sec) +{ + struct tm *tms; + + tms = gmtime(&sec); + + /* RFC date format; as strftime '%a, %d %b %Y %T GMT' */ + return ap_psprintf(p, + "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[tms->tm_wday], + tms->tm_mday, ap_month_snames[tms->tm_mon], tms->tm_year + 1900, + tms->tm_hour, tms->tm_min, tms->tm_sec); +} + +/* What a pain in the ass. */ +#if defined(HAVE_GMTOFF) +API_EXPORT(struct tm *) ap_get_gmtoff(int *tz) +{ + time_t tt = time(NULL); + struct tm *t; + + t = localtime(&tt); + *tz = (int) (t->tm_gmtoff / 60); + return t; +} +#else +API_EXPORT(struct tm *) ap_get_gmtoff(int *tz) +{ + time_t tt = time(NULL); + struct tm gmt; + struct tm *t; + int days, hours, minutes; + + /* Assume we are never more than 24 hours away. */ + gmt = *gmtime(&tt); /* remember gmtime/localtime return ptr to static */ + t = localtime(&tt); /* buffer... so be careful */ + days = t->tm_yday - gmt.tm_yday; + hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + + t->tm_hour - gmt.tm_hour); + minutes = hours * 60 + t->tm_min - gmt.tm_min; + *tz = minutes; + return t; +} +#endif + + +/* Match = 0, NoMatch = 1, Abort = -1 + * Based loosely on sections of wildmat.c by Rich Salz + * Hmmm... shouldn't this really go component by component? + */ +API_EXPORT(int) ap_strcmp_match(const char *str, const char *exp) +{ + int x, y; + + for (x = 0, y = 0; exp[y]; ++y, ++x) { + if ((!str[x]) && (exp[y] != '*')) + return -1; + if (exp[y] == '*') { + while (exp[++y] == '*'); + if (!exp[y]) + return 0; + while (str[x]) { + int ret; + if ((ret = ap_strcmp_match(&str[x++], &exp[y])) != 1) + return ret; + } + return -1; + } + else if ((exp[y] != '?') && (str[x] != exp[y])) + return 1; + } + return (str[x] != '\0'); +} + +API_EXPORT(int) ap_strcasecmp_match(const char *str, const char *exp) +{ + int x, y; + + for (x = 0, y = 0; exp[y]; ++y, ++x) { + if ((!str[x]) && (exp[y] != '*')) + return -1; + if (exp[y] == '*') { + while (exp[++y] == '*'); + if (!exp[y]) + return 0; + while (str[x]) { + int ret; + if ((ret = ap_strcasecmp_match(&str[x++], &exp[y])) != 1) + return ret; + } + return -1; + } + else if ((exp[y] != '?') && (tolower(str[x]) != tolower(exp[y]))) + return 1; + } + return (str[x] != '\0'); +} + +API_EXPORT(int) ap_is_matchexp(const char *str) +{ + register int x; + + for (x = 0; str[x]; x++) + if ((str[x] == '*') || (str[x] == '?')) + return 1; + return 0; +} + +/* This function substitutes for $0-$9, filling in regular expression + * submatches. Pass it the same nmatch and pmatch arguments that you + * passed regexec(). pmatch should not be greater than the maximum number + * of subexpressions - i.e. one more than the re_nsub member of regex_t. + * + * input should be the string with the $-expressions, source should be the + * string that was matched against. + * + * It returns the substituted string, or NULL on error. + * + * Parts of this code are based on Henry Spencer's regsub(), from his + * AT&T V8 regexp package. + */ + +API_EXPORT(char *) ap_pregsub(pool *p, const char *input, const char *source, + size_t nmatch, regmatch_t pmatch[]) +{ + const char *src = input; + char *dest, *dst; + char c; + size_t no; + int len; + + if (!source) + return NULL; + if (!nmatch) + return ap_pstrdup(p, src); + + /* First pass, find the size */ + + len = 0; + + while ((c = *src++) != '\0') { + if (c == '&') + no = 0; + else if (c == '$' && isdigit(*src)) + no = *src++ - '0'; + else + no = 10; + + if (no > 9) { /* Ordinary character. */ + if (c == '\\' && (*src == '$' || *src == '&')) + c = *src++; + len++; + } + else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) { + len += pmatch[no].rm_eo - pmatch[no].rm_so; + } + + } + + dest = dst = ap_pcalloc(p, len + 1); + + /* Now actually fill in the string */ + + src = input; + + while ((c = *src++) != '\0') { + if (c == '&') + no = 0; + else if (c == '$' && isdigit(*src)) + no = *src++ - '0'; + else + no = 10; + + if (no > 9) { /* Ordinary character. */ + if (c == '\\' && (*src == '$' || *src == '&')) + c = *src++; + *dst++ = c; + } + else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) { + len = pmatch[no].rm_eo - pmatch[no].rm_so; + memcpy(dst, source + pmatch[no].rm_so, len); + dst += len; + } + + } + *dst = '\0'; + + return dest; +} + +/* + * Parse .. so we don't compromise security + */ +API_EXPORT(void) ap_getparents(char *name) +{ + int l, w; + + /* Four paseses, as per RFC 1808 */ + /* a) remove ./ path segments */ + + for (l = 0, w = 0; name[l] != '\0';) { + if (name[l] == '.' && name[l + 1] == '/' && (l == 0 || name[l - 1] == '/')) + l += 2; + else + name[w++] = name[l++]; + } + + /* b) remove trailing . path, segment */ + if (w == 1 && name[0] == '.') + w--; + else if (w > 1 && name[w - 1] == '.' && name[w - 2] == '/') + w--; + name[w] = '\0'; + + /* c) remove all xx/../ segments. (including leading ../ and /../) */ + l = 0; + + while (name[l] != '\0') { + if (name[l] == '.' && name[l + 1] == '.' && name[l + 2] == '/' && + (l == 0 || name[l - 1] == '/')) { + register int m = l + 3, n; + + l = l - 2; + if (l >= 0) { + while (l >= 0 && name[l] != '/') + l--; + l++; + } + else + l = 0; + n = l; + while ((name[n] = name[m])) + (++n, ++m); + } + else + ++l; + } + + /* d) remove trailing xx/.. segment. */ + if (l == 2 && name[0] == '.' && name[1] == '.') + name[0] = '\0'; + else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.' && name[l - 3] == '/') { + l = l - 4; + if (l >= 0) { + while (l >= 0 && name[l] != '/') + l--; + l++; + } + else + l = 0; + name[l] = '\0'; + } +} + +API_EXPORT(void) ap_no2slash(char *name) +{ + char *d, *s; + + s = d = name; + while (*s) { + if ((*d++ = *s) == '/') { + do { + ++s; + } while (*s == '/'); + } + else { + ++s; + } + } + *d = '\0'; +} + + +/* + * copy at most n leading directories of s into d + * d should be at least as large as s plus 1 extra byte + * assumes n > 0 + * the return value is the ever useful pointer to the trailing \0 of d + * + * examples: + * /a/b, 1 ==> / + * /a/b, 2 ==> /a/ + * /a/b, 3 ==> /a/b/ + * /a/b, 4 ==> /a/b/ + */ +API_EXPORT(char *) ap_make_dirstr_prefix(char *d, const char *s, int n) +{ + for (;;) { + *d = *s; + if (*d == '\0') { + *d = '/'; + break; + } + if (*d == '/' && (--n) == 0) + break; + ++d; + ++s; + } + *++d = 0; + return (d); +} + + +/* + * return the parent directory name including trailing / of the file s + */ +API_EXPORT(char *) ap_make_dirstr_parent(pool *p, const char *s) +{ + char *last_slash = strrchr(s, '/'); + char *d; + int l; + + if (last_slash == NULL) { + /* XXX: well this is really broken if this happens */ + return (ap_pstrdup(p, "/")); + } + l = (last_slash - s) + 1; + d = ap_palloc(p, l + 1); + memcpy(d, s, l); + d[l] = 0; + return (d); +} + + +/* + * This function is deprecated. Use one of the preceeding two functions + * which are faster. + */ +API_EXPORT(char *) ap_make_dirstr(pool *p, const char *s, int n) +{ + register int x, f; + char *res; + + for (x = 0, f = 0; s[x]; x++) { + if (s[x] == '/') + if ((++f) == n) { + res = ap_palloc(p, x + 2); + memcpy(res, s, x); + res[x] = '/'; + res[x + 1] = '\0'; + return res; + } + } + + if (s[strlen(s) - 1] == '/') + return ap_pstrdup(p, s); + else + return ap_pstrcat(p, s, "/", NULL); +} + +API_EXPORT(int) ap_count_dirs(const char *path) +{ + register int x, n; + + for (x = 0, n = 0; path[x]; x++) + if (path[x] == '/') + n++; + return n; +} + + +API_EXPORT(void) ap_chdir_file(const char *file) +{ + const char *x; + char buf[HUGE_STRING_LEN]; + + x = strrchr(file, '/'); + if (x == NULL) { + chdir(file); + } + else if (x - file < sizeof(buf) - 1) { + memcpy(buf, file, x - file); + buf[x - file] = '\0'; + chdir(buf); + } + /* XXX: well, this is a silly function, no method of reporting an + * error... ah well. */ +} + +API_EXPORT(char *) ap_getword_nc(pool *atrans, char **line, char stop) +{ + return ap_getword(atrans, (const char **) line, stop); +} + +API_EXPORT(char *) ap_getword(pool *atrans, const char **line, char stop) +{ + char *pos = strchr(*line, stop); + char *res; + + if (!pos) { + res = ap_pstrdup(atrans, *line); + *line += strlen(*line); + return res; + } + + res = ap_pstrndup(atrans, *line, pos - *line); + + while (*pos == stop) { + ++pos; + } + + *line = pos; + + return res; +} + +API_EXPORT(char *) ap_getword_white_nc(pool *atrans, char **line) +{ + return ap_getword_white(atrans, (const char **) line); +} + +API_EXPORT(char *) ap_getword_white(pool *atrans, const char **line) +{ + int pos = -1, x; + char *res; + + for (x = 0; (*line)[x]; x++) { + if (isspace((*line)[x])) { + pos = x; + break; + } + } + + if (pos == -1) { + res = ap_pstrdup(atrans, *line); + *line += strlen(*line); + return res; + } + + res = ap_palloc(atrans, pos + 1); + ap_cpystrn(res, *line, pos + 1); + + while (isspace((*line)[pos])) + ++pos; + + *line += pos; + + return res; +} + +API_EXPORT(char *) ap_getword_nulls_nc(pool *atrans, char **line, char stop) +{ + return ap_getword_nulls(atrans, (const char **) line, stop); +} + +API_EXPORT(char *) ap_getword_nulls(pool *atrans, const char **line, char stop) +{ + char *pos = strchr(*line, stop); + char *res; + + if (!pos) { + res = ap_pstrdup(atrans, *line); + *line += strlen(*line); + return res; + } + + res = ap_pstrndup(atrans, *line, pos - *line); + + ++pos; + + *line = pos; + + return res; +} + +/* Get a word, (new) config-file style --- quoted strings and backslashes + * all honored + */ + +static char *substring_conf(pool *p, const char *start, int len, char quote) +{ + char *result = ap_palloc(p, len + 2); + char *resp = result; + int i; + + for (i = 0; i < len; ++i) { + if (start[i] == '\\' && (start[i + 1] == '\\' + || (quote && start[i + 1] == quote))) + *resp++ = start[++i]; + else + *resp++ = start[i]; + } + + *resp++ = '\0'; + return result; +} + +API_EXPORT(char *) ap_getword_conf_nc(pool *p, char **line) +{ + return ap_getword_conf(p, (const char **) line); +} + +API_EXPORT(char *) ap_getword_conf(pool *p, const char **line) +{ + const char *str = *line, *strend; + char *res; + char quote; + + while (*str && isspace(*str)) + ++str; + + if (!*str) { + *line = str; + return ""; + } + + if ((quote = *str) == '"' || quote == '\'') { + strend = str + 1; + while (*strend && *strend != quote) { + if (*strend == '\\' && strend[1] && strend[1] == quote) + strend += 2; + else + ++strend; + } + res = substring_conf(p, str + 1, strend - str - 1, quote); + + if (*strend == quote) + ++strend; + } + else { + strend = str; + while (*strend && !isspace(*strend)) + ++strend; + + res = substring_conf(p, str, strend - str, 0); + } + + while (*strend && isspace(*strend)) + ++strend; + *line = strend; + return res; +} + +API_EXPORT(int) ap_cfg_closefile(configfile_t *cfp) +{ +#ifdef DEBUG + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Done with config file %s", fp->name); +#endif + return (cfp->close == NULL) ? 0 : cfp->close(cfp->param); +} + +static int cfg_close(void *param) +{ + poolfile_t *cfp = (poolfile_t *) param; + return (ap_pfclose(cfp->pool, cfp->file)); +} + +static int cfg_getch(void *param) +{ + poolfile_t *cfp = (poolfile_t *) param; + return (fgetc(cfp->file)); +} + +static void *cfg_getstr(void *buf, size_t bufsiz, void *param) +{ + poolfile_t *cfp = (poolfile_t *) param; + return (fgets(buf, bufsiz, cfp->file)); +} + +/* Open a configfile_t as FILE, return open configfile_t struct pointer */ +API_EXPORT(configfile_t *) ap_pcfg_openfile(pool *p, const char *name) +{ + configfile_t *new_cfg; + poolfile_t *new_pfile; + FILE *file; + struct stat stbuf; + + if (name == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, NULL, + "Internal error: pcfg_openfile() called with NULL filename"); + return NULL; + } + + file = ap_pfopen(p, name, "r"); +#ifdef DEBUG + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, NULL, + "Opening config file %s (%s)", + name, (file == NULL) ? strerror(errno) : "successful"); +#endif + if (file == NULL) + return NULL; + + if (strcmp(name, "/dev/null") != 0 && + fstat(fileno(file), &stbuf) == 0 && + !S_ISREG(stbuf.st_mode)) { + ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, NULL, + "Access to file %s denied by server: not a regular file", + name); + ap_pfclose(p, file); + return NULL; + } + + new_cfg = ap_palloc(p, sizeof(*new_cfg)); + new_pfile = ap_palloc(p, sizeof(*new_pfile)); + new_pfile->file = file; + new_pfile->pool = p; + new_cfg->param = new_pfile; + new_cfg->name = ap_pstrdup(p, name); + new_cfg->getch = (int (*)(void *)) cfg_getch; + new_cfg->getstr = (void *(*)(void *, size_t, void *)) cfg_getstr; + new_cfg->close = (int (*)(void *)) cfg_close; + new_cfg->line_number = 0; + return new_cfg; +} + + +/* Allocate a configfile_t handle with user defined functions and params */ +API_EXPORT(configfile_t *) ap_pcfg_open_custom(pool *p, const char *descr, + void *param, + int(*getch)(void *param), + void *(*getstr) (void *buf, size_t bufsiz, void *param), + int(*close_func)(void *param)) +{ + configfile_t *new_cfg = ap_palloc(p, sizeof(*new_cfg)); +#ifdef DEBUG + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, NULL, "Opening config handler %s", descr); +#endif + new_cfg->param = param; + new_cfg->name = descr; + new_cfg->getch = getch; + new_cfg->getstr = getstr; + new_cfg->close = close_func; + new_cfg->line_number = 0; + return new_cfg; +} + + +/* Read one character from a configfile_t */ +API_EXPORT(int) ap_cfg_getc(configfile_t *cfp) +{ + register int ch = cfp->getch(cfp->param); + if (ch == LF) + ++cfp->line_number; + return ch; +} + + +/* Read one line from open configfile_t, strip LF, increase line number */ +/* If custom handler does not define a getstr() function, read char by char */ +API_EXPORT(int) ap_cfg_getline(char *buf, size_t bufsize, configfile_t *cfp) +{ + /* If a "get string" function is defined, use it */ + if (cfp->getstr != NULL) { + char *src, *dst; + char *cp; + char *cbuf = buf; + size_t cbufsize = bufsize; + + while (1) { + ++cfp->line_number; + if (cfp->getstr(cbuf, cbufsize, cfp->param) == NULL) + return 1; + + /* + * check for line continuation, + * i.e. match [^\\]\\[\r]\n only + */ + cp = cbuf; + while (cp < cbuf+cbufsize && *cp != '\0') + cp++; + if (cp > cbuf && cp[-1] == LF) { + cp--; + if (cp > cbuf && cp[-1] == CR) + cp--; + if (cp > cbuf && cp[-1] == '\\') { + cp--; + if (!(cp > cbuf && cp[-1] == '\\')) { + /* + * line continuation requested - + * then remove backslash and continue + */ + cbuf = cp; + cbufsize -= (cp-cbuf); + continue; + } + else { + /* + * no real continuation because escaped - + * then just remove escape character + */ + for ( ; cp < cbuf+cbufsize && *cp != '\0'; cp++) + cp[0] = cp[1]; + } + } + } + break; + } + + /* Compress the line, reducing all blanks and tabs to one space. + * Leading and trailing white space is eliminated completely + */ + src = dst = buf; + while (isspace(*src)) + ++src; + while (*src != '\0') + { + /* Copy words */ + while (!isspace(*dst = *src) && *src != '\0') { + ++src; + ++dst; + } + if (*src == '\0') break; + *dst++ = ' '; + while (isspace(*src)) + ++src; + } + *dst = '\0'; + /* blast trailing whitespace */ + while (--dst >= buf && isspace(*dst)) + *dst = '\0'; + +#ifdef DEBUG_CFG_LINES + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Read config: %s", buf); +#endif + return 0; + } else { + /* No "get string" function defined; read character by character */ + register int c; + register size_t i = 0; + + buf[0] = '\0'; + /* skip leading whitespace */ + do { + c = cfp->getch(cfp->param); + } while (c == '\t' || c == ' '); + + if (c == EOF) + return 1; + + if(bufsize < 2) { + /* too small, assume caller is crazy */ + return 1; + } + + while (1) { + if ((c == '\t') || (c == ' ')) { + buf[i++] = ' '; + while ((c == '\t') || (c == ' ')) + c = cfp->getch(cfp->param); + } + if (c == CR) { + /* silently ignore CR (_assume_ that a LF follows) */ + c = cfp->getch(cfp->param); + } + if (c == LF) { + /* increase line number and return on LF */ + ++cfp->line_number; + } + if (c == EOF || c == 0x4 || c == LF || i >= (bufsize - 2)) { + /* + * check for line continuation + */ + if (i > 0 && buf[i-1] == '\\') { + i--; + if (!(i > 0 && buf[i-1] == '\\')) { + /* line is continued */ + c = cfp->getch(cfp->param); + continue; + } + /* else nothing needs be done because + * then the backslash is escaped and + * we just strip to a single one + */ + } + /* blast trailing whitespace */ + while (i > 0 && isspace(buf[i - 1])) + --i; + buf[i] = '\0'; +#ifdef DEBUG_CFG_LINES + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, "Read config: %s", buf); +#endif + return 0; + } + buf[i] = c; + ++i; + c = cfp->getch(cfp->param); + } + } +} + +/* Retrieve a token, spacing over it and returning a pointer to + * the first non-white byte afterwards. Note that these tokens + * are delimited by semis and commas; and can also be delimited + * by whitespace at the caller's option. + */ + +API_EXPORT(char *) ap_get_token(pool *p, char **accept_line, int accept_white) +{ + char *ptr = *accept_line; + char *tok_start; + char *token; + int tok_len; + + /* Find first non-white byte */ + + while (*ptr && isspace(*ptr)) + ++ptr; + + tok_start = ptr; + + /* find token end, skipping over quoted strings. + * (comments are already gone). + */ + + while (*ptr && (accept_white || !isspace(*ptr)) + && *ptr != ';' && *ptr != ',') { + if (*ptr++ == '"') + while (*ptr) + if (*ptr++ == '"') + break; + } + + tok_len = ptr - tok_start; + token = ap_pstrndup(p, tok_start, tok_len); + + /* Advance accept_line pointer to the next non-white byte */ + + while (*ptr && isspace(*ptr)) + ++ptr; + + *accept_line = ptr; + return token; +} + + +/* find http tokens, see the definition of token from RFC2068 */ +API_EXPORT(int) ap_find_token(pool *p, const char *line, const char *tok) +{ + const unsigned char *start_token; + const unsigned char *s; + + if (!line) + return 0; + + s = (const unsigned char *)line; + for (;;) { + /* find start of token, skip all stop characters, note NUL + * isn't a token stop, so we don't need to test for it + */ + while (TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) { + ++s; + } + if (!*s) { + return 0; + } + start_token = s; + /* find end of the token */ + while (*s && !TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) { + ++s; + } + if (!strncasecmp((const char *)start_token, (const char *)tok, s - start_token)) { + return 1; + } + if (!*s) { + return 0; + } + } +} + + +API_EXPORT(int) ap_find_last_token(pool *p, const char *line, const char *tok) +{ + int llen, tlen, lidx; + + if (!line) + return 0; + + llen = strlen(line); + tlen = strlen(tok); + lidx = llen - tlen; + + if ((lidx < 0) || + ((lidx > 0) && !(isspace(line[lidx - 1]) || line[lidx - 1] == ','))) + return 0; + + return (strncasecmp(&line[lidx], tok, tlen) == 0); +} + +API_EXPORT(char *) ap_escape_shell_cmd(pool *p, const char *str) +{ + char *cmd; + unsigned char *d; + const unsigned char *s; + + cmd = ap_palloc(p, 2 * strlen(str) + 1); /* Be safe */ + d = (unsigned char *)cmd; + s = (const unsigned char *)str; + for (; *s; ++s) { + +#if defined(__EMX__) || defined(WIN32) + /* Don't allow '&' in parameters under OS/2. */ + /* This can be used to send commands to the shell. */ + if (*s == '&') { + *d++ = ' '; + continue; + } +#endif + + if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) { + *d++ = '\\'; + } + *d++ = *s; + } + *d = '\0'; + + return cmd; +} + +static char x2c(const char *what) +{ + register char digit; + +#ifndef CHARSET_EBCDIC + digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); + digit *= 16; + digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0')); +#else /*CHARSET_EBCDIC*/ + char xstr[5]; + xstr[0]='0'; + xstr[1]='x'; + xstr[2]=what[0]; + xstr[3]=what[1]; + xstr[4]='\0'; + digit = os_toebcdic[0xFF & strtol(xstr, NULL, 16)]; +#endif /*CHARSET_EBCDIC*/ + return (digit); +} + +/* + * Unescapes a URL. + * Returns 0 on success, non-zero on error + * Failure is due to + * bad % escape returns BAD_REQUEST + * + * decoding %00 -> \0 + * decoding %2f -> / (a special character) + * returns NOT_FOUND + */ +API_EXPORT(int) ap_unescape_url(char *url) +{ + register int x, y, badesc, badpath; + + badesc = 0; + badpath = 0; + for (x = 0, y = 0; url[y]; ++x, ++y) { + if (url[y] != '%') + url[x] = url[y]; + else { + if (!isxdigit(url[y + 1]) || !isxdigit(url[y + 2])) { + badesc = 1; + url[x] = '%'; + } + else { + url[x] = x2c(&url[y + 1]); + y += 2; + if (url[x] == '/' || url[x] == '\0') + badpath = 1; + } + } + } + url[x] = '\0'; + if (badesc) + return BAD_REQUEST; + else if (badpath) + return NOT_FOUND; + else + return OK; +} + +API_EXPORT(char *) ap_construct_server(pool *p, const char *hostname, + unsigned port, const request_rec *r) +{ + if (is_default_port(port, r)) + return ap_pstrdup(p, hostname); + else { + return ap_psprintf(p, "%s:%u", hostname, port); + } +} + +/* c2x takes an unsigned, and expects the caller has guaranteed that + * 0 <= what < 256... which usually means that you have to cast to + * unsigned char first, because (unsigned)(char)(x) fist goes through + * signed extension to an int before the unsigned cast. + * + * The reason for this assumption is to assist gcc code generation -- + * the unsigned char -> unsigned extension is already done earlier in + * both uses of this code, so there's no need to waste time doing it + * again. + */ +static const char c2x_table[] = "0123456789abcdef"; + +static ap_inline unsigned char *c2x(unsigned what, unsigned char *where) +{ + *where++ = '%'; + *where++ = c2x_table[what >> 4]; + *where++ = c2x_table[what & 0xf]; + return where; +} + +/* + * escape_path_segment() escapes a path segment, as defined in RFC 1808. This + * routine is (should be) OS independent. + * + * os_escape_path() converts an OS path to a URL, in an OS dependent way. In all + * cases if a ':' occurs before the first '/' in the URL, the URL should be + * prefixed with "./" (or the ':' escaped). In the case of Unix, this means + * leaving '/' alone, but otherwise doing what escape_path_segment() does. For + * efficiency reasons, we don't use escape_path_segment(), which is provided for + * reference. Again, RFC 1808 is where this stuff is defined. + * + * If partial is set, os_escape_path() assumes that the path will be appended to + * something with a '/' in it (and thus does not prefix "./"). + */ + +API_EXPORT(char *) ap_escape_path_segment(pool *p, const char *segment) +{ + char *copy = ap_palloc(p, 3 * strlen(segment) + 1); + const unsigned char *s = (const unsigned char *)segment; + unsigned char *d = (unsigned char *)copy; + unsigned c; + + while ((c = *s)) { + if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) { + d = c2x(c, d); + } + else { + *d++ = c; + } + ++s; + } + *d = '\0'; + return copy; +} + +API_EXPORT(char *) ap_os_escape_path(pool *p, const char *path, int partial) +{ + char *copy = ap_palloc(p, 3 * strlen(path) + 3); + const unsigned char *s = (const unsigned char *)path; + unsigned char *d = (unsigned char *)copy; + unsigned c; + + if (!partial) { + char *colon = strchr(path, ':'); + char *slash = strchr(path, '/'); + + if (colon && (!slash || colon < slash)) { + *d++ = '.'; + *d++ = '/'; + } + } + while ((c = *s)) { + if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) { + d = c2x(c, d); + } + else { + *d++ = c; + } + ++s; + } + *d = '\0'; + return copy; +} + +/* escape_uri is now a macro for os_escape_path */ + +API_EXPORT(char *) ap_escape_html(pool *p, const char *s) +{ + int i, j; + char *x; + + /* first, count the number of extra characters */ + for (i = 0, j = 0; s[i] != '\0'; i++) + if (s[i] == '<' || s[i] == '>') + j += 3; + else if (s[i] == '&') + j += 4; + + if (j == 0) + return ap_pstrdup(p, s); + x = ap_palloc(p, i + j + 1); + for (i = 0, j = 0; s[i] != '\0'; i++, j++) + if (s[i] == '<') { + memcpy(&x[j], "<", 4); + j += 3; + } + else if (s[i] == '>') { + memcpy(&x[j], ">", 4); + j += 3; + } + else if (s[i] == '&') { + memcpy(&x[j], "&", 5); + j += 4; + } + else + x[j] = s[i]; + + x[j] = '\0'; + return x; +} + +API_EXPORT(int) ap_is_directory(const char *path) +{ + struct stat finfo; + + if (stat(path, &finfo) == -1) + return 0; /* in error condition, just return no */ + + return (S_ISDIR(finfo.st_mode)); +} + +API_EXPORT(char *) ap_make_full_path(pool *a, const char *src1, + const char *src2) +{ + register int x; + + x = strlen(src1); + if (x == 0) + return ap_pstrcat(a, "/", src2, NULL); + + if (src1[x - 1] != '/') + return ap_pstrcat(a, src1, "/", src2, NULL); + else + return ap_pstrcat(a, src1, src2, NULL); +} + +/* + * Check for an absoluteURI syntax (see section 3.2 in RFC2068). + */ +API_EXPORT(int) ap_is_url(const char *u) +{ + register int x; + + for (x = 0; u[x] != ':'; x++) { + if ((!u[x]) || + ((!isalpha(u[x])) && (!isdigit(u[x])) && + (u[x] != '+') && (u[x] != '-') && (u[x] != '.'))) { + return 0; + } + } + + return (x ? 1 : 0); /* If the first character is ':', it's broken, too */ +} + +API_EXPORT(int) ap_can_exec(const struct stat *finfo) +{ +#ifdef MULTIPLE_GROUPS + int cnt; +#endif +#if defined(__EMX__) || defined(WIN32) + /* OS/2 dosen't have Users and Groups */ + return 1; +#else + if (ap_user_id == finfo->st_uid) + if (finfo->st_mode & S_IXUSR) + return 1; + if (ap_group_id == finfo->st_gid) + if (finfo->st_mode & S_IXGRP) + return 1; +#ifdef MULTIPLE_GROUPS + for (cnt = 0; cnt < NGROUPS_MAX; cnt++) { + if (group_id_list[cnt] == finfo->st_gid) + if (finfo->st_mode & S_IXGRP) + return 1; + } +#endif + return (finfo->st_mode & S_IXOTH); +#endif +} + +#ifdef NEED_STRDUP +char *strdup(const char *str) +{ + char *sdup; + + if (!(sdup = (char *) malloc(strlen(str) + 1))) + return NULL; + sdup = strcpy(sdup, str); + + return sdup; +} +#endif + +/* The following two routines were donated for SVR4 by Andreas Vogel */ +#ifdef NEED_STRCASECMP +int strcasecmp(const char *a, const char *b) +{ + const char *p = a; + const char *q = b; + for (p = a, q = b; *p && *q; p++, q++) { + int diff = tolower(*p) - tolower(*q); + if (diff) + return diff; + } + if (*p) + return 1; /* p was longer than q */ + if (*q) + return -1; /* p was shorter than q */ + return 0; /* Exact match */ +} + +#endif + +#ifdef NEED_STRNCASECMP +int strncasecmp(const char *a, const char *b, int n) +{ + const char *p = a; + const char *q = b; + + for (p = a, q = b; /*NOTHING */ ; p++, q++) { + int diff; + if (p == a + n) + return 0; /* Match up to n characters */ + if (!(*p && *q)) + return *p - *q; + diff = tolower(*p) - tolower(*q); + if (diff) + return diff; + } + /*NOTREACHED */ +} +#endif + + + +#ifdef NEED_INITGROUPS +int initgroups(const char *name, gid_t basegid) +{ +#if defined(QNX) || defined(MPE) || defined(BEOS) || defined(_OSD_POSIX) +/* QNX, MPE and BeOS do not appear to support supplementary groups. */ + return 0; +#else /* ndef QNX */ + gid_t groups[NGROUPS_MAX]; + struct group *g; + int index = 0; + + setgrent(); + + groups[index++] = basegid; + + while (index < NGROUPS_MAX && ((g = getgrent()) != NULL)) + if (g->gr_gid != basegid) { + char **names; + + for (names = g->gr_mem; *names != NULL; ++names) + if (!strcmp(*names, name)) + groups[index++] = g->gr_gid; + } + + endgrent(); + + return setgroups(index, groups); +#endif /* def QNX */ +} +#endif /* def NEED_INITGROUPS */ + +#ifdef NEED_WAITPID +/* From ikluft@amdahl.com + * this is not ideal but it works for SVR3 variants + * httpd does not use the options so this doesn't implement them + */ +int waitpid(pid_t pid, int *statusp, int options) +{ + int tmp_pid; + if (kill(pid, 0) == -1) { + errno = ECHILD; + return -1; + } + while (((tmp_pid = wait(statusp)) != pid) && (tmp_pid != -1)); + return tmp_pid; +} +#endif + +API_EXPORT(int) ap_ind(const char *s, char c) +{ + register int x; + + for (x = 0; s[x]; x++) + if (s[x] == c) + return x; + + return -1; +} + +API_EXPORT(int) ap_rind(const char *s, char c) +{ + register int x; + + for (x = strlen(s) - 1; x != -1; x--) + if (s[x] == c) + return x; + + return -1; +} + +API_EXPORT(void) ap_str_tolower(char *str) +{ + while (*str) { + *str = tolower(*str); + ++str; + } +} + +API_EXPORT(uid_t) ap_uname2id(const char *name) +{ +#ifdef WIN32 + return (1); +#else + struct passwd *ent; + + if (name[0] == '#') + return (atoi(&name[1])); + + if (!(ent = getpwnam(name))) { + fprintf(stderr, "httpd: bad user name %s\n", name); + exit(1); + } + return (ent->pw_uid); +#endif +} + +API_EXPORT(gid_t) ap_gname2id(const char *name) +{ +#ifdef WIN32 + return (1); +#else + struct group *ent; + + if (name[0] == '#') + return (atoi(&name[1])); + + if (!(ent = getgrnam(name))) { + fprintf(stderr, "httpd: bad group name %s\n", name); + exit(1); + } + return (ent->gr_gid); +#endif +} + + +/* + * Parses a host of the form
    [:port] + * :port is permitted if 'port' is not NULL + */ +unsigned long ap_get_virthost_addr(const char *w, unsigned short *ports) +{ + struct hostent *hep; + unsigned long my_addr; + char *p; + + p = strchr(w, ':'); + if (ports != NULL) { + *ports = 0; + if (p != NULL && strcmp(p + 1, "*") != 0) + *ports = atoi(p + 1); + } + + if (p != NULL) + *p = '\0'; + if (strcmp(w, "*") == 0) { + if (p != NULL) + *p = ':'; + return htonl(INADDR_ANY); + } + + my_addr = ap_inet_addr(w); + if (my_addr != INADDR_NONE) { + if (p != NULL) + *p = ':'; + return my_addr; + } + + hep = gethostbyname(w); + + if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) { + fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w); + exit(1); + } + + if (hep->h_addr_list[1]) { + fprintf(stderr, "Host %s has multiple addresses ---\n", w); + fprintf(stderr, "you must choose one explicitly for use as\n"); + fprintf(stderr, "a virtual host. Exiting!!!\n"); + exit(1); + } + + if (p != NULL) + *p = ':'; + + return ((struct in_addr *) (hep->h_addr))->s_addr; +} + + +static char *find_fqdn(pool *a, struct hostent *p) +{ + int x; + + if (!strchr(p->h_name, '.')) { + for (x = 0; p->h_aliases[x]; ++x) { + if (strchr(p->h_aliases[x], '.') && + (!strncasecmp(p->h_aliases[x], p->h_name, strlen(p->h_name)))) + return ap_pstrdup(a, p->h_aliases[x]); + } + return NULL; + } + return ap_pstrdup(a, (void *) p->h_name); +} + +char *ap_get_local_host(pool *a) +{ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + char str[MAXHOSTNAMELEN + 1]; + char *server_hostname; + struct hostent *p; + + if (gethostname(str, sizeof(str) - 1) != 0) { + perror("Unable to gethostname"); + exit(1); + } + str[MAXHOSTNAMELEN] = '\0'; + if ((!(p = gethostbyname(str))) || (!(server_hostname = find_fqdn(a, p)))) { + fprintf(stderr, "httpd: cannot determine local host name.\n"); + fprintf(stderr, "Use ServerName to set it manually.\n"); + exit(1); + } + + return server_hostname; +} + +/* aaaack but it's fast and const should make it shared text page. */ +static const unsigned char pr2six[256] = +{ + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 +}; + +API_EXPORT(char *) ap_uudecode(pool *p, const char *bufcoded) +{ + int nbytesdecoded; + register const unsigned char *bufin; + register char *bufplain; + register unsigned char *bufout; + register int nprbytes; + + /* Strip leading whitespace. */ + + while (*bufcoded == ' ' || *bufcoded == '\t') + bufcoded++; + + /* Figure out how many characters are in the input buffer. + * Allocate this many from the per-transaction pool for the result. + */ +#ifndef CHARSET_EBCDIC + bufin = (const unsigned char *) bufcoded; + while (pr2six[*(bufin++)] <= 63); + nprbytes = (bufin - (const unsigned char *) bufcoded) - 1; + nbytesdecoded = ((nprbytes + 3) / 4) * 3; + + bufplain = ap_palloc(p, nbytesdecoded + 1); + bufout = (unsigned char *) bufplain; + + bufin = (const unsigned char *) bufcoded; + + while (nprbytes > 0) { + *(bufout++) = + (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); + *(bufout++) = + (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); + *(bufout++) = + (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); + bufin += 4; + nprbytes -= 4; + } + + if (nprbytes & 03) { + if (pr2six[bufin[-2]] > 63) + nbytesdecoded -= 2; + else + nbytesdecoded -= 1; + } + bufplain[nbytesdecoded] = '\0'; +#else /*CHARSET_EBCDIC*/ + bufin = (const unsigned char *) bufcoded; + while (pr2six[os_toascii[(unsigned char)*(bufin++)]] <= 63); + nprbytes = (bufin - (const unsigned char *) bufcoded) - 1; + nbytesdecoded = ((nprbytes + 3) / 4) * 3; + + bufplain = ap_palloc(p, nbytesdecoded + 1); + bufout = (unsigned char *) bufplain; + + bufin = (const unsigned char *) bufcoded; + + while (nprbytes > 0) { + *(bufout++) = os_toebcdic[ + (unsigned char) (pr2six[os_toascii[*bufin]] << 2 | pr2six[os_toascii[bufin[1]]] >> 4)]; + *(bufout++) = os_toebcdic[ + (unsigned char) (pr2six[os_toascii[bufin[1]]] << 4 | pr2six[os_toascii[bufin[2]]] >> 2)]; + *(bufout++) = os_toebcdic[ + (unsigned char) (pr2six[os_toascii[bufin[2]]] << 6 | pr2six[os_toascii[bufin[3]]])]; + bufin += 4; + nprbytes -= 4; + } + + if (nprbytes & 03) { + if (pr2six[os_toascii[bufin[-2]]] > 63) + nbytesdecoded -= 2; + else + nbytesdecoded -= 1; + } + bufplain[nbytesdecoded] = '\0'; +#endif /*CHARSET_EBCDIC*/ + return bufplain; +} + +#ifdef __EMX__ +void os2pathname(char *path) +{ + char newpath[MAX_STRING_LEN]; + int loop; + int offset; + + offset = 0; + for (loop = 0; loop < (strlen(path) + 1) && loop < sizeof(newpath) - 1; loop++) { + if (path[loop] == '/') { + newpath[offset] = '\\'; + /* + offset = offset + 1; + newpath[offset] = '\\'; + */ + } + else + newpath[offset] = path[loop]; + offset = offset + 1; + }; + /* Debugging code */ + /* fprintf(stderr, "%s \n", newpath); */ + + strcpy(path, newpath); +}; +#endif + + +#ifdef NEED_STRERROR +char * + strerror(int err) +{ + + char *p; + extern char *const sys_errlist[]; + + p = sys_errlist[err]; + return (p); +} +#endif + +#if defined(NEED_DIFFTIME) +double difftime(time_t time1, time_t time0) +{ + return (time1 - time0); +} +#endif diff --git a/APACHE_1_3b7/src/main/util_date.c b/APACHE_1_3b7/src/main/util_date.c new file mode 100644 index 0000000000..1ad2a8a3f9 --- /dev/null +++ b/APACHE_1_3b7/src/main/util_date.c @@ -0,0 +1,321 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 . + * + */ + +/* + * util_date.c: date parsing utility routines + * These routines are (hopefully) platform-independent. + * + * 27 Oct 1996 Roy Fielding + * Extracted (with many modifications) from mod_proxy.c and + * tested with over 50,000 randomly chosen valid date strings + * and several hundred variations of invalid date strings. + * + */ + +#include "conf.h" +#include "util_date.h" +#include +#include + +/* + * Compare a string to a mask + * Mask characters (arbitrary maximum is 256 characters, just in case): + * @ - uppercase letter + * $ - lowercase letter + * & - hex digit + * # - digit + * ~ - digit or space + * * - swallow remaining characters + * - exact match for any other character + */ +API_EXPORT(int) ap_checkmask(const char *data, const char *mask) +{ + int i; + char d; + + for (i = 0; i < 256; i++) { + d = data[i]; + switch (mask[i]) { + case '\0': + return (d == '\0'); + + case '*': + return 1; + + case '@': + if (!isupper(d)) + return 0; + break; + case '$': + if (!islower(d)) + return 0; + break; + case '#': + if (!isdigit(d)) + return 0; + break; + case '&': + if (!isxdigit(d)) + return 0; + break; + case '~': + if ((d != ' ') && !isdigit(d)) + return 0; + break; + default: + if (mask[i] != d) + return 0; + break; + } + } + return 0; /* We only get here if mask is corrupted (exceeds 256) */ +} + +/* + * tm2sec converts a GMT tm structure into the number of seconds since + * 1st January 1970 UT. Note that we ignore tm_wday, tm_yday, and tm_dst. + * + * The return value is always a valid time_t value -- (time_t)0 is returned + * if the input date is outside that capable of being represented by time(), + * i.e., before Thu, 01 Jan 1970 00:00:00 for all systems and + * beyond 2038 for 32bit systems. + * + * This routine is intended to be very fast, much faster than mktime(). + */ +API_EXPORT(time_t) ap_tm2sec(const struct tm * t) +{ + int year; + time_t days; + static const int dayoffset[12] = + {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275}; + + year = t->tm_year; + + if (year < 70 || ((sizeof(time_t) <= 4) && (year >= 138))) + return BAD_DATE; + + /* shift new year to 1st March in order to make leap year calc easy */ + + if (t->tm_mon < 2) + year--; + + /* Find number of days since 1st March 1900 (in the Gregorian calendar). */ + + days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4; + days += dayoffset[t->tm_mon] + t->tm_mday - 1; + days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */ + + days = ((days * 24 + t->tm_hour) * 60 + t->tm_min) * 60 + t->tm_sec; + + if (days < 0) + return BAD_DATE; /* must have overflowed */ + else + return days; /* must be a valid time */ +} + +/* + * Parses an HTTP date in one of three standard forms: + * + * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 + * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 + * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + * + * and returns the time_t number of seconds since 1 Jan 1970 GMT, or + * 0 if this would be out of range or if the date is invalid. + * + * The restricted HTTP syntax is + * + * HTTP-date = rfc1123-date | rfc850-date | asctime-date + * + * rfc1123-date = wkday "," SP date1 SP time SP "GMT" + * rfc850-date = weekday "," SP date2 SP time SP "GMT" + * asctime-date = wkday SP date3 SP time SP 4DIGIT + * + * date1 = 2DIGIT SP month SP 4DIGIT + * ; day month year (e.g., 02 Jun 1982) + * date2 = 2DIGIT "-" month "-" 2DIGIT + * ; day-month-year (e.g., 02-Jun-82) + * date3 = month SP ( 2DIGIT | ( SP 1DIGIT )) + * ; month day (e.g., Jun 2) + * + * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + * ; 00:00:00 - 23:59:59 + * + * wkday = "Mon" | "Tue" | "Wed" + * | "Thu" | "Fri" | "Sat" | "Sun" + * + * weekday = "Monday" | "Tuesday" | "Wednesday" + * | "Thursday" | "Friday" | "Saturday" | "Sunday" + * + * month = "Jan" | "Feb" | "Mar" | "Apr" + * | "May" | "Jun" | "Jul" | "Aug" + * | "Sep" | "Oct" | "Nov" | "Dec" + * + * However, for the sake of robustness (and Netscapeness), we ignore the + * weekday and anything after the time field (including the timezone). + * + * This routine is intended to be very fast; 10x faster than using sscanf. + * + * Originally from Andrew Daviel , 29 Jul 96 + * but many changes since then. + * + */ +API_EXPORT(time_t) ap_parseHTTPdate(const char *date) +{ + struct tm ds; + int mint, mon; + const char *monstr, *timstr; + static const int months[12] = + { + ('J' << 16) | ('a' << 8) | 'n', ('F' << 16) | ('e' << 8) | 'b', + ('M' << 16) | ('a' << 8) | 'r', ('A' << 16) | ('p' << 8) | 'r', + ('M' << 16) | ('a' << 8) | 'y', ('J' << 16) | ('u' << 8) | 'n', + ('J' << 16) | ('u' << 8) | 'l', ('A' << 16) | ('u' << 8) | 'g', + ('S' << 16) | ('e' << 8) | 'p', ('O' << 16) | ('c' << 8) | 't', + ('N' << 16) | ('o' << 8) | 'v', ('D' << 16) | ('e' << 8) | 'c'}; + + if (!date) + return BAD_DATE; + + while (*date && isspace(*date)) /* Find first non-whitespace char */ + ++date; + + if (*date == '\0') + return BAD_DATE; + + if ((date = strchr(date, ' ')) == NULL) /* Find space after weekday */ + return BAD_DATE; + + ++date; /* Now pointing to first char after space, which should be */ + /* start of the actual date information for all 3 formats. */ + + if (ap_checkmask(date, "## @$$ #### ##:##:## *")) { /* RFC 1123 format */ + ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100; + if (ds.tm_year < 0) + return BAD_DATE; + + ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0'); + + ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0'); + + monstr = date + 3; + timstr = date + 12; + } + else if (ap_checkmask(date, "##-@$$-## ##:##:## *")) { /* RFC 850 format */ + ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0'); + if (ds.tm_year < 70) + ds.tm_year += 100; + + ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0'); + + monstr = date + 3; + timstr = date + 10; + } + else if (ap_checkmask(date, "@$$ ~# ##:##:## ####*")) { /* asctime format */ + ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100; + if (ds.tm_year < 0) + return BAD_DATE; + + ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0'); + + if (date[4] == ' ') + ds.tm_mday = 0; + else + ds.tm_mday = (date[4] - '0') * 10; + + ds.tm_mday += (date[5] - '0'); + + monstr = date; + timstr = date + 7; + } + else + return BAD_DATE; + + if (ds.tm_mday <= 0 || ds.tm_mday > 31) + return BAD_DATE; + + ds.tm_hour = ((timstr[0] - '0') * 10) + (timstr[1] - '0'); + ds.tm_min = ((timstr[3] - '0') * 10) + (timstr[4] - '0'); + ds.tm_sec = ((timstr[6] - '0') * 10) + (timstr[7] - '0'); + + if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61)) + return BAD_DATE; + + mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2]; + for (mon = 0; mon < 12; mon++) + if (mint == months[mon]) + break; + if (mon == 12) + return BAD_DATE; + + if ((ds.tm_mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10)) + return BAD_DATE; + + /* February gets special check for leapyear */ + + if ((mon == 1) && + ((ds.tm_mday > 29) + || ((ds.tm_mday == 29) + && ((ds.tm_year & 3) + || (((ds.tm_year % 100) == 0) + && (((ds.tm_year % 400) != 100))))))) + return BAD_DATE; + + ds.tm_mon = mon; + + return ap_tm2sec(&ds); +} diff --git a/APACHE_1_3b7/src/main/util_md5.c b/APACHE_1_3b7/src/main/util_md5.c new file mode 100644 index 0000000000..ab00b0a1d3 --- /dev/null +++ b/APACHE_1_3b7/src/main/util_md5.c @@ -0,0 +1,196 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/************************************************************************ + * NCSA HTTPd Server + * Software Development Group + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * 605 E. Springfield, Champaign, IL 61820 + * httpd@ncsa.uiuc.edu + * + * Copyright (C) 1995, Board of Trustees of the University of Illinois + * + ************************************************************************ + * + * md5.c: NCSA HTTPd code which uses the md5c.c RSA Code + * + * Original Code Copyright (C) 1994, Jeff Hostetler, Spyglass, Inc. + * Portions of Content-MD5 code Copyright (C) 1993, 1994 by Carnegie Mellon + * University (see Copyright below). + * Portions of Content-MD5 code Copyright (C) 1991 Bell Communications + * Research, Inc. (Bellcore) (see Copyright below). + * Portions extracted from mpack, John G. Myers - jgm+@cmu.edu + * Content-MD5 Code contributed by Martin Hamilton (martin@net.lut.ac.uk) + * + */ + + + +/* md5.c --Module Interface to MD5. */ +/* Jeff Hostetler, Spyglass, Inc., 1994. */ + +#include "httpd.h" +#include "util_md5.h" + +API_EXPORT(char *) ap_md5(pool *p, unsigned char *string) +{ + AP_MD5_CTX my_md5; + unsigned char hash[16]; + char *r, result[33]; + int i; + + /* + * Take the MD5 hash of the string argument. + */ + + ap_MD5Init(&my_md5); + ap_MD5Update(&my_md5, string, strlen((const char *) string)); + ap_MD5Final(hash, &my_md5); + + for (i = 0, r = result; i < 16; i++, r += 2) + sprintf(r, "%02x", hash[i]); + *r = '\0'; + + return ap_pstrdup(p, result); +} + +/* these portions extracted from mpack, John G. Myers - jgm+@cmu.edu */ + +/* (C) Copyright 1993,1994 by Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Carnegie + * Mellon University not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. Carnegie Mellon University makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore) + * + * Permission to use, copy, modify, and distribute this material + * for any purpose and without fee is hereby granted, provided + * that the above copyright notice and this permission notice + * appear in all copies, and that the name of Bellcore not be + * used in advertising or publicity pertaining to this + * material without the specific, prior written permission + * of an authorized representative of Bellcore. BELLCORE + * MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY + * OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS", + * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. + */ + +static char basis_64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +API_EXPORT(char *) ap_md5contextTo64(pool *a, AP_MD5_CTX * context) +{ + unsigned char digest[18]; + char *encodedDigest; + int i; + char *p; + + encodedDigest = (char *) ap_pcalloc(a, 25 * sizeof(char)); + + ap_MD5Final(digest, context); + digest[sizeof(digest) - 1] = digest[sizeof(digest) - 2] = 0; + + p = encodedDigest; + for (i = 0; i < sizeof(digest); i += 3) { + *p++ = basis_64[digest[i] >> 2]; + *p++ = basis_64[((digest[i] & 0x3) << 4) | ((int) (digest[i + 1] & 0xF0) >> 4)]; + *p++ = basis_64[((digest[i + 1] & 0xF) << 2) | ((int) (digest[i + 2] & 0xC0) >> 6)]; + *p++ = basis_64[digest[i + 2] & 0x3F]; + } + *p-- = '\0'; + *p-- = '='; + *p-- = '='; + return encodedDigest; +} + +API_EXPORT(char *) ap_md5digest(pool *p, FILE *infile) +{ + AP_MD5_CTX context; + unsigned char buf[1000]; + long length = 0; + int nbytes; + + ap_MD5Init(&context); + while ((nbytes = fread(buf, 1, sizeof(buf), infile))) { + length += nbytes; + ap_MD5Update(&context, buf, nbytes); + } + rewind(infile); + return ap_md5contextTo64(p, &context); +} diff --git a/APACHE_1_3b7/src/main/util_script.c b/APACHE_1_3b7/src/main/util_script.c new file mode 100644 index 0000000000..c04bb6434c --- /dev/null +++ b/APACHE_1_3b7/src/main/util_script.c @@ -0,0 +1,994 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +#define CORE_PRIVATE +#include "httpd.h" +#include "http_config.h" +#include "http_conf_globals.h" +#include "http_main.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_core.h" /* For document_root. Sigh... */ +#include "http_request.h" /* for sub_req_lookup_uri() */ +#include "util_script.h" +#include "util_date.h" /* For parseHTTPdate() */ + +/* + * Various utility functions which are common to a whole lot of + * script-type extensions mechanisms, and might as well be gathered + * in one place (if only to avoid creating inter-module dependancies + * where there don't have to be). + */ + +#define MALFORMED_MESSAGE "malformed header from script. Bad header=" +#define MALFORMED_HEADER_LENGTH_TO_SHOW 30 + +/* If a request includes query info in the URL (stuff after "?"), and + * the query info does not contain "=" (indicative of a FORM submission), + * then this routine is called to create the argument list to be passed + * to the CGI script. When suexec is enabled, the suexec path, user, and + * group are the first three arguments to be passed; if not, all three + * must be NULL. The query info is split into separate arguments, where + * "+" is the separator between keyword arguments. + * + * XXXX: note that the WIN32 code uses one of the suexec strings + * to pass an interpreter name. Remember this if changing the way they + * are handled in create_argv. + * + */ +static char **create_argv(pool *p, char *path, char *user, char *group, + char *av0, const char *args) +{ + int x, numwords; + char **av; + char *w; + int idx = 0; + + /* count the number of keywords */ + + for (x = 0, numwords = 1; args[x]; x++) + if (args[x] == '+') + ++numwords; + + if (numwords > APACHE_ARG_MAX - 5) { + numwords = APACHE_ARG_MAX - 5; /* Truncate args to prevent overrun */ + } + av = (char **) ap_palloc(p, (numwords + 5) * sizeof(char *)); + + if (path) + av[idx++] = path; + if (user) + av[idx++] = user; + if (group) + av[idx++] = group; + + av[idx++] = av0; + + for (x = 1; x <= numwords; x++) { + w = ap_getword_nulls(p, &args, '+'); + ap_unescape_url(w); + av[idx++] = ap_escape_shell_cmd(p, w); + } + av[idx] = NULL; + return av; +} + + +static char *http2env(pool *a, char *w) +{ + char *res = ap_pstrcat(a, "HTTP_", w, NULL); + char *cp = res; + + while (*++cp) { + if (!isalnum(*cp) && *cp != '_') { + *cp = '_'; + } + else { + *cp = toupper(*cp); + } + } + + return res; +} + +API_EXPORT(char **) ap_create_environment(pool *p, table *t) +{ + array_header *env_arr = table_elts(t); + table_entry *elts = (table_entry *) env_arr->elts; + char **env = (char **) ap_palloc(p, (env_arr->nelts + 2) * sizeof(char *)); + int i, j; + char *tz; + char *whack; + + j = 0; + if (!ap_table_get(t, "TZ")) { + tz = getenv("TZ"); + if (tz != NULL) + env[j++] = ap_pstrcat(p, "TZ=", tz, NULL); + } + for (i = 0; i < env_arr->nelts; ++i) { + if (!elts[i].key) + continue; + env[j] = ap_pstrcat(p, elts[i].key, "=", elts[i].val, NULL); + whack = env[j]; + if (isdigit(*whack)) { + *whack++ = '_'; + } + while (*whack != '=') { + if (!isalnum(*whack) && *whack != '_') { + *whack = '_'; + } + ++whack; + } + ++j; + } + + env[j] = NULL; + return env; +} + +API_EXPORT(void) ap_add_common_vars(request_rec *r) +{ + table *e = r->subprocess_env; + server_rec *s = r->server; + conn_rec *c = r->connection; + const char *rem_logname; + char *env_path; +#ifdef WIN32 + char *env_temp; +#endif + const char *host; + + array_header *hdrs_arr = table_elts(r->headers_in); + table_entry *hdrs = (table_entry *) hdrs_arr->elts; + int i; + + /* First, add environment vars from headers... this is as per + * CGI specs, though other sorts of scripting interfaces see + * the same vars... + */ + + for (i = 0; i < hdrs_arr->nelts; ++i) { + if (!hdrs[i].key) + continue; + + /* A few headers are special cased --- Authorization to prevent + * rogue scripts from capturing passwords; content-type and -length + * for no particular reason. + */ + + if (!strcasecmp(hdrs[i].key, "Content-type")) + ap_table_setn(e, "CONTENT_TYPE", hdrs[i].val); + else if (!strcasecmp(hdrs[i].key, "Content-length")) + ap_table_setn(e, "CONTENT_LENGTH", hdrs[i].val); + /* + * You really don't want to disable this check, since it leaves you + * wide open to CGIs stealing passwords and people viewing them + * in the environment with "ps -e". But, if you must... + */ +#ifndef SECURITY_HOLE_PASS_AUTHORIZATION + else if (!strcasecmp(hdrs[i].key, "Authorization") || + !strcasecmp(hdrs[i].key, "Proxy-Authorization")) + continue; +#endif + else + ap_table_setn(e, http2env(r->pool, hdrs[i].key), hdrs[i].val); + } + + if (!(env_path = getenv("PATH"))) + env_path = DEFAULT_PATH; + +#ifdef WIN32 + if (env_temp = getenv("SystemRoot")) + ap_table_setn(e, "SystemRoot", env_temp); + if (env_temp = getenv("COMSPEC")) + ap_table_setn(e, "COMSPEC", env_temp); + if (env_temp = getenv("WINDIR")) + ap_table_setn(e, "WINDIR", env_temp); +#endif + + ap_table_setn(e, "PATH", env_path); + ap_table_setn(e, "SERVER_SOFTWARE", ap_get_server_version()); + ap_table_setn(e, "SERVER_NAME", ap_get_server_name(r)); + ap_table_setn(e, "SERVER_PORT", ap_psprintf(r->pool, "%u", ap_get_server_port(r))); + host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST); + if (host) { + ap_table_setn(e, "REMOTE_HOST", host); + } + ap_table_setn(e, "REMOTE_ADDR", c->remote_ip); + ap_table_setn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */ + ap_table_setn(e, "SERVER_ADMIN", s->server_admin); /* Apache */ + ap_table_setn(e, "SCRIPT_FILENAME", r->filename); /* Apache */ + + ap_table_setn(e, "REMOTE_PORT", ap_psprintf(r->pool, "%d", ntohs(c->remote_addr.sin_port))); + + if (c->user) + ap_table_setn(e, "REMOTE_USER", c->user); + if (c->ap_auth_type) + ap_table_setn(e, "AUTH_TYPE", c->ap_auth_type); + rem_logname = ap_get_remote_logname(r); + if (rem_logname) + ap_table_setn(e, "REMOTE_IDENT", ap_pstrdup(r->pool, rem_logname)); + + /* Apache custom error responses. If we have redirected set two new vars */ + + if (r->prev) { + if (r->prev->args) + ap_table_setn(e, "REDIRECT_QUERY_STRING", r->prev->args); + if (r->prev->uri) + ap_table_setn(e, "REDIRECT_URL", r->prev->uri); + } +} + +/* This "cute" little function comes about because the path info on + * filenames and URLs aren't always the same. So we take the two, + * and find as much of the two that match as possible. + */ + +API_EXPORT(int) ap_find_path_info(const char *uri, const char *path_info) +{ + int lu = strlen(uri); + int lp = strlen(path_info); + + while (lu-- && lp-- && uri[lu] == path_info[lp]); + + if (lu == -1) + lu = 0; + + while (uri[lu] != '\0' && uri[lu] != '/') + lu++; + + return lu; +} + +/* Obtain the Request-URI from the original request-line, returning + * a new string from the request pool containing the URI or "". + */ +static char *original_uri(request_rec *r) +{ + char *first, *last; + + if (r->the_request == NULL) + return (char *) ap_pcalloc(r->pool, 1); + + first = r->the_request; /* use the request-line */ + + while (*first && !isspace(*first)) + ++first; /* skip over the method */ + while (isspace(*first)) + ++first; /* and the space(s) */ + + last = first; + while (*last && !isspace(*last)) + ++last; /* end at next whitespace */ + + return ap_pstrndup(r->pool, first, last - first); +} + +API_EXPORT(void) ap_add_cgi_vars(request_rec *r) +{ + table *e = r->subprocess_env; + + ap_table_setn(e, "GATEWAY_INTERFACE", "CGI/1.1"); + ap_table_setn(e, "SERVER_PROTOCOL", r->protocol); + ap_table_setn(e, "REQUEST_METHOD", r->method); + ap_table_setn(e, "QUERY_STRING", r->args ? r->args : ""); + ap_table_setn(e, "REQUEST_URI", original_uri(r)); + + /* Note that the code below special-cases scripts run from includes, + * because it "knows" that the sub_request has been hacked to have the + * args and path_info of the original request, and not any that may have + * come with the script URI in the include command. Ugh. + */ + + if (!strcmp(r->protocol, "INCLUDED")) { + ap_table_setn(e, "SCRIPT_NAME", r->uri); + if (r->path_info && *r->path_info) + ap_table_setn(e, "PATH_INFO", r->path_info); + } + else if (!r->path_info || !*r->path_info) { + ap_table_setn(e, "SCRIPT_NAME", r->uri); + } + else { + int path_info_start = ap_find_path_info(r->uri, r->path_info); + + ap_table_setn(e, "SCRIPT_NAME", ap_pstrndup(r->pool, r->uri, + path_info_start)); + + ap_table_setn(e, "PATH_INFO", r->path_info); + } + + if (r->path_info && r->path_info[0]) { + /* + * To get PATH_TRANSLATED, treat PATH_INFO as a URI path. + * Need to re-escape it for this, since the entire URI was + * un-escaped before we determined where the PATH_INFO began. + */ + request_rec *pa_req = ap_sub_req_lookup_uri(escape_uri(r->pool, r->path_info), + r); + + /* Don't bother destroying pa_req --- it's only created in + * child processes which are about to jettison their address + * space anyway. BTW, we concatenate filename and path_info + * from the sub_request to be compatible in case the PATH_INFO + * is pointing to an object which doesn't exist. + */ + + if (pa_req->filename) { +#ifdef WIN32 + char buffer[HUGE_STRING_LEN]; +#endif + char *pt = ap_pstrcat(r->pool, pa_req->filename, pa_req->path_info, + NULL); +#ifdef WIN32 + /* We need to make this a real Windows path name */ + GetFullPathName(pt, HUGE_STRING_LEN, buffer, NULL); + ap_table_setn(e, "PATH_TRANSLATED", ap_pstrdup(r->pool, buffer)); +#else + ap_table_setn(e, "PATH_TRANSLATED", pt); +#endif + } + } +} + + +static int scan_script_header_err_core(request_rec *r, char *buffer, + int (*getsfunc) (char *, int, void *), void *getsfunc_data) +{ + char x[MAX_STRING_LEN]; + char *w, *l; + int p; + int cgi_status = HTTP_OK; + + if (buffer) + *buffer = '\0'; + w = buffer ? buffer : x; + + ap_hard_timeout("read script header", r); + + while (1) { + + if ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data) == 0) { + ap_kill_timeout(r); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Premature end of script headers: %s", r->filename); + return SERVER_ERROR; + } + + /* Delete terminal (CR?)LF */ + + p = strlen(w); + if (p > 0 && w[p - 1] == '\n') { + if (p > 1 && w[p - 2] == '\015') + w[p - 2] = '\0'; + else + w[p - 1] = '\0'; + } + + /* + * If we've finished reading the headers, check to make sure any + * HTTP/1.1 conditions are met. If so, we're done; normal processing + * will handle the script's output. If not, just return the error. + * The appropriate thing to do would be to send the script process a + * SIGPIPE to let it know we're ignoring it, close the channel to the + * script process, and *then* return the failed-to-meet-condition + * error. Otherwise we'd be waiting for the script to finish + * blithering before telling the client the output was no good. + * However, we don't have the information to do that, so we have to + * leave it to an upper layer. + */ + if (w[0] == '\0') { + int cond_status = OK; + + ap_kill_timeout(r); + if ((cgi_status == HTTP_OK) && (r->method_number == M_GET)) { + cond_status = ap_meets_conditions(r); + } + return cond_status; + } + + /* if we see a bogus header don't ignore it. Shout and scream */ + + if (!(l = strchr(w, ':'))) { + char malformed[(sizeof MALFORMED_MESSAGE) + 1 + MALFORMED_HEADER_LENGTH_TO_SHOW]; + strcpy(malformed, MALFORMED_MESSAGE); + strncat(malformed, w, MALFORMED_HEADER_LENGTH_TO_SHOW); + + if (!buffer) + /* Soak up all the script output --- may save an outright kill */ + while ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data)) + continue; + + ap_kill_timeout(r); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "%s: %s", malformed, r->filename); + return SERVER_ERROR; + } + + *l++ = '\0'; + while (*l && isspace(*l)) + ++l; + + if (!strcasecmp(w, "Content-type")) { + + /* Nuke trailing whitespace */ + + char *endp = l + strlen(l) - 1; + while (endp > l && isspace(*endp)) + *endp-- = '\0'; + + r->content_type = ap_pstrdup(r->pool, l); + ap_str_tolower(r->content_type); + } + /* + * If the script returned a specific status, that's what + * we'll use - otherwise we assume 200 OK. + */ + else if (!strcasecmp(w, "Status")) { + r->status = cgi_status = atoi(l); + r->status_line = ap_pstrdup(r->pool, l); + } + else if (!strcasecmp(w, "Location")) { + ap_table_set(r->headers_out, w, l); + } + else if (!strcasecmp(w, "Content-Length")) { + ap_table_set(r->headers_out, w, l); + } + else if (!strcasecmp(w, "Transfer-Encoding")) { + ap_table_set(r->headers_out, w, l); + } + /* + * If the script gave us a Last-Modified header, we can't just + * pass it on blindly because of restrictions on future values. + */ + else if (!strcasecmp(w, "Last-Modified")) { + time_t mtime = ap_parseHTTPdate(l); + + ap_update_mtime(r, mtime); + ap_set_last_modified(r); + } + /* The HTTP specification says that it is legal to merge duplicate + * headers into one. Some browsers that support Cookies don't like + * merged headers and prefer that each Set-Cookie header is sent + * separately. Lets humour those browsers. + */ + else if (!strcasecmp(w, "Set-Cookie")) { + ap_table_add(r->err_headers_out, w, l); + } + else { + ap_table_merge(r->err_headers_out, w, l); + } + } +} + +static int getsfunc_FILE(char *buf, int len, void *f) +{ + return fgets(buf, len, (FILE *) f) != NULL; +} + +API_EXPORT(int) ap_scan_script_header_err(request_rec *r, FILE *f, char *buffer) +{ + return scan_script_header_err_core(r, buffer, getsfunc_FILE, f); +} + +static int getsfunc_BUFF(char *w, int len, void *fb) +{ + return ap_bgets(w, len, (BUFF *) fb) > 0; +} + +API_EXPORT(int) ap_scan_script_header_err_buff(request_rec *r, BUFF *fb, + char *buffer) +{ + return scan_script_header_err_core(r, buffer, getsfunc_BUFF, fb); +} + + +API_EXPORT(void) ap_send_size(size_t size, request_rec *r) +{ + /* XXX: this -1 thing is a gross hack */ + if (size == (size_t)-1) + ap_rputs(" -", r); + else if (!size) + ap_rputs(" 0k", r); + else if (size < 1024) + ap_rputs(" 1k", r); + else if (size < 1048576) + ap_rprintf(r, "%4dk", (size + 512) / 1024); + else if (size < 103809024) + ap_rprintf(r, "%4.1fM", size / 1048576.0); + else + ap_rprintf(r, "%4dM", (size + 524288) / 1048576); +} + +#if defined(__EMX__) || defined(WIN32) +static char **create_argv_cmd(pool *p, char *av0, const char *args, char *path) +{ + register int x, n; + char **av; + char *w; + + for (x = 0, n = 2; args[x]; x++) + if (args[x] == '+') + ++n; + + /* Add extra strings to array. */ + n = n + 2; + + av = (char **) ap_palloc(p, (n + 1) * sizeof(char *)); + av[0] = av0; + + /* Now insert the extra strings we made room for above. */ + av[1] = strdup("/C"); + av[2] = strdup(path); + + for (x = (1 + 2); x < n; x++) { + w = ap_getword(p, &args, '+'); + ap_unescape_url(w); + av[x] = ap_escape_shell_cmd(p, w); + } + av[n] = NULL; + return av; +} +#endif + + +API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0, char **env, int shellcmd) +{ + int pid = 0; +#if defined(RLIMIT_CPU) || defined(RLIMIT_NPROC) || \ + defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS) + + core_dir_config *conf = + (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module); + +#endif + +#ifndef WIN32 + /* the fd on r->server->error_log is closed, but we need somewhere to + * put the error messages from the log_* functions. So, we use stderr, + * since that is better than allowing errors to go unnoticed. Don't do + * this on Win32, though, since we haven't fork()'d. + */ + r->server->error_log = stderr; +#endif + +#ifdef RLIMIT_CPU + if (conf->limit_cpu != NULL) + if ((setrlimit(RLIMIT_CPU, conf->limit_cpu)) != 0) + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "setrlimit: failed to set CPU usage limit"); +#endif +#ifdef RLIMIT_NPROC + if (conf->limit_nproc != NULL) + if ((setrlimit(RLIMIT_NPROC, conf->limit_nproc)) != 0) + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "setrlimit: failed to set process limit"); +#endif +#if defined(RLIMIT_AS) + if (conf->limit_mem != NULL) + if ((setrlimit(RLIMIT_AS, conf->limit_mem)) != 0) + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "setrlimit(RLIMIT_AS): failed to set memory usage limit"); +#elif defined(RLIMIT_DATA) + if (conf->limit_mem != NULL) + if ((setrlimit(RLIMIT_DATA, conf->limit_mem)) != 0) + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "setrlimit(RLIMIT_DATA): failed to set memory usage limit"); +#elif defined(RLIMIT_VMEM) + if (conf->limit_mem != NULL) + if ((setrlimit(RLIMIT_VMEM, conf->limit_mem)) != 0) + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "setrlimit(RLIMIT_VMEM): failed to set memory usage limit"); +#endif + +#ifdef __EMX__ + { + /* Additions by Alec Kloss, to allow exec'ing of scripts under OS/2 */ + int is_script; + char interpreter[2048]; /* hope this is large enough for the interpreter path */ + FILE *program; + program = fopen(r->filename, "rt"); + if (!program) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "fopen(%s) failed", + r->filename); + return (pid); + } + fgets(interpreter, sizeof(interpreter), program); + fclose(program); + if (!strncmp(interpreter, "#!", 2)) { + is_script = 1; + interpreter[strlen(interpreter) - 1] = '\0'; + } + else { + is_script = 0; + } + + if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) { + int emxloop; + char *emxtemp; + + /* For OS/2 place the variables in the current + * enviornment then it will be inherited. This way + * the program will also get all of OS/2's other SETs. + */ + for (emxloop = 0; ((emxtemp = env[emxloop]) != NULL); emxloop++) + putenv(emxtemp); + + /* Additions by Alec Kloss, to allow exec'ing of scripts under OS/2 */ + if (is_script) { + /* here's the stuff to run the interpreter */ + execl(interpreter + 2, interpreter + 2, r->filename, NULL); + } + else if (strstr(strupr(r->filename), ".CMD") > 0) { + /* Special case to allow use of REXX commands as scripts. */ + os2pathname(r->filename); + execl("CMD.EXE", "CMD.EXE", "/C", r->filename, NULL); + } + else { + execl(r->filename, argv0, NULL); + } + } + else { + int emxloop; + char *emxtemp; + + /* For OS/2 place the variables in the current + * environment so that they will be inherited. This way + * the program will also get all of OS/2's other SETs. + */ + for (emxloop = 0; ((emxtemp = env[emxloop]) != NULL); emxloop++) + putenv(emxtemp); + + if (strstr(strupr(r->filename), ".CMD") > 0) { + /* Special case to allow use of REXX commands as scripts. */ + os2pathname(r->filename); + execv("CMD.EXE", create_argv_cmd(r->pool, argv0, r->args, r->filename)); + } + else + execv(r->filename, + create_argv(r->pool, NULL, NULL, NULL, argv0, r->args)); + } + return (pid); + } +#elif defined(WIN32) + { + /* Adapted from work by Alec Kloss, to allow exec'ing of scripts under OS/2 */ + int is_script = 0; + int is_binary = 0; + char interpreter[2048]; /* hope this is large enough for the interpreter path */ + FILE *program; + int i, sz; + char *dot; + char *exename; + int is_exe = 0; + STARTUPINFO si; + PROCESS_INFORMATION pi; + char *pCommand; + + memset(&si, 0, sizeof(si)); + memset(&pi, 0, sizeof(pi)); + + interpreter[0] = 0; + + exename = strrchr(r->filename, '/'); + if (!exename) + exename = strrchr(r->filename, '\\'); + if (!exename) + exename = r->filename; + else + exename++; + dot = strrchr(exename, '.'); + if (dot) { + if (!strcasecmp(dot, ".BAT") || + !strcasecmp(dot, ".CMD") || + !strcasecmp(dot, ".EXE") || + !strcasecmp(dot, ".COM")) + is_exe = 1; + } + + if (!is_exe) { + program = fopen(r->filename, "rb"); + if (!program) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "fopen(%s) failed", r->filename); + return (pid); + } + sz = fread(interpreter, 1, sizeof(interpreter) - 1, program); + if (sz < 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "fread of %s failed", r->filename); + fclose(program); + return (pid); + } + interpreter[sz] = 0; + fclose(program); + if (!strncmp(interpreter, "#!", 2)) { + is_script = 1; + for (i = 2; i < sizeof(interpreter); i++) { + if ((interpreter[i] == '\r') || + (interpreter[i] == '\n')) + break; + } + interpreter[i] = 0; + for (i = 2; interpreter[i] == ' '; ++i) + ; + memmove(interpreter+2,interpreter+i,strlen(interpreter+i)+1); + } + else { + /* Check to see if it's a executable */ + IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)interpreter; + if (hdr->e_magic == IMAGE_DOS_SIGNATURE && hdr->e_cblp < 512) + is_binary = 1; + } + } + + /* + * Make child process use hPipeOutputWrite as standard out, + * and make sure it does not show on screen. + */ + si.cb = sizeof(si); + si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + si.wShowWindow = SW_HIDE; + si.hStdInput = pinfo->hPipeInputRead; + si.hStdOutput = pinfo->hPipeOutputWrite; + si.hStdError = pinfo->hPipeErrorWrite; + + pid = -1; + if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) { + if (is_exe || is_binary) { + /* + * When the CGI is a straight binary executable, + * we can run it as is + */ + pCommand = r->filename; + } + else if (is_script) { + /* When an interpreter is needed, we need to create + * a command line that has the interpreter name + * followed by the CGI script name. + */ + pCommand = ap_pstrcat(r->pool, interpreter + 2, " ", + r->filename, NULL); + } + else { + /* If not an executable or script, just execute it + * from a command prompt. + */ + pCommand = ap_pstrcat(r->pool, "CMD.EXE", " /C ", + r->filename, NULL); + } + } + else { + + /* If we are in this leg, there are some other arguments + * that we must include in the execution of the CGI. + * Because CreateProcess is the way it is, we have to + * create a command line like format for the execution + * of the CGI. This means we need to create on long + * string with the executable and arguments. + * + * The arguments string comes in the request structure, + * and each argument is separated by a '+'. We'll replace + * these pluses with spaces. + */ + char *arguments=NULL; + int iStringSize = 0; + int x; + + /* + * Duplicate the request structure string so we don't change it. + */ + arguments = ap_pstrdup(r->pool, r->args); + + /* + * Change the '+' to ' ' + */ + for (x=0; arguments[x]; x++) { + if ('+' == arguments[x]) { + arguments[x] = ' '; + } + } + + /* + * We need to unescape any characters that are + * in the arguments list. + */ + ap_unescape_url(arguments); + arguments = ap_escape_shell_cmd(r->pool, arguments); + + /* + * The argument list should now be good to use, + * so now build the command line. + */ + if (is_exe || is_binary) { + pCommand = ap_pstrcat(r->pool, r->filename, " ", + arguments, NULL); + } + else if (is_script) { + pCommand = ap_pstrcat(r->pool, interpreter + 2, " ", + r->filename, " ", arguments, NULL); + } + else { + pCommand = ap_pstrcat(r->pool, "CMD.EXE", " /C ", + r->filename, " ", arguments, NULL); + } + } + + if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, 0, env, NULL, &si, &pi)) { + pid = pi.dwProcessId; + /* + * We must close the handles to the new process and its main thread + * to prevent handle and memory leaks. + */ + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } +#if 0 + if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) { + if (is_exe || is_binary) { + pid = spawnle(_P_NOWAIT, r->filename, r->filename, NULL, env); + } + else if (is_script) { + pid = spawnle(_P_NOWAIT, interpreter + 2, interpreter + 2, + r->filename, NULL, env); + } + else { + pid = spawnle(_P_NOWAIT, "CMD.EXE", "CMD.EXE", "/C", + r->filename, NULL, env); + } + } + else { + if (is_exe || is_binary) { + pid = spawnve(_P_NOWAIT, r->filename, + create_argv(r->pool, NULL, NULL, NULL, argv0, + r->args), env); + } + else if (is_script) { + pid = spawnve(_P_NOWAIT, interpreter + 2, + create_argv(r->pool, interpreter + 2, NULL, NULL, + r->filename, r->args), env); + } + else { + pid = spawnve(_P_NOWAIT, "CMD.EXE", + create_argv_cmd(r->pool, argv0, r->args, + r->filename), env); + } + } +#endif + return (pid); + } +#else + if (ap_suexec_enabled && + ((r->server->server_uid != ap_user_id) || + (r->server->server_gid != ap_group_id) || + (!strncmp("/~", r->uri, 2)))) { + + char *execuser, *grpname; + struct passwd *pw; + struct group *gr; + + if (!strncmp("/~", r->uri, 2)) { + gid_t user_gid; + char *username = ap_pstrdup(r->pool, r->uri + 2); + char *pos = strchr(username, '/'); + + if (pos) + *pos = '\0'; + + if ((pw = getpwnam(username)) == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "getpwnam: invalid username %s", username); + return (pid); + } + execuser = ap_pstrcat(r->pool, "~", pw->pw_name, NULL); + user_gid = pw->pw_gid; + + if ((gr = getgrgid(user_gid)) == NULL) { + if ((grpname = ap_palloc(r->pool, 16)) == NULL) + return (pid); + else + ap_snprintf(grpname, 16, "%ld", (long) user_gid); + } + else + grpname = gr->gr_name; + } + else { + if ((pw = getpwuid(r->server->server_uid)) == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "getpwuid: invalid userid %ld", + (long) r->server->server_uid); + return (pid); + } + execuser = ap_pstrdup(r->pool, pw->pw_name); + + if ((gr = getgrgid(r->server->server_gid)) == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "getgrgid: invalid groupid %ld", + (long) r->server->server_gid); + return (pid); + } + grpname = gr->gr_name; + } + + if (shellcmd) + execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0, NULL, env); + + else if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) + execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0, NULL, env); + + else { + execve(SUEXEC_BIN, + create_argv(r->pool, SUEXEC_BIN, execuser, grpname, + argv0, r->args), + env); + } + } + else { + if (shellcmd) + execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env); + + else if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) + execle(r->filename, argv0, NULL, env); + + else + execve(r->filename, + create_argv(r->pool, NULL, NULL, NULL, argv0, r->args), + env); + } + return (pid); +#endif +} diff --git a/APACHE_1_3b7/src/main/util_uri.c b/APACHE_1_3b7/src/main/util_uri.c new file mode 100644 index 0000000000..85740b60ac --- /dev/null +++ b/APACHE_1_3b7/src/main/util_uri.c @@ -0,0 +1,583 @@ +/* ==================================================================== + * Copyright (c) 1998 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. + * + * 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 . + * + */ + +/* + * util_uri.c: URI related utility things + * + */ + +#include "httpd.h" +#include "http_log.h" +#include "http_conf_globals.h" /* for user_id & group_id */ +#include "util_uri.h" + +/* Some WWW schemes and their default ports; this is basically /etc/services */ +/* This will become global when the protocol abstraction comes */ +static schemes_t schemes[] = +{ + {"ftp", DEFAULT_FTP_PORT}, + {"gopher", DEFAULT_GOPHER_PORT}, + {"http", DEFAULT_HTTP_PORT}, + {"nntp", DEFAULT_NNTP_PORT}, + {"wais", DEFAULT_WAIS_PORT}, + {"https", DEFAULT_HTTPS_PORT}, + {"snews", DEFAULT_SNEWS_PORT}, + {"prospero", DEFAULT_PROSPERO_PORT}, + { NULL, 0xFFFF } /* unknown port */ +}; + + +API_EXPORT(unsigned short) ap_default_port_for_scheme(const char *scheme_str) +{ + schemes_t *scheme; + + for (scheme = schemes; scheme->name != NULL; ++scheme) + if (strcasecmp(scheme_str, scheme->name) == 0) + return scheme->default_port; + + return 0; +} + +API_EXPORT(unsigned short) ap_default_port_for_request(const request_rec *r) +{ + return (r->parsed_uri.scheme) + ? ap_default_port_for_scheme(r->parsed_uri.scheme) + : 0; +} + +/* Create a copy of a "struct hostent" record; it was presumably returned + * from a call to gethostbyname() and lives in static storage. + * By creating a copy we can tuck it away for later use. + */ +API_EXPORT(struct hostent *) ap_pduphostent(pool *p, struct hostent *hp) +{ + struct hostent *newent; + char **ptrs; + char **aliases; + struct in_addr *addrs; + int i = 0, j = 0; + + if (hp == NULL) + return hp; + + /* Count number of alias entries */ + if (hp->h_aliases != NULL) + for (; hp->h_aliases[j] != NULL; ++j) + continue; + + /* Count number of in_addr entries */ + if (hp->h_addr_list != NULL) + for (; hp->h_addr_list[i] != NULL; ++i) + continue; + + /* Allocate hostent structure, alias ptrs, addr ptrs, addrs */ + newent = (struct hostent *) ap_palloc(p, sizeof(*hp)); + aliases = (char **) ap_palloc(p, (j+1) * sizeof(char*)); + ptrs = (char **) ap_palloc(p, (i+1) * sizeof(char*)); + addrs = (struct in_addr *) ap_palloc(p, (i+1) * sizeof(struct in_addr)); + + *newent = *hp; + newent->h_name = ap_pstrdup(p, hp->h_name); + newent->h_aliases = aliases; + newent->h_addr_list = (char**) ptrs; + + /* Copy Alias Names: */ + for (j = 0; hp->h_aliases[j] != NULL; ++j) { + aliases[j] = ap_pstrdup(p, hp->h_aliases[j]); + } + aliases[j] = NULL; + + /* Copy address entries */ + for (i = 0; hp->h_addr_list[i] != NULL; ++i) { + ptrs[i] = (char*) &addrs[i]; + addrs[i] = *(struct in_addr *) hp->h_addr_list[i]; + } + ptrs[i] = NULL; + + return newent; +} + + +/* pgethostbyname(): resolve hostname, if successful return an ALLOCATED + * COPY OF the hostent structure, intended to be stored and used later. + * (gethostbyname() uses static storage that would be overwritten on each call) + */ +API_EXPORT(struct hostent *) ap_pgethostbyname(pool *p, const char *hostname) +{ + struct hostent *hp = gethostbyname(hostname); + return (hp == NULL) ? NULL : ap_pduphostent(p, hp); +} + + +/* Unparse a uri_components structure to an URI string. + * Optionally suppress the password for security reasons. + */ +API_EXPORT(char *) ap_unparse_uri_components(pool *p, const uri_components *uptr, unsigned flags) +{ + char *ret = ""; + + /* Construct a "user:password@" string, honoring the passed UNP_ flags: */ + if (uptr->user||uptr->password) + ret = ap_pstrcat (p, + (uptr->user && !(flags & UNP_OMITUSER)) ? uptr->user : "", + (uptr->password && !(flags & UNP_OMITPASSWORD)) ? ":" : "", + (uptr->password && !(flags & UNP_OMITPASSWORD)) + ? ((flags & UNP_REVEALPASSWORD) ? uptr->password : "XXXXXXXX") + : "", + "@", NULL); + + /* Construct scheme://site string */ + if (uptr->hostname && !(flags & UNP_OMITSITEPART)) { + ret = ap_pstrcat (p, + uptr->scheme, "://", ret, + uptr->hostname ? uptr->hostname : "", + uptr->port_str ? ":" : "", + uptr->port_str ? uptr->port_str : "", + NULL); + } + + /* Append path, query and fragment strings: */ + ret = ap_pstrcat (p, + ret, + uptr->path, + uptr->query ? "?" : "", + uptr->query ? uptr->query : "", + uptr->fragment ? "#" : NULL, + uptr->fragment ? uptr->fragment : NULL, + NULL); + return ret; +} + +/* The regex version of parse_uri_components has the advantage that it is + * relatively easy to understand and extend. But it has the disadvantage + * that the regexes are complex enough that regex libraries really + * don't do a great job with them performancewise. + * + * The default is a hand coded scanner that is two orders of magnitude + * faster. + */ +#ifdef UTIL_URI_REGEX + +static regex_t re_uri; +static regex_t re_hostpart; + +void ap_util_uri_init(void) +{ + int ret; + const char *re_str; + + /* This is a modified version of the regex that appeared in + * draft-fielding-uri-syntax-01. It doesnt allow the uri to contain a + * scheme but no hostinfo or vice versa. + * + * draft-fielding-uri-syntax-01.txt, section 4.4 tells us: + * + * Although the BNF defines what is allowed in each component, it is + * ambiguous in terms of differentiating between a site component and + * a path component that begins with two slash characters. + * + * RFC2068 disambiguates this for the Request-URI, which may only ever be + * the "abs_path" portion of the URI. So a request "GET //foo/bar + * HTTP/1.1" is really referring to the path //foo/bar, not the host foo, + * path /bar. Nowhere in RFC2068 is it possible to have a scheme but no + * hostinfo or a hostinfo but no scheme. (Unless you're proxying a + * protocol other than HTTP, but this parsing engine probably won't work + * for other protocols.) + * + * 12 3 4 5 6 7 8 */ + re_str = "^(([^:/?#]+)://([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"; + /* ^scheme--^ ^site---^ ^path--^ ^query^ ^frag */ + if ((ret = regcomp(&re_uri, re_str, REG_EXTENDED)) != 0) { + char line[1024]; + + /* Make a readable error message */ + ret = regerror(ret, &re_uri, line, sizeof line); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "Internal error: regcomp(\"%s\") returned non-zero (%s) - " + "possibly due to broken regex lib! " + "Did you define WANTHSREGEX=yes?", + re_str, line); + + exit(1); + } + + /* This is a sub-RE which will break down the hostinfo part, + * i.e., user, password, hostname and port. + * $ 12 3 4 5 6 7 */ + re_str = "^(([^:]*)(:(.*))?@)?([^@:]*)(:(.*))?$"; + /* ^^user^ :pw ^host^ port */ + if ((ret = regcomp(&re_hostpart, re_str, REG_EXTENDED)) != 0) { + char line[1024]; + + /* Make a readable error message */ + ret = regerror(ret, &re_hostpart, line, sizeof line); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "Internal error: regcomp(\"%s\") returned non-zero (%s) - " + "possibly due to broken regex lib! " + "Did you define WANTHSREGEX=yes?", + re_str, line); + + exit(1); + } +} + + +/* parse_uri_components(): + * Parse a given URI, fill in all supplied fields of a uri_components + * structure. This eliminates the necessity of extracting host, port, + * path, query info repeatedly in the modules. + * Side effects: + * - fills in fields of uri_components *uptr + * - none on any of the r->* fields + */ +API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri, uri_components *uptr) +{ + int ret; + regmatch_t match[10]; /* This must have at least as much elements + * as there are braces in the re_strings */ + + ap_assert (uptr != NULL); + + /* Initialize the structure. parse_uri() and parse_uri_components() + * can be called more than once per request. + */ + memset (uptr, '\0', sizeof(*uptr)); + uptr->is_initialized = 1; + + ret = regexec(&re_uri, uri, re_uri.re_nsub + 1, match, 0); + + if (ret != 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "regexec() could not parse uri (\"%s\")", + uri); + + return HTTP_BAD_REQUEST; + } + + if (match[2].rm_so != match[2].rm_eo) + uptr->scheme = ap_pstrndup (p, uri+match[2].rm_so, match[2].rm_eo - match[2].rm_so); + + /* empty hostinfo is valid, that's why we test $1 but use $3 */ + if (match[1].rm_so != match[1].rm_eo) + uptr->hostinfo = ap_pstrndup (p, uri+match[3].rm_so, match[3].rm_eo - match[3].rm_so); + + if (match[4].rm_so != match[4].rm_eo) + uptr->path = ap_pstrndup (p, uri+match[4].rm_so, match[4].rm_eo - match[4].rm_so); + + /* empty query string is valid, that's why we test $5 but use $6 */ + if (match[5].rm_so != match[5].rm_eo) + uptr->query = ap_pstrndup (p, uri+match[6].rm_so, match[6].rm_eo - match[6].rm_so); + + /* empty fragment is valid, test $7 use $8 */ + if (match[7].rm_so != match[7].rm_eo) + uptr->fragment = ap_pstrndup (p, uri+match[8].rm_so, match[8].rm_eo - match[8].rm_so); + + if (uptr->hostinfo) { + /* Parse the hostinfo part to extract user, password, host, and port */ + ret = regexec(&re_hostpart, uptr->hostinfo, re_hostpart.re_nsub + 1, match, 0); + if (ret != 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "regexec() could not parse (\"%s\") as host part", + uptr->hostinfo); + + return HTTP_BAD_REQUEST; + } + + /* $ 12 3 4 5 6 7 */ + /* = "^(([^:]*)(:(.*))?@)?([^@:]*)(:(.*))?$" */ + /* ^^user^ :pw ^host^ port */ + + /* empty user is valid, that's why we test $1 but use $2 */ + if (match[1].rm_so != match[1].rm_eo) + uptr->user = ap_pstrndup (p, uptr->hostinfo+match[2].rm_so, match[2].rm_eo - match[2].rm_so); + + /* empty password is valid, test $3 but use $4 */ + if (match[3].rm_so != match[3].rm_eo) + uptr->password = ap_pstrndup (p, uptr->hostinfo+match[4].rm_so, match[4].rm_eo - match[4].rm_so); + + /* empty hostname is valid, and implied by the existence of hostinfo */ + uptr->hostname = ap_pstrndup (p, uptr->hostinfo+match[5].rm_so, match[5].rm_eo - match[5].rm_so); + + if (match[6].rm_so != match[6].rm_eo) { + /* Note that the port string can be empty. + * If it is, we use the default port associated with the scheme + */ + uptr->port_str = ap_pstrndup (p, uptr->hostinfo+match[7].rm_so, match[7].rm_eo - match[7].rm_so); + if (uptr->port_str[0] != '\0') { + char *endstr; + int port; + + port = strtol(uptr->port_str, &endstr, 10); + uptr->port = port; + if (*endstr != '\0' || uptr->port != port) { + /* Invalid characters after ':' found */ + return HTTP_BAD_REQUEST; + } + } + else { + uptr->port = uptr->scheme ? ap_default_port_for_scheme(uptr->scheme) : DEFAULT_HTTP_PORT; + } + } + } + + if (ret == 0) + ret = HTTP_OK; + return ret; +} +#else + +/* Here is the hand-optimized parse_uri_components(). There are some wild + * tricks we could pull in assembly language that we don't pull here... like we + * can do word-at-time scans for delimiter characters using the same technique + * that fast memchr()s use. But that would be way non-portable. -djg + */ + +/* We have a table that we can index by character and it tells us if the + * character is one of the interesting delimiters. Note that we even get + * compares for NUL for free -- it's just another delimiter. + */ + +#define T_COLON 0x01 /* ':' */ +#define T_SLASH 0x02 /* '/' */ +#define T_QUESTION 0x04 /* '?' */ +#define T_HASH 0x08 /* '#' */ +#define T_NUL 0x80 /* '\0' */ + +/* the uri_delims.h file is autogenerated by gen_uri_delims.c */ +#include "uri_delims.h" + +/* it works like this: + if (uri_delims[ch] & NOTEND_foobar) { + then we're not at a delimiter for foobar + } +*/ + +/* Note that we optimize the scheme scanning here, we cheat and let the + * compiler know that it doesn't have to do the & masking. + */ +#define NOTEND_SCHEME (0xff) +#define NOTEND_HOSTINFO (T_SLASH | T_QUESTION | T_HASH | T_NUL) +#define NOTEND_PATH (T_QUESTION | T_HASH | T_NUL) + +void ap_util_uri_init(void) +{ + /* nothing to do */ +} + +/* parse_uri_components(): + * Parse a given URI, fill in all supplied fields of a uri_components + * structure. This eliminates the necessity of extracting host, port, + * path, query info repeatedly in the modules. + * Side effects: + * - fills in fields of uri_components *uptr + * - none on any of the r->* fields + */ +API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri, uri_components *uptr) +{ + const char *s; + const char *s1; + const char *hostinfo; + char *endstr; + int port; + + /* Initialize the structure. parse_uri() and parse_uri_components() + * can be called more than once per request. + */ + memset (uptr, '\0', sizeof(*uptr)); + uptr->is_initialized = 1; + + /* We assume the processor has a branch predictor like most -- + * it assumes forward branches are untaken and backwards are taken. That's + * the reason for the gotos. -djg + */ + if (uri[0] == '/') { +deal_with_path: + /* we expect uri to point to first character of path ... remember + * that the path could be empty -- http://foobar?query for example + */ + s = uri; + while ((uri_delims[*(unsigned char *)s] & NOTEND_PATH) == 0) { + ++s; + } + if (s != uri) { + uptr->path = ap_pstrndup(p, uri, s - uri); + } + if (*s == 0) { + return HTTP_OK; + } + if (*s == '?') { + ++s; + s1 = strchr(s, '#'); + if (s1) { + uptr->fragment = ap_pstrdup(p, s1 + 1); + uptr->query = ap_pstrndup(p, s, s1 - s); + } + else { + uptr->query = ap_pstrdup(p, s); + } + return HTTP_OK; + } + /* otherwise it's a fragment */ + uptr->fragment = ap_pstrdup(p, s + 1); + return HTTP_OK; + } + + /* find the scheme: */ + s = uri; + while ((uri_delims[*(unsigned char *)s] & NOTEND_SCHEME) == 0) { + ++s; + } + /* scheme must be non-empty and followed by :// */ + if (s == uri || s[0] != ':' || s[1] != '/' || s[2] != '/') { + goto deal_with_path; /* backwards predicted taken! */ + } + + uptr->scheme = ap_pstrndup(p, uri, s - uri); + s += 3; + hostinfo = s; + while ((uri_delims[*(unsigned char *)s] & NOTEND_HOSTINFO) == 0) { + ++s; + } + uri = s; /* whatever follows hostinfo is start of uri */ + uptr->hostinfo = ap_pstrndup(p, hostinfo, uri - hostinfo); + + /* If there's a username:password@host:port, the @ we want is the last @... + * too bad there's no memrchr()... For the C purists, note that hostinfo + * is definately not the first character of the original uri so therefore + * &hostinfo[-1] < &hostinfo[0] ... and this loop is valid C. + */ + do { + --s; + } while (s >= hostinfo && *s != '@'); + if (s < hostinfo) { + /* again we want the common case to be fall through */ +deal_with_host: + /* We expect hostinfo to point to the first character of + * the hostname. If there's a port it is the first colon. + */ + s = memchr(hostinfo, ':', uri - hostinfo); + if (s == NULL) { + /* we expect the common case to have no port */ + uptr->hostname = ap_pstrndup(p, hostinfo, uri - hostinfo); + goto deal_with_path; + } + uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo); + ++s; + uptr->port_str = ap_pstrndup(p, s, uri - s); + if (uri != s) { + port = strtol(uptr->port_str, &endstr, 10); + uptr->port = port; + if (*endstr == '\0') { + goto deal_with_path; + } + /* Invalid characters after ':' found */ + return HTTP_BAD_REQUEST; + } + uptr->port = ap_default_port_for_scheme(uptr->scheme); + goto deal_with_path; + } + + /* first colon delimits username:password */ + s1 = memchr(hostinfo, ':', s - hostinfo); + if (s1) { + uptr->user = ap_pstrndup(p, hostinfo, s1 - hostinfo); + ++s1; + uptr->password = ap_pstrndup(p, s1, s - s1); + } + else { + uptr->user = ap_pstrndup(p, hostinfo, s - hostinfo); + } + hostinfo = s + 1; + goto deal_with_host; +} + +/* Special case for CONNECT parsing: it comes with the hostinfo part only */ +/* See the INTERNET-DRAFT document "Tunneling SSL Through a WWW Proxy" + * currently at http://www.mcom.com/newsref/std/tunneling_ssl.html + * for the format of the "CONNECT host:port HTTP/1.0" request + */ +API_EXPORT(int) ap_parse_hostinfo_components(pool *p, const char *hostinfo, uri_components *uptr) +{ + const char *s; + char *endstr; + + /* Initialize the structure. parse_uri() and parse_uri_components() + * can be called more than once per request. + */ + memset (uptr, '\0', sizeof(*uptr)); + uptr->is_initialized = 1; + uptr->hostinfo = ap_pstrdup(p, hostinfo); + + /* We expect hostinfo to point to the first character of + * the hostname. There must be a port, separated by a colon + */ + s = strchr(hostinfo, ':'); + if (s == NULL) { + return HTTP_BAD_REQUEST; + } + uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo); + ++s; + uptr->port_str = ap_pstrdup(p, s); + if (*s != '\0') { + uptr->port = strtol(uptr->port_str, &endstr, 10); + if (*endstr == '\0') { + return HTTP_OK; + } + /* Invalid characters after ':' found */ + } + return HTTP_BAD_REQUEST; +} +#endif diff --git a/APACHE_1_3b7/src/modules/.cvsignore b/APACHE_1_3b7/src/modules/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/APACHE_1_3b7/src/modules/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/APACHE_1_3b7/src/modules/README b/APACHE_1_3b7/src/modules/README new file mode 100644 index 0000000000..b576a3f20b --- /dev/null +++ b/APACHE_1_3b7/src/modules/README @@ -0,0 +1,36 @@ +The directory structure for this level is as follows: + +standard/ + + In this directory are the standard supported modules for + Apache. Not all are compiled by default. + +proxy/ + + This houses the code for the proxy module for Apache. + +experimental/ + + In this directory we've placed some modules which we think + provide some pretty interesting functionality, but which + are still in the early stages of development and could + evolve radically in the future. This code isn't supported + officially. + +extra/ + + This is the directory for third-party modules, such as + mod_perl, mod_php, or mod_jserv. + +test/ + + This directory houses modules which test various components + of Apache. You should not compile these into a production + server. + +example/ + + This directory houses example modules, to help module authors + figure their way around the Apache API and module concept. + + diff --git a/APACHE_1_3b7/src/modules/example/.cvsignore b/APACHE_1_3b7/src/modules/example/.cvsignore new file mode 100644 index 0000000000..8b4c6e3da4 --- /dev/null +++ b/APACHE_1_3b7/src/modules/example/.cvsignore @@ -0,0 +1,3 @@ +Makefile +*.lo +*.so diff --git a/APACHE_1_3b7/src/modules/example/.indent.pro b/APACHE_1_3b7/src/modules/example/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3b7/src/modules/example/.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/APACHE_1_3b7/src/modules/example/Makefile.tmpl b/APACHE_1_3b7/src/modules/example/Makefile.tmpl new file mode 100644 index 0000000000..80c105cde3 --- /dev/null +++ b/APACHE_1_3b7/src/modules/example/Makefile.tmpl @@ -0,0 +1,12 @@ + +#Dependencies + +$(OBJS) $(OBJS_PIC): Makefile + +# DO NOT REMOVE +mod_example.o: mod_example.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_main.h \ + $(INCDIR)/http_protocol.h $(INCDIR)/util_script.h diff --git a/APACHE_1_3b7/src/modules/example/README b/APACHE_1_3b7/src/modules/example/README new file mode 100644 index 0000000000..77abc097c0 --- /dev/null +++ b/APACHE_1_3b7/src/modules/example/README @@ -0,0 +1,53 @@ +README for Apache 1.2 Example Module +[April, 1997] + +The files in the src/modules/example directory under the Apache +distribution directory tree are provided as an example to those that +wish to write modules that use the Apache API. + +The main file is mod_example.c, which illustrates all the different +callback mechanisms and call syntaces. By no means does an add-on +module need to include routines for all of the callbacks - quite the +contrary! + +The example module is an actual working module. If you link it into +your server, enable the "example-handler" handler for a location, and then +browse to that location, you will see a display of some of the tracing +the example module did as the various callbacks were made. + +To include the example module in your server, follow the steps below: + + 1. Uncomment the "Module example_module" line near the bottom of + the src/Configuration file. If there isn't one, add it; it + should look like this: + + Module example_module modules/example/mod_example.o + + 2. Run the src/Configure script ("cd src; ./Configure"). This will + build the Makefile for the server itself, and update the + src/modules/Makefile for any additional modules you have + requested from beneath that subdirectory. + + 3. Make the server (run "make" in the src directory). + +To add another module of your own: + + A. mkdir src/modules/mymodule + B. cp src/modules/example/* src/modules/mymodule + C. Modify the files in the new directory + D. Follow steps [1] through [3] above, with appropriate changes. + +To activate the example module, include a block similar to the +following in your srm.conf file: + + + SetHandler example-handler + + +As an alternative, you can put the following into a .htaccess file and +then request the file "test.example" from that location: + + AddHandler example-handler .example + +After reloading/restarting your server, you should be able to browse +to this location and see the brief display mentioned earlier. diff --git a/APACHE_1_3b7/src/modules/example/mod_example.c b/APACHE_1_3b7/src/modules/example/mod_example.c new file mode 100644 index 0000000000..173e4dd70f --- /dev/null +++ b/APACHE_1_3b7/src/modules/example/mod_example.c @@ -0,0 +1,1141 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * Apache example module. Provide demonstrations of how modules do things. + * + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_main.h" +#include "http_protocol.h" +#include "util_script.h" + +#include + +/*--------------------------------------------------------------------------*/ +/* */ +/* Data declarations. */ +/* */ +/* Here are the static cells and structure declarations private to our */ +/* module. */ +/* */ +/*--------------------------------------------------------------------------*/ + +/* + * Sample configuration record. Used for both per-directory and per-server + * configuration data. + * + * It's perfectly reasonable to have two different structures for the two + * different environments. The same command handlers will be called for + * both, though, so the handlers need to be able to tell them apart. One + * possibility is for both structures to start with an int which is zero for + * one and 1 for the other. + * + * Note that while the per-directory and per-server configuration records are + * available to most of the module handlers, they should be treated as + * READ-ONLY by all except the command and merge handlers. Sometimes handlers + * are handed a record that applies to the current location by implication or + * inheritance, and modifying it will change the rules for other locations. + */ +typedef struct excfg { + int cmode; /* Environment to which record applies (directory, + * server, or combination). + */ +#define CONFIG_MODE_SERVER 1 +#define CONFIG_MODE_DIRECTORY 2 +#define CONFIG_MODE_COMBO 3 /* Shouldn't ever happen. */ + int local; /* Boolean: "Example" directive declared here? */ + int congenital; /* Boolean: did we inherit an "Example"? */ + char *trace; /* Pointer to trace string. */ + char *loc; /* Location to which this record applies. */ +} excfg; + +/* + * Let's set up a module-local static cell to point to the accreting callback + * trace. As each API callback is made to us, we'll tack on the particulars + * to whatever we've already recorded. To avoid massive memory bloat as + * directories are walked again and again, we record the routine/environment + * the first time (non-request context only), and ignore subsequent calls for + * the same routine/environment. + */ +static char *trace = NULL; +static table *static_calls_made = NULL; + +/* + * To avoid leaking memory from pools other than the per-request one, we + * allocate a module-private pool, and then use a sub-pool of that which gets + * freed each time we modify the trace. That way previous layers of trace + * data don't get lost. + */ +static pool *example_pool = NULL; +static pool *example_subpool = NULL; + +/* + * Declare ourselves so the configuration routines can find and know us. + * We'll fill it in at the end of the module. + */ +module example_module; + +/*--------------------------------------------------------------------------*/ +/* */ +/* The following pseudo-prototype declarations illustrate the parameters */ +/* passed to command handlers for the different types of directive */ +/* syntax. If an argument was specified in the directive definition */ +/* (look for "command_rec" below), it's available to the command handler */ +/* via the (void *) info field in the cmd_parms argument passed to the */ +/* handler (cmd->info for the examples below). */ +/* */ +/*--------------------------------------------------------------------------*/ + +/* + * Command handler for a NO_ARGS directive. + * + * static const char *handle_NO_ARGS(cmd_parms *cmd, void *mconfig); + */ + +/* + * Command handler for a RAW_ARGS directive. The "args" argument is the text + * of the commandline following the directive itself. + * + * static const char *handle_RAW_ARGS(cmd_parms *cmd, void *mconfig, + * const char *args); + */ + +/* + * Command handler for a FLAG directive. The single parameter is passed in + * "bool", which is either zero or not for Off or On respectively. + * + * static const char *handle_FLAG(cmd_parms *cmd, void *mconfig, int bool); + */ + +/* + * Command handler for a TAKE1 directive. The single parameter is passed in + * "word1". + * + * static const char *handle_TAKE1(cmd_parms *cmd, void *mconfig, + * char *word1); + */ + +/* + * Command handler for a TAKE2 directive. TAKE2 commands must always have + * exactly two arguments. + * + * static const char *handle_TAKE2(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2); + */ + +/* + * Command handler for a TAKE3 directive. Like TAKE2, these must have exactly + * three arguments, or the parser complains and doesn't bother calling us. + * + * static const char *handle_TAKE3(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2, char *word3); + */ + +/* + * Command handler for a TAKE12 directive. These can take either one or two + * arguments. + * - word2 is a NULL pointer if no second argument was specified. + * + * static const char *handle_TAKE12(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2); + */ + +/* + * Command handler for a TAKE123 directive. A TAKE123 directive can be given, + * as might be expected, one, two, or three arguments. + * - word2 is a NULL pointer if no second argument was specified. + * - word3 is a NULL pointer if no third argument was specified. + * + * static const char *handle_TAKE123(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2, char *word3); + */ + +/* + * Command handler for a TAKE13 directive. Either one or three arguments are + * permitted - no two-parameters-only syntax is allowed. + * - word2 and word3 are NULL pointers if only one argument was specified. + * + * static const char *handle_TAKE13(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2, char *word3); + */ + +/* + * Command handler for a TAKE23 directive. At least two and as many as three + * arguments must be specified. + * - word3 is a NULL pointer if no third argument was specified. + * + * static const char *handle_TAKE23(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2, char *word3); + */ + +/* + * Command handler for a ITERATE directive. + * - Handler is called once for each of n arguments given to the directive. + * - word1 points to each argument in turn. + * + * static const char *handle_ITERATE(cmd_parms *cmd, void *mconfig, + * char *word1); + */ + +/* + * Command handler for a ITERATE2 directive. + * - Handler is called once for each of the second and subsequent arguments + * given to the directive. + * - word1 is the same for each call for a particular directive instance (the + * first argument). + * - word2 points to each of the second and subsequent arguments in turn. + * + * static const char *handle_ITERATE2(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2); + */ + +/*--------------------------------------------------------------------------*/ +/* */ +/* These routines are strictly internal to this module, and support its */ +/* operation. They are not referenced by any external portion of the */ +/* server. */ +/* */ +/*--------------------------------------------------------------------------*/ + +/* + * Locate our directory configuration record for the current request. + */ +static excfg *our_dconfig(request_rec *r) +{ + + return (excfg *) ap_get_module_config(r->per_dir_config, &example_module); +} + +#if 0 +/* + * Locate our server configuration record for the specified server. + */ +static excfg *our_sconfig(server_rec *s) +{ + + return (excfg *) ap_get_module_config(s->module_config, &example_module); +} + +/* + * Likewise for our configuration record for the specified request. + */ +static excfg *our_rconfig(request_rec *r) +{ + + return (excfg *) ap_get_module_config(r->request_config, &example_module); +} +#endif + +/* + * This routine sets up some module-wide cells if they haven't been already. + */ +static void setup_module_cells() +{ + /* + * If we haven't already allocated our module-private pool, do so now. + */ + if (example_pool == NULL) { + example_pool = ap_make_sub_pool(NULL); + }; + /* + * Likewise for the table of routine/environment pairs we visit outside of + * request context. + */ + if (static_calls_made == NULL) { + static_calls_made = ap_make_table(example_pool, 16); + }; +} + +/* + * This routine is used to add a trace of a callback to the list. We're + * passed the server record (if available), the request record (if available), + * a pointer to our private configuration record (if available) for the + * environment to which the callback is supposed to apply, and some text. We + * turn this into a textual representation and add it to the tail of the list. + * The list can be displayed by the example_handler() routine. + * + * If the call occurs within a request context (i.e., we're passed a request + * record), we put the trace into the request pool and attach it to the + * request via the notes mechanism. Otherwise, the trace gets added + * to the static (non-request-specific) list. + * + * Note that the r->notes table is only for storing strings; if you need to + * maintain per-request data of any other type, you need to use another + * mechanism. + */ + +#define TRACE_NOTE "example-trace" + +static void trace_add(server_rec *s, request_rec *r, excfg *mconfig, + const char *note) +{ + + char *sofar; + char *addon; + char *where; + pool *p; + char *trace_copy; + + /* + * Make sure our pools and tables are set up - we need 'em. + */ + setup_module_cells(); + /* + * Now, if we're in request-context, we use the request pool. + */ + if (r != NULL) { + p = r->pool; + if ((trace_copy = ap_table_get(r->notes, TRACE_NOTE)) == NULL) { + trace_copy = ""; + } + } + else { + /* + * We're not in request context, so the trace gets attached to our + * module-wide pool. We do the create/destroy every time we're called + * in non-request context; this avoids leaking memory in some of + * the subsequent calls that allocate memory only once (such as the + * key formation below). + * + * Make a new sub-pool and copy any existing trace to it. Point the + * trace cell at the copied value. + */ + p = ap_make_sub_pool(example_pool); + if (trace != NULL) { + trace = ap_pstrdup(p, trace); + } + /* + * Now, if we have a sub-pool from before, nuke it and replace with + * the one we just allocated. + */ + if (example_subpool != NULL) { + ap_destroy_pool(example_subpool); + } + example_subpool = p; + trace_copy = trace; + } + /* + * If we weren't passed a configuration record, we can't figure out to + * what location this call applies. This only happens for co-routines + * that don't operate in a particular directory or server context. If we + * got a valid record, extract the location (directory or server) to which + * it applies. + */ + where = (mconfig != NULL) ? mconfig->loc : "nowhere"; + where = (where != NULL) ? where : ""; + /* + * Now, if we're not in request context, see if we've been called with + * this particular combination before. The table is allocated in the + * module's private pool, which doesn't get destroyed. + */ + if (r == NULL) { + char *key; + + key = ap_pstrcat(p, note, ":", where, NULL); + if (ap_table_get(static_calls_made, key) != NULL) { + /* + * Been here, done this. + */ + return; + } + else { + /* + * First time for this combination of routine and environment - + * log it so we don't do it again. + */ + ap_table_set(static_calls_made, key, "been here"); + } + } + addon = ap_pstrcat(p, "
  • \n", "
    \n", "
    ", + note, "\n", "
    \n", "
    [", + where, "]\n", "
    \n", "
    \n", + "
  • \n", NULL); + sofar = (trace_copy == NULL) ? "" : trace_copy; + trace_copy = ap_pstrcat(p, sofar, addon, NULL); + if (r != NULL) { + ap_table_set(r->notes, TRACE_NOTE, trace_copy); + } + else { + trace = trace_copy; + } + /* + * You *could* change the following if you wanted to see the calling + * sequence reported in the server's error_log, but beware - almost all of + * these co-routines are called for every single request, and the impact + * on the size (and readability) of the error_log is considerable. + */ +#define EXAMPLE_LOG_EACH 0 + if (EXAMPLE_LOG_EACH && (s != NULL)) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, s, "mod_example: %s", note); + } +} + +/*--------------------------------------------------------------------------*/ +/* We prototyped the various syntax for command handlers (routines that */ +/* are called when the configuration parser detects a directive declared */ +/* by our module) earlier. Now we actually declare a "real" routine that */ +/* will be invoked by the parser when our "real" directive is */ +/* encountered. */ +/* */ +/* If a command handler encounters a problem processing the directive, it */ +/* signals this fact by returning a non-NULL pointer to a string */ +/* describing the problem. */ +/* */ +/* The magic return value DECLINE_CMD is used to deal with directives */ +/* that might be declared by multiple modules. If the command handler */ +/* returns NULL, the directive was processed; if it returns DECLINE_CMD, */ +/* the next module (if any) that declares the directive is given a chance */ +/* at it. If it returns any other value, it's treated as the text of an */ +/* error message. */ +/*--------------------------------------------------------------------------*/ +/* + * Command handler for the NO_ARGS "Example" directive. All we do is mark the + * call in the trace log, and flag the applicability of the directive to the + * current location in that location's configuration record. + */ +static const char *cmd_example(cmd_parms *cmd, void *mconfig) +{ + + excfg *cfg = (excfg *) mconfig; + + /* + * "Example Wuz Here" + */ + cfg->local = 1; + trace_add(cmd->server, NULL, cfg, "cmd_example()"); + return NULL; +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* Now we declare our content handlers, which are invoked when the server */ +/* encounters a document which our module is supposed to have a chance to */ +/* see. (See mod_mime's SetHandler and AddHandler directives, and the */ +/* mod_info and mod_status examples, for more details.) */ +/* */ +/* Since content handlers are dumping data directly into the connexion */ +/* (using the r*() routines, such as rputs() and rprintf()) without */ +/* intervention by other parts of the server, they need to make */ +/* sure any accumulated HTTP headers are sent first. This is done by */ +/* calling send_http_header(). Otherwise, no header will be sent at all, */ +/* and the output sent to the client will actually be HTTP-uncompliant. */ +/*--------------------------------------------------------------------------*/ +/* + * Sample content handler. All this does is display the call list that has + * been built up so far. + * + * The return value instructs the caller concerning what happened and what to + * do next: + * OK ("we did our thing") + * DECLINED ("this isn't something with which we want to get involved") + * HTTP_mumble ("an error status should be reported") + */ +static int example_handler(request_rec *r) +{ + + excfg *dcfg; + + dcfg = our_dconfig(r); + trace_add(r->server, r, dcfg, "example_handler()"); + /* + * We're about to start sending content, so we need to force the HTTP + * headers to be sent at this point. Otherwise, no headers will be sent + * at all. We can set any we like first, of course. **NOTE** Here's + * where you set the "Content-type" header, and you do so by putting it in + * r->content_type, *not* r->headers_out("Content-type"). If you don't + * set it, it will be filled in with the server's default type (typically + * "text/plain"). You *must* also ensure that r->content_type is lower + * case. + * + * We also need to start a timer so the server can know if the connexion + * is broken. + */ + r->content_type = "text/html"; + ap_soft_timeout("send example call trace", r); + ap_send_http_header(r); + /* + * If we're only supposed to send header information (HEAD request), we're + * already there. + */ + if (r->header_only) { + ap_kill_timeout(r); + return OK; + } + + /* + * Now send our actual output. Since we tagged this as being + * "text/html", we need to embed any HTML. + */ + ap_rputs("\n", r); + ap_rputs("\n", r); + ap_rputs(" \n", r); + ap_rputs(" mod_example Module Content-Handler Output\n", r); + ap_rputs(" \n", r); + ap_rputs(" \n", r); + ap_rputs(" \n", r); + ap_rputs("

    mod_example Module Content-Handler Output\n", r); + ap_rputs("

    \n", r); + ap_rputs("

    \n", r); + ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n", + ap_get_server_version()); + ap_rputs("
    \n", r); + ap_rprintf(r, " Server built: \"%s\"\n", ap_get_server_built()); + ap_rputs("

    \n", r);; + ap_rputs("

    \n", r); + ap_rputs(" The format for the callback trace is:\n", r); + ap_rputs("

    \n", r); + ap_rputs("
    \n", r); + ap_rputs("
    n.<routine-name>", r); + ap_rputs("(<routine-data>)\n", r); + ap_rputs("
    \n", r); + ap_rputs("
    [<applies-to>]\n", r); + ap_rputs("
    \n", r); + ap_rputs("
    \n", r); + ap_rputs("

    \n", r); + ap_rputs(" The <routine-data> is supplied by\n", r); + ap_rputs(" the routine when it requests the trace,\n", r); + ap_rputs(" and the <applies-to> is extracted\n", r); + ap_rputs(" from the configuration record at the time of the trace.\n", r); + ap_rputs(" SVR() indicates a server environment\n", r); + ap_rputs(" (blank means the main or default server, otherwise it's\n", r); + ap_rputs(" the name of the VirtualHost); DIR()\n", r); + ap_rputs(" indicates a location in the URL or filesystem\n", r); + ap_rputs(" namespace.\n", r); + ap_rputs("

    \n", r); + ap_rprintf(r, "

    Static callbacks so far:

    \n
      \n%s
    \n", + trace); + ap_rputs("

    Request-specific callbacks so far:

    \n", r); + ap_rprintf(r, "
      \n%s
    \n", ap_table_get(r->notes, TRACE_NOTE)); + ap_rputs("

    Environment for this call:

    \n", r); + ap_rputs("
      \n", r); + ap_rprintf(r, "
    • Applies-to: %s\n
    • \n", dcfg->loc); + ap_rprintf(r, "
    • \"Example\" directive declared here: %s\n
    • \n", + (dcfg->local ? "YES" : "NO")); + ap_rprintf(r, "
    • \"Example\" inherited: %s\n
    • \n", + (dcfg->congenital ? "YES" : "NO")); + ap_rputs("
    \n", r); + ap_rputs(" \n", r); + ap_rputs("\n", r); + /* + * We're all done, so cancel the timeout we set. Since this is probably + * the end of the request we *could* assume this would be done during + * post-processing - but it's possible that another handler might be + * called and inherit our outstanding timer. Not good; to each its own. + */ + ap_kill_timeout(r); + /* + * We did what we wanted to do, so tell the rest of the server we + * succeeded. + */ + return OK; +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* Now let's declare routines for each of the callback phase in order. */ +/* (That's the order in which they're listed in the callback list, *not */ +/* the order in which the server calls them! See the command_rec */ +/* declaration near the bottom of this file.) Note that these may be */ +/* called for situations that don't relate primarily to our function - in */ +/* other words, the fixup handler shouldn't assume that the request has */ +/* to do with "example" stuff. */ +/* */ +/* With the exception of the content handler, all of our routines will be */ +/* called for each request, unless an earlier handler from another module */ +/* aborted the sequence. */ +/* */ +/* Handlers that are declared as "int" can return the following: */ +/* */ +/* OK Handler accepted the request and did its thing with it. */ +/* DECLINED Handler took no action. */ +/* HTTP_mumble Handler looked at request and found it wanting. */ +/* */ +/* What the server does after calling a module handler depends upon the */ +/* handler's return value. In all cases, if the handler returns */ +/* DECLINED, the server will continue to the next module with an handler */ +/* for the current phase. However, if the handler return a non-OK, */ +/* non-DECLINED status, the server aborts the request right there. If */ +/* the handler returns OK, the server's next action is phase-specific; */ +/* see the individual handler comments below for details. */ +/* */ +/*--------------------------------------------------------------------------*/ +/* + * This function is called during server initialisation. Any information + * that needs to be recorded must be in static cells, since there's no + * configuration record. + * + * There is no return value. + */ + +/* + * All our module-initialiser does is add its trace to the log. + */ +static void example_init(server_rec *s, pool *p) +{ + + char *note; + char *sname = s->server_hostname; + + /* + * Set up any module cells that ought to be initialised. + */ + setup_module_cells(); + /* + * The arbitrary text we add to our trace entry indicates for which server + * we're being called. + */ + sname = (sname != NULL) ? sname : ""; + note = ap_pstrcat(p, "example_init(", sname, ")", NULL); + trace_add(s, NULL, NULL, note); +} + +/* + * This function is called during server initialisation when an heavy-weight + * process (such as a child) is being initialised. As with the + * module-initialisation function, any information that needs to be recorded + * must be in static cells, since there's no configuration record. + * + * There is no return value. + */ + +/* + * All our process-initialiser does is add its trace to the log. + */ +static void example_child_init(server_rec *s, pool *p) +{ + + char *note; + char *sname = s->server_hostname; + + /* + * Set up any module cells that ought to be initialised. + */ + setup_module_cells(); + /* + * The arbitrary text we add to our trace entry indicates for which server + * we're being called. + */ + sname = (sname != NULL) ? sname : ""; + note = ap_pstrcat(p, "example_child_init(", sname, ")", NULL); + trace_add(s, NULL, NULL, note); +} + +/* + * This function is called when an heavy-weight process (such as a child) is + * being run down or destroyed. As with the child-initialisation function, + * any information that needs to be recorded must be in static cells, since + * there's no configuration record. + * + * There is no return value. + */ + +/* + * All our process-death routine does is add its trace to the log. + */ +static void example_child_exit(server_rec *s, pool *p) +{ + + char *note; + char *sname = s->server_hostname; + + /* + * The arbitrary text we add to our trace entry indicates for which server + * we're being called. + */ + sname = (sname != NULL) ? sname : ""; + note = ap_pstrcat(p, "example_child_exit(", sname, ")", NULL); + trace_add(s, NULL, NULL, note); +} + +/* + * This function gets called to create up a per-directory configuration + * record. This will be called for the "default" server environment, and for + * each directory for which the parser finds any of our directives applicable. + * If a directory doesn't have any of our directives involved (i.e., they + * aren't in the .htaccess file, or a , , or related + * block), this routine will *not* be called - the configuration for the + * closest ancestor is used. + * + * The return value is a pointer to the created module-specific + * structure. + */ +static void *example_create_dir_config(pool *p, char *dirspec) +{ + + excfg *cfg; + char *dname = dirspec; + + /* + * Allocate the space for our record from the pool supplied. + */ + cfg = (excfg *) ap_pcalloc(p, sizeof(excfg)); + /* + * Now fill in the defaults. If there are any `parent' configuration + * records, they'll get merged as part of a separate callback. + */ + cfg->local = 0; + cfg->congenital = 0; + cfg->cmode = CONFIG_MODE_DIRECTORY; + /* + * Finally, add our trace to the callback list. + */ + dname = (dname != NULL) ? dname : ""; + cfg->loc = ap_pstrcat(p, "DIR(", dname, ")", NULL); + trace_add(NULL, NULL, cfg, "example_create_dir_config()"); + return (void *) cfg; +} + +/* + * This function gets called to merge two per-directory configuration + * records. This is typically done to cope with things like .htaccess files + * or directives for directories that are beneath one for which a + * configuration record was already created. The routine has the + * responsibility of creating a new record and merging the contents of the + * other two into it appropriately. If the module doesn't declare a merge + * routine, the record for the closest ancestor location (that has one) is + * used exclusively. + * + * The routine MUST NOT modify any of its arguments! + * + * The return value is a pointer to the created module-specific structure + * containing the merged values. + */ +static void *example_merge_dir_config(pool *p, void *parent_conf, + void *newloc_conf) +{ + + excfg *merged_config = (excfg *) ap_pcalloc(p, sizeof(excfg)); + excfg *pconf = (excfg *) parent_conf; + excfg *nconf = (excfg *) newloc_conf; + char *note; + + /* + * Some things get copied directly from the more-specific record, rather + * than getting merged. + */ + merged_config->local = nconf->local; + merged_config->loc = ap_pstrdup(p, nconf->loc); + /* + * Others, like the setting of the `congenital' flag, get ORed in. The + * setting of that particular flag, for instance, is TRUE if it was ever + * true anywhere in the upstream configuration. + */ + merged_config->congenital = (pconf->congenital | pconf->local); + /* + * If we're merging records for two different types of environment (server + * and directory), mark the new record appropriately. Otherwise, inherit + * the current value. + */ + merged_config->cmode = + (pconf->cmode == nconf->cmode) ? pconf->cmode : CONFIG_MODE_COMBO; + /* + * Now just record our being called in the trace list. Include the + * locations we were asked to merge. + */ + note = ap_pstrcat(p, "example_merge_dir_config(\"", pconf->loc, "\",\"", + nconf->loc, "\")", NULL); + trace_add(NULL, NULL, merged_config, note); + return (void *) merged_config; +} + +/* + * This function gets called to create a per-server configuration + * record. It will always be called for the "default" server. + * + * The return value is a pointer to the created module-specific + * structure. + */ +static void *example_create_server_config(pool *p, server_rec *s) +{ + + excfg *cfg; + char *sname = s->server_hostname; + + /* + * As with the example_create_dir_config() reoutine, we allocate and fill + * in an empty record. + */ + cfg = (excfg *) ap_pcalloc(p, sizeof(excfg)); + cfg->local = 0; + cfg->congenital = 0; + cfg->cmode = CONFIG_MODE_SERVER; + /* + * Note that we were called in the trace list. + */ + sname = (sname != NULL) ? sname : ""; + cfg->loc = ap_pstrcat(p, "SVR(", sname, ")", NULL); + trace_add(s, NULL, cfg, "example_create_server_config()"); + return (void *) cfg; +} + +/* + * This function gets called to merge two per-server configuration + * records. This is typically done to cope with things like virtual hosts and + * the default server configuration The routine has the responsibility of + * creating a new record and merging the contents of the other two into it + * appropriately. If the module doesn't declare a merge routine, the more + * specific existing record is used exclusively. + * + * The routine MUST NOT modify any of its arguments! + * + * The return value is a pointer to the created module-specific structure + * containing the merged values. + */ +static void *example_merge_server_config(pool *p, void *server1_conf, + void *server2_conf) +{ + + excfg *merged_config = (excfg *) ap_pcalloc(p, sizeof(excfg)); + excfg *s1conf = (excfg *) server1_conf; + excfg *s2conf = (excfg *) server2_conf; + char *note; + + /* + * Our inheritance rules are our own, and part of our module's semantics. + * Basically, just note whence we came. + */ + merged_config->cmode = + (s1conf->cmode == s2conf->cmode) ? s1conf->cmode : CONFIG_MODE_COMBO; + merged_config->local = s2conf->local; + merged_config->congenital = (s1conf->congenital | s1conf->local); + merged_config->loc = ap_pstrdup(p, s2conf->loc); + /* + * Trace our call, including what we were asked to merge. + */ + note = ap_pstrcat(p, "example_merge_server_config(\"", s1conf->loc, "\",\"", + s2conf->loc, "\")", NULL); + trace_add(NULL, NULL, merged_config, note); + return (void *) merged_config; +} + +/* + * This routine is called after the request has been read but before any other + * phases have been processed. This allows us to make decisions based upon + * the input header fields. + * + * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no + * further modules are called for this phase. + */ +static int example_post_read_request(request_rec *r) +{ + + excfg *cfg; + + cfg = our_dconfig(r); + /* + * We don't actually *do* anything here, except note the fact that we were + * called. + */ + trace_add(r->server, r, cfg, "example_post_read_request()"); + return DECLINED; +} + +/* + * This routine gives our module an opportunity to translate the URI into an + * actual filename. If we don't do anything special, the server's default + * rules (Alias directives and the like) will continue to be followed. + * + * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no + * further modules are called for this phase. + */ +static int example_translate_handler(request_rec *r) +{ + + excfg *cfg; + + cfg = our_dconfig(r); + /* + * We don't actually *do* anything here, except note the fact that we were + * called. + */ + trace_add(r->server, r, cfg, "example_translate_handler()"); + return DECLINED; +} + +/* + * This routine is called to check the authentication information sent with + * the request (such as looking up the user in a database and verifying that + * the [encrypted] password sent matches the one in the database). + * + * The return value is OK, DECLINED, or some HTTP_mumble error (typically + * HTTP_UNAUTHORIZED). If we return OK, no other modules are given a chance + * at the request during this phase. + */ +static int example_check_user_id(request_rec *r) +{ + + excfg *cfg; + + cfg = our_dconfig(r); + /* + * Don't do anything except log the call. + */ + trace_add(r->server, r, cfg, "example_check_user_id()"); + return DECLINED; +} + +/* + * This routine is called to check to see if the resource being requested + * requires authorisation. + * + * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no + * other modules are called during this phase. + * + * If *all* modules return DECLINED, the request is aborted with a server + * error. + */ +static int example_auth_checker(request_rec *r) +{ + + excfg *cfg; + + cfg = our_dconfig(r); + /* + * Log the call and return OK, or access will be denied (even though we + * didn't actually do anything). + */ + trace_add(r->server, r, cfg, "example_auth_checker()"); + return DECLINED; +} + +/* + * This routine is called to check for any module-specific restrictions placed + * upon the requested resource. (See the mod_access module for an example.) + * + * The return value is OK, DECLINED, or HTTP_mumble. All modules with an + * handler for this phase are called regardless of whether their predecessors + * return OK or DECLINED. The first one to return any other status, however, + * will abort the sequence (and the request) as usual. + */ +static int example_access_checker(request_rec *r) +{ + + excfg *cfg; + + cfg = our_dconfig(r); + trace_add(r->server, r, cfg, "example_access_checker()"); + return DECLINED; +} + +/* + * This routine is called to determine and/or set the various document type + * information bits, like Content-type (via r->content_type), language, et + * cetera. + * + * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no + * further modules are given a chance at the request for this phase. + */ +static int example_type_checker(request_rec *r) +{ + + excfg *cfg; + + cfg = our_dconfig(r); + /* + * Log the call, but don't do anything else - and report truthfully that + * we didn't do anything. + */ + trace_add(r->server, r, cfg, "example_type_checker()"); + return DECLINED; +} + +/* + * This routine is called to perform any module-specific fixing of header + * fields, et cetera. It is invoked just before any content-handler. + * + * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the + * server will still call any remaining modules with an handler for this + * phase. + */ +static int example_fixer_upper(request_rec *r) +{ + + excfg *cfg; + + cfg = our_dconfig(r); + /* + * Log the call and exit. + */ + trace_add(r->server, r, cfg, "example_fixer_upper()"); + return OK; +} + +/* + * This routine is called to perform any module-specific logging activities + * over and above the normal server things. + * + * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, any + * remaining modules with an handler for this phase will still be called. + */ +static int example_logger(request_rec *r) +{ + + excfg *cfg; + + cfg = our_dconfig(r); + trace_add(r->server, r, cfg, "example_logger()"); + return DECLINED; +} + +/* + * This routine is called to give the module a chance to look at the request + * headers and take any appropriate specific actions early in the processing + * sequence. + * + * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, any + * remaining modules with handlers for this phase will still be called. + */ +static int example_header_parser(request_rec *r) +{ + + excfg *cfg; + + cfg = our_dconfig(r); + trace_add(r->server, r, cfg, "example_header_parser()"); + return DECLINED; +} + +/*--------------------------------------------------------------------------*/ +/* */ +/* All of the routines have been declared now. Here's the list of */ +/* directives specific to our module, and information about where they */ +/* may appear and how the command parser should pass them to us for */ +/* processing. Note that care must be taken to ensure that there are NO */ +/* collisions of directive names between modules. */ +/* */ +/*--------------------------------------------------------------------------*/ +/* + * List of directives specific to our module. + */ +static const command_rec example_cmds[] = +{ + { + "Example", /* directive name */ + cmd_example, /* config action routine */ + NULL, /* argument to include in call */ + OR_OPTIONS, /* where available */ + NO_ARGS, /* arguments */ + "Example directive - no arguments" + /* directive description */ + }, + {NULL} +}; + +/*--------------------------------------------------------------------------*/ +/* */ +/* Now the list of content handlers available from this module. */ +/* */ +/*--------------------------------------------------------------------------*/ +/* + * List of content handlers our module supplies. Each handler is defined by + * two parts: a name by which it can be referenced (such as by + * {Add,Set}Handler), and the actual routine name. The list is terminated by + * a NULL block, since it can be of variable length. + * + * Note that content-handlers are invoked on a most-specific to least-specific + * basis; that is, a handler that is declared for "text/plain" will be + * invoked before one that was declared for "text / *". Note also that + * if a content-handler returns anything except DECLINED, no other + * content-handlers will be called. + */ +static const handler_rec example_handlers[] = +{ + {"example-handler", example_handler}, + {NULL} +}; + +/*--------------------------------------------------------------------------*/ +/* */ +/* Finally, the list of callback routines and data structures that */ +/* provide the hooks into our module from the other parts of the server. */ +/* */ +/*--------------------------------------------------------------------------*/ +/* + * Module definition for configuration. If a particular callback is not + * needed, replace its routine name below with the word NULL. + * + * The number in brackets indicates the order in which the routine is called + * during request processing. Note that not all routines are necessarily + * called (such as if a resource doesn't have access restrictions). + */ +module example_module = +{ + STANDARD_MODULE_STUFF, + example_init, /* module initializer */ + example_create_dir_config, /* per-directory config creator */ + example_merge_dir_config, /* dir config merger */ + example_create_server_config, /* server config creator */ + example_merge_server_config, /* server config merger */ + example_cmds, /* command table */ + example_handlers, /* [7] list of handlers */ + example_translate_handler, /* [2] filename-to-URI translation */ + example_check_user_id, /* [5] check/validate user_id */ + example_auth_checker, /* [6] check user_id is valid *here* */ + example_access_checker, /* [4] check access by host address */ + example_type_checker, /* [7] MIME type checker/setter */ + example_fixer_upper, /* [8] fixups */ + example_logger, /* [10] logger */ + example_header_parser, /* [3] header parser */ + example_child_init, /* process initializer */ + example_child_exit, /* process exit/cleanup */ + example_post_read_request /* [1] post read_request handling */ +}; diff --git a/APACHE_1_3b7/src/modules/experimental/.cvsignore b/APACHE_1_3b7/src/modules/experimental/.cvsignore new file mode 100644 index 0000000000..8b4c6e3da4 --- /dev/null +++ b/APACHE_1_3b7/src/modules/experimental/.cvsignore @@ -0,0 +1,3 @@ +Makefile +*.lo +*.so diff --git a/APACHE_1_3b7/src/modules/experimental/.indent.pro b/APACHE_1_3b7/src/modules/experimental/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3b7/src/modules/experimental/.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/APACHE_1_3b7/src/modules/experimental/Makefile.tmpl b/APACHE_1_3b7/src/modules/experimental/Makefile.tmpl new file mode 100644 index 0000000000..1978c45da9 --- /dev/null +++ b/APACHE_1_3b7/src/modules/experimental/Makefile.tmpl @@ -0,0 +1,12 @@ + +#Dependencies + +$(OBJS) $(OBJS_PIC): Makefile + +# DO NOT REMOVE +mod_mmap_static.o: mod_mmap_static.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_log.h \ + $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \ + $(INCDIR)/http_core.h diff --git a/APACHE_1_3b7/src/modules/experimental/mod_mmap_static.c b/APACHE_1_3b7/src/modules/experimental/mod_mmap_static.c new file mode 100644 index 0000000000..b82492fd31 --- /dev/null +++ b/APACHE_1_3b7/src/modules/experimental/mod_mmap_static.c @@ -0,0 +1,390 @@ +/* ==================================================================== + * Copyright (c) 1998 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 . + * + */ + +/* + * mod_mmap_static: mmap a config-time list of files for faster serving + * + * v0.04 + * + * Author: Dean Gaudet + * + * v0.01: initial implementation + * v0.02: get rid of the extra stat() in the core by filling in what we know + * v0.03: get rid of the cached match from the xlat routine since there are + * many cases where the request is modified between it and the + * handler... so we do the binary search twice, but the second time + * we can use st_ino and st_dev to speed it up. + * v0.04: work around mod_rewrite, which sets r->filename to the uri first + */ + +/* + Documentation: + + The concept is simple. Some sites have a set of static files that are + really busy, and change infrequently (or even on a regular schedule). + Save time by mmap()ing these files into memory and avoid a lot of the + crap required to do normal file serving. Place directives such as: + + mmapfile /path/to/file1 + mmapfile /path/to/file2 + ... + + into your configuration. These files are only mmap()d when the server + is restarted, so if you change the list, or if the files are changed, + then you'll need to restart the server. + + To reiterate that point: if the files are modified *in place* + without restarting the server you may end up serving requests that + are completely bogus. You should update files by unlinking the old + copy and putting a new copy in place. Most tools such as rdist and + mv do this. + + There's no such thing as inheriting these files across vhosts or + whatever... place the directives in the main server only. + + Known problems: + + Don't use Alias or RewriteRule to move these files around... unless + you feel like paying for an extra stat() on each request. This is + a deficiency in the Apache API that will hopefully be solved some day. + The file will be served out of the mmap cache, but there will be + an extra stat() that's a waste. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#define CORE_PRIVATE + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" +#include "http_core.h" + +module MODULE_VAR_EXPORT mmap_static_module; + +typedef struct { + char *filename; + void *mm; + struct stat finfo; +} a_file; + +typedef struct { + array_header *files; + array_header *inode_sorted; +} a_server_config; + + +static void *create_server_config(pool *p, server_rec *s) +{ + a_server_config *sconf = ap_palloc(p, sizeof(*sconf)); + + sconf->files = ap_make_array(p, 20, sizeof(a_file)); + sconf->inode_sorted = NULL; + return sconf; +} + +static void cleanup_mmap(void *sconfv) +{ + a_server_config *sconf = sconfv; + size_t n; + a_file *file; + + n = sconf->files->nelts; + file = (a_file *)sconf->files->elts; + while(n) { + munmap(file->mm, file->finfo.st_size); + ++file; + --n; + } +} + +static const char *mmapfile(cmd_parms *cmd, void *dummy, char *filename) +{ + a_server_config *sconf; + a_file *new_file; + a_file tmp; + int fd; + caddr_t mm; + + if (stat(filename, &tmp.finfo) == -1) { + ap_log_error(APLOG_MARK, APLOG_WARNING, cmd->server, + "mmap_static: unable to stat(%s), skipping", filename); + return NULL; + } + if ((tmp.finfo.st_mode & S_IFMT) != S_IFREG) { + ap_log_error(APLOG_MARK, APLOG_WARNING, cmd->server, + "mmap_static: %s isn't a regular file, skipping", filename); + return NULL; + } + ap_block_alarms(); + fd = open(filename, O_RDONLY, 0); + if (fd == -1) { + ap_log_error(APLOG_MARK, APLOG_WARNING, cmd->server, + "mmap_static: unable to open(%s, O_RDONLY), skipping", filename); + return NULL; + } + mm = mmap(NULL, tmp.finfo.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (mm == (caddr_t)-1) { + int save_errno = errno; + close(fd); + ap_unblock_alarms(); + errno = save_errno; + ap_log_error(APLOG_MARK, APLOG_WARNING, cmd->server, + "mmap_static: unable to mmap %s, skipping", filename); + return NULL; + } + close(fd); + tmp.mm = mm; + tmp.filename = ap_pstrdup(cmd->pool, filename); + sconf = ap_get_module_config(cmd->server->module_config, &mmap_static_module); + new_file = ap_push_array(sconf->files); + *new_file = tmp; + if (sconf->files->nelts == 1) { + /* first one, register the cleanup */ + ap_register_cleanup(cmd->pool, sconf, cleanup_mmap, ap_null_cleanup); + } + ap_unblock_alarms(); + return NULL; +} + +static command_rec mmap_static_cmds[] = +{ + { + "mmapfile", mmapfile, NULL, RSRC_CONF, ITERATE, + "A space separated list of files to mmap at config time" + }, + { + NULL + } +}; + +static int file_compare(const void *av, const void *bv) +{ + const a_file *a = av; + const a_file *b = bv; + + return strcmp(a->filename, b->filename); +} + +static int inode_compare(const void *av, const void *bv) +{ + const a_file *a = *(a_file **)av; + const a_file *b = *(a_file **)bv; + long c; + + c = a->finfo.st_ino - b->finfo.st_ino; + if (c == 0) { + return a->finfo.st_dev - b->finfo.st_dev; + } + return c; +} + +static void mmap_init(server_rec *s, pool *p) +{ + a_server_config *sconf; + array_header *inodes; + a_file *elts; + int nelts; + int i; + + /* sort the elements of the main_server, by filename */ + sconf = ap_get_module_config(s->module_config, &mmap_static_module); + elts = (a_file *)sconf->files->elts; + nelts = sconf->files->nelts; + qsort(elts, nelts, sizeof(a_file), file_compare); + + /* build an index by inode as well, speeds up the search in the handler */ + inodes = ap_make_array(p, nelts, sizeof(a_file *)); + sconf->inode_sorted = inodes; + for (i = 0; i < nelts; ++i) { + *(a_file **)ap_push_array(inodes) = &elts[i]; + } + qsort(inodes->elts, nelts, sizeof(a_file *), inode_compare); + + /* and make the virtualhosts share the same thing */ + for (s = s->next; s; s = s->next) { + ap_set_module_config(s->module_config, &mmap_static_module, sconf); + } +} + +/* If it's one of ours, fill in r->finfo now to avoid extra stat()... this is a + * bit of a kludge, because we really want to run after core_translate runs. + */ + +static int mmap_static_xlat(request_rec *r) +{ + a_server_config *sconf; + a_file tmp; + a_file *match; + int res; + + /* we require other modules to first set up a filename */ + res = core_module.translate_handler(r); + if (res == DECLINED || !r->filename) { + return res; + } + sconf = ap_get_module_config(r->server->module_config, &mmap_static_module); + tmp.filename = r->filename; + match = (a_file *)bsearch(&tmp, sconf->files->elts, sconf->files->nelts, + sizeof(a_file), file_compare); + if (match == NULL) { + return DECLINED; + } + + /* shortcircuit the get_path_info() stat() calls and stuff */ + r->finfo = match->finfo; + return OK; +} + + +static int mmap_static_handler(request_rec *r) +{ + a_server_config *sconf; + a_file tmp; + a_file *ptmp; + a_file **pmatch; + a_file *match; + int rangestatus, errstatus; + + /* we don't handle anything but GET */ + if (r->method_number != M_GET) return DECLINED; + + /* file doesn't exist, we won't be dealing with it */ + if (r->finfo.st_mode == 0) return DECLINED; + + sconf = ap_get_module_config(r->server->module_config, &mmap_static_module); + tmp.finfo.st_dev = r->finfo.st_dev; + tmp.finfo.st_ino = r->finfo.st_ino; + ptmp = &tmp; + pmatch = (a_file **)bsearch(&ptmp, sconf->inode_sorted->elts, + sconf->inode_sorted->nelts, sizeof(a_file *), inode_compare); + if (pmatch == NULL) { + return DECLINED; + } + match = *pmatch; + + /* note that we would handle GET on this resource */ + r->allowed |= (1 << M_GET); + + /* This handler has no use for a request body (yet), but we still + * need to read and discard it if the client sent one. + */ + if ((errstatus = ap_discard_request_body(r)) != OK) + return errstatus; + + ap_update_mtime(r, match->finfo.st_mtime); + ap_set_last_modified(r); + ap_set_etag(r); + if (((errstatus = ap_meets_conditions(r)) != OK) + || (errstatus = ap_set_content_length (r, match->finfo.st_size))) { + return errstatus; + } + + rangestatus = ap_set_byterange(r); + ap_send_http_header(r); + + if (!r->header_only) { + if (!rangestatus) { + ap_send_mmap (match->mm, r, 0, match->finfo.st_size); + } + else { + long offset, length; + while (ap_each_byterange(r, &offset, &length)) { + ap_send_mmap(match->mm, r, offset, length); + } + } + } + return OK; +} + + +static const handler_rec mmap_static_handlers[] = +{ + { "*/*", mmap_static_handler }, + { NULL } +}; + +module MODULE_VAR_EXPORT mmap_static_module = +{ + STANDARD_MODULE_STUFF, + mmap_init, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + create_server_config, /* server config */ + NULL, /* merge server config */ + mmap_static_cmds, /* command handlers */ + mmap_static_handlers, /* handlers */ + mmap_static_xlat, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/extra/.cvsignore b/APACHE_1_3b7/src/modules/extra/.cvsignore new file mode 100644 index 0000000000..4eb14983bc --- /dev/null +++ b/APACHE_1_3b7/src/modules/extra/.cvsignore @@ -0,0 +1,3 @@ +*.lo +*.so +* diff --git a/APACHE_1_3b7/src/modules/extra/.indent.pro b/APACHE_1_3b7/src/modules/extra/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3b7/src/modules/extra/.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/APACHE_1_3b7/src/modules/extra/Makefile.tmpl b/APACHE_1_3b7/src/modules/extra/Makefile.tmpl new file mode 100644 index 0000000000..67c70fab94 --- /dev/null +++ b/APACHE_1_3b7/src/modules/extra/Makefile.tmpl @@ -0,0 +1,6 @@ + +#Dependencies + +$(OBJS) $(OBJS_PIC): Makefile + +# DO NOT REMOVE diff --git a/APACHE_1_3b7/src/modules/proxy/.cvsignore b/APACHE_1_3b7/src/modules/proxy/.cvsignore new file mode 100644 index 0000000000..e14a4bec3b --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/.cvsignore @@ -0,0 +1,10 @@ +Debug +Release +ApacheModuleProxy.dsw +ApacheModuleProxy.mdp +ApacheModuleProxy.ncb +ApacheModuleProxy.opt +ApacheModuleProxy.plg +Makefile +*.lo +*.so diff --git a/APACHE_1_3b7/src/modules/proxy/.indent.pro b/APACHE_1_3b7/src/modules/proxy/.indent.pro new file mode 100644 index 0000000000..20c2d83371 --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/.indent.pro @@ -0,0 +1,55 @@ +-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 +-Tproxy_server_conf diff --git a/APACHE_1_3b7/src/modules/proxy/ApacheModuleProxy.dsp b/APACHE_1_3b7/src/modules/proxy/ApacheModuleProxy.dsp new file mode 100644 index 0000000000..9c94df590e --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/ApacheModuleProxy.dsp @@ -0,0 +1,133 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleProxy" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleProxy - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleProxy.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleProxy.mak"\ + CFG="ApacheModuleProxy - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleProxy - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleProxy - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\ApacheMo" +# PROP BASE Intermediate_Dir ".\ApacheMo" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 wsock32.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\ApacheM0" +# PROP BASE Intermediate_Dir ".\ApacheM0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleProxy - Win32 Release" +# Name "ApacheModuleProxy - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\mod_proxy.c +# End Source File +# Begin Source File + +SOURCE=.\proxy_cache.c +# End Source File +# Begin Source File + +SOURCE=.\proxy_connect.c +# End Source File +# Begin Source File + +SOURCE=.\proxy_ftp.c +# End Source File +# Begin Source File + +SOURCE=.\proxy_http.c +# End Source File +# Begin Source File + +SOURCE=.\proxy_util.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\mod_proxy.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/modules/proxy/ApacheModuleProxy.mak b/APACHE_1_3b7/src/modules/proxy/ApacheModuleProxy.mak new file mode 100644 index 0000000000..8c77037ba1 --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/ApacheModuleProxy.mak @@ -0,0 +1,557 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleProxy.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleProxy - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleProxy - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleProxy - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleProxy - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleProxy.mak"\ + CFG="ApacheModuleProxy - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleProxy - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleProxy - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleProxy.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleProxy.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_proxy.obj" + -@erase "$(INTDIR)\proxy_cache.obj" + -@erase "$(INTDIR)\proxy_connect.obj" + -@erase "$(INTDIR)\proxy_ftp.obj" + -@erase "$(INTDIR)\proxy_http.obj" + -@erase "$(INTDIR)\proxy_util.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleProxy.dll" + -@erase "$(OUTDIR)\ApacheModuleProxy.exp" + -@erase "$(OUTDIR)\ApacheModuleProxy.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleProxy.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Release/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleProxy.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo\ + /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleProxy.pdb"\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleProxy.dll"\ + /implib:"$(OUTDIR)\ApacheModuleProxy.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_proxy.obj" \ + "$(INTDIR)\proxy_cache.obj" \ + "$(INTDIR)\proxy_connect.obj" \ + "$(INTDIR)\proxy_ftp.obj" \ + "$(INTDIR)\proxy_http.obj" \ + "$(INTDIR)\proxy_util.obj" + +"$(OUTDIR)\ApacheModuleProxy.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleProxy.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleProxy.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_proxy.obj" + -@erase "$(INTDIR)\proxy_cache.obj" + -@erase "$(INTDIR)\proxy_connect.obj" + -@erase "$(INTDIR)\proxy_ftp.obj" + -@erase "$(INTDIR)\proxy_http.obj" + -@erase "$(INTDIR)\proxy_util.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleProxy.dll" + -@erase "$(OUTDIR)\ApacheModuleProxy.exp" + -@erase "$(OUTDIR)\ApacheModuleProxy.ilk" + -@erase "$(OUTDIR)\ApacheModuleProxy.lib" + -@erase "$(OUTDIR)\ApacheModuleProxy.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W4 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleProxy.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleProxy.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo\ + /subsystem:windows /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleProxy.pdb"\ + /debug /machine:I386 /out:"$(OUTDIR)\ApacheModuleProxy.dll"\ + /implib:"$(OUTDIR)\ApacheModuleProxy.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_proxy.obj" \ + "$(INTDIR)\proxy_cache.obj" \ + "$(INTDIR)\proxy_connect.obj" \ + "$(INTDIR)\proxy_ftp.obj" \ + "$(INTDIR)\proxy_http.obj" \ + "$(INTDIR)\proxy_util.obj" + +"$(OUTDIR)\ApacheModuleProxy.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleProxy - Win32 Debug" +SOURCE=.\mod_proxy.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_MOD_P=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_vhost.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_P=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_proxy.obj" : $(SOURCE) $(DEP_CPP_MOD_P) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_MOD_P=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_vhost.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\mod_proxy.obj" : $(SOURCE) $(DEP_CPP_MOD_P) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_cache.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\md5.h"\ + "..\..\include\multithread.h"\ + "..\..\include\util_date.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + {$(INCLUDE)}"sys\utime.h"\ + +NODEP_CPP_PROXY=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\proxy_cache.obj" : $(SOURCE) $(DEP_CPP_PROXY) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\md5.h"\ + "..\..\include\multithread.h"\ + "..\..\include\util_date.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_cache.obj" : $(SOURCE) $(DEP_CPP_PROXY) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_connect.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY_=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_PROXY_=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\proxy_connect.obj" : $(SOURCE) $(DEP_CPP_PROXY_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY_=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_connect.obj" : $(SOURCE) $(DEP_CPP_PROXY_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_ftp.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY_F=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_PROXY_F=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\proxy_ftp.obj" : $(SOURCE) $(DEP_CPP_PROXY_F) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY_F=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_ftp.obj" : $(SOURCE) $(DEP_CPP_PROXY_F) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_http.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY_H=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_date.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_PROXY_H=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\proxy_http.obj" : $(SOURCE) $(DEP_CPP_PROXY_H) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY_H=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_date.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_http.obj" : $(SOURCE) $(DEP_CPP_PROXY_H) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_util.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY_U=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\md5.h"\ + "..\..\include\multithread.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_PROXY_U=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\proxy_util.obj" : $(SOURCE) $(DEP_CPP_PROXY_U) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY_U=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\explain.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\md5.h"\ + "..\..\include\multithread.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_util.obj" : $(SOURCE) $(DEP_CPP_PROXY_U) "$(INTDIR)" + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/modules/proxy/Makefile.libdir b/APACHE_1_3b7/src/modules/proxy/Makefile.libdir new file mode 100644 index 0000000000..7b5254013a --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/Makefile.libdir @@ -0,0 +1,4 @@ +This is a place-holder which indicates to Configure that it shouldn't +provide the default targets when building the Makefile in this directory. +Instead it'll just prepend all the important variable definitions, and +copy the Makefile.tmpl onto the end. diff --git a/APACHE_1_3b7/src/modules/proxy/Makefile.tmpl b/APACHE_1_3b7/src/modules/proxy/Makefile.tmpl new file mode 100644 index 0000000000..d027ce7d70 --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/Makefile.tmpl @@ -0,0 +1,91 @@ + +LIB=libproxy.$(LIBEXT) + +OBJS=\ + mod_proxy.o \ + proxy_cache.o proxy_connect.o proxy_ftp.o proxy_http.o proxy_util.o +OBJS_PIC=\ + mod_proxy.lo \ + proxy_cache.lo proxy_connect.lo proxy_ftp.lo proxy_http.lo proxy_util.lo + +all: lib + +lib: $(LIB) + +libproxy.a: $(OBJS) + rm -f $@ + ar cr $@ $(OBJS) + $(RANLIB) $@ + +libproxy.so: $(OBJS_PIC) + rm -f $@ + $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $@ $(OBJS_PIC) + +.SUFFIXES: .o .lo + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $< + +.c.lo: + $(CC) -c $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $< && mv $*.o $*.lo + +clean: + rm -f $(OBJS) $(OBJS_PIC) $(LIB) + +distclean: clean + -rm -f Makefile + +# We really don't expect end users to use this rule. It works only with +# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after +# using it. +depend: + cp Makefile.tmpl Makefile.tmpl.bak \ + && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \ + && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \ + && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \ + -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \ + > Makefile.tmpl \ + && rm Makefile.new + +#Dependencies + +$(OBJS) $(OBJS_PIC): Makefile + +# DO NOT REMOVE +mod_proxy.o: mod_proxy.c mod_proxy.h $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/explain.h $(INCDIR)/http_log.h \ + $(INCDIR)/http_vhost.h +proxy_cache.o: proxy_cache.c mod_proxy.h $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/explain.h $(INCDIR)/http_log.h \ + $(INCDIR)/http_main.h $(INCDIR)/util_date.h \ + $(INCDIR)/multithread.h $(INCDIR)/md5.h +proxy_connect.o: proxy_connect.c mod_proxy.h $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/explain.h $(INCDIR)/http_log.h \ + $(INCDIR)/http_main.h +proxy_ftp.o: proxy_ftp.c mod_proxy.h $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/explain.h $(INCDIR)/http_main.h +proxy_http.o: proxy_http.c mod_proxy.h $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/explain.h $(INCDIR)/http_log.h \ + $(INCDIR)/http_main.h $(INCDIR)/http_core.h \ + $(INCDIR)/util_date.h +proxy_util.o: proxy_util.c mod_proxy.h $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/explain.h $(INCDIR)/http_main.h $(INCDIR)/md5.h \ + $(INCDIR)/multithread.h $(INCDIR)/http_log.h diff --git a/APACHE_1_3b7/src/modules/proxy/mod_proxy.c b/APACHE_1_3b7/src/modules/proxy/mod_proxy.c new file mode 100644 index 0000000000..2c1293deaa --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/mod_proxy.c @@ -0,0 +1,811 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 . + * + */ + +#include "mod_proxy.h" +#include "http_log.h" +#include "http_vhost.h" + +/* Some WWW schemes and their default ports; this is basically /etc/services */ +/* This will become global when the protocol abstraction comes */ +static struct proxy_services defports[] = +{ + {"ftp", DEFAULT_FTP_PORT}, + {"gopher", DEFAULT_GOPHER_PORT}, + {"http", DEFAULT_HTTP_PORT}, + {"nntp", DEFAULT_NNTP_PORT}, + {"wais", DEFAULT_WAIS_PORT}, + {"https", DEFAULT_HTTPS_PORT}, + {"snews", DEFAULT_SNEWS_PORT}, + {"prospero", DEFAULT_PROSPERO_PORT}, + {NULL, -1} /* unknown port */ +}; + +/* + * A Web proxy module. Stages: + * + * translate_name: set filename to proxy: + * type_checker: set type to PROXY_MAGIC_TYPE if filename begins proxy: + * fix_ups: convert the URL stored in the filename to the + * canonical form. + * handler: handle proxy requests + */ + +/* -------------------------------------------------------------- */ +/* Translate the URL into a 'filename' */ + +static int alias_match(const char *uri, const char *alias_fakename) +{ + const char *end_fakename = alias_fakename + strlen(alias_fakename); + const char *aliasp = alias_fakename, *urip = uri; + + while (aliasp < end_fakename) { + if (*aliasp == '/') { + /* any number of '/' in the alias matches any number in + * the supplied URI, but there must be at least one... + */ + if (*urip != '/') + return 0; + + while (*aliasp == '/') + ++aliasp; + while (*urip == '/') + ++urip; + } + else { + /* Other characters are compared literally */ + if (*urip++ != *aliasp++) + return 0; + } + } + + /* Check last alias path component matched all the way */ + + if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/') + return 0; + + /* Return number of characters from URI which matched (may be + * greater than length of alias, since we may have matched + * doubled slashes) + */ + + return urip - uri; +} + +/* Detect if an absoluteURI should be proxied or not. Note that we + * have to do this during this phase because later phases are + * "short-circuiting"... i.e. translate_names will end when the first + * module returns OK. So for example, if the request is something like: + * + * GET http://othervhost/cgi-bin/printenv HTTP/1.0 + * + * mod_alias will notice the /cgi-bin part and ScriptAlias it and + * short-circuit the proxy... just because of the ordering in the + * configuration file. + */ +static int proxy_detect(request_rec *r) +{ + void *sconf = r->server->module_config; + proxy_server_conf *conf; + + conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + + if (conf->req && r->parsed_uri.scheme) { + /* but it might be something vhosted */ + if (!(r->parsed_uri.hostname + && !strcasecmp(r->parsed_uri.scheme, http_method(r)) + && ap_matches_request_vhost(r, r->parsed_uri.hostname, + r->parsed_uri.port_str ? r->parsed_uri.port : default_port(r)))) { + r->proxyreq = 1; + r->uri = r->unparsed_uri; + r->filename = ap_pstrcat(r->pool, "proxy:", r->uri, NULL); + r->handler = "proxy-server"; + } + } + /* We need special treatment for CONNECT proxying: it has no scheme part */ + else if (conf->req && r->method_number == M_CONNECT + && r->parsed_uri.hostname + && r->parsed_uri.port_str) { + r->proxyreq = 1; + r->uri = r->unparsed_uri; + r->filename = ap_pstrcat(r->pool, "proxy:", r->uri, NULL); + r->handler = "proxy-server"; + } + return DECLINED; +} + +static int proxy_trans(request_rec *r) +{ + void *sconf = r->server->module_config; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + int i, len; + struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts; + + if (r->proxyreq) { + /* someone has already set up the proxy, it was possibly ourselves + * in proxy_detect + */ + return OK; + } + + /* XXX: since r->uri has been manipulated already we're not really + * compliant with RFC1945 at this point. But this probably isn't + * an issue because this is a hybrid proxy/origin server. + */ + + for (i = 0; i < conf->aliases->nelts; i++) { + len = alias_match(r->uri, ent[i].fake); + + if (len > 0) { + r->filename = ap_pstrcat(r->pool, "proxy:", ent[i].real, + r->uri + len, NULL); + r->handler = "proxy-server"; + r->proxyreq = 1; + return OK; + } + } + return DECLINED; +} + +/* -------------------------------------------------------------- */ +/* Fixup the filename */ + +/* + * Canonicalise the URL + */ +static int proxy_fixup(request_rec *r) +{ + char *url, *p; + + if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0) + return DECLINED; + + url = &r->filename[6]; + +/* canonicalise each specific scheme */ + if (strncasecmp(url, "http:", 5) == 0) + return ap_proxy_http_canon(r, url + 5, "http", DEFAULT_HTTP_PORT); + else if (strncasecmp(url, "ftp:", 4) == 0) + return ap_proxy_ftp_canon(r, url + 4); + + p = strchr(url, ':'); + if (p == NULL || p == url) + return HTTP_BAD_REQUEST; + + return OK; /* otherwise; we've done the best we can */ +} + +static void proxy_init(server_rec *r, pool *p) +{ + ap_proxy_garbage_init(r, p); +} + + + +/* Send a redirection if the request contains a hostname which is not */ +/* fully qualified, i.e. doesn't have a domain name appended. Some proxy */ +/* servers like Netscape's allow this and access hosts from the local */ +/* domain in this case. I think it is better to redirect to a FQDN, since */ +/* these will later be found in the bookmarks files. */ +/* The "ProxyDomain" directive determines what domain will be appended */ +static int proxy_needsdomain(request_rec *r, const char *url, const char *domain) +{ + char *nuri, *ref; + + /* We only want to worry about GETs */ + if (!r->proxyreq || r->method_number != M_GET || !r->parsed_uri.hostname) + return DECLINED; + + /* If host does contain a dot already, or it is "localhost", decline */ + if (strchr(r->parsed_uri.hostname, '.') != NULL + || strcasecmp(r->parsed_uri.hostname, "localhost") == 0) + return DECLINED; /* host name has a dot already */ + + ref = ap_table_get(r->headers_in, "Referer"); + + /* Reassemble the request, but insert the domain after the host name */ + /* Note that the domain name always starts with a dot */ + r->parsed_uri.hostname = ap_pstrcat(r->pool, r->parsed_uri.hostname, + domain, NULL); + nuri = ap_unparse_uri_components(r->pool, + &r->parsed_uri, + UNP_REVEALPASSWORD); + + ap_table_set(r->headers_out, "Location", nuri); + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r->server, + "Domain missing: %s sent to %s%s%s", r->uri, + ap_unparse_uri_components(r->pool, &r->parsed_uri, + UNP_OMITUSERINFO), + ref ? " from " : "", ref ? ref : ""); + + return HTTP_MOVED_PERMANENTLY; +} + +/* -------------------------------------------------------------- */ +/* Invoke handler */ + +static int proxy_handler(request_rec *r) +{ + char *url, *scheme, *p; + void *sconf = r->server->module_config; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + array_header *proxies = conf->proxies; + struct proxy_remote *ents = (struct proxy_remote *) proxies->elts; + int i, rc; + struct cache_req *cr; + int direct_connect = 0; + + if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0) + return DECLINED; + + if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) + return rc; + + url = r->filename + 6; + p = strchr(url, ':'); + if (p == NULL) + return HTTP_BAD_REQUEST; + + rc = ap_proxy_cache_check(r, url, &conf->cache, &cr); + if (rc != DECLINED) + return rc; + + /* If the host doesn't have a domain name, add one and redirect. */ + if (conf->domain != NULL) { + rc = proxy_needsdomain(r, url, conf->domain); + if (is_HTTP_REDIRECT(rc)) + return HTTP_MOVED_PERMANENTLY; + } + + *p = '\0'; + scheme = ap_pstrdup(r->pool, url); + *p = ':'; + + /* Check URI's destination host against NoProxy hosts */ + /* Bypass ProxyRemote server lookup if configured as NoProxy */ + /* we only know how to handle communication to a proxy via http */ + /*if (strcasecmp(scheme, "http") == 0) */ + { + int ii; + struct dirconn_entry *list = (struct dirconn_entry *) conf->dirconn->elts; + + for (direct_connect = ii = 0; ii < conf->dirconn->nelts && !direct_connect; ii++) { + direct_connect = list[ii].matcher(&list[ii], r); + } +#if DEBUGGING + { + char msg[256]; + sprintf(msg, (direct_connect) ? "NoProxy for %s" : "UseProxy for %s", r->uri); + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, msg); + } +#endif + } + +/* firstly, try a proxy, unless a NoProxy directive is active */ + + if (!direct_connect) + for (i = 0; i < proxies->nelts; i++) { + p = strchr(ents[i].scheme, ':'); /* is it a partial URL? */ + if (strcmp(ents[i].scheme, "*") == 0 || + (p == NULL && strcasecmp(scheme, ents[i].scheme) == 0) || + (p != NULL && + strncasecmp(url, ents[i].scheme, strlen(ents[i].scheme)) == 0)) { + /* CONNECT is a special method that bypasses the normal + * proxy code. + */ + if (r->method_number == M_CONNECT) + rc = ap_proxy_connect_handler(r, cr, url, ents[i].hostname, + ents[i].port); +/* we only know how to handle communication to a proxy via http */ + else if (strcasecmp(ents[i].protocol, "http") == 0) + rc = ap_proxy_http_handler(r, cr, url, ents[i].hostname, + ents[i].port); + else + rc = DECLINED; + + /* an error or success */ + if (rc != DECLINED && rc != HTTP_BAD_GATEWAY) + return rc; + /* we failed to talk to the upstream proxy */ + } + } + +/* otherwise, try it direct */ +/* N.B. what if we're behind a firewall, where we must use a proxy or + * give up?? + */ + /* handle the scheme */ + if (r->method_number == M_CONNECT) + return ap_proxy_connect_handler(r, cr, url, NULL, 0); + if (strcasecmp(scheme, "http") == 0) + return ap_proxy_http_handler(r, cr, url, NULL, 0); + if (strcasecmp(scheme, "ftp") == 0) + return ap_proxy_ftp_handler(r, cr, url); + else + return NOT_IMPLEMENTED; +} + +/* -------------------------------------------------------------- */ +/* Setup configurable data */ + +static void * + create_proxy_config(pool *p, server_rec *s) +{ + proxy_server_conf *ps = ap_pcalloc(p, sizeof(proxy_server_conf)); + + ps->proxies = ap_make_array(p, 10, sizeof(struct proxy_remote)); + ps->aliases = ap_make_array(p, 10, sizeof(struct proxy_alias)); + ps->raliases = ap_make_array(p, 10, sizeof(struct proxy_alias)); + ps->noproxies = ap_make_array(p, 10, sizeof(struct noproxy_entry)); + ps->dirconn = ap_make_array(p, 10, sizeof(struct dirconn_entry)); + ps->nocaches = ap_make_array(p, 10, sizeof(struct nocache_entry)); + ps->domain = NULL; + ps->req = 0; + + ps->cache.root = NULL; + ps->cache.space = DEFAULT_CACHE_SPACE; + ps->cache.maxexpire = DEFAULT_CACHE_MAXEXPIRE; + ps->cache.defaultexpire = DEFAULT_CACHE_EXPIRE; + ps->cache.lmfactor = DEFAULT_CACHE_LMFACTOR; + ps->cache.gcinterval = -1; + /* at these levels, the cache can have 2^18 directories (256,000) */ + ps->cache.dirlevels = 3; + ps->cache.dirlength = 1; + + return ps; +} + +static const char * + add_proxy(cmd_parms *cmd, void *dummy, char *f, char *r) +{ + server_rec *s = cmd->server; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); + struct proxy_remote *new; + char *p, *q; + int port; + + p = strchr(r, ':'); + if (p == NULL || p[1] != '/' || p[2] != '/' || p[3] == '\0') + return "Bad syntax for a remote proxy server"; + q = strchr(p + 3, ':'); + if (q != NULL) { + if (sscanf(q + 1, "%u", &port) != 1 || port > 65535) + return "Bad syntax for a remote proxy server (bad port number)"; + *q = '\0'; + } + else + port = -1; + *p = '\0'; + if (strchr(f, ':') == NULL) + ap_str_tolower(f); /* lowercase scheme */ + ap_str_tolower(p + 3); /* lowercase hostname */ + + if (port == -1) { + int i; + for (i = 0; defports[i].scheme != NULL; i++) + if (strcasecmp(defports[i].scheme, r) == 0) + break; + port = defports[i].port; + } + + new = ap_push_array(conf->proxies); + new->scheme = f; + new->protocol = r; + new->hostname = p + 3; + new->port = port; + return NULL; +} + +static const char * + add_pass(cmd_parms *cmd, void *dummy, char *f, char *r) +{ + server_rec *s = cmd->server; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); + struct proxy_alias *new; + + new = ap_push_array(conf->aliases); + new->fake = f; + new->real = r; + return NULL; +} + +static const char * + add_pass_reverse(cmd_parms *cmd, void *dummy, char *f, char *r) +{ + server_rec *s = cmd->server; + proxy_server_conf *conf; + struct proxy_alias *new; + + conf = (proxy_server_conf *)ap_get_module_config(s->module_config, + &proxy_module); + new = ap_push_array(conf->raliases); + new->fake = f; + new->real = r; + return NULL; +} + +static const char * + set_proxy_exclude(cmd_parms *parms, void *dummy, char *arg) +{ + server_rec *s = parms->server; + proxy_server_conf *conf = + ap_get_module_config(s->module_config, &proxy_module); + struct noproxy_entry *new; + struct noproxy_entry *list = (struct noproxy_entry *) conf->noproxies->elts; + struct hostent hp; + int found = 0; + int i; + + /* Don't duplicate entries */ + for (i = 0; i < conf->noproxies->nelts; i++) { + if (strcasecmp(arg, list[i].name) == 0) /* ignore case for host names */ + found = 1; + } + + if (!found) { + new = ap_push_array(conf->noproxies); + new->name = arg; + /* Don't do name lookups on things that aren't dotted */ + if (strchr(arg, '.') != NULL && ap_proxy_host2addr(new->name, &hp) == NULL) + memcpy(&new->addr, hp.h_addr, sizeof(struct in_addr)); + else + new->addr.s_addr = 0; + } + return NULL; +} + +/* Similar to set_proxy_exclude(), but defining directly connected hosts, + * which should never be accessed via the configured ProxyRemote servers + */ +static const char * + set_proxy_dirconn(cmd_parms *parms, void *dummy, char *arg) +{ + server_rec *s = parms->server; + proxy_server_conf *conf = + ap_get_module_config(s->module_config, &proxy_module); + struct dirconn_entry *New; + struct dirconn_entry *list = (struct dirconn_entry *) conf->dirconn->elts; + int found = 0; + int i; + + /* Don't duplicate entries */ + for (i = 0; i < conf->dirconn->nelts; i++) { + if (strcasecmp(arg, list[i].name) == 0) + found = 1; + } + + if (!found) { + New = ap_push_array(conf->dirconn); + New->name = arg; + New->hostentry = NULL; + + if (ap_proxy_is_ipaddr(New, parms->pool)) { +#if DEBUGGING + fprintf(stderr, "Parsed addr %s\n", inet_ntoa(New->addr)); + fprintf(stderr, "Parsed mask %s\n", inet_ntoa(New->mask)); +#endif + } + else if (ap_proxy_is_domainname(New, parms->pool)) { + ap_str_tolower(New->name); +#if DEBUGGING + fprintf(stderr, "Parsed domain %s\n", New->name); +#endif + } + else if (ap_proxy_is_hostname(New, parms->pool)) { + ap_str_tolower(New->name); +#if DEBUGGING + fprintf(stderr, "Parsed host %s\n", New->name); +#endif + } + else { + ap_proxy_is_word(New, parms->pool); +#if DEBUGGING + fprintf(stderr, "Parsed word %s\n", New->name); +#endif + } + } + return NULL; +} + +static const char * + set_proxy_domain(cmd_parms *parms, void *dummy, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + + if (arg[0] != '.') + return "Domain name must start with a dot."; + + psf->domain = arg; + return NULL; +} + +static const char * + set_proxy_req(cmd_parms *parms, void *dummy, int flag) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + + psf->req = flag; + return NULL; +} + + +static const char * + set_cache_size(cmd_parms *parms, char *struct_ptr, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + int val; + + if (sscanf(arg, "%d", &val) != 1) + return "Value must be an integer"; + psf->cache.space = val; + return NULL; +} + +static const char * + set_cache_root(cmd_parms *parms, void *dummy, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + + psf->cache.root = arg; + + return NULL; +} + +static const char * + set_cache_factor(cmd_parms *parms, void *dummy, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + double val; + + if (sscanf(arg, "%lg", &val) != 1) + return "Value must be a float"; + psf->cache.lmfactor = val; + + return NULL; +} + +static const char * + set_cache_maxex(cmd_parms *parms, void *dummy, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + double val; + + if (sscanf(arg, "%lg", &val) != 1) + return "Value must be a float"; + psf->cache.maxexpire = (int) (val * (double) SEC_ONE_HR); + return NULL; +} + +static const char * + set_cache_defex(cmd_parms *parms, void *dummy, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + double val; + + if (sscanf(arg, "%lg", &val) != 1) + return "Value must be a float"; + psf->cache.defaultexpire = (int) (val * (double) SEC_ONE_HR); + return NULL; +} + +static const char * + set_cache_gcint(cmd_parms *parms, void *dummy, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + double val; + + if (sscanf(arg, "%lg", &val) != 1) + return "Value must be a float"; + psf->cache.gcinterval = (int) (val * (double) SEC_ONE_HR); + return NULL; +} + +static const char * + set_cache_dirlevels(cmd_parms *parms, char *struct_ptr, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + int val; + + val = atoi(arg); + if (val < 1) + return "Value must be an integer greater than 0"; + if (val * psf->cache.dirlength > CACHEFILE_LEN) + return "CacheDirLevels*CacheDirLength value must not be higher than 20"; + psf->cache.dirlevels = val; + return NULL; +} + +static const char * + set_cache_dirlength(cmd_parms *parms, char *struct_ptr, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + int val; + + val = atoi(arg); + if (val < 1) + return "Value must be an integer greater than 0"; + if (val * psf->cache.dirlevels > CACHEFILE_LEN) + return "CacheDirLevels*CacheDirLength value must not be higher than 20"; + psf->cache.dirlength = val; + return NULL; +} + +static const char * + set_cache_exclude(cmd_parms *parms, void *dummy, char *arg) +{ + server_rec *s = parms->server; + proxy_server_conf *conf = + ap_get_module_config(s->module_config, &proxy_module); + struct nocache_entry *new; + struct nocache_entry *list = (struct nocache_entry *) conf->nocaches->elts; + struct hostent hp; + int found = 0; + int i; + + /* Don't duplicate entries */ + for (i = 0; i < conf->nocaches->nelts; i++) { + if (strcasecmp(arg, list[i].name) == 0) /* ignore case for host names */ + found = 1; + } + + if (!found) { + new = ap_push_array(conf->nocaches); + new->name = arg; + /* Don't do name lookups on things that aren't dotted */ + if (strchr(arg, '.') != NULL && ap_proxy_host2addr(new->name, &hp) == NULL) + /*@@@FIXME: This copies only the first of (possibly many) IP addrs */ + memcpy(&new->addr, hp.h_addr, sizeof(struct in_addr)); + else + new->addr.s_addr = 0; + } + return NULL; +} + +static const char * + set_recv_buffer_size(cmd_parms *parms, void *dummy, char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + int s = atoi(arg); + if (s < 512 && s != 0) { + return "ProxyReceiveBufferSize must be >= 512 bytes, or 0 for system default."; + } + + psf->recv_buffer_size = s; + return NULL; +} + +static const handler_rec proxy_handlers[] = +{ + {"proxy-server", proxy_handler}, + {NULL} +}; + +static const command_rec proxy_cmds[] = +{ + {"ProxyRequests", set_proxy_req, NULL, RSRC_CONF, FLAG, + "on if the true proxy requests should be accepted"}, + {"ProxyRemote", add_proxy, NULL, RSRC_CONF, TAKE2, + "a scheme, partial URL or '*' and a proxy server"}, + {"ProxyPass", add_pass, NULL, RSRC_CONF, TAKE2, + "a virtual path and a URL"}, + {"ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF, TAKE2, + "a virtual path and a URL for reverse proxy behaviour"}, + {"ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, ITERATE, + "A list of names, hosts or domains to which the proxy will not connect"}, + {"ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF, TAKE1, + "Receive buffer size for outgoing HTTP and FTP connections in bytes"}, + {"NoProxy", set_proxy_dirconn, NULL, RSRC_CONF, ITERATE, + "A list of domains, hosts, or subnets to which the proxy will connect directly"}, + {"ProxyDomain", set_proxy_domain, NULL, RSRC_CONF, TAKE1, + "The default intranet domain name (in absence of a domain in the URL)"}, + {"CacheRoot", set_cache_root, NULL, RSRC_CONF, TAKE1, + "The directory to store cache files"}, + {"CacheSize", set_cache_size, NULL, RSRC_CONF, TAKE1, + "The maximum disk space used by the cache in Kb"}, + {"CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF, TAKE1, + "The maximum time in hours to cache a document"}, + {"CacheDefaultExpire", set_cache_defex, NULL, RSRC_CONF, TAKE1, + "The default time in hours to cache a document"}, + {"CacheLastModifiedFactor", set_cache_factor, NULL, RSRC_CONF, TAKE1, + "The factor used to estimate Expires date from LastModified date"}, + {"CacheGcInterval", set_cache_gcint, NULL, RSRC_CONF, TAKE1, + "The interval between garbage collections, in hours"}, + {"CacheDirLevels", set_cache_dirlevels, NULL, RSRC_CONF, TAKE1, + "The number of levels of subdirectories in the cache"}, + {"CacheDirLength", set_cache_dirlength, NULL, RSRC_CONF, TAKE1, + "The number of characters in subdirectory names"}, + {"NoCache", set_cache_exclude, NULL, RSRC_CONF, ITERATE, + "A list of names, hosts or domains for which caching is *not* provided"}, + {NULL} +}; + +module MODULE_VAR_EXPORT proxy_module = +{ + STANDARD_MODULE_STUFF, + proxy_init, /* initializer */ + NULL, /* create per-directory config structure */ + NULL, /* merge per-directory config structures */ + create_proxy_config, /* create per-server config structure */ + NULL, /* merge per-server config structures */ + proxy_cmds, /* command table */ + proxy_handlers, /* handlers */ + proxy_trans, /* translate_handler */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + proxy_fixup, /* pre-run fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + proxy_detect /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/proxy/mod_proxy.h b/APACHE_1_3b7/src/modules/proxy/mod_proxy.h new file mode 100644 index 0000000000..c7eca449e1 --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/mod_proxy.h @@ -0,0 +1,298 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 . + * + */ + +/* + * Main include file for the Apache proxy + */ + +/* + + Note that the Explain() stuff is not yet complete. + Also note numerous FIXMEs and CHECKMEs which should be eliminated. + + If TESTING is set, then garbage collection doesn't delete ... probably a good + idea when hacking. + + This code is still experimental! + + Things to do: + + 1. Make it garbage collect in the background, not while someone is waiting for + a response! + + 2. Check the logic thoroughly. + + 3. Empty directories are only removed the next time round (but this does avoid + two passes). Consider doing them the first time round. + + Ben Laurie 30 Mar 96 + + More things to do: + + 0. Code cleanup (ongoing) + + 1. add 230 response output for ftp now that it works + + 2. Make the ftp proxy transparent, also same with (future) gopher & wais + + 3. Use protocol handler struct a la Apache module handlers (Dirk van Gulik) + + 4. Use a cache expiry database for more efficient GC (Jeremy Wohl) + + 5. Bulletproof GC against SIGALRM + + Chuck Murcko 15 April 1997 + + */ + +#define TESTING 0 +#undef EXPLAIN + +#include "httpd.h" +#include "http_config.h" +#include "http_protocol.h" + +#include "explain.h" + +extern module MODULE_VAR_EXPORT proxy_module; + + +/* for proxy_canonenc() */ +enum enctype { + enc_path, enc_search, enc_user, enc_fpath, enc_parm +}; + +#define HDR_APP (0) /* append header, for proxy_add_header() */ +#define HDR_REP (1) /* replace header, for proxy_add_header() */ + +/* number of characters in the hash */ +#define HASH_LEN (22*2) + +/* maximum 'CacheDirLevels*CacheDirLength' value */ +#define CACHEFILE_LEN 20 /* must be less than HASH_LEN/2 */ + +#ifdef CHARSET_EBCDIC +#define CRLF "\r\n" +#else /*CHARSET_EBCDIC*/ +#define CRLF "\015\012" +#endif /*CHARSET_EBCDIC*/ + + +#define SEC_ONE_DAY 86400 /* one day, in seconds */ +#define SEC_ONE_HR 3600 /* one hour, in seconds */ + +#define DEFAULT_FTP_DATA_PORT 20 +#define DEFAULT_FTP_PORT 21 +#define DEFAULT_GOPHER_PORT 70 +#define DEFAULT_NNTP_PORT 119 +#define DEFAULT_WAIS_PORT 210 +#define DEFAULT_HTTPS_PORT 443 +#define DEFAULT_SNEWS_PORT 563 +#define DEFAULT_PROSPERO_PORT 1525 /* WARNING: conflict w/Oracle */ + +/* Some WWW schemes and their default ports; this is basically /etc/services */ +struct proxy_services { + const char *scheme; + int port; +}; + +/* static information about a remote proxy */ +struct proxy_remote { + const char *scheme; /* the schemes handled by this proxy, or '*' */ + const char *protocol; /* the scheme used to talk to this proxy */ + const char *hostname; /* the hostname of this proxy */ + int port; /* the port for this proxy */ +}; + +struct proxy_alias { + char *real; + char *fake; +}; + +struct dirconn_entry { + char *name; + struct in_addr addr, mask; + struct hostent *hostentry; + int (*matcher) (struct dirconn_entry * This, request_rec *r); +}; + +struct noproxy_entry { + char *name; + struct in_addr addr; +}; + +struct nocache_entry { + char *name; + struct in_addr addr; +}; + +#define DEFAULT_CACHE_SPACE 5 +#define DEFAULT_CACHE_MAXEXPIRE SEC_ONE_DAY +#define DEFAULT_CACHE_EXPIRE SEC_ONE_HR +#define DEFAULT_CACHE_LMFACTOR (0.1) + +/* static information about the local cache */ +struct cache_conf { + const char *root; /* the location of the cache directory */ + int space; /* Maximum cache size (in 1024 bytes) */ + int maxexpire; /* Maximum time to keep cached files in secs */ + int defaultexpire; /* default time to keep cached file in secs */ + double lmfactor; /* factor for estimating expires date */ + int gcinterval; /* garbage collection interval, in seconds */ + int dirlevels; /* Number of levels of subdirectories */ + int dirlength; /* Length of subdirectory names */ +}; + +typedef struct { + struct cache_conf cache; /* cache configuration */ + array_header *proxies; + array_header *aliases; + array_header *raliases; + array_header *noproxies; + array_header *dirconn; + array_header *nocaches; + char *domain; /* domain name to use in absence of a domain name in the request */ + int req; /* true if proxy requests are enabled */ + int recv_buffer_size; +} proxy_server_conf; + +struct hdr_entry { + char *field; + char *value; +}; + +/* caching information about a request */ +struct cache_req { + request_rec *req; /* the request */ + char *url; /* the URL requested */ + char *filename; /* name of the cache file, or NULL if no cache */ + char *tempfile; /* name of the temporary file, of NULL if not caching */ + time_t ims; /* if-modified-since date of request; -1 if no header */ + BUFF *fp; /* the cache file descriptor if the file is cached + and may be returned, or NULL if the file is + not cached (or must be reloaded) */ + time_t expire; /* calculated expire date of cached entity */ + time_t lmod; /* last-modified date of cached entity */ + time_t date; /* the date the cached file was last touched */ + int version; /* update count of the file */ + unsigned int len; /* content length */ + char *protocol; /* Protocol, and major/minor number, e.g. HTTP/1.1 */ + int status; /* the status of the cached file */ + char *resp_line; /* the whole status like (protocol, code + message) */ + array_header *hdrs; /* the HTTP headers of the file */ +}; + +/* Function prototypes */ + +/* proxy_cache.c */ + +void ap_proxy_cache_tidy(struct cache_req *c); +int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, + struct cache_req **cr); +int ap_proxy_cache_update(struct cache_req *c, array_header *resp_hdrs, + const int is_HTTP1, int nocache); +void ap_proxy_garbage_coll(request_rec *r); + +/* proxy_connect.c */ + +int ap_proxy_connect_handler(request_rec *r, struct cache_req *c, char *url, + const char *proxyhost, int proxyport); + +/* proxy_ftp.c */ + +int ap_proxy_ftp_canon(request_rec *r, char *url); +int ap_proxy_ftp_handler(request_rec *r, struct cache_req *c, char *url); + +/* proxy_http.c */ + +int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, + int def_port); +int ap_proxy_http_handler(request_rec *r, struct cache_req *c, char *url, + const char *proxyhost, int proxyport); + +/* proxy_util.c */ + +int ap_proxy_hex2c(const char *x); +void ap_proxy_c2hex(int ch, char *x); +char *ap_proxy_canonenc(pool *p, const char *x, int len, enum enctype t, + int isenc); +char *ap_proxy_canon_netloc(pool *p, char **const urlp, char **userp, + char **passwordp, char **hostp, int *port); +char *ap_proxy_date_canon(pool *p, char *x); +array_header *ap_proxy_read_headers(pool *p, char *buffer, int size, BUFF *f); +long int ap_proxy_send_fb(BUFF *f, request_rec *r, BUFF *f2, struct cache_req *c); +struct hdr_entry *ap_proxy_get_header(array_header *hdrs_arr, const char *name); +struct hdr_entry *ap_proxy_add_header(array_header *hdrs_arr, char *field, + char *value, int rep); +void ap_proxy_del_header(array_header *hdrs_arr, const char *field); +void ap_proxy_send_headers(request_rec *r, const char *respline, + array_header *hdrs_arr); +int ap_proxy_liststr(const char *list, const char *val); +void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength); +int ap_proxy_hex2sec(const char *x); +void ap_proxy_sec2hex(int t, char *y); +void ap_proxy_log_uerror(const char *routine, const char *file, const char *err, + server_rec *s); +BUFF *ap_proxy_cache_error(struct cache_req *r); +int ap_proxyerror(request_rec *r, const char *message); +const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp); +int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p); +int ap_proxy_is_domainname(struct dirconn_entry *This, pool *p); +int ap_proxy_is_hostname(struct dirconn_entry *This, pool *p); +int ap_proxy_is_word(struct dirconn_entry *This, pool *p); +int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r); +int ap_proxy_garbage_init(server_rec *, pool *); diff --git a/APACHE_1_3b7/src/modules/proxy/proxy_cache.c b/APACHE_1_3b7/src/modules/proxy/proxy_cache.c new file mode 100644 index 0000000000..7a020817e7 --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/proxy_cache.c @@ -0,0 +1,980 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 . + * + */ + +/* Cache and garbage collection routines for Apache proxy */ + +#include "mod_proxy.h" +#include "http_log.h" +#include "http_main.h" +#include "util_date.h" +#ifdef WIN32 +#include +#else +#include +#endif /* WIN32 */ +#include "multithread.h" +#include "md5.h" + +DEF_Explain + +#ifndef abs +#define abs(c) ((c) >= 0 ? (c) : -(c)) +#endif + +struct gc_ent { + unsigned long int len; + time_t expire; + char file[HASH_LEN + 1]; + +}; + +static int gcdiff(const void *ap, const void *bp) +{ + const struct gc_ent *a = *(const struct gc_ent * const *) ap; + const struct gc_ent *b = *(const struct gc_ent * const *) bp; + + if (a->expire > b->expire) + return 1; + else if (a->expire < b->expire) + return -1; + else + return 0; +} + +static int curbytes, cachesize, every; +static unsigned long int curblocks; +static time_t garbage_now, garbage_expire; +static char *filename; +static mutex *garbage_mutex = NULL; + + +int ap_proxy_garbage_init(server_rec *r, pool *p) +{ + if (!garbage_mutex) + garbage_mutex = ap_create_mutex(NULL); + + return (0); +} + + +static int sub_garbage_coll(request_rec *r, array_header *files, + const char *cachedir, const char *cachesubdir); +static void help_proxy_garbage_coll(request_rec *r); + +void ap_proxy_garbage_coll(request_rec *r) +{ + static int inside = 0; + + (void) ap_acquire_mutex(garbage_mutex); + if (inside == 1) { + (void) ap_release_mutex(garbage_mutex); + return; + } + else + inside = 1; + (void) ap_release_mutex(garbage_mutex); + + help_proxy_garbage_coll(r); + + (void) ap_acquire_mutex(garbage_mutex); + inside = 0; + (void) ap_release_mutex(garbage_mutex); +} + + +static void help_proxy_garbage_coll(request_rec *r) +{ + const char *cachedir; + void *sconf = r->server->module_config; + proxy_server_conf *pconf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + const struct cache_conf *conf = &pconf->cache; + array_header *files; + struct stat buf; + struct gc_ent *fent, **elts; + int i, timefd; + static time_t lastcheck = BAD_DATE; /* static data!!! */ + + cachedir = conf->root; + cachesize = conf->space; + every = conf->gcinterval; + + if (cachedir == NULL || every == -1) + return; + garbage_now = time(NULL); + if (garbage_now != -1 && lastcheck != BAD_DATE && garbage_now < lastcheck + every) + return; + + ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */ + + filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2); + strcpy(filename, cachedir); + strcat(filename, "/.time"); + if (stat(filename, &buf) == -1) { /* does not exist */ + if (errno != ENOENT) { + ap_proxy_log_uerror("stat", filename, NULL, r->server); + ap_unblock_alarms(); + return; + } + if ((timefd = creat(filename, 0666)) == -1) { + if (errno != EEXIST) + ap_proxy_log_uerror("creat", filename, NULL, r->server); + else + lastcheck = abs(garbage_now); /* someone else got in there */ + ap_unblock_alarms(); + return; + } + close(timefd); + } + else { + lastcheck = buf.st_mtime; /* save the time */ + if (garbage_now < lastcheck + every) { + ap_unblock_alarms(); + return; + } + if (utime(filename, NULL) == -1) + ap_proxy_log_uerror("utimes", filename, NULL, r->server); + } + files = ap_make_array(r->pool, 100, sizeof(struct gc_ent *)); + curblocks = 0; + curbytes = 0; + + sub_garbage_coll(r, files, cachedir, "/"); + + if (curblocks < cachesize || curblocks + curbytes <= cachesize) { + ap_unblock_alarms(); + return; + } + + qsort(files->elts, files->nelts, sizeof(struct gc_ent *), gcdiff); + + elts = (struct gc_ent **) files->elts; + for (i = 0; i < files->nelts; i++) { + fent = elts[i]; + sprintf(filename, "%s%s", cachedir, fent->file); + Explain3("GC Unlinking %s (expiry %ld, garbage_now %ld)", filename, fent->expire, garbage_now); +#if TESTING + fprintf(stderr, "Would unlink %s\n", filename); +#else + if (unlink(filename) == -1) { + if (errno != ENOENT) + ap_proxy_log_uerror("unlink", filename, NULL, r->server); + } + else +#endif + { + curblocks -= fent->len >> 10; + curbytes -= fent->len & 0x3FF; + if (curbytes < 0) { + curbytes += 1024; + curblocks--; + } + if (curblocks < cachesize || curblocks + curbytes <= cachesize) + break; + } + } + ap_unblock_alarms(); +} + +static int sub_garbage_coll(request_rec *r, array_header *files, + const char *cachebasedir, const char *cachesubdir) +{ + char line[27]; + char cachedir[HUGE_STRING_LEN]; + struct stat buf; + int fd, i; + DIR *dir; +#if defined(NEXT) || defined(WIN32) + struct DIR_TYPE *ent; +#else + struct dirent *ent; +#endif + struct gc_ent *fent; + int nfiles = 0; + + ap_snprintf(cachedir, sizeof(cachedir), "%s%s", cachebasedir, cachesubdir); + Explain1("GC Examining directory %s", cachedir); + dir = opendir(cachedir); + if (dir == NULL) { + ap_proxy_log_uerror("opendir", cachedir, NULL, r->server); + return 0; + } + + while ((ent = readdir(dir)) != NULL) { + if (ent->d_name[0] == '.') + continue; + sprintf(filename, "%s%s", cachedir, ent->d_name); + Explain1("GC Examining file %s", filename); +/* is it a temporary file? */ + if (strncmp(ent->d_name, "tmp", 3) == 0) { +/* then stat it to see how old it is; delete temporary files > 1 day old */ + if (stat(filename, &buf) == -1) { + if (errno != ENOENT) + ap_proxy_log_uerror("stat", filename, NULL, r->server); + } + else if (garbage_now != -1 && buf.st_atime < garbage_now - SEC_ONE_DAY && + buf.st_mtime < garbage_now - SEC_ONE_DAY) { + Explain1("GC unlink %s", filename); +#if TESTING + fprintf(stderr, "Would unlink %s\n", filename); +#else + unlink(filename); +#endif + } + continue; + } + ++nfiles; +/* is it another file? */ + /* FIXME: Shouldn't any unexpected files be deleted? */ + /* if (strlen(ent->d_name) != HASH_LEN) continue; */ + +/* under OS/2 use dirent's d_attr to identify a diretory */ +#ifdef __EMX__ +/* is it a directory? */ + if (ent->d_attr & A_DIR) { + char newcachedir[HUGE_STRING_LEN]; + ap_snprintf(newcachedir, sizeof(newcachedir), + "%s%s/", cachesubdir, ent->d_name); + if (!sub_garbage_coll(r, files, cachebasedir, newcachedir)) { + ap_snprintf(newcachedir, sizeof(newcachedir), + "%s%s", cachedir, ent->d_name); +#if TESTING + fprintf(stderr, "Would remove directory %s\n", newcachedir); +#else + rmdir(newcachedir); +#endif + --nfiles; + } + continue; + } +#endif + +/* read the file */ + fd = open(filename, O_RDONLY | O_BINARY); + if (fd == -1) { + if (errno != ENOENT) + ap_proxy_log_uerror("open", filename, NULL, + r->server); + continue; + } + if (fstat(fd, &buf) == -1) { + ap_proxy_log_uerror("fstat", filename, NULL, r->server); + close(fd); + continue; + } + +/* In OS/2 this has already been done above */ +#ifndef __EMX__ + if (S_ISDIR(buf.st_mode)) { + char newcachedir[HUGE_STRING_LEN]; + close(fd); + ap_snprintf(newcachedir, sizeof(newcachedir), + "%s%s/", cachesubdir, ent->d_name); + if (!sub_garbage_coll(r, files, cachebasedir, newcachedir)) { + ap_snprintf(newcachedir, sizeof(newcachedir), + "%s%s", cachedir, ent->d_name); +#if TESTING + fprintf(stderr, "Would remove directory %s\n", newcachedir); +#else + rmdir(newcachedir); +#endif + --nfiles; + } + continue; + } +#endif + + i = read(fd, line, 26); + if (i == -1) { + ap_proxy_log_uerror("read", filename, NULL, r->server); + close(fd); + continue; + } + close(fd); + line[i] = '\0'; + garbage_expire = ap_proxy_hex2sec(line + 18); + if (!ap_checkmask(line, "&&&&&&&& &&&&&&&& &&&&&&&&") || + garbage_expire == BAD_DATE) { + /* bad file */ + if (garbage_now != -1 && buf.st_atime > garbage_now + SEC_ONE_DAY && + buf.st_mtime > garbage_now + SEC_ONE_DAY) { + ap_log_error_old("proxy: deleting bad cache file", r->server); +#if TESTING + fprintf(stderr, "Would unlink bad file %s\n", filename); +#else + unlink(filename); +#endif + } + continue; + } + +/* + * we need to calculate an 'old' factor, and remove the 'oldest' files + * so that the space requirement is met; sort by the expires date of the + * file. + * + */ + /* FIXME: We should make the array an array of gc_ents, not gc_ent *s + */ + fent = ap_palloc(r->pool, sizeof(struct gc_ent)); + fent->len = buf.st_size; + fent->expire = garbage_expire; + strcpy(fent->file, cachesubdir); + strcat(fent->file, ent->d_name); + *(struct gc_ent **) ap_push_array(files) = fent; + +/* accumulate in blocks, to cope with directories > 4Gb */ + curblocks += buf.st_size >> 10; /* Kbytes */ + curbytes += buf.st_size & 0x3FF; + if (curbytes >= 1024) { + curbytes -= 1024; + curblocks++; + } + } + + closedir(dir); + + return nfiles; + +} + +/* + * read a cache file; + * returns 1 on success, + * 0 on failure (bad file or wrong URL) + * -1 on UNIX error + */ +static int rdcache(pool *p, BUFF *cachefp, struct cache_req *c) +{ + char urlbuff[1034], *strp; + int len; +/* read the data from the cache file */ +/* format + * date SP lastmod SP expire SP count SP content-length CRLF + * dates are stored as hex seconds since 1970 + */ + len = ap_bgets(urlbuff, 1034, cachefp); + if (len == -1) + return -1; + if (len == 0 || urlbuff[len - 1] != '\n') + return 0; + urlbuff[len - 1] = '\0'; + + if (!ap_checkmask(urlbuff, + "&&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&&")) + return 0; + + c->date = ap_proxy_hex2sec(urlbuff); + c->lmod = ap_proxy_hex2sec(urlbuff + 9); + c->expire = ap_proxy_hex2sec(urlbuff + 18); + c->version = ap_proxy_hex2sec(urlbuff + 27); + c->len = ap_proxy_hex2sec(urlbuff + 36); + +/* check that we have the same URL */ + len = ap_bgets(urlbuff, 1034, cachefp); + if (len == -1) + return -1; + if (len == 0 || strncmp(urlbuff, "X-URL: ", 7) != 0 || + urlbuff[len - 1] != '\n') + return 0; + urlbuff[len - 1] = '\0'; + if (strcmp(urlbuff + 7, c->url) != 0) + return 0; + +/* What follows is the message */ + len = ap_bgets(urlbuff, 1034, cachefp); + if (len == -1) + return -1; + if (len == 0 || urlbuff[len - 1] != '\n') + return 0; + urlbuff[--len] = '\0'; + + c->resp_line = ap_pstrdup(p, urlbuff); + strp = strchr(urlbuff, ' '); + if (strp == NULL) + return 0; + + c->status = atoi(strp); + c->hdrs = ap_proxy_read_headers(p, urlbuff, 1034, cachefp); + if (c->hdrs == NULL) + return -1; + if (c->len != -1) { /* add a content-length header */ + struct hdr_entry *q; + q = ap_proxy_get_header(c->hdrs, "Content-Length"); + if (q == NULL) { + strp = ap_palloc(p, 15); + ap_snprintf(strp, 15, "%u", c->len); + ap_proxy_add_header(c->hdrs, "Content-Length", strp, HDR_REP); + } + } + return 1; +} + + +/* + * Call this to test for a resource in the cache + * Returns DECLINED if we need to check the remote host + * or an HTTP status code if successful + * + * Functions: + * if URL is cached then + * if cached file is not expired then + * if last modified after if-modified-since then send body + * else send 304 Not modified + * else + * if last modified after if-modified-since then add + * last modified date to request + */ +int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, + struct cache_req **cr) +{ + char hashfile[66], *imstr, *pragma, *auth; + struct cache_req *c; + time_t now; + BUFF *cachefp; + int cfd, i; + const long int zero = 0L; + void *sconf = r->server->module_config; + proxy_server_conf *pconf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + + c = ap_pcalloc(r->pool, sizeof(struct cache_req)); + *cr = c; + c->req = r; + c->url = ap_pstrdup(r->pool, url); + +/* get the If-Modified-Since date of the request */ + c->ims = BAD_DATE; + imstr = ap_table_get(r->headers_in, "If-Modified-Since"); + if (imstr != NULL) { +/* this may modify the value in the original table */ + imstr = ap_proxy_date_canon(r->pool, imstr); + c->ims = ap_parseHTTPdate(imstr); + if (c->ims == BAD_DATE) /* bad or out of range date; remove it */ + ap_table_unset(r->headers_in, "If-Modified-Since"); + } + +/* find the filename for this cache entry */ + ap_proxy_hash(url, hashfile, pconf->cache.dirlevels, pconf->cache.dirlength); + if (conf->root != NULL) + c->filename = ap_pstrcat(r->pool, conf->root, "/", hashfile, NULL); + else + c->filename = NULL; + + cachefp = NULL; +/* find out about whether the request can access the cache */ + pragma = ap_table_get(r->headers_in, "Pragma"); + auth = ap_table_get(r->headers_in, "Authorization"); + Explain5("Request for %s, pragma=%s, auth=%s, ims=%ld, imstr=%s", url, + pragma, auth, c->ims, imstr); + if (c->filename != NULL && r->method_number == M_GET && + strlen(url) < 1024 && !ap_proxy_liststr(pragma, "no-cache") && + auth == NULL) { + Explain1("Check file %s", c->filename); + cfd = open(c->filename, O_RDWR | O_BINARY); + if (cfd != -1) { + ap_note_cleanups_for_fd(r->pool, cfd); + cachefp = ap_bcreate(r->pool, B_RD | B_WR); + ap_bpushfd(cachefp, cfd, cfd); + } + else if (errno != ENOENT) + ap_proxy_log_uerror("open", c->filename, + "proxy: error opening cache file", r->server); +#ifdef EXPLAIN + else + Explain1("File %s not found", c->filename); +#endif + } + + if (cachefp != NULL) { + i = rdcache(r->pool, cachefp, c); + if (i == -1) + ap_proxy_log_uerror("read", c->filename, + "proxy: error reading cache file", r->server); + else if (i == 0) + ap_log_error_old("proxy: bad cache file", r->server); + if (i != 1) { + ap_pclosef(r->pool, cachefp->fd); + cachefp = NULL; + } + } + if (cachefp == NULL) + c->hdrs = ap_make_array(r->pool, 2, sizeof(struct hdr_entry)); + /* FIXME: Shouldn't we check the URL somewhere? */ + now = time(NULL); +/* Ok, have we got some un-expired data? */ + if (cachefp != NULL && c->expire != BAD_DATE && now < c->expire) { + Explain0("Unexpired data available"); +/* check IMS */ + if (c->lmod != BAD_DATE && c->ims != BAD_DATE && c->ims >= c->lmod) { +/* has the cached file changed since this request? */ + if (c->date == BAD_DATE || c->date > c->ims) { +/* No, but these header values may have changed, so we send them with the + * 304 response + */ + /* CHECKME: surely this was wrong? (Ben) + p = table_get(r->headers_in, "Expires"); + */ + struct hdr_entry *q; + + q = ap_proxy_get_header(c->hdrs, "Expires"); + if (q != NULL && q->value != NULL) + ap_table_set(r->headers_out, "Expires", q->value); + } + ap_pclosef(r->pool, cachefp->fd); + Explain0("Use local copy, cached file hasn't changed"); + return USE_LOCAL_COPY; + } + +/* Ok, has been modified */ + Explain0("Local copy modified, send it"); + r->status_line = strchr(c->resp_line, ' ') + 1; + r->status = c->status; + if (!r->assbackwards) { + ap_soft_timeout("proxy send headers", r); + ap_proxy_send_headers(r, c->resp_line, c->hdrs); + ap_kill_timeout(r); + } + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); + r->sent_bodyct = 1; + if (!r->header_only) + ap_proxy_send_fb(cachefp, r, NULL, NULL); + ap_pclosef(r->pool, cachefp->fd); + return OK; + } + +/* if we already have data and a last-modified date, and it is not a head + * request, then add an If-Modified-Since + */ + + if (cachefp != NULL && c->lmod != BAD_DATE && !r->header_only) { +/* + * use the later of the one from the request and the last-modified date + * from the cache + */ + if (c->ims == BAD_DATE || c->ims < c->lmod) { + struct hdr_entry *q; + + q = ap_proxy_get_header(c->hdrs, "Last-Modified"); + + if (q != NULL && q->value != NULL) + ap_table_set(r->headers_in, "If-Modified-Since", + (char *) q->value); + } + } + c->fp = cachefp; + + Explain0("Local copy not present or expired. Declining."); + + return DECLINED; +} + +/* + * Having read the response from the client, decide what to do + * If the response is not cachable, then delete any previously cached + * response, and copy data from remote server to client. + * Functions: + * parse dates + * check for an uncachable response + * calculate an expiry date, if one is not provided + * if the remote file has not been modified, then return the document + * from the cache, maybe updating the header line + * otherwise, delete the old cached file and open a new temporary file + */ +int ap_proxy_cache_update(struct cache_req *c, array_header *resp_hdrs, + const int is_HTTP1, int nocache) +{ +#ifdef ULTRIX_BRAIN_DEATH + extern char *mktemp(char *template); +#endif + request_rec *r = c->req; + char *p; + int i; + struct hdr_entry *expire, *dates, *lmods, *clen; + time_t expc, date, lmod, now; + char buff[46]; + void *sconf = r->server->module_config; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + const long int zero = 0L; + + c->tempfile = NULL; + +/* we've received the response */ +/* read expiry date; if a bad date, then leave it so the client can + * read it + */ + expire = ap_proxy_get_header(resp_hdrs, "Expires"); + if (expire != NULL) + expc = ap_parseHTTPdate(expire->value); + else + expc = BAD_DATE; + +/* + * read the last-modified date; if the date is bad, then delete it + */ + lmods = ap_proxy_get_header(resp_hdrs, "Last-Modified"); + if (lmods != NULL) { + lmod = ap_parseHTTPdate(lmods->value); + if (lmod == BAD_DATE) { +/* kill last modified date */ + lmods->value = NULL; + lmods = NULL; + } + } + else + lmod = BAD_DATE; + +/* + * what responses should we not cache? + * Unknown status responses and those known to be uncacheable + * 304 response when we have no valid cache file, or + * 200 response from HTTP/1.0 and up without a Last-Modified header, or + * HEAD requests, or + * requests with an Authorization header, or + * protocol requests nocache (e.g. ftp with user/password) + */ + if ((r->status != 200 && r->status != 301 && r->status != 304) || + (expire != NULL && expc == BAD_DATE) || + (r->status == 304 && c->fp == NULL) || + (r->status == 200 && lmods == NULL && is_HTTP1) || + r->header_only || + ap_table_get(r->headers_in, "Authorization") != NULL || + nocache) { + Explain1("Response is not cacheable, unlinking %s", c->filename); +/* close the file */ + if (c->fp != NULL) { + ap_pclosef(r->pool, c->fp->fd); + c->fp = NULL; + } +/* delete the previously cached file */ + unlink(c->filename); + return DECLINED; /* send data to client but not cache */ + } + +/* otherwise, we are going to cache the response */ +/* + * Read the date. Generate one if one is not supplied + */ + dates = ap_proxy_get_header(resp_hdrs, "Date"); + if (dates != NULL) + date = ap_parseHTTPdate(dates->value); + else + date = BAD_DATE; + + now = time(NULL); + + if (date == BAD_DATE) { /* No, or bad date */ +/* no date header! */ +/* add one; N.B. use the time _now_ rather than when we were checking the cache + */ + date = abs(now); + p = ap_gm_timestr_822(r->pool, now); + dates = ap_proxy_add_header(resp_hdrs, "Date", p, HDR_REP); + Explain0("Added date header"); + } + +/* check last-modified date */ + if (lmod != BAD_DATE && lmod > date) +/* if its in the future, then replace by date */ + { + lmod = date; + lmods->value = dates->value; + Explain0("Last modified is in the future, replacing with now"); + } +/* if the response did not contain the header, then use the cached version */ + if (lmod == BAD_DATE && c->fp != NULL) { + lmod = c->lmod; + Explain0("Reusing cached last modified"); + } + +/* we now need to calculate the expire data for the object. */ + if (expire == NULL && c->fp != NULL) { /* no expiry data sent in response */ + expire = ap_proxy_get_header(c->hdrs, "Expires"); + if (expire != NULL) + expc = ap_parseHTTPdate(expire->value); + } +/* so we now have the expiry date */ +/* if no expiry date then + * if lastmod + * expiry date = now + min((date - lastmod) * factor, maxexpire) + * else + * expire date = now + defaultexpire + */ + Explain1("Expiry date is %ld", expc); + if (expc == BAD_DATE) { + if (lmod != BAD_DATE) { + double x = (double) (date - lmod) * conf->cache.lmfactor; + double maxex = conf->cache.maxexpire; + if (x > maxex) + x = maxex; + expc = abs(now) + (int) x; + } + else + expc = abs(now) + conf->cache.defaultexpire; + Explain1("Expiry date calculated %ld", expc); + } + +/* get the content-length header */ + clen = ap_proxy_get_header(resp_hdrs, "Content-Length"); + if (clen == NULL) + c->len = -1; + else + c->len = atoi(clen->value); + + ap_proxy_sec2hex(date, buff); + buff[8] = ' '; + ap_proxy_sec2hex(lmod, buff + 9); + buff[17] = ' '; + ap_proxy_sec2hex(expc, buff + 18); + buff[26] = ' '; + ap_proxy_sec2hex(c->version++, buff + 27); + buff[35] = ' '; + ap_proxy_sec2hex(c->len, buff + 36); + buff[44] = '\n'; + buff[45] = '\0'; + +/* if file not modified */ + if (r->status == 304) { + if (c->ims != BAD_DATE && lmod != BAD_DATE && lmod <= c->ims) { +/* set any changed headers somehow */ +/* update dates and version, but not content-length */ + if (lmod != c->lmod || expc != c->expire || date != c->date) { + off_t curpos = lseek(c->fp->fd, 0, SEEK_SET); + if (curpos == -1) + ap_proxy_log_uerror("lseek", c->filename, + "proxy: error seeking on cache file", r->server); + else if (write(c->fp->fd, buff, 35) == -1) + ap_proxy_log_uerror("write", c->filename, + "proxy: error updating cache file", r->server); + } + ap_pclosef(r->pool, c->fp->fd); + Explain0("Remote document not modified, use local copy"); + /* CHECKME: Is this right? Shouldn't we check IMS again here? */ + return USE_LOCAL_COPY; + } + else { +/* return the whole document */ + Explain0("Remote document updated, sending"); + r->status_line = strchr(c->resp_line, ' ') + 1; + r->status = c->status; + if (!r->assbackwards) { + ap_soft_timeout("proxy send headers", r); + ap_proxy_send_headers(r, c->resp_line, c->hdrs); + ap_kill_timeout(r); + } + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); + r->sent_bodyct = 1; + if (!r->header_only) + ap_proxy_send_fb(c->fp, r, NULL, NULL); +/* set any changed headers somehow */ +/* update dates and version, but not content-length */ + if (lmod != c->lmod || expc != c->expire || date != c->date) { + off_t curpos = lseek(c->fp->fd, 0, SEEK_SET); + + if (curpos == -1) + ap_proxy_log_uerror("lseek", c->filename, + "proxy: error seeking on cache file", r->server); + else if (write(c->fp->fd, buff, 35) == -1) + ap_proxy_log_uerror("write", c->filename, + "proxy: error updating cache file", r->server); + } + ap_pclosef(r->pool, c->fp->fd); + return OK; + } + } +/* new or modified file */ + if (c->fp != NULL) { + ap_pclosef(r->pool, c->fp->fd); + c->fp->fd = -1; + } + c->version = 0; + ap_proxy_sec2hex(0, buff + 27); + buff[35] = ' '; + +/* open temporary file */ +#define TMPFILESTR "/tmpXXXXXX" + if (conf->cache.root == NULL) + return DECLINED; + c->tempfile = ap_palloc(r->pool, strlen(conf->cache.root) + sizeof(TMPFILESTR)); + strcpy(c->tempfile, conf->cache.root); + strcat(c->tempfile, TMPFILESTR); +#undef TMPFILESTR + p = mktemp(c->tempfile); + if (p == NULL) + return DECLINED; + + Explain1("Create temporary file %s", c->tempfile); + + i = open(c->tempfile, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0622); + if (i == -1) { + ap_proxy_log_uerror("open", c->tempfile, + "proxy: error creating cache file", r->server); + return DECLINED; + } + ap_note_cleanups_for_fd(r->pool, i); + c->fp = ap_bcreate(r->pool, B_WR); + ap_bpushfd(c->fp, -1, i); + + if (ap_bvputs(c->fp, buff, "X-URL: ", c->url, "\n", NULL) == -1) { + ap_proxy_log_uerror("write", c->tempfile, + "proxy: error writing cache file", r->server); + ap_pclosef(r->pool, c->fp->fd); + unlink(c->tempfile); + c->fp = NULL; + } + return DECLINED; +} + +void ap_proxy_cache_tidy(struct cache_req *c) +{ + server_rec *s = c->req->server; + long int bc; + + if (c->fp == NULL) + return; + + ap_bgetopt(c->req->connection->client, BO_BYTECT, &bc); + + if (c->len != -1) { +/* file lengths don't match; don't cache it */ + if (bc != c->len) { + ap_pclosef(c->req->pool, c->fp->fd); /* no need to flush */ + unlink(c->tempfile); + return; + } + } + else if (c->req->connection->aborted) { + ap_pclosef(c->req->pool, c->fp->fd); /* no need to flush */ + unlink(c->tempfile); + return; + } + else { +/* update content-length of file */ + char buff[9]; + off_t curpos; + + c->len = bc; + ap_bflush(c->fp); + ap_proxy_sec2hex(c->len, buff); + curpos = lseek(c->fp->fd, 36, SEEK_SET); + if (curpos == -1) + ap_proxy_log_uerror("lseek", c->tempfile, + "proxy: error seeking on cache file", s); + else if (write(c->fp->fd, buff, 8) == -1) + ap_proxy_log_uerror("write", c->tempfile, + "proxy: error updating cache file", s); + } + + if (ap_bflush(c->fp) == -1) { + ap_proxy_log_uerror("write", c->tempfile, + "proxy: error writing to cache file", s); + ap_pclosef(c->req->pool, c->fp->fd); + unlink(c->tempfile); + return; + } + + if (ap_pclosef(c->req->pool, c->fp->fd) == -1) { + ap_proxy_log_uerror("close", c->tempfile, + "proxy: error closing cache file", s); + unlink(c->tempfile); + return; + } + + if (unlink(c->filename) == -1 && errno != ENOENT) { + ap_proxy_log_uerror("unlink", c->filename, + "proxy: error deleting old cache file", s); + } + else { + char *p; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); + + for (p = c->filename + strlen(conf->cache.root) + 1;;) { + p = strchr(p, '/'); + if (!p) + break; + *p = '\0'; +#ifdef WIN32 + if (mkdir(c->filename) < 0 && errno != EEXIST) +#else + if (mkdir(c->filename, S_IREAD | S_IWRITE | S_IEXEC) < 0 && errno != EEXIST) +#endif /* WIN32 */ + ap_proxy_log_uerror("mkdir", c->filename, + "proxy: error creating cache directory", s); + *p = '/'; + ++p; + } +#if defined(__EMX__) || defined(WIN32) + /* Under OS/2 use rename. */ + if (rename(c->tempfile, c->filename) == -1) + ap_proxy_log_uerror("rename", c->filename, + "proxy: error renaming cache file", s); + } +#else + + if (link(c->tempfile, c->filename) == -1) + ap_proxy_log_uerror("link", c->filename, + "proxy: error linking cache file", s); + } + + if (unlink(c->tempfile) == -1) + ap_proxy_log_uerror("unlink", c->tempfile, + "proxy: error deleting temp file", s); +#endif + +} diff --git a/APACHE_1_3b7/src/modules/proxy/proxy_connect.c b/APACHE_1_3b7/src/modules/proxy/proxy_connect.c new file mode 100644 index 0000000000..761ef43c59 --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/proxy_connect.c @@ -0,0 +1,264 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 . + * + */ + +/* CONNECT method for Apache proxy */ + +#include "mod_proxy.h" +#include "http_log.h" +#include "http_main.h" + +#ifdef HAVE_BSTRING_H +#include /* for IRIX, FD_SET calls bzero() */ +#endif + +DEF_Explain + +/* + * This handles Netscape CONNECT method secure proxy requests. + * A connection is opened to the specified host and data is + * passed through between the WWW site and the browser. + * + * This code is based on the INTERNET-DRAFT document + * "Tunneling SSL Through a WWW Proxy" currently at + * http://www.mcom.com/newsref/std/tunneling_ssl.html. + * + * If proxyhost and proxyport are set, we send a CONNECT to + * the specified proxy.. + * + * FIXME: this is bad, because it does its own socket I/O + * instead of using the I/O in buff.c. However, + * the I/O in buff.c blocks on reads, and because + * this function doesn't know how much data will + * be sent either way (or when) it can't use blocking + * I/O. This may be very implementation-specific + * (to Linux). Any suggestions? + * FIXME: this doesn't log the number of bytes sent, but + * that may be okay, since the data is supposed to + * be transparent. In fact, this doesn't log at all + * yet. 8^) + * FIXME: doesn't check any headers initally sent from the + * client. + * FIXME: should allow authentication, but hopefully the + * generic proxy authentication is good enough. + * FIXME: no check for r->assbackwards, whatever that is. + */ + +int ap_proxy_connect_handler(request_rec *r, struct cache_req *c, char *url, + const char *proxyhost, int proxyport) +{ + struct sockaddr_in server; + struct in_addr destaddr; + struct hostent server_hp; + const char *host, *err; + char *p; + int port, sock; + char buffer[HUGE_STRING_LEN]; + int nbytes, i, j; + fd_set fds; + + void *sconf = r->server->module_config; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; + + memset(&server, '\0', sizeof(server)); + server.sin_family = AF_INET; + + /* Break the URL into host:port pairs */ + + host = url; + p = strchr(url, ':'); + if (p == NULL) + port = DEFAULT_HTTPS_PORT; + else { + port = atoi(p + 1); + *p = '\0'; + } + +/* check if ProxyBlock directive on this host */ + destaddr.s_addr = ap_inet_addr(host); + for (i = 0; i < conf->noproxies->nelts; i++) { + if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL) + || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') + return ap_proxyerror(r, "Connect to remote machine blocked"); + } + + switch (port) { + case DEFAULT_HTTPS_PORT: + case DEFAULT_SNEWS_PORT: + break; + default: + return HTTP_SERVICE_UNAVAILABLE; + } + + if (proxyhost) { + Explain2("CONNECT to remote proxy %s on port %d", proxyhost, proxyport); + } + else { + Explain2("CONNECT to %s on port %d", host, port); + } + + server.sin_port = (proxyport ? htons(proxyport) : htons(port)); + err = ap_proxy_host2addr(proxyhost ? proxyhost : host, &server_hp); + + if (err != NULL) + return ap_proxyerror(r, err); /* give up */ + + sock = ap_psocket(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy: error creating socket"); + return SERVER_ERROR; + } + +#ifndef WIN32 + if (sock >= FD_SETSIZE) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL, + "proxy_connect_handler: filedescriptor (%u) " + "larger than FD_SETSIZE (%u) " + "found, you probably need to rebuild Apache with a " + "larger FD_SETSIZE", sock, FD_SETSIZE); + ap_pclosesocket(r->pool, sock); + return SERVER_ERROR; + } +#endif + + j = 0; + while (server_hp.h_addr_list[j] != NULL) { + memcpy(&server.sin_addr, server_hp.h_addr_list[j], + sizeof(struct in_addr)); + i = ap_proxy_doconnect(sock, &server, r); + if (i == 0) + break; + j++; + } + if (i == -1) { + ap_pclosesocket(r->pool, sock); + return ap_proxyerror(r, "Could not connect to remote machine"); + } + + /* If we are connecting through a remote proxy, we need to pass + * the CONNECT request on to it. + */ + if (proxyport) { + /* FIXME: We should not be calling write() directly, but we currently + * have no alternative. Error checking ignored. Also, we force + * a HTTP/1.0 request to keep things simple. + */ + Explain0("Sending the CONNECT request to the remote proxy"); + ap_snprintf(buffer, sizeof(buffer), "CONNECT %s HTTP/1.0" CRLF, + r->uri); + write(sock, buffer, strlen(buffer)); + ap_snprintf(buffer, sizeof(buffer), + "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); + write(sock, buffer, strlen(buffer)); + } + else { + Explain0("Returning 200 OK Status"); + ap_rvputs(r, "HTTP/1.0 200 Connection established" CRLF, NULL); + ap_rvputs(r, "Proxy-agent: ", ap_get_server_version(), CRLF CRLF, NULL); + ap_bflush(r->connection->client); + } + + while (1) { /* Infinite loop until error (one side closes the connection) */ + FD_ZERO(&fds); + FD_SET(sock, &fds); + FD_SET(r->connection->client->fd, &fds); + + Explain0("Going to sleep (select)"); + i = ap_select((r->connection->client->fd > sock ? + r->connection->client->fd + 1 : + sock + 1), &fds, NULL, NULL, NULL); + Explain1("Woke from select(), i=%d", i); + + if (i) { + if (FD_ISSET(sock, &fds)) { + Explain0("sock was set"); + if ((nbytes = read(sock, buffer, HUGE_STRING_LEN)) != 0) { + if (nbytes == -1) + break; + if (write(r->connection->client->fd, buffer, nbytes) == EOF) + break; + Explain1("Wrote %d bytes to client", nbytes); + } + else + break; + } + else if (FD_ISSET(r->connection->client->fd, &fds)) { + Explain0("client->fd was set"); + if ((nbytes = read(r->connection->client->fd, buffer, + HUGE_STRING_LEN)) != 0) { + if (nbytes == -1) + break; + if (write(sock, buffer, nbytes) == EOF) + break; + Explain1("Wrote %d bytes to server", nbytes); + } + else + break; + } + else + break; /* Must be done waiting */ + } + else + break; + } + + ap_pclosesocket(r->pool, sock); + + return OK; +} diff --git a/APACHE_1_3b7/src/modules/proxy/proxy_ftp.c b/APACHE_1_3b7/src/modules/proxy/proxy_ftp.c new file mode 100644 index 0000000000..1eeda6ca23 --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/proxy_ftp.c @@ -0,0 +1,1135 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 . + * + */ + +/* FTP routines for Apache proxy */ + +#include "mod_proxy.h" +#include "http_main.h" + +DEF_Explain + +/* + * Decodes a '%' escaped string, and returns the number of characters + */ +static int decodeenc(char *x) +{ + int i, j, ch; + + if (x[0] == '\0') + return 0; /* special case for no characters */ + for (i = 0, j = 0; x[i] != '\0'; i++, j++) { +/* decode it if not already done */ + ch = x[i]; + if (ch == '%' && isxdigit(x[i + 1]) && isxdigit(x[i + 2])) { + ch = ap_proxy_hex2c(&x[i + 1]); + i += 2; + } + x[j] = ch; + } + x[j] = '\0'; + return j; +} + +/* + * checks an encoded ftp string for bad characters, namely, CR, LF or + * non-ascii character + */ +static int ftp_check_string(const char *x) +{ + int i, ch; + + for (i = 0; x[i] != '\0'; i++) { + ch = x[i]; + if (ch == '%' && isxdigit(x[i + 1]) && isxdigit(x[i + 2])) { + ch = ap_proxy_hex2c(&x[i + 1]); + i += 2; + } +#ifndef CHARSET_EBCDIC + if (ch == '\015' || ch == '\012' || (ch & 0x80)) +#else /*CHARSET_EBCDIC*/ + if (ch == '\r' || ch == '\n' || (os_toascii[ch] & 0x80)) +#endif /*CHARSET_EBCDIC*/ + return 0; + } + return 1; +} + +/* + * Canonicalise ftp URLs. + */ +int ap_proxy_ftp_canon(request_rec *r, char *url) +{ + char *user, *password, *host, *path, *parms, *strp, sport[7]; + pool *p = r->pool; + const char *err; + int port; + + port = DEFAULT_FTP_PORT; + err = ap_proxy_canon_netloc(p, &url, &user, &password, &host, &port); + if (err) + return HTTP_BAD_REQUEST; + if (user != NULL && !ftp_check_string(user)) + return HTTP_BAD_REQUEST; + if (password != NULL && !ftp_check_string(password)) + return HTTP_BAD_REQUEST; + +/* now parse path/parameters args, according to rfc1738 */ +/* N.B. if this isn't a true proxy request, then the URL path + * (but not query args) has already been decoded. + * This gives rise to the problem of a ; being decoded into the + * path. + */ + strp = strchr(url, ';'); + if (strp != NULL) { + *(strp++) = '\0'; + parms = ap_proxy_canonenc(p, strp, strlen(strp), enc_parm, r->proxyreq); + if (parms == NULL) + return HTTP_BAD_REQUEST; + } + else + parms = ""; + + path = ap_proxy_canonenc(p, url, strlen(url), enc_path, r->proxyreq); + if (path == NULL) + return HTTP_BAD_REQUEST; + if (!ftp_check_string(path)) + return HTTP_BAD_REQUEST; + + if (!r->proxyreq && r->args != NULL) { + if (strp != NULL) { + strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_parm, 1); + if (strp == NULL) + return HTTP_BAD_REQUEST; + parms = ap_pstrcat(p, parms, "?", strp, NULL); + } + else { + strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_fpath, 1); + if (strp == NULL) + return HTTP_BAD_REQUEST; + path = ap_pstrcat(p, path, "?", strp, NULL); + } + r->args = NULL; + } + +/* now, rebuild URL */ + + if (port != DEFAULT_FTP_PORT) + ap_snprintf(sport, sizeof(sport), ":%d", port); + else + sport[0] = '\0'; + + r->filename = ap_pstrcat(p, "proxy:ftp://", (user != NULL) ? user : "", + (password != NULL) ? ":" : "", + (password != NULL) ? password : "", + (user != NULL) ? "@" : "", host, sport, "/", path, + (parms[0] != '\0') ? ";" : "", parms, NULL); + + return OK; +} + +/* + * Returns the ftp status code; + * or -1 on I/O error, 0 on data error + */ +static int ftp_getrc(BUFF *f) +{ + int len, status; + char linebuff[100], buff[5]; + + len = ap_bgets(linebuff, 100, f); + if (len == -1) + return -1; +/* check format */ + if (len < 5 || !isdigit(linebuff[0]) || !isdigit(linebuff[1]) || + !isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) + status = 0; + else + status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0'; + + if (linebuff[len - 1] != '\n') { + (void)ap_bskiplf(f); + } + +/* skip continuation lines */ + if (linebuff[3] == '-') { + memcpy(buff, linebuff, 3); + buff[3] = ' '; + do { + len = ap_bgets(linebuff, 100, f); + if (len == -1) + return -1; + if (linebuff[len - 1] != '\n') { + (void)ap_bskiplf(f); + } + } while (memcmp(linebuff, buff, 4) != 0); + } + + return status; +} + +/* + * Like ftp_getrc but returns both the ftp status code and + * remembers the response message in the supplied buffer + */ +static int ftp_getrc_msg(BUFF *f, char *msgbuf, int msglen) +{ + int len, status; + char linebuff[100], buff[5]; + char *mb = msgbuf; + int ml = msglen; + + len = ap_bgets(linebuff, 100, f); + if (len == -1) + return -1; + if (len < 5 || !isdigit(linebuff[0]) || !isdigit(linebuff[1]) || + !isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) + status = 0; + else + status = 100 * linebuff[0] + 10 * linebuff[1] + linebuff[2] - 111 * '0'; + + mb = ap_cpystrn(mb, linebuff+4, len-4 < ml ? len-4 : ml); + + if (linebuff[len - 1] != '\n') + (void)ap_bskiplf(f); + + if (linebuff[3] == '-') { + memcpy(buff, linebuff, 3); + buff[3] = ' '; + do { + len = ap_bgets(linebuff, 100, f); + if (len == -1) + return -1; + if (linebuff[len - 1] != '\n') { + (void)ap_bskiplf(f); + } + mb = ap_cpystrn(mb, linebuff+4, len-4 < ml ? len-4 : ml); + } while (memcmp(linebuff, buff, 4) != 0); + } + return status; +} + +static long int send_dir(BUFF *f, request_rec *r, BUFF *f2, struct cache_req *c, char *url) +{ + char buf[IOBUFSIZE]; + char buf2[IOBUFSIZE]; + char *filename; + char *tempurl; + int searchidx = 0; + char *searchptr = NULL; + int firstfile = 1; + char urlptr[HUGE_STRING_LEN]; + unsigned long total_bytes_sent = 0; + register int n, o, w; + int hostlen; + conn_rec *con = r->connection; + char *dir, *path, *reldir, *site, *psite; + const char *sig; + + tempurl = ap_pstrdup(r->pool, url); + + (void)decodeenc(tempurl); + + /* Determine length of "scheme://site" prefix */ + for (hostlen=0; tempurl[hostlen]!='/'; ++hostlen) + continue; + if (tempurl[hostlen] == '/' && tempurl[hostlen+1] == '/') { + for (hostlen+=2; tempurl[hostlen]!='/' && tempurl[hostlen]!='?'; ++hostlen) + continue; + } else { + hostlen = 0; + } + + /* Save "scheme://site" prefix */ + site = psite = ap_pstrndup(r->pool, tempurl, hostlen); + + if ((n = strcspn(tempurl, "@")) != strlen(tempurl) && n < hostlen) { /* hide user/passwd */ + memmove(tempurl + (n - 5), tempurl, 6); + tempurl += n - 5; /* leave room for ftp:// */ + hostlen -= (n-5); + + /* Save "scheme://site" prefix without user/password */ + site = ap_pstrndup(r->pool, tempurl, hostlen); + } + + /* Copy path, strip (all except the last) trailing slashes */ + path = dir = ap_pstrcat(r->pool, tempurl+hostlen, "/", NULL); + while ((n = strlen(path)) > 1 && path[n-1] == '/' && path[n-2] == '/') + path[n-1] = '\0'; + + /* print "ftp://host/" */ + ap_snprintf(buf, sizeof(buf), "\n" + "%s\n" + "\n" + "

    Directory of " + "%s/", + tempurl, psite, path, site); + ap_bputs(buf, con->client); + if (f2 != NULL) + ap_bputs(buf, f2); + total_bytes_sent += strlen(buf); + + while ((dir = strchr(dir+1, '/')) != NULL) + { + *dir = '\0'; + if ((reldir = strrchr(path+1, '/'))==NULL) + reldir = path+1; + else + ++reldir; + /* print "path/" component */ + ap_snprintf(buf, sizeof(buf), "%s/", path+1, reldir); + ap_bputs(buf, con->client); + if (f2 != NULL) + ap_bputs(buf, f2); + total_bytes_sent += strlen(buf); + *dir = '/'; + } + ap_snprintf(buf, sizeof(buf), "

    \n
    ");
    +    ap_bputs(buf, con->client);
    +    if (f2 != NULL)
    +	    ap_bputs(buf, f2);
    +    total_bytes_sent += strlen(buf);
    +
    +    for (hostlen=0; url[hostlen]!='/'; ++hostlen)
    +	continue;
    +    if (url[hostlen] == '/' && url[hostlen+1] == '/') {
    +	for (hostlen+=2; url[hostlen]!='/' && url[hostlen]!='?'; ++hostlen)
    +	    continue;
    +    } else
    +	hostlen = 0;
    +
    +    while (!con->aborted) {
    +	n = ap_bgets(buf, IOBUFSIZE, f);
    +	if (n == -1) {		/* input error */
    +	    if (f2 != NULL)
    +		f2 = ap_proxy_cache_error(c);
    +	    break;
    +	}
    +	if (n == 0)
    +	    break;		/* EOF */
    +	if (buf[0] == 'l' && (filename=strstr(buf, " -> ")) != NULL) {
    +	    char *link_ptr = filename;
    +
    +	    do
    +		filename--;
    +	    while (filename[0] != ' ');
    +	    *(filename++) = 0;
    +	    *(link_ptr++) = 0;
    +	    if ((n = strlen(link_ptr)) > 1 && link_ptr[n - 1] == '\n')
    +	      link_ptr[n - 1] = '\0';
    +	    ap_snprintf(urlptr, sizeof(urlptr), "%s%s%s", url+hostlen, (url[strlen(url) - 1] == '/' ? "" : "/"), filename);
    +	    ap_snprintf(buf2, sizeof(buf2), "%s %s %s\n", buf, filename, filename, link_ptr);
    +	    ap_cpystrn(buf, buf2, sizeof(buf));
    +	    n = strlen(buf);
    +	}
    +	else if (buf[0] == 'd' || buf[0] == '-' || buf[0] == 'l' || isdigit(buf[0])) {
    +	    if (isdigit(buf[0])) {	/* handle DOS dir */
    +		searchptr = strchr(buf, '<');
    +		if (searchptr != NULL)
    +		    *searchptr = '[';
    +		searchptr = strchr(buf, '>');
    +		if (searchptr != NULL)
    +		    *searchptr = ']';
    +	    }
    +
    +	    filename = strrchr(buf, ' ');
    +	    *(filename++) = 0;
    +	    filename[strlen(filename) - 1] = 0;
    +
    +	    /* handle filenames with spaces in 'em */
    +	    if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) {
    +		firstfile = 0;
    +		searchidx = filename - buf;
    +	    }
    +	    else if (searchidx != 0 && buf[searchidx] != 0) {
    +		*(--filename) = ' ';
    +		buf[searchidx - 1] = 0;
    +		filename = &buf[searchidx];
    +	    }
    +
    +	    /* Special handling for '.' and '..' */
    +	    if (!strcmp(filename, ".") || !strcmp(filename, "..") || buf[0] == 'd') {
    +		ap_snprintf(buf2, sizeof(buf2), "%s %s\n",
    +		    buf, filename, filename);
    +	    }
    +	    else {
    +		ap_snprintf(buf2, sizeof(buf2), "%s %s\n", buf, filename, filename);
    +	    }
    +	    ap_cpystrn(buf, buf2, sizeof(buf));
    +	    n = strlen(buf);
    +	}
    +
    +	o = 0;
    +	total_bytes_sent += n;
    +
    +	if (f2 != NULL)
    +	    if (ap_bwrite(f2, buf, n) != n)
    +		f2 = ap_proxy_cache_error(c);
    +
    +	while (n && !r->connection->aborted) {
    +	    w = ap_bwrite(con->client, &buf[o], n);
    +	    if (w <= 0)
    +		break;
    +	    ap_reset_timeout(r);	/* reset timeout after successfule write */
    +	    n -= w;
    +	    o += w;
    +	}
    +    }
    +    site = "

    \n"; + ap_bputs(site, con->client); + if (f2 != NULL) + ap_bputs(site, f2); + total_bytes_sent += strlen(site); + + sig = ap_psignature("", r); + ap_bputs(sig, con->client); + if (f2 != NULL) + ap_bputs(sig, f2); + total_bytes_sent += strlen(sig); + + site = "\n"; + ap_bputs(site, con->client); + if (f2 != NULL) + ap_bputs(site, f2); + total_bytes_sent += strlen(site); + ap_bflush(con->client); + + return total_bytes_sent; +} + +/* + * Handles direct access of ftp:// URLs + * Original (Non-PASV) version from + * Troy Morrison + * PASV added by Chuck + */ +int ap_proxy_ftp_handler(request_rec *r, struct cache_req *c, char *url) +{ + char *host, *path, *strp, *user, *password, *parms; + const char *err; + int port, userlen, i, j, len, sock, dsock, rc, nocache; + int passlen = 0; + int csd = 0; + struct sockaddr_in server; + struct hostent server_hp; + struct hdr_entry *hdr; + struct in_addr destaddr; + array_header *resp_hdrs; + BUFF *f, *cache; + BUFF *data = NULL; + pool *p = r->pool; + int one = 1; + const long int zero = 0L; + NET_SIZE_T clen; + + void *sconf = r->server->module_config; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; + struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts; + +/* stuff for PASV mode */ + unsigned int presult, h0, h1, h2, h3, p0, p1; + unsigned int paddr; + unsigned short pport; + struct sockaddr_in data_addr; + int pasvmode = 0; + char pasv[64]; + char *pstr; + +/* stuff for responses */ + char *resp; + int resplen; + char *size = NULL; + +/* we only support GET and HEAD */ + + if (r->method_number != M_GET) + return NOT_IMPLEMENTED; + +/* allocate a buffer for the response message */ + resplen = MAX_STRING_LEN; + resp = (char *)ap_palloc(r->pool, resplen); + +/* We break the URL into host, port, path-search */ + + host = ap_pstrdup(p, url + 6); + port = DEFAULT_FTP_PORT; + path = strchr(host, '/'); + if (path == NULL) + path = ""; + else + *(path++) = '\0'; + + user = password = NULL; + nocache = 0; + strp = strchr(host, '@'); + if (strp != NULL) { + (*strp++) = '\0'; + user = host; + host = strp; +/* find password */ + strp = strchr(user, ':'); + if (strp != NULL) { + *(strp++) = '\0'; + password = strp; + passlen = decodeenc(password); + } + userlen = decodeenc(user); + nocache = 1; /* don't cache when a username is supplied */ + } + else { + user = "anonymous"; + userlen = 9; + + password = "apache_proxy@"; + passlen = strlen(password); + } + + strp = strchr(host, ':'); + if (strp != NULL) { + *(strp++) = '\0'; + if (isdigit(*strp)) + port = atoi(strp); + } + +/* check if ProxyBlock directive on this host */ + destaddr.s_addr = ap_inet_addr(host); + for (i = 0; i < conf->noproxies->nelts; i++) { + if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL) + || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') + return ap_proxyerror(r, "Connect to remote machine blocked"); + } + + Explain2("FTP: connect to %s:%d", host, port); + + parms = strchr(path, ';'); + if (parms != NULL) + *(parms++) = '\0'; + + memset(&server, 0, sizeof(struct sockaddr_in)); + server.sin_family = AF_INET; + server.sin_port = htons(port); + err = ap_proxy_host2addr(host, &server_hp); + if (err != NULL) + return ap_proxyerror(r, err); /* give up */ + + sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == -1) { + ap_proxy_log_uerror("socket", NULL, "proxy: error creating socket", + r->server); + return SERVER_ERROR; + } + + if (conf->recv_buffer_size) { + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, + (const char *) &conf->recv_buffer_size, sizeof(int)) + == -1) { + ap_proxy_log_uerror("setsockopt", "(SO_RCVBUF)", + "Failed to set ProxyReceiveBufferSize, using default", + r->server); + } + } + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &one, + sizeof(one)) == -1) { +#ifndef _OSD_POSIX /* BS2000 has this option "always on" */ + ap_proxy_log_uerror("setsockopt", NULL, + "proxy: error setting reuseaddr option", r->server); + ap_pclosesocket(p, sock); + return SERVER_ERROR; +#endif /*_OSD_POSIX*/ + } + +#ifdef SINIX_D_RESOLVER_BUG + { + struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list; + + for (; ip_addr->s_addr != 0; ++ip_addr) { + memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr)); + i = ap_proxy_doconnect(sock, &server, r); + if (i == 0) + break; + } + } +#else + j = 0; + while (server_hp.h_addr_list[j] != NULL) { + memcpy(&server.sin_addr, server_hp.h_addr_list[j], + sizeof(struct in_addr)); + i = ap_proxy_doconnect(sock, &server, r); + if (i == 0) + break; + j++; + } +#endif + if (i == -1) { + ap_pclosesocket(p, sock); + return ap_proxyerror(r, "Could not connect to remote machine"); + } + + f = ap_bcreate(p, B_RDWR | B_SOCKET); + ap_bpushfd(f, sock, sock); +/* shouldn't we implement telnet control options here? */ + +#ifdef CHARSET_EBCDIC + ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 1); +#endif /*CHARSET_EBCDIC*/ + +/* possible results: 120, 220, 421 */ + ap_hard_timeout("proxy ftp", r); + i = ftp_getrc(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Error reading from remote server"); + } + if (i != 220) { + ap_kill_timeout(r); + return BAD_GATEWAY; + } + + Explain0("FTP: connected."); + + ap_bputs("USER ", f); + ap_bwrite(f, user, userlen); + ap_bputs(CRLF, f); + ap_bflush(f); /* capture any errors */ + Explain1("FTP: USER %s", user); + +/* possible results; 230, 331, 332, 421, 500, 501, 530 */ +/* states: 1 - error, 2 - success; 3 - send password, 4,5 fail */ + i = ftp_getrc(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Error sending to remote server"); + } + if (i == 530) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Not logged in"); + } + if (i != 230 && i != 331) { + ap_kill_timeout(r); + return BAD_GATEWAY; + } + + if (i == 331) { /* send password */ + if (password == NULL) + return FORBIDDEN; + ap_bputs("PASS ", f); + ap_bwrite(f, password, passlen); + ap_bputs(CRLF, f); + ap_bflush(f); + Explain1("FTP: PASS %s", password); +/* possible results 202, 230, 332, 421, 500, 501, 503, 530 */ + i = ftp_getrc(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Error sending to remote server"); + } + if (i == 332) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Need account for login"); + } + if (i == 530) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Not logged in"); + } + if (i != 230 && i != 202) { + ap_kill_timeout(r); + return BAD_GATEWAY; + } + } + +/* set the directory */ +/* this is what we must do if we don't know the OS type of the remote + * machine + */ + for (;;) { + strp = strchr(path, '/'); + if (strp == NULL) + break; + *strp = '\0'; + + len = decodeenc(path); + ap_bputs("CWD ", f); + ap_bwrite(f, path, len); + ap_bputs(CRLF, f); + ap_bflush(f); + Explain1("FTP: CWD %s", path); +/* responses: 250, 421, 500, 501, 502, 530, 550 */ +/* 1,3 error, 2 success, 4,5 failure */ + i = ftp_getrc(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Error sending to remote server"); + } + if (i == 550) { + ap_kill_timeout(r); + return NOT_FOUND; + } + if (i != 250) { + ap_kill_timeout(r); + return BAD_GATEWAY; + } + + path = strp + 1; + } + + if (parms != NULL && strncmp(parms, "type=", 5) == 0) { + parms += 5; + if ((parms[0] != 'd' && parms[0] != 'a' && parms[0] != 'i') || + parms[1] != '\0') + parms = ""; + } + else + parms = ""; + + /* changed to make binary transfers the default */ + + if (parms[0] != 'a') { + /* set type to image */ + /* TM - Added \015\012 to the end of TYPE I, otherwise it hangs the + connection */ + ap_bputs("TYPE I" CRLF, f); + ap_bflush(f); + Explain0("FTP: TYPE I"); +/* responses: 200, 421, 500, 501, 504, 530 */ + i = ftp_getrc(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Error sending to remote server"); + } + if (i != 200 && i != 504) { + ap_kill_timeout(r); + return BAD_GATEWAY; + } +/* Allow not implemented */ + if (i == 504) + parms[0] = '\0'; + } + +/* try to set up PASV data connection first */ + dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (dsock == -1) { + ap_proxy_log_uerror("socket", NULL, "proxy: error creating PASV socket", + r->server); + ap_bclose(f); + ap_kill_timeout(r); + return SERVER_ERROR; + } + + if (conf->recv_buffer_size) { + if (setsockopt(dsock, SOL_SOCKET, SO_RCVBUF, + (const char *) &conf->recv_buffer_size, sizeof(int)) == -1) { + ap_proxy_log_uerror("setsockopt", "(SO_RCVBUF)", + "Failed to set ProxyReceiveBufferSize, using default", r->server); + } + } + + ap_bputs("PASV" CRLF, f); + ap_bflush(f); + Explain0("FTP: PASV command issued"); +/* possible results: 227, 421, 500, 501, 502, 530 */ + i = ap_bgets(pasv, sizeof(pasv), f); + + if (i == -1) { + ap_proxy_log_uerror("command", NULL, "PASV: control connection is toast", + r->server); + ap_pclosesocket(p, dsock); + ap_bclose(f); + ap_kill_timeout(r); + return SERVER_ERROR; + } + else { + pasv[i - 1] = '\0'; + pstr = strtok(pasv, " "); /* separate result code */ + if (pstr != NULL) { + presult = atoi(pstr); + if (*(pstr + strlen(pstr) + 1) == '=') + pstr += strlen(pstr) + 2; + else + { + pstr = strtok(NULL, "("); /* separate address & port params */ + if (pstr != NULL) + pstr = strtok(NULL, ")"); + } + } + else + presult = atoi(pasv); + + Explain1("FTP: returned status %d", presult); + + if (presult == 227 && pstr != NULL && (sscanf(pstr, + "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) { + /* pardon the parens, but it makes gcc happy */ + paddr = (((((h3 << 8) + h2) << 8) + h1) << 8) + h0; + pport = (p1 << 8) + p0; + Explain5("FTP: contacting host %d.%d.%d.%d:%d", + h3, h2, h1, h0, pport); + data_addr.sin_family = AF_INET; + data_addr.sin_addr.s_addr = htonl(paddr); + data_addr.sin_port = htons(pport); + i = ap_proxy_doconnect(dsock, &data_addr, r); + + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Could not connect to remote machine"); + } + else { + pasvmode = 1; + } + } + else + ap_pclosesocket(p, dsock); /* and try the regular way */ + } + + if (!pasvmode) { /* set up data connection */ + clen = sizeof(struct sockaddr_in); + if (getsockname(sock, (struct sockaddr *) &server, &clen) < 0) { + ap_proxy_log_uerror("getsockname", NULL, + "proxy: error getting socket address", r->server); + ap_bclose(f); + ap_kill_timeout(r); + return SERVER_ERROR; + } + + dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (dsock == -1) { + ap_proxy_log_uerror("socket", NULL, "proxy: error creating socket", + r->server); + ap_bclose(f); + ap_kill_timeout(r); + return SERVER_ERROR; + } + + if (setsockopt(dsock, SOL_SOCKET, SO_REUSEADDR, (void *) &one, + sizeof(one)) == -1) { +#ifndef _OSD_POSIX /* BS2000 has this option "always on" */ + ap_proxy_log_uerror("setsockopt", NULL, + "proxy: error setting reuseaddr option", r->server); + ap_pclosesocket(p, dsock); + ap_bclose(f); + ap_kill_timeout(r); + return SERVER_ERROR; +#endif /*_OSD_POSIX*/ + } + + if (bind(dsock, (struct sockaddr *) &server, + sizeof(struct sockaddr_in)) == -1) { + char buff[22]; + + ap_snprintf(buff, sizeof(buff), "%s:%d", inet_ntoa(server.sin_addr), server.sin_port); + ap_proxy_log_uerror("bind", buff, + "proxy: error binding to ftp data socket", r->server); + ap_bclose(f); + ap_pclosesocket(p, dsock); + return SERVER_ERROR; + } + listen(dsock, 2); /* only need a short queue */ + } + +/* set request */ + len = decodeenc(path); + + /* TM - if len == 0 then it must be a directory (you can't RETR nothing) */ + + if (len == 0) { + parms = "d"; + } + else { + ap_bputs("SIZE ", f); + ap_bwrite(f, path, len); + ap_bputs(CRLF, f); + ap_bflush(f); + Explain1("FTP: SIZE %s", path); + i = ftp_getrc_msg(f, resp, resplen); + Explain2("FTP: returned status %d with response %s", i, resp); + if (i != 500) { /* Size command not recognized */ + if (i == 550) { /* Not a regular file */ + Explain0("FTP: SIZE shows this is a directory"); + parms = "d"; + ap_bputs("CWD ", f); + ap_bwrite(f, path, len); + ap_bputs(CRLF, f); + ap_bflush(f); + Explain1("FTP: CWD %s", path); + i = ftp_getrc(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Error sending to remote server"); + } + if (i == 550) { + ap_kill_timeout(r); + return NOT_FOUND; + } + if (i != 250) { + ap_kill_timeout(r); + return BAD_GATEWAY; + } + path = ""; + len = 0; + } + else if (i == 213) { /* Size command ok */ + size = resp; + } + } + } + + if (parms[0] == 'd') { + if (len != 0) + ap_bputs("LIST ", f); + else + ap_bputs("LIST -lag", f); + Explain1("FTP: LIST %s", (len == 0 ? "" : path)); + } + else { + ap_bputs("RETR ", f); + Explain1("FTP: RETR %s", path); + } + ap_bwrite(f, path, len); + ap_bputs(CRLF, f); + ap_bflush(f); +/* RETR: 110, 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 530, 550 + NLST: 125, 150, 226, 250, 421, 425, 426, 450, 451, 500, 501, 502, 530 */ + rc = ftp_getrc(f); + Explain1("FTP: returned status %d", rc); + if (rc == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Error sending to remote server"); + } + if (rc == 550) { + Explain0("FTP: RETR failed, trying LIST instead"); + parms = "d"; + ap_bputs("CWD ", f); + ap_bwrite(f, path, len); + ap_bputs(CRLF, f); + ap_bflush(f); + Explain1("FTP: CWD %s", path); + rc = ftp_getrc(f); + Explain1("FTP: returned status %d", rc); + if (rc == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, "Error sending to remote server"); + } + if (rc == 550) { + ap_kill_timeout(r); + return NOT_FOUND; + } + if (rc != 250) { + ap_kill_timeout(r); + return BAD_GATEWAY; + } + + ap_bputs("LIST -lag" CRLF, f); + ap_bflush(f); + Explain0("FTP: LIST -lag"); + rc = ftp_getrc(f); + Explain1("FTP: returned status %d", rc); + if (rc == -1) + return ap_proxyerror(r, "Error sending to remote server"); + } + ap_kill_timeout(r); + if (rc != 125 && rc != 150 && rc != 226 && rc != 250) + return BAD_GATEWAY; + + r->status = 200; + r->status_line = "200 OK"; + + resp_hdrs = ap_make_array(p, 2, sizeof(struct hdr_entry)); + if (parms[0] == 'd') + ap_proxy_add_header(resp_hdrs, "Content-Type", "text/html", HDR_REP); + else { + if (r->content_type != NULL) { + ap_proxy_add_header(resp_hdrs, "Content-Type", r->content_type, + HDR_REP); + Explain1("FTP: Content-Type set to %s", r->content_type); + } + else { + ap_proxy_add_header(resp_hdrs, "Content-Type", "text/plain", HDR_REP); + } + if (parms[0] != 'a' && size != NULL) { + ap_proxy_add_header(resp_hdrs, "Content-Length", size, HDR_REP); + Explain1("FTP: Content-Length set to %s", size); + } + } + +/* check if NoCache directive on this host */ + for (i = 0; i < conf->nocaches->nelts; i++) { + if ((ncent[i].name != NULL && strstr(host, ncent[i].name) != NULL) + || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') + nocache = 1; + } + + i = ap_proxy_cache_update(c, resp_hdrs, 0, nocache); + + if (i != DECLINED) { + ap_pclosesocket(p, dsock); + ap_bclose(f); + return i; + } + cache = c->fp; + + if (!pasvmode) { /* wait for connection */ + ap_hard_timeout("proxy ftp data connect", r); + clen = sizeof(struct sockaddr_in); + do + csd = accept(dsock, (struct sockaddr *) &server, &clen); + while (csd == -1 && errno == EINTR); + if (csd == -1) { + ap_proxy_log_uerror("accept", NULL, + "proxy: failed to accept data connection", r->server); + ap_pclosesocket(p, dsock); + ap_bclose(f); + ap_kill_timeout(r); + ap_proxy_cache_error(c); + return BAD_GATEWAY; + } + ap_note_cleanups_for_socket(p, csd); + data = ap_bcreate(p, B_RDWR | B_SOCKET); + ap_bpushfd(data, csd, -1); + ap_kill_timeout(r); + } + else { + data = ap_bcreate(p, B_RDWR | B_SOCKET); + ap_bpushfd(data, dsock, dsock); + } + +#ifdef CHARSET_EBCDIC +/* bsetflag(data, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);*/ +#endif /*CHARSET_EBCDIC*/ + + ap_hard_timeout("proxy receive", r); +/* send response */ +/* write status line */ + if (!r->assbackwards) + ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); + if (cache != NULL) + if (ap_bvputs(cache, "HTTP/1.0 ", r->status_line, CRLF, + NULL) == -1) + cache = ap_proxy_cache_error(c); + +/* send headers */ + len = resp_hdrs->nelts; + hdr = (struct hdr_entry *) resp_hdrs->elts; + for (i = 0; i < len; i++) { + if (hdr[i].field == NULL || hdr[i].value == NULL || + hdr[i].value[0] == '\0') + continue; + if (!r->assbackwards) + ap_rvputs(r, hdr[i].field, ": ", hdr[i].value, CRLF, NULL); + if (cache != NULL) + if (ap_bvputs(cache, hdr[i].field, ": ", hdr[i].value, CRLF, + NULL) == -1) + cache = ap_proxy_cache_error(c); + } + + if (!r->assbackwards) + ap_rputs(CRLF, r); + if (cache != NULL) + if (ap_bputs(CRLF, cache) == -1) + cache = ap_proxy_cache_error(c); + + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); + r->sent_bodyct = 1; +/* send body */ + if (!r->header_only) { + if (parms[0] != 'd') + ap_proxy_send_fb(data, r, cache, c); + else + send_dir(data, r, cache, c, url); + + if (rc == 125 || rc == 150) + rc = ftp_getrc(f); + if (rc != 226 && rc != 250) + ap_proxy_cache_error(c); + } + else { +/* abort the transfer */ + ap_bputs("ABOR" CRLF, f); + ap_bflush(f); + if (!pasvmode) + ap_bclose(data); + Explain0("FTP: ABOR"); +/* responses: 225, 226, 421, 500, 501, 502 */ + i = ftp_getrc(f); + Explain1("FTP: returned status %d", i); + } + + ap_kill_timeout(r); + ap_proxy_cache_tidy(c); + +/* finish */ + ap_bputs("QUIT" CRLF, f); + ap_bflush(f); + Explain0("FTP: QUIT"); +/* responses: 221, 500 */ + + if (pasvmode) + ap_bclose(data); + ap_bclose(f); + + ap_rflush(r); /* flush before garbage collection */ + + ap_proxy_garbage_coll(r); + + return OK; +} diff --git a/APACHE_1_3b7/src/modules/proxy/proxy_http.c b/APACHE_1_3b7/src/modules/proxy/proxy_http.c new file mode 100644 index 0000000000..241fbdb80f --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/proxy_http.c @@ -0,0 +1,469 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 routines for Apache proxy */ + +#include "mod_proxy.h" +#include "http_log.h" +#include "http_main.h" +#include "http_core.h" +#include "util_date.h" + +/* + * Canonicalise http-like URLs. + * scheme is the scheme for the URL + * url is the URL starting with the first '/' + * def_port is the default port for this scheme. + */ +int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_port) +{ + char *host, *path, *search, sport[7]; + const char *err; + int port; + +/* do syntatic check. + * We break the URL into host, port, path, search + */ + port = def_port; + err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); + if (err) + return HTTP_BAD_REQUEST; + +/* now parse path/search args, according to rfc1738 */ +/* N.B. if this isn't a true proxy request, then the URL _path_ + * has already been decoded. True proxy requests have r->uri + * == r->unparsed_uri, and no others have that property. + */ + if (r->uri == r->unparsed_uri) { + search = strchr(url, '?'); + if (search != NULL) + *(search++) = '\0'; + } + else + search = r->args; + +/* process path */ + path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq); + if (path == NULL) + return HTTP_BAD_REQUEST; + + if (port != def_port) + ap_snprintf(sport, sizeof(sport), ":%d", port); + else + sport[0] = '\0'; + + r->filename = ap_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/", + path, (search) ? "?" : "", (search) ? search : "", NULL); + return OK; +} + +static char *proxy_location_reverse_map(request_rec *r, char *url) +{ + void *sconf; + proxy_server_conf *conf; + struct proxy_alias *ent; + int i, l1, l2; + char *u; + + sconf = r->server->module_config; + conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); + l1 = strlen(url); + ent = (struct proxy_alias *)conf->raliases->elts; + for (i = 0; i < conf->raliases->nelts; i++) { + l2 = strlen(ent[i].real); + if (l1 >= l2 && strncmp(ent[i].real, url, l2) == 0) { + u = ap_pstrcat(r->pool, ent[i].fake, &url[l2], NULL); + return ap_construct_url(r->pool, u, r); + } + } + return url; +} + +/* Clear all connection-based headers from the incoming headers table */ +static void clear_connection(table *headers) +{ + char *name; + char *next = ap_table_get(headers, "Connection"); + + ap_table_unset(headers, "Proxy-Connection"); + if (!next) + return; + + while (*next) { + name = next; + while (*next && !isspace(*next) && (*next != ',')) + ++next; + while (*next && (isspace(*next) || (*next == ','))) { + *next = '\0'; + ++next; + } + ap_table_unset(headers, name); + } + ap_table_unset(headers, "Connection"); +} + +/* + * This handles http:// URLs, and other URLs using a remote proxy over http + * If proxyhost is NULL, then contact the server directly, otherwise + * go via the proxy. + * Note that if a proxy is used, then URLs other than http: can be accessed, + * also, if we have trouble which is clearly specific to the proxy, then + * we return DECLINED so that we can try another proxy. (Or the direct + * route.) + */ +int ap_proxy_http_handler(request_rec *r, struct cache_req *c, char *url, + const char *proxyhost, int proxyport) +{ + char *strp; + const char *err, *desthost; + int i, j, sock, len, backasswards; + array_header *reqhdrs_arr, *resp_hdrs; + table_entry *reqhdrs; + struct sockaddr_in server; + struct in_addr destaddr; + struct hostent server_hp; + BUFF *f, *cache; + struct hdr_entry *hdr; + char buffer[HUGE_STRING_LEN]; + pool *p = r->pool; + const long int zero = 0L; + int destport = 0; + char *destportstr = NULL; + char *urlptr = NULL; + + void *sconf = r->server->module_config; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; + struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts; + int nocache = 0; + + memset(&server, '\0', sizeof(server)); + server.sin_family = AF_INET; + +/* We break the URL into host, port, path-search */ + + urlptr = strstr(url, "://"); + if (urlptr == NULL) + return HTTP_BAD_REQUEST; + urlptr += 3; + destport = DEFAULT_HTTP_PORT; + strp = strchr(urlptr, '/'); + if (strp == NULL) { + desthost = ap_pstrdup(p, urlptr); + urlptr = "/"; + } + else { + char *q = ap_palloc(p, strp - urlptr + 1); + memcpy(q, urlptr, strp - urlptr); + q[strp - urlptr] = '\0'; + urlptr = strp; + desthost = q; + } + + strp = strchr(desthost, ':'); + if (strp != NULL) { + *(strp++) = '\0'; + if (isdigit(*strp)) { + destport = atoi(strp); + destportstr = strp; + } + } + +/* check if ProxyBlock directive on this host */ + destaddr.s_addr = ap_inet_addr(desthost); + for (i = 0; i < conf->noproxies->nelts; i++) { + if ((npent[i].name != NULL && strstr(desthost, npent[i].name) != NULL) + || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') + return ap_proxyerror(r, "Connect to remote machine blocked"); + } + + if (proxyhost != NULL) { + server.sin_port = htons(proxyport); + err = ap_proxy_host2addr(proxyhost, &server_hp); + if (err != NULL) + return DECLINED; /* try another */ + } + else { + server.sin_port = htons(destport); + err = ap_proxy_host2addr(desthost, &server_hp); + if (err != NULL) + return ap_proxyerror(r, err); /* give up */ + } + + sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy: error creating socket"); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (conf->recv_buffer_size) { + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, + (const char *) &conf->recv_buffer_size, sizeof(int)) + == -1) { + ap_proxy_log_uerror("setsockopt", "(SO_RCVBUF)", + "Failed to set ReceiveBufferSize, using default", + r->server); + } + } + +#ifdef SINIX_D_RESOLVER_BUG + { + struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list; + + for (; ip_addr->s_addr != 0; ++ip_addr) { + memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr)); + i = ap_proxy_doconnect(sock, &server, r); + if (i == 0) + break; + } + } +#else + j = 0; + while (server_hp.h_addr_list[j] != NULL) { + memcpy(&server.sin_addr, server_hp.h_addr_list[j], + sizeof(struct in_addr)); + i = ap_proxy_doconnect(sock, &server, r); + if (i == 0) + break; + j++; + } +#endif + if (i == -1) { + if (proxyhost != NULL) + return DECLINED; /* try again another way */ + else + return ap_proxyerror(r, "Could not connect to remote machine"); + } + + clear_connection(r->headers_in); /* Strip connection-based headers */ + + f = ap_bcreate(p, B_RDWR | B_SOCKET); + ap_bpushfd(f, sock, sock); + + ap_hard_timeout("proxy send", r); + ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0" CRLF, + NULL); + ap_bvputs(f, "Host: ", desthost, NULL); + if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) + ap_bvputs(f, ":", destportstr, CRLF, NULL); + else + ap_bputs(CRLF, f); + + reqhdrs_arr = table_elts(r->headers_in); + reqhdrs = (table_entry *) reqhdrs_arr->elts; + for (i = 0; i < reqhdrs_arr->nelts; i++) { + if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL + /* Clear out headers not to send */ + || !strcasecmp(reqhdrs[i].key, "Host") /* Already sent */ + ||!strcasecmp(reqhdrs[i].key, "Proxy-Authorization")) + continue; + ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL); + } + + ap_bputs(CRLF, f); +/* send the request data, if any. N.B. should we trap SIGPIPE ? */ + + if (ap_should_client_block(r)) { + while ((i = ap_get_client_block(r, buffer, HUGE_STRING_LEN)) > 0) + ap_bwrite(f, buffer, i); + } + ap_bflush(f); + ap_kill_timeout(r); + + ap_hard_timeout("proxy receive", r); + + len = ap_bgets(buffer, HUGE_STRING_LEN - 1, f); + if (len == -1 || len == 0) { + ap_bclose(f); + ap_kill_timeout(r); + return ap_proxyerror(r, "Error reading from remote server"); + } + +/* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */ + if (ap_checkmask(buffer, "HTTP/#.# ###*")) { +/* If not an HTTP/1 messsage or if the status line was > 8192 bytes */ + if (buffer[5] != '1' || buffer[len - 1] != '\n') { + ap_bclose(f); + ap_kill_timeout(r); + return BAD_GATEWAY; + } + backasswards = 0; + buffer[--len] = '\0'; + + buffer[12] = '\0'; + r->status = atoi(&buffer[9]); + buffer[12] = ' '; + r->status_line = ap_pstrdup(p, &buffer[9]); + +/* read the headers. */ +/* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */ +/* Also, take care with headers with multiple occurences. */ + + resp_hdrs = ap_proxy_read_headers(p, buffer, HUGE_STRING_LEN, f); + + clear_connection((table *) resp_hdrs); /* Strip Connection hdrs */ + } + else { +/* an http/0.9 response */ + backasswards = 1; + r->status = 200; + r->status_line = "200 OK"; + +/* no headers */ + resp_hdrs = ap_make_array(p, 2, sizeof(struct hdr_entry)); + } + + ap_kill_timeout(r); + +/* + * HTTP/1.0 requires us to accept 3 types of dates, but only generate + * one type + */ + + hdr = (struct hdr_entry *) resp_hdrs->elts; + for (i = 0; i < resp_hdrs->nelts; i++) { + if (hdr[i].value[0] == '\0') + continue; + strp = hdr[i].field; + if (strcasecmp(strp, "Date") == 0 || + strcasecmp(strp, "Last-Modified") == 0 || + strcasecmp(strp, "Expires") == 0) + hdr[i].value = ap_proxy_date_canon(p, hdr[i].value); + if (strcasecmp(strp, "Location") == 0 || + strcasecmp(strp, "URI") == 0) + hdr[i].value = proxy_location_reverse_map(r, hdr[i].value); + } + +/* check if NoCache directive on this host */ + for (i = 0; i < conf->nocaches->nelts; i++) { + if ((ncent[i].name != NULL && strstr(desthost, ncent[i].name) != NULL) + || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') + nocache = 1; + } + + i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache); + if (i != DECLINED) { + ap_bclose(f); + return i; + } + + cache = c->fp; + + ap_hard_timeout("proxy receive", r); + +/* write status line */ + if (!r->assbackwards) + ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); + if (cache != NULL) + if (ap_bvputs(cache, "HTTP/1.0 ", r->status_line, CRLF, NULL) == -1) + cache = ap_proxy_cache_error(c); + +/* send headers */ + for (i = 0; i < resp_hdrs->nelts; i++) { + if (hdr[i].field == NULL || hdr[i].value == NULL || + hdr[i].value[0] == '\0') + continue; + if (!r->assbackwards) { + ap_rvputs(r, hdr[i].field, ": ", hdr[i].value, CRLF, NULL); + ap_table_set(r->headers_out, hdr[i].field, hdr[i].value); + } + if (cache != NULL) + if (ap_bvputs(cache, hdr[i].field, ": ", hdr[i].value, CRLF, + NULL) == -1) + cache = ap_proxy_cache_error(c); + } + + if (!r->assbackwards) + ap_rputs(CRLF, r); + if (cache != NULL) + if (ap_bputs(CRLF, cache) == -1) + cache = ap_proxy_cache_error(c); + + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); + r->sent_bodyct = 1; +/* Is it an HTTP/0.9 respose? If so, send the extra data */ + if (backasswards) { + ap_bwrite(r->connection->client, buffer, len); + if (cache != NULL) + if (ap_bwrite(f, buffer, len) != len) + cache = ap_proxy_cache_error(c); + } + ap_kill_timeout(r); + +#ifdef CHARSET_EBCDIC + /* What we read/write after the header should not be modified + * (i.e., the cache copy is ASCII, not EBCDIC, even for text/html) + */ + ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); + ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); +#endif + +/* send body */ +/* if header only, then cache will be NULL */ +/* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */ + if (!r->header_only) + ap_proxy_send_fb(f, r, cache, c); + + ap_proxy_cache_tidy(c); + + ap_bclose(f); + + ap_proxy_garbage_coll(r); + return OK; +} diff --git a/APACHE_1_3b7/src/modules/proxy/proxy_util.c b/APACHE_1_3b7/src/modules/proxy/proxy_util.c new file mode 100644 index 0000000000..d5fbfe991e --- /dev/null +++ b/APACHE_1_3b7/src/modules/proxy/proxy_util.c @@ -0,0 +1,1228 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 . + * + */ + +/* Utility routines for Apache proxy */ +#include "mod_proxy.h" +#include "http_main.h" +#include "md5.h" +#include "multithread.h" +#include "http_log.h" +#include "util_uri.h" + +static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r); +static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r); +static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r); +static int proxy_match_word(struct dirconn_entry *This, request_rec *r); + +/* already called in the knowledge that the characters are hex digits */ +int ap_proxy_hex2c(const char *x) +{ + int i, ch; + +#ifndef CHARSET_EBCDIC + ch = x[0]; + if (isdigit(ch)) + i = ch - '0'; + else if (isupper(ch)) + i = ch - ('A' - 10); + else + i = ch - ('a' - 10); + i <<= 4; + + ch = x[1]; + if (isdigit(ch)) + i += ch - '0'; + else if (isupper(ch)) + i += ch - ('A' - 10); + else + i += ch - ('a' - 10); + return i; +#else /*CHARSET_EBCDIC*/ + return (1 == sscanf(x, "%2x", &i)) ? os_toebcdic[i&0xFF] : 0; +#endif /*CHARSET_EBCDIC*/ +} + +void ap_proxy_c2hex(int ch, char *x) +{ +#ifndef CHARSET_EBCDIC + int i; + + x[0] = '%'; + i = (ch & 0xF0) >> 4; + if (i >= 10) + x[1] = ('A' - 10) + i; + else + x[1] = '0' + i; + + i = ch & 0x0F; + if (i >= 10) + x[2] = ('A' - 10) + i; + else + x[2] = '0' + i; +#else /*CHARSET_EBCDIC*/ + static const char ntoa[] = { "0123456789ABCDEF" }; + ch &= 0xFF; + x[0] = '%'; + x[1] = ntoa[(os_toascii[ch]>>4)&0x0F]; + x[2] = ntoa[os_toascii[ch]&0x0F]; + x[3] = '\0'; +#endif /*CHARSET_EBCDIC*/ +} + +/* + * canonicalise a URL-encoded string + */ + +/* + * Convert a URL-encoded string to canonical form. + * It decodes characters which need not be encoded, + * and encodes those which must be encoded, and does not touch + * those which must not be touched. + */ +char * + ap_proxy_canonenc(pool *p, const char *x, int len, enum enctype t, int isenc) +{ + int i, j, ch; + char *y; + const char *allowed; /* characters which should not be encoded */ + const char *reserved; /* characters which much not be en/de-coded */ + +/* N.B. in addition to :@&=, this allows ';' in an http path + * and '?' in an ftp path -- this may be revised + * + * Also, it makes a '+' character in a search string reserved, as + * it may be form-encoded. (Although RFC 1738 doesn't allow this - + * it only permits ; / ? : @ = & as reserved chars.) + */ + if (t == enc_path) + allowed = "$-_.+!*'(),;:@&="; + else if (t == enc_search) + allowed = "$-_.!*'(),;:@&="; + else if (t == enc_user) + allowed = "$-_.+!*'(),;@&="; + else if (t == enc_fpath) + allowed = "$-_.+!*'(),?:@&="; + else /* if (t == enc_parm) */ + allowed = "$-_.+!*'(),?/:@&="; + + if (t == enc_path) + reserved = "/"; + else if (t == enc_search) + reserved = "+"; + else + reserved = ""; + + y = ap_palloc(p, 3 * len + 1); + + for (i = 0, j = 0; i < len; i++, j++) { +/* always handle '/' first */ + ch = x[i]; + if (strchr(reserved, ch)) { + y[j] = ch; + continue; + } +/* decode it if not already done */ + if (isenc && ch == '%') { + if (!isxdigit(x[i + 1]) || !isxdigit(x[i + 2])) + return NULL; + ch = ap_proxy_hex2c(&x[i + 1]); + i += 2; + if (ch != 0 && strchr(reserved, ch)) { /* keep it encoded */ + ap_proxy_c2hex(ch, &y[j]); + j += 2; + continue; + } + } +/* recode it, if necessary */ + if (!isalnum(ch) && !strchr(allowed, ch)) { + ap_proxy_c2hex(ch, &y[j]); + j += 2; + } + else + y[j] = ch; + } + y[j] = '\0'; + return y; +} + +/* + * Parses network-location. + * urlp on input the URL; on output the path, after the leading / + * user NULL if no user/password permitted + * password holder for password + * host holder for host + * port port number; only set if one is supplied. + * + * Returns an error string. + */ +char * + ap_proxy_canon_netloc(pool *p, char **const urlp, char **userp, + char **passwordp, char **hostp, int *port) +{ + int i; + char *strp, *host, *url = *urlp; + char *user = NULL, *password = NULL; + + if (url[0] != '/' || url[1] != '/') + return "Malformed URL"; + host = url + 2; + url = strchr(host, '/'); + if (url == NULL) + url = ""; + else + *(url++) = '\0'; /* skip seperating '/' */ + + /* find _last_ '@' since it might occur in user/password part */ + strp = strrchr(host, '@'); + + if (strp != NULL) { + *strp = '\0'; + user = host; + host = strp + 1; + +/* find password */ + strp = strchr(user, ':'); + if (strp != NULL) { + *strp = '\0'; + password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1); + if (password == NULL) + return "Bad %-escape in URL (password)"; + } + + user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1); + if (user == NULL) + return "Bad %-escape in URL (username)"; + } + if (userp != NULL) { + *userp = user; + } + if (passwordp != NULL) { + *passwordp = password; + } + + strp = strrchr(host, ':'); + if (strp != NULL) { + *(strp++) = '\0'; + + for (i = 0; strp[i] != '\0'; i++) + if (!isdigit(strp[i])) + break; + + if (i == 0 || strp[i] != '\0') + return "Bad port number in URL"; + *port = atoi(strp); + if (*port > 65535) + return "Port number in URL > 65535"; + } + ap_str_tolower(host); /* DNS names are case-insensitive */ + if (*host == '\0') + return "Missing host in URL"; +/* check hostname syntax */ + for (i = 0; host[i] != '\0'; i++) + if (!isdigit(host[i]) && host[i] != '.') + break; + /* must be an IP address */ +#ifdef WIN32 + if (host[i] == '\0' && (inet_addr(host) == -1)) +#else + if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1)) +#endif + { + return "Bad IP address in URL"; + } + +/* if (strchr(host,'.') == NULL && domain != NULL) + host = pstrcat(p, host, domain, NULL); + */ + *urlp = url; + *hostp = host; + + return NULL; +} + +static const char * const lwday[7] = +{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; + +/* + * If the date is a valid RFC 850 date or asctime() date, then it + * is converted to the RFC 1123 format, otherwise it is not modified. + * This routine is not very fast at doing conversions, as it uses + * sscanf and sprintf. However, if the date is already correctly + * formatted, then it exits very quickly. + */ +char * + ap_proxy_date_canon(pool *p, char *x) +{ + int wk, mday, year, hour, min, sec, mon; + char *q, month[4], zone[4], week[4]; + + q = strchr(x, ','); + /* check for RFC 850 date */ + if (q != NULL && q - x > 3 && q[1] == ' ') { + *q = '\0'; + for (wk = 0; wk < 7; wk++) + if (strcmp(x, lwday[wk]) == 0) + break; + *q = ','; + if (wk == 7) + return x; /* not a valid date */ + if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' || + q[17] != ':' || strcmp(&q[20], " GMT") != 0) + return x; + if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year, + &hour, &min, &sec, zone) != 7) + return x; + if (year < 70) + year += 2000; + else + year += 1900; + } + else { +/* check for acstime() date */ + if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' || + x[16] != ':' || x[19] != ' ' || x[24] != '\0') + return x; + if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour, + &min, &sec, &year) != 7) + return x; + for (wk = 0; wk < 7; wk++) + if (strcmp(week, ap_day_snames[wk]) == 0) + break; + if (wk == 7) + return x; + } + +/* check date */ + for (mon = 0; mon < 12; mon++) + if (strcmp(month, ap_month_snames[mon]) == 0) + break; + if (mon == 12) + return x; + + if (strlen(x)+1 < 30) + x = ap_palloc(p, 30); + ap_snprintf(x, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[wk], mday, + ap_month_snames[mon], year, hour, min, sec); + return x; +} + +/* + * Reads headers from a buffer and returns an array of headers. + * Returns NULL on file error + */ +array_header * + ap_proxy_read_headers(pool *p, char *buffer, int size, BUFF *f) +{ + int gotcr, len, i, j; + array_header *resp_hdrs; + struct hdr_entry *hdr; + char *strp; + + resp_hdrs = ap_make_array(p, 10, sizeof(struct hdr_entry)); + hdr = NULL; + + gotcr = 1; + for (;;) { + len = ap_bgets(buffer, size, f); + if (len == -1) + return NULL; + if (len == 0) + break; + if (buffer[len - 1] == '\n') { + buffer[--len] = '\0'; + i = 1; + } + else + i = 0; + + if (!gotcr || buffer[0] == ' ' || buffer[0] == '\t') { + /* a continuation header */ + if (hdr == NULL) { + /* error!! */ + if (!i) { + i = ap_bskiplf(f); + if (i == -1) + return NULL; + } + gotcr = 1; + continue; + } + hdr->value = ap_pstrcat(p, hdr->value, buffer, NULL); + } + else if (gotcr && len == 0) + break; + else { + strp = strchr(buffer, ':'); + if (strp == NULL) { + /* error!! */ + if (!gotcr) { + i = ap_bskiplf(f); + if (i == -1) + return NULL; + } + gotcr = 1; + hdr = NULL; + continue; + } + hdr = ap_push_array(resp_hdrs); + *(strp++) = '\0'; + hdr->field = ap_pstrdup(p, buffer); + while (*strp == ' ' || *strp == '\t') + strp++; + hdr->value = ap_pstrdup(p, strp); + gotcr = i; + } + } + + hdr = (struct hdr_entry *) resp_hdrs->elts; + for (i = 0; i < resp_hdrs->nelts; i++) { + strp = hdr[i].value; + j = strlen(strp); + while (j > 0 && (strp[j - 1] == ' ' || strp[j - 1] == '\t')) + j--; + strp[j] = '\0'; + } + + return resp_hdrs; +} + +long int ap_proxy_send_fb(BUFF *f, request_rec *r, BUFF *f2, struct cache_req *c) +{ + char buf[IOBUFSIZE]; + long total_bytes_sent; + register int n, o, w; + conn_rec *con = r->connection; + + total_bytes_sent = 0; + +#ifdef CHARSET_EBCDIC + /* The cache copy is ASCII, not EBCDIC, even for text/html) */ + ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); + if (f2 != NULL) + ap_bsetflag(f2, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); + ap_bsetflag(con->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); +#endif + + /* Since we are reading from one buffer and writing to another, + * it is unsafe to do a soft_timeout here, at least until the proxy + * has its own timeout handler which can set both buffers to EOUT. + */ + ap_hard_timeout("proxy send body", r); + + while (!con->aborted && f != NULL) { + n = ap_bread(f, buf, IOBUFSIZE); + if (n == -1) { /* input error */ + if (f2 != NULL) + f2 = ap_proxy_cache_error(c); + break; + } + if (n == 0) + break; /* EOF */ + o = 0; + total_bytes_sent += n; + + if (f2 != NULL) + if (ap_bwrite(f2, buf, n) != n) + f2 = ap_proxy_cache_error(c); + + while (n && !con->aborted) { + w = ap_bwrite(con->client, &buf[o], n); + if (w <= 0) { + if (f2 != NULL) { + ap_pclosef(c->req->pool, c->fp->fd); + c->fp = NULL; + f2 = NULL; + con->aborted = 1; + unlink(c->tempfile); + } + break; + } + ap_reset_timeout(r); /* reset timeout after successful write */ + n -= w; + o += w; + } + } + if (!con->aborted) + ap_bflush(con->client); + + ap_kill_timeout(r); + return total_bytes_sent; +} + +/* + * Read a header from the array, returning the first entry + */ +struct hdr_entry * + ap_proxy_get_header(array_header *hdrs_arr, const char *name) +{ + struct hdr_entry *hdrs; + int i; + + hdrs = (struct hdr_entry *) hdrs_arr->elts; + for (i = 0; i < hdrs_arr->nelts; i++) + if (hdrs[i].field != NULL && strcasecmp(name, hdrs[i].field) == 0) + return &hdrs[i]; + + return NULL; +} + +/* + * Add to the header reply, either concatenating, or replacing existin + * headers. It stores the pointers provided, so make sure the data + * is not subsequently overwritten + */ +struct hdr_entry * + ap_proxy_add_header(array_header *hdrs_arr, char *field, char *value, + int rep) +{ + int i; + struct hdr_entry *hdrs; + + hdrs = (struct hdr_entry *) hdrs_arr->elts; + if (rep) + for (i = 0; i < hdrs_arr->nelts; i++) + if (hdrs[i].field != NULL && strcasecmp(field, hdrs[i].field) == 0) { + hdrs[i].value = value; + return hdrs; + } + + hdrs = ap_push_array(hdrs_arr); + hdrs->field = field; + hdrs->value = value; + + return hdrs; +} + +void ap_proxy_del_header(array_header *hdrs_arr, const char *field) +{ + int i; + struct hdr_entry *hdrs; + + hdrs = (struct hdr_entry *) hdrs_arr->elts; + + for (i = 0; i < hdrs_arr->nelts; i++) + if (hdrs[i].field != NULL && strcasecmp(field, hdrs[i].field) == 0) + hdrs[i].value = NULL; +} + +/* + * Sends response line and headers. Uses the client fd and the + * headers_out array from the passed request_rec to talk to the client + * and to properly set the headers it sends for things such as logging. + * + * A timeout should be set before calling this routine. + */ +void ap_proxy_send_headers(request_rec *r, const char *respline, array_header *hdrs_arr) +{ + struct hdr_entry *hdrs; + int i; + BUFF *fp = r->connection->client; + + hdrs = (struct hdr_entry *) hdrs_arr->elts; + + ap_bputs(respline, fp); + ap_bputs(CRLF, fp); + for (i = 0; i < hdrs_arr->nelts; i++) { + if (hdrs[i].field == NULL) + continue; + ap_bvputs(fp, hdrs[i].field, ": ", hdrs[i].value, CRLF, NULL); + ap_table_set(r->headers_out, hdrs[i].field, hdrs[i].value); + } + + ap_bputs(CRLF, fp); +} + + +/* + * list is a comma-separated list of case-insensitive tokens, with + * optional whitespace around the tokens. + * The return returns 1 if the token val is found in the list, or 0 + * otherwise. + */ +int ap_proxy_liststr(const char *list, const char *val) +{ + int len, i; + const char *p; + + len = strlen(val); + + while (list != NULL) { + p = strchr(list, ','); + if (p != NULL) { + i = p - list; + do + p++; + while (isspace(*p)); + } + else + i = strlen(list); + + while (i > 0 && isspace(list[i - 1])) + i--; + if (i == len && strncasecmp(list, val, len) == 0) + return 1; + list = p; + } + return 0; +} + +#ifdef WIN32 + +/* + * On NT, the file system is NOT case sensitive. So, a == A + * need to map to smaller set of characters + */ +void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength) +{ + AP_MD5_CTX context; + unsigned char digest[16]; + char tmp[26]; + int i, k, d; + unsigned int x; + static const char enc_table[32] = "abcdefghijklmnopqrstuvwxyz012345"; + + ap_MD5Init(&context); + ap_MD5Update(&context, (const unsigned char *) it, strlen(it)); + ap_MD5Final(digest, &context); + +/* encode 128 bits as 26 characters, using a modified uuencoding */ +/* the encoding is 5 bytes -> 8 characters + * i.e. 128 bits is 3 x 5 bytes + 1 byte -> 3 * 8 characters + 2 characters + */ + for (i = 0, k = 0; i < 15; i += 5) { + x = (digest[i] << 24) | (digest[i + 1] << 16) | (digest[i + 2] << 8) | digest[i + 3]; + tmp[k++] = enc_table[x >> 27]; + tmp[k++] = enc_table[(x >> 22) & 0x1f]; + tmp[k++] = enc_table[(x >> 17) & 0x1f]; + tmp[k++] = enc_table[(x >> 12) & 0x1f]; + tmp[k++] = enc_table[(x >> 7) & 0x1f]; + tmp[k++] = enc_table[(x >> 2) & 0x1f]; + x = ((x & 0x3) << 8) | digest[i + 4]; + tmp[k++] = enc_table[x >> 5]; + tmp[k++] = enc_table[x & 0x1f]; + } +/* one byte left */ + x = digest[15]; + tmp[k++] = enc_table[x >> 3]; /* use up 5 bits */ + tmp[k++] = enc_table[x & 0x7]; + /* now split into directory levels */ + + for (i = k = d = 0; d < ndepth; ++d) { + memcpy(&val[i], &tmp[k], nlength); + k += nlength; + val[i + nlength] = '/'; + i += nlength + 1; + } + memcpy(&val[i], &tmp[k], 26 - k); + val[i + 26 - k] = '\0'; +} + +#else + +void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength) +{ + AP_MD5_CTX context; + unsigned char digest[16]; + char tmp[22]; + int i, k, d; + unsigned int x; +#if defined(AIX) && defined(__ps2__) + /* Believe it or not, AIX 1.x does not allow you to name a file '@', + * so hack around it in the encoding. */ + static const char enc_table[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_%"; +#else + static const char enc_table[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@"; +#endif + + ap_MD5Init(&context); + ap_MD5Update(&context, (const unsigned char *) it, strlen(it)); + ap_MD5Final(digest, &context); + +/* encode 128 bits as 22 characters, using a modified uuencoding */ +/* the encoding is 3 bytes -> 4 characters + * i.e. 128 bits is 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters + */ + for (i = 0, k = 0; i < 15; i += 3) { + x = (digest[i] << 16) | (digest[i + 1] << 8) | digest[i + 2]; + tmp[k++] = enc_table[x >> 18]; + tmp[k++] = enc_table[(x >> 12) & 0x3f]; + tmp[k++] = enc_table[(x >> 6) & 0x3f]; + tmp[k++] = enc_table[x & 0x3f]; + } +/* one byte left */ + x = digest[15]; + tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */ + tmp[k++] = enc_table[(x << 4) & 0x3f]; + /* now split into directory levels */ + + for (i = k = d = 0; d < ndepth; ++d) { + memcpy(&val[i], &tmp[k], nlength); + k += nlength; + val[i + nlength] = '/'; + i += nlength + 1; + } + memcpy(&val[i], &tmp[k], 22 - k); + val[i + 22 - k] = '\0'; +} + +#endif /* WIN32 */ + +/* + * Converts 8 hex digits to a time integer + */ +int ap_proxy_hex2sec(const char *x) +{ + int i, ch; + unsigned int j; + + for (i = 0, j = 0; i < 8; i++) { + ch = x[i]; + j <<= 4; + if (isdigit(ch)) + j |= ch - '0'; + else if (isupper(ch)) + j |= ch - ('A' - 10); + else + j |= ch - ('a' - 10); + } + if (j == 0xffffffff) + return -1; /* so that it works with 8-byte ints */ + else + return j; +} + +/* + * Converts a time integer to 8 hex digits + */ +void ap_proxy_sec2hex(int t, char *y) +{ + int i, ch; + unsigned int j = t; + + for (i = 7; i >= 0; i--) { + ch = j & 0xF; + j >>= 4; + if (ch >= 10) + y[i] = ch + ('A' - 10); + else + y[i] = ch + '0'; + } + y[8] = '\0'; +} + +void ap_proxy_log_uerror(const char *routine, const char *file, const char *err, + server_rec *s) +{ + char *p, *q; + + q = ap_get_time(); + p = strerror(errno); + + if (err != NULL) { + fprintf(s->error_log, "[%s] %s\n", q, err); + if (file != NULL) + fprintf(s->error_log, "- %s: %s: %s\n", routine, file, p); + else + fprintf(s->error_log, "- %s: %s\n", routine, p); + } + else { + if (file != NULL) + fprintf(s->error_log, "[%s] %s: %s: %s\n", q, routine, file, p); + else + fprintf(s->error_log, "[%s] %s: %s\n", q, routine, p); + } + + fflush(s->error_log); +} + +BUFF * + ap_proxy_cache_error(struct cache_req *c) +{ + ap_proxy_log_uerror("write", c->tempfile, "proxy: error writing to cache file", + c->req->server); + ap_pclosef(c->req->pool, c->fp->fd); + c->fp = NULL; + unlink(c->tempfile); + return NULL; +} + +int ap_proxyerror(request_rec *r, const char *message) +{ + r->status = SERVER_ERROR; + r->status_line = "500 Proxy Error"; + r->content_type = "text/html"; + + ap_send_http_header(r); + ap_soft_timeout("proxy error", r); + + ap_rvputs(r, "\n" + "Proxy Error\n" + "

    Proxy Error

    \n" + "The proxy server could not handle this request.\n

    \n" + "Reason: ", message, "\n", + ap_psignature("


    \n", r), + "\n", + NULL); + + ap_kill_timeout(r); + return OK; +} + +/* + * This routine returns its own error message + */ +const char * + ap_proxy_host2addr(const char *host, struct hostent *reqhp) +{ + int i; + struct hostent *hp; + static APACHE_TLS struct hostent hpbuf; + static APACHE_TLS u_long ipaddr; + static APACHE_TLS char *charpbuf[2]; + + for (i = 0; host[i] != '\0'; i++) + if (!isdigit(host[i]) && host[i] != '.') + break; + + if (host[i] != '\0') { + hp = gethostbyname(host); + if (hp == NULL) + return "Host not found"; + } + else { + ipaddr = ap_inet_addr(host); + hp = gethostbyaddr((char *) &ipaddr, sizeof(u_long), AF_INET); + if (hp == NULL) { + memset(&hpbuf, 0, sizeof(hpbuf)); + hpbuf.h_name = 0; + hpbuf.h_addrtype = AF_INET; + hpbuf.h_length = sizeof(u_long); + hpbuf.h_addr_list = charpbuf; + hpbuf.h_addr_list[0] = (char *) &ipaddr; + hpbuf.h_addr_list[1] = 0; + hp = &hpbuf; + } + } + *reqhp = *hp; + return NULL; +} + +static char * + proxy_get_host_of_request(request_rec *r) +{ + char *url, *user = NULL, *password = NULL, *err, *host; + int port = -1; + + if (r->hostname != NULL) + return r->hostname; + + /* Set url to the first char after "scheme://" */ + if ((url = strchr(r->uri, ':')) == NULL + || url[1] != '/' || url[2] != '/') + return NULL; + + url = ap_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */ + + err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port); + + if (err != NULL) + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r->server, err); + + r->hostname = host; + + return host; /* ought to return the port, too */ +} + +/* Return TRUE if addr represents an IP address (or an IP network address) */ +int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p) +{ + const char *addr = This->name; + long ip_addr[4]; + int i, quads; + long bits; + + /* if the address is given with an explicit netmask, use that */ + /* Due to a deficiency in ap_inet_addr(), it is impossible to parse */ + /* "partial" addresses (with less than 4 quads) correctly, i.e. */ + /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */ + /* I therefore have to parse the IP address manually: */ + /*if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0) */ + /* addr and mask were set by proxy_readmask() */ + /*return 1; */ + + /* Parse IP addr manually, optionally allowing */ + /* abbreviated net addresses like 192.168. */ + + /* Iterate over up to 4 (dotted) quads. */ + for (quads = 0; quads < 4 && *addr != '\0'; ++quads) { + char *tmp; + + if (*addr == '/' && quads > 0) /* netmask starts here. */ + break; + + if (!isdigit(*addr)) + return 0; /* no digit at start of quad */ + + ip_addr[quads] = strtol(addr, &tmp, 0); + + if (tmp == addr) /* expected a digit, found something else */ + return 0; + + if (ip_addr[quads] < 0 || ip_addr[quads] > 255) { + /* invalid octet */ + return 0; + } + + addr = tmp; + + if (*addr == '.' && quads != 3) + ++addr; /* after the 4th quad, a dot would be illegal */ + } + + for (This->addr.s_addr = 0, i = 0; i < quads; ++i) + This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i)); + + if (addr[0] == '/' && isdigit(addr[1])) { /* net mask follows: */ + char *tmp; + + ++addr; + + bits = strtol(addr, &tmp, 0); + + if (tmp == addr) /* expected a digit, found something else */ + return 0; + + addr = tmp; + + if (bits < 0 || bits > 32) /* netmask must be between 0 and 32 */ + return 0; + + } + else { + /* Determine (i.e., "guess") netmask by counting the */ + /* number of trailing .0's; reduce #quads appropriately */ + /* (so that 192.168.0.0 is equivalent to 192.168.) */ + while (quads > 0 && ip_addr[quads - 1] == 0) + --quads; + + /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */ + if (quads < 1) + return 0; + + /* every zero-byte counts as 8 zero-bits */ + bits = 8 * quads; + + if (bits != 32) /* no warning for fully qualified IP address */ + fprintf(stderr, "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n", + inet_ntoa(This->addr), bits); + } + + This->mask.s_addr = htonl(INADDR_NONE << (32 - bits)); + + if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) { + fprintf(stderr, "Warning: NetMask and IP-Addr disagree in %s/%ld\n", + inet_ntoa(This->addr), bits); + This->addr.s_addr &= This->mask.s_addr; + fprintf(stderr, " Set to %s/%ld\n", + inet_ntoa(This->addr), bits); + } + + if (*addr == '\0') { + This->matcher = proxy_match_ipaddr; + return 1; + } + else + return (*addr == '\0'); /* okay iff we've parsed the whole string */ +} + +/* Return TRUE if addr represents an IP address (or an IP network address) */ +static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r) +{ + int i; + int ip_addr[4]; + struct in_addr addr; + struct in_addr *ip_list; + char **ip_listptr; + const char *found; + const char *host = proxy_get_host_of_request(r); + + if (host == NULL) /* oops! */ + return 0; + + memset(&addr, '\0', sizeof addr); + memset(ip_addr, '\0', sizeof ip_addr); + + if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) { + for (addr.s_addr = 0, i = 0; i < 4; ++i) + addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i)); + + if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) { +#if DEBUGGING + fprintf(stderr, "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr)); + fprintf(stderr, "%s/", inet_ntoa(This->addr)); + fprintf(stderr, "%s\n", inet_ntoa(This->mask)); +#endif + return 1; + } +#if DEBUGGING + else { + fprintf(stderr, "1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr)); + fprintf(stderr, "%s/", inet_ntoa(This->addr)); + fprintf(stderr, "%s\n", inet_ntoa(This->mask)); + } +#endif + } + else { + struct hostent the_host; + + memset(&the_host, '\0', sizeof the_host); + found = ap_proxy_host2addr(host, &the_host); + + if (found != NULL) { +#if DEBUGGING + fprintf(stderr, "2)IP-NoMatch: hostname=%s msg=%s\n", host, found); +#endif + return 0; + } + + if (the_host.h_name != NULL) + found = the_host.h_name; + else + found = host; + + /* Try to deal with multiple IP addr's for a host */ + for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) { + ip_list = (struct in_addr *) *ip_listptr; + if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) { +#if DEBUGGING + fprintf(stderr, "3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list)); + fprintf(stderr, "%s/", inet_ntoa(This->addr)); + fprintf(stderr, "%s\n", inet_ntoa(This->mask)); +#endif + return 1; + } +#if DEBUGGING + else { + fprintf(stderr, "3)IP-NoMatch: %s[%s] <-> ", found, inet_ntoa(*ip_list)); + fprintf(stderr, "%s/", inet_ntoa(This->addr)); + fprintf(stderr, "%s\n", inet_ntoa(This->mask)); + } +#endif + } + } + + return 0; +} + +/* Return TRUE if addr represents a domain name */ +int ap_proxy_is_domainname(struct dirconn_entry *This, pool *p) +{ + char *addr = This->name; + int i; + + /* Domain name must start with a '.' */ + if (addr[0] != '.') + return 0; + + /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */ + for (i = 0; isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i) + continue; + +#if 0 + if (addr[i] == ':') { + fprintf(stderr, "@@@@ handle optional port in proxy_is_domainname()\n"); + /* @@@@ handle optional port */ + } +#endif + + if (addr[i] != '\0') + return 0; + + /* Strip trailing dots */ + for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i) + addr[i] = '\0'; + + This->matcher = proxy_match_domainname; + return 1; +} + +/* Return TRUE if host "host" is in domain "domain" */ +static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r) +{ + const char *host = proxy_get_host_of_request(r); + int d_len = strlen(This->name), h_len; + + if (host == NULL) /* some error was logged already */ + return 0; + + h_len = strlen(host); + + /* @@@ do this within the setup? */ + /* Ignore trailing dots in domain comparison: */ + while (d_len > 0 && This->name[d_len - 1] == '.') + --d_len; + while (h_len > 0 && host[h_len - 1] == '.') + --h_len; + return h_len > d_len + && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0; +} + +/* Return TRUE if addr represents a host name */ +int ap_proxy_is_hostname(struct dirconn_entry *This, pool *p) +{ + struct hostent host; + char *addr = This->name; + int i; + + /* Host names must not start with a '.' */ + if (addr[0] == '.') + return 0; + + /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */ + for (i = 0; isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i); + +#if 0 + if (addr[i] == ':') { + fprintf(stderr, "@@@@ handle optional port in proxy_is_hostname()\n"); + /* @@@@ handle optional port */ + } +#endif + + if (addr[i] != '\0' || ap_proxy_host2addr(addr, &host) != NULL) + return 0; + + This->hostentry = ap_pduphostent (p, &host); + + /* Strip trailing dots */ + for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i) + addr[i] = '\0'; + + This->matcher = proxy_match_hostname; + return 1; +} + +/* Return TRUE if host "host" is equal to host2 "host2" */ +static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r) +{ + char *host = This->name; + char *host2 = proxy_get_host_of_request(r); + int h2_len; + int h1_len; + + if (host == NULL || host2 == NULL) + return 0; /* oops! */ + + h2_len = strlen(host2); + h1_len = strlen(host); + +#if 0 + unsigned long *ip_list; + + /* Try to deal with multiple IP addr's for a host */ + for (ip_list = *This->hostentry->h_addr_list; *ip_list != 0UL; ++ip_list) + if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?) + return 1; +#endif + + /* Ignore trailing dots in host2 comparison: */ + while (h2_len > 0 && host2[h2_len - 1] == '.') + --h2_len; + while (h1_len > 0 && host[h1_len - 1] == '.') + --h1_len; + return h1_len == h2_len + && strncasecmp(host, host2, h1_len) == 0; +} + +/* Return TRUE if addr is to be matched as a word */ +int ap_proxy_is_word(struct dirconn_entry *This, pool *p) +{ + This->matcher = proxy_match_word; + return 1; +} + +/* Return TRUE if string "str2" occurs literally in "str1" */ +static int proxy_match_word(struct dirconn_entry *This, request_rec *r) +{ + char *host = proxy_get_host_of_request(r); + return host != NULL && strstr(host, This->name) != NULL; +} + +int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r) +{ + int i; + + ap_hard_timeout("proxy connect", r); + do { + i = connect(sock, (struct sockaddr *) addr, sizeof(struct sockaddr_in)); +#ifdef WIN32 + if (i == SOCKET_ERROR) + errno = WSAGetLastError(); +#endif /* WIN32 */ + } while (i == -1 && errno == EINTR); + if (i == -1) { + char details[128]; + + ap_snprintf(details, sizeof(details), "%s port %d", + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); + ap_proxy_log_uerror("connect", details, NULL, r->server); + } + ap_kill_timeout(r); + + return i; +} diff --git a/APACHE_1_3b7/src/modules/standard/.cvsignore b/APACHE_1_3b7/src/modules/standard/.cvsignore new file mode 100644 index 0000000000..8b4c6e3da4 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/.cvsignore @@ -0,0 +1,3 @@ +Makefile +*.lo +*.so diff --git a/APACHE_1_3b7/src/modules/standard/.indent.pro b/APACHE_1_3b7/src/modules/standard/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/.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/APACHE_1_3b7/src/modules/standard/Makefile.tmpl b/APACHE_1_3b7/src/modules/standard/Makefile.tmpl new file mode 100644 index 0000000000..31036c47d6 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/Makefile.tmpl @@ -0,0 +1,183 @@ + +#Dependencies + +$(OBJS) $(OBJS_PIC): Makefile + +# DO NOT REMOVE +mod_access.o: mod_access.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_log.h \ + $(INCDIR)/http_request.h +mod_actions.o: mod_actions.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_request.h \ + $(INCDIR)/http_core.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/http_main.h $(INCDIR)/http_log.h \ + $(INCDIR)/util_script.h +mod_alias.o: mod_alias.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h +mod_asis.o: mod_asis.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/http_log.h $(INCDIR)/util_script.h \ + $(INCDIR)/http_main.h $(INCDIR)/http_request.h +mod_auth.o: mod_auth.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_protocol.h +mod_auth_anon.o: mod_auth_anon.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/http_request.h +mod_auth_db.o: mod_auth_db.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_protocol.h +mod_auth_dbm.o: mod_auth_dbm.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_protocol.h +mod_autoindex.o: mod_autoindex.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_request.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_main.h \ + $(INCDIR)/util_script.h +mod_cern_meta.o: mod_cern_meta.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/util_script.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_request.h +mod_cgi.o: mod_cgi.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_request.h \ + $(INCDIR)/http_core.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/http_main.h $(INCDIR)/http_log.h \ + $(INCDIR)/util_script.h $(INCDIR)/http_conf_globals.h +mod_digest.o: mod_digest.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/util_md5.h $(INCDIR)/md5.h +mod_dir.o: mod_dir.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_request.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_main.h \ + $(INCDIR)/util_script.h +mod_env.o: mod_env.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h +mod_expires.o: mod_expires.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_log.h +mod_headers.o: mod_headers.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h +mod_imap.o: mod_imap.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_request.h \ + $(INCDIR)/http_core.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/http_main.h $(INCDIR)/http_log.h \ + $(INCDIR)/util_script.h +mod_include.o: mod_include.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_request.h \ + $(INCDIR)/http_core.h $(INCDIR)/http_protocol.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_main.h \ + $(INCDIR)/util_script.h +mod_info.o: mod_info.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_log.h $(INCDIR)/http_main.h \ + $(INCDIR)/http_protocol.h $(INCDIR)/util_script.h \ + $(INCDIR)/http_conf_globals.h +mod_log_agent.o: mod_log_agent.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h +mod_log_config.o: mod_log_config.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_log.h +mod_log_referer.o: mod_log_referer.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h +mod_mime.o: mod_mime.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h +mod_mime_magic.o: mod_mime_magic.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_request.h \ + $(INCDIR)/http_core.h $(INCDIR)/http_log.h \ + $(INCDIR)/http_protocol.h +mod_negotiation.o: mod_negotiation.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_request.h \ + $(INCDIR)/http_core.h $(INCDIR)/http_log.h \ + $(INCDIR)/util_script.h +mod_rewrite.o: mod_rewrite.c mod_rewrite.h $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_request.h \ + $(INCDIR)/http_core.h $(INCDIR)/http_log.h \ + $(INCDIR)/http_vhost.h +mod_setenvif.o: mod_setenvif.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_log.h +mod_so.o: mod_so.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_log.h +mod_speling.o: mod_speling.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_core.h $(INCDIR)/http_config.h \ + $(INCDIR)/http_log.h +mod_status.o: mod_status.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ + $(OSDIR)/os.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h \ + $(INCDIR)/http_protocol.h $(INCDIR)/http_main.h \ + $(INCDIR)/util_script.h $(INCDIR)/scoreboard.h \ + $(INCDIR)/http_log.h +mod_unique_id.o: mod_unique_id.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_log.h \ + $(INCDIR)/multithread.h +mod_userdir.o: mod_userdir.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h +mod_usertrack.o: mod_usertrack.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h $(OSDIR)/os.h $(INCDIR)/alloc.h \ + $(INCDIR)/buff.h $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_config.h $(INCDIR)/http_core.h diff --git a/APACHE_1_3b7/src/modules/standard/mod_access.c b/APACHE_1_3b7/src/modules/standard/mod_access.c new file mode 100644 index 0000000000..4326065112 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_access.c @@ -0,0 +1,410 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * Security options etc. + * + * Module derived from code originally written by Rob McCool + * + */ + +#include "httpd.h" +#include "http_core.h" +#include "http_config.h" +#include "http_log.h" +#include "http_request.h" + +enum allowdeny_type { + T_ENV, + T_ALL, + T_IP, + T_HOST, + T_FAIL +}; + +typedef struct { + int limited; + union { + char *from; + struct { + unsigned long net; + unsigned long mask; + } ip; + } x; + enum allowdeny_type type; +} allowdeny; + +/* things in the 'order' array */ +#define DENY_THEN_ALLOW 0 +#define ALLOW_THEN_DENY 1 +#define MUTUAL_FAILURE 2 + +typedef struct { + int order[METHODS]; + array_header *allows; + array_header *denys; +} access_dir_conf; + +module MODULE_VAR_EXPORT access_module; + +static void *create_access_dir_config(pool *p, char *dummy) +{ + access_dir_conf *conf = + (access_dir_conf *) ap_pcalloc(p, sizeof(access_dir_conf)); + int i; + + for (i = 0; i < METHODS; ++i) + conf->order[i] = DENY_THEN_ALLOW; + conf->allows = ap_make_array(p, 1, sizeof(allowdeny)); + conf->denys = ap_make_array(p, 1, sizeof(allowdeny)); + + return (void *) conf; +} + +static const char *order(cmd_parms *cmd, void *dv, char *arg) +{ + access_dir_conf *d = (access_dir_conf *) dv; + int i, o; + + if (!strcasecmp(arg, "allow,deny")) + o = ALLOW_THEN_DENY; + else if (!strcasecmp(arg, "deny,allow")) + o = DENY_THEN_ALLOW; + else if (!strcasecmp(arg, "mutual-failure")) + o = MUTUAL_FAILURE; + else + return "unknown order"; + + for (i = 0; i < METHODS; ++i) + if (cmd->limited & (1 << i)) + d->order[i] = o; + + return NULL; +} + +static int is_ip(const char *host) +{ + while ((*host == '.') || isdigit(*host)) + host++; + return (*host == '\0'); +} + +static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where) +{ + access_dir_conf *d = (access_dir_conf *) dv; + allowdeny *a; + char *s; + + if (strcasecmp(from, "from")) + return "allow and deny must be followed by 'from'"; + + a = (allowdeny *) ap_push_array(cmd->info ? d->allows : d->denys); + a->x.from = where; + a->limited = cmd->limited; + + if (!strncasecmp(where, "env=", 4)) { + a->type = T_ENV; + a->x.from += 4; + + } + else if (!strcasecmp(where, "all")) { + a->type = T_ALL; + + } + else if ((s = strchr(where, '/'))) { + unsigned long mask; + + a->type = T_IP; + /* trample on where, we won't be using it any more */ + *s++ = '\0'; + + if (!is_ip(where) + || (a->x.ip.net = ap_inet_addr(where)) == INADDR_NONE) { + a->type = T_FAIL; + return "syntax error in network portion of network/netmask"; + } + + /* is_ip just tests if it matches [\d.]+ */ + if (!is_ip(s)) { + a->type = T_FAIL; + return "syntax error in mask portion of network/netmask"; + } + /* is it in /a.b.c.d form? */ + if (strchr(s, '.')) { + mask = ap_inet_addr(s); + if (mask == INADDR_NONE) { + a->type = T_FAIL; + return "syntax error in mask portion of network/netmask"; + } + } + else { + /* assume it's in /nnn form */ + mask = atoi(s); + if (mask > 32 || mask <= 0) { + a->type = T_FAIL; + return "invalid mask in network/netmask"; + } + mask = 0xFFFFFFFFUL << (32 - mask); + mask = htonl(mask); + } + a->x.ip.mask = mask; + + } + else if (isdigit(*where) && is_ip(where)) { + /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */ + int shift; + char *t; + int octet; + + a->type = T_IP; + /* parse components */ + s = where; + a->x.ip.net = 0; + a->x.ip.mask = 0; + shift = 24; + while (*s) { + t = s; + if (!isdigit(*t)) { + a->type = T_FAIL; + return "invalid ip address"; + } + while (isdigit(*t)) { + ++t; + } + if (*t == '.') { + *t++ = 0; + } + else if (*t) { + a->type = T_FAIL; + return "invalid ip address"; + } + if (shift < 0) { + return "invalid ip address, only 4 octets allowed"; + } + octet = atoi(s); + if (octet < 0 || octet > 255) { + a->type = T_FAIL; + return "each octet must be between 0 and 255 inclusive"; + } + a->x.ip.net |= octet << shift; + a->x.ip.mask |= 0xFFUL << shift; + s = t; + shift -= 8; + } + a->x.ip.net = ntohl(a->x.ip.net); + a->x.ip.mask = ntohl(a->x.ip.mask); + } + else { + a->type = T_HOST; + } + + return NULL; +} + +static char its_an_allow; + +static const command_rec access_cmds[] = +{ + {"order", order, NULL, OR_LIMIT, TAKE1, + "'allow,deny', 'deny,allow', or 'mutual-failure'"}, + {"allow", allow_cmd, &its_an_allow, OR_LIMIT, ITERATE2, + "'from' followed by hostnames or IP-address wildcards"}, + {"deny", allow_cmd, NULL, OR_LIMIT, ITERATE2, + "'from' followed by hostnames or IP-address wildcards"}, + {NULL} +}; + +static int in_domain(const char *domain, const char *what) +{ + int dl = strlen(domain); + int wl = strlen(what); + + if ((wl - dl) >= 0) { + if (strcasecmp(domain, &what[wl - dl]) != 0) + return 0; + + /* Make sure we matched an *entire* subdomain --- if the user + * said 'allow from good.com', we don't want people from nogood.com + * to be able to get in. + */ + + if (wl == dl) + return 1; /* matched whole thing */ + else + return (domain[0] == '.' || what[wl - dl - 1] == '.'); + } + else + return 0; +} + +static int find_allowdeny(request_rec *r, array_header *a, int method) +{ + allowdeny *ap = (allowdeny *) a->elts; + int mmask = (1 << method); + int i; + int gothost = 0; + const char *remotehost = NULL; + + for (i = 0; i < a->nelts; ++i) { + if (!(mmask & ap[i].limited)) + continue; + + switch (ap[i].type) { + case T_ENV: + if (ap_table_get(r->subprocess_env, ap[i].x.from)) { + return 1; + } + break; + + case T_ALL: + return 1; + + case T_IP: + if (ap[i].x.ip.net != INADDR_NONE + && (r->connection->remote_addr.sin_addr.s_addr + & ap[i].x.ip.mask) == ap[i].x.ip.net) { + return 1; + } + break; + + case T_HOST: + if (!gothost) { + remotehost = ap_get_remote_host(r->connection, r->per_dir_config, + REMOTE_DOUBLE_REV); + + if ((remotehost == NULL) || is_ip(remotehost)) + gothost = 1; + else + gothost = 2; + } + + if ((gothost == 2) && in_domain(ap[i].x.from, remotehost)) + return 1; + break; + + case T_FAIL: + /* do nothing? */ + break; + } + } + + return 0; +} + +static int check_dir_access(request_rec *r) +{ + int method = r->method_number; + access_dir_conf *a = + (access_dir_conf *) + ap_get_module_config(r->per_dir_config, &access_module); + int ret = OK; + + if (a->order[method] == ALLOW_THEN_DENY) { + ret = FORBIDDEN; + if (find_allowdeny(r, a->allows, method)) + ret = OK; + if (find_allowdeny(r, a->denys, method)) + ret = FORBIDDEN; + } + else if (a->order[method] == DENY_THEN_ALLOW) { + if (find_allowdeny(r, a->denys, method)) + ret = FORBIDDEN; + if (find_allowdeny(r, a->allows, method)) + ret = OK; + } + else { + if (find_allowdeny(r, a->allows, method) + && !find_allowdeny(r, a->denys, method)) + ret = OK; + else + ret = FORBIDDEN; + } + + if (ret == FORBIDDEN + && (ap_satisfies(r) != SATISFY_ANY || !ap_some_auth_required(r))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "client %pI denied by server configuration: %s", + &r->connection->remote_addr, r->filename); + } + + return ret; +} + + + +module MODULE_VAR_EXPORT access_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_access_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + access_cmds, + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + check_dir_access, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_actions.c b/APACHE_1_3b7/src/modules/standard/mod_actions.c new file mode 100644 index 0000000000..5655b7a1a0 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_actions.c @@ -0,0 +1,235 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * mod_actions.c: executes scripts based on MIME type + * + * by Alexei Kosut; based on mod_cgi.c, mod_mime.c and mod_includes.c, + * adapted by rst from original NCSA code by Rob McCool + * + * Usage instructions: + * + * Action mime/type /cgi-bin/script + * + * will activate /cgi-bin/script when a file of content type mime/type is + * requested. It sends the URL and file path of the requested document using + * the standard CGI PATH_INFO and PATH_TRANSLATED environment variables. + * + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_main.h" +#include "http_log.h" +#include "util_script.h" + +typedef struct { + table *action_types; /* Added with Action... */ + char *get; /* Added with Script GET */ + char *post; /* Added with Script POST */ + char *put; /* Added with Script PUT */ + char *delete; /* Added with Script DELETE */ +} action_dir_config; + +module action_module; + +static void *create_action_dir_config(pool *p, char *dummy) +{ + action_dir_config *new = + (action_dir_config *) ap_palloc(p, sizeof(action_dir_config)); + + new->action_types = ap_make_table(p, 4); + new->get = NULL; + new->post = NULL; + new->put = NULL; + new->delete = NULL; + + return new; +} + +static void *merge_action_dir_configs(pool *p, void *basev, void *addv) +{ + action_dir_config *base = (action_dir_config *) basev; + action_dir_config *add = (action_dir_config *) addv; + action_dir_config *new = + (action_dir_config *) ap_palloc(p, sizeof(action_dir_config)); + + new->action_types = ap_overlay_tables(p, add->action_types, + base->action_types); + + new->get = add->get ? add->get : base->get; + new->post = add->post ? add->post : base->post; + new->put = add->put ? add->put : base->put; + new->delete = add->delete ? add->delete : base->delete; + + return new; +} + +static const char *add_action(cmd_parms *cmd, action_dir_config * m, char *type, + char *script) +{ + ap_table_setn(m->action_types, type, script); + return NULL; +} + +static const char *set_script(cmd_parms *cmd, action_dir_config * m, char *method, + char *script) +{ + if (!strcmp(method, "GET")) + m->get = script; + else if (!strcmp(method, "POST")) + m->post = script; + else if (!strcmp(method, "PUT")) + m->put = script; + else if (!strcmp(method, "DELETE")) + m->delete = script; + else + return "Unknown method type for Script"; + + return NULL; +} + +static const command_rec action_cmds[] = +{ + {"Action", add_action, NULL, OR_FILEINFO, TAKE2, + "a media type followed by a script name"}, + {"Script", set_script, NULL, ACCESS_CONF | RSRC_CONF, TAKE2, + "a method followed by a script name"}, + {NULL} +}; + +static int action_handler(request_rec *r) +{ + action_dir_config *conf = + (action_dir_config *) ap_get_module_config(r->per_dir_config, &action_module); + char *t, *action = r->handler ? r->handler : r->content_type; + char *script = NULL; + + /* Set allowed stuff */ + if (conf->get) + r->allowed |= (1 << M_GET); + if (conf->post) + r->allowed |= (1 << M_POST); + if (conf->put) + r->allowed |= (1 << M_PUT); + if (conf->delete) + r->allowed |= (1 << M_DELETE); + + /* First, check for the method-handling scripts */ + if ((r->method_number == M_GET) && r->args && conf->get) + script = conf->get; + else if ((r->method_number == M_POST) && conf->post) + script = conf->post; + else if ((r->method_number == M_PUT) && conf->put) + script = conf->put; + else if ((r->method_number == M_DELETE) && conf->delete) + script = conf->delete; + + /* Check for looping, which can happen if the CGI script isn't */ + if (script && r->prev && r->prev->prev) + return DECLINED; + + /* Second, check for actions (which override the method scripts) */ + if ((t = ap_table_get(conf->action_types, + action ? action : ap_default_type(r)))) { + script = t; + if (r->finfo.st_mode == 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "File does not exist: %s", r->filename); + return NOT_FOUND; + } + } + + if (script == NULL) + return DECLINED; + + ap_internal_redirect_handler(ap_pstrcat(r->pool, script, escape_uri(r->pool, + r->uri), r->args ? "?" : NULL, r->args, NULL), r); + return OK; +} + +static const handler_rec action_handlers[] = +{ + {"*/*", action_handler}, + {NULL} +}; + +module action_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_action_dir_config, /* dir config creater */ + merge_action_dir_configs, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + action_cmds, /* command table */ + action_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_alias.c b/APACHE_1_3b7/src/modules/standard/mod_alias.c new file mode 100644 index 0000000000..7f5dbdaaa2 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_alias.c @@ -0,0 +1,418 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_alias.c: Stuff for dealing with directory aliases + * + * Original by Rob McCool, rewritten in succession by David Robinson + * and rst. + * + */ + +#include "httpd.h" +#include "http_config.h" + +typedef struct { + char *real; + char *fake; + char *handler; + regex_t *regexp; + int redir_status; /* 301, 302, 303, 410, etc */ +} alias_entry; + +typedef struct { + array_header *aliases; + array_header *redirects; +} alias_server_conf; + +typedef struct { + array_header *redirects; +} alias_dir_conf; + +module MODULE_VAR_EXPORT alias_module; + +static void *create_alias_config(pool *p, server_rec *s) +{ + alias_server_conf *a = + (alias_server_conf *) ap_pcalloc(p, sizeof(alias_server_conf)); + + a->aliases = ap_make_array(p, 20, sizeof(alias_entry)); + a->redirects = ap_make_array(p, 20, sizeof(alias_entry)); + return a; +} + +static void *create_alias_dir_config(pool *p, char *d) +{ + alias_dir_conf *a = + (alias_dir_conf *) ap_pcalloc(p, sizeof(alias_dir_conf)); + a->redirects = ap_make_array(p, 2, sizeof(alias_entry)); + return a; +} + +static void *merge_alias_config(pool *p, void *basev, void *overridesv) +{ + alias_server_conf *a = + (alias_server_conf *) ap_pcalloc(p, sizeof(alias_server_conf)); + alias_server_conf *base = (alias_server_conf *) basev, *overrides = (alias_server_conf *) overridesv; + + a->aliases = ap_append_arrays(p, overrides->aliases, base->aliases); + a->redirects = ap_append_arrays(p, overrides->redirects, base->redirects); + return a; +} + +static void *merge_alias_dir_config(pool *p, void *basev, void *overridesv) +{ + alias_dir_conf *a = + (alias_dir_conf *) ap_pcalloc(p, sizeof(alias_dir_conf)); + alias_dir_conf *base = (alias_dir_conf *) basev, *overrides = (alias_dir_conf *) overridesv; + a->redirects = ap_append_arrays(p, overrides->redirects, base->redirects); + return a; +} + +static const char *add_alias_internal(cmd_parms *cmd, void *dummy, char *f, char *r, + int use_regex) +{ + server_rec *s = cmd->server; + alias_server_conf *conf = + (alias_server_conf *) ap_get_module_config(s->module_config, &alias_module); + alias_entry *new = ap_push_array(conf->aliases); + + /* XX r can NOT be relative to DocumentRoot here... compat bug. */ + + if (use_regex) { + new->regexp = ap_pregcomp(cmd->pool, f, REG_EXTENDED); + if (new->regexp == NULL) + return "Regular expression could not be compiled."; + } + + new->fake = f; + new->real = r; + new->handler = cmd->info; + + return NULL; +} + +static const char *add_alias(cmd_parms *cmd, void *dummy, char *f, char *r) +{ + return add_alias_internal(cmd, dummy, f, r, 0); +} + +static const char *add_alias_regex(cmd_parms *cmd, void *dummy, char *f, char *r) +{ + return add_alias_internal(cmd, dummy, f, r, 1); +} + +static const char *add_redirect_internal(cmd_parms *cmd, alias_dir_conf * dirconf, + char *arg1, char *arg2, char *arg3, + int use_regex) +{ + alias_entry *new; + server_rec *s = cmd->server; + alias_server_conf *serverconf = + (alias_server_conf *) ap_get_module_config(s->module_config, &alias_module); + int status = (int) (long) cmd->info; + regex_t *r = NULL; + char *f = arg2; + char *url = arg3; + + if (!strcasecmp(arg1, "gone")) + status = HTTP_GONE; + else if (!strcasecmp(arg1, "permanent")) + status = HTTP_MOVED_PERMANENTLY; + else if (!strcasecmp(arg1, "temp")) + status = HTTP_MOVED_TEMPORARILY; + else if (!strcasecmp(arg1, "seeother")) + status = HTTP_SEE_OTHER; + else if (isdigit(*arg1)) + status = atoi(arg1); + else { + f = arg1; + url = arg2; + } + + if (use_regex) { + r = ap_pregcomp(cmd->pool, f, REG_EXTENDED); + if (r == NULL) + return "Regular expression could not be compiled."; + } + + if (is_HTTP_REDIRECT(status)) { + if (!url) + return "URL to redirect to is missing"; + if (!use_regex && !ap_is_url(url)) + return "Redirect to non-URL"; + } + else { + if (url) + return "Redirect URL not valid for this status"; + } + + if (cmd->path) + new = ap_push_array(dirconf->redirects); + else + new = ap_push_array(serverconf->redirects); + + new->fake = f; + new->real = url; + new->regexp = r; + new->redir_status = status; + return NULL; +} + +static const char *add_redirect(cmd_parms *cmd, alias_dir_conf * dirconf, char *arg1, + char *arg2, char *arg3) +{ + return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 0); +} + +static const char *add_redirect_regex(cmd_parms *cmd, alias_dir_conf * dirconf, + char *arg1, char *arg2, char *arg3) +{ + return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 1); +} + +static const command_rec alias_cmds[] = +{ + {"Alias", add_alias, NULL, RSRC_CONF, TAKE2, + "a fakename and a realname"}, + {"ScriptAlias", add_alias, "cgi-script", RSRC_CONF, TAKE2, + "a fakename and a realname"}, + {"Redirect", add_redirect, (void *) HTTP_MOVED_TEMPORARILY, + OR_FILEINFO, TAKE23, + "an optional status, then document to be redirected and destination URL"}, + {"AliasMatch", add_alias_regex, NULL, RSRC_CONF, TAKE2, + "a regular expression and a filename"}, + {"ScriptAliasMatch", add_alias_regex, "cgi-script", RSRC_CONF, TAKE2, + "a regular expression and a filename"}, + {"RedirectMatch", add_redirect_regex, (void *) HTTP_MOVED_TEMPORARILY, + OR_FILEINFO, TAKE23, + "an optional status, then a regular expression and destination URL"}, + {"RedirectTemp", add_redirect, (void *) HTTP_MOVED_TEMPORARILY, + OR_FILEINFO, TAKE2, + "a document to be redirected, then the destination URL"}, + {"RedirectPermanent", add_redirect, (void *) HTTP_MOVED_PERMANENTLY, + OR_FILEINFO, TAKE2, + "a document to be redirected, then the destination URL"}, + {NULL} +}; + +static int alias_matches(const char *uri, const char *alias_fakename) +{ + const char *end_fakename = alias_fakename + strlen(alias_fakename); + const char *aliasp = alias_fakename, *urip = uri; + + while (aliasp < end_fakename) { + if (*aliasp == '/') { + /* any number of '/' in the alias matches any number in + * the supplied URI, but there must be at least one... + */ + if (*urip != '/') + return 0; + + while (*aliasp == '/') + ++aliasp; + while (*urip == '/') + ++urip; + } + else { + /* Other characters are compared literally */ + if (*urip++ != *aliasp++) + return 0; + } + } + + /* Check last alias path component matched all the way */ + + if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/') + return 0; + + /* Return number of characters from URI which matched (may be + * greater than length of alias, since we may have matched + * doubled slashes) + */ + + return urip - uri; +} + +static char *try_alias_list(request_rec *r, array_header *aliases, int doesc, int *status) +{ + alias_entry *entries = (alias_entry *) aliases->elts; + regmatch_t regm[10]; + char *found = NULL; + int i; + + for (i = 0; i < aliases->nelts; ++i) { + alias_entry *p = &entries[i]; + int l; + + if (p->regexp) { + if (!regexec(p->regexp, r->uri, p->regexp->re_nsub + 1, regm, 0)) { + if (p->real) { + found = ap_pregsub(r->pool, p->real, r->uri, + p->regexp->re_nsub + 1, regm); + if (found && doesc) { + found = escape_uri(r->pool, found); + } + } + else { + /* need something non-null */ + found = ap_pstrdup(r->pool, ""); + } + } + } + else { + l = alias_matches(r->uri, p->fake); + + if (l > 0) { + if (doesc) { + char *escurl; + escurl = ap_os_escape_path(r->pool, r->uri + l, 1); + + found = ap_pstrcat(r->pool, p->real, escurl, NULL); + } + else + found = ap_pstrcat(r->pool, p->real, r->uri + l, NULL); + } + } + + if (found) { + if (p->handler) { /* Set handler, and leave a note for mod_cgi */ + r->handler = p->handler; + ap_table_setn(r->notes, "alias-forced-type", r->handler); + } + + *status = p->redir_status; + + return found; + } + + } + + return NULL; +} + +static int translate_alias_redir(request_rec *r) +{ + void *sconf = r->server->module_config; + alias_server_conf *serverconf = + (alias_server_conf *) ap_get_module_config(sconf, &alias_module); + char *ret; + int status; + + if (r->uri[0] != '/' && r->uri[0] != '\0') + return DECLINED; + + if ((ret = try_alias_list(r, serverconf->redirects, 1, &status)) != NULL) { + if (is_HTTP_REDIRECT(status)) { + /* include QUERY_STRING if any */ + if (r->args) { + ret = ap_pstrcat(r->pool, ret, "?", r->args, NULL); + } + ap_table_setn(r->headers_out, "Location", ret); + } + return status; + } + + if ((ret = try_alias_list(r, serverconf->aliases, 0, &status)) != NULL) { + r->filename = ret; + return OK; + } + + return DECLINED; +} + +static int fixup_redir(request_rec *r) +{ + void *dconf = r->per_dir_config; + alias_dir_conf *dirconf = + (alias_dir_conf *) ap_get_module_config(dconf, &alias_module); + char *ret; + int status; + + /* It may have changed since last time, so try again */ + + if ((ret = try_alias_list(r, dirconf->redirects, 1, &status)) != NULL) { + if (is_HTTP_REDIRECT(status)) + ap_table_setn(r->headers_out, "Location", ret); + return status; + } + + return DECLINED; +} + +module MODULE_VAR_EXPORT alias_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_alias_dir_config, /* dir config creater */ + merge_alias_dir_config, /* dir merger --- default is to override */ + create_alias_config, /* server config */ + merge_alias_config, /* merge server configs */ + alias_cmds, /* command table */ + NULL, /* handlers */ + translate_alias_redir, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + fixup_redir, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_asis.c b/APACHE_1_3b7/src/modules/standard/mod_asis.c new file mode 100644 index 0000000000..ae3a179268 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_asis.c @@ -0,0 +1,145 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_protocol.h" +#include "http_log.h" +#include "util_script.h" +#include "http_main.h" +#include "http_request.h" + +static int asis_handler(request_rec *r) +{ + FILE *f; + char *location; + + r->allowed |= (1 << M_GET); + if (r->method_number != M_GET) + return DECLINED; + if (r->finfo.st_mode == 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "File does not exist: %s", r->filename); + return NOT_FOUND; + } + + f = ap_pfopen(r->pool, r->filename, "r"); + + if (f == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "file permissions deny server access: %s", r->filename); + return FORBIDDEN; + } + + scan_script_header(r, f); + location = ap_table_get(r->headers_out, "Location"); + + if (location && location[0] == '/' && + ((r->status == HTTP_OK) || is_HTTP_REDIRECT(r->status))) { + + ap_pfclose(r->pool, f); + + /* Internal redirect -- fake-up a pseudo-request */ + r->status = HTTP_OK; + + /* This redirect needs to be a GET no matter what the original + * method was. + */ + r->method = ap_pstrdup(r->pool, "GET"); + r->method_number = M_GET; + + ap_internal_redirect_handler(location, r); + return OK; + } + + ap_send_http_header(r); + if (!r->header_only) + ap_send_fd(f, r); + + ap_pfclose(r->pool, f); + return OK; +} + +static const handler_rec asis_handlers[] = +{ + {ASIS_MAGIC_TYPE, asis_handler}, + {"send-as-is", asis_handler}, + {NULL} +}; + +module MODULE_VAR_EXPORT asis_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* create per-directory config structure */ + NULL, /* merge per-directory config structures */ + NULL, /* create per-server config structure */ + NULL, /* merge per-server config structures */ + NULL, /* command table */ + asis_handlers, /* handlers */ + NULL, /* translate_handler */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* pre-run fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_auth.c b/APACHE_1_3b7/src/modules/standard/mod_auth.c new file mode 100644 index 0000000000..88d031a13f --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_auth.c @@ -0,0 +1,319 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_auth: authentication + * + * Rob McCool + * + * Adapted to Apache by rst. + * + * dirkx - Added Authoritative control to allow passing on to lower + * modules if and only if the user-id is not known to this + * module. A known user with a faulty or absent password still + * causes an AuthRequired. The default is 'Authoritative', i.e. + * no control is passed along. + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#if defined(HAVE_CRYPT_H) +#include +#endif + +typedef struct auth_config_struct { + char *auth_pwfile; + char *auth_grpfile; + int auth_authoritative; +} auth_config_rec; + +static void *create_auth_dir_config(pool *p, char *d) +{ + auth_config_rec *sec = + (auth_config_rec *) ap_pcalloc(p, sizeof(auth_config_rec)); + sec->auth_pwfile = NULL; /* just to illustrate the default really */ + sec->auth_grpfile = NULL; /* unless you have a broken HP cc */ + sec->auth_authoritative = 1; /* keep the fortress secure by default */ + return sec; +} + +static const char *set_auth_slot(cmd_parms *cmd, void *offset, char *f, char *t) +{ + if (t && strcmp(t, "standard")) + return ap_pstrcat(cmd->pool, "Invalid auth file type: ", t, NULL); + + return ap_set_file_slot(cmd, offset, f); +} + +static const command_rec auth_cmds[] = +{ + {"AuthUserFile", set_auth_slot, + (void *) XtOffsetOf(auth_config_rec, auth_pwfile), OR_AUTHCFG, TAKE12, + "text file containing user IDs and passwords"}, + {"AuthGroupFile", set_auth_slot, + (void *) XtOffsetOf(auth_config_rec, auth_grpfile), OR_AUTHCFG, TAKE12, + "text file containing group names and member user IDs"}, + {"AuthAuthoritative", ap_set_flag_slot, + (void *) XtOffsetOf(auth_config_rec, auth_authoritative), + OR_AUTHCFG, FLAG, + "Set to 'no' to allow access control to be passed along to lower modules if the UserID is not known to this module"}, + {NULL} +}; + +module MODULE_VAR_EXPORT auth_module; + +static char *get_pw(request_rec *r, char *user, char *auth_pwfile) +{ + configfile_t *f; + char l[MAX_STRING_LEN]; + const char *rpw, *w; + + if (!(f = ap_pcfg_openfile(r->pool, auth_pwfile))) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "Could not open password file: %s", auth_pwfile); + return NULL; + } + while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { + if ((l[0] == '#') || (!l[0])) + continue; + rpw = l; + w = ap_getword(r->pool, &rpw, ':'); + + if (!strcmp(user, w)) { + ap_cfg_closefile(f); + return ap_getword(r->pool, &rpw, ':'); + } + } + ap_cfg_closefile(f); + return NULL; +} + +static table *groups_for_user(pool *p, char *user, char *grpfile) +{ + configfile_t *f; + table *grps = ap_make_table(p, 15); + pool *sp; + char l[MAX_STRING_LEN]; + const char *group_name, *ll, *w; + + if (!(f = ap_pcfg_openfile(p, grpfile))) { +/*add? aplog_error(APLOG_MARK, APLOG_ERR, NULL, + "Could not open group file: %s", grpfile);*/ + return NULL; + } + + sp = ap_make_sub_pool(p); + + while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { + if ((l[0] == '#') || (!l[0])) + continue; + ll = l; + ap_clear_pool(sp); + + group_name = ap_getword(sp, &ll, ':'); + + while (ll[0]) { + w = ap_getword_conf(sp, &ll); + if (!strcmp(w, user)) { + ap_table_setn(grps, ap_pstrdup(p, group_name), "in"); + break; + } + } + } + ap_cfg_closefile(f); + ap_destroy_pool(sp); + return grps; +} + +/* These functions return 0 if client is OK, and proper error status + * if not... either AUTH_REQUIRED, if we made a check, and it failed, or + * SERVER_ERROR, if things are so totally confused that we couldn't + * figure out how to tell if the client is authorized or not. + * + * If they return DECLINED, and all other modules also decline, that's + * treated by the server core as a configuration error, logged and + * reported as such. + */ + +/* Determine user ID, and check if it really is that user, for HTTP + * basic authentication... + */ + +static int authenticate_basic_user(request_rec *r) +{ + auth_config_rec *sec = + (auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_module); + conn_rec *c = r->connection; + char *sent_pw, *real_pw; + int res; + + if ((res = ap_get_basic_auth_pw(r, &sent_pw))) + return res; + + if (!sec->auth_pwfile) + return DECLINED; + + if (!(real_pw = get_pw(r, c->user, sec->auth_pwfile))) { + if (!(sec->auth_authoritative)) + return DECLINED; + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "user %s not found: %s", c->user, r->uri); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + /* anyone know where the prototype for crypt is? */ + if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "user %s: password mismatch: %s", c->user, r->uri); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + return OK; +} + +/* Checking ID */ + +static int check_user_access(request_rec *r) +{ + auth_config_rec *sec = + (auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_module); + char *user = r->connection->user; + int m = r->method_number; + int method_restricted = 0; + register int x; + const char *t, *w; + table *grpstatus; + array_header *reqs_arr = ap_requires(r); + require_line *reqs; + + /* BUG FIX: tadc, 11-Nov-1995. If there is no "requires" directive, + * then any user will do. + */ + if (!reqs_arr) + return (OK); + reqs = (require_line *) reqs_arr->elts; + + if (sec->auth_grpfile) + grpstatus = groups_for_user(r->pool, user, sec->auth_grpfile); + else + grpstatus = NULL; + + for (x = 0; x < reqs_arr->nelts; x++) { + + if (!(reqs[x].method_mask & (1 << m))) + continue; + + method_restricted = 1; + + t = reqs[x].requirement; + w = ap_getword(r->pool, &t, ' '); + if (!strcmp(w, "valid-user")) + return OK; + if (!strcmp(w, "user")) { + while (t[0]) { + w = ap_getword_conf(r->pool, &t); + if (!strcmp(user, w)) + return OK; + } + } + else if (!strcmp(w, "group")) { + if (!grpstatus) + return DECLINED; /* DBM group? Something else? */ + + while (t[0]) { + w = ap_getword_conf(r->pool, &t); + if (ap_table_get(grpstatus, w)) + return OK; + } + } + } + + if (!method_restricted) + return OK; + + if (!(sec->auth_authoritative)) + return DECLINED; + + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; +} + +module MODULE_VAR_EXPORT auth_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_auth_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + auth_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + authenticate_basic_user, /* check_user_id */ + check_user_access, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_auth_anon.c b/APACHE_1_3b7/src/modules/standard/mod_auth_anon.c new file mode 100644 index 0000000000..782d534b00 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_auth_anon.c @@ -0,0 +1,315 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 + * IT'S 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_auth: authentication + * + * Rob McCool & Brian Behlendorf. + * + * Adapted to Apache by rst. + * + * Version 0.5 May 1996 + * + * Modified by Dirk.vanGulik@jrc.it to + * + * Adapted to allow anonymous logins, just like with Anon-FTP, when + * one gives the magic user name 'anonymous' and ones email address + * as the password. + * + * Just add the following tokes to your setup: + * + * Anonymous magic-user-id [magic-user-id]... + * + * Anonymous_MustGiveEmail [ on | off ] default = off + * Anonymous_LogEmail [ on | off ] default = on + * Anonymous_VerifyEmail [ on | off ] default = off + * Anonymous_NoUserId [ on | off ] default = off + * Anonymous_Authoritative [ on | off ] default = off + * + * The magic user id is something like 'anonymous', it is NOT case sensitive. + * + * The MustGiveEmail flag can be used to force users to enter something + * in the password field (like an email address). Default is off. + * + * Furthermore the 'NoUserID' flag can be set to allow completely empty + * usernames in as well; this can be is convenient as a single return + * in broken GUIs like W95 is often given by the user. The Default is off. + * + * Dirk.vanGulik@jrc.it; http://ewse.ceo.org; http://me-www.jrc.it/~dirkx + * + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" + +typedef struct auth_anon { + char *password; + struct auth_anon *next; +} auth_anon; + +typedef struct { + + auth_anon *auth_anon_passwords; + int auth_anon_nouserid; + int auth_anon_logemail; + int auth_anon_verifyemail; + int auth_anon_mustemail; + int auth_anon_authoritative; + +} anon_auth_config_rec; + +static void *create_anon_auth_dir_config(pool *p, char *d) +{ + anon_auth_config_rec *sec = (anon_auth_config_rec *) + ap_pcalloc(p, sizeof(anon_auth_config_rec)); + + if (!sec) + return NULL; /* no memory... */ + + /* just to illustrate the defaults really. */ + sec->auth_anon_passwords = NULL; + + sec->auth_anon_nouserid = 0; + sec->auth_anon_logemail = 1; + sec->auth_anon_verifyemail = 0; + sec->auth_anon_mustemail = 1; + sec->auth_anon_authoritative = 0; + return sec; +} + +static const char *anon_set_passwd_flag(cmd_parms *cmd, + anon_auth_config_rec * sec, int arg) +{ + sec->auth_anon_mustemail = arg; + return NULL; +} + +static const char *anon_set_userid_flag(cmd_parms *cmd, + anon_auth_config_rec * sec, int arg) +{ + sec->auth_anon_nouserid = arg; + return NULL; +} +static const char *anon_set_logemail_flag(cmd_parms *cmd, + anon_auth_config_rec * sec, int arg) +{ + sec->auth_anon_logemail = arg; + return NULL; +} +static const char *anon_set_verifyemail_flag(cmd_parms *cmd, + anon_auth_config_rec * sec, int arg) +{ + sec->auth_anon_verifyemail = arg; + return NULL; +} +static const char *anon_set_authoritative_flag(cmd_parms *cmd, + anon_auth_config_rec * sec, int arg) +{ + sec->auth_anon_authoritative = arg; + return NULL; +} + +static const char *anon_set_string_slots(cmd_parms *cmd, + anon_auth_config_rec * sec, char *arg) +{ + + auth_anon *first; + + if (!(*arg)) + return "Anonymous string cannot be empty, use Anonymous_NoUserId instead"; + + /* squeeze in a record */ + first = sec->auth_anon_passwords; + + if ( + (!(sec->auth_anon_passwords = (auth_anon *) ap_palloc(cmd->pool, sizeof(auth_anon)))) || + (!(sec->auth_anon_passwords->password = arg)) + ) + return "Failed to claim memory for an anonymous password..."; + + /* and repair the next */ + sec->auth_anon_passwords->next = first; + + return NULL; +} + +static const command_rec anon_auth_cmds[] = +{ + {"Anonymous", anon_set_string_slots, NULL, OR_AUTHCFG, ITERATE, + "a space-separated list of user IDs"}, + {"Anonymous_MustGiveEmail", anon_set_passwd_flag, NULL, OR_AUTHCFG, FLAG, + "Limited to 'on' or 'off'"}, + {"Anonymous_NoUserId", anon_set_userid_flag, NULL, OR_AUTHCFG, FLAG, + "Limited to 'on' or 'off'"}, +{"Anonymous_VerifyEmail", anon_set_verifyemail_flag, NULL, OR_AUTHCFG, FLAG, + "Limited to 'on' or 'off'"}, + {"Anonymous_LogEmail", anon_set_logemail_flag, NULL, OR_AUTHCFG, FLAG, + "Limited to 'on' or 'off'"}, + {"Anonymous_Authoritative", anon_set_authoritative_flag, NULL, OR_AUTHCFG, FLAG, + "Limited to 'on' or 'off'"}, + + {NULL} +}; + +module MODULE_VAR_EXPORT anon_auth_module; + +static int anon_authenticate_basic_user(request_rec *r) +{ + anon_auth_config_rec *sec = + (anon_auth_config_rec *) ap_get_module_config(r->per_dir_config, + &anon_auth_module); + conn_rec *c = r->connection; + char *send_pw; + int res = DECLINED; + + if ((res = ap_get_basic_auth_pw(r, &send_pw))) + return res; + + /* Ignore if we are not configured */ + if (!sec->auth_anon_passwords) + return DECLINED; + + /* Do we allow an empty userID and/or is it the magic one + */ + + if ((!(c->user[0])) && (sec->auth_anon_nouserid)) { + res = OK; + } + else { + auth_anon *p = sec->auth_anon_passwords; + res = DECLINED; + while ((res == DECLINED) && (p != NULL)) { + if (!(strcasecmp(c->user, p->password))) + res = OK; + p = p->next; + } + } + if ( + /* username is OK */ + (res == OK) + /* password been filled out ? */ + && ((!sec->auth_anon_mustemail) || strlen(send_pw)) + /* does the password look like an email address ? */ + && ((!sec->auth_anon_verifyemail) + || ((strpbrk("@", send_pw) != NULL) + && (strpbrk(".", send_pw) != NULL)))) { + if (sec->auth_anon_logemail && ap_is_initial_req(r)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r->server, + "Anonymous: Passwd <%s> Accepted", + send_pw ? send_pw : "\'none\'"); + } + return OK; + } + else { + if (sec->auth_anon_authoritative) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Anonymous: Authoritative, Passwd <%s> not accepted", + send_pw ? send_pw : "\'none\'"); + return AUTH_REQUIRED; + } + /* Drop out the bottom to return DECLINED */ + } + + return DECLINED; +} + +static int check_anon_access(request_rec *r) +{ +#ifdef NOTYET + conn_rec *c = r->connection; + anon_auth_config_rec *sec = + (anon_auth_config_rec *) ap_get_module_config(r->per_dir_config, + &anon_auth_module); + + if (!sec->auth_anon) + return DECLINED; + + if (strcasecmp(r->connection->user, sec->auth_anon)) + return DECLINED; + + return OK; +#endif + return DECLINED; +} + + +module MODULE_VAR_EXPORT anon_auth_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_anon_auth_dir_config, /* dir config creater */ + NULL, /* dir merger ensure strictness */ + NULL, /* server config */ + NULL, /* merge server config */ + anon_auth_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + anon_authenticate_basic_user, /* check_user_id */ + check_anon_access, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_auth_db.c b/APACHE_1_3b7/src/modules/standard/mod_auth_db.c new file mode 100644 index 0000000000..d29de222aa --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_auth_db.c @@ -0,0 +1,324 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 + * IT'S 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 . + * + */ + +/* + * mod_auth_db: authentication + * + * Original work by Rob McCool & Brian Behlendorf. + * + * Adapted to Apache by rst (mod_auth_dbm) + * + * Adapted for Berkeley DB by Andrew Cohen + * + * mod_auth_db was based on mod_auth_dbm. + * + * Warning, this is not a drop in replacement for mod_auth_dbm, + * for people wanting to switch from dbm to Berkeley DB. + * It requires the use of AuthDBUserFile and AuthDBGroupFile + * instead of AuthDBMUserFile AuthDBMGroupFile + * + * Also, in the configuration file you need to specify + * db_auth_module rather than dbm_auth_module + * + * On some BSD systems (e.g. FreeBSD and NetBSD) dbm is automatically + * mapped to Berkeley DB. You can use either mod_auth_dbm or + * mod_auth_db. The latter makes it more obvious that it's Berkeley. + * On other platforms where you want to use the DB library you + * usually have to install it first. See http://www.sleepycat.com/ + * for the distribution. The interface this module uses is the + * one from DB version 1.85 and 1.86, but DB version 2.x + * can also be used when compatibility mode is enabled. + * + * dirkx - Added Authoritative control to allow passing on to lower + * modules if and only if the user-id is not known to this + * module. A known user with a faulty or absent password still + * causes an AuthRequired. The default is 'Authoritative', i.e. + * no control is passed along. + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include + +typedef struct { + + char *auth_dbpwfile; + char *auth_dbgrpfile; + int auth_dbauthoritative; +} db_auth_config_rec; + +static void *create_db_auth_dir_config(pool *p, char *d) +{ + db_auth_config_rec *sec + = (db_auth_config_rec *) ap_pcalloc(p, sizeof(db_auth_config_rec)); + sec->auth_dbpwfile = NULL; + sec->auth_dbgrpfile = NULL; + sec->auth_dbauthoritative = 1; /* fortress is secure by default */ + return sec; +} + +static const char *set_db_slot(cmd_parms *cmd, void *offset, char *f, char *t) +{ + if (!t || strcmp(t, "db")) + return DECLINE_CMD; + + return ap_set_file_slot(cmd, offset, f); +} + +static const command_rec db_auth_cmds[] = +{ + {"AuthDBUserFile", ap_set_file_slot, + (void *) XtOffsetOf(db_auth_config_rec, auth_dbpwfile), + OR_AUTHCFG, TAKE1, NULL}, + {"AuthDBGroupFile", ap_set_file_slot, + (void *) XtOffsetOf(db_auth_config_rec, auth_dbgrpfile), + OR_AUTHCFG, TAKE1, NULL}, + {"AuthUserFile", set_db_slot, + (void *) XtOffsetOf(db_auth_config_rec, auth_dbpwfile), + OR_AUTHCFG, TAKE12, NULL}, + {"AuthGroupFile", set_db_slot, + (void *) XtOffsetOf(db_auth_config_rec, auth_dbgrpfile), + OR_AUTHCFG, TAKE12, NULL}, + {"AuthDBAuthoritative", ap_set_flag_slot, + (void *) XtOffsetOf(db_auth_config_rec, auth_dbauthoritative), + OR_AUTHCFG, FLAG, + "Set to 'no' to allow access control to be passed along to lower modules if the userID is not known to this module"}, + {NULL} +}; + +module db_auth_module; + +static char *get_db_pw(request_rec *r, char *user, const char *auth_dbpwfile) +{ + DB *f; + DBT d, q; + char *pw = NULL; + + q.data = user; + q.size = strlen(q.data); + + if (!(f = dbopen(auth_dbpwfile, O_RDONLY, 0664, DB_HASH, NULL))) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "could not open db auth file: %s", auth_dbpwfile); + return NULL; + } + + if (!((f->get) (f, &q, &d, 0))) { + pw = ap_palloc(r->pool, d.size + 1); + strncpy(pw, d.data, d.size); + pw[d.size] = '\0'; /* Terminate the string */ + } + + (f->close) (f); + return pw; +} + +/* We do something strange with the group file. If the group file + * contains any : we assume the format is + * key=username value=":"groupname [":"anything here is ignored] + * otherwise we now (0.8.14+) assume that the format is + * key=username value=groupname + * The first allows the password and group files to be the same + * physical DB file; key=username value=password":"groupname[":"anything] + * + * mark@telescope.org, 22Sep95 + */ + +static char *get_db_grp(request_rec *r, char *user, const char *auth_dbgrpfile) +{ + char *grp_data = get_db_pw(r, user, auth_dbgrpfile); + char *grp_colon; + char *grp_colon2; + + if (grp_data == NULL) + return NULL; + + if ((grp_colon = strchr(grp_data, ':')) != NULL) { + grp_colon2 = strchr(++grp_colon, ':'); + if (grp_colon2) + *grp_colon2 = '\0'; + return grp_colon; + } + return grp_data; +} + +static int db_authenticate_basic_user(request_rec *r) +{ + db_auth_config_rec *sec = + (db_auth_config_rec *) ap_get_module_config(r->per_dir_config, + &db_auth_module); + conn_rec *c = r->connection; + char *sent_pw, *real_pw, *colon_pw; + int res; + + if ((res = ap_get_basic_auth_pw(r, &sent_pw))) + return res; + + if (!sec->auth_dbpwfile) + return DECLINED; + + if (!(real_pw = get_db_pw(r, c->user, sec->auth_dbpwfile))) { + if (!(sec->auth_dbauthoritative)) + return DECLINED; + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "DB user %s not found: %s", c->user, r->filename); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + /* Password is up to first : if exists */ + colon_pw = strchr(real_pw, ':'); + if (colon_pw) + *colon_pw = '\0'; + /* anyone know where the prototype for crypt is? */ + if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "DB user %s: password mismatch: %s", c->user, r->uri); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + return OK; +} + +/* Checking ID */ + +static int db_check_auth(request_rec *r) +{ + db_auth_config_rec *sec = + (db_auth_config_rec *) ap_get_module_config(r->per_dir_config, + &db_auth_module); + char *user = r->connection->user; + int m = r->method_number; + + array_header *reqs_arr = ap_requires(r); + require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL; + + register int x; + const char *t; + char *w; + + if (!sec->auth_dbgrpfile) + return DECLINED; + if (!reqs_arr) + return DECLINED; + + for (x = 0; x < reqs_arr->nelts; x++) { + + if (!(reqs[x].method_mask & (1 << m))) + continue; + + t = reqs[x].requirement; + w = ap_getword(r->pool, &t, ' '); + + if (!strcmp(w, "group") && sec->auth_dbgrpfile) { + const char *orig_groups, *groups; + char *v; + + if (!(groups = get_db_grp(r, user, sec->auth_dbgrpfile))) { + if (!(sec->auth_dbauthoritative)) + return DECLINED; + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "user %s not in DB group file %s: %s", + user, sec->auth_dbgrpfile, r->filename); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + orig_groups = groups; + while (t[0]) { + w = ap_getword(r->pool, &t, ' '); + groups = orig_groups; + while (groups[0]) { + v = ap_getword(r->pool, &groups, ','); + if (!strcmp(v, w)) + return OK; + } + } + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "user %s not in right group: %s", user, r->filename); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + } + + return DECLINED; +} + + +module db_auth_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_db_auth_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + db_auth_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + db_authenticate_basic_user, /* check_user_id */ + db_check_auth, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_auth_db.module b/APACHE_1_3b7/src/modules/standard/mod_auth_db.module new file mode 100644 index 0000000000..68aa260918 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_auth_db.module @@ -0,0 +1,20 @@ +Name: db_auth_module +ConfigStart + if ./helpers/TestCompile func dbopen; then + : + else + case "$PLAT" in + *-linux*) + # many systems have -ldb installed + DB_LIB="" + if ./helpers/TestCompile lib db dbopen; then + DB_LIB="-ldb" + fi + ;; + esac + LIBS="$LIBS $DB_LIB" + if [ "X$DB_LIB" != "X" ]; then + echo " + using $DB_LIB for mod_auth_db" + fi + fi +ConfigEnd diff --git a/APACHE_1_3b7/src/modules/standard/mod_auth_dbm.c b/APACHE_1_3b7/src/modules/standard/mod_auth_dbm.c new file mode 100644 index 0000000000..a68e5a9164 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_auth_dbm.c @@ -0,0 +1,326 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_auth: authentication + * + * Rob McCool & Brian Behlendorf. + * + * Adapted to Apache by rst. + * + * dirkx - Added Authoritative control to allow passing on to lower + * modules if and only if the user-id is not known to this + * module. A known user with a faulty or absent password still + * causes an AuthRequired. The default is 'Authoritative', i.e. + * no control is passed along. + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include + +/* + * Module definition information - the part between the -START and -END + * lines below is used by Configure. This could be stored in a separate + * instead. + * + * MODULE-DEFINITION-START + * Name: dbm_auth_module + * ConfigStart + . ./helpers/find-dbm-lib + * ConfigEnd + * MODULE-DEFINITION-END + */ + +typedef struct { + + char *auth_dbmpwfile; + char *auth_dbmgrpfile; + int auth_dbmauthoritative; + +} dbm_auth_config_rec; + +static void *create_dbm_auth_dir_config(pool *p, char *d) +{ + dbm_auth_config_rec *sec + = (dbm_auth_config_rec *) ap_pcalloc(p, sizeof(dbm_auth_config_rec)); + + sec->auth_dbmpwfile = NULL; + sec->auth_dbmgrpfile = NULL; + sec->auth_dbmauthoritative = 1; /* fortress is secure by default */ + + return sec; +} + +static const char *set_dbm_slot(cmd_parms *cmd, void *offset, char *f, char *t) +{ + if (!t || strcmp(t, "dbm")) + return DECLINE_CMD; + + return ap_set_file_slot(cmd, offset, f); +} + +static const command_rec dbm_auth_cmds[] = +{ + {"AuthDBMUserFile", ap_set_file_slot, + (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmpwfile), + OR_AUTHCFG, TAKE1, NULL}, + {"AuthDBMGroupFile", ap_set_file_slot, + (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmgrpfile), + OR_AUTHCFG, TAKE1, NULL}, + {"AuthUserFile", set_dbm_slot, + (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmpwfile), + OR_AUTHCFG, TAKE12, NULL}, + {"AuthGroupFile", set_dbm_slot, + (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmgrpfile), + OR_AUTHCFG, TAKE12, NULL}, + {"AuthDBMAuthoritative", ap_set_flag_slot, + (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmauthoritative), + OR_AUTHCFG, FLAG, "Set to 'no' to allow access control to be passed along to lower modules, if the UserID is not known in this module"}, + {NULL} +}; + +module dbm_auth_module; + +static char *get_dbm_pw(request_rec *r, char *user, char *auth_dbmpwfile) +{ + DBM *f; + datum d, q; + char *pw = NULL; + + q.dptr = user; +#ifndef NETSCAPE_DBM_COMPAT + q.dsize = strlen(q.dptr); +#else + q.dsize = strlen(q.dptr) + 1; +#endif + + + if (!(f = dbm_open(auth_dbmpwfile, O_RDONLY, 0664))) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "could not open dbm auth file: %s", auth_dbmpwfile); + return NULL; + } + + d = dbm_fetch(f, q); + + if (d.dptr) { + pw = ap_palloc(r->pool, d.dsize + 1); + strncpy(pw, d.dptr, d.dsize); + pw[d.dsize] = '\0'; /* Terminate the string */ + } + + dbm_close(f); + return pw; +} + +/* We do something strange with the group file. If the group file + * contains any : we assume the format is + * key=username value=":"groupname [":"anything here is ignored] + * otherwise we now (0.8.14+) assume that the format is + * key=username value=groupname + * The first allows the password and group files to be the same + * physical DBM file; key=username value=password":"groupname[":"anything] + * + * mark@telescope.org, 22Sep95 + */ + +static char *get_dbm_grp(request_rec *r, char *user, char *auth_dbmgrpfile) +{ + char *grp_data = get_dbm_pw(r, user, auth_dbmgrpfile); + char *grp_colon; + char *grp_colon2; + + if (grp_data == NULL) + return NULL; + + if ((grp_colon = strchr(grp_data, ':')) != NULL) { + grp_colon2 = strchr(++grp_colon, ':'); + if (grp_colon2) + *grp_colon2 = '\0'; + return grp_colon; + } + return grp_data; +} + +static int dbm_authenticate_basic_user(request_rec *r) +{ + dbm_auth_config_rec *sec = + (dbm_auth_config_rec *) ap_get_module_config(r->per_dir_config, + &dbm_auth_module); + conn_rec *c = r->connection; + char *sent_pw, *real_pw, *colon_pw; + int res; + + if ((res = ap_get_basic_auth_pw(r, &sent_pw))) + return res; + + if (!sec->auth_dbmpwfile) + return DECLINED; + + if (!(real_pw = get_dbm_pw(r, c->user, sec->auth_dbmpwfile))) { + if (!(sec->auth_dbmauthoritative)) + return DECLINED; + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "DBM user %s not found: %s", c->user, r->filename); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + /* Password is up to first : if exists */ + colon_pw = strchr(real_pw, ':'); + if (colon_pw) + *colon_pw = '\0'; + /* anyone know where the prototype for crypt is? */ + if (strcmp(real_pw, (char *) crypt(sent_pw, real_pw))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "user %s: password mismatch: %s", c->user, r->uri); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + return OK; +} + +/* Checking ID */ + +static int dbm_check_auth(request_rec *r) +{ + dbm_auth_config_rec *sec = + (dbm_auth_config_rec *) ap_get_module_config(r->per_dir_config, + &dbm_auth_module); + char *user = r->connection->user; + int m = r->method_number; + + array_header *reqs_arr = ap_requires(r); + require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL; + + register int x; + const char *t; + char *w; + + if (!sec->auth_dbmgrpfile) + return DECLINED; + if (!reqs_arr) + return DECLINED; + + for (x = 0; x < reqs_arr->nelts; x++) { + + if (!(reqs[x].method_mask & (1 << m))) + continue; + + t = reqs[x].requirement; + w = ap_getword(r->pool, &t, ' '); + + if (!strcmp(w, "group") && sec->auth_dbmgrpfile) { + const char *orig_groups, *groups; + char *v; + + if (!(groups = get_dbm_grp(r, user, sec->auth_dbmgrpfile))) { + if (!(sec->auth_dbmauthoritative)) + return DECLINED; + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "user %s not in DBM group file %s: %s", + user, sec->auth_dbmgrpfile, r->filename); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + orig_groups = groups; + while (t[0]) { + w = ap_getword(r->pool, &t, ' '); + groups = orig_groups; + while (groups[0]) { + v = ap_getword(r->pool, &groups, ','); + if (!strcmp(v, w)) + return OK; + } + } + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "user %s not in right group: %s", + user, r->filename); + ap_note_basic_auth_failure(r); + return AUTH_REQUIRED; + } + } + + return DECLINED; +} + + +module dbm_auth_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_dbm_auth_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + dbm_auth_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + dbm_authenticate_basic_user, /* check_user_id */ + dbm_check_auth, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_autoindex.c b/APACHE_1_3b7/src/modules/standard/mod_autoindex.c new file mode 100644 index 0000000000..3455f714cb --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_autoindex.c @@ -0,0 +1,1201 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * mod_autoindex.c: Handles the on-the-fly html index generation + * + * Rob McCool + * 3/23/93 + * + * Adapted to Apache by rst. + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_request.h" +#include "http_protocol.h" +#include "http_log.h" +#include "http_main.h" +#include "util_script.h" + +module MODULE_VAR_EXPORT autoindex_module; + +/**************************************************************** + * + * Handling configuration directives... + */ + +#define HRULE 1 +#define NO_HRULE 0 +#define FRONT_MATTER 1 +#define END_MATTER 0 + +#define FANCY_INDEXING 1 /* Indexing options */ +#define ICONS_ARE_LINKS 2 +#define SCAN_HTML_TITLES 4 +#define SUPPRESS_LAST_MOD 8 +#define SUPPRESS_SIZE 16 +#define SUPPRESS_DESC 32 +#define SUPPRESS_PREAMBLE 64 +#define SUPPRESS_COLSORT 128 + +/* + * Define keys for sorting. + */ +#define K_NAME 'N' /* Sort by file name (default) */ +#define K_LAST_MOD 'M' /* Last modification date */ +#define K_SIZE 'S' /* Size (absolute, not as displayed) */ +#define K_DESC 'D' /* Description */ + +#define D_ASCENDING 'A' +#define D_DESCENDING 'D' + +/* + * These are the dimensions of the default icons supplied with Apache. + */ +#define DEFAULT_ICON_WIDTH 20 +#define DEFAULT_ICON_HEIGHT 22 + +struct item { + char *type; + char *apply_to; + char *apply_path; + char *data; +}; + +typedef struct autoindex_config_struct { + + char *default_icon; + int icon_width; + int icon_height; + + array_header *icon_list, *alt_list, *desc_list, *ign_list; + array_header *hdr_list, *rdme_list, *opts_list; + +} autoindex_config_rec; + +static char c_by_encoding, c_by_type, c_by_path; + +#define BY_ENCODING &c_by_encoding +#define BY_TYPE &c_by_type +#define BY_PATH &c_by_path + +/* + * This routine puts the standard HTML header at the top of the index page. + * We include the DOCTYPE because we may be using features therefrom (i.e., + * HEIGHT and WIDTH attributes on the icons if we're FancyIndexing). + */ +static void emit_preamble(request_rec *r, char *title) +{ + ap_rvputs + ( + r, + "\n", + "\n \n Index of ", + title, + "\n \n \n", + NULL + ); +} + +static void push_item(array_header *arr, char *type, char *to, char *path, + char *data) +{ + struct item *p = (struct item *) ap_push_array(arr); + + if (!to) + to = ""; + if (!path) + path = ""; + + p->type = type; + p->data = data ? ap_pstrdup(arr->pool, data) : NULL; + p->apply_path = ap_pstrcat(arr->pool, path, "*", NULL); + + if ((type == BY_PATH) && (!ap_is_matchexp(to))) + p->apply_to = ap_pstrcat(arr->pool, "*", to, NULL); + else if (to) + p->apply_to = ap_pstrdup(arr->pool, to); + else + p->apply_to = NULL; +} + +static const char *add_alt(cmd_parms *cmd, void *d, char *alt, char *to) +{ + if (cmd->info == BY_PATH) + if (!strcmp(to, "**DIRECTORY**")) + to = "^^DIRECTORY^^"; + if (cmd->info == BY_ENCODING) { + ap_str_tolower(to); + } + + push_item(((autoindex_config_rec *) d)->alt_list, cmd->info, to, cmd->path, alt); + return NULL; +} + +static const char *add_icon(cmd_parms *cmd, void *d, char *icon, char *to) +{ + char *iconbak = ap_pstrdup(cmd->pool, icon); + + if (icon[0] == '(') { + char *alt; + char *cl = strchr(iconbak, ')'); + + if (cl == NULL) { + return "missing closing paren"; + } + alt = ap_getword_nc(cmd->pool, &iconbak, ','); + *cl = '\0'; /* Lose closing paren */ + add_alt(cmd, d, &alt[1], to); + } + if (cmd->info == BY_PATH) + if (!strcmp(to, "**DIRECTORY**")) + to = "^^DIRECTORY^^"; + if (cmd->info == BY_ENCODING) { + ap_str_tolower(to); + } + + push_item(((autoindex_config_rec *) d)->icon_list, cmd->info, to, cmd->path, + iconbak); + return NULL; +} + +static const char *add_desc(cmd_parms *cmd, void *d, char *desc, char *to) +{ + push_item + ( + ((autoindex_config_rec *) d)->desc_list, + cmd->info, + to, + cmd->path, + desc + ); + return NULL; +} + +static const char *add_ignore(cmd_parms *cmd, void *d, char *ext) +{ + push_item(((autoindex_config_rec *) d)->ign_list, 0, ext, cmd->path, NULL); + return NULL; +} + +static const char *add_header(cmd_parms *cmd, void *d, char *name) +{ + if (strchr(name, '/')) { + return "HeaderName cannot contain a /"; + } + push_item(((autoindex_config_rec *) d)->hdr_list, 0, NULL, cmd->path, name); + return NULL; +} + +static const char *add_readme(cmd_parms *cmd, void *d, char *name) +{ + if (strchr(name, '/')) { + return "ReadmeName cannot contain a /"; + } + push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path, name); + return NULL; +} + + +static const char *add_opts_int(cmd_parms *cmd, void *d, int opts) +{ + push_item(((autoindex_config_rec *) d)->opts_list, (char *) (long) opts, NULL, + cmd->path, NULL); + return NULL; +} + +static const char *fancy_indexing(cmd_parms *cmd, void *d, int arg) +{ + return add_opts_int(cmd, d, arg ? FANCY_INDEXING : 0); +} + +static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr) +{ + char *w; + int opts = 0; + autoindex_config_rec *d_cfg = (autoindex_config_rec *) d; + + while (optstr[0]) { + w = ap_getword_conf(cmd->pool, &optstr); + if (!strcasecmp(w, "FancyIndexing")) + opts |= FANCY_INDEXING; + else if (!strcasecmp(w, "IconsAreLinks")) + opts |= ICONS_ARE_LINKS; + else if (!strcasecmp(w, "ScanHTMLTitles")) + opts |= SCAN_HTML_TITLES; + else if (!strcasecmp(w, "SuppressLastModified")) + opts |= SUPPRESS_LAST_MOD; + else if (!strcasecmp(w, "SuppressSize")) + opts |= SUPPRESS_SIZE; + else if (!strcasecmp(w, "SuppressDescription")) + opts |= SUPPRESS_DESC; + else if (!strcasecmp(w, "SuppressHTMLPreamble")) + opts |= SUPPRESS_PREAMBLE; + else if (!strcasecmp(w, "SuppressColumnSorting")) { + opts |= SUPPRESS_COLSORT; + } + else if (!strcasecmp(w, "None")) + opts = 0; + else if (!strncasecmp(w, "IconWidth", 9)) { + if (strchr(w, '=') != NULL) { + const char *x = ap_pstrdup(cmd->pool, w); + char *val; + val = ap_getword(cmd->pool, &x, '='); + val = ap_getword(cmd->pool, &x, '='); + d_cfg->icon_width = atoi(val); + } + else { + d_cfg->icon_width = DEFAULT_ICON_WIDTH; + } + } + else if (!strncasecmp(w, "IconHeight", 10)) { + if (strchr(w, '=') != NULL) { + const char *x = ap_pstrdup(cmd->pool, w); + char *val; + val = ap_getword(cmd->pool, &x, '='); + val = ap_getword(cmd->pool, &x, '='); + d_cfg->icon_height = atoi(val); + } + else { + d_cfg->icon_height = DEFAULT_ICON_HEIGHT; + } + } + else + return "Invalid directory indexing option"; + } + return add_opts_int(cmd, d, opts); +} + +#define DIR_CMD_PERMS OR_INDEXES + +static const command_rec autoindex_cmds[] = +{ + {"AddIcon", add_icon, BY_PATH, DIR_CMD_PERMS, ITERATE2, + "an icon URL followed by one or more filenames"}, + {"AddIconByType", add_icon, BY_TYPE, DIR_CMD_PERMS, ITERATE2, + "an icon URL followed by one or more MIME types"}, + {"AddIconByEncoding", add_icon, BY_ENCODING, DIR_CMD_PERMS, ITERATE2, + "an icon URL followed by one or more content encodings"}, + {"AddAlt", add_alt, BY_PATH, DIR_CMD_PERMS, ITERATE2, + "alternate descriptive text followed by one or more filenames"}, + {"AddAltByType", add_alt, BY_TYPE, DIR_CMD_PERMS, ITERATE2, + "alternate descriptive text followed by one or more MIME types"}, + {"AddAltByEncoding", add_alt, BY_ENCODING, DIR_CMD_PERMS, ITERATE2, + "alternate descriptive text followed by one or more content encodings"}, + {"IndexOptions", add_opts, NULL, DIR_CMD_PERMS, RAW_ARGS, + "one or more index options"}, + {"IndexIgnore", add_ignore, NULL, DIR_CMD_PERMS, ITERATE, + "one or more file extensions"}, + {"AddDescription", add_desc, BY_PATH, DIR_CMD_PERMS, ITERATE2, + "Descriptive text followed by one or more filenames"}, + {"HeaderName", add_header, NULL, DIR_CMD_PERMS, TAKE1, "a filename"}, + {"ReadmeName", add_readme, NULL, DIR_CMD_PERMS, TAKE1, "a filename"}, + {"FancyIndexing", fancy_indexing, NULL, DIR_CMD_PERMS, FLAG, + "Limited to 'on' or 'off' (superseded by IndexOptions FancyIndexing)"}, + {"DefaultIcon", ap_set_string_slot, + (void *) XtOffsetOf(autoindex_config_rec, default_icon), + DIR_CMD_PERMS, TAKE1, "an icon URL"}, + {NULL} +}; + +static void *create_autoindex_config(pool *p, char *dummy) +{ + autoindex_config_rec *new = + (autoindex_config_rec *) ap_pcalloc(p, sizeof(autoindex_config_rec)); + + new->icon_width = 0; + new->icon_height = 0; + new->icon_list = ap_make_array(p, 4, sizeof(struct item)); + new->alt_list = ap_make_array(p, 4, sizeof(struct item)); + new->desc_list = ap_make_array(p, 4, sizeof(struct item)); + new->ign_list = ap_make_array(p, 4, sizeof(struct item)); + new->hdr_list = ap_make_array(p, 4, sizeof(struct item)); + new->rdme_list = ap_make_array(p, 4, sizeof(struct item)); + new->opts_list = ap_make_array(p, 4, sizeof(struct item)); + + return (void *) new; +} + +static void *merge_autoindex_configs(pool *p, void *basev, void *addv) +{ + autoindex_config_rec *new = (autoindex_config_rec *) ap_pcalloc(p, sizeof(autoindex_config_rec)); + autoindex_config_rec *base = (autoindex_config_rec *) basev; + autoindex_config_rec *add = (autoindex_config_rec *) addv; + + new->default_icon = add->default_icon ? add->default_icon:base->default_icon; + new->icon_height = add->icon_height ? add->icon_height : base->icon_height; + new->icon_width = add->icon_width ? add->icon_width : base->icon_width; + + new->alt_list = ap_append_arrays(p, add->alt_list, base->alt_list); + new->ign_list = ap_append_arrays(p, add->ign_list, base->ign_list); + new->hdr_list = ap_append_arrays(p, add->hdr_list, base->hdr_list); + new->desc_list = ap_append_arrays(p, add->desc_list, base->desc_list); + new->icon_list = ap_append_arrays(p, add->icon_list, base->icon_list); + new->rdme_list = ap_append_arrays(p, add->rdme_list, base->rdme_list); + new->opts_list = ap_append_arrays(p, add->opts_list, base->opts_list); + + return new; +} + +/**************************************************************** + * + * Looking things up in config entries... + */ + +/* Structure used to hold entries when we're actually building an index */ + +struct ent { + char *name; + char *icon; + char *alt; + char *desc; + size_t size; + char *size_cmp; + time_t lm; + char *lm_cmp; + struct ent *next; + int ascending; + char key; +}; + +static char *find_item(request_rec *r, array_header *list, int path_only) +{ + char *content_type = r->content_type; + char *content_encoding = r->content_encoding; + char *path = r->filename; + + struct item *items = (struct item *) list->elts; + int i; + + for (i = 0; i < list->nelts; ++i) { + struct item *p = &items[i]; + + /* Special cased for ^^DIRECTORY^^ and ^^BLANKICON^^ */ + if ((path[0] == '^') || (!ap_strcmp_match(path, p->apply_path))) { + if (!*(p->apply_to)) + return p->data; + else if (p->type == BY_PATH || path[0] == '^') { + if (!ap_strcmp_match(path, p->apply_to)) + return p->data; + } + else if (!path_only) { + if (!content_encoding) { + if (p->type == BY_TYPE) { + if (content_type && !ap_strcasecmp_match(content_type, p->apply_to)) + return p->data; + } + } + else { + if (p->type == BY_ENCODING) { + if (!ap_strcasecmp_match(content_encoding, p->apply_to)) + return p->data; + } + } + } + } + } + return NULL; +} + +#define find_icon(d,p,t) find_item(p,d->icon_list,t) +#define find_alt(d,p,t) find_item(p,d->alt_list,t) +#define find_desc(d,p) find_item(p,d->desc_list,0) +#define find_header(d,p) find_item(p,d->hdr_list,0) +#define find_readme(d,p) find_item(p,d->rdme_list,0) + +static char *find_default_icon(autoindex_config_rec * d, char *bogus_name) +{ + request_rec r; + + /* Bleah. I tried to clean up find_item, and it lead to this bit + * of ugliness. Note that the fields initialized are precisely + * those that find_item looks at... + */ + + r.filename = bogus_name; + r.content_type = r.content_encoding = NULL; + + return find_item(&r, d->icon_list, 1); +} + +static int ignore_entry(autoindex_config_rec * d, char *path) +{ + array_header *list = d->ign_list; + struct item *items = (struct item *) list->elts; + char *tt; + int i; + + if ((tt = strrchr(path, '/')) == NULL) + tt = path; + else { + tt++; + } + + for (i = 0; i < list->nelts; ++i) { + struct item *p = &items[i]; + char *ap; + + if ((ap = strrchr(p->apply_to, '/')) == NULL) + ap = p->apply_to; + else + ap++; + + if (!ap_strcmp_match(path, p->apply_path) && !ap_strcmp_match(tt, ap)) + return 1; + } + return 0; +} + +static int find_opts(autoindex_config_rec * d, request_rec *r) +{ + char *path = r->filename; + array_header *list = d->opts_list; + struct item *items = (struct item *) list->elts; + int i; + + for (i = 0; i < list->nelts; ++i) { + struct item *p = &items[i]; + + if (!ap_strcmp_match(path, p->apply_path)) + return (int) (long) p->type; + } + return 0; +} + +/***************************************************************** + * + * Actually generating output + */ + +/* + * Look for the specified file, and pump it into the response stream if we + * find it. + */ +static int insert_readme(char *name, char *readme_fname, char *title, int hrule, + int whichend, request_rec *r) +{ + char *fn; + FILE *f; + struct stat finfo; + int plaintext = 0; + request_rec *rr; + autoindex_config_rec *cfg = + (autoindex_config_rec *) ap_get_module_config + ( + r->per_dir_config, + &autoindex_module + ); + int autoindex_opts = find_opts(cfg, r); + + /* XXX: this is a load of crap, it needs to do a full sub_req_lookup_uri */ + fn = ap_make_full_path(r->pool, name, readme_fname); + fn = ap_pstrcat(r->pool, fn, ".html", NULL); + if (stat(fn, &finfo) == -1) { + /* A brief fake multiviews search for README.html */ + fn[strlen(fn) - 5] = '\0'; + if (stat(fn, &finfo) == -1) + return 0; + plaintext = 1; + if (hrule) + ap_rputs("
    \n", r); + } + else if (hrule) + ap_rputs("
    \n", r); + /* XXX: when the above is rewritten properly, this necessary security + * check will be redundant. -djg */ + rr = ap_sub_req_lookup_file(fn, r); + if (rr->status != HTTP_OK) { + ap_destroy_sub_req(rr); + return 0; + } + ap_destroy_sub_req(rr); + if (!(f = ap_pfopen(r->pool, fn, "r"))) + return 0; + if ( + (whichend == FRONT_MATTER) && + (!(autoindex_opts & SUPPRESS_PREAMBLE)) + ) { + emit_preamble(r, title); + } + if (!plaintext) { + ap_send_fd(f, r); + } + else { + char buf[IOBUFSIZE + 1]; + int i, n, c, ch; + ap_rputs("
    \n", r);
    +	while (!feof(f)) {
    +	    do
    +		n = fread(buf, sizeof(char), IOBUFSIZE, f);
    +	    while (n == -1 && ferror(f) && errno == EINTR);
    +	    if (n == -1 || n == 0)
    +		break;
    +	    buf[n] = '\0';
    +	    c = 0;
    +	    while (c < n) {
    +		for (i = c; i < n; i++)
    +		    if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&')
    +			break;
    +		ch = buf[i];
    +		buf[i] = '\0';
    +		ap_rputs(&buf[c], r);
    +		if (ch == '<')
    +		    ap_rputs("<", r);
    +		else if (ch == '>')
    +		    ap_rputs(">", r);
    +		else if (ch == '&')
    +		    ap_rputs("&", r);
    +		c = i + 1;
    +	    }
    +	}
    +    }
    +    ap_pfclose(r->pool, f);
    +    if (plaintext)
    +	ap_rputs("
    \n", r); + return 1; +} + + +static char *find_title(request_rec *r) +{ + char titlebuf[MAX_STRING_LEN], *find = ""; + FILE *thefile = NULL; + int x, y, n, p; + + if (r->status != HTTP_OK) { + return NULL; + } + if (r->content_type + && (!strcmp(r->content_type, "text/html") + || !strcmp(r->content_type, INCLUDES_MAGIC_TYPE)) + && !r->content_encoding) { + if (!(thefile = ap_pfopen(r->pool, r->filename, "r"))) + return NULL; + n = fread(titlebuf, sizeof(char), MAX_STRING_LEN - 1, thefile); + if (n <= 0) { + ap_pfclose(r->pool, thefile); + return NULL; + } + titlebuf[n] = '\0'; + for (x = 0, p = 0; titlebuf[x]; x++) { + if (toupper(titlebuf[x]) == find[p]) { + if (!find[++p]) { + if ((p = ap_ind(&titlebuf[++x], '<')) != -1) + titlebuf[x + p] = '\0'; + /* Scan for line breaks for Tanmoy's secretary */ + for (y = x; titlebuf[y]; y++) { + if ((titlebuf[y] == CR) || (titlebuf[y] == LF)) { + if (y == x) { + x++; + } + else { + titlebuf[y] = ' '; + } + } + } + ap_pfclose(r->pool, thefile); + return ap_pstrdup(r->pool, &titlebuf[x]); + } + } + else + p = 0; + } + ap_pfclose(r->pool, thefile); + } + return NULL; +} + +static struct ent *make_autoindex_entry(char *name, int autoindex_opts, + autoindex_config_rec * d, + request_rec *r, char keyid, + char direction) +{ + struct ent *p; + + if ((name[0] == '.') && (!name[1])) + return (NULL); + + if (ignore_entry(d, ap_make_full_path(r->pool, r->filename, name))) + return (NULL); + + p = (struct ent *) ap_pcalloc(r->pool, sizeof(struct ent)); + p->name = ap_pstrdup(r->pool, name); + p->size = 0; + p->icon = NULL; + p->alt = NULL; + p->desc = NULL; + p->lm = -1; + p->key = toupper(keyid); + p->ascending = (toupper(direction) == D_ASCENDING); + + if (autoindex_opts & FANCY_INDEXING) { + request_rec *rr = ap_sub_req_lookup_file(name, r); + + if (rr->finfo.st_mode != 0) { + p->lm = rr->finfo.st_mtime; + if (S_ISDIR(rr->finfo.st_mode)) { + if (!(p->icon = find_icon(d, rr, 1))) + p->icon = find_default_icon(d, "^^DIRECTORY^^"); + if (!(p->alt = find_alt(d, rr, 1))) + p->alt = "DIR"; + p->size = 0; + p->name = ap_pstrcat(r->pool, name, "/", NULL); + } + else { + p->icon = find_icon(d, rr, 0); + p->alt = find_alt(d, rr, 0); + p->size = rr->finfo.st_size; + } + } + + p->desc = find_desc(d, rr); + + if ((!p->desc) && (autoindex_opts & SCAN_HTML_TITLES)) + p->desc = ap_pstrdup(r->pool, find_title(rr)); + + ap_destroy_sub_req(rr); + } + if (keyid == K_SIZE) { + p->size_cmp = ap_palloc(r->pool, 14); + ap_snprintf(p->size_cmp, 14, "%013d", p->size); + } + if (keyid == K_LAST_MOD) { + struct tm *ts = localtime(&p->lm); + + if(ts) { + p->lm_cmp = ap_palloc(r->pool, 15); + strftime(p->lm_cmp, 15, "%Y%m%d%H%M%S", ts); + } + else + p->lm_cmp=NULL; + } + return (p); +} + +static char *terminate_description(autoindex_config_rec * d, char *desc, + int autoindex_opts) +{ + int maxsize = 23; + register int x; + + if (autoindex_opts & SUPPRESS_LAST_MOD) + maxsize += 19; + if (autoindex_opts & SUPPRESS_SIZE) + maxsize += 7; + + for (x = 0; desc[x] && (maxsize > 0 || desc[x]=='<'); x++) { + if (desc[x] == '<') { + while (desc[x] != '>') { + if (!desc[x]) { + maxsize = 0; + break; + } + ++x; + } + } + else if (desc[x] == '&') { + /* entities like ä count as one character */ + --maxsize; + for ( ; desc[x] != ';'; ++x) { + if (desc[x] == '\0') { + maxsize = 0; + break; + } + } + } + else + --maxsize; + } + if (!maxsize && desc[x] != '\0') { + desc[x - 1] = '>'; /* Grump. */ + desc[x] = '\0'; /* Double Grump! */ + } + return desc; +} + +/* + * Emit the anchor for the specified field. If a field is the key for the + * current request, the link changes its meaning to reverse the order when + * selected again. Non-active fields always start in ascending order. + */ +static void emit_link(request_rec *r, char *anchor, char fname, char curkey, + char curdirection, int nosort) +{ + char qvalue[5]; + int reverse; + + if (!nosort) { + qvalue[0] = '?'; + qvalue[1] = fname; + qvalue[2] = '='; + qvalue[4] = '\0'; + reverse = ((curkey == fname) && (curdirection == D_ASCENDING)); + qvalue[3] = reverse ? D_DESCENDING : D_ASCENDING; + ap_rvputs(r, "<A HREF=\"", qvalue, "\">", anchor, "</A>", NULL); + } + else { + ap_rputs(anchor, r); + } +} + +static void output_directories(struct ent **ar, int n, + autoindex_config_rec * d, request_rec *r, + int autoindex_opts, char keyid, char direction) +{ + int x, len; + char *name = r->uri; + char *tp; + int static_columns = (autoindex_opts & SUPPRESS_COLSORT); + pool *scratch = ap_make_sub_pool(r->pool); + + if (name[0] == '\0') + name = "/"; + + if (autoindex_opts & FANCY_INDEXING) { + ap_rputs("<PRE>", r); + if ((tp = find_default_icon(d, "^^BLANKICON^^"))) { + ap_rvputs(r, "<IMG SRC=\"", ap_escape_html(scratch, tp), + "\" ALT=\" \"", NULL); + if (d->icon_width && d->icon_height) { + ap_rprintf + ( + r, + " HEIGHT=\"%d\" WIDTH=\"%d\"", + d->icon_height, + d->icon_width + ); + } + ap_rputs("> ", r); + } + emit_link(r, "Name", K_NAME, keyid, direction, static_columns); + ap_rputs(" ", r); + if (!(autoindex_opts & SUPPRESS_LAST_MOD)) { + emit_link(r, "Last modified", K_LAST_MOD, keyid, direction, + static_columns); + ap_rputs(" ", r); + } + if (!(autoindex_opts & SUPPRESS_SIZE)) { + emit_link(r, "Size", K_SIZE, keyid, direction, static_columns); + ap_rputs(" ", r); + } + if (!(autoindex_opts & SUPPRESS_DESC)) { + emit_link(r, "Description", K_DESC, keyid, direction, + static_columns); + } + ap_rputs("\n<HR>\n", r); + } + else { + ap_rputs("<UL>", r); + } + + for (x = 0; x < n; x++) { + char *anchor = NULL, *t = NULL, *t2 = NULL; + + ap_clear_pool(scratch); + + if ((!strcmp(ar[x]->name, "../")) || (!strcmp(ar[x]->name, ".."))) { + t = ap_make_full_path(scratch, name, "../"); + ap_getparents(t); + if (t[0] == '\0') + t = "/"; + anchor = ap_pstrcat(scratch, "<A HREF=\"", + ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0)), + "\">", NULL); + t2 = "Parent Directory</A> "; + } + else { + t = ar[x]->name; + len = strlen(t); + if (len > 23) { + t2 = ap_pstrdup(scratch, t); + t2[21] = '.'; + t2[22] = '.'; + t2[23] = '\0'; + t2 = ap_escape_html(scratch, t2); + t2 = ap_pstrcat(scratch, t2, "</A>", NULL); + } + else { + char buff[24] = " "; + t2 = ap_escape_html(scratch, t); + buff[23 - len] = '\0'; + t2 = ap_pstrcat(scratch, t2, "</A>", buff, NULL); + } + anchor = ap_pstrcat(scratch, "<A HREF=\"", + ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0)), + "\">", NULL); + } + + if (autoindex_opts & FANCY_INDEXING) { + if (autoindex_opts & ICONS_ARE_LINKS) + ap_rputs(anchor, r); + if ((ar[x]->icon) || d->default_icon) { + ap_rvputs(r, "<IMG SRC=\"", + ap_escape_html(scratch, ar[x]->icon ? + ar[x]->icon : d->default_icon), + "\" ALT=\"[", (ar[x]->alt ? ar[x]->alt : " "), + "]\"", NULL); + if (d->icon_width && d->icon_height) { + ap_rprintf + ( + r, + " HEIGHT=\"%d\" WIDTH=\"%d\"", + d->icon_height, + d->icon_width + ); + } + ap_rputs(">", r); + } + if (autoindex_opts & ICONS_ARE_LINKS) + ap_rputs("</A>", r); + + ap_rvputs(r, " ", anchor, t2, NULL); + if (!(autoindex_opts & SUPPRESS_LAST_MOD)) { + if (ar[x]->lm != -1) { + char time_str[MAX_STRING_LEN]; + struct tm *ts = localtime(&ar[x]->lm); + strftime(time_str, MAX_STRING_LEN, "%d-%b-%Y %H:%M ", ts); + ap_rputs(time_str, r); + } + else { + ap_rputs(" ", r); + } + } + if (!(autoindex_opts & SUPPRESS_SIZE)) { + ap_send_size(ar[x]->size, r); + ap_rputs(" ", r); + } + if (!(autoindex_opts & SUPPRESS_DESC)) { + if (ar[x]->desc) { + ap_rputs(terminate_description(d, ar[x]->desc, autoindex_opts), r); + } + } + } + else + ap_rvputs(r, "<LI> ", anchor, " ", t2, NULL); + ap_rputc('\n', r); + } + if (autoindex_opts & FANCY_INDEXING) { + ap_rputs("</PRE>", r); + } + else { + ap_rputs("</UL>", r); + } +} + + +static int dsortf(struct ent **e1, struct ent **e2) +{ + char *s1; + char *s2; + char *s3; + int result; + + /* + * Choose the right values for the sort keys. + */ + switch ((*e1)->key) { + case K_LAST_MOD: + s1 = (*e1)->lm_cmp; + s2 = (*e2)->lm_cmp; + break; + case K_SIZE: + s1 = (*e1)->size_cmp; + s2 = (*e2)->size_cmp; + break; + case K_DESC: + s1 = (*e1)->desc; + s2 = (*e2)->desc; + break; + case K_NAME: + default: + s1 = (*e1)->name; + s2 = (*e2)->name; + break; + } + /* + * If we're supposed to sort in DEscending order, reverse the arguments. + */ + if (!(*e1)->ascending) { + s3 = s1; + s1 = s2; + s2 = s3; + } + + /* + * Take some care, here, in case one string or the other (or both) is + * NULL. + */ + + /* + * Two valid strings, compare normally. + */ + if ((s1 != NULL) && (s2 != NULL)) { + result = strcmp(s1, s2); + } + /* + * Two NULL strings - primary keys are equal (fake it). + */ + else if ((s1 == NULL) && (s2 == NULL)) { + result = 0; + } + /* + * s1 is NULL, but s2 is a string - so s2 wins. + */ + else if (s1 == NULL) { + result = -1; + } + /* + * Last case: s1 is a string and s2 is NULL, so s1 wins. + */ + else { + result = 1; + } + /* + * If the keys were equal, the file name is *always* the secondary key - + * in ascending order. + */ + if (!result) { + result = strcmp((*e1)->name, (*e2)->name); + } + return result; +} + + +static int index_directory(request_rec *r, autoindex_config_rec * autoindex_conf) +{ + char *title_name = ap_escape_html(r->pool, r->uri); + char *title_endp; + char *name = r->filename; + + DIR *d; + struct DIR_TYPE *dstruct; + int num_ent = 0, x; + struct ent *head, *p; + struct ent **ar = NULL; + char *tmp; + const char *qstring; + int autoindex_opts = find_opts(autoindex_conf, r); + char keyid; + char direction; + + if (!(d = ap_popendir(r->pool, name))) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "Can't open directory for index: %s", r->filename); + return HTTP_FORBIDDEN; + } + + r->content_type = "text/html"; + + ap_send_http_header(r); + + if (r->header_only) { + ap_pclosedir(r->pool, d); + return 0; + } + ap_hard_timeout("send directory", r); + + /* Spew HTML preamble */ + + title_endp = title_name + strlen(title_name) - 1; + + while (title_endp > title_name && *title_endp == '/') + *title_endp-- = '\0'; + + if ((!(tmp = find_header(autoindex_conf, r))) + || (!(insert_readme(name, tmp, title_name, NO_HRULE, FRONT_MATTER, r))) + ) { + emit_preamble(r, title_name); + ap_rvputs(r, "<H1>Index of ", title_name, "</H1>\n", NULL); + } + + /* + * Figure out what sort of indexing (if any) we're supposed to use. + */ + if (autoindex_opts & SUPPRESS_COLSORT) { + keyid = K_NAME; + direction = D_ASCENDING; + } + else { + qstring = r->args; + + /* + * If no QUERY_STRING was specified, we use the default: ascending + * by name. + */ + if ((qstring == NULL) || (*qstring == '\0')) { + keyid = K_NAME; + direction = D_ASCENDING; + } + else { + keyid = *qstring; + ap_getword(r->pool, &qstring, '='); + if (qstring != '\0') { + direction = *qstring; + } + else { + direction = D_ASCENDING; + } + } + } + + /* + * Since we don't know how many dir. entries there are, put them into a + * linked list and then arrayificate them so qsort can use them. + */ + head = NULL; + while ((dstruct = readdir(d))) { + p = make_autoindex_entry(dstruct->d_name, autoindex_opts, + autoindex_conf, r, keyid, direction); + if (p != NULL) { + p->next = head; + head = p; + num_ent++; + } + } + if (num_ent > 0) { + ar = (struct ent **) ap_palloc(r->pool, num_ent * sizeof(struct ent *)); + p = head; + x = 0; + while (p) { + ar[x++] = p; + p = p->next; + } + + qsort((void *) ar, num_ent, sizeof(struct ent *), + (int (*)(const void *, const void *)) dsortf); + } + output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid, + direction); + ap_pclosedir(r->pool, d); + + if ((tmp = find_readme(autoindex_conf, r))) { + if (!insert_readme(name, tmp, "", + ((autoindex_opts & FANCY_INDEXING) ? HRULE : NO_HRULE), + END_MATTER, r)) { + ap_rputs(ap_psignature("<HR>\n", r), r); + } + } + ap_rputs("</BODY></HTML>\n", r); + + ap_kill_timeout(r); + return 0; +} + +/* The formal handler... */ + +static int handle_autoindex(request_rec *r) +{ + autoindex_config_rec *d = + (autoindex_config_rec *) ap_get_module_config(r->per_dir_config, + &autoindex_module); + int allow_opts = ap_allow_options(r); + + r->allowed |= (1 << M_GET); + if (r->method_number != M_GET) + return DECLINED; + + /* OK, nothing easy. Trot out the heavy artillery... */ + + if (allow_opts & OPT_INDEXES) { + /* KLUDGE --- make the sub_req lookups happen in the right directory. + * Fixing this in the sub_req_lookup functions themselves is difficult, + * and would probably break virtual includes... + */ + + if (r->filename[strlen(r->filename) - 1] != '/') { + r->filename = ap_pstrcat(r->pool, r->filename, "/", NULL); + } + return index_directory(r, d); + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Directory index forbidden by rule: %s", r->filename); + return HTTP_FORBIDDEN; + } +} + + +static const handler_rec autoindex_handlers[] = +{ + {DIR_MAGIC_TYPE, handle_autoindex}, + {NULL} +}; + +module MODULE_VAR_EXPORT autoindex_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_autoindex_config, /* dir config creater */ + merge_autoindex_configs, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + autoindex_cmds, /* command table */ + autoindex_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_cern_meta.c b/APACHE_1_3b7/src/modules/standard/mod_cern_meta.c new file mode 100644 index 0000000000..ab530ddca5 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_cern_meta.c @@ -0,0 +1,387 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 + * IT'S 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_cern_meta.c + * version 0.1.0 + * status beta + * + * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 25.Jan.96 + * + * *** IMPORTANT *** + * This version of mod_cern_meta.c controls Meta File behaviour on a + * per-directory basis. Previous versions of the module defined behaviour + * on a per-server basis. The upshot is that you'll need to revisit your + * configuration files in order to make use of the new module. + * *** + * + * Emulate the CERN HTTPD Meta file semantics. Meta files are HTTP + * headers that can be output in addition to the normal range of + * headers for each file accessed. They appear rather like the Apache + * .asis files, and are able to provide a crude way of influencing + * the Expires: header, as well as providing other curiosities. + * There are many ways to manage meta information, this one was + * chosen because there is already a large number of CERN users + * who can exploit this module. It should be noted that there are probably + * more sensitive ways of managing the Expires: header specifically. + * + * The module obeys the following directives, which can appear + * in the server's .conf files and in .htaccess files. + * + * MetaFiles <on|off> + * + * turns on|off meta file processing for any directory. + * Default value is off + * + * # turn on MetaFiles in this directory + * MetaFiles on + * + * MetaDir <directory name> + * + * specifies the name of the directory in which Apache can find + * meta information files. The directory is usually a 'hidden' + * subdirectory of the directory that contains the file being + * accessed. eg: + * + * # .meta files are in the *same* directory as the + * # file being accessed + * MetaDir . + * + * the default is to look in a '.web' subdirectory. This is the + * same as for CERN 3.+ webservers and behaviour is the same as + * for the directive: + * + * MetaDir .web + * + * MetaSuffix <meta file suffix> + * + * specifies the file name suffix for the file containing the + * meta information. eg: + * + * # our meta files are suffixed with '.cern_meta' + * MetaSuffix .cern_meta + * + * the default is to look for files with the suffix '.meta'. This + * behaviour is the same as for the directive: + * + * MetaSuffix .meta + * + * When accessing the file + * + * DOCUMENT_ROOT/somedir/index.html + * + * this module will look for the file + * + * DOCUMENT_ROOT/somedir/.web/index.html.meta + * + * and will use its contents to generate additional MIME header + * information. + * + * For more information on the CERN Meta file semantics see: + * + * http://www.w3.org/hypertext/WWW/Daemon/User/Config/General.html#MetaDir + * + * Change-log: + * 29.Jan.96 pfopen/pfclose instead of fopen/fclose + * DECLINE when real file not found, we may be checking each + * of the index.html/index.shtml/index.htm variants and don't + * need to report missing ones as spurious errors. + * 31.Jan.96 log_error reports about a malformed .meta file, rather + * than a script error. + * 20.Jun.96 MetaFiles <on|off> default off, added, so that module + * can be configured per-directory. Prior to this the module + * was running for each request anywhere on the server, naughty.. + * 29.Jun.96 All directives made per-directory. + */ + +#include "httpd.h" +#include "http_config.h" +#include <sys/types.h> +#include <sys/stat.h> +#include "util_script.h" +#include "http_log.h" +#include "http_request.h" + +#define DIR_CMD_PERMS OR_INDEXES + +#define DEFAULT_METADIR ".web" +#define DEFAULT_METASUFFIX ".meta" +#define DEFAULT_METAFILES 0 + +module MODULE_VAR_EXPORT cern_meta_module; + +typedef struct { + char *metadir; + char *metasuffix; + char *metafiles; +} cern_meta_dir_config; + +static void *create_cern_meta_dir_config(pool *p, char *dummy) +{ + cern_meta_dir_config *new = + (cern_meta_dir_config *) ap_palloc(p, sizeof(cern_meta_dir_config)); + + new->metadir = NULL; + new->metasuffix = NULL; + new->metafiles = DEFAULT_METAFILES; + + return new; +} + +static void *merge_cern_meta_dir_configs(pool *p, void *basev, void *addv) +{ + cern_meta_dir_config *base = (cern_meta_dir_config *) basev; + cern_meta_dir_config *add = (cern_meta_dir_config *) addv; + cern_meta_dir_config *new = + (cern_meta_dir_config *) ap_palloc(p, sizeof(cern_meta_dir_config)); + + new->metadir = add->metadir ? add->metadir : base->metadir; + new->metasuffix = add->metasuffix ? add->metasuffix : base->metasuffix; + new->metafiles = add->metafiles; + + return new; +} + +static const char *set_metadir(cmd_parms *parms, cern_meta_dir_config * dconf, char *arg) +{ + dconf->metadir = arg; + return NULL; +} + +static const char *set_metasuffix(cmd_parms *parms, cern_meta_dir_config * dconf, char *arg) +{ + dconf->metasuffix = arg; + return NULL; +} + +static const char *set_metafiles(cmd_parms *parms, cern_meta_dir_config * dconf, char *arg) +{ + dconf->metafiles = arg; + return NULL; +} + + +static const command_rec cern_meta_cmds[] = +{ + {"MetaFiles", set_metafiles, NULL, DIR_CMD_PERMS, FLAG, NULL}, + {"MetaDir", set_metadir, NULL, DIR_CMD_PERMS, TAKE1, + "the name of the directory containing meta files"}, + {"MetaSuffix", set_metasuffix, NULL, DIR_CMD_PERMS, TAKE1, + "the filename suffix for meta files"}, + {NULL} +}; + +static int scan_meta_file(request_rec *r, FILE *f) +{ + char w[MAX_STRING_LEN]; + char *l; + int p; + + while (fgets(w, MAX_STRING_LEN - 1, f) != NULL) { + + /* Delete terminal (CR?)LF */ + + p = strlen(w); + if (p > 0 && w[p - 1] == '\n') { + if (p > 1 && w[p - 2] == '\015') + w[p - 2] = '\0'; + else + w[p - 1] = '\0'; + } + + if (w[0] == '\0') { + return OK; + } + + /* if we see a bogus header don't ignore it. Shout and scream */ + + if (!(l = strchr(w, ':'))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "malformed header in meta file: %s", r->filename); + return SERVER_ERROR; + } + + *l++ = '\0'; + while (*l && isspace(*l)) + ++l; + + if (!strcasecmp(w, "Content-type")) { + + /* Nuke trailing whitespace */ + + char *endp = l + strlen(l) - 1; + while (endp > l && isspace(*endp)) + *endp-- = '\0'; + + r->content_type = ap_pstrdup(r->pool, l); + ap_str_tolower(r->content_type); + } + else if (!strcasecmp(w, "Status")) { + sscanf(l, "%d", &r->status); + r->status_line = ap_pstrdup(r->pool, l); + } + else { + ap_table_set(r->headers_out, w, l); + } + } + return OK; +} + +static int add_cern_meta_data(request_rec *r) +{ + char *metafilename; + char *last_slash; + char *real_file; + char *scrap_book; + FILE *f; + cern_meta_dir_config *dconf; + int rv; + request_rec *rr; + + dconf = ap_get_module_config(r->per_dir_config, &cern_meta_module); + + if (!dconf->metafiles) { + return DECLINED; + }; + + /* if ./.web/$1.meta exists then output 'asis' */ + + if (r->finfo.st_mode == 0) { + return DECLINED; + }; + + /* is this a directory? */ + if (S_ISDIR(r->finfo.st_mode) || r->uri[strlen(r->uri) - 1] == '/') { + return DECLINED; + }; + + /* what directory is this file in? */ + scrap_book = ap_pstrdup(r->pool, r->filename); + /* skip leading slash, recovered in later processing */ + scrap_book++; + last_slash = strrchr(scrap_book, '/'); + if (last_slash != NULL) { + /* skip over last slash */ + real_file = last_slash; + real_file++; + *last_slash = '\0'; + } + else { + /* no last slash, buh?! */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "internal error in mod_cern_meta: %s", r->filename); + /* should really barf, but hey, let's be friends... */ + return DECLINED; + }; + + metafilename = ap_pstrcat(r->pool, "/", scrap_book, "/", + dconf->metadir ? dconf->metadir : DEFAULT_METADIR, + "/", real_file, + dconf->metasuffix ? dconf->metasuffix : DEFAULT_METASUFFIX, + NULL); + + /* XXX: it sucks to require this subrequest to complete, because this + * means people must leave their meta files accessible to the world. + * A better solution might be a "safe open" feature of pfopen to avoid + * pipes, symlinks, and crap like that. + */ + rr = ap_sub_req_lookup_file(metafilename, r); + if (rr->status != HTTP_OK) { + ap_destroy_sub_req(rr); + return DECLINED; + } + ap_destroy_sub_req(rr); + + f = ap_pfopen(r->pool, metafilename, "r"); + if (f == NULL) { + if (errno == ENOENT) { + return DECLINED; + } + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "meta file permissions deny server access: %s", metafilename); + return FORBIDDEN; + }; + + /* read the headers in */ + rv = scan_meta_file(r, f); + ap_pfclose(r->pool, f); + + return rv; +} + +module MODULE_VAR_EXPORT cern_meta_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_cern_meta_dir_config, /* dir config creater */ + merge_cern_meta_dir_configs, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server configs */ + cern_meta_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + add_cern_meta_data, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_cgi.c b/APACHE_1_3b7/src/modules/standard/mod_cgi.c new file mode 100644 index 0000000000..8c8d6584f6 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_cgi.c @@ -0,0 +1,593 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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/>. + * + */ + +/* + * http_script: keeps all script-related ramblings together. + * + * Compliant to CGI/1.1 spec + * + * Adapted by rst from original NCSA code by Rob McCool + * + * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for + * custom error responses, and DOCUMENT_ROOT because we found it useful. + * It also adds SERVER_ADMIN - useful for scripts to know who to mail when + * they fail. + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_main.h" +#include "http_log.h" +#include "util_script.h" +#include "http_conf_globals.h" + +module MODULE_VAR_EXPORT cgi_module; + +/* KLUDGE --- for back-combatibility, we don't have to check ExecCGI + * in ScriptAliased directories, which means we need to know if this + * request came through ScriptAlias or not... so the Alias module + * leaves a note for us. + */ + +static int is_scriptaliased(request_rec *r) +{ + char *t = ap_table_get(r->notes, "alias-forced-type"); + return t && (!strcasecmp(t, "cgi-script")); +} + +/* Configuration stuff */ + +#define DEFAULT_LOGBYTES 10385760 +#define DEFAULT_BUFBYTES 1024 + +typedef struct { + char *logname; + long logbytes; + int bufbytes; +} cgi_server_conf; + +static void *create_cgi_config(pool *p, server_rec *s) +{ + cgi_server_conf *c = + (cgi_server_conf *) ap_pcalloc(p, sizeof(cgi_server_conf)); + + c->logname = NULL; + c->logbytes = DEFAULT_LOGBYTES; + c->bufbytes = DEFAULT_BUFBYTES; + + return c; +} + +static void *merge_cgi_config(pool *p, void *basev, void *overridesv) +{ + cgi_server_conf *base = (cgi_server_conf *) basev, *overrides = (cgi_server_conf *) overridesv; + + return overrides->logname ? overrides : base; +} + +static const char *set_scriptlog(cmd_parms *cmd, void *dummy, char *arg) +{ + server_rec *s = cmd->server; + cgi_server_conf *conf = + (cgi_server_conf *) ap_get_module_config(s->module_config, &cgi_module); + + conf->logname = arg; + return NULL; +} + +static const char *set_scriptlog_length(cmd_parms *cmd, void *dummy, char *arg) +{ + server_rec *s = cmd->server; + cgi_server_conf *conf = + (cgi_server_conf *) ap_get_module_config(s->module_config, &cgi_module); + + conf->logbytes = atol(arg); + return NULL; +} + +static const char *set_scriptlog_buffer(cmd_parms *cmd, void *dummy, char *arg) +{ + server_rec *s = cmd->server; + cgi_server_conf *conf = + (cgi_server_conf *) ap_get_module_config(s->module_config, &cgi_module); + + conf->bufbytes = atoi(arg); + return NULL; +} + +static const command_rec cgi_cmds[] = +{ + {"ScriptLog", set_scriptlog, NULL, RSRC_CONF, TAKE1, + "the name of a log for script debugging info"}, + {"ScriptLogLength", set_scriptlog_length, NULL, RSRC_CONF, TAKE1, + "the maximum length (in bytes) of the script debug log"}, + {"ScriptLogBuffer", set_scriptlog_buffer, NULL, RSRC_CONF, TAKE1, + "the maximum size (in bytes) to record of a POST request"}, + {NULL} +}; + +static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret, + int show_errno, char *error) +{ + FILE *f; + struct stat finfo; + + ap_log_error(APLOG_MARK, show_errno|APLOG_ERR, r->server, + "%s: %s", error, r->filename); + + if (!conf->logname || + ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0) + && (finfo.st_size > conf->logbytes)) || + ((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname), + "a")) == NULL)) { + return ret; + } + + /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */ + fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri, + r->args ? "?" : "", r->args ? r->args : "", r->protocol); + /* "%% 500 /usr/local/apache/cgi-bin */ + fprintf(f, "%%%% %d %s\n", ret, r->filename); + + fprintf(f, "%%error\n%s\n", error); + + ap_pfclose(r->pool, f); + return ret; +} + +static int log_script(request_rec *r, cgi_server_conf * conf, int ret, + char *dbuf, char *sbuf, BUFF *script_in, BUFF *script_err) +{ + array_header *hdrs_arr = table_elts(r->headers_in); + table_entry *hdrs = (table_entry *) hdrs_arr->elts; + char argsbuffer[HUGE_STRING_LEN]; + FILE *f; + int i; + struct stat finfo; + + if (!conf->logname || + ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0) + && (finfo.st_size > conf->logbytes)) || + ((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname), + "a")) == NULL)) { + /* Soak up script output */ + while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) + continue; + while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) + continue; + return ret; + } + + /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */ + fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri, + r->args ? "?" : "", r->args ? r->args : "", r->protocol); + /* "%% 500 /usr/local/apache/cgi-bin" */ + fprintf(f, "%%%% %d %s\n", ret, r->filename); + + fputs("%request\n", f); + for (i = 0; i < hdrs_arr->nelts; ++i) { + if (!hdrs[i].key) + continue; + fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val); + } + if ((r->method_number == M_POST || r->method_number == M_PUT) + && *dbuf) { + fprintf(f, "\n%s\n", dbuf); + } + + fputs("%response\n", f); + hdrs_arr = table_elts(r->err_headers_out); + hdrs = (table_entry *) hdrs_arr->elts; + + for (i = 0; i < hdrs_arr->nelts; ++i) { + if (!hdrs[i].key) + continue; + fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val); + } + + if (sbuf && *sbuf) + fprintf(f, "%s\n", sbuf); + + if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) { + fputs("%stdout\n", f); + fputs(argsbuffer, f); + while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) + fputs(argsbuffer, f); + fputs("\n", f); + } + + if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) { + fputs("%stderr\n", f); + fputs(argsbuffer, f); + while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) + fputs(argsbuffer, f); + fputs("\n", f); + } + + ap_bclose(script_in); + ap_bclose(script_err); + + ap_pfclose(r->pool, f); + return ret; +} + +/**************************************************************** + * + * Actual CGI handling... + */ + + +struct cgi_child_stuff { + request_rec *r; + int nph; + int debug; + char *argv0; +}; + +static int cgi_child(void *child_stuff, child_info *pinfo) +{ + struct cgi_child_stuff *cld = (struct cgi_child_stuff *) child_stuff; + request_rec *r = cld->r; + char *argv0 = cld->argv0; + int child_pid; + +#ifdef DEBUG_CGI +#ifdef __EMX__ + /* Under OS/2 need to use device con. */ + FILE *dbg = fopen("con", "w"); +#else + FILE *dbg = fopen("/dev/tty", "w"); +#endif + int i; +#endif + + char **env; + + RAISE_SIGSTOP(CGI_CHILD); +#ifdef DEBUG_CGI + fprintf(dbg, "Attempting to exec %s as %sCGI child (argv0 = %s)\n", + r->filename, cld->nph ? "NPH " : "", argv0); +#endif + + ap_add_cgi_vars(r); + env = ap_create_environment(r->pool, r->subprocess_env); + +#ifdef DEBUG_CGI + fprintf(dbg, "Environment: \n"); + for (i = 0; env[i]; ++i) + fprintf(dbg, "'%s'\n", env[i]); +#endif + +#ifndef WIN32 + ap_chdir_file(r->filename); +#endif + if (!cld->debug) + ap_error_log2stderr(r->server); + + /* Transumute outselves into the script. + * NB only ISINDEX scripts get decoded arguments. + */ + + ap_cleanup_for_exec(); + + child_pid = ap_call_exec(r, pinfo, argv0, env, 0); +#ifdef WIN32 + return (child_pid); +#else + + /* Uh oh. Still here. Where's the kaboom? There was supposed to be an + * EARTH-shattering kaboom! + * + * Oh, well. Muddle through as best we can... + * + * Note that only stderr is available at this point, so don't pass in + * a server to aplog_error. + */ + + ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "exec of %s failed", r->filename); + exit(0); + /* NOT REACHED */ + return (0); +#endif +} + +static int cgi_handler(request_rec *r) +{ + int retval, nph, dbpos = 0; + char *argv0, *dbuf = NULL; + BUFF *script_out, *script_in, *script_err; + char argsbuffer[HUGE_STRING_LEN]; + int is_included = !strcmp(r->protocol, "INCLUDED"); + void *sconf = r->server->module_config; + cgi_server_conf *conf = + (cgi_server_conf *) ap_get_module_config(sconf, &cgi_module); + + struct cgi_child_stuff cld; + + if (r->method_number == M_OPTIONS) { + /* 99 out of 100 CGI scripts, this is all they support */ + r->allowed |= (1 << M_GET); + r->allowed |= (1 << M_POST); + return DECLINED; + } + + if ((argv0 = strrchr(r->filename, '/')) != NULL) + argv0++; + else + argv0 = r->filename; + + nph = !(strncmp(argv0, "nph-", 4)); + + if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r)) + return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO, + "Options ExecCGI is off in this directory"); + if (nph && is_included) + return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO, + "attempt to include NPH CGI script"); + +#if defined(__EMX__) || defined(WIN32) + /* Allow for cgi files without the .EXE extension on them under OS/2 */ + if (r->finfo.st_mode == 0) { + struct stat statbuf; + + r->filename = ap_pstrcat(r->pool, r->filename, ".EXE", NULL); + + if ((stat(r->filename, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode))) { + return log_scripterror(r, conf, NOT_FOUND, 0, + "script not found or unable to stat"); + } + } +#else + if (r->finfo.st_mode == 0) + return log_scripterror(r, conf, NOT_FOUND, APLOG_NOERRNO, + "script not found or unable to stat"); +#endif + if (S_ISDIR(r->finfo.st_mode)) + return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO, + "attempt to invoke directory as script"); + if (!ap_suexec_enabled) { + if (!ap_can_exec(&r->finfo)) + return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO, + "file permissions deny server execution"); + } + + if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) + return retval; + + ap_add_common_vars(r); + cld.argv0 = argv0; + cld.r = r; + cld.nph = nph; + cld.debug = conf->logname ? 1 : 0; + +#ifdef CHARSET_EBCDIC + /* XXX:@@@ Is the generated/included output ALWAYS in text/ebcdic format? */ + /* Or must we check the Content-Type first? */ + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1); +#endif /*CHARSET_EBCDIC*/ + + /* + * we spawn out of r->main if it's there so that we can avoid + * waiting for free_proc_chain to cleanup in the middle of an + * SSI request -djg + */ + if (!ap_spawn_child_err_buff(r->main ? r->main->pool : r->pool, cgi_child, + (void *) &cld, + kill_after_timeout, + &script_out, &script_in, &script_err)) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "couldn't spawn child process: %s", r->filename); + return SERVER_ERROR; + } + + /* Transfer any put/post args, CERN style... + * Note that if a buggy script fails to read everything we throw + * at it, or a buggy client sends too much, we get a SIGPIPE, so + * we have to ignore SIGPIPE while doing this. CERN does the same + * (and in fact, they pretty nearly guarantee themselves a SIGPIPE + * on every invocation by chasing the real client data with a + * spurious newline). + */ + + if (ap_should_client_block(r)) { + void (*handler) (int); + int dbsize, len_read; + + if (conf->logname) { + dbuf = ap_pcalloc(r->pool, conf->bufbytes + 1); + dbpos = 0; + } + + ap_hard_timeout("copy script args", r); +#ifdef SIGPIPE + handler = signal(SIGPIPE, SIG_IGN); +#endif + + while ((len_read = + ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)) > 0) { + if (conf->logname) { + if ((dbpos + len_read) > conf->bufbytes) { + dbsize = conf->bufbytes - dbpos; + } + else { + dbsize = len_read; + } + memcpy(dbuf + dbpos, argsbuffer, dbsize); + dbpos += dbsize; + } + ap_reset_timeout(r); + if (ap_bwrite(script_out, argsbuffer, len_read) < len_read) { + /* silly script stopped reading, soak up remaining message */ + while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0) { + /* dump it */ + } + break; + } + } + + ap_bflush(script_out); + signal(SIGPIPE, handler); + + ap_kill_timeout(r); + } + + ap_bclose(script_out); + + /* Handle script return... */ + if (script_in && !nph) { + char *location, sbuf[MAX_STRING_LEN]; + int ret; + + if ((ret = ap_scan_script_header_err_buff(r, script_in, sbuf))) { + return log_script(r, conf, ret, dbuf, sbuf, script_in, script_err); + } + +#ifdef CHARSET_EBCDIC + /* Now check the Content-Type to decide if conversion is needed */ + ap_checkconv(r); +#endif /*CHARSET_EBCDIC*/ + + location = ap_table_get(r->headers_out, "Location"); + + if (location && location[0] == '/' && r->status == 200) { + + /* Soak up all the script output */ + ap_hard_timeout("read from script", r); + while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) { + continue; + } + while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) { + continue; + } + ap_kill_timeout(r); + + + /* This redirect needs to be a GET no matter what the original + * method was. + */ + r->method = ap_pstrdup(r->pool, "GET"); + r->method_number = M_GET; + + /* We already read the message body (if any), so don't allow + * the redirected request to think it has one. We can ignore + * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR. + */ + ap_table_unset(r->headers_in, "Content-Length"); + + ap_internal_redirect_handler(location, r); + return OK; + } + else if (location && r->status == 200) { + /* XX Note that if a script wants to produce its own Redirect + * body, it now has to explicitly *say* "Status: 302" + */ + return REDIRECT; + } + + ap_send_http_header(r); + if (!r->header_only) { + ap_send_fb(script_in, r); + } + ap_bclose(script_in); + + ap_soft_timeout("soaking script stderr", r); + while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) { + continue; + } + ap_kill_timeout(r); + ap_bclose(script_err); + } + + if (script_in && nph) { + ap_send_fb(script_in, r); + } + + return OK; /* NOT r->status, even if it has changed. */ +} + +static const handler_rec cgi_handlers[] = +{ + {CGI_MAGIC_TYPE, cgi_handler}, + {"cgi-script", cgi_handler}, + {NULL} +}; + +module MODULE_VAR_EXPORT cgi_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + create_cgi_config, /* server config */ + merge_cgi_config, /* merge server config */ + cgi_cmds, /* command table */ + cgi_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_digest.c b/APACHE_1_3b7/src/modules/standard/mod_digest.c new file mode 100644 index 0000000000..742ca32e69 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_digest.c @@ -0,0 +1,387 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_digest: MD5 digest authentication + * + * by Alexei Kosut <akosut@nueva.pvt.k12.ca.us> + * based on mod_auth, by Rob McCool and Robert S. Thau + * + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "util_md5.h" + +typedef struct digest_config_struct { + char *pwfile; +} digest_config_rec; + +typedef struct digest_header_struct { + char *username; + char *realm; + char *nonce; + char *requested_uri; + char *digest; +} digest_header_rec; + +static void *create_digest_dir_config(pool *p, char *d) +{ + return ap_pcalloc(p, sizeof(digest_config_rec)); +} + +static const char *set_digest_slot(cmd_parms *cmd, void *offset, char *f, char *t) +{ + if (t && strcmp(t, "standard")) + return ap_pstrcat(cmd->pool, "Invalid auth file type: ", t, NULL); + + return ap_set_string_slot(cmd, offset, f); +} + +static const command_rec digest_cmds[] = +{ + {"AuthDigestFile", set_digest_slot, + (void *) XtOffsetOf(digest_config_rec, pwfile), OR_AUTHCFG, TAKE12, NULL}, + {NULL} +}; + +module MODULE_VAR_EXPORT digest_module; + +static char *get_hash(request_rec *r, char *user, char *auth_pwfile) +{ + configfile_t *f; + char l[MAX_STRING_LEN]; + const char *rpw; + char *w, *x; + + if (!(f = ap_pcfg_openfile(r->pool, auth_pwfile))) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "Could not open password file: %s", auth_pwfile); + return NULL; + } + while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { + if ((l[0] == '#') || (!l[0])) + continue; + rpw = l; + w = ap_getword(r->pool, &rpw, ':'); + x = ap_getword(r->pool, &rpw, ':'); + + if (x && w && !strcmp(user, w) && !strcmp(ap_auth_name(r), x)) { + ap_cfg_closefile(f); + return ap_pstrdup(r->pool, rpw); + } + } + ap_cfg_closefile(f); + return NULL; +} + +/* Parse the Authorization header, if it exists */ + +static int get_digest_rec(request_rec *r, digest_header_rec * response) +{ + const char *auth_line = ap_table_get(r->headers_in, + r->proxyreq ? "Proxy-Authorization" + : "Authorization"); + int l; + int s, vk = 0, vv = 0; + char *t, *key, *value; + + if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest")) + return DECLINED; + + if (!ap_auth_name(r)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "need AuthName: %s", r->uri); + return SERVER_ERROR; + } + + if (!auth_line) { + ap_note_digest_auth_failure(r); + return AUTH_REQUIRED; + } + + if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Digest")) { + /* Client tried to authenticate using wrong auth scheme */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "client used wrong authentication scheme: %s", r->uri); + ap_note_digest_auth_failure(r); + return AUTH_REQUIRED; + } + + l = strlen(auth_line); + + /* Note we don't allocate l + 1 bytes for these deliberately, because + * there has to be at least one '=' character for either of these two + * new strings to be terminated. That takes care of the need for +1. + */ + key = ap_palloc(r->pool, l); + value = ap_palloc(r->pool, l); + + /* There's probably a better way to do this, but for the time being... */ + +#define D_KEY 0 +#define D_VALUE 1 +#define D_STRING 2 +#define D_EXIT -1 + + s = D_KEY; + while (s != D_EXIT) { + switch (s) { + case D_STRING: + if (auth_line[0] == '\"') { + s = D_VALUE; + } + else { + value[vv] = auth_line[0]; + vv++; + } + auth_line++; + break; + + case D_VALUE: + if (isalnum(auth_line[0])) { + value[vv] = auth_line[0]; + vv++; + } + else if (auth_line[0] == '\"') { + s = D_STRING; + } + else { + value[vv] = '\0'; + + if (!strcasecmp(key, "username")) + response->username = ap_pstrdup(r->pool, value); + else if (!strcasecmp(key, "realm")) + response->realm = ap_pstrdup(r->pool, value); + else if (!strcasecmp(key, "nonce")) + response->nonce = ap_pstrdup(r->pool, value); + else if (!strcasecmp(key, "uri")) + response->requested_uri = ap_pstrdup(r->pool, value); + else if (!strcasecmp(key, "response")) + response->digest = ap_pstrdup(r->pool, value); + + vv = 0; + s = D_KEY; + } + auth_line++; + break; + + case D_KEY: + if (isalnum(auth_line[0])) { + key[vk] = auth_line[0]; + vk++; + } + else if (auth_line[0] == '=') { + key[vk] = '\0'; + vk = 0; + s = D_VALUE; + } + auth_line++; + break; + } + + if (auth_line[-1] == '\0') + s = D_EXIT; + } + + if (!response->username || !response->realm || !response->nonce || + !response->requested_uri || !response->digest) { + ap_note_digest_auth_failure(r); + return AUTH_REQUIRED; + } + + r->connection->user = response->username; + r->connection->ap_auth_type = "Digest"; + + return OK; +} + +/* The actual MD5 code... whee */ + +static char *find_digest(request_rec *r, digest_header_rec * h, char *a1) +{ + return ap_md5(r->pool, + (unsigned char *)ap_pstrcat(r->pool, a1, ":", h->nonce, ":", + ap_md5(r->pool, + (unsigned char *)ap_pstrcat(r->pool, r->method, ":", + h->requested_uri, NULL)), + NULL)); +} + +/* These functions return 0 if client is OK, and proper error status + * if not... either AUTH_REQUIRED, if we made a check, and it failed, or + * SERVER_ERROR, if things are so totally confused that we couldn't + * figure out how to tell if the client is authorized or not. + * + * If they return DECLINED, and all other modules also decline, that's + * treated by the server core as a configuration error, logged and + * reported as such. + */ + +/* Determine user ID, and check if it really is that user, for HTTP + * basic authentication... + */ + +static int authenticate_digest_user(request_rec *r) +{ + digest_config_rec *sec = + (digest_config_rec *) ap_get_module_config(r->per_dir_config, + &digest_module); + digest_header_rec *response = ap_pcalloc(r->pool, sizeof(digest_header_rec)); + conn_rec *c = r->connection; + char *a1; + int res; + + if ((res = get_digest_rec(r, response))) + return res; + + if (!sec->pwfile) + return DECLINED; + + if (!(a1 = get_hash(r, c->user, sec->pwfile))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "user %s not found: %s", c->user, r->uri); + ap_note_digest_auth_failure(r); + return AUTH_REQUIRED; + } + if (strcmp(response->digest, find_digest(r, response, a1))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "user %s: password mismatch: %s", c->user, r->uri); + ap_note_digest_auth_failure(r); + return AUTH_REQUIRED; + } + return OK; +} + +/* Checking ID */ + +static int digest_check_auth(request_rec *r) +{ + char *user = r->connection->user; + int m = r->method_number; + int method_restricted = 0; + register int x; + const char *t; + char *w; + array_header *reqs_arr; + require_line *reqs; + + if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest")) + return DECLINED; + + reqs_arr = ap_requires(r); + /* If there is no "requires" directive, + * then any user will do. + */ + if (!reqs_arr) + return OK; + reqs = (require_line *) reqs_arr->elts; + + for (x = 0; x < reqs_arr->nelts; x++) { + + if (!(reqs[x].method_mask & (1 << m))) + continue; + + method_restricted = 1; + + t = reqs[x].requirement; + w = ap_getword(r->pool, &t, ' '); + if (!strcmp(w, "valid-user")) + return OK; + else if (!strcmp(w, "user")) { + while (t[0]) { + w = ap_getword_conf(r->pool, &t); + if (!strcmp(user, w)) + return OK; + } + } + else + return DECLINED; + } + + if (!method_restricted) + return OK; + + ap_note_digest_auth_failure(r); + return AUTH_REQUIRED; +} + +module MODULE_VAR_EXPORT digest_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_digest_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + digest_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + authenticate_digest_user, /* check_user_id */ + digest_check_auth, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_dir.c b/APACHE_1_3b7/src/modules/standard/mod_dir.c new file mode 100644 index 0000000000..972010a3e4 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_dir.c @@ -0,0 +1,246 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_dir.c: handle default index files, and trailing-/ redirects + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_request.h" +#include "http_protocol.h" +#include "http_log.h" +#include "http_main.h" +#include "util_script.h" + +module MODULE_VAR_EXPORT dir_module; + +typedef struct dir_config_struct { + array_header *index_names; +} dir_config_rec; + +#define DIR_CMD_PERMS OR_INDEXES + +static const char *add_index(cmd_parms *cmd, void *dummy, char *arg) +{ + dir_config_rec *d = dummy; + + if (!d->index_names) { + d->index_names = ap_make_array(cmd->pool, 2, sizeof(char *)); + } + *(char **)ap_push_array(d->index_names) = arg; + return NULL; +} + +static const command_rec dir_cmds[] = +{ + {"DirectoryIndex", add_index, NULL, + DIR_CMD_PERMS, ITERATE, + "a list of file names"}, + {NULL} +}; + +static void *create_dir_config(pool *p, char *dummy) +{ + dir_config_rec *new = + (dir_config_rec *) ap_pcalloc(p, sizeof(dir_config_rec)); + + new->index_names = NULL; + return (void *) new; +} + +static void *merge_dir_configs(pool *p, void *basev, void *addv) +{ + dir_config_rec *new = (dir_config_rec *) ap_pcalloc(p, sizeof(dir_config_rec)); + dir_config_rec *base = (dir_config_rec *) basev; + dir_config_rec *add = (dir_config_rec *) addv; + + new->index_names = add->index_names ? add->index_names : base->index_names; + return new; +} + +static int handle_dir(request_rec *r) +{ + dir_config_rec *d = + (dir_config_rec *) ap_get_module_config(r->per_dir_config, + &dir_module); + char *dummy_ptr[1]; + char **names_ptr; + int num_names; + int error_notfound = 0; + + if (r->uri[0] == '\0' || r->uri[strlen(r->uri) - 1] != '/') { + char *ifile; + if (r->args != NULL) + ifile = ap_pstrcat(r->pool, escape_uri(r->pool, r->uri), + "/", "?", r->args, NULL); + else + ifile = ap_pstrcat(r->pool, escape_uri(r->pool, r->uri), + "/", NULL); + + ap_table_setn(r->headers_out, "Location", + ap_construct_url(r->pool, ifile, r)); + return HTTP_MOVED_PERMANENTLY; + } + + /* KLUDGE --- make the sub_req lookups happen in the right directory. + * Fixing this in the sub_req_lookup functions themselves is difficult, + * and would probably break virtual includes... + */ + + if (r->filename[strlen(r->filename) - 1] != '/') { + r->filename = ap_pstrcat(r->pool, r->filename, "/", NULL); + } + + if (d->index_names) { + names_ptr = (char **)d->index_names->elts; + num_names = d->index_names->nelts; + } + else { + dummy_ptr[0] = DEFAULT_INDEX; + names_ptr = dummy_ptr; + num_names = 1; + } + + for (; num_names; ++names_ptr, --num_names) { + char *name_ptr = *names_ptr; + request_rec *rr = ap_sub_req_lookup_uri(name_ptr, r); + + if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) { + char *new_uri = escape_uri(r->pool, rr->uri); + + if (rr->args != NULL) + new_uri = ap_pstrcat(r->pool, new_uri, "?", rr->args, NULL); + else if (r->args != NULL) + new_uri = ap_pstrcat(r->pool, new_uri, "?", r->args, NULL); + + ap_destroy_sub_req(rr); + ap_internal_redirect(new_uri, r); + return OK; + } + + /* If the request returned a redirect, propagate it to the client */ + + if (is_HTTP_REDIRECT(rr->status) || + (rr->status == HTTP_NOT_ACCEPTABLE && num_names == 1)) { + + error_notfound = rr->status; + r->notes = ap_overlay_tables(r->pool, r->notes, rr->notes); + r->headers_out = ap_overlay_tables(r->pool, r->headers_out, + rr->headers_out); + r->err_headers_out = ap_overlay_tables(r->pool, r->err_headers_out, + rr->err_headers_out); + ap_destroy_sub_req(rr); + return error_notfound; + } + + /* If the request returned something other than 404 (or 200), + * it means the module encountered some sort of problem. To be + * secure, we should return the error, rather than create + * along a (possibly unsafe) directory index. + * + * So we store the error, and if none of the listed files + * exist, we return the last error response we got, instead + * of a directory listing. + */ + if (rr->status && rr->status != HTTP_NOT_FOUND && rr->status != HTTP_OK) + error_notfound = rr->status; + + ap_destroy_sub_req(rr); + } + + if (error_notfound) + return error_notfound; + + if (r->method_number != M_GET) + return DECLINED; + + /* nothing for us to do, pass on through */ + + return DECLINED; +} + + +static const handler_rec dir_handlers[] = +{ + {DIR_MAGIC_TYPE, handle_dir}, + {NULL} +}; + +module MODULE_VAR_EXPORT dir_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_dir_config, /* dir config creater */ + merge_dir_configs, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + dir_cmds, /* command table */ + dir_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_env.c b/APACHE_1_3b7/src/modules/standard/mod_env.c new file mode 100644 index 0000000000..f794d404e1 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_env.c @@ -0,0 +1,274 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 + * IT'S 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_env.c + * version 0.0.5 + * status beta + * Pass environment variables to CGI/SSI scripts. + * + * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 06.Dec.95 + * + * Change log: + * 08.Dec.95 Now allows PassEnv directive to appear more than once in + * conf files. + * 10.Dec.95 optimisation. getenv() only called at startup and used + * to build a fast-to-access table. table used to build + * per-server environment for each request. + * robustness. better able to handle errors in configuration + * files: + * 1) PassEnv directive present, but no environment variable listed + * 2) PassEnv FOO present, but $FOO not present in environment + * 3) no PassEnv directive present + * 23.Dec.95 Now allows SetEnv directive with same semantics as 'sh' setenv: + * SetEnv Var sets Var to the empty string + * SetEnv Var Val sets Var to the value Val + * Values containing whitespace should be quoted, eg: + * SetEnv Var "this is some text" + * Environment variables take their value from the last instance + * of PassEnv / SetEnv to be reached in the configuration file. + * For example, the sequence: + * PassEnv FOO + * SetEnv FOO override + * Causes FOO to take the value 'override'. + * 23.Feb.96 Added UnsetEnv directive to allow environment variables + * to be removed. + * Virtual hosts now 'inherit' parent server environment which + * they're able to overwrite with their own directives or + * selectively ignore with UnsetEnv. + * *** IMPORTANT - the way that virtual hosts inherit their *** + * *** environment variables from the default server's *** + * *** configuration has changed. You should test your *** + * *** configuration carefully before accepting this *** + * *** version of the module in a live webserver which used *** + * *** older versions of the module. *** + */ + +#include "httpd.h" +#include "http_config.h" + +typedef struct { + table *vars; + char *unsetenv; + int vars_present; +} env_server_config_rec; + +module MODULE_VAR_EXPORT env_module; + +static void *create_env_server_config(pool *p, server_rec *dummy) +{ + env_server_config_rec *new = + (env_server_config_rec *) ap_palloc(p, sizeof(env_server_config_rec)); + new->vars = ap_make_table(p, 50); + new->unsetenv = ""; + new->vars_present = 0; + return (void *) new; +} + +static void *merge_env_server_configs(pool *p, void *basev, void *addv) +{ + env_server_config_rec *base = (env_server_config_rec *) basev; + env_server_config_rec *add = (env_server_config_rec *) addv; + env_server_config_rec *new = + (env_server_config_rec *) ap_palloc(p, sizeof(env_server_config_rec)); + + table *new_table; + table_entry *elts; + array_header *arr; + + int i; + const char *uenv, *unset; + + /* + * new_table = copy_table( p, base->vars ); + * foreach $element ( @add->vars ) { + * table_set( new_table, $element.key, $element.val ); + * }; + * foreach $unsetenv ( @UNSETENV ) { + * table_unset( new_table, $unsetenv ); + * } + */ + + new_table = ap_copy_table(p, base->vars); + + arr = table_elts(add->vars); + elts = (table_entry *)arr->elts; + + for (i = 0; i < arr->nelts; ++i) { + ap_table_setn(new_table, elts[i].key, elts[i].val); + } + + unset = add->unsetenv; + uenv = ap_getword_conf(p, &unset); + while (uenv[0] != '\0') { + ap_table_unset(new_table, uenv); + uenv = ap_getword_conf(p, &unset); + } + + new->vars = new_table; + + new->vars_present = base->vars_present || add->vars_present; + + return new; +} + +static const char *add_env_module_vars_passed(cmd_parms *cmd, char *struct_ptr, + const char *arg) +{ + env_server_config_rec *sconf = + ap_get_module_config(cmd->server->module_config, &env_module); + table *vars = sconf->vars; + char *env_var; + char *name_ptr; + + while (*arg) { + name_ptr = ap_getword_conf(cmd->pool, &arg); + env_var = getenv(name_ptr); + if (env_var != NULL) { + sconf->vars_present = 1; + ap_table_setn(vars, name_ptr, ap_pstrdup(cmd->pool, env_var)); + } + } + return NULL; +} + +static const char *add_env_module_vars_set(cmd_parms *cmd, char *struct_ptr, + const char *arg) +{ + env_server_config_rec *sconf = + ap_get_module_config(cmd->server->module_config, &env_module); + table *vars = sconf->vars; + char *name, *value; + + name = ap_getword_conf(cmd->pool, &arg); + value = ap_getword_conf(cmd->pool, &arg); + + /* name is mandatory, value is optional. no value means + * set the variable to an empty string + */ + + + if ((*name == '\0') || (*arg != '\0')) { + return "SetEnv takes one or two arguments. An environment variable name and an optional value to pass to CGI."; + } + + sconf->vars_present = 1; + ap_table_setn(vars, name, value); + + return NULL; +} + +static const char *add_env_module_vars_unset(cmd_parms *cmd, char *struct_ptr, + char *arg) +{ + env_server_config_rec *sconf = + ap_get_module_config(cmd->server->module_config, &env_module); + sconf->unsetenv = sconf->unsetenv ? + ap_pstrcat(cmd->pool, sconf->unsetenv, " ", arg, NULL) : + arg; + return NULL; +} + +static const command_rec env_module_cmds[] = +{ + {"PassEnv", add_env_module_vars_passed, NULL, + RSRC_CONF, RAW_ARGS, "a list of environment variables to pass to CGI."}, + {"SetEnv", add_env_module_vars_set, NULL, + RSRC_CONF, RAW_ARGS, "an environment variable name and a value to pass to CGI."}, + {"UnsetEnv", add_env_module_vars_unset, NULL, + RSRC_CONF, RAW_ARGS, "a list of variables to remove from the CGI environment."}, + {NULL}, +}; + +static int fixup_env_module(request_rec *r) +{ + table *e = r->subprocess_env; + server_rec *s = r->server; + env_server_config_rec *sconf = ap_get_module_config(s->module_config, + &env_module); + table *vars = sconf->vars; + + if (!sconf->vars_present) + return DECLINED; + + r->subprocess_env = ap_overlay_tables(r->pool, e, vars); + + return OK; +} + +module MODULE_VAR_EXPORT env_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + create_env_server_config, /* server config */ + merge_env_server_configs, /* merge server configs */ + env_module_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + fixup_env_module, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_expires.c b/APACHE_1_3b7/src/modules/standard/mod_expires.c new file mode 100644 index 0000000000..05bc3e50fe --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_expires.c @@ -0,0 +1,507 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 + * IT'S 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_expires.c + * version 0.0.11 + * status beta + * + * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 26.Jan.96 + * + * This module allows you to control the form of the Expires: header + * that Apache issues for each access. Directives can appear in + * configuration files or in .htaccess files so expiry semantics can + * be defined on a per-directory basis. + * + * DIRECTIVE SYNTAX + * + * Valid directives are: + * + * ExpiresActive on | off + * ExpiresDefault <code><seconds> + * ExpiresByType type/encoding <code><seconds> + * + * Valid values for <code> are: + * + * 'M' expires header shows file modification date + <seconds> + * 'A' expires header shows access time + <seconds> + * + * [I'm not sure which of these is best under different + * circumstances, I guess it's for other people to explore. + * The effects may be indistinguishable for a number of cases] + * + * <seconds> should be an integer value [acceptable to atoi()] + * + * There is NO space between the <code> and <seconds>. + * + * For example, a directory which contains information which changes + * frequently might contain: + * + * # reports generated by cron every hour. don't let caches + * # hold onto stale information + * ExpiresDefault M3600 + * + * Another example, our html pages can change all the time, the gifs + * tend not to change often: + * + * # pages are hot (1 week), images are cold (1 month) + * ExpiresByType text/html A604800 + * ExpiresByType image/gif A2592000 + * + * Expires can be turned on for all URLs on the server by placing the + * following directive in a conf file: + * + * ExpiresActive on + * + * ExpiresActive can also appear in .htaccess files, enabling the + * behaviour to be turned on or off for each chosen directory. + * + * # turn off Expires behaviour in this directory + * # and subdirectories + * ExpiresActive off + * + * Directives defined for a directory are valid in subdirectories + * unless explicitly overridden by new directives in the subdirectory + * .htaccess files. + * + * ALTERNATIVE DIRECTIVE SYNTAX + * + * Directives can also be defined in a more readable syntax of the form: + * + * ExpiresDefault "<base> [plus] {<num> <type>}*" + * ExpiresByType type/encoding "<base> [plus] {<num> <type>}*" + * + * where <base> is one of: + * access + * now equivalent to 'access' + * modification + * + * where the 'plus' keyword is optional + * + * where <num> should be an integer value [acceptable to atoi()] + * + * where <type> is one of: + * years + * months + * weeks + * days + * hours + * minutes + * seconds + * + * For example, any of the following directives can be used to make + * documents expire 1 month after being accessed, by default: + * + * ExpiresDefault "access plus 1 month" + * ExpiresDefault "access plus 4 weeks" + * ExpiresDefault "access plus 30 days" + * + * The expiry time can be fine-tuned by adding several '<num> <type>' + * clauses: + * + * ExpiresByType text/html "access plus 1 month 15 days 2 hours" + * ExpiresByType image/gif "modification plus 5 hours 3 minutes" + * + * --- + * + * Change-log: + * 29.Jan.96 Hardened the add_* functions. Server will now bail out + * if bad directives are given in the conf files. + * 02.Feb.96 Returns DECLINED if not 'ExpiresActive on', giving other + * expires-aware modules a chance to play with the same + * directives. [Michael Rutman] + * 03.Feb.96 Call tzset() before localtime(). Trying to get the module + * to work properly in non GMT timezones. + * 12.Feb.96 Modified directive syntax to allow more readable commands: + * ExpiresDefault "now plus 10 days 20 seconds" + * ExpiresDefault "access plus 30 days" + * ExpiresDefault "modification plus 1 year 10 months 30 days" + * 13.Feb.96 Fix call to table_get() with NULL 2nd parameter [Rob Hartill] + * 19.Feb.96 Call gm_timestr_822() to get time formatted correctly, can't + * rely on presence of HTTP_TIME_FORMAT in Apache 1.1+. + * 21.Feb.96 This version (0.0.9) reverses assumptions made in 0.0.8 + * about star/star handlers. Reverting to 0.0.7 behaviour. + * 08.Jun.96 allows ExpiresDefault to be used with responses that use + * the DefaultType by not DECLINING, but instead skipping + * the table_get check and then looking for an ExpiresDefault. + * [Rob Hartill] + * 04.Nov.96 'const' definitions added. + * + * TODO + * add support for Cache-Control: max-age=20 from the HTTP/1.1 + * proposal (in this case, a ttl of 20 seconds) [ask roy] + * add per-file expiry and explicit expiry times - duplicates some + * of the mod_cern_meta.c functionality. eg: + * ExpiresExplicit index.html "modification plus 30 days" + * + * BUGS + * Hi, welcome to the internet. + */ + +#include <ctype.h> +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" + +typedef struct { + int active; + char *expiresdefault; + table *expiresbytype; +} expires_dir_config; + +/* from mod_dir, why is this alias used? + */ +#define DIR_CMD_PERMS OR_INDEXES + +#define ACTIVE_ON 1 +#define ACTIVE_OFF 0 +#define ACTIVE_DONTCARE 2 + +module MODULE_VAR_EXPORT expires_module; + +static void *create_dir_expires_config(pool *p, char *dummy) +{ + expires_dir_config *new = + (expires_dir_config *) ap_pcalloc(p, sizeof(expires_dir_config)); + new->active = ACTIVE_DONTCARE; + new->expiresdefault = ""; + new->expiresbytype = ap_make_table(p, 4); + return (void *) new; +} + +static const char *set_expiresactive(cmd_parms *cmd, expires_dir_config * dir_config, int arg) +{ + /* if we're here at all it's because someone explicitly + * set the active flag + */ + dir_config->active = ACTIVE_ON; + if (arg == 0) { + dir_config->active = ACTIVE_OFF; + }; + return NULL; +} + +/* check_code() parse 'code' and return NULL or an error response + * string. If we return NULL then real_code contains code converted + * to the cnnnn format. + */ +static char *check_code(pool *p, const char *code, char **real_code) +{ + char *word; + char base = 'X'; + int modifier = 0; + int num = 0; + int factor = 0; + + /* 0.0.4 compatibility? + */ + if ((code[0] == 'A') || (code[0] == 'M')) { + *real_code = (char *)code; + return NULL; + }; + + /* <base> [plus] {<num> <type>}* + */ + + /* <base> + */ + word = ap_getword_conf(p, &code); + if (!strncasecmp(word, "now", 1) || + !strncasecmp(word, "access", 1)) { + base = 'A'; + } + else if (!strncasecmp(word, "modification", 1)) { + base = 'M'; + } + else { + return ap_pstrcat(p, "bad expires code, unrecognised <base> '", + word, "'", NULL); + }; + + /* [plus] + */ + word = ap_getword_conf(p, &code); + if (!strncasecmp(word, "plus", 1)) { + word = ap_getword_conf(p, &code); + }; + + /* {<num> <type>}* + */ + while (word[0]) { + /* <num> + */ + if (isdigit(word[0])) { + num = atoi(word); + } + else { + return ap_pstrcat(p, "bad expires code, numeric value expected <num> '", + word, "'", NULL); + }; + + /* <type> + */ + word = ap_getword_conf(p, &code); + if (word[0]) { + /* do nothing */ + } + else { + return ap_pstrcat(p, "bad expires code, missing <type>", NULL); + }; + + factor = 0; + if (!strncasecmp(word, "years", 1)) { + factor = 60 * 60 * 24 * 365; + } + else if (!strncasecmp(word, "months", 2)) { + factor = 60 * 60 * 24 * 30; + } + else if (!strncasecmp(word, "weeks", 1)) { + factor = 60 * 60 * 24 * 7; + } + else if (!strncasecmp(word, "days", 1)) { + factor = 60 * 60 * 24; + } + else if (!strncasecmp(word, "hours", 1)) { + factor = 60 * 60; + } + else if (!strncasecmp(word, "minutes", 2)) { + factor = 60; + } + else if (!strncasecmp(word, "seconds", 1)) { + factor = 1; + } + else { + return ap_pstrcat(p, "bad expires code, unrecognised <type>", + "'", word, "'", NULL); + }; + + modifier = modifier + factor * num; + + /* next <num> + */ + word = ap_getword_conf(p, &code); + }; + + *real_code = ap_psprintf(p, "%c%d", base, modifier); + + return NULL; +} + +static const char *set_expiresbytype(cmd_parms *cmd, expires_dir_config * dir_config, char *mime, char *code) +{ + char *response, *real_code; + + if ((response = check_code(cmd->pool, code, &real_code)) == NULL) { + ap_table_setn(dir_config->expiresbytype, mime, real_code); + return NULL; + }; + return ap_pstrcat(cmd->pool, + "'ExpiresByType ", mime, " ", code, "': ", response, NULL); +} + +static const char *set_expiresdefault(cmd_parms *cmd, expires_dir_config * dir_config, char *code) +{ + char *response, *real_code; + + if ((response = check_code(cmd->pool, code, &real_code)) == NULL) { + dir_config->expiresdefault = real_code; + return NULL; + }; + return ap_pstrcat(cmd->pool, + "'ExpiresDefault ", code, "': ", response, NULL); +} + +static const command_rec expires_cmds[] = +{ + {"ExpiresActive", set_expiresactive, NULL, DIR_CMD_PERMS, FLAG, + "Limited to 'on' or 'off'"}, + {"ExpiresBytype", set_expiresbytype, NULL, DIR_CMD_PERMS, TAKE2, + "a MIME type followed by an expiry date code"}, + {"ExpiresDefault", set_expiresdefault, NULL, DIR_CMD_PERMS, TAKE1, + "an expiry date code"}, + {NULL} +}; + +static void *merge_expires_dir_configs(pool *p, void *basev, void *addv) +{ + expires_dir_config *new = (expires_dir_config *) ap_pcalloc(p, sizeof(expires_dir_config)); + expires_dir_config *base = (expires_dir_config *) basev; + expires_dir_config *add = (expires_dir_config *) addv; + + if (add->active == ACTIVE_DONTCARE) { + new->active = base->active; + } + else { + new->active = add->active; + }; + + if (add->expiresdefault != '\0') { + new->expiresdefault = add->expiresdefault; + }; + + new->expiresbytype = ap_overlay_tables(p, add->expiresbytype, + base->expiresbytype); + return new; +} + +static int add_expires(request_rec *r) +{ + expires_dir_config *conf; + char *code; + time_t base; + time_t additional; + time_t expires; + char age[20]; + + if (is_HTTP_ERROR(r->status)) /* Don't add Expires headers to errors */ + return DECLINED; + + if (r->main != NULL) /* Say no to subrequests */ + return DECLINED; + + if (r->finfo.st_mode == 0) /* no file ? shame. */ + return DECLINED; + + conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config, &expires_module); + if (conf == NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "internal error: %s", r->filename); + return SERVER_ERROR; + }; + + if (conf->active != ACTIVE_ON) + return DECLINED; + + /* we perhaps could use the default_type(r) in its place but that + * may be 2nd guesing the desired configuration... calling table_get + * with a NULL key will SEGV us + * + * I still don't know *why* r->content_type would ever be NULL, this + * is possibly a result of fixups being called in many different + * places. Fixups is probably the wrong place to be doing all this + * work... Bah. + * + * Changed as of 08.Jun.96 don't DECLINE, look for an ExpiresDefault. + */ + if (r->content_type == NULL) + code = NULL; + else + code = (char *) ap_table_get(conf->expiresbytype, r->content_type); + + if (code == NULL) { + /* no expires defined for that type, is there a default? */ + code = conf->expiresdefault; + + if (code[0] == '\0') + return OK; + }; + + /* we have our code */ + + switch (code[0]) { + case 'M': + base = r->finfo.st_mtime; + additional = atoi(&code[1]); + break; + case 'A': + /* there's been some discussion and it's possible that + * 'access time' will be stored in request structure + */ + base = r->request_time; + additional = atoi(&code[1]); + break; + default: + /* expecting the add_* routines to be case-hardened this + * is just a reminder that module is beta + */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "internal error: bad expires code: %s", r->filename); + return SERVER_ERROR; + }; + + expires = base + additional; + ap_snprintf(age, sizeof(age), "max-age=%d", (int) expires - (int) r->request_time); + ap_table_setn(r->headers_out, "Cache-Control", ap_pstrdup(r->pool, age)); + tzset(); /* redundant? called implicitly by localtime, at least + * under FreeBSD + */ + ap_table_setn(r->headers_out, "Expires", ap_gm_timestr_822(r->pool, expires)); + return OK; +} + +module MODULE_VAR_EXPORT expires_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_dir_expires_config, /* dir config creater */ + merge_expires_dir_configs, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server configs */ + expires_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + add_expires, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_headers.c b/APACHE_1_3b7/src/modules/standard/mod_headers.c new file mode 100644 index 0000000000..665182db46 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_headers.c @@ -0,0 +1,265 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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_headers.c: Add/append/remove HTTP response headers + * Written by Paul Sutton, paul@ukweb.com, 1 Oct 1996 + * + * New directive, Header, can be used to add/replace/remove HTTP headers. + * Valid in both per-server and per-dir configurations. + * + * Syntax is: + * + * Header action header value + * + * Where action is one of: + * set - set this header, replacing any old value + * add - add this header, possible resulting in two or more + * headers with the same name + * append - append this text onto any existing header of this same + * unset - remove this header + * + * Where action is unset, the third argument (value) should not be given. + * The header name can include the colon, or not. + * + * The Header directive can only be used where allowed by the FileInfo + * override. + * + * When the request is processed, the header directives are processed in + * this order: firstly, the main server, then the virtual server handling + * this request (if any), then any <Directory> sections (working downwards + * from the root dir), then an <Location> sections (working down from + * shortest URL component), the any <File> sections. This order is + * important if any 'set' or 'unset' actions are used. For example, + * the following two directives have different effect if applied in + * the reverse order: + * + * Header append Author "John P. Doe" + * Header unset Author + * + * Examples: + * + * To set the "Author" header, use + * Header add Author "John P. Doe" + * + * To remove a header: + * Header unset Author + * + */ + +#include "httpd.h" +#include "http_config.h" + +typedef enum { + hdr_add = 'a', /* add header (could mean multiple hdrs) */ + hdr_set = 's', /* set (replace old value) */ + hdr_append = 'm', /* append (merge into any old value) */ + hdr_unset = 'u' /* unset header */ +} hdr_actions; + +typedef struct { + hdr_actions action; + char *header; + char *value; +} header_entry; + +/* + * headers_conf is our per-module configuration. This is used as both + * a per-dir and per-server config + */ +typedef struct { + array_header *headers; +} headers_conf; + +module MODULE_VAR_EXPORT headers_module; + +static void *create_headers_config(pool *p, server_rec *s) +{ + headers_conf *a = + (headers_conf *) ap_pcalloc(p, sizeof(headers_conf)); + + a->headers = ap_make_array(p, 2, sizeof(header_entry)); + return a; +} + +static void *create_headers_dir_config(pool *p, char *d) +{ + return (headers_conf *) create_headers_config(p, NULL); +} + +static void *merge_headers_config(pool *p, void *basev, void *overridesv) +{ + headers_conf *a = + (headers_conf *) ap_pcalloc(p, sizeof(headers_conf)); + headers_conf *base = (headers_conf *) basev, *overrides = (headers_conf *) overridesv; + + a->headers = ap_append_arrays(p, base->headers, overrides->headers); + + return a; +} + + +static const char *header_cmd(cmd_parms *cmd, headers_conf * dirconf, char *action, char *hdr, char *value) +{ + header_entry *new; + server_rec *s = cmd->server; + headers_conf *serverconf = + (headers_conf *) ap_get_module_config(s->module_config, &headers_module); + char *colon; + + if (cmd->path) { + new = (header_entry *) ap_push_array(dirconf->headers); + } + else { + new = (header_entry *) ap_push_array(serverconf->headers); + } + + if (!strcasecmp(action, "set")) + new->action = hdr_set; + else if (!strcasecmp(action, "add")) + new->action = hdr_add; + else if (!strcasecmp(action, "append")) + new->action = hdr_append; + else if (!strcasecmp(action, "unset")) + new->action = hdr_unset; + else + return "first argument must be add, set, append or unset."; + + if (new->action == hdr_unset) { + if (value) + return "Header unset takes two arguments"; + } + else if (!value) + return "Header requires three arguments"; + + if ((colon = strchr(hdr, ':'))) + *colon = '\0'; + + new->header = hdr; + new->value = value; + + return NULL; +} + +static const command_rec headers_cmds[] = +{ + {"Header", header_cmd, NULL, OR_FILEINFO, TAKE23, + "an action, header and value"}, + {NULL} +}; + +static void do_headers_fixup(request_rec *r, array_header *headers) +{ + int i; + + for (i = 0; i < headers->nelts; ++i) { + header_entry *hdr = &((header_entry *) (headers->elts))[i]; + switch (hdr->action) { + case hdr_add: + ap_table_addn(r->headers_out, hdr->header, hdr->value); + break; + case hdr_append: + ap_table_mergen(r->headers_out, hdr->header, hdr->value); + break; + case hdr_set: + ap_table_setn(r->headers_out, hdr->header, hdr->value); + break; + case hdr_unset: + ap_table_unset(r->headers_out, hdr->header); + break; + } + } + +} + +static int fixup_headers(request_rec *r) +{ + void *sconf = r->server->module_config; + headers_conf *serverconf = + (headers_conf *) ap_get_module_config(sconf, &headers_module); + void *dconf = r->per_dir_config; + headers_conf *dirconf = + (headers_conf *) ap_get_module_config(dconf, &headers_module); + + do_headers_fixup(r, serverconf->headers); + do_headers_fixup(r, dirconf->headers); + + return DECLINED; +} + +module MODULE_VAR_EXPORT headers_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_headers_dir_config, /* dir config creater */ + merge_headers_config, /* dir merger --- default is to override */ + create_headers_config, /* server config */ + merge_headers_config, /* merge server configs */ + headers_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + fixup_headers, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_imap.c b/APACHE_1_3b7/src/modules/standard/mod_imap.c new file mode 100644 index 0000000000..49ced49083 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_imap.c @@ -0,0 +1,916 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 + * IT'S 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 imagemap module started as a port of the original imagemap.c + * written by Rob McCool (11/13/93 robm@ncsa.uiuc.edu). + * This version includes the mapping algorithms found in version 1.3 + * of imagemap.c. + * + * Contributors to this code include: + * + * Kevin Hughes, kevinh@pulua.hcc.hawaii.edu + * + * Eric Haines, erich@eye.com + * "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com + * + * Randy Terbush, randy@zyzzyva.com + * port to Apache module format, "base_uri" and support for relative URLs + * + * James H. Cloos, Jr., cloos@jhcloos.com + * Added point datatype, using code in NCSA's version 1.8 imagemap.c + * program, as distributed with version 1.4.1 of their server. + * The point code is originally added by Craig Milo Rogers, Rogers@ISI.Edu + * + * Nathan Kurz, nate@tripod.com + * Rewrite/reorganization. New handling of default, base and relative URLs. + * New Configuration directives: + * ImapMenu {none, formatted, semiformatted, unformatted} + * ImapDefault {error, nocontent, referer, menu, URL} + * ImapBase {map, referer, URL} + * Support for creating non-graphical menu added. (backwards compatible): + * Old: directive URL [x,y ...] + * New: directive URL "Menu text" [x,y ...] + * or: directive URL x,y ... "Menu text" + * Map format and menu concept courtesy Joshua Bell, jsbell@acs.ucalgary.ca. + * + * Mark Cox, mark@ukweb.com, Allow relative URLs even when no base specified + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_main.h" +#include "http_log.h" +#include "util_script.h" + +#define IMAP_MAGIC_TYPE "application/x-httpd-imap" +#define MAXVERTS 100 +#define X 0 +#define Y 1 + +#define IMAP_MENU_DEFAULT "formatted" +#define IMAP_DEFAULT_DEFAULT "nocontent" +#define IMAP_BASE_DEFAULT "map" + +#ifdef SUNOS4 +double strtod(); /* SunOS needed this */ +#endif + +module MODULE_VAR_EXPORT imap_module; + +typedef struct { + char *imap_menu; + char *imap_default; + char *imap_base; +} imap_conf_rec; + +static void *create_imap_dir_config(pool *p, char *dummy) +{ + imap_conf_rec *icr = + (imap_conf_rec *) ap_palloc(p, sizeof(imap_conf_rec)); + + icr->imap_menu = NULL; + icr->imap_default = NULL; + icr->imap_base = NULL; + + return icr; +} + +static void *merge_imap_dir_configs(pool *p, void *basev, void *addv) +{ + imap_conf_rec *new = (imap_conf_rec *) ap_pcalloc(p, sizeof(imap_conf_rec)); + imap_conf_rec *base = (imap_conf_rec *) basev; + imap_conf_rec *add = (imap_conf_rec *) addv; + + new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu; + new->imap_default = add->imap_default ? add->imap_default + : base->imap_default; + new->imap_base = add->imap_base ? add->imap_base : base->imap_base; + + return new; +} + + +static const command_rec imap_cmds[] = +{ + {"ImapMenu", ap_set_string_slot, + (void *) XtOffsetOf(imap_conf_rec, imap_menu), OR_INDEXES, TAKE1, + "the type of menu generated: none, formatted, semiformatted, unformatted"}, + {"ImapDefault", ap_set_string_slot, + (void *) XtOffsetOf(imap_conf_rec, imap_default), OR_INDEXES, TAKE1, + "the action taken if no match: error, nocontent, referer, menu, URL"}, + {"ImapBase", ap_set_string_slot, + (void *) XtOffsetOf(imap_conf_rec, imap_base), OR_INDEXES, TAKE1, + "the base for all URL's: map, referer, URL (or start of)"}, + {NULL} +}; + +static int pointinrect(const double point[2], double coords[MAXVERTS][2]) +{ + double max[2], min[2]; + if (coords[0][X] > coords[1][X]) { + max[0] = coords[0][X]; + min[0] = coords[1][X]; + } + else { + max[0] = coords[1][X]; + min[0] = coords[0][X]; + } + + if (coords[0][Y] > coords[1][Y]) { + max[1] = coords[0][Y]; + min[1] = coords[1][Y]; + } + else { + max[1] = coords[1][Y]; + min[1] = coords[0][Y]; + } + + return ((point[X] >= min[0] && point[X] <= max[0]) && + (point[Y] >= min[1] && point[Y] <= max[1])); +} + +static int pointincircle(const double point[2], double coords[MAXVERTS][2]) +{ + double radius1, radius2; + + radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y])) + + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X])); + + radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y])) + + ((coords[0][X] - point[X]) * (coords[0][X] - point[X])); + + return (radius2 <= radius1); +} + +#define fmin(a,b) (((a)>(b))?(b):(a)) +#define fmax(a,b) (((a)>(b))?(a):(b)) + +static int pointinpoly(const double point[2], double pgon[MAXVERTS][2]) +{ + int i, numverts, crossings = 0; + double x = point[X], y = point[Y]; + + for (numverts = 0; pgon[numverts][X] != -1 && numverts < MAXVERTS; + numverts++) { + /* just counting the vertexes */ + } + + for (i = 0; i < numverts; i++) { + double x1=pgon[i][X]; + double y1=pgon[i][Y]; + double x2=pgon[(i + 1) % numverts][X]; + double y2=pgon[(i + 1) % numverts][Y]; + double d=(y - y1) * (x2 - x1) - (x - x1) * (y2 - y1); + + if ((y1 >= y) != (y2 >= y)) { + crossings +=y2 - y1 >= 0 ? d >= 0 : d <= 0; + } + if (!d && fmin(x1,x2) <= x && x <= fmax(x1,x2) + && fmin(y1,y2) <= y && y <= fmax(y1,y2)) { + return 1; + } + } + return crossings & 0x01; +} + + +static int is_closer(const double point[2], double coords[MAXVERTS][2], + double *closest) +{ + double dist_squared = ((point[X] - coords[0][X]) + * (point[X] - coords[0][X])) + + ((point[Y] - coords[0][Y]) + * (point[Y] - coords[0][Y])); + + if (point[X] < 0 || point[Y] < 0) { + return (0); /* don't mess around with negative coordinates */ + } + + if (*closest < 0 || dist_squared < *closest) { + *closest = dist_squared; + return (1); /* if this is the first point or is the closest yet + set 'closest' equal to this distance^2 */ + } + + return (0); /* if it's not the first or closest */ + +} + +static double get_x_coord(const char *args) +{ + char *endptr; /* we want it non-null */ + double x_coord = -1; /* -1 is returned if no coordinate is given */ + + if (args == NULL) { + return (-1); /* in case we aren't passed anything */ + } + + while (*args && !isdigit(*args) && *args != ',') { + args++; /* jump to the first digit, but not past + a comma or end */ + } + + x_coord = strtod(args, &endptr); + + if (endptr > args) { /* if a conversion was made */ + return (x_coord); + } + + return (-1); /* else if no conversion was made, + or if no args was given */ +} + +static double get_y_coord(const char *args) +{ + char *endptr; /* we want it non-null */ + char *start_of_y = NULL; + double y_coord = -1; /* -1 is returned on error */ + + if (args == NULL) { + return (-1); /* in case we aren't passed anything */ + } + + start_of_y = strchr(args, ','); /* the comma */ + + if (start_of_y) { + + start_of_y++; /* start looking at the character after + the comma */ + + while (*start_of_y && !isdigit(*start_of_y)) { + start_of_y++; /* jump to the first digit, but not + past the end */ + } + + y_coord = strtod(start_of_y, &endptr); + + if (endptr > start_of_y) { + return (y_coord); + } + } + + return (-1); /* if no conversion was made, or + no comma was found in args */ +} + + +/* See if string has a "quoted part", and if so set *quoted_part to + * the first character of the quoted part, then hammer a \0 onto the + * trailing quote, and set *string to point at the first character + * past the second quote. + * + * Otherwise set *quoted_part to NULL, and leave *string alone. + */ +static void read_quoted(char **string, char **quoted_part) +{ + char *strp = *string; + + /* assume there's no quoted part */ + *quoted_part = NULL; + + while (isspace(*strp)) { + strp++; /* go along string until non-whitespace */ + } + + if (*strp == '"') { /* if that character is a double quote */ + strp++; /* step over it */ + *quoted_part = strp; /* note where the quoted part begins */ + + while (*strp && *strp != '"') { + ++strp; /* skip the quoted portion */ + } + + *strp = '\0'; /* end the string with a NUL */ + + strp++; /* step over the last double quote */ + *string = strp; + } +} + +/* + * returns the mapped URL or NULL. + */ +static char *imap_url(request_rec *r, const char *base, const char *value) +{ +/* translates a value into a URL. */ + int slen, clen; + char *string_pos = NULL; + const char *string_pos_const = NULL; + char *directory = NULL; + char *referer = NULL; + char *my_base; + + if (!strcasecmp(value, "map") || !strcasecmp(value, "menu")) { + return ap_construct_url(r->pool, r->uri, r); + } + + if (!strcasecmp(value, "nocontent") || !strcasecmp(value, "error")) { + return ap_pstrdup(r->pool, value); /* these are handled elsewhere, + so just copy them */ + } + + if (!strcasecmp(value, "referer")) { + referer = ap_table_get(r->headers_in, "Referer"); + if (referer && *referer) { + return ap_pstrdup(r->pool, referer); + } + else { + /* XXX: This used to do *value = '\0'; ... which is totally bogus + * because it hammers the passed in value, which can be a string + * constant, or part of a config, or whatever. Total garbage. + * This works around that without changing the rest of this + * code much + */ + value = ""; /* if 'referer' but no referring page, + null the value */ + } + } + + string_pos_const = value; + while (isalpha(*string_pos_const)) { + string_pos_const++; /* go along the URL from the map + until a non-letter */ + } + if (*string_pos_const == ':') { + /* if letters and then a colon (like http:) */ + /* it's an absolute URL, so use it! */ + return ap_pstrdup(r->pool, value); + } + + if (!base || !*base) { + if (value && *value) { + return ap_pstrdup(r->pool, value); /* no base: use what is given */ + } + /* no base, no value: pick a simple default */ + return ap_construct_url(r->pool, "/", r); + } + + /* must be a relative URL to be combined with base */ + if (strchr(base, '/') == NULL && (!strncmp(value, "../", 3) + || !strcmp(value, ".."))) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "invalid base directive in map file: %s", r->uri); + return NULL; + } + my_base = ap_pstrdup(r->pool, base); + string_pos = my_base; + while (*string_pos) { + if (*string_pos == '/' && *(string_pos + 1) == '/') { + string_pos += 2; /* if there are two slashes, jump over them */ + continue; + } + if (*string_pos == '/') { /* the first single slash */ + if (value[0] == '/') { + *string_pos = '\0'; + } /* if the URL from the map starts from root, + end the base URL string at the first single + slash */ + else { + directory = string_pos; /* save the start of + the directory portion */ + + string_pos = strrchr(string_pos, '/'); /* now reuse + string_pos */ + string_pos++; /* step over that last slash */ + *string_pos = '\0'; + } /* but if the map url is relative, leave the + slash on the base (if there is one) */ + break; + } + string_pos++; /* until we get to the end of my_base without + finding a slash by itself */ + } + + while (!strncmp(value, "../", 3) || !strcmp(value, "..")) { + + if (directory && (slen = strlen(directory))) { + + /* for each '..', knock a directory off the end + by ending the string right at the last slash. + But only consider the directory portion: don't eat + into the server name. And only try if a directory + portion was found */ + + clen = slen - 1; + + while ((slen - clen) == 1) { + + if ((string_pos = strrchr(directory, '/'))) { + *string_pos = '\0'; + } + clen = strlen(directory); + if (clen == 0) { + break; + } + } + + value += 2; /* jump over the '..' that we found in the + value */ + } + else if (directory) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "invalid directory name in map file: %s", r->uri); + return NULL; + } + + if (!strncmp(value, "/../", 4) || !strcmp(value, "/..")) { + value++; /* step over the '/' if there are more '..' + to do. This way, we leave the starting + '/' on value after the last '..', but get + rid of it otherwise */ + } + + } /* by this point, value does not start + with '..' */ + + if (value && *value) { + return ap_pstrcat(r->pool, my_base, value, NULL); + } + return my_base; +} + +static int imap_reply(request_rec *r, char *redirect) +{ + if (!strcasecmp(redirect, "error")) { + return SERVER_ERROR; /* they actually requested an error! */ + } + if (!strcasecmp(redirect, "nocontent")) { + return HTTP_NO_CONTENT; /* tell the client to keep the page it has */ + } + if (redirect && *redirect) { + ap_table_setn(r->headers_out, "Location", redirect); + return REDIRECT; /* must be a URL, so redirect to it */ + } + return SERVER_ERROR; +} + +static void menu_header(request_rec *r, char *menu) +{ + r->content_type = "text/html"; + ap_send_http_header(r); + ap_hard_timeout("send menu", r); /* killed in menu_footer */ + + ap_rvputs(r, "<html><head>\n<title>Menu for ", r->uri, + "\n\n", NULL); + + if (!strcasecmp(menu, "formatted")) { + ap_rvputs(r, "

    Menu for ", r->uri, "

    \n
    \n\n", NULL); + } + + return; +} + +static void menu_blank(request_rec *r, char *menu) +{ + if (!strcasecmp(menu, "formatted")) { + ap_rputs("\n", r); + } + if (!strcasecmp(menu, "semiformatted")) { + ap_rputs("
    \n", r); + } + if (!strcasecmp(menu, "unformatted")) { + ap_rputs("\n", r); + } + return; +} + +static void menu_comment(request_rec *r, char *menu, char *comment) +{ + if (!strcasecmp(menu, "formatted")) { + ap_rputs("\n", r); /* print just a newline if 'formatted' */ + } + if (!strcasecmp(menu, "semiformatted") && *comment) { + ap_rvputs(r, comment, "\n", NULL); + } + if (!strcasecmp(menu, "unformatted") && *comment) { + ap_rvputs(r, comment, "\n", NULL); + } + return; /* comments are ignored in the + 'formatted' form */ +} + +static void menu_default(request_rec *r, char *menu, char *href, char *text) +{ + if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) { + return; /* don't print such lines, these aren't + really href's */ + } + if (!strcasecmp(menu, "formatted")) { + ap_rvputs(r, "
    (Default) ", text,
    +               "
    \n", NULL); + } + if (!strcasecmp(menu, "semiformatted")) { + ap_rvputs(r, "
    (Default) ", text,
    +               "
    \n", NULL); + } + if (!strcasecmp(menu, "unformatted")) { + ap_rvputs(r, "", text, "", NULL); + } + return; +} + +static void menu_directive(request_rec *r, char *menu, char *href, char *text) +{ + if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) { + return; /* don't print such lines, as this isn't + really an href */ + } + if (!strcasecmp(menu, "formatted")) { + ap_rvputs(r, "
              ", text,
    +               "
    \n", NULL); + } + if (!strcasecmp(menu, "semiformatted")) { + ap_rvputs(r, "
              ", text,
    +               "
    \n", NULL); + } + if (!strcasecmp(menu, "unformatted")) { + ap_rvputs(r, "", text, "", NULL); + } + return; +} + +static void menu_footer(request_rec *r) +{ + ap_rputs("\n\n\n\n", r); /* finish the menu */ + ap_kill_timeout(r); +} + +static int imap_handler(request_rec *r) +{ + char input[MAX_STRING_LEN]; + char *directive; + char *value; + char *href_text; + char *base; + char *redirect; + char *mapdflt; + char *closest = NULL; + double closest_yet = -1; + + double testpoint[2]; + double pointarray[MAXVERTS + 1][2]; + int vertex; + + char *string_pos; + int showmenu = 0; + + imap_conf_rec *icr = ap_get_module_config(r->per_dir_config, &imap_module); + + char *imap_menu = icr->imap_menu ? icr->imap_menu : IMAP_MENU_DEFAULT; + char *imap_default = icr->imap_default + ? icr->imap_default : IMAP_DEFAULT_DEFAULT; + char *imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT; + + configfile_t *imap; + + if (r->method_number != M_GET) { + return DECLINED; + } + + imap = ap_pcfg_openfile(r->pool, r->filename); + + if (!imap) { + return NOT_FOUND; + } + + base = imap_url(r, NULL, imap_base); /* set base according + to default */ + if (!base) { + return HTTP_INTERNAL_SERVER_ERROR; + } + mapdflt = imap_url(r, NULL, imap_default); /* and default to + global default */ + if (!mapdflt) { + return HTTP_INTERNAL_SERVER_ERROR; + } + + testpoint[X] = get_x_coord(r->args); + testpoint[Y] = get_y_coord(r->args); + + if ((testpoint[X] == -1 || testpoint[Y] == -1) || + (testpoint[X] == 0 && testpoint[Y] == 0)) { + /* if either is -1 or if both are zero (new Lynx) */ + /* we don't have valid coordinates */ + testpoint[X] = -1; + testpoint[Y] = -1; + if (strncasecmp(imap_menu, "none", 2)) { + showmenu = 1; /* show the menu _unless_ ImapMenu is + 'none' or 'no' */ + } + } + + if (showmenu) { /* send start of imagemap menu if + we're going to */ + menu_header(r, imap_menu); + } + + while (!ap_cfg_getline(input, sizeof(input), imap)) { + if (!input[0]) { + if (showmenu) { + menu_blank(r, imap_menu); + } + continue; + } + + if (input[0] == '#') { + if (showmenu) { + menu_comment(r, imap_menu, input + 1); + } + continue; + } /* blank lines and comments are ignored + if we aren't printing a menu */ + + /* find the first two space delimited fields, recall that + * cfg_getline has removed leading/trailing whitespace and + * compressed the other whitespace down to one space a piece + * + * note that we're tokenizing as we go... if we were to use the + * getword() class of functions we would end up allocating extra + * memory for every line of the map file + */ + string_pos = input; + if (!*string_pos) { /* need at least two fields */ + goto need_2_fields; + } + + directive = string_pos; + while (*string_pos && *string_pos != ' ') { /* past directive */ + ++string_pos; + } + if (!*string_pos) { /* need at least two fields */ + goto need_2_fields; + } + *string_pos++ = '\0'; + + if (!*string_pos) { /* need at least two fields */ + goto need_2_fields; + } + value = string_pos; + while (*string_pos && *string_pos != ' ') { /* past value */ + ++string_pos; + } + if (*string_pos == ' ') { + *string_pos++ = '\0'; + } + else { + /* end of input, don't advance past it */ + *string_pos = '\0'; + } + + if (!strncasecmp(directive, "base", 4)) { /* base, base_uri */ + base = imap_url(r, NULL, value); + if (!base) { + goto menu_bail; + } + continue; /* base is never printed to a menu */ + } + + read_quoted(&string_pos, &href_text); + + if (!strcasecmp(directive, "default")) { /* default */ + mapdflt = imap_url(r, NULL, value); + if (!mapdflt) { + goto menu_bail; + } + if (showmenu) { /* print the default if there's a menu */ + redirect = imap_url(r, base, mapdflt); + if (!redirect) { + goto menu_bail; + } + menu_default(r, imap_menu, redirect, + href_text ? href_text : mapdflt); + } + continue; + } + + vertex = 0; + while (vertex < MAXVERTS && + sscanf(string_pos, "%lf%*[, ]%lf", + &pointarray[vertex][X], &pointarray[vertex][Y]) == 2) { + /* Now skip what we just read... we can't use ANSIism %n */ + while (isspace(*string_pos)) { /* past whitespace */ + string_pos++; + } + while (isdigit(*string_pos)) { /* and the 1st number */ + string_pos++; + } + string_pos++; /* skip the ',' */ + while (isspace(*string_pos)) { /* past any more whitespace */ + string_pos++; + } + while (isdigit(*string_pos)) { /* 2nd number */ + string_pos++; + } + vertex++; + } /* so long as there are more vertices to + read, and we have room, read them in. + We start where we left off of the last + sscanf, not at the beginning. */ + + pointarray[vertex][X] = -1; /* signals the end of vertices */ + + if (showmenu) { + if (!href_text) { + read_quoted(&string_pos, &href_text); /* href text could + be here instead */ + } + redirect = imap_url(r, base, value); + if (!redirect) { + goto menu_bail; + } + menu_directive(r, imap_menu, redirect, + href_text ? href_text : value); + continue; + } + /* note that we don't make it past here if we are making a menu */ + + if (testpoint[X] == -1 || pointarray[0][X] == -1) { + continue; /* don't try the following tests if testpoints + are invalid, or if there are no + coordinates */ + } + + if (!strcasecmp(directive, "poly")) { /* poly */ + + if (pointinpoly(testpoint, pointarray)) { + ap_cfg_closefile(imap); + redirect = imap_url(r, base, value); + if (!redirect) { + return HTTP_INTERNAL_SERVER_ERROR; + } + return (imap_reply(r, redirect)); + } + continue; + } + + if (!strcasecmp(directive, "circle")) { /* circle */ + + if (pointincircle(testpoint, pointarray)) { + ap_cfg_closefile(imap); + redirect = imap_url(r, base, value); + if (!redirect) { + return HTTP_INTERNAL_SERVER_ERROR; + } + return (imap_reply(r, redirect)); + } + continue; + } + + if (!strcasecmp(directive, "rect")) { /* rect */ + + if (pointinrect(testpoint, pointarray)) { + ap_cfg_closefile(imap); + redirect = imap_url(r, base, value); + if (!redirect) { + return HTTP_INTERNAL_SERVER_ERROR; + } + return (imap_reply(r, redirect)); + } + continue; + } + + if (!strcasecmp(directive, "point")) { /* point */ + + if (is_closer(testpoint, pointarray, &closest_yet)) { + closest = ap_pstrdup(r->pool, value); + } + + continue; + } /* move on to next line whether it's + closest or not */ + + } /* nothing matched, so we get another line! */ + + ap_cfg_closefile(imap); /* we are done with the map file; close it */ + + if (showmenu) { + menu_footer(r); /* finish the menu and we are done */ + return OK; + } + + if (closest) { /* if a 'point' directive has been seen */ + redirect = imap_url(r, base, closest); + if (!redirect) { + return HTTP_INTERNAL_SERVER_ERROR; + } + return (imap_reply(r, redirect)); + } + + if (mapdflt) { /* a default should be defined, even if + only 'nocontent' */ + redirect = imap_url(r, base, mapdflt); + if (!redirect) { + return HTTP_INTERNAL_SERVER_ERROR; + } + return (imap_reply(r, redirect)); + } + + return HTTP_INTERNAL_SERVER_ERROR; /* If we make it this far, + we failed. They lose! */ + +need_2_fields: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "map file %s, line %d syntax error: requires at " + "least two fields", r->uri, imap->line_number); + /* fall through */ +menu_bail: + ap_cfg_closefile(imap); + if (showmenu) { + /* There's not much else we can do ... we've already sent the headers + * to the client. + */ + ap_rputs("\n\n[an internal server error occured]\n", r); + menu_footer(r); + return OK; + } + return HTTP_INTERNAL_SERVER_ERROR; +} + + +static const handler_rec imap_handlers[] = +{ + {IMAP_MAGIC_TYPE, imap_handler}, + {"imap-file", imap_handler}, + {NULL} +}; + +module MODULE_VAR_EXPORT imap_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_imap_dir_config, /* dir config creater */ + merge_imap_dir_configs, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + imap_cmds, /* command table */ + imap_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_include.c b/APACHE_1_3b7/src/modules/standard/mod_include.c new file mode 100644 index 0000000000..89b7d3d832 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_include.c @@ -0,0 +1,2414 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_include.c: Handles the server-parsed HTML documents + * + * Original by Rob McCool; substantial fixups by David Robinson; + * incorporated into the Apache module framework by rst. + * + */ +/* + * sub key may be anything a Perl*Handler can be: + * subroutine name, package name (defaults to package::handler), + * Class->method call or anoymous sub {} + * + * Child accessed + * times.
    + * + * + * + * -Doug MacEachern + */ + +#ifdef USE_PERL_SSI +#include "config.h" +#undef VOIDUSED +#ifdef USE_SFIO +#undef USE_SFIO +#define USE_STDIO +#endif +#include "modules/perl/mod_perl.h" +#else +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_log.h" +#include "http_main.h" +#include "util_script.h" +#endif + +#define STARTING_SEQUENCE "" +#define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]" +#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z" +#define SIZEFMT_BYTES 0 +#define SIZEFMT_KMG 1 +#ifdef CHARSET_EBCDIC +#define RAW_ASCII_CHAR(ch) os_toebcdic[(unsigned char)ch] +#else /*CHARSET_EBCDIC*/ +#define RAW_ASCII_CHAR(ch) (ch) +#endif /*CHARSET_EBCDIC*/ + +module MODULE_VAR_EXPORT includes_module; + +/* just need some arbitrary non-NULL pointer which can't also be a request_rec */ +#define NESTED_INCLUDE_MAGIC (&includes_module) + +/* ------------------------ Environment function -------------------------- */ + +static void add_include_vars(request_rec *r, char *timefmt) +{ +#ifndef WIN32 + struct passwd *pw; +#endif /* ndef WIN32 */ + table *e = r->subprocess_env; + char *t; + time_t date = r->request_time; + + ap_table_setn(e, "DATE_LOCAL", ap_ht_time(r->pool, date, timefmt, 0)); + ap_table_setn(e, "DATE_GMT", ap_ht_time(r->pool, date, timefmt, 1)); + ap_table_setn(e, "LAST_MODIFIED", + ap_ht_time(r->pool, r->finfo.st_mtime, timefmt, 0)); + ap_table_setn(e, "DOCUMENT_URI", r->uri); + ap_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info); +#ifndef WIN32 + pw = getpwuid(r->finfo.st_uid); + if (pw) { + ap_table_setn(e, "USER_NAME", ap_pstrdup(r->pool, pw->pw_name)); + } + else { + ap_table_setn(e, "USER_NAME", ap_psprintf(r->pool, "user#%lu", + (unsigned long) r->finfo.st_uid)); + } +#endif /* ndef WIN32 */ + + if ((t = strrchr(r->filename, '/'))) { + ap_table_setn(e, "DOCUMENT_NAME", ++t); + } + else { + ap_table_setn(e, "DOCUMENT_NAME", r->uri); + } + if (r->args) { + char *arg_copy = ap_pstrdup(r->pool, r->args); + + ap_unescape_url(arg_copy); + ap_table_setn(e, "QUERY_STRING_UNESCAPED", + ap_escape_shell_cmd(r->pool, arg_copy)); + } +} + + + +/* --------------------------- Parser functions --------------------------- */ + +#define OUTBUFSIZE 4096 +/* PUT_CHAR and FLUSH_BUF currently only work within the scope of + * find_string(); they are hacks to avoid calling rputc for each and + * every character output. A common set of buffering calls for this + * type of output SHOULD be implemented. + */ +#define PUT_CHAR(c,r) \ + { \ + outbuf[outind++] = c; \ + if (outind == OUTBUFSIZE) { \ + FLUSH_BUF(r) \ + }; \ + } + +/* there SHOULD be some error checking on the return value of + * rwrite, however it is unclear what the API for rwrite returning + * errors is and little can really be done to help the error in + * any case. + */ +#define FLUSH_BUF(r) \ + { \ + ap_rwrite(outbuf, outind, r); \ + outind = 0; \ + } + +/* + * f: file handle being read from + * c: character to read into + * ret: return value to use if input fails + * r: current request_rec + * + * This macro is redefined after find_string() for historical reasons + * to avoid too many code changes. This is one of the many things + * that should be fixed. + */ +#define GET_CHAR(f,c,ret,r) \ + { \ + int i = getc(f); \ + if (i == EOF) { /* either EOF or error -- needs error handling if latter */ \ + if (ferror(f)) { \ + fprintf(stderr, "encountered error in GET_CHAR macro, " \ + "mod_include.\n"); \ + } \ + FLUSH_BUF(r); \ + ap_pfclose(r->pool, f); \ + return ret; \ + } \ + c = (char)i; \ + } + +static int find_string(FILE *in, const char *str, request_rec *r, int printing) +{ + int x, l = strlen(str), p; + char outbuf[OUTBUFSIZE]; + int outind = 0; + char c; + + p = 0; + while (1) { + GET_CHAR(in, c, 1, r); + if (c == str[p]) { + if ((++p) == l) { + FLUSH_BUF(r); + return 0; + } + } + else { + if (printing) { + for (x = 0; x < p; x++) { + PUT_CHAR(str[x], r); + } + PUT_CHAR(c, r); + } + p = 0; + } + } +} + +#undef FLUSH_BUF +#undef PUT_CHAR +#undef GET_CHAR +#define GET_CHAR(f,c,r,p) \ + { \ + int i = getc(f); \ + if (i == EOF) { /* either EOF or error -- needs error handling if latter */ \ + if (ferror(f)) { \ + fprintf(stderr, "encountered error in GET_CHAR macro, " \ + "mod_include.\n"); \ + } \ + ap_pfclose(p, f); \ + return r; \ + } \ + c = (char)i; \ + } + +/* + * decodes a string containing html entities or numeric character references. + * 's' is overwritten with the decoded string. + * If 's' is syntatically incorrect, then the followed fixups will be made: + * unknown entities will be left undecoded; + * references to unused numeric characters will be deleted. + * In particular, � will not be decoded, but will be deleted. + * + * drtr + */ + +/* maximum length of any ISO-LATIN-1 HTML entity name. */ +#define MAXENTLEN (6) + +/* The following is a shrinking transformation, therefore safe. */ + +static void decodehtml(char *s) +{ + int val, i, j; + char *p = s; + const char *ents; + static const char * const entlist[MAXENTLEN + 1] = + { + NULL, /* 0 */ + NULL, /* 1 */ + "lt\074gt\076", /* 2 */ + "amp\046ETH\320eth\360", /* 3 */ + "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml\353\ +iuml\357ouml\366uuml\374yuml\377", /* 4 */ + "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc\333\ +THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352icirc\356ocirc\364\ +ucirc\373thorn\376", /* 5 */ + "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311\ +Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde\325Oslash\330\ +Ugrave\331Uacute\332Yacute\335agrave\340aacute\341atilde\343ccedil\347\ +egrave\350eacute\351igrave\354iacute\355ntilde\361ograve\362oacute\363\ +otilde\365oslash\370ugrave\371uacute\372yacute\375" /* 6 */ + }; + + for (; *s != '\0'; s++, p++) { + if (*s != '&') { + *p = *s; + continue; + } + /* find end of entity */ + for (i = 1; s[i] != ';' && s[i] != '\0'; i++) { + continue; + } + + if (s[i] == '\0') { /* treat as normal data */ + *p = *s; + continue; + } + + /* is it numeric ? */ + if (s[1] == '#') { + for (j = 2, val = 0; j < i && isdigit(s[j]); j++) { + val = val * 10 + s[j] - '0'; + } + s += i; + if (j < i || val <= 8 || (val >= 11 && val <= 31) || + (val >= 127 && val <= 160) || val >= 256) { + p--; /* no data to output */ + } + else { + *p = RAW_ASCII_CHAR(val); + } + } + else { + j = i - 1; + if (j > MAXENTLEN || entlist[j] == NULL) { + /* wrong length */ + *p = '&'; + continue; /* skip it */ + } + for (ents = entlist[j]; *ents != '\0'; ents += i) { + if (strncmp(s + 1, ents, j) == 0) { + break; + } + } + + if (*ents == '\0') { + *p = '&'; /* unknown */ + } + else { + *p = RAW_ASCII_CHAR(((const unsigned char *) ents)[j]); + s += i; + } + } + } + + *p = '\0'; +} + +/* + * extract the next tag name and value. + * if there are no more tags, set the tag name to 'done' + * the tag value is html decoded if dodecode is non-zero + */ + +static char *get_tag(pool *p, FILE *in, char *tag, int tagbuf_len, int dodecode) +{ + char *t = tag, *tag_val, c, term; + + /* makes code below a little less cluttered */ + --tagbuf_len; + + do { /* skip whitespace */ + GET_CHAR(in, c, NULL, p); + } while (isspace(c)); + + /* tags can't start with - */ + if (c == '-') { + GET_CHAR(in, c, NULL, p); + if (c == '-') { + do { + GET_CHAR(in, c, NULL, p); + } while (isspace(c)); + if (c == '>') { + ap_cpystrn(tag, "done", tagbuf_len); + return tag; + } + } + return NULL; /* failed */ + } + + /* find end of tag name */ + while (1) { + if (t - tag == tagbuf_len) { + *t = '\0'; + return NULL; + } + if (c == '=' || isspace(c)) { + break; + } + *(t++) = tolower(c); + GET_CHAR(in, c, NULL, p); + } + + *t++ = '\0'; + tag_val = t; + + while (isspace(c)) { + GET_CHAR(in, c, NULL, p); /* space before = */ + } + if (c != '=') { + ungetc(c, in); + return NULL; + } + + do { + GET_CHAR(in, c, NULL, p); /* space after = */ + } while (isspace(c)); + + /* we should allow a 'name' as a value */ + + if (c != '"' && c != '\'') { + return NULL; + } + term = c; + while (1) { + GET_CHAR(in, c, NULL, p); + if (t - tag == tagbuf_len) { + *t = '\0'; + return NULL; + } +/* Want to accept \" as a valid character within a string. */ + if (c == '\\') { + *(t++) = c; /* Add backslash */ + GET_CHAR(in, c, NULL, p); + if (c == term) { /* Only if */ + *(--t) = c; /* Replace backslash ONLY for terminator */ + } + } + else if (c == term) { + break; + } + *(t++) = c; + } + *t = '\0'; + if (dodecode) { + decodehtml(tag_val); + } + return ap_pstrdup(p, tag_val); +} + +static int get_directive(FILE *in, char *dest, size_t len, pool *p) +{ + char *d = dest; + char c; + + /* make room for nul terminator */ + --len; + + /* skip initial whitespace */ + while (1) { + GET_CHAR(in, c, 1, p); + if (!isspace(c)) { + break; + } + } + /* now get directive */ + while (1) { + if (d - dest == len) { + return 1; + } + *d++ = tolower(c); + GET_CHAR(in, c, 1, p); + if (isspace(c)) { + break; + } + } + *d = '\0'; + return 0; +} + +/* + * Do variable substitution on strings + */ +static void parse_string(request_rec *r, const char *in, char *out, + size_t length, int leave_name) +{ + char ch; + char *next = out; + char *end_out; + + /* leave room for nul terminator */ + end_out = out + length - 1; + + while ((ch = *in++) != '\0') { + switch (ch) { + case '\\': + if (next == end_out) { + /* truncated */ + *next = '\0'; + return; + } + if (*in == '$') { + *next++ = *in++; + } + else { + *next++ = ch; + } + break; + case '$': + { + char var[MAX_STRING_LEN]; + const char *start_of_var_name; + const char *end_of_var_name; /* end of var name + 1 */ + const char *expansion; + const char *val; + size_t l; + + /* guess that the expansion won't happen */ + expansion = in - 1; + if (*in == '{') { + ++in; + start_of_var_name = in; + in = strchr(in, '}'); + if (in == NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, + r->server, "Missing '}' on variable \"%s\"", + expansion); + *next = '\0'; + return; + } + end_of_var_name = in; + ++in; + } + else { + start_of_var_name = in; + while (isalnum(*in) || *in == '_') { + ++in; + } + end_of_var_name = in; + } + /* what a pain, too bad there's no table_getn where you can + * pass a non-nul terminated string */ + l = end_of_var_name - start_of_var_name; + l = (l > sizeof(var) - 1) ? (sizeof(var) - 1) : l; + memcpy(var, start_of_var_name, l); + var[l] = '\0'; + + val = ap_table_get(r->subprocess_env, var); + if (val) { + expansion = val; + l = strlen(expansion); + } + else if (leave_name) { + l = in - expansion; + } + else { + break; /* no expansion to be done */ + } + l = (l > end_out - next) ? (end_out - next) : l; + memcpy(next, expansion, l); + next += l; + break; + } + default: + if (next == end_out) { + /* truncated */ + *next = '\0'; + return; + } + *next++ = ch; + break; + } + } + *next = '\0'; + return; +} + +/* --------------------------- Action handlers ---------------------------- */ + +static int include_cgi(char *s, request_rec *r) +{ + request_rec *rr = ap_sub_req_lookup_uri(s, r); + int rr_status; + + if (rr->status != HTTP_OK) { + return -1; + } + + /* No hardwired path info or query allowed */ + + if ((rr->path_info && rr->path_info[0]) || rr->args) { + return -1; + } + if (rr->finfo.st_mode == 0) { + return -1; + } + + /* Script gets parameters of the *document*, for back compatibility */ + + rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */ + rr->args = r->args; + + /* Force sub_req to be treated as a CGI request, even if ordinary + * typing rules would have called it something else. + */ + + rr->content_type = CGI_MAGIC_TYPE; + + /* Run it. */ + + rr_status = ap_run_sub_req(rr); + if (is_HTTP_REDIRECT(rr_status)) { + char *location = ap_table_get(rr->headers_out, "Location"); + location = ap_escape_html(rr->pool, location); + ap_rvputs(r, "", location, "", NULL); + } + + ap_destroy_sub_req(rr); +#ifndef WIN32 + ap_chdir_file(r->filename); +#endif + + return 0; +} + +/* ensure that path is relative, and does not contain ".." elements + * ensentially ensure that it does not match the regex: + * (^/|(^|/)\.\.(/|$)) + * XXX: this needs os abstraction... consider c:..\foo in win32 + */ +static int is_only_below(const char *path) +{ +#if WIN32 + if (path[1] == ':') + return 0; +#endif + if (path[0] == '/') { + return 0; + } + if (path[0] == '.' && path[1] == '.' + && (path[2] == '\0' || path[2] == '/')) { + return 0; + } + while (*path) { + if (*path == '/' && path[1] == '.' && path[2] == '.' + && (path[3] == '\0' || path[3] == '/')) { + return 0; + } + ++path; + } + return 1; +} + +static int handle_include(FILE *in, request_rec *r, const char *error, int noexec) +{ + char tag[MAX_STRING_LEN]; + char parsed_string[MAX_STRING_LEN]; + char *tag_val; + + while (1) { + if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { + return 1; + } + if (!strcmp(tag, "file") || !strcmp(tag, "virtual")) { + request_rec *rr = NULL; + char *error_fmt = NULL; + + parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); + if (tag[0] == 'f') { + /* be safe; only files in this directory or below allowed */ + if (!is_only_below(parsed_string)) { + error_fmt = "unable to include file \"%s\" " + "in parsed file %s"; + } + else { + rr = ap_sub_req_lookup_file(parsed_string, r); + } + } + else { + rr = ap_sub_req_lookup_uri(parsed_string, r); + } + + if (!error_fmt && rr->status != HTTP_OK) { + error_fmt = "unable to include \"%s\" in parsed file %s"; + } + + if (!error_fmt && noexec && rr->content_type + && (strncmp(rr->content_type, "text/", 5))) { + error_fmt = "unable to include potential exec \"%s\" " + "in parsed file %s"; + } + if (error_fmt == NULL) { + request_rec *p; + + for (p = r; p != NULL; p = p->main) { + if (strcmp(p->filename, rr->filename) == 0) { + break; + } + } + if (p != NULL) { + error_fmt = "Recursive include of \"%s\" " + "in parsed file %s"; + } + } + + /* see the Kludge in send_parsed_file for why */ + if (rr) + ap_set_module_config(rr->request_config, &includes_module, r); + + if (!error_fmt && ap_run_sub_req(rr)) { + error_fmt = "unable to include \"%s\" in parsed file %s"; + } +#ifndef WIN32 + ap_chdir_file(r->filename); +#endif + if (error_fmt) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, + r->server, error_fmt, tag_val, r->filename); + ap_rputs(error, r); + } + + /* destroy the sub request if it's not a nested include */ + if (rr != NULL + && ap_get_module_config(rr->request_config, &includes_module) + != NESTED_INCLUDE_MAGIC) { + ap_destroy_sub_req(rr); + } + } + else if (!strcmp(tag, "done")) { + return 0; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "unknown parameter \"%s\" to tag include in %s", + tag, r->filename); + ap_rputs(error, r); + } + } +} + +typedef struct { + request_rec *r; + char *s; +} include_cmd_arg; + +static int include_cmd_child(void *arg, child_info *pinfo) +{ + request_rec *r = ((include_cmd_arg *) arg)->r; + char *s = ((include_cmd_arg *) arg)->s; + table *env = r->subprocess_env; + int child_pid = 0; +#ifdef DEBUG_INCLUDE_CMD + FILE *dbg = fopen("/dev/tty", "w"); +#endif +#ifndef WIN32 + char err_string[MAX_STRING_LEN]; +#endif + +#ifdef DEBUG_INCLUDE_CMD +#ifdef __EMX__ + /* under OS/2 /dev/tty is referenced as con */ + FILE *dbg = fopen("con", "w"); +#else + fprintf(dbg, "Attempting to include command '%s'\n", s); +#endif +#endif + + if (r->path_info && r->path_info[0] != '\0') { + request_rec *pa_req; + + ap_table_setn(env, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info)); + + pa_req = ap_sub_req_lookup_uri(escape_uri(r->pool, r->path_info), r); + if (pa_req->filename) { + ap_table_setn(env, "PATH_TRANSLATED", + ap_pstrcat(r->pool, pa_req->filename, pa_req->path_info, + NULL)); + } + } + + if (r->args) { + char *arg_copy = ap_pstrdup(r->pool, r->args); + + ap_table_setn(env, "QUERY_STRING", r->args); + ap_unescape_url(arg_copy); + ap_table_setn(env, "QUERY_STRING_UNESCAPED", + ap_escape_shell_cmd(r->pool, arg_copy)); + } + + ap_error_log2stderr(r->server); + +#ifdef DEBUG_INCLUDE_CMD + fprintf(dbg, "Attempting to exec '%s'\n", s); +#endif + ap_cleanup_for_exec(); + /* set shellcmd flag to pass arg to SHELL_PATH */ + child_pid = ap_call_exec(r, pinfo, s, ap_create_environment(r->pool, env), + 1); +#ifdef WIN32 + return (child_pid); +#else + /* Oh, drat. We're still here. The log file descriptors are closed, + * so we have to whimper a complaint onto stderr... + */ + +#ifdef DEBUG_INCLUDE_CMD + fprintf(dbg, "Exec failed\n"); +#endif + ap_snprintf(err_string, sizeof(err_string), + "httpd: exec of %s failed, reason: %s (errno = %d)\n", + SHELL_PATH, strerror(errno), errno); + write(STDERR_FILENO, err_string, strlen(err_string)); + exit(0); + /* NOT REACHED */ + return (child_pid); +#endif /* WIN32 */ +} + +static int include_cmd(char *s, request_rec *r) +{ + include_cmd_arg arg; + BUFF *script_in; + + arg.r = r; + arg.s = s; + + if (!ap_spawn_child_err_buff(r->pool, include_cmd_child, &arg, + kill_after_timeout, NULL, &script_in, NULL)) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "couldn't spawn include command"); + return -1; + } + + ap_send_fb(script_in, r); + ap_bclose(script_in); + return 0; +} + +static int handle_exec(FILE *in, request_rec *r, const char *error) +{ + char tag[MAX_STRING_LEN]; + char *tag_val; + char *file = r->filename; + char parsed_string[MAX_STRING_LEN]; + + while (1) { + if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { + return 1; + } + if (!strcmp(tag, "cmd")) { + parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 1); + if (include_cmd(parsed_string, r) == -1) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "execution failure for parameter \"%s\" " + "to tag exec in file %s", + tag, r->filename); + ap_rputs(error, r); + } + /* just in case some stooge changed directories */ +#ifndef WIN32 + ap_chdir_file(r->filename); +#endif + } + else if (!strcmp(tag, "cgi")) { + parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); + if (include_cgi(parsed_string, r) == -1) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "invalid CGI ref \"%s\" in %s", tag_val, file); + ap_rputs(error, r); + } + /* grumble groan */ +#ifndef WIN32 + ap_chdir_file(r->filename); +#endif + } + else if (!strcmp(tag, "done")) { + return 0; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "unknown parameter \"%s\" to tag exec in %s", + tag, file); + ap_rputs(error, r); + } + } + +} + +static int handle_echo(FILE *in, request_rec *r, const char *error) +{ + char tag[MAX_STRING_LEN]; + char *tag_val; + + while (1) { + if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { + return 1; + } + if (!strcmp(tag, "var")) { + char *val = ap_table_get(r->subprocess_env, tag_val); + + if (val) { + ap_rputs(val, r); + } + else { + ap_rputs("(none)", r); + } + } + else if (!strcmp(tag, "done")) { + return 0; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "unknown parameter \"%s\" to tag echo in %s", + tag, r->filename); + ap_rputs(error, r); + } + } +} + +#ifdef USE_PERL_SSI +static int handle_perl(FILE *in, request_rec *r, const char *error) +{ + char tag[MAX_STRING_LEN]; + char *tag_val; + SV *sub = Nullsv; + AV *av = newAV(); + + if (!(ap_allow_options(r) & OPT_INCLUDES)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "httpd: #perl SSI disallowed by IncludesNoExec in %s", + r->filename); + return DECLINED; + } + while (1) { + if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { + break; + } + if (strnEQ(tag, "sub", 3)) { + sub = newSVpv(tag_val, 0); + } + else if (strnEQ(tag, "arg", 3)) { + av_push(av, newSVpv(tag_val, 0)); + } + else if (strnEQ(tag, "done", 4)) { + break; + } + } + perl_stdout2client(r); + perl_call_handler(sub, r, av); + return OK; +} +#endif + +/* error and tf must point to a string with room for at + * least MAX_STRING_LEN characters + */ +static int handle_config(FILE *in, request_rec *r, char *error, char *tf, + int *sizefmt) +{ + char tag[MAX_STRING_LEN]; + char *tag_val; + char parsed_string[MAX_STRING_LEN]; + table *env = r->subprocess_env; + + while (1) { + if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0))) { + return 1; + } + if (!strcmp(tag, "errmsg")) { + parse_string(r, tag_val, error, MAX_STRING_LEN, 0); + } + else if (!strcmp(tag, "timefmt")) { + time_t date = r->request_time; + + parse_string(r, tag_val, tf, MAX_STRING_LEN, 0); + ap_table_setn(env, "DATE_LOCAL", ap_ht_time(r->pool, date, tf, 0)); + ap_table_setn(env, "DATE_GMT", ap_ht_time(r->pool, date, tf, 1)); + ap_table_setn(env, "LAST_MODIFIED", + ap_ht_time(r->pool, r->finfo.st_mtime, tf, 0)); + } + else if (!strcmp(tag, "sizefmt")) { + parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); + decodehtml(parsed_string); + if (!strcmp(parsed_string, "bytes")) { + *sizefmt = SIZEFMT_BYTES; + } + else if (!strcmp(parsed_string, "abbrev")) { + *sizefmt = SIZEFMT_KMG; + } + } + else if (!strcmp(tag, "done")) { + return 0; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "unknown parameter \"%s\" to tag config in %s", + tag, r->filename); + ap_rputs(error, r); + } + } +} + + +static int find_file(request_rec *r, const char *directive, const char *tag, + char *tag_val, struct stat *finfo, const char *error) +{ + char *to_send; + + if (!strcmp(tag, "file")) { + ap_getparents(tag_val); /* get rid of any nasties */ + to_send = ap_make_full_path(r->pool, "./", tag_val); + if (stat(to_send, finfo) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "unable to get information about \"%s\" " + "in parsed file %s", + to_send, r->filename); + ap_rputs(error, r); + return -1; + } + return 0; + } + else if (!strcmp(tag, "virtual")) { + request_rec *rr = ap_sub_req_lookup_uri(tag_val, r); + + if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) { + memcpy((char *) finfo, (const char *) &rr->finfo, + sizeof(struct stat)); + ap_destroy_sub_req(rr); + return 0; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "unable to get information about \"%s\" " + "in parsed file %s", + tag_val, r->filename); + ap_rputs(error, r); + ap_destroy_sub_req(rr); + return -1; + } + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "unknown parameter \"%s\" to tag %s in %s", + tag, directive, r->filename); + ap_rputs(error, r); + return -1; + } +} + + +static int handle_fsize(FILE *in, request_rec *r, const char *error, int sizefmt) +{ + char tag[MAX_STRING_LEN]; + char *tag_val; + struct stat finfo; + char parsed_string[MAX_STRING_LEN]; + + while (1) { + if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { + return 1; + } + else if (!strcmp(tag, "done")) { + return 0; + } + else { + parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); + if (!find_file(r, "fsize", tag, parsed_string, &finfo, error)) { + if (sizefmt == SIZEFMT_KMG) { + ap_send_size(finfo.st_size, r); + } + else { + int l, x; +#if defined(BSD) && BSD > 199305 + /* ap_snprintf can't handle %qd */ + sprintf(tag, "%qd", finfo.st_size); +#else + ap_snprintf(tag, sizeof(tag), "%ld", finfo.st_size); +#endif + l = strlen(tag); /* grrr */ + for (x = 0; x < l; x++) { + if (x && (!((l - x) % 3))) { + ap_rputc(',', r); + } + ap_rputc(tag[x], r); + } + } + } + } + } +} + +static int handle_flastmod(FILE *in, request_rec *r, const char *error, const char *tf) +{ + char tag[MAX_STRING_LEN]; + char *tag_val; + struct stat finfo; + char parsed_string[MAX_STRING_LEN]; + + while (1) { + if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { + return 1; + } + else if (!strcmp(tag, "done")) { + return 0; + } + else { + parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); + if (!find_file(r, "flastmod", tag, parsed_string, &finfo, error)) { + ap_rputs(ap_ht_time(r->pool, finfo.st_mtime, tf, 0), r); + } + } + } +} + +static int re_check(request_rec *r, char *string, char *rexp) +{ + regex_t *compiled; + int regex_error; + + compiled = ap_pregcomp(r->pool, rexp, REG_EXTENDED | REG_NOSUB); + if (compiled == NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "unable to compile pattern \"%s\"", rexp); + return -1; + } + regex_error = regexec(compiled, string, 0, (regmatch_t *) NULL, 0); + ap_pregfree(r->pool, compiled); + return (!regex_error); +} + +enum token_type { + token_string, + token_and, token_or, token_not, token_eq, token_ne, + token_rbrace, token_lbrace, token_group, + token_ge, token_le, token_gt, token_lt +}; +struct token { + enum token_type type; + char value[MAX_STRING_LEN]; +}; + +/* there is an implicit assumption here that string is at most MAX_STRING_LEN-1 + * characters long... + */ +static const char *get_ptoken(request_rec *r, const char *string, struct token *token) +{ + char ch; + int next = 0; + int qs = 0; + + /* Skip leading white space */ + if (string == (char *) NULL) { + return (char *) NULL; + } + while ((ch = *string++)) { + if (!isspace(ch)) { + break; + } + } + if (ch == '\0') { + return (char *) NULL; + } + + token->type = token_string; /* the default type */ + switch (ch) { + case '(': + token->type = token_lbrace; + return (string); + case ')': + token->type = token_rbrace; + return (string); + case '=': + token->type = token_eq; + return (string); + case '!': + if (*string == '=') { + token->type = token_ne; + return (string + 1); + } + else { + token->type = token_not; + return (string); + } + case '\'': + token->type = token_string; + qs = 1; + break; + case '|': + if (*string == '|') { + token->type = token_or; + return (string + 1); + } + break; + case '&': + if (*string == '&') { + token->type = token_and; + return (string + 1); + } + break; + case '>': + if (*string == '=') { + token->type = token_ge; + return (string + 1); + } + else { + token->type = token_gt; + return (string); + } + case '<': + if (*string == '=') { + token->type = token_le; + return (string + 1); + } + else { + token->type = token_lt; + return (string); + } + default: + token->type = token_string; + break; + } + /* We should only be here if we are in a string */ + if (!qs) { + token->value[next++] = ch; + } + + /* + * Yes I know that goto's are BAD. But, c doesn't allow me to + * exit a loop from a switch statement. Yes, I could use a flag, + * but that is (IMHO) even less readable/maintainable than the goto. + */ + /* + * I used the ++string throughout this section so that string + * ends up pointing to the next token and I can just return it + */ + for (ch = *string; ch != '\0'; ch = *++string) { + if (ch == '\\') { + if ((ch = *++string) == '\0') { + goto TOKEN_DONE; + } + token->value[next++] = ch; + continue; + } + if (!qs) { + if (isspace(ch)) { + goto TOKEN_DONE; + } + switch (ch) { + case '(': + goto TOKEN_DONE; + case ')': + goto TOKEN_DONE; + case '=': + goto TOKEN_DONE; + case '!': + goto TOKEN_DONE; + case '|': + if (*(string + 1) == '|') { + goto TOKEN_DONE; + } + break; + case '&': + if (*(string + 1) == '&') { + goto TOKEN_DONE; + } + break; + case '<': + goto TOKEN_DONE; + case '>': + goto TOKEN_DONE; + } + token->value[next++] = ch; + } + else { + if (ch == '\'') { + qs = 0; + ++string; + goto TOKEN_DONE; + } + token->value[next++] = ch; + } + } + TOKEN_DONE: + /* If qs is still set, I have an unmatched ' */ + if (qs) { + ap_rputs("\nUnmatched '\n", r); + next = 0; + } + token->value[next] = '\0'; + return (string); +} + + +/* + * Hey I still know that goto's are BAD. I don't think that I've ever + * used two in the same project, let alone the same file before. But, + * I absolutely want to make sure that I clean up the memory in all + * cases. And, without rewriting this completely, the easiest way + * is to just branch to the return code which cleans it up. + */ +/* there is an implicit assumption here that expr is at most MAX_STRING_LEN-1 + * characters long... + */ +static int parse_expr(request_rec *r, const char *expr, const char *error) +{ + struct parse_node { + struct parse_node *left, *right, *parent; + struct token token; + int value, done; + } *root, *current, *new; + const char *parse; + char buffer[MAX_STRING_LEN]; + pool *expr_pool; + int retval = 0; + + if ((parse = expr) == (char *) NULL) { + return (0); + } + root = current = (struct parse_node *) NULL; + expr_pool = ap_make_sub_pool(r->pool); + + /* Create Parse Tree */ + while (1) { + new = (struct parse_node *) ap_palloc(expr_pool, + sizeof(struct parse_node)); + new->parent = new->left = new->right = (struct parse_node *) NULL; + new->done = 0; + if ((parse = get_ptoken(r, parse, &new->token)) == (char *) NULL) { + break; + } + switch (new->token.type) { + + case token_string: +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Token: string (", new->token.value, ")\n", NULL); +#endif + if (current == (struct parse_node *) NULL) { + root = current = new; + break; + } + switch (current->token.type) { + case token_string: + if (current->token.value[0] != '\0') { + strncat(current->token.value, " ", + sizeof(current->token.value) + - strlen(current->token.value) - 1); + } + strncat(current->token.value, new->token.value, + sizeof(current->token.value) + - strlen(current->token.value) - 1); + current->token.value[sizeof(current->token.value) - 1] = '\0'; + break; + case token_eq: + case token_ne: + case token_and: + case token_or: + case token_lbrace: + case token_not: + case token_ge: + case token_gt: + case token_le: + case token_lt: + new->parent = current; + current = current->right = new; + break; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + break; + + case token_and: + case token_or: +#ifdef DEBUG_INCLUDE + ap_rputs(" Token: and/or\n", r); +#endif + if (current == (struct parse_node *) NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + /* Percolate upwards */ + while (current != (struct parse_node *) NULL) { + switch (current->token.type) { + case token_string: + case token_group: + case token_not: + case token_eq: + case token_ne: + case token_and: + case token_or: + case token_ge: + case token_gt: + case token_le: + case token_lt: + current = current->parent; + continue; + case token_lbrace: + break; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + break; + } + if (current == (struct parse_node *) NULL) { + new->left = root; + new->left->parent = new; + new->parent = (struct parse_node *) NULL; + root = new; + } + else { + new->left = current->right; + current->right = new; + new->parent = current; + } + current = new; + break; + + case token_not: +#ifdef DEBUG_INCLUDE + ap_rputs(" Token: not\n", r); +#endif + if (current == (struct parse_node *) NULL) { + root = current = new; + break; + } + /* Percolate upwards */ + while (current != (struct parse_node *) NULL) { + switch (current->token.type) { + case token_not: + case token_eq: + case token_ne: + case token_and: + case token_or: + case token_lbrace: + case token_ge: + case token_gt: + case token_le: + case token_lt: + break; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + break; + } + if (current == (struct parse_node *) NULL) { + new->left = root; + new->left->parent = new; + new->parent = (struct parse_node *) NULL; + root = new; + } + else { + new->left = current->right; + current->right = new; + new->parent = current; + } + current = new; + break; + + case token_eq: + case token_ne: + case token_ge: + case token_gt: + case token_le: + case token_lt: +#ifdef DEBUG_INCLUDE + ap_rputs(" Token: eq/ne/ge/gt/le/lt\n", r); +#endif + if (current == (struct parse_node *) NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + /* Percolate upwards */ + while (current != (struct parse_node *) NULL) { + switch (current->token.type) { + case token_string: + case token_group: + current = current->parent; + continue; + case token_lbrace: + case token_and: + case token_or: + break; + case token_not: + case token_eq: + case token_ne: + case token_ge: + case token_gt: + case token_le: + case token_lt: + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + break; + } + if (current == (struct parse_node *) NULL) { + new->left = root; + new->left->parent = new; + new->parent = (struct parse_node *) NULL; + root = new; + } + else { + new->left = current->right; + current->right = new; + new->parent = current; + } + current = new; + break; + + case token_rbrace: +#ifdef DEBUG_INCLUDE + ap_rputs(" Token: rbrace\n", r); +#endif + while (current != (struct parse_node *) NULL) { + if (current->token.type == token_lbrace) { + current->token.type = token_group; + break; + } + current = current->parent; + } + if (current == (struct parse_node *) NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Unmatched ')' in \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + break; + + case token_lbrace: +#ifdef DEBUG_INCLUDE + ap_rputs(" Token: lbrace\n", r); +#endif + if (current == (struct parse_node *) NULL) { + root = current = new; + break; + } + /* Percolate upwards */ + while (current != (struct parse_node *) NULL) { + switch (current->token.type) { + case token_not: + case token_eq: + case token_ne: + case token_and: + case token_or: + case token_lbrace: + case token_ge: + case token_gt: + case token_le: + case token_lt: + break; + case token_string: + case token_group: + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + break; + } + if (current == (struct parse_node *) NULL) { + new->left = root; + new->left->parent = new; + new->parent = (struct parse_node *) NULL; + root = new; + } + else { + new->left = current->right; + current->right = new; + new->parent = current; + } + current = new; + break; + default: + break; + } + } + + /* Evaluate Parse Tree */ + current = root; + while (current != (struct parse_node *) NULL) { + switch (current->token.type) { + case token_string: +#ifdef DEBUG_INCLUDE + ap_rputs(" Evaluate string\n", r); +#endif + parse_string(r, current->token.value, buffer, sizeof(buffer), 0); + ap_cpystrn(current->token.value, buffer, sizeof(current->token.value)); + current->value = (current->token.value[0] != '\0'); + current->done = 1; + current = current->parent; + break; + + case token_and: + case token_or: +#ifdef DEBUG_INCLUDE + ap_rputs(" Evaluate and/or\n", r); +#endif + if (current->left == (struct parse_node *) NULL || + current->right == (struct parse_node *) NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + if (!current->left->done) { + switch (current->left->token.type) { + case token_string: + parse_string(r, current->left->token.value, + buffer, sizeof(buffer), 0); + ap_cpystrn(current->left->token.value, buffer, + sizeof(current->left->token.value)); + current->left->value = (current->left->token.value[0] != '\0'); + current->left->done = 1; + break; + default: + current = current->left; + continue; + } + } + if (!current->right->done) { + switch (current->right->token.type) { + case token_string: + parse_string(r, current->right->token.value, + buffer, sizeof(buffer), 0); + ap_cpystrn(current->right->token.value, buffer, + sizeof(current->right->token.value)); + current->right->value = (current->right->token.value[0] != '\0'); + current->right->done = 1; + break; + default: + current = current->right; + continue; + } + } +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Left: ", current->left->value ? "1" : "0", + "\n", NULL); + ap_rvputs(r, " Right: ", current->right->value ? "1" : "0", + "\n", NULL); +#endif + if (current->token.type == token_and) { + current->value = current->left->value && current->right->value; + } + else { + current->value = current->left->value || current->right->value; + } +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Returning ", current->value ? "1" : "0", + "\n", NULL); +#endif + current->done = 1; + current = current->parent; + break; + + case token_eq: + case token_ne: +#ifdef DEBUG_INCLUDE + ap_rputs(" Evaluate eq/ne\n", r); +#endif + if ((current->left == (struct parse_node *) NULL) || + (current->right == (struct parse_node *) NULL) || + (current->left->token.type != token_string) || + (current->right->token.type != token_string)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + parse_string(r, current->left->token.value, + buffer, sizeof(buffer), 0); + ap_cpystrn(current->left->token.value, buffer, + sizeof(current->left->token.value)); + parse_string(r, current->right->token.value, + buffer, sizeof(buffer), 0); + ap_cpystrn(current->right->token.value, buffer, + sizeof(current->right->token.value)); + if (current->right->token.value[0] == '/') { + int len; + len = strlen(current->right->token.value); + if (current->right->token.value[len - 1] == '/') { + current->right->token.value[len - 1] = '\0'; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid rexp \"%s\" in file %s", + current->right->token.value, r->filename); + ap_rputs(error, r); + goto RETURN; + } +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Re Compare (", current->left->token.value, + ") with /", ¤t->right->token.value[1], "/\n", NULL); +#endif + current->value = + re_check(r, current->left->token.value, + ¤t->right->token.value[1]); + } + else { +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Compare (", current->left->token.value, + ") with (", current->right->token.value, ")\n", NULL); +#endif + current->value = + (strcmp(current->left->token.value, + current->right->token.value) == 0); + } + if (current->token.type == token_ne) { + current->value = !current->value; + } +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Returning ", current->value ? "1" : "0", + "\n", NULL); +#endif + current->done = 1; + current = current->parent; + break; + case token_ge: + case token_gt: + case token_le: + case token_lt: +#ifdef DEBUG_INCLUDE + ap_rputs(" Evaluate ge/gt/le/lt\n", r); +#endif + if ((current->left == (struct parse_node *) NULL) || + (current->right == (struct parse_node *) NULL) || + (current->left->token.type != token_string) || + (current->right->token.type != token_string)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid expression \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + } + parse_string(r, current->left->token.value, + buffer, sizeof(buffer), 0); + ap_cpystrn(current->left->token.value, buffer, + sizeof(current->left->token.value)); + parse_string(r, current->right->token.value, + buffer, sizeof(buffer), 0); + ap_cpystrn(current->right->token.value, buffer, + sizeof(current->right->token.value)); +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Compare (", current->left->token.value, + ") with (", current->right->token.value, ")\n", NULL); +#endif + current->value = + strcmp(current->left->token.value, + current->right->token.value); + if (current->token.type == token_ge) { + current->value = current->value >= 0; + } + else if (current->token.type == token_gt) { + current->value = current->value > 0; + } + else if (current->token.type == token_le) { + current->value = current->value <= 0; + } + else if (current->token.type == token_lt) { + current->value = current->value < 0; + } + else { + current->value = 0; /* Don't return -1 if unknown token */ + } +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Returning ", current->value ? "1" : "0", + "\n", NULL); +#endif + current->done = 1; + current = current->parent; + break; + + case token_not: + if (current->right != (struct parse_node *) NULL) { + if (!current->right->done) { + current = current->right; + continue; + } + current->value = !current->right->value; + } + else { + current->value = 0; + } +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Evaluate !: ", current->value ? "1" : "0", + "\n", NULL); +#endif + current->done = 1; + current = current->parent; + break; + + case token_group: + if (current->right != (struct parse_node *) NULL) { + if (!current->right->done) { + current = current->right; + continue; + } + current->value = current->right->value; + } + else { + current->value = 1; + } +#ifdef DEBUG_INCLUDE + ap_rvputs(r, " Evaluate (): ", current->value ? "1" : "0", + "\n", NULL); +#endif + current->done = 1; + current = current->parent; + break; + + case token_lbrace: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Unmatched '(' in \"%s\" in file %s", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + + case token_rbrace: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Unmatched ')' in \"%s\" in file %s\n", + expr, r->filename); + ap_rputs(error, r); + goto RETURN; + + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "bad token type"); + ap_rputs(error, r); + goto RETURN; + } + } + + retval = (root == (struct parse_node *) NULL) ? 0 : root->value; + RETURN: + ap_destroy_pool(expr_pool); + return (retval); +} + +static int handle_if(FILE *in, request_rec *r, const char *error, + int *conditional_status, int *printing) +{ + char tag[MAX_STRING_LEN]; + char *tag_val; + char *expr; + + expr = NULL; + while (1) { + tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0); + if (*tag == '\0') { + return 1; + } + else if (!strcmp(tag, "done")) { + if (expr == NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "missing expr in if statement: %s", + r->filename); + ap_rputs(error, r); + return 1; + } + *printing = *conditional_status = parse_expr(r, expr, error); +#ifdef DEBUG_INCLUDE + ap_rvputs(r, "**** if conditional_status=\"", + *conditional_status ? "1" : "0", "\"\n", NULL); +#endif + return 0; + } + else if (!strcmp(tag, "expr")) { + expr = tag_val; +#ifdef DEBUG_INCLUDE + ap_rvputs(r, "**** if expr=\"", expr, "\"\n", NULL); +#endif + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "unknown parameter \"%s\" to tag if in %s", + tag, r->filename); + ap_rputs(error, r); + } + } +} + +static int handle_elif(FILE *in, request_rec *r, const char *error, + int *conditional_status, int *printing) +{ + char tag[MAX_STRING_LEN]; + char *tag_val; + char *expr; + + expr = NULL; + while (1) { + tag_val = get_tag(r->pool, in, tag, sizeof(tag), 0); + if (*tag == '\0') { + return 1; + } + else if (!strcmp(tag, "done")) { +#ifdef DEBUG_INCLUDE + ap_rvputs(r, "**** elif conditional_status=\"", + *conditional_status ? "1" : "0", "\"\n", NULL); +#endif + if (*conditional_status) { + *printing = 0; + return (0); + } + if (expr == NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "missing expr in elif statement: %s", + r->filename); + ap_rputs(error, r); + return 1; + } + *printing = *conditional_status = parse_expr(r, expr, error); +#ifdef DEBUG_INCLUDE + ap_rvputs(r, "**** elif conditional_status=\"", + *conditional_status ? "1" : "0", "\"\n", NULL); +#endif + return 0; + } + else if (!strcmp(tag, "expr")) { + expr = tag_val; +#ifdef DEBUG_INCLUDE + ap_rvputs(r, "**** if expr=\"", expr, "\"\n", NULL); +#endif + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "unknown parameter \"%s\" to tag if in %s", + tag, r->filename); + ap_rputs(error, r); + } + } +} + +static int handle_else(FILE *in, request_rec *r, const char *error, + int *conditional_status, int *printing) +{ + char tag[MAX_STRING_LEN]; + + if (!get_tag(r->pool, in, tag, sizeof(tag), 1)) { + return 1; + } + else if (!strcmp(tag, "done")) { +#ifdef DEBUG_INCLUDE + ap_rvputs(r, "**** else conditional_status=\"", + *conditional_status ? "1" : "0", "\"\n", NULL); +#endif + *printing = !(*conditional_status); + *conditional_status = 1; + return 0; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "else directive does not take tags in %s", + r->filename); + if (*printing) { + ap_rputs(error, r); + } + return -1; + } +} + +static int handle_endif(FILE *in, request_rec *r, const char *error, + int *conditional_status, int *printing) +{ + char tag[MAX_STRING_LEN]; + + if (!get_tag(r->pool, in, tag, sizeof(tag), 1)) { + return 1; + } + else if (!strcmp(tag, "done")) { +#ifdef DEBUG_INCLUDE + ap_rvputs(r, "**** endif conditional_status=\"", + *conditional_status ? "1" : "0", "\"\n", NULL); +#endif + *printing = 1; + *conditional_status = 1; + return 0; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "endif directive does not take tags in %s", + r->filename); + ap_rputs(error, r); + return -1; + } +} + +static int handle_set(FILE *in, request_rec *r, const char *error) +{ + char tag[MAX_STRING_LEN]; + char parsed_string[MAX_STRING_LEN]; + char *tag_val; + char *var; + + var = (char *) NULL; + while (1) { + if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { + return 1; + } + else if (!strcmp(tag, "done")) { + return 0; + } + else if (!strcmp(tag, "var")) { + var = tag_val; + } + else if (!strcmp(tag, "value")) { + if (var == (char *) NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "variable must precede value in set directive in %s", + r->filename); + ap_rputs(error, r); + return -1; + } + parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); + ap_table_setn(r->subprocess_env, var, ap_pstrdup(r->pool, parsed_string)); + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Invalid tag for set directive in %s", r->filename); + ap_rputs(error, r); + return -1; + } + } +} + +static int handle_printenv(FILE *in, request_rec *r, const char *error) +{ + char tag[MAX_STRING_LEN]; + char *tag_val; + array_header *arr = table_elts(r->subprocess_env); + table_entry *elts = (table_entry *) arr->elts; + int i; + + if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { + return 1; + } + else if (!strcmp(tag, "done")) { + for (i = 0; i < arr->nelts; ++i) { + ap_rvputs(r, elts[i].key, "=", elts[i].val, "\n", NULL); + } + return 0; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "printenv directive does not take tags in %s", + r->filename); + ap_rputs(error, r); + return -1; + } +} + + + +/* -------------------------- The main function --------------------------- */ + +/* This is a stub which parses a file descriptor. */ + +static void send_parsed_content(FILE *f, request_rec *r) +{ + char directive[MAX_STRING_LEN], error[MAX_STRING_LEN]; + char timefmt[MAX_STRING_LEN]; + int noexec = ap_allow_options(r) & OPT_INCNOEXEC; + int ret, sizefmt; + int if_nesting; + int printing; + int conditional_status; + + ap_cpystrn(error, DEFAULT_ERROR_MSG, sizeof(error)); + ap_cpystrn(timefmt, DEFAULT_TIME_FORMAT, sizeof(timefmt)); + sizefmt = SIZEFMT_KMG; + +/* Turn printing on */ + printing = conditional_status = 1; + if_nesting = 0; + +#ifndef WIN32 + ap_chdir_file(r->filename); +#endif + if (r->args) { /* add QUERY stuff to env cause it ain't yet */ + char *arg_copy = ap_pstrdup(r->pool, r->args); + + ap_table_setn(r->subprocess_env, "QUERY_STRING", r->args); + ap_unescape_url(arg_copy); + ap_table_setn(r->subprocess_env, "QUERY_STRING_UNESCAPED", + ap_escape_shell_cmd(r->pool, arg_copy)); + } + + while (1) { + if (!find_string(f, STARTING_SEQUENCE, r, printing)) { + if (get_directive(f, directive, sizeof(directive), r->pool)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "mod_include: error reading directive in %s", + r->filename); + ap_rputs(error, r); + return; + } + if (!strcmp(directive, "if")) { + if (!printing) { + if_nesting++; + } + else { + ret = handle_if(f, r, error, &conditional_status, + &printing); + if_nesting = 0; + } + continue; + } + else if (!strcmp(directive, "else")) { + if (!if_nesting) { + ret = handle_else(f, r, error, &conditional_status, + &printing); + } + continue; + } + else if (!strcmp(directive, "elif")) { + if (!if_nesting) { + ret = handle_elif(f, r, error, &conditional_status, + &printing); + } + continue; + } + else if (!strcmp(directive, "endif")) { + if (!if_nesting) { + ret = handle_endif(f, r, error, &conditional_status, + &printing); + } + else { + if_nesting--; + } + continue; + } + if (!printing) { + continue; + } + if (!strcmp(directive, "exec")) { + if (noexec) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "httpd: exec used but not allowed in %s", + r->filename); + if (printing) { + ap_rputs(error, r); + } + ret = find_string(f, ENDING_SEQUENCE, r, 0); + } + else { + ret = handle_exec(f, r, error); + } + } + else if (!strcmp(directive, "config")) { + ret = handle_config(f, r, error, timefmt, &sizefmt); + } + else if (!strcmp(directive, "set")) { + ret = handle_set(f, r, error); + } + else if (!strcmp(directive, "include")) { + ret = handle_include(f, r, error, noexec); + } + else if (!strcmp(directive, "echo")) { + ret = handle_echo(f, r, error); + } + else if (!strcmp(directive, "fsize")) { + ret = handle_fsize(f, r, error, sizefmt); + } + else if (!strcmp(directive, "flastmod")) { + ret = handle_flastmod(f, r, error, timefmt); + } + else if (!strcmp(directive, "printenv")) { + ret = handle_printenv(f, r, error); + } +#ifdef USE_PERL_SSI + else if (!strcmp(directive, "perl")) { + ret = handle_perl(f, r, error); + } +#endif + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "httpd: unknown directive \"%s\" " + "in parsed doc %s", + directive, r->filename); + if (printing) { + ap_rputs(error, r); + } + ret = find_string(f, ENDING_SEQUENCE, r, 0); + } + if (ret) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "httpd: premature EOF in parsed file %s", + r->filename); + return; + } + } + else { + return; + } + } +} + +/***************************************************************** + * + * XBITHACK. Sigh... NB it's configurable per-directory; the compile-time + * option only changes the default. + */ + +module includes_module; +enum xbithack { + xbithack_off, xbithack_on, xbithack_full +}; + +#ifdef XBITHACK +#define DEFAULT_XBITHACK xbithack_full +#else +#define DEFAULT_XBITHACK xbithack_off +#endif + +static void *create_includes_dir_config(pool *p, char *dummy) +{ + enum xbithack *result = (enum xbithack *) ap_palloc(p, sizeof(enum xbithack)); + *result = DEFAULT_XBITHACK; + return result; +} + +static const char *set_xbithack(cmd_parms *cmd, void *xbp, char *arg) +{ + enum xbithack *state = (enum xbithack *) xbp; + + if (!strcasecmp(arg, "off")) { + *state = xbithack_off; + } + else if (!strcasecmp(arg, "on")) { + *state = xbithack_on; + } + else if (!strcasecmp(arg, "full")) { + *state = xbithack_full; + } + else { + return "XBitHack must be set to Off, On, or Full"; + } + + return NULL; +} + +static int send_parsed_file(request_rec *r) +{ + FILE *f; + enum xbithack *state = + (enum xbithack *) ap_get_module_config(r->per_dir_config, &includes_module); + int errstatus; + request_rec *parent; + + if (!(ap_allow_options(r) & OPT_INCLUDES)) { + return DECLINED; + } + r->allowed |= (1 << M_GET); + if (r->method_number != M_GET) { + return DECLINED; + } + if (r->finfo.st_mode == 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "File does not exist: %s", + (r->path_info + ? ap_pstrcat(r->pool, r->filename, r->path_info, NULL) + : r->filename)); + return HTTP_NOT_FOUND; + } + + if (!(f = ap_pfopen(r->pool, r->filename, "r"))) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "file permissions deny server access: %s", r->filename); + return HTTP_FORBIDDEN; + } + + if ((*state == xbithack_full) +#if !defined(__EMX__) && !defined(WIN32) + /* OS/2 dosen't support Groups. */ + && (r->finfo.st_mode & S_IXGRP) +#endif + ) { + ap_update_mtime(r, r->finfo.st_mtime); + ap_set_last_modified(r); + } + if ((errstatus = ap_meets_conditions(r)) != OK) { + return errstatus; + } + + ap_send_http_header(r); + + if (r->header_only) { + ap_pfclose(r->pool, f); + return OK; + } + + if ((parent = ap_get_module_config(r->request_config, &includes_module))) { + /* Kludge --- for nested includes, we want to keep the subprocess + * environment of the base document (for compatibility); that means + * torquing our own last_modified date as well so that the + * LAST_MODIFIED variable gets reset to the proper value if the + * nested document resets . + * We also insist that the memory for this subrequest not be + * destroyed, that's dealt with in handle_include(). + */ + r->subprocess_env = parent->subprocess_env; + ap_pool_join(parent->pool, r->pool); + r->finfo.st_mtime = parent->finfo.st_mtime; + } + else { + /* we're not a nested include, so we create an initial + * environment */ + ap_add_common_vars(r); + ap_add_cgi_vars(r); + add_include_vars(r, DEFAULT_TIME_FORMAT); + } + /* XXX: this is bogus, at some point we're going to do a subrequest, + * and when we do it we're going to be subjecting code that doesn't + * expect to be signal-ready to SIGALRM. There is no clean way to + * fix this, except to put alarm support into BUFF. -djg + */ + ap_hard_timeout("send SSI", r); + +#ifdef CHARSET_EBCDIC + /* XXX:@@@ Is the generated/included output ALWAYS in text/ebcdic format? */ + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1); +#endif + + send_parsed_content(f, r); + + if (parent) { + /* signify that the sub request should not be killed */ + ap_set_module_config(r->request_config, &includes_module, + NESTED_INCLUDE_MAGIC); + } + + ap_kill_timeout(r); + return OK; +} + +static int send_shtml_file(request_rec *r) +{ + r->content_type = "text/html"; + return send_parsed_file(r); +} + +static int xbithack_handler(request_rec *r) +{ +#if defined(__EMX__) || defined(WIN32) + /* OS/2 dosen't currently support the xbithack. This is being worked on. */ + return DECLINED; +#else + enum xbithack *state; + + if (!(r->finfo.st_mode & S_IXUSR)) { + return DECLINED; + } + + state = (enum xbithack *) ap_get_module_config(r->per_dir_config, + &includes_module); + + if (*state == xbithack_off) { + return DECLINED; + } + return send_parsed_file(r); +#endif +} + +static const command_rec includes_cmds[] = +{ + {"XBitHack", set_xbithack, NULL, OR_OPTIONS, TAKE1, "Off, On, or Full"}, + {NULL} +}; + +static const handler_rec includes_handlers[] = +{ + {INCLUDES_MAGIC_TYPE, send_shtml_file}, + {INCLUDES_MAGIC_TYPE3, send_shtml_file}, + {"server-parsed", send_parsed_file}, + {"text/html", xbithack_handler}, + {NULL} +}; + +module MODULE_VAR_EXPORT includes_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_includes_dir_config, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + includes_cmds, /* command table */ + includes_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_info.c b/APACHE_1_3b7/src/modules/standard/mod_info.c new file mode 100644 index 0000000000..6b881abd57 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_info.c @@ -0,0 +1,694 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * Info Module. Display configuration information for the server and + * all included modules. + * + * + * SetHandler server-info + * + * + * GET /server-info - Returns full configuration page for server and all modules + * GET /server-info?server - Returns server configuration only + * GET /server-info?module_name - Returns configuration for a single module + * GET /server-info?list - Returns quick list of included modules + * + * Rasmus Lerdorf , May 1996 + * + * 05.01.96 Initial Version + * + * Lou Langholtz , July 1997 + * + * 07.11.97 Addition of the AddModuleInfo directive + * + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_main.h" +#include "http_protocol.h" +#include "util_script.h" +#include "http_conf_globals.h" + +typedef struct { + char *name; /* matching module name */ + char *info; /* additional info */ +} info_entry; + +typedef struct { + array_header *more_info; +} info_svr_conf; + +typedef struct info_cfg_lines { + char *cmd; + char *line; + struct info_cfg_lines *next; +} info_cfg_lines; + +module MODULE_VAR_EXPORT info_module; +extern module *top_module; + +static void *create_info_config(pool *p, server_rec *s) +{ + info_svr_conf *conf = (info_svr_conf *) ap_pcalloc(p, sizeof(info_svr_conf)); + + conf->more_info = ap_make_array(p, 20, sizeof(info_entry)); + return conf; +} + +static void *merge_info_config(pool *p, void *basev, void *overridesv) +{ + info_svr_conf *new = (info_svr_conf *) ap_pcalloc(p, sizeof(info_svr_conf)); + info_svr_conf *base = (info_svr_conf *) basev; + info_svr_conf *overrides = (info_svr_conf *) overridesv; + + new->more_info = ap_append_arrays(p, overrides->more_info, base->more_info); + return new; +} + +static char *mod_info_html_cmd_string(const char *string, char *buf, size_t buf_len) +{ + const char *s; + char *t; + char *end_buf; + + s = string; + t = buf; + /* keep space for \0 byte */ + end_buf = buf + buf_len - 1; + while ((*s) && (t < end_buf)) { + if (*s == '<') { + strncpy(t, "<", end_buf - t); + t += 4; + } + else if (*s == '>') { + strncpy(t, ">", end_buf - t); + t += 4; + } + else if (*s == '&') { + strncpy(t, "&", end_buf - t); + t += 5; + } + else { + *t++ = *s; + } + s++; + } + /* oops, overflowed... don't overwrite */ + if (t > end_buf) { + *end_buf = '\0'; + } + else { + *t = '\0'; + } + return (buf); +} + +static info_cfg_lines *mod_info_load_config(pool *p, const char *filename, + request_rec *r) +{ + char s[MAX_STRING_LEN]; + configfile_t *fp; + info_cfg_lines *new, *ret, *prev; + const char *t; + + fp = ap_pcfg_openfile(p, filename); + if (!fp) { + ap_log_error(APLOG_MARK, APLOG_WARNING, r->server, + "mod_info: couldn't open config file %s", + filename); + return NULL; + } + ret = NULL; + prev = NULL; + while (!ap_cfg_getline(s, MAX_STRING_LEN, fp)) { + if (*s == '#') { + continue; /* skip comments */ + } + new = ap_palloc(p, sizeof(struct info_cfg_lines)); + new->next = NULL; + if (!ret) { + ret = new; + } + if (prev) { + prev->next = new; + } + t = s; + new->cmd = ap_getword_conf(p, &t); + if (*t) { + new->line = ap_pstrdup(p, t); + } + else { + new->line = NULL; + } + prev = new; + } + ap_cfg_closefile(fp); + return (ret); +} + +static void mod_info_module_cmds(request_rec *r, info_cfg_lines *cfg, + const command_rec *cmds, char *label) +{ + const command_rec *cmd = cmds; + info_cfg_lines *li = cfg, *li_st = NULL, *li_se = NULL; + info_cfg_lines *block_start = NULL; + int lab = 0, nest = 0; + char buf[MAX_STRING_LEN]; + + while (li) { + if (!strncasecmp(li->cmd, "cmd, "cmd, "cmd, "next; + nest++; + continue; + } + else if (nest && (!strncasecmp(li->cmd, "cmd, "cmd, "cmd, "", r); + if (nest == 2) { + ap_rputs("  ", r); + } + ap_rputs(mod_info_html_cmd_string(li->cmd, buf, sizeof(buf)), r); + ap_rputs(" ", r); + if (li->line) { + ap_rputs(mod_info_html_cmd_string(li->line, buf, sizeof(buf)), r); + } + ap_rputs("\n", r); + nest--; + if (!nest) { + block_start = NULL; + li_st = NULL; + } + else { + block_start = li_st; + } + li_se = NULL; + } + else { + nest--; + if (!nest) { + li_st = NULL; + } + li_se = NULL; + } + } + else { + nest--; + if (!nest) { + li_st = NULL; + } + li_se = NULL; + } + li = li->next; + continue; + } + cmd = cmds; + while (cmd) { + if (cmd->name) { + if (!strcasecmp(cmd->name, li->cmd)) { + if (!lab) { + ap_rputs("
    ", r); + ap_rputs(label, r); + ap_rputs("\n", r); + lab = 1; + } + if (((nest && block_start == NULL) || + (nest == 2 && block_start == li_st)) && + (strncasecmp(li->cmd, "cmd, "cmd, "cmd, "cmd, "cmd, "cmd, "", r); + ap_rputs(mod_info_html_cmd_string(li_st->cmd, buf, sizeof(buf)), r); + ap_rputs(" ", r); + if (li_st->line) { + ap_rputs(mod_info_html_cmd_string(li_st->line, buf, sizeof(buf)), r); + } + ap_rputs("\n", r); + block_start = li_st; + if (li_se) { + ap_rputs("
      ", r); + ap_rputs(mod_info_html_cmd_string(li_se->cmd, buf, sizeof(buf)), r); + ap_rputs(" ", r); + if (li_se->line) { + ap_rputs(mod_info_html_cmd_string(li_se->line, buf, sizeof(buf)), r); + } + ap_rputs("\n", r); + block_start = li_se; + } + } + ap_rputs("
    ", r); + if (nest) { + ap_rputs("  ", r); + } + if (nest == 2) { + ap_rputs("  ", r); + } + ap_rputs(mod_info_html_cmd_string(li->cmd, buf, sizeof(buf)), r); + if (li->line) { + ap_rputs(" ", r); + ap_rputs(mod_info_html_cmd_string(li->line, buf, sizeof(buf)), r); + ap_rputs("", r); + } + ap_rputs("", r); + } + } + else + break; + cmd++; + } + li = li->next; + } +} + +static char *find_more_info(server_rec *s, const char *module_name) +{ + int i; + info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config, + &info_module); + info_entry *entry = (info_entry *) conf->more_info->elts; + + if (!module_name) { + return 0; + } + for (i = 0; i < conf->more_info->nelts; i++) { + if (!strcmp(module_name, entry->name)) { + return entry->info; + } + entry++; + } + return 0; +} + +static int display_info(request_rec *r) +{ + module *modp = NULL; + char buf[MAX_STRING_LEN], *cfname; + char *more_info; + const command_rec *cmd = NULL; + const handler_rec *hand = NULL; + server_rec *serv = r->server; + int comma = 0; + info_cfg_lines *mod_info_cfg_httpd = NULL; + info_cfg_lines *mod_info_cfg_srm = NULL; + info_cfg_lines *mod_info_cfg_access = NULL; + + r->allowed |= (1 << M_GET); + if (r->method_number != M_GET) + return DECLINED; + + r->content_type = "text/html"; + ap_send_http_header(r); + if (r->header_only) { + return 0; + } + ap_hard_timeout("send server info", r); + + ap_rputs("Server Information\n", r); + ap_rputs("

    Apache Server Information

    \n", r); + if (!r->args || strcasecmp(r->args, "list")) { + cfname = ap_server_root_relative(r->pool, ap_server_confname); + mod_info_cfg_httpd = mod_info_load_config(r->pool, cfname, r); + cfname = ap_server_root_relative(r->pool, serv->srm_confname); + mod_info_cfg_srm = mod_info_load_config(r->pool, cfname, r); + cfname = ap_server_root_relative(r->pool, serv->access_confname); + mod_info_cfg_access = mod_info_load_config(r->pool, cfname, r); + if (!r->args) { + ap_rputs("Server Settings, ", r); + for (modp = top_module; modp; modp = modp->next) { + ap_rprintf(r, "%s", modp->name, modp->name); + if (modp->next) { + ap_rputs(", ", r); + } + } + ap_rputs("
    ", r); + + } + if (!r->args || !strcasecmp(r->args, "server")) { + ap_rprintf(r, "Server Version: " + "%s
    \n", + ap_get_server_version()); + ap_rprintf(r, "Server Built: " + "%s
    \n", + ap_get_server_built()); + ap_rprintf(r, "API Version: " + "%d
    \n", + MODULE_MAGIC_NUMBER); + ap_rprintf(r, "Run Mode: %s
    \n", + (ap_standalone ? "standalone" : "inetd")); + ap_rprintf(r, "User/Group: " + "%s(%d)/%d
    \n", + ap_user_name, (int) ap_user_id, (int) ap_group_id); + ap_rprintf(r, "Hostname/port: " + "%s:%u
    \n", + serv->server_hostname, serv->port); + ap_rprintf(r, "Daemons: " + "start: %d    " + "min idle: %d    " + "max idle: %d    " + "max: %d
    \n", + ap_daemons_to_start, ap_daemons_min_free, + ap_daemons_max_free, ap_daemons_limit); + ap_rprintf(r, "Max Requests: " + "per child: %d    " + "keep alive: %s    " + "max per connection: %d
    \n", + ap_max_requests_per_child, + (serv->keep_alive ? "on" : "off"), + serv->keep_alive_max); + ap_rprintf(r, "Threads: " + "per child: %d   
    \n", + ap_threads_per_child); + ap_rprintf(r, "Excess requests: " + "per child: %d   
    \n", + ap_excess_requests_per_child); + ap_rprintf(r, "Timeouts: " + "connection: %d    " + "keep-alive: %d
    ", + serv->timeout, serv->keep_alive_timeout); + ap_rprintf(r, "Server Root: " + "%s
    \n", ap_server_root); + ap_rprintf(r, "Config File: " + "%s
    \n", ap_server_confname); + ap_rprintf(r, "PID File: " + "%s
    \n", ap_pid_fname); + ap_rprintf(r, "Scoreboard File: " + "%s
    \n", ap_scoreboard_fname); + } + ap_rputs("
    ", r); + for (modp = top_module; modp; modp = modp->next) { + if (!r->args || !strcasecmp(modp->name, r->args)) { + ap_rprintf(r, "
    Module Name: " + "%s\n", + modp->name, modp->name); + ap_rputs("
    Content handlers:", r); + hand = modp->handlers; + if (hand) { + while (hand) { + if (hand->content_type) { + ap_rprintf(r, " %s\n", hand->content_type); + } + else { + break; + } + hand++; + if (hand && hand->content_type) { + ap_rputs(",", r); + } + } + } + else { + ap_rputs(" none", r); + } + ap_rputs("
    Configuration Phase Participation: \n", + r); + if (modp->child_init) { + ap_rputs("Child Init", r); + comma = 1; + } + if (modp->create_dir_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Create Directory Config", r); + comma = 1; + } + if (modp->merge_dir_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Merge Directory Configs", r); + comma = 1; + } + if (modp->create_server_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Create Server Config", r); + comma = 1; + } + if (modp->merge_server_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Merge Server Configs", r); + comma = 1; + } + if (modp->child_exit) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Child Exit", r); + comma = 1; + } + if (!comma) + ap_rputs(" none", r); + comma = 0; + ap_rputs("
    Request Phase Participation: \n", + r); + if (modp->post_read_request) { + ap_rputs("Post-Read Request", r); + comma = 1; + } + if (modp->header_parser) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Header Parse", r); + comma = 1; + } + if (modp->translate_handler) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Translate Path", r); + comma = 1; + } + if (modp->access_checker) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Check Access", r); + comma = 1; + } + if (modp->ap_check_user_id) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Verify User ID", r); + comma = 1; + } + if (modp->auth_checker) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Verify User Access", r); + comma = 1; + } + if (modp->type_checker) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Check Type", r); + comma = 1; + } + if (modp->fixer_upper) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Fixups", r); + comma = 1; + } + if (modp->logger) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Logging", r); + comma = 1; + } + if (!comma) + ap_rputs(" none", r); + comma = 0; + ap_rputs("
    Module Directives: ", r); + cmd = modp->cmds; + if (cmd) { + while (cmd) { + if (cmd->name) { + ap_rprintf(r, "
    %s - ", + mod_info_html_cmd_string(cmd->name, + buf, sizeof(buf))); + if (cmd->errmsg) { + ap_rputs(cmd->errmsg, r); + } + ap_rputs("\n", r); + } + else { + break; + } + cmd++; + } + ap_rputs("
    Current Configuration:\n", r); + mod_info_module_cmds(r, mod_info_cfg_httpd, modp->cmds, + "httpd.conf"); + mod_info_module_cmds(r, mod_info_cfg_srm, modp->cmds, + "srm.conf"); + mod_info_module_cmds(r, mod_info_cfg_access, modp->cmds, + "access.conf"); + } + else { + ap_rputs(" none\n", r); + } + more_info = find_more_info(serv, modp->name); + if (more_info) { + ap_rputs("
    Additional Information:\n
    ", + r); + ap_rputs(more_info, r); + } + ap_rputs("

    \n", r); + if (r->args) { + break; + } + } + } + if (!modp && r->args && strcasecmp(r->args, "server")) { + ap_rputs("No such module\n", r); + } + } + else { + for (modp = top_module; modp; modp = modp->next) { + ap_rputs(modp->name, r); + if (modp->next) { + ap_rputs("
    ", r); + } + } + } + ap_rputs("
    \n", r); + ap_rputs(ap_psignature("",r), r); + ap_rputs("\n", r); + /* Done, turn off timeout, close file and return */ + ap_kill_timeout(r); + return 0; +} + +static const char *add_module_info(cmd_parms *cmd, void *dummy, char *name, + char *info) +{ + server_rec *s = cmd->server; + info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config, + &info_module); + info_entry *new = ap_push_array(conf->more_info); + + new->name = name; + new->info = info; + return NULL; +} + +static const command_rec info_cmds[] = +{ + {"AddModuleInfo", add_module_info, NULL, RSRC_CONF, TAKE2, + "a module name and additional information on that module"}, + {NULL} +}; + +static const handler_rec info_handlers[] = +{ + {"server-info", display_info}, + {NULL} +}; + +module MODULE_VAR_EXPORT info_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + create_info_config, /* server config */ + merge_info_config, /* merge server config */ + info_cmds, /* command table */ + info_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_log_agent.c b/APACHE_1_3b7/src/modules/standard/mod_log_agent.c new file mode 100644 index 0000000000..1bbf12e422 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_log_agent.c @@ -0,0 +1,188 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" + +module agent_log_module; + +static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT); +#ifdef __EMX__ +/* OS/2 dosen't support users and groups */ +static mode_t xfer_mode = (S_IREAD | S_IWRITE); +#else +static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#endif + +typedef struct { + char *fname; + int agent_fd; +} agent_log_state; + +static void *make_agent_log_state(pool *p, server_rec *s) +{ + agent_log_state *cls = + (agent_log_state *) ap_palloc(p, sizeof(agent_log_state)); + + cls->fname = ""; + cls->agent_fd = -1; + + return (void *) cls; +} + +static const char *set_agent_log(cmd_parms *parms, void *dummy, char *arg) +{ + agent_log_state *cls = ap_get_module_config(parms->server->module_config, + &agent_log_module); + + cls->fname = arg; + return NULL; +} + +static const command_rec agent_log_cmds[] = +{ + {"AgentLog", set_agent_log, NULL, RSRC_CONF, TAKE1, + "the filename of the agent log"}, + {NULL} +}; + +static void open_agent_log(server_rec *s, pool *p) +{ + agent_log_state *cls = ap_get_module_config(s->module_config, + &agent_log_module); + + char *fname = ap_server_root_relative(p, cls->fname); + + if (cls->agent_fd > 0) + return; /* virtual log shared w/main server */ + + if (*cls->fname == '|') { + piped_log *pl; + + pl = ap_open_piped_log(p, cls->fname + 1); + if (pl == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, s, + "couldn't spawn agent log pipe"); + exit(1); + } + cls->agent_fd = ap_piped_log_write_fd(pl); + } + else if (*cls->fname != '\0') { + if ((cls->agent_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) { + perror("open"); + fprintf(stderr, "httpd: could not open agent log file %s.\n", fname); + exit(1); + } + } +} + +static void init_agent_log(server_rec *s, pool *p) +{ + for (; s; s = s->next) + open_agent_log(s, p); +} + +static int agent_log_transaction(request_rec *orig) +{ + agent_log_state *cls = ap_get_module_config(orig->server->module_config, + &agent_log_module); + + char str[HUGE_STRING_LEN]; + char *agent; + request_rec *r; + + if (cls->agent_fd < 0) + return OK; + + for (r = orig; r->next; r = r->next) + continue; + if (*cls->fname == '\0') /* Don't log agent */ + return DECLINED; + + agent = ap_table_get(orig->headers_in, "User-Agent"); + if (agent != NULL) { + ap_snprintf(str, sizeof(str), "%s\n", agent); + write(cls->agent_fd, str, strlen(str)); + } + + return OK; +} + +module agent_log_module = +{ + STANDARD_MODULE_STUFF, + init_agent_log, /* initializer */ + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + make_agent_log_state, /* server config */ + NULL, /* merge server config */ + agent_log_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + agent_log_transaction, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_log_config.c b/APACHE_1_3b7/src/modules/standard/mod_log_config.c new file mode 100644 index 0000000000..cab154c203 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_log_config.c @@ -0,0 +1,1031 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * Modified by djm@va.pubnix.com: + * If no TransferLog is given explicitly, decline to log. + * + * This is module implements the TransferLog directive (same as the + * common log module), and additional directives, LogFormat and CustomLog. + * + * + * Syntax: + * + * TransferLog fn Logs transfers to fn in standard log format, unless + * a custom format is set with LogFormat + * LogFormat format Set a log format from TransferLog files + * CustomLog fn format + * Log to file fn with format given by the format + * argument + * + * CookieLog fn For backwards compatability with old Cookie + * logging module - now deprecated. + * + * There can be any number of TransferLog and CustomLog + * commands. Each request will be logged to _ALL_ the + * named files, in the appropriate format. + * + * If no TransferLog or CustomLog directive appears in a VirtualHost, + * the request will be logged to the log file(s) defined outside + * the virtual host section. If a TransferLog or CustomLog directive + * appears in the VirtualHost section, the log files defined outside + * the VirtualHost will _not_ be used. This makes this module compatable + * with the CLF and config log modules, where the use of TransferLog + * inside the VirtualHost section overrides its use outside. + * + * Examples: + * + * TransferLog logs/access_log + * + * LogFormat "... custom format ..." + * TransferLog log/virtual_only + * CustomLog log/virtual_useragents "%t %{user-agent}i" + * + * + * This will log using CLF to access_log any requests handled by the + * main server, while any requests to the virtual host will be logged + * with the "... custom format..." to virtual_only _AND_ using + * the custom user-agent log to virtual_useragents. + * + * Note that the NCSA referer and user-agent logs are easily added with + * CustomLog: + * CustomLog logs/referer "%{referer}i -> %U" + * CustomLog logs/agent "%{user-agent}i" + * + * Except: no RefererIgnore functionality + * logs '-' if no Referer or User-Agent instead of nothing + * + * But using this method allows much easier modification of the + * log format, e.g. to log hosts along with UA: + * CustomLog logs/referer "%{referer}i %U %h" + * + * The argument to LogFormat and CustomLog is a string, which can include + * literal characters copied into the log files, and '%' directives as + * follows: + * + * %...b: bytes sent, excluding HTTP headers. + * %...{FOOBAR}e: The contents of the environment variable FOOBAR + * %...f: filename + * %...h: remote host + * %...a: remote IP-address + * %...{Foobar}i: The contents of Foobar: header line(s) in the request + * sent to the client. + * %...l: remote logname (from identd, if supplied) + * %...{Foobar}n: The contents of note "Foobar" from another module. + * %...{Foobar}o: The contents of Foobar: header line(s) in the reply. + * %...p: the port the request was served to + * %...P: the process ID of the child that serviced the request. + * %...r: first line of request + * %...s: status. For requests that got internally redirected, this + * is status of the *original* request --- %...>s for the last. + * %...t: time, in common log format time format + * %...{format}t: The time, in the form given by format, which should + * be in strftime(3) format. + * %...T: the time taken to serve the request, in seconds. + * %...u: remote user (from auth; may be bogus if return status (%s) is 401) + * %...U: the URL path requested. + * %...v: the name of the server (i.e. which virtual host?) + * + * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can + * indicate conditions for inclusion of the item (which will cause it + * to be replaced with '-' if the condition is not met). Note that + * there is no escaping performed on the strings from %r, %...i and + * %...o; some with long memories may remember that I thought this was + * a bad idea, once upon a time, and I'm still not comfortable with + * it, but it is difficult to see how to "do the right thing" with all + * of '%..i', unless we URL-escape everything and break with CLF. + * + * The forms of condition are a list of HTTP status codes, which may + * or may not be preceded by '!'. Thus, '%400,501{User-agent}i' logs + * User-agent: on 400 errors and 501 errors (Bad Request, Not + * Implemented) only; '%!200,304,302{Referer}i' logs Referer: on all + * requests which did *not* return some sort of normal status. + * + * The default LogFormat reproduces CLF; see below. + * + * The way this is supposed to work with virtual hosts is as follows: + * a virtual host can have its own LogFormat, or its own TransferLog. + * If it doesn't have its own LogFormat, it inherits from the main + * server. If it doesn't have its own TransferLog, it writes to the + * same descriptor (meaning the same process for "| ..."). + * + * --- rst */ + +#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b" + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" /* For REMOTE_NAME */ +#include "http_log.h" +#include + +module MODULE_VAR_EXPORT config_log_module; + +static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT); +#if defined(__EMX__) || defined(WIN32) +/* OS/2 dosen't support users and groups */ +static mode_t xfer_mode = (S_IREAD | S_IWRITE); +#else +static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#endif + +/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is + * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512 + * is guaranteed. So we'll just guess 512 in the event the system + * doesn't have this. Now, for file writes there is actually no limit, + * the entire write is atomic. Whether all systems implement this + * correctly is another question entirely ... so we'll just use PIPE_BUF + * because it's probably a good guess as to what is implemented correctly + * everywhere. + */ +#ifdef PIPE_BUF +#define LOG_BUFSIZE PIPE_BUF +#else +#define LOG_BUFSIZE (512) +#endif + +/* + * multi_log_state is our per-(virtual)-server configuration. We store + * an array of the logs we are going to use, each of type config_log_state. + * If a default log format is given by LogFormat, store in default_format + * (backward compat. with mod_log_config). We also store a pointer to + * the logs specified for the main server for virtual servers, so that + * if this vhost has now logs defined, we can use the main server's + * logs instead. + * + * So, for the main server, config_logs contains a list of the log files + * and server_config_logs in empty. For a vhost, server_config_logs + * points to the same array as config_logs in the main server, and + * config_logs points to the array of logs defined inside this vhost, + * which might be empty. + */ + +typedef struct { + array_header *default_format; + array_header *config_logs; + array_header *server_config_logs; + table *formats; +} multi_log_state; + +/* + * config_log_state holds the status of a single log file. fname might + * be NULL, which means this module does no logging for this + * request. format might be NULL, in which case the default_format + * from the multi_log_state should be used, or if that is NULL as + * well, use the CLF. log_fd is -1 before the log file is opened and + * set to a valid fd after it is opened. + */ + +typedef struct { + char *fname; + array_header *format; + int log_fd; +#ifdef BUFFERED_LOGS + int outcnt; + char outbuf[LOG_BUFSIZE]; +#endif +} config_log_state; + +/* + * Format items... + */ + +typedef char *(*item_key_func) (request_rec *, char *); + +typedef struct { + item_key_func func; + char *arg; + int condition_sense; + int want_orig; + array_header *conditions; +} log_format_item; + +static char *format_integer(pool *p, int i) +{ + return ap_psprintf(p, "%d", i); +} + +static char *pfmt(pool *p, int i) +{ + if (i <= 0) { + return "-"; + } + else { + return format_integer(p, i); + } +} + +static char *constant_item(request_rec *dummy, char *stuff) +{ + return stuff; +} + +static char *log_remote_host(request_rec *r, char *a) +{ + return (char *) ap_get_remote_host(r->connection, r->per_dir_config, + REMOTE_NAME); +} + +static char *log_remote_address(request_rec *r, char *a) +{ + return r->connection->remote_ip; +} + +static char *log_remote_logname(request_rec *r, char *a) +{ + return (char *) ap_get_remote_logname(r); +} + +static char *log_remote_user(request_rec *r, char *a) +{ + char *rvalue = r->connection->user; + + if (rvalue == NULL) { + rvalue = "-"; + } + else if (strlen(rvalue) == 0) { + rvalue = "\"\""; + } + return rvalue; +} + +static char *log_request_line(request_rec *r, char *a) +{ + /* NOTE: If the original request contained a password, we + * re-write the request line here to contain XXXXXX instead: + * (note the truncation before the protocol string for HTTP/0.9 requests) + * (note also that r->the_request contains the unmodified request) + */ + return (r->parsed_uri.password) ? ap_pstrcat(r->pool, r->method, " ", + ap_unparse_uri_components(r->pool, &r->parsed_uri, 0), + r->assbackwards ? NULL : " ", r->protocol, NULL) + : r->the_request; +} + +static char *log_request_file(request_rec *r, char *a) +{ + return r->filename; +} +static char *log_request_uri(request_rec *r, char *a) +{ + return r->uri; +} +static char *log_status(request_rec *r, char *a) +{ + return pfmt(r->pool, r->status); +} + +static char *log_bytes_sent(request_rec *r, char *a) +{ + if (!r->sent_bodyct) { + return "-"; + } + else { + long int bs; + ap_bgetopt(r->connection->client, BO_BYTECT, &bs); + return ap_psprintf(r->pool, "%ld", bs); + } +} + +static char *log_header_in(request_rec *r, char *a) +{ + return ap_table_get(r->headers_in, a); +} + +static char *log_header_out(request_rec *r, char *a) +{ + char *cp = ap_table_get(r->headers_out, a); + if (!strcasecmp(a, "Content-type") && r->content_type) { + cp = r->content_type; + } + if (cp) { + return cp; + } + return ap_table_get(r->err_headers_out, a); +} + +static char *log_note(request_rec *r, char *a) +{ + return ap_table_get(r->notes, a); +} +static char *log_env_var(request_rec *r, char *a) +{ + return ap_table_get(r->subprocess_env, a); +} + +static char *log_request_time(request_rec *r, char *a) +{ + int timz; + struct tm *t; + char tstr[MAX_STRING_LEN]; + + t = ap_get_gmtoff(&timz); + + if (a && *a) { /* Custom format */ + strftime(tstr, MAX_STRING_LEN, a, t); + } + else { /* CLF format */ + char sign = (timz < 0 ? '-' : '+'); + size_t l; + + if (timz < 0) { + timz = -timz; + } + + strftime(tstr, MAX_STRING_LEN, "[%d/%b/%Y:%H:%M:%S ", t); + l = strlen(tstr); + ap_snprintf(tstr + l, sizeof(tstr) - l, + "%c%.2d%.2d]", sign, timz / 60, timz % 60); + } + + return ap_pstrdup(r->pool, tstr); +} + +static char *log_request_duration(request_rec *r, char *a) +{ + return ap_psprintf(r->pool, "%ld", time(NULL) - r->request_time); +} + +/* These next two routines use the canonical name:port so that log + * parsers don't need to duplicate all the vhost parsing crud. + */ +static char *log_virtual_host(request_rec *r, char *a) +{ + return ap_pstrdup(r->pool, ap_get_server_name(r)); +} + +static char *log_server_port(request_rec *r, char *a) +{ + return ap_psprintf(r->pool, "%u", ap_get_server_port(r)); +} + +static char *log_child_pid(request_rec *r, char *a) +{ + return ap_psprintf(r->pool, "%ld", (long) getpid()); +} + +/***************************************************************** + * + * Parsing the log format string + */ + +static struct log_item_list { + char ch; + item_key_func func; + int want_orig_default; +} log_item_keys[] = { + + { + 'h', log_remote_host, 0 + }, + { + 'a', log_remote_address, 0 + }, + { + 'l', log_remote_logname, 0 + }, + { + 'u', log_remote_user, 0 + }, + { + 't', log_request_time, 0 + }, + { + 'T', log_request_duration, 1 + }, + { + 'r', log_request_line, 1 + }, + { + 'f', log_request_file, 0 + }, + { + 'U', log_request_uri, 1 + }, + { + 's', log_status, 1 + }, + { + 'b', log_bytes_sent, 0 + }, + { + 'i', log_header_in, 0 + }, + { + 'o', log_header_out, 0 + }, + { + 'n', log_note, 0 + }, + { + 'e', log_env_var, 0 + }, + { + 'v', log_virtual_host, 0 + }, + { + 'p', log_server_port, 0 + }, + { + 'P', log_child_pid, 0 + }, + { + '\0' + } +}; + +static struct log_item_list *find_log_func(char k) +{ + int i; + + for (i = 0; log_item_keys[i].ch; ++i) + if (k == log_item_keys[i].ch) { + return &log_item_keys[i]; + } + + return NULL; +} + +static char *log_format_substring(pool *p, const char *start, + const char *end) +{ + char *res = ap_palloc(p, end - start + 1); + + strncpy(res, start, end - start); + res[end - start] = '\0'; + return res; +} + +static char *parse_log_misc_string(pool *p, log_format_item *it, + const char **sa) +{ + const char *s = *sa; + + it->func = constant_item; + it->conditions = NULL; + + while (*s && *s != '%') { + ++s; + } + it->arg = log_format_substring(p, *sa, s); + *sa = s; + + return NULL; +} + +static char *parse_log_item(pool *p, log_format_item *it, const char **sa) +{ + const char *s = *sa; + + if (*s != '%') { + return parse_log_misc_string(p, it, sa); + } + + ++s; + it->condition_sense = 0; + it->conditions = NULL; + it->want_orig = -1; + it->arg = ""; /* For safety's sake... */ + + while (*s) { + int i; + struct log_item_list *l; + + switch (*s) { + case '!': + ++s; + it->condition_sense = !it->condition_sense; + break; + + case '<': + ++s; + it->want_orig = 1; + break; + + case '>': + ++s; + it->want_orig = 0; + break; + + case ',': + ++s; + break; + + case '{': + ++s; + it->arg = ap_getword(p, &s, '}'); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + i = *s - '0'; + while (isdigit(*++s)) { + i = i * 10 + (*s) - '0'; + } + if (!it->conditions) { + it->conditions = ap_make_array(p, 4, sizeof(int)); + } + *(int *) ap_push_array(it->conditions) = i; + break; + + default: + l = find_log_func(*s++); + if (!l) { + char dummy[2]; + + dummy[0] = s[-1]; + dummy[1] = '\0'; + return ap_pstrcat(p, "Unrecognized LogFormat directive %", + dummy, NULL); + } + it->func = l->func; + if (it->want_orig == -1) { + it->want_orig = l->want_orig_default; + } + *sa = s; + return NULL; + } + } + + return "Ran off end of LogFormat parsing args to some directive"; +} + +static array_header *parse_log_string(pool *p, const char *s, const char **err) +{ + array_header *a = ap_make_array(p, 30, sizeof(log_format_item)); + char *res; + + while (*s) { + if ((res = parse_log_item(p, (log_format_item *) ap_push_array(a), &s))) { + *err = res; + return NULL; + } + } + + s = "\n"; + parse_log_item(p, (log_format_item *) ap_push_array(a), &s); + return a; +} + +/***************************************************************** + * + * Actually logging. + */ + +static char *process_item(request_rec *r, request_rec *orig, + log_format_item *item) +{ + char *cp; + + /* First, see if we need to process this thing at all... */ + + if (item->conditions && item->conditions->nelts != 0) { + int i; + int *conds = (int *) item->conditions->elts; + int in_list = 0; + + for (i = 0; i < item->conditions->nelts; ++i) { + if (r->status == conds[i]) { + in_list = 1; + break; + } + } + + if ((item->condition_sense && in_list) + || (!item->condition_sense && !in_list)) { + return "-"; + } + } + + /* We do. Do it... */ + + cp = (*item->func) (item->want_orig ? orig : r, item->arg); + return cp ? cp : "-"; +} + +#ifdef BUFFERED_LOGS +static void flush_log(config_log_state *cls) +{ + if (cls->outcnt && cls->log_fd != -1) { + write(cls->log_fd, cls->outbuf, cls->outcnt); + cls->outcnt = 0; + } +} +#endif + +static int config_log_transaction(request_rec *r, config_log_state *cls, + array_header *default_format) +{ + log_format_item *items; + char *str, **strs, *s; + int *strl; + request_rec *orig; + int i; + int len = 0; + array_header *format; + + if (cls->fname == NULL) { + return DECLINED; + } + + format = cls->format ? cls->format : default_format; + + strs = ap_palloc(r->pool, sizeof(char *) * (format->nelts)); + strl = ap_palloc(r->pool, sizeof(int) * (format->nelts)); + items = (log_format_item *) format->elts; + + orig = r; + while (orig->prev) { + orig = orig->prev; + } + while (r->next) { + r = r->next; + } + + for (i = 0; i < format->nelts; ++i) { + strs[i] = process_item(r, orig, &items[i]); + } + + for (i = 0; i < format->nelts; ++i) { + len += strl[i] = strlen(strs[i]); + } + +#ifdef BUFFERED_LOGS + if (len + cls->outcnt > LOG_BUFSIZE) { + flush_log(cls); + } + if (len >= LOG_BUFSIZE) { + str = ap_palloc(r->pool, len + 1); + for (i = 0, s = str; i < format->nelts; ++i) { + memcpy(s, strs[i], strl[i]); + s += strl[i]; + } + write(cls->log_fd, str, len); + } + else { + for (i = 0, s = &cls->outbuf[cls->outcnt]; i < format->nelts; ++i) { + memcpy(s, strs[i], strl[i]); + s += strl[i]; + } + cls->outcnt += len; + } +#else + str = ap_palloc(r->pool, len + 1); + + for (i = 0, s = str; i < format->nelts; ++i) { + memcpy(s, strs[i], strl[i]); + s += strl[i]; + } + + write(cls->log_fd, str, len); +#endif + + return OK; +} + +static int multi_log_transaction(request_rec *r) +{ + multi_log_state *mls = ap_get_module_config(r->server->module_config, + &config_log_module); + config_log_state *clsarray; + int i; + + if (mls->config_logs->nelts) { + clsarray = (config_log_state *) mls->config_logs->elts; + for (i = 0; i < mls->config_logs->nelts; ++i) { + config_log_state *cls = &clsarray[i]; + + config_log_transaction(r, cls, mls->default_format); + } + } + else if (mls->server_config_logs) { + clsarray = (config_log_state *) mls->server_config_logs->elts; + for (i = 0; i < mls->server_config_logs->nelts; ++i) { + config_log_state *cls = &clsarray[i]; + + config_log_transaction(r, cls, mls->default_format); + } + } + + return OK; +} + +/***************************************************************** + * + * Module glue... + */ + +static void *make_config_log_state(pool *p, server_rec *s) +{ + multi_log_state *mls = (multi_log_state *) ap_palloc(p, sizeof(multi_log_state)); + + mls->config_logs = ap_make_array(p, 1, sizeof(config_log_state)); + mls->default_format = NULL; + mls->server_config_logs = NULL; + mls->formats = ap_make_table(p, 4); + ap_table_setn(mls->formats, "CLF", DEFAULT_LOG_FORMAT); + + return mls; +} + +/* + * Use the merger to simply add a pointer from the vhost log state + * to the log of logs specified for the non-vhost configuration. Make sure + * vhosts inherit any globally-defined format names. + */ + +static void *merge_config_log_state(pool *p, void *basev, void *addv) +{ + multi_log_state *base = (multi_log_state *) basev; + multi_log_state *add = (multi_log_state *) addv; + + add->server_config_logs = base->config_logs; + if (!add->default_format) { + add->default_format = base->default_format; + } + add->formats = ap_overlay_tables(p, base->formats, add->formats); + + return add; +} + +/* + * Set the default logfile format, or define a nickname for a format string. + */ +static const char *log_format(cmd_parms *cmd, void *dummy, char *fmt, + char *name) +{ + const char *err_string = NULL; + char *format; + multi_log_state *mls = ap_get_module_config(cmd->server->module_config, + &config_log_module); + + /* + * If we were given two arguments, the second is a name to be given to the + * format. This syntax just defines the nickname - it doesn't actually + * make the format the default. + */ + if (name != NULL) { + parse_log_string(cmd->pool, fmt, &err_string); + if (err_string == NULL) { + ap_table_setn(mls->formats, name, fmt); + } + } + else { + /* + * See if we were given a name rather than a format string. + */ + format = ap_table_get(mls->formats, fmt); + if (format == NULL) { + format = fmt; + } + mls->default_format = parse_log_string(cmd->pool, format, &err_string); + } + return err_string; +} + +static const char *add_custom_log(cmd_parms *cmd, void *dummy, char *fn, + char *fmt) +{ + const char *err_string = NULL; + multi_log_state *mls = ap_get_module_config(cmd->server->module_config, + &config_log_module); + config_log_state *cls; + char *format; + + cls = (config_log_state *) ap_push_array(mls->config_logs); + cls->fname = fn; + if (!fmt) { + cls->format = NULL; + } + else { + format = ap_table_get(mls->formats, fmt); + format = (format != NULL) ? format : fmt; + cls->format = parse_log_string(cmd->pool, format, &err_string); + } + cls->log_fd = -1; + + return err_string; +} + +static const char *set_transfer_log(cmd_parms *cmd, void *dummy, char *fn) +{ + return add_custom_log(cmd, dummy, fn, NULL); +} + +static const char *set_cookie_log(cmd_parms *cmd, void *dummy, char *fn) +{ + return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t"); +} + +static const command_rec config_log_cmds[] = +{ + {"CustomLog", add_custom_log, NULL, RSRC_CONF, TAKE2, + "a file name and a custom log format string or format name"}, + {"TransferLog", set_transfer_log, NULL, RSRC_CONF, TAKE1, + "the filename of the access log"}, + {"LogFormat", log_format, NULL, RSRC_CONF, TAKE12, + "a log format string (see docs) and an optional format name"}, + {"CookieLog", set_cookie_log, NULL, RSRC_CONF, TAKE1, + "the filename of the cookie log"}, + {NULL} +}; + +static config_log_state *open_config_log(server_rec *s, pool *p, + config_log_state *cls, + array_header *default_format) +{ + if (cls->log_fd > 0) { + return cls; /* virtual config shared w/main server */ + } + + if (cls->fname == NULL) { + return cls; /* Leave it NULL to decline. */ + } + + if (*cls->fname == '|') { + piped_log *pl; + + pl = ap_open_piped_log(p, cls->fname + 1); + if (pl == NULL) { + exit(1); + } + cls->log_fd = ap_piped_log_write_fd(pl); + } + else { + char *fname = ap_server_root_relative(p, cls->fname); + if ((cls->log_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) { + perror("open"); + fprintf(stderr, "httpd: could not open transfer log file %s.\n", + fname); + exit(1); + } + } +#ifdef BUFFERED_LOGS + cls->outcnt = 0; +#endif + + return cls; +} + +static config_log_state *open_multi_logs(server_rec *s, pool *p) +{ + int i; + multi_log_state *mls = ap_get_module_config(s->module_config, + &config_log_module); + config_log_state *clsarray; + const char *dummy; + + if (!mls->default_format) { + mls->default_format = parse_log_string(p, DEFAULT_LOG_FORMAT, &dummy); + } + + if (mls->config_logs->nelts) { + clsarray = (config_log_state *) mls->config_logs->elts; + for (i = 0; i < mls->config_logs->nelts; ++i) { + config_log_state *cls = &clsarray[i]; + + cls = open_config_log(s, p, cls, mls->default_format); + } + } + else if (mls->server_config_logs) { + clsarray = (config_log_state *) mls->server_config_logs->elts; + for (i = 0; i < mls->server_config_logs->nelts; ++i) { + config_log_state *cls = &clsarray[i]; + + cls = open_config_log(s, p, cls, mls->default_format); + } + } + + return NULL; +} + +static void init_config_log(server_rec *s, pool *p) +{ + /* First, do "physical" server, which gets default log fd and format + * for the virtual servers, if they don't override... + */ + + open_multi_logs(s, p); + + /* Then, virtual servers */ + + for (s = s->next; s; s = s->next) { + open_multi_logs(s, p); + } +} + +#ifdef BUFFERED_LOGS +static void flush_all_logs(server_rec *s, pool *p) +{ + multi_log_state *mls; + array_header *log_list; + config_log_state *clsarray; + int i; + + for (; s; s = s->next) { + mls = ap_get_module_config(s->module_config, &config_log_module); + log_list = NULL; + if (mls->config_logs->nelts) { + log_list = mls->config_logs; + } + else if (mls->server_config_logs) { + log_list = mls->server_config_logs; + } + if (log_list) { + clsarray = (config_log_state *) log_list->elts; + for (i = 0; i < log_list->nelts; ++i) { + flush_log(&clsarray[i]); + } + } + } +} +#endif + +module MODULE_VAR_EXPORT config_log_module = +{ + STANDARD_MODULE_STUFF, + init_config_log, /* initializer */ + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + make_config_log_state, /* server config */ + merge_config_log_state, /* merge server config */ + config_log_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + multi_log_transaction, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ +#ifdef BUFFERED_LOGS + flush_all_logs, /* child_exit */ +#else + NULL, +#endif + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_log_referer.c b/APACHE_1_3b7/src/modules/standard/mod_log_referer.c new file mode 100644 index 0000000000..6e5ef04ed7 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_log_referer.c @@ -0,0 +1,228 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" + +module referer_log_module; + +static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT); + +#ifdef __EMX__ +/* OS/2 lacks support for users and groups */ +static mode_t xfer_mode = (S_IREAD | S_IWRITE); +#else +static mode_t xfer_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#endif + +typedef struct { + char *fname; + int referer_fd; + array_header *referer_ignore_list; +} referer_log_state; + +static void *make_referer_log_state(pool *p, server_rec *s) +{ + referer_log_state *cls = + (referer_log_state *) ap_palloc(p, sizeof(referer_log_state)); + + cls->fname = ""; + cls->referer_fd = -1; + cls->referer_ignore_list = ap_make_array(p, 1, sizeof(char *)); + return (void *) cls; +} + +static const char *set_referer_log(cmd_parms *parms, void *dummy, char *arg) +{ + referer_log_state *cls = ap_get_module_config(parms->server->module_config, + &referer_log_module); + + cls->fname = arg; + return NULL; +} + +static const char *add_referer_ignore(cmd_parms *parms, void *dummy, char *arg) +{ + char **addme; + referer_log_state *cls = ap_get_module_config(parms->server->module_config, + &referer_log_module); + + addme = ap_push_array(cls->referer_ignore_list); + ap_str_tolower(arg); + *addme = arg; + return NULL; +} + +static const command_rec referer_log_cmds[] = +{ + {"RefererLog", set_referer_log, NULL, RSRC_CONF, TAKE1, + "the filename of the referer log"}, + {"RefererIgnore", add_referer_ignore, NULL, RSRC_CONF, ITERATE, + "referer hostnames to ignore"}, + {NULL} +}; + +static void open_referer_log(server_rec *s, pool *p) +{ + referer_log_state *cls = ap_get_module_config(s->module_config, + &referer_log_module); + + char *fname = ap_server_root_relative(p, cls->fname); + + if (cls->referer_fd > 0) + return; /* virtual log shared w/main server */ + + if (*cls->fname == '|') { + piped_log *pl; + + pl = ap_open_piped_log(p, cls->fname + 1); + if (pl == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, s, + "couldn't spawn referer log pipe"); + exit(1); + } + + cls->referer_fd = ap_piped_log_write_fd(pl); + } + else if (*cls->fname != '\0') { + if ((cls->referer_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) { + perror("open"); + fprintf(stderr, "httpd: could not open referer log file %s.\n", fname); + exit(1); + } + } +} + +static void init_referer_log(server_rec *s, pool *p) +{ + for (; s; s = s->next) + open_referer_log(s, p); +} + +static int referer_log_transaction(request_rec *orig) +{ + char **ptrptr, **ptrptr2; + referer_log_state *cls = ap_get_module_config(orig->server->module_config, + &referer_log_module); + + char *str; + char *referer, *referertest; + request_rec *r; + + if (cls->referer_fd < 0) + return OK; + + for (r = orig; r->next; r = r->next) + continue; + if (*cls->fname == '\0') /* Don't log referer */ + return DECLINED; + + referer = ap_table_get(orig->headers_in, "Referer"); + if (referer != NULL) { + + referertest = ap_pstrdup(orig->pool, referer); + ap_str_tolower(referertest); + /* The following is an upsetting mess of pointers, I'm sorry + Anyone with the motiviation and/or the time should feel free + to make this cleaner... */ + + ptrptr2 = (char **) (cls->referer_ignore_list->elts + + (cls->referer_ignore_list->nelts * + cls->referer_ignore_list->elt_size)); + + /* Go through each element of the ignore list and compare it to the + referer_host. If we get a match, return without logging */ + + for (ptrptr = (char **) cls->referer_ignore_list->elts; + ptrptr < ptrptr2; + ptrptr = (char **) ((char *) ptrptr + cls->referer_ignore_list->elt_size)) { + if (strstr(referertest, *ptrptr)) + return OK; + } + + + str = ap_pstrcat(orig->pool, referer, " -> ", r->uri, "\n", NULL); + write(cls->referer_fd, str, strlen(str)); + } + + return OK; +} + +module referer_log_module = +{ + STANDARD_MODULE_STUFF, + init_referer_log, /* initializer */ + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + make_referer_log_state, /* server config */ + NULL, /* merge server config */ + referer_log_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + referer_log_transaction, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_mime.c b/APACHE_1_3b7/src/modules/standard/mod_mime.c new file mode 100644 index 0000000000..af2145092c --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_mime.c @@ -0,0 +1,351 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_mime.c: Sends/gets MIME headers for requests + * + * Rob McCool + * + */ + +#define MIME_PRIVATE + +#include "httpd.h" +#include "http_config.h" + +typedef struct { + table *forced_types; /* Additional AddTyped stuff */ + table *encoding_types; /* Added with AddEncoding... */ + table *language_types; /* Added with AddLanguage... */ + table *handlers; /* Added with AddHandler... */ + + char *type; /* Type forced with ForceType */ + char *handler; /* Handler forced with SetHandler */ +} mime_dir_config; + +module MODULE_VAR_EXPORT mime_module; + +static void *create_mime_dir_config(pool *p, char *dummy) +{ + mime_dir_config *new = + (mime_dir_config *) ap_palloc(p, sizeof(mime_dir_config)); + + new->forced_types = ap_make_table(p, 4); + new->encoding_types = ap_make_table(p, 4); + new->language_types = ap_make_table(p, 4); + new->handlers = ap_make_table(p, 4); + + new->type = NULL; + new->handler = NULL; + + return new; +} + +static void *merge_mime_dir_configs(pool *p, void *basev, void *addv) +{ + mime_dir_config *base = (mime_dir_config *) basev; + mime_dir_config *add = (mime_dir_config *) addv; + mime_dir_config *new = + (mime_dir_config *) ap_palloc(p, sizeof(mime_dir_config)); + + new->forced_types = ap_overlay_tables(p, add->forced_types, + base->forced_types); + new->encoding_types = ap_overlay_tables(p, add->encoding_types, + base->encoding_types); + new->language_types = ap_overlay_tables(p, add->language_types, + base->language_types); + new->handlers = ap_overlay_tables(p, add->handlers, + base->handlers); + + new->type = add->type ? add->type : base->type; + new->handler = add->handler ? add->handler : base->handler; + + return new; +} + +static const char *add_type(cmd_parms *cmd, mime_dir_config * m, char *ct, + char *ext) +{ + if (*ext == '.') + ++ext; + ap_str_tolower(ct); + ap_table_setn(m->forced_types, ext, ct); + return NULL; +} + +static const char *add_encoding(cmd_parms *cmd, mime_dir_config * m, char *enc, + char *ext) +{ + if (*ext == '.') + ++ext; + ap_str_tolower(enc); + ap_table_setn(m->encoding_types, ext, enc); + return NULL; +} + +static const char *add_language(cmd_parms *cmd, mime_dir_config * m, char *lang, + char *ext) +{ + if (*ext == '.') + ++ext; + ap_str_tolower(lang); + ap_table_setn(m->language_types, ext, lang); + return NULL; +} + +static const char *add_handler(cmd_parms *cmd, mime_dir_config * m, char *hdlr, + char *ext) +{ + if (*ext == '.') + ++ext; + ap_str_tolower(hdlr); + ap_table_setn(m->handlers, ext, hdlr); + return NULL; +} + +/* The sole bit of server configuration that the MIME module has is + * the name of its config file, so... + */ + +static const char *set_types_config(cmd_parms *cmd, void *dummy, char *arg) +{ + ap_set_module_config(cmd->server->module_config, &mime_module, arg); + return NULL; +} + +static const command_rec mime_cmds[] = +{ + {"AddType", add_type, NULL, OR_FILEINFO, ITERATE2, + "a mime type followed by one or more file extensions"}, + {"AddEncoding", add_encoding, NULL, OR_FILEINFO, ITERATE2, + "an encoding (e.g., gzip), followed by one or more file extensions"}, + {"AddLanguage", add_language, NULL, OR_FILEINFO, ITERATE2, + "a language (e.g., fr), followed by one or more file extensions"}, + {"AddHandler", add_handler, NULL, OR_FILEINFO, ITERATE2, + "a handler name followed by one or more file extensions"}, + {"ForceType", ap_set_string_slot_lower, + (void *)XtOffsetOf(mime_dir_config, type), OR_FILEINFO, TAKE1, + "a media type"}, + {"SetHandler", ap_set_string_slot_lower, + (void *)XtOffsetOf(mime_dir_config, handler), OR_FILEINFO, TAKE1, + "a handler name"}, + {"TypesConfig", set_types_config, NULL, RSRC_CONF, TAKE1, + "the MIME types config file"}, + {NULL} +}; + +/* Hash table --- only one of these per daemon; virtual hosts can + * get private versions through AddType... + */ + +/* MIME_HASHSIZE used to be 27 (26 chars and one "non-alpha" slot), but + * with character sets like EBCDIC, this is insufficient because the + * range 'a'...'z' is not contigous. Defining it as ('z'-'a'+2) is + * equivalent to 27 in ASCII, and makes it work in EBCDIC. + */ +#define MIME_HASHSIZE ('z'-'a'+2) +#define hash(i) (isalpha(i) ? (tolower(i)) - 'a' : (MIME_HASHSIZE-1)) + +static table *hash_buckets[MIME_HASHSIZE]; + +static void init_mime(server_rec *s, pool *p) +{ + configfile_t *f; + char l[MAX_STRING_LEN]; + int x; + char *types_confname = ap_get_module_config(s->module_config, &mime_module); + + if (!types_confname) + types_confname = TYPES_CONFIG_FILE; + + types_confname = ap_server_root_relative(p, types_confname); + + if (!(f = ap_pcfg_openfile(p, types_confname))) { + perror("fopen"); + fprintf(stderr, "httpd: could not open mime types file %s\n", + types_confname); + exit(1); + } + + for (x = 0; x < MIME_HASHSIZE; x++) + hash_buckets[x] = ap_make_table(p, 10); + + while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { + const char *ll = l, *ct; + + if (l[0] == '#') + continue; + ct = ap_getword_conf(p, &ll); + + while (ll[0]) { + char *ext = ap_getword_conf(p, &ll); + ap_str_tolower(ext); /* ??? */ + ap_table_setn(hash_buckets[hash(ext[0])], ext, ct); + } + } + ap_cfg_closefile(f); +} + +static int find_ct(request_rec *r) +{ + const char *fn = strrchr(r->filename, '/'); + mime_dir_config *conf = + (mime_dir_config *) ap_get_module_config(r->per_dir_config, &mime_module); + char *ext, *type, *orighandler = r->handler; + + if (S_ISDIR(r->finfo.st_mode)) { + r->content_type = DIR_MAGIC_TYPE; + return OK; + } + + /* TM -- FIXME + * if r->filename does not contain a '/', the following passes a null + * pointer to getword, causing a SEGV .. + */ + + if (fn == NULL) + fn = r->filename; + + /* Parse filename extensions, which can be in any order */ + while ((ext = ap_getword(r->pool, &fn, '.')) && *ext) { + int found = 0; + + /* Check for Content-Type */ + if ((type = ap_table_get(conf->forced_types, ext)) + || (type = ap_table_get(hash_buckets[hash(*ext)], ext))) { + r->content_type = type; + found = 1; + } + + /* Check for Content-Language */ + if ((type = ap_table_get(conf->language_types, ext))) { + char **new; + + r->content_language = type; /* back compat. only */ + if (!r->content_languages) + r->content_languages = ap_make_array(r->pool, 2, sizeof(char *)); + new = (char **) ap_push_array(r->content_languages); + *new = type; + found = 1; + } + + /* Check for Content-Encoding */ + if ((type = ap_table_get(conf->encoding_types, ext))) { + if (!r->content_encoding) + r->content_encoding = type; + else + r->content_encoding = ap_pstrcat(r->pool, r->content_encoding, + ", ", type, NULL); + found = 1; + } + + /* Check for a special handler, but not for proxy request */ + if ((type = ap_table_get(conf->handlers, ext)) && !r->proxyreq) { + r->handler = type; + found = 1; + } + + /* This is to deal with cases such as foo.gif.bak, which we want + * to not have a type. So if we find an unknown extension, we + * zap the type/language/encoding and reset the handler + */ + + if (!found) { + r->content_type = NULL; + r->content_language = NULL; + r->content_languages = NULL; + r->content_encoding = NULL; + r->handler = orighandler; + } + + } + + /* Check for overrides with ForceType/SetHandler */ + + if (conf->type && strcmp(conf->type, "none")) + r->content_type = conf->type; + if (conf->handler && strcmp(conf->handler, "none")) + r->handler = conf->handler; + + if (!r->content_type) + return DECLINED; + + return OK; +} + +module MODULE_VAR_EXPORT mime_module = +{ + STANDARD_MODULE_STUFF, + init_mime, /* initializer */ + create_mime_dir_config, /* dir config creator */ + merge_mime_dir_configs, /* dir config merger */ + NULL, /* server config */ + NULL, /* merge server config */ + mime_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + find_ct, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_mime_magic.c b/APACHE_1_3b7/src/modules/standard/mod_mime_magic.c new file mode 100644 index 0000000000..37376b3ac2 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_mime_magic.c @@ -0,0 +1,2474 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * mod_mime_magic: MIME type lookup via file magic numbers + * Copyright (c) 1996-1997 Cisco Systems, Inc. + * + * This software was submitted by Cisco Systems to the Apache Group in July + * 1997. Future revisions and derivatives of this source code must + * acknowledge Cisco Systems as the original contributor of this module. + * All other licensing and usage conditions are those of the Apache Group. + * + * Some of this code is derived from the free version of the file command + * originally posted to comp.sources.unix. Copyright info for that program + * is included below as required. + * --------------------------------------------------------------------------- + * - Copyright (c) Ian F. Darwin, 1987. Written by Ian F. Darwin. + * + * This software is not subject to any license of the American Telephone and + * Telegraph Company or of the Regents of the University of California. + * + * Permission is granted to anyone to use this software for any purpose on any + * computer system, and to alter it and redistribute it freely, subject to + * the following restrictions: + * + * 1. The author is not responsible for the consequences of use of this + * software, no matter how awful, even if they arise from flaws in it. + * + * 2. The origin of this software must not be misrepresented, either by + * explicit claim or by omission. Since few users ever read sources, credits + * must appear in the documentation. + * + * 3. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software. Since few users ever read + * sources, credits must appear in the documentation. + * + * 4. This notice may not be removed or altered. + * ------------------------------------------------------------------------- + * + * For compliance with Mr Darwin's terms: this has been very significantly + * modified from the free "file" command. + * - all-in-one file for compilation convenience when moving from one + * version of Apache to the next. + * - Memory allocation is done through the Apache API's pool structure. + * - All functions have had necessary Apache API request or server + * structures passed to them where necessary to call other Apache API + * routines. (i.e. usually for logging, files, or memory allocation in + * itself or a called function.) + * - struct magic has been converted from an array to a single-ended linked + * list because it only grows one record at a time, it's only accessed + * sequentially, and the Apache API has no equivalent of realloc(). + * - Functions have been changed to get their parameters from the server + * configuration instead of globals. (It should be reentrant now but has + * not been tested in a threaded environment.) + * - Places where it used to print results to stdout now saves them in a + * list where they're used to set the MIME type in the Apache request + * record. + * - Command-line flags have been removed since they will never be used here. + * + * Ian Kluft + * Engineering Information Framework + * Central Engineering + * Cisco Systems, Inc. + * San Jose, CA, USA + * + * Initial installation July/August 1996 + * Misc bug fixes May 1997 + * Submission to Apache Group July 1997 + * + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" + +#include + + +/* + * data structures and related constants + */ + +#define MODNAME "mod_mime_magic" +#define MIME_MAGIC_DEBUG 0 + +#define MIME_BINARY_UNKNOWN "application/octet-stream" +#define MIME_TEXT_UNKNOWN "text/plain" + +#define MAXMIMESTRING 256 + +/* HOWMANY must be at least 4096 to make gzip -dcq work */ +#define HOWMANY 4096 +/* SMALL_HOWMANY limits how much work we do to figure out text files */ +#define SMALL_HOWMANY 1024 +#define MAXDESC 50 /* max leng of text description */ +#define MAXstring 64 /* max leng of "string" types */ + +struct magic { + struct magic *next; /* link to next entry */ + int lineno; /* line number from magic file */ + + short flag; +#define INDIR 1 /* if '>(...)' appears, */ +#define UNSIGNED 2 /* comparison is unsigned */ + short cont_level; /* level of ">" */ + struct { + char type; /* byte short long */ + long offset; /* offset from indirection */ + } in; + long offset; /* offset to magic number */ + unsigned char reln; /* relation (0=eq, '>'=gt, etc) */ + char type; /* int, short, long or string. */ + char vallen; /* length of string value, if any */ +#define BYTE 1 +#define SHORT 2 +#define LONG 4 +#define STRING 5 +#define DATE 6 +#define BESHORT 7 +#define BELONG 8 +#define BEDATE 9 +#define LESHORT 10 +#define LELONG 11 +#define LEDATE 12 + union VALUETYPE { + unsigned char b; + unsigned short h; + unsigned long l; + char s[MAXstring]; + unsigned char hs[2]; /* 2 bytes of a fixed-endian "short" */ + unsigned char hl[4]; /* 2 bytes of a fixed-endian "long" */ + } value; /* either number or string */ + unsigned long mask; /* mask before comparison with value */ + char nospflag; /* supress space character */ + + /* NOTE: this string is suspected of overrunning - find it! */ + char desc[MAXDESC]; /* description */ +}; + +/* + * data structures for tar file recognition + * -------------------------------------------------------------------------- + * Header file for public domain tar (tape archive) program. + * + * @(#)tar.h 1.20 86/10/29 Public Domain. Created 25 August 1985 by John + * Gilmore, ihnp4!hoptoad!gnu. + * + * Header block on tape. + * + * I'm going to use traditional DP naming conventions here. A "block" is a big + * chunk of stuff that we do I/O on. A "record" is a piece of info that we + * care about. Typically many "record"s fit into a "block". + */ +#define RECORDSIZE 512 +#define NAMSIZ 100 +#define TUNMLEN 32 +#define TGNMLEN 32 + +union record { + char charptr[RECORDSIZE]; + struct header { + char name[NAMSIZ]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char linkflag; + char linkname[NAMSIZ]; + char magic[8]; + char uname[TUNMLEN]; + char gname[TGNMLEN]; + char devmajor[8]; + char devminor[8]; + } header; +}; + +/* The magic field is filled with this if uname and gname are valid. */ +#define TMAGIC "ustar " /* 7 chars and a null */ + +/* + * file-function prototypes + */ +static int ascmagic(request_rec *, unsigned char *, int); +static int is_tar(unsigned char *, int); +static int softmagic(request_rec *, unsigned char *, int); +static void tryit(request_rec *, unsigned char *, int); +static int zmagic(request_rec *, unsigned char *, int); + +static int getvalue(server_rec *, struct magic *, char **); +static int hextoint(int); +static char *getstr(server_rec *, char *, char *, int, int *); +static int parse(server_rec *, pool *p, char *, int); + +static int match(request_rec *, unsigned char *, int); +static int mget(request_rec *, union VALUETYPE *, unsigned char *, + struct magic *, int); +static int mcheck(request_rec *, union VALUETYPE *, struct magic *); +static void mprint(request_rec *, union VALUETYPE *, struct magic *); + +static int uncompress(request_rec *, int, const unsigned char *, + unsigned char **, int); +static long from_oct(int, char *); +static int fsmagic(request_rec *r, const char *fn); + +/* + * includes for ASCII substring recognition formerly "names.h" in file + * command + * + * Original notes: names and types used by ascmagic in file(1). These tokens are + * here because they can appear anywhere in the first HOWMANY bytes, while + * tokens in /etc/magic must appear at fixed offsets into the file. Don't + * make HOWMANY too high unless you have a very fast CPU. + */ + +/* these types are used to index the table 'types': keep em in sync! */ +/* HTML inserted in first because this is a web server module now */ +#define L_HTML 0 /* HTML */ +#define L_C 1 /* first and foremost on UNIX */ +#define L_FORT 2 /* the oldest one */ +#define L_MAKE 3 /* Makefiles */ +#define L_PLI 4 /* PL/1 */ +#define L_MACH 5 /* some kinda assembler */ +#define L_ENG 6 /* English */ +#define L_PAS 7 /* Pascal */ +#define L_MAIL 8 /* Electronic mail */ +#define L_NEWS 9 /* Usenet Netnews */ + +static char *types[] = +{ + "text/html", /* HTML */ + "text/plain", /* "c program text", */ + "text/plain", /* "fortran program text", */ + "text/plain", /* "make commands text", */ + "text/plain", /* "pl/1 program text", */ + "text/plain", /* "assembler program text", */ + "text/plain", /* "English text", */ + "text/plain", /* "pascal program text", */ + "message/rfc822", /* "mail text", */ + "message/news", /* "news text", */ + "application/binary", /* "can't happen error on names.h/types", */ + 0 +}; + +static struct names { + char *name; + short type; +} names[] = { + + /* These must be sorted by eye for optimal hit rate */ + /* Add to this list only after substantial meditation */ + { + "", L_HTML + }, + { + "", L_HTML + }, + { + "", L_HTML + }, + { + "", L_HTML + }, + { + "", L_HTML + }, + { + "<TITLE>", L_HTML + }, + { + "<h1>", L_HTML + }, + { + "<H1>", L_HTML + }, + { + "<!--", L_HTML + }, + { + "<!DOCTYPE HTML", L_HTML + }, + { + "/*", L_C + }, /* must precede "The", "the", etc. */ + { + "#include", L_C + }, + { + "char", L_C + }, + { + "The", L_ENG + }, + { + "the", L_ENG + }, + { + "double", L_C + }, + { + "extern", L_C + }, + { + "float", L_C + }, + { + "real", L_C + }, + { + "struct", L_C + }, + { + "union", L_C + }, + { + "CFLAGS", L_MAKE + }, + { + "LDFLAGS", L_MAKE + }, + { + "all:", L_MAKE + }, + { + ".PRECIOUS", L_MAKE + }, + /* + * Too many files of text have these words in them. Find another way to + * recognize Fortrash. + */ +#ifdef NOTDEF + { + "subroutine", L_FORT + }, + { + "function", L_FORT + }, + { + "block", L_FORT + }, + { + "common", L_FORT + }, + { + "dimension", L_FORT + }, + { + "integer", L_FORT + }, + { + "data", L_FORT + }, +#endif /* NOTDEF */ + { + ".ascii", L_MACH + }, + { + ".asciiz", L_MACH + }, + { + ".byte", L_MACH + }, + { + ".even", L_MACH + }, + { + ".globl", L_MACH + }, + { + "clr", L_MACH + }, + { + "(input,", L_PAS + }, + { + "dcl", L_PLI + }, + { + "Received:", L_MAIL + }, + { + ">From", L_MAIL + }, + { + "Return-Path:", L_MAIL + }, + { + "Cc:", L_MAIL + }, + { + "Newsgroups:", L_NEWS + }, + { + "Path:", L_NEWS + }, + { + "Organization:", L_NEWS + }, + { + NULL, 0 + } +}; + +#define NNAMES ((sizeof(names)/sizeof(struct names)) - 1) + +/* + * Result String List (RSL) + * + * The file(1) command prints its output. Instead, we store the various + * "printed" strings in a list (allocating memory as we go) and concatenate + * them at the end when we finally know how much space they'll need. + */ + +typedef struct magic_rsl_s { + char *str; /* string, possibly a fragment */ + struct magic_rsl_s *next; /* pointer to next fragment */ +} magic_rsl; + +/* + * Apache module configuration structures + */ + +/* per-server info */ +typedef struct { + char *magicfile; /* where magic be found */ + struct magic *magic; /* head of magic config list */ + struct magic *last; +} magic_server_config_rec; + +/* per-request info */ +typedef struct { + magic_rsl *head; /* result string list */ + magic_rsl *tail; + unsigned suf_recursion; /* recursion depth in suffix check */ +} magic_req_rec; + +/* + * configuration functions - called by Apache API routines + */ + +module mime_magic_module; + +static void *create_magic_server_config(pool *p, server_rec *d) +{ + /* allocate the config - use pcalloc because it needs to be zeroed */ + return ap_pcalloc(p, sizeof(magic_server_config_rec)); +} + +static void *merge_magic_server_config(pool *p, void *basev, void *addv) +{ + magic_server_config_rec *base = (magic_server_config_rec *) basev; + magic_server_config_rec *add = (magic_server_config_rec *) addv; + magic_server_config_rec *new = (magic_server_config_rec *) + ap_palloc(p, sizeof(magic_server_config_rec)); + + new->magicfile = add->magicfile ? add->magicfile : base->magicfile; + new->magic = NULL; + new->last = NULL; + return new; +} + +static const char *set_magicfile(cmd_parms *cmd, char *d, char *arg) +{ + magic_server_config_rec *conf = (magic_server_config_rec *) + ap_get_module_config(cmd->server->module_config, + &mime_magic_module); + + if (!conf) { + return MODNAME ": server structure not allocated"; + } + conf->magicfile = arg; + return NULL; +} + +/* + * configuration file commands - exported to Apache API + */ + +static const command_rec mime_magic_cmds[] = +{ + {"MimeMagicFile", set_magicfile, NULL, RSRC_CONF, TAKE1, + "Path to MIME Magic file (in file(1) format)"}, + {NULL} +}; + +/* + * RSL (result string list) processing routines + * + * These collect strings that would have been printed in fragments by file(1) + * into a list of magic_rsl structures with the strings. When complete, + * they're concatenated together to become the MIME content and encoding + * types. + * + * return value conventions for these functions: functions which return int: + * failure = -1, other = result functions which return pointers: failure = 0, + * other = result + */ + +/* allocate a per-request structure and put it in the request record */ +static magic_req_rec *magic_set_config(request_rec *r) +{ + magic_req_rec *req_dat = (magic_req_rec *) ap_palloc(r->pool, + sizeof(magic_req_rec)); + + req_dat->head = req_dat->tail = (magic_rsl *) NULL; + ap_set_module_config(r->request_config, &mime_magic_module, req_dat); + return req_dat; +} + +/* add a string to the result string list for this request */ +/* it is the responsibility of the caller to allocate "str" */ +static int magic_rsl_add(request_rec *r, char *str) +{ + magic_req_rec *req_dat = (magic_req_rec *) + ap_get_module_config(r->request_config, &mime_magic_module); + magic_rsl *rsl; + + /* make sure we have a list to put it in */ + if (!req_dat) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": request config should not be NULL"); + if (!(req_dat = magic_set_config(r))) { + /* failure */ + return -1; + } + } + + /* allocate the list entry */ + rsl = (magic_rsl *) ap_palloc(r->pool, sizeof(magic_rsl)); + + /* fill it */ + rsl->str = str; + rsl->next = (magic_rsl *) NULL; + + /* append to the list */ + if (req_dat->head && req_dat->tail) { + req_dat->tail->next = rsl; + req_dat->tail = rsl; + } + else { + req_dat->head = req_dat->tail = rsl; + } + + /* success */ + return 0; +} + +/* RSL hook for puts-type functions */ +static int magic_rsl_puts(request_rec *r, char *str) +{ + return magic_rsl_add(r, str); +} + +/* RSL hook for printf-type functions */ +static int magic_rsl_printf(request_rec *r, char *str,...) +{ + va_list ap; + + char buf[MAXMIMESTRING]; + + /* assemble the string into the buffer */ + va_start(ap, str); + ap_vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + + /* add the buffer to the list */ + return magic_rsl_add(r, strdup(buf)); +} + +/* RSL hook for putchar-type functions */ +static int magic_rsl_putchar(request_rec *r, char c) +{ + char str[2]; + + /* high overhead for 1 char - just hope they don't do this much */ + str[0] = c; + str[1] = '\0'; + return magic_rsl_add(r, str); +} + +/* allocate and copy a contiguous string from a result string list */ +static char *rsl_strdup(request_rec *r, int start_frag, int start_pos, int len) +{ + char *result; /* return value */ + int cur_frag, /* current fragment number/counter */ + cur_pos, /* current position within fragment */ + res_pos; /* position in result string */ + magic_rsl *frag; /* list-traversal pointer */ + magic_req_rec *req_dat = (magic_req_rec *) + ap_get_module_config(r->request_config, &mime_magic_module); + + /* allocate the result string */ + result = (char *) ap_palloc(r->pool, len + 1); + + /* loop through and collect the string */ + res_pos = 0; + for (frag = req_dat->head, cur_frag = 0; + frag->next; + frag = frag->next, cur_frag++) { + /* loop to the first fragment */ + if (cur_frag < start_frag) + continue; + + /* loop through and collect chars */ + for (cur_pos = (cur_frag == start_frag) ? start_pos : 0; + frag->str[cur_pos]; + cur_pos++) { + if (cur_frag >= start_frag + && cur_pos >= start_pos + && res_pos <= len) { + result[res_pos++] = frag->str[cur_pos]; + if (res_pos > len) { + break; + } + } + } + } + + /* clean up and return */ + result[res_pos] = 0; +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": rsl_strdup() %d chars: %s", res_pos - 1, result); +#endif + return result; +} + +/* states for the state-machine algorithm in magic_rsl_to_request() */ +typedef enum { + rsl_leading_space, rsl_type, rsl_subtype, rsl_separator, rsl_encoding +} rsl_states; + +/* process the RSL and set the MIME info in the request record */ +static int magic_rsl_to_request(request_rec *r) +{ + int cur_frag, /* current fragment number/counter */ + cur_pos, /* current position within fragment */ + type_frag, /* content type starting point: fragment */ + type_pos, /* content type starting point: position */ + type_len, /* content type length */ + encoding_frag, /* content encoding starting point: fragment */ + encoding_pos, /* content encoding starting point: position */ + encoding_len; /* content encoding length */ + + magic_rsl *frag; /* list-traversal pointer */ + rsl_states state; + + magic_req_rec *req_dat = (magic_req_rec *) + ap_get_module_config(r->request_config, &mime_magic_module); + + /* check if we have a result */ + if (!req_dat || !req_dat->head) { + /* empty - no match, we defer to other Apache modules */ + return DECLINED; + } + + /* start searching for the type and encoding */ + state = rsl_leading_space; + type_frag = type_pos = type_len = 0; + encoding_frag = encoding_pos = encoding_len = 0; + for (frag = req_dat->head, cur_frag = 0; + frag && frag->next; + frag = frag->next, cur_frag++) { + /* loop through the characters in the fragment */ + for (cur_pos = 0; frag->str[cur_pos]; cur_pos++) { + if (isspace(frag->str[cur_pos])) { + /* process whitespace actions for each state */ + if (state == rsl_leading_space) { + /* eat whitespace in this state */ + continue; + } + else if (state == rsl_type) { + /* whitespace: type has no slash! */ + return DECLINED; + } + else if (state == rsl_subtype) { + /* whitespace: end of MIME type */ + state++; + continue; + } + else if (state == rsl_separator) { + /* eat whitespace in this state */ + continue; + } + else if (state == rsl_encoding) { + /* whitespace: end of MIME encoding */ + /* we're done */ + frag = req_dat->tail; + break; + } + else { + /* should not be possible */ + /* abandon malfunctioning module */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": bad state %d (ws)", state); + return DECLINED; + } + /* NOTREACHED */ + } + else if (state == rsl_type && + frag->str[cur_pos] == '/') { + /* copy the char and go to rsl_subtype state */ + type_len++; + state++; + } + else { + /* process non-space actions for each state */ + if (state == rsl_leading_space) { + /* non-space: begin MIME type */ + state++; + type_frag = cur_frag; + type_pos = cur_pos; + type_len = 1; + continue; + } + else if (state == rsl_type || + state == rsl_subtype) { + /* non-space: adds to type */ + type_len++; + continue; + } + else if (state == rsl_separator) { + /* non-space: begin MIME encoding */ + state++; + encoding_frag = cur_frag; + encoding_pos = cur_pos; + encoding_len = 1; + continue; + } + else if (state == rsl_encoding) { + /* non-space: adds to encoding */ + encoding_len++; + continue; + } + else { + /* should not be possible */ + /* abandon malfunctioning module */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": bad state %d (ns)", state); + return DECLINED; + } + /* NOTREACHED */ + } + /* NOTREACHED */ + } + } + + /* if we ended prior to state rsl_subtype, we had incomplete info */ + if (state != rsl_subtype && state != rsl_separator && + state != rsl_encoding) { + /* defer to other modules */ + return DECLINED; + } + + /* save the info in the request record */ + if (state == rsl_subtype || state == rsl_encoding || + state == rsl_encoding) { + r->content_type = rsl_strdup(r, type_frag, type_pos, type_len); + /* XXX: this could be done at config time I'm sure... but I'm + * confused by all this magic_rsl stuff. -djg */ + ap_str_tolower(r->content_type); + } + if (state == rsl_encoding) { + r->content_encoding = rsl_strdup(r, encoding_frag, + encoding_pos, encoding_len); + /* XXX: this could be done at config time I'm sure... but I'm + * confused by all this magic_rsl stuff. -djg */ + ap_str_tolower(r->content_encoding); + } + + /* detect memory allocation errors */ + if (!r->content_type || + (state == rsl_encoding && !r->content_encoding)) { + return HTTP_INTERNAL_SERVER_ERROR; + } + + /* success! */ + return OK; +} + +/* + * magic_process - process input file r Apache API request record + * (formerly called "process" in file command, prefix added for clarity) Opens + * the file and reads a fixed-size buffer to begin processing the contents. + */ +static int magic_process(request_rec *r) +{ + int fd = 0; + unsigned char buf[HOWMANY + 1]; /* one extra for terminating '\0' */ + int nbytes = 0; /* number of bytes read from a datafile */ + int result; + + /* + * first try judging the file based on its filesystem status + */ + switch ((result = fsmagic(r, r->filename))) { + case DONE: + magic_rsl_putchar(r, '\n'); + return OK; + case OK: + break; + default: + /* fatal error, bail out */ + return result; + } + + if ((fd = ap_popenf(r->pool, r->filename, O_RDONLY, 0)) < 0) { + /* We can't open it, but we were able to stat it. */ + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + MODNAME ": can't read `%s'", r->filename); + /* let some other handler decide what the problem is */ + return DECLINED; + } + + /* + * try looking at the first HOWMANY bytes + */ + if ((nbytes = read(fd, (char *) buf, sizeof(buf) - 1)) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + MODNAME ": read failed: %s", r->filename); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (nbytes == 0) + magic_rsl_puts(r, MIME_TEXT_UNKNOWN); + else { + buf[nbytes++] = '\0'; /* null-terminate it */ + tryit(r, buf, nbytes); + } + + (void) ap_pclosef(r->pool, fd); + (void) magic_rsl_putchar(r, '\n'); + + return OK; +} + + +static void tryit(request_rec *r, unsigned char *buf, int nb) +{ + /* + * Try compression stuff + */ + if (zmagic(r, buf, nb) == 1) + return; + + /* + * try tests in /etc/magic (or surrogate magic file) + */ + if (softmagic(r, buf, nb) == 1) + return; + + /* + * try known keywords, check for ascii-ness too. + */ + if (ascmagic(r, buf, nb) == 1) + return; + + /* + * abandon hope, all ye who remain here + */ + magic_rsl_puts(r, MIME_BINARY_UNKNOWN); +} + +#define EATAB {while (isascii((unsigned char) *l) && \ + isspace((unsigned char) *l)) ++l;} + +/* + * apprentice - load configuration from the magic file r + * API request record + */ +static int apprentice(server_rec *s, pool *p) +{ + FILE *f; + char line[BUFSIZ + 1]; + int errs = 0; + int lineno; +#if MIME_MAGIC_DEBUG + int rule = 0; + struct magic *m, *prevm; +#endif + char *fname; + + magic_server_config_rec *conf = (magic_server_config_rec *) + ap_get_module_config(s->module_config, &mime_magic_module); + + fname = ap_server_root_relative(p, conf->magicfile); + f = ap_pfopen(p, fname, "r"); + if (f == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, s, + MODNAME ": can't read magic file %s", fname); + return -1; + } + + /* set up the magic list (empty) */ + conf->magic = conf->last = NULL; + + /* parse it */ + for (lineno = 1; fgets(line, BUFSIZ, f) != NULL; lineno++) { + int ws_offset; + + /* delete newline */ + if (line[0]) { + line[strlen(line) - 1] = '\0'; + } + + /* skip leading whitespace */ + ws_offset = 0; + while (line[ws_offset] && isspace(line[ws_offset])) { + ws_offset++; + } + + /* skip blank lines */ + if (line[ws_offset] == 0) { + continue; + } + + /* comment, do not parse */ + if (line[ws_offset] == '#') + continue; + +#if MIME_MAGIC_DEBUG + /* if we get here, we're going to use it so count it */ + rule++; +#endif + + /* parse it */ + if (parse(s, p, line + ws_offset, lineno) != 0) + ++errs; + } + + (void) ap_pfclose(p, f); + +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s, + MODNAME ": apprentice conf=%x file=%s m=%s m->next=%s last=%s", + conf, + conf->magicfile ? conf->magicfile : "NULL", + conf->magic ? "set" : "NULL", + (conf->magic && conf->magic->next) ? "set" : "NULL", + conf->last ? "set" : "NULL"); + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s, + MODNAME ": apprentice read %d lines, %d rules, %d errors", + lineno, rule, errs); +#endif + +#if MIME_MAGIC_DEBUG + prevm = 0; + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s, + MODNAME ": apprentice test"); + for (m = conf->magic; m; m = m->next) { + if (isprint((((unsigned long) m) >> 24) & 255) && + isprint((((unsigned long) m) >> 16) & 255) && + isprint((((unsigned long) m) >> 8) & 255) && + isprint(((unsigned long) m) & 255)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s, + MODNAME ": apprentice: POINTER CLOBBERED! " + "m=\"%c%c%c%c\" line=%d", + (((unsigned long) m) >> 24) & 255, + (((unsigned long) m) >> 16) & 255, + (((unsigned long) m) >> 8) & 255, + ((unsigned long) m) & 255, + prevm ? prevm->lineno : -1); + break; + } + prevm = m; + } +#endif + + return (errs ? -1 : 0); +} + +/* + * extend the sign bit if the comparison is to be signed + */ +static unsigned long signextend(server_rec *s, struct magic *m, unsigned long v) +{ + if (!(m->flag & UNSIGNED)) + switch (m->type) { + /* + * Do not remove the casts below. They are vital. When later + * compared with the data, the sign extension must have happened. + */ + case BYTE: + v = (char) v; + break; + case SHORT: + case BESHORT: + case LESHORT: + v = (short) v; + break; + case DATE: + case BEDATE: + case LEDATE: + case LONG: + case BELONG: + case LELONG: + v = (long) v; + break; + case STRING: + break; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, s, + MODNAME ": can't happen: m->type=%d", m->type); + return -1; + } + return v; +} + +/* + * parse one line from magic file, put into magic[index++] if valid + */ +static int parse(server_rec *serv, pool *p, char *l, int lineno) +{ + struct magic *m; + char *t, *s; + magic_server_config_rec *conf = (magic_server_config_rec *) + ap_get_module_config(serv->module_config, &mime_magic_module); + + /* allocate magic structure entry */ + m = (struct magic *) ap_pcalloc(p, sizeof(struct magic)); + + /* append to linked list */ + m->next = NULL; + if (!conf->magic || !conf->last) { + conf->magic = conf->last = m; + } + else { + conf->last->next = m; + conf->last = m; + } + + /* set values in magic structure */ + m->flag = 0; + m->cont_level = 0; + m->lineno = lineno; + + while (*l == '>') { + ++l; /* step over */ + m->cont_level++; + } + + if (m->cont_level != 0 && *l == '(') { + ++l; /* step over */ + m->flag |= INDIR; + } + + /* get offset, then skip over it */ + m->offset = (int) strtol(l, &t, 0); + if (l == t) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv, + MODNAME ": offset %s invalid", l); + } + l = t; + + if (m->flag & INDIR) { + m->in.type = LONG; + m->in.offset = 0; + /* + * read [.lbs][+-]nnnnn) + */ + if (*l == '.') { + switch (*++l) { + case 'l': + m->in.type = LONG; + break; + case 's': + m->in.type = SHORT; + break; + case 'b': + m->in.type = BYTE; + break; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv, + MODNAME ": indirect offset type %c invalid", *l); + break; + } + l++; + } + s = l; + if (*l == '+' || *l == '-') + l++; + if (isdigit((unsigned char) *l)) { + m->in.offset = strtol(l, &t, 0); + if (*s == '-') + m->in.offset = -m->in.offset; + } + else + t = l; + if (*t++ != ')') { + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv, + MODNAME ": missing ')' in indirect offset"); + } + l = t; + } + + + while (isascii((unsigned char) *l) && isdigit((unsigned char) *l)) + ++l; + EATAB; + +#define NBYTE 4 +#define NSHORT 5 +#define NLONG 4 +#define NSTRING 6 +#define NDATE 4 +#define NBESHORT 7 +#define NBELONG 6 +#define NBEDATE 6 +#define NLESHORT 7 +#define NLELONG 6 +#define NLEDATE 6 + + if (*l == 'u') { + ++l; + m->flag |= UNSIGNED; + } + + /* get type, skip it */ + if (strncmp(l, "byte", NBYTE) == 0) { + m->type = BYTE; + l += NBYTE; + } + else if (strncmp(l, "short", NSHORT) == 0) { + m->type = SHORT; + l += NSHORT; + } + else if (strncmp(l, "long", NLONG) == 0) { + m->type = LONG; + l += NLONG; + } + else if (strncmp(l, "string", NSTRING) == 0) { + m->type = STRING; + l += NSTRING; + } + else if (strncmp(l, "date", NDATE) == 0) { + m->type = DATE; + l += NDATE; + } + else if (strncmp(l, "beshort", NBESHORT) == 0) { + m->type = BESHORT; + l += NBESHORT; + } + else if (strncmp(l, "belong", NBELONG) == 0) { + m->type = BELONG; + l += NBELONG; + } + else if (strncmp(l, "bedate", NBEDATE) == 0) { + m->type = BEDATE; + l += NBEDATE; + } + else if (strncmp(l, "leshort", NLESHORT) == 0) { + m->type = LESHORT; + l += NLESHORT; + } + else if (strncmp(l, "lelong", NLELONG) == 0) { + m->type = LELONG; + l += NLELONG; + } + else if (strncmp(l, "ledate", NLEDATE) == 0) { + m->type = LEDATE; + l += NLEDATE; + } + else { + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv, + MODNAME ": type %s invalid", l); + return -1; + } + /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */ + if (*l == '&') { + ++l; + m->mask = signextend(serv, m, strtol(l, &l, 0)); + } + else + m->mask = ~0L; + EATAB; + + switch (*l) { + case '>': + case '<': + /* Old-style anding: "0 byte &0x80 dynamically linked" */ + case '&': + case '^': + case '=': + m->reln = *l; + ++l; + break; + case '!': + if (m->type != STRING) { + m->reln = *l; + ++l; + break; + } + /* FALL THROUGH */ + default: + if (*l == 'x' && isascii((unsigned char) l[1]) && + isspace((unsigned char) l[1])) { + m->reln = *l; + ++l; + goto GetDesc; /* Bill The Cat */ + } + m->reln = '='; + break; + } + EATAB; + + if (getvalue(serv, m, &l)) + return -1; + /* + * now get last part - the description + */ + GetDesc: + EATAB; + if (l[0] == '\b') { + ++l; + m->nospflag = 1; + } + else if ((l[0] == '\\') && (l[1] == 'b')) { + ++l; + ++l; + m->nospflag = 1; + } + else + m->nospflag = 0; + strncpy(m->desc, l, sizeof(m->desc) - 1); + m->desc[sizeof(m->desc) - 1] = '\0'; + +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, serv, + MODNAME ": parse line=%d m=%x next=%x cont=%d desc=%s", + lineno, m, m->next, m->cont_level, m->desc); +#endif /* MIME_MAGIC_DEBUG */ + + return 0; +} + +/* + * Read a numeric value from a pointer, into the value union of a magic + * pointer, according to the magic type. Update the string pointer to point + * just after the number read. Return 0 for success, non-zero for failure. + */ +static int getvalue(server_rec *s, struct magic *m, char **p) +{ + int slen; + + if (m->type == STRING) { + *p = getstr(s, *p, m->value.s, sizeof(m->value.s), &slen); + m->vallen = slen; + } + else if (m->reln != 'x') + m->value.l = signextend(s, m, strtol(*p, p, 0)); + return 0; +} + +/* + * Convert a string containing C character escapes. Stop at an unescaped + * space or tab. Copy the converted version to "p", returning its length in + * *slen. Return updated scan pointer as function result. + */ +static char *getstr(server_rec *serv, register char *s, register char *p, + int plen, int *slen) +{ + char *origs = s, *origp = p; + char *pmax = p + plen - 1; + register int c; + register int val; + + while ((c = *s++) != '\0') { + if (isspace((unsigned char) c)) + break; + if (p >= pmax) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, serv, + MODNAME ": string too long: %s", origs); + break; + } + if (c == '\\') { + switch (c = *s++) { + + case '\0': + goto out; + + default: + *p++ = (char) c; + break; + + case 'n': + *p++ = '\n'; + break; + + case 'r': + *p++ = '\r'; + break; + + case 'b': + *p++ = '\b'; + break; + + case 't': + *p++ = '\t'; + break; + + case 'f': + *p++ = '\f'; + break; + + case 'v': + *p++ = '\v'; + break; + + /* \ and up to 3 octal digits */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + val = c - '0'; + c = *s++; /* try for 2 */ + if (c >= '0' && c <= '7') { + val = (val << 3) | (c - '0'); + c = *s++; /* try for 3 */ + if (c >= '0' && c <= '7') + val = (val << 3) | (c - '0'); + else + --s; + } + else + --s; + *p++ = (char) val; + break; + + /* \x and up to 3 hex digits */ + case 'x': + val = 'x'; /* Default if no digits */ + c = hextoint(*s++); /* Get next char */ + if (c >= 0) { + val = c; + c = hextoint(*s++); + if (c >= 0) { + val = (val << 4) + c; + c = hextoint(*s++); + if (c >= 0) { + val = (val << 4) + c; + } + else + --s; + } + else + --s; + } + else + --s; + *p++ = (char) val; + break; + } + } + else + *p++ = (char) c; + } + out: + *p = '\0'; + *slen = p - origp; + return s; +} + + +/* Single hex char to int; -1 if not a hex char. */ +static int hextoint(int c) +{ + if (!isascii((unsigned char) c)) + return -1; + if (isdigit((unsigned char) c)) + return c - '0'; + if ((c >= 'a') && (c <= 'f')) + return c + 10 - 'a'; + if ((c >= 'A') && (c <= 'F')) + return c + 10 - 'A'; + return -1; +} + + +/* + * return DONE to indicate it's been handled + * return OK to indicate it's a regular file still needing handling + * other returns indicate a failure of some sort + */ +static int fsmagic(request_rec *r, const char *fn) +{ + switch (r->finfo.st_mode & S_IFMT) { + case S_IFDIR: + magic_rsl_puts(r, DIR_MAGIC_TYPE); + return DONE; + case S_IFCHR: + /* + * (void) magic_rsl_printf(r,"character special (%d/%d)", + * major(sb->st_rdev), minor(sb->st_rdev)); + */ + (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN); + return DONE; +#ifdef S_IFBLK + case S_IFBLK: + /* + * (void) magic_rsl_printf(r,"block special (%d/%d)", + * major(sb->st_rdev), minor(sb->st_rdev)); + */ + (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN); + return DONE; + /* TODO add code to handle V7 MUX and Blit MUX files */ +#endif +#ifdef S_IFIFO + case S_IFIFO: + /* + * magic_rsl_puts(r,"fifo (named pipe)"); + */ + (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN); + return DONE; +#endif +#ifdef S_IFLNK + case S_IFLNK: + /* We used stat(), the only possible reason for this is that the + * symlink is broken. + */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": broken symlink (%s)", fn); + return HTTP_INTERNAL_SERVER_ERROR; +#endif +#ifdef S_IFSOCK +#ifndef __COHERENT__ + case S_IFSOCK: + magic_rsl_puts(r, MIME_BINARY_UNKNOWN); + return DONE; +#endif +#endif + case S_IFREG: + break; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": invalid mode 0%o.", (unsigned int)r->finfo.st_mode); + return HTTP_INTERNAL_SERVER_ERROR; + } + + /* + * regular file, check next possibility + */ + if (r->finfo.st_size == 0) { + magic_rsl_puts(r, MIME_TEXT_UNKNOWN); + return DONE; + } + return OK; +} + +/* + * softmagic - lookup one file in database (already read from /etc/magic by + * apprentice.c). Passed the name and FILE * of one file to be typed. + */ + /* ARGSUSED1 *//* nbytes passed for regularity, maybe need later */ +static int softmagic(request_rec *r, unsigned char *buf, int nbytes) +{ + if (match(r, buf, nbytes)) + return 1; + + return 0; +} + +/* + * Go through the whole list, stopping if you find a match. Process all the + * continuations of that match before returning. + * + * We support multi-level continuations: + * + * At any time when processing a successful top-level match, there is a current + * continuation level; it represents the level of the last successfully + * matched continuation. + * + * Continuations above that level are skipped as, if we see one, it means that + * the continuation that controls them - i.e, the lower-level continuation + * preceding them - failed to match. + * + * Continuations below that level are processed as, if we see one, it means + * we've finished processing or skipping higher-level continuations under the + * control of a successful or unsuccessful lower-level continuation, and are + * now seeing the next lower-level continuation and should process it. The + * current continuation level reverts to the level of the one we're seeing. + * + * Continuations at the current level are processed as, if we see one, there's + * no lower-level continuation that may have failed. + * + * If a continuation matches, we bump the current continuation level so that + * higher-level continuations are processed. + */ +static int match(request_rec *r, unsigned char *s, int nbytes) +{ +#if MIME_MAGIC_DEBUG + int rule_counter = 0; +#endif + int cont_level = 0; + int need_separator = 0; + union VALUETYPE p; + magic_server_config_rec *conf = (magic_server_config_rec *) + ap_get_module_config(r->server->module_config, &mime_magic_module); + struct magic *m; + +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": match conf=%x file=%s m=%s m->next=%s last=%s", + conf, + conf->magicfile ? conf->magicfile : "NULL", + conf->magic ? "set" : "NULL", + (conf->magic && conf->magic->next) ? "set" : "NULL", + conf->last ? "set" : "NULL"); +#endif + +#if MIME_MAGIC_DEBUG + for (m = conf->magic; m; m = m->next) { + if (isprint((((unsigned long) m) >> 24) & 255) && + isprint((((unsigned long) m) >> 16) & 255) && + isprint((((unsigned long) m) >> 8) & 255) && + isprint(((unsigned long) m) & 255)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": match: POINTER CLOBBERED! " + "m=\"%c%c%c%c\"", + (((unsigned long) m) >> 24) & 255, + (((unsigned long) m) >> 16) & 255, + (((unsigned long) m) >> 8) & 255, + ((unsigned long) m) & 255); + break; + } + } +#endif + + for (m = conf->magic; m; m = m->next) { +#if MIME_MAGIC_DEBUG + rule_counter++; + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": line=%d desc=%s", m->lineno, m->desc); +#endif + + /* check if main entry matches */ + if (!mget(r, &p, s, m, nbytes) || + !mcheck(r, &p, m)) { + struct magic *m_cont; + + /* + * main entry didn't match, flush its continuations + */ + if (!m->next || (m->next->cont_level == 0)) { + continue; + } + + m_cont = m->next; + while (m_cont && (m_cont->cont_level != 0)) { +#if MIME_MAGIC_DEBUG + rule_counter++; + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": line=%d mc=%x mc->next=%x cont=%d desc=%s", + m_cont->lineno, m_cont, + m_cont->next, m_cont->cont_level, + m_cont->desc); +#endif + /* + * this trick allows us to keep *m in sync when the continue + * advances the pointer + */ + m = m_cont; + m_cont = m_cont->next; + } + continue; + } + + /* if we get here, the main entry rule was a match */ + /* this will be the last run through the loop */ +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": rule matched, line=%d type=%d %s", + m->lineno, m->type, + (m->type == STRING) ? m->value.s : ""); +#endif + + /* print the match */ + mprint(r, &p, m); + + /* + * If we printed something, we'll need to print a blank before we + * print something else. + */ + if (m->desc[0]) + need_separator = 1; + /* and any continuations that match */ + cont_level++; + /* + * while (m && m->next && m->next->cont_level != 0 && ( m = m->next + * )) + */ + m = m->next; + while (m && (m->cont_level != 0)) { +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": match line=%d cont=%d type=%d %s", + m->lineno, m->cont_level, m->type, + (m->type == STRING) ? m->value.s : ""); +#endif + if (cont_level >= m->cont_level) { + if (cont_level > m->cont_level) { + /* + * We're at the end of the level "cont_level" + * continuations. + */ + cont_level = m->cont_level; + } + if (mget(r, &p, s, m, nbytes) && + mcheck(r, &p, m)) { + /* + * This continuation matched. Print its message, with a + * blank before it if the previous item printed and this + * item isn't empty. + */ + /* space if previous printed */ + if (need_separator + && (m->nospflag == 0) + && (m->desc[0] != '\0') + ) { + (void) magic_rsl_putchar(r, ' '); + need_separator = 0; + } + mprint(r, &p, m); + if (m->desc[0]) + need_separator = 1; + + /* + * If we see any continuations at a higher level, process + * them. + */ + cont_level++; + } + } + + /* move to next continuation record */ + m = m->next; + } +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": matched after %d rules", rule_counter); +#endif + return 1; /* all through */ + } +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": failed after %d rules", rule_counter); +#endif + return 0; /* no match at all */ +} + +static void mprint(request_rec *r, union VALUETYPE *p, struct magic *m) +{ + char *pp, *rt; + unsigned long v; + + switch (m->type) { + case BYTE: + v = p->b; + break; + + case SHORT: + case BESHORT: + case LESHORT: + v = p->h; + break; + + case LONG: + case BELONG: + case LELONG: + v = p->l; + break; + + case STRING: + if (m->reln == '=') { + (void) magic_rsl_printf(r, m->desc, m->value.s); + } + else { + (void) magic_rsl_printf(r, m->desc, p->s); + } + return; + + case DATE: + case BEDATE: + case LEDATE: + /* XXX: not multithread safe */ + pp = ctime((time_t *) & p->l); + if ((rt = strchr(pp, '\n')) != NULL) + *rt = '\0'; + (void) magic_rsl_printf(r, m->desc, pp); + return; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": invalid m->type (%d) in mprint().", + m->type); + return; + } + + v = signextend(r->server, m, v) & m->mask; + (void) magic_rsl_printf(r, m->desc, (unsigned long) v); +} + +/* + * Convert the byte order of the data we are looking at + */ +static int mconvert(request_rec *r, union VALUETYPE *p, struct magic *m) +{ + char *rt; + + switch (m->type) { + case BYTE: + case SHORT: + case LONG: + case DATE: + return 1; + case STRING: + /* Null terminate and eat the return */ + p->s[sizeof(p->s) - 1] = '\0'; + if ((rt = strchr(p->s, '\n')) != NULL) + *rt = '\0'; + return 1; + case BESHORT: + p->h = (short) ((p->hs[0] << 8) | (p->hs[1])); + return 1; + case BELONG: + case BEDATE: + p->l = (long) + ((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])); + return 1; + case LESHORT: + p->h = (short) ((p->hs[1] << 8) | (p->hs[0])); + return 1; + case LELONG: + case LEDATE: + p->l = (long) + ((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])); + return 1; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": invalid type %d in mconvert().", m->type); + return 0; + } +} + + +static int mget(request_rec *r, union VALUETYPE *p, unsigned char *s, + struct magic *m, int nbytes) +{ + long offset = m->offset; + + if (offset + sizeof(union VALUETYPE) > nbytes) + return 0; + + memcpy(p, s + offset, sizeof(union VALUETYPE)); + + if (!mconvert(r, p, m)) + return 0; + + if (m->flag & INDIR) { + + switch (m->in.type) { + case BYTE: + offset = p->b + m->in.offset; + break; + case SHORT: + offset = p->h + m->in.offset; + break; + case LONG: + offset = p->l + m->in.offset; + break; + } + + if (offset + sizeof(union VALUETYPE) > nbytes) + return 0; + + memcpy(p, s + offset, sizeof(union VALUETYPE)); + + if (!mconvert(r, p, m)) + return 0; + } + return 1; +} + +static int mcheck(request_rec *r, union VALUETYPE *p, struct magic *m) +{ + register unsigned long l = m->value.l; + register unsigned long v; + int matched; + + if ((m->value.s[0] == 'x') && (m->value.s[1] == '\0')) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": BOINK"); + return 1; + } + + switch (m->type) { + case BYTE: + v = p->b; + break; + + case SHORT: + case BESHORT: + case LESHORT: + v = p->h; + break; + + case LONG: + case BELONG: + case LELONG: + case DATE: + case BEDATE: + case LEDATE: + v = p->l; + break; + + case STRING: + l = 0; + /* + * What we want here is: v = strncmp(m->value.s, p->s, m->vallen); + * but ignoring any nulls. bcmp doesn't give -/+/0 and isn't + * universally available anyway. + */ + v = 0; + { + register unsigned char *a = (unsigned char *) m->value.s; + register unsigned char *b = (unsigned char *) p->s; + register int len = m->vallen; + + while (--len >= 0) + if ((v = *b++ - *a++) != 0) + break; + } + break; + default: + /* bogosity, pretend that it just wasn't a match */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": invalid type %d in mcheck().", m->type); + return 0; + } + + v = signextend(r->server, m, v) & m->mask; + + switch (m->reln) { + case 'x': +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + "%lu == *any* = 1", v); +#endif + matched = 1; + break; + + case '!': + matched = v != l; +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + "%lu != %lu = %d", v, l, matched); +#endif + break; + + case '=': + matched = v == l; +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + "%lu == %lu = %d", v, l, matched); +#endif + break; + + case '>': + if (m->flag & UNSIGNED) { + matched = v > l; +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + "%lu > %lu = %d", v, l, matched); +#endif + } + else { + matched = (long) v > (long) l; +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + "%ld > %ld = %d", v, l, matched); +#endif + } + break; + + case '<': + if (m->flag & UNSIGNED) { + matched = v < l; +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + "%lu < %lu = %d", v, l, matched); +#endif + } + else { + matched = (long) v < (long) l; +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + "%ld < %ld = %d", v, l, matched); +#endif + } + break; + + case '&': + matched = (v & l) == l; +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + "((%lx & %lx) == %lx) = %d", v, l, l, matched); +#endif + break; + + case '^': + matched = (v & l) != l; +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + "((%lx & %lx) != %lx) = %d", v, l, l, matched); +#endif + break; + + default: + /* bogosity, pretend it didn't match */ + matched = 0; + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->server, + MODNAME ": mcheck: can't happen: invalid relation %d.", + m->reln); + break; + } + + return matched; +} + +/* an optimization over plain strcmp() */ +#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) + +static int ascmagic(request_rec *r, unsigned char *buf, int nbytes) +{ + int i, has_escapes = 0; + unsigned char *s; + char nbuf[HOWMANY + 1]; /* one extra for terminating '\0' */ + char *token; + register struct names *p; + int small_nbytes; + + /* these are easy, do them first */ + + /* + * for troff, look for . + letter + letter or .\"; this must be done to + * disambiguate tar archives' ./file and other trash from real troff + * input. + */ + if (*buf == '.') { + unsigned char *tp = buf + 1; + + while (isascii(*tp) && isspace(*tp)) + ++tp; /* skip leading whitespace */ + if ((isascii(*tp) && (isalnum(*tp) || *tp == '\\') && + isascii(*(tp + 1)) && (isalnum(*(tp + 1)) || *tp == '"'))) { + magic_rsl_puts(r, "application/x-troff"); + return 1; + } + } + if ((*buf == 'c' || *buf == 'C') && + isascii(*(buf + 1)) && isspace(*(buf + 1))) { + /* Fortran */ + magic_rsl_puts(r, "text/plain"); + return 1; + } + + /* look for tokens from names.h - this is expensive!, so we'll limit + * ourselves to only SMALL_HOWMANY bytes */ + small_nbytes = (nbytes > SMALL_HOWMANY) ? SMALL_HOWMANY : nbytes; + /* make a copy of the buffer here because strtok() will destroy it */ + s = (unsigned char *) memcpy(nbuf, buf, small_nbytes); + s[small_nbytes] = '\0'; + has_escapes = (memchr(s, '\033', small_nbytes) != NULL); + /* XXX: not multithread safe */ + while ((token = strtok((char *) s, " \t\n\r\f")) != NULL) { + s = NULL; /* make strtok() keep on tokin' */ + for (p = names; p < names + NNAMES; p++) { + if (STREQ(p->name, token)) { + magic_rsl_puts(r, types[p->type]); + if (has_escapes) + magic_rsl_puts(r, " (with escape sequences)"); + return 1; + } + } + } + + switch (is_tar(buf, nbytes)) { + case 1: + /* V7 tar archive */ + magic_rsl_puts(r, "application/x-tar"); + return 1; + case 2: + /* POSIX tar archive */ + magic_rsl_puts(r, "application/x-tar"); + return 1; + } + + for (i = 0; i < nbytes; i++) { + if (!isascii(*(buf + i))) + return 0; /* not all ascii */ + } + + /* all else fails, but it is ascii... */ + if (has_escapes) { + /* text with escape sequences */ + /* we leave this open for further differentiation later */ + magic_rsl_puts(r, "text/plain"); + } + else { + /* plain text */ + magic_rsl_puts(r, "text/plain"); + } + return 1; +} + + +/* + * compress routines: zmagic() - returns 0 if not recognized, uncompresses + * and prints information if recognized uncompress(s, method, old, n, newch) + * - uncompress old into new, using method, return sizeof new + */ + +static struct { + char *magic; + int maglen; + char *argv[3]; + int silent; + char *encoding; /* MUST be lowercase */ +} compr[] = { + + { + "\037\235", 2, { + "uncompress", "-c", NULL + }, 0, "x-compress" + }, + { + "\037\213", 2, { + "gzip", "-dcq", NULL + }, 1, "x-gzip" + }, + /* + * XXX pcat does not work, cause I don't know how to make it read stdin, + * so we use gzip + */ + { + "\037\036", 2, { + "gzip", "-dcq", NULL + }, 0, "x-gzip" + }, +}; + +static int ncompr = sizeof(compr) / sizeof(compr[0]); + +static int zmagic(request_rec *r, unsigned char *buf, int nbytes) +{ + unsigned char *newbuf; + int newsize; + int i; + + for (i = 0; i < ncompr; i++) { + if (nbytes < compr[i].maglen) + continue; + if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0) + break; + } + + if (i == ncompr) + return 0; + + if ((newsize = uncompress(r, i, buf, &newbuf, nbytes)) > 0) { + tryit(r, newbuf, newsize); + + /* set encoding type in the request record */ + r->content_encoding = compr[i].encoding; + } + return 1; +} + + +struct uncompress_parms { + request_rec *r; + int method; +}; + +static int uncompress_child(void *data, child_info *pinfo) +{ + struct uncompress_parms *parm = data; +#if defined(WIN32) + int child_pid; +#endif + + if (compr[parm->method].silent) { + close(STDERR_FILENO); + } + +#if defined(WIN32) + child_pid = spawnvp(compr[parm->method].argv[0], + compr[parm->method].argv); + return (child_pid); +#else + execvp(compr[parm->method].argv[0], compr[parm->method].argv); + ap_log_error(APLOG_MARK, APLOG_ERR, parm->r->server, + MODNAME ": could not execute `%s'.", + compr[parm->method].argv[0]); + return -1; +#endif +} + + +static int uncompress(request_rec *r, int method, const unsigned char *old, + unsigned char **newch, int n) +{ + struct uncompress_parms parm; + BUFF *bin, *bout; + pool *sub_pool; + + parm.r = r; + parm.method = method; + + /* We make a sub_pool so that we can collect our child early, otherwise + * there are cases (i.e. generating directory indicies with mod_autoindex) + * where we would end up with LOTS of zombies. + */ + sub_pool = ap_make_sub_pool(r->pool); + + if (!ap_spawn_child_err_buff(sub_pool, uncompress_child, &parm, kill_always, + &bin, &bout, NULL)) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + MODNAME ": couldn't spawn uncompress process: %s", r->uri); + return -1; + } + + if (ap_bwrite(bin, old, n) != n) { + ap_destroy_pool(sub_pool); + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + MODNAME ": write failed."); + return -1; + } + ap_bclose(bin); + *newch = (unsigned char *) ap_palloc(r->pool, n); + if ((n = ap_bread(bout, *newch, n)) <= 0) { + ap_destroy_pool(sub_pool); + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + MODNAME ": read failed %s", r->filename); + return -1; + } + ap_destroy_pool(sub_pool); + return n; +} + +/* + * is_tar() -- figure out whether file is a tar archive. + * + * Stolen (by author of file utility) from the public domain tar program: Public + * Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu). + * + * @(#)list.c 1.18 9/23/86 Public Domain - gnu $Id: mod_mime_magic.c,v 1.7 + * 1997/06/24 00:41:02 ikluft Exp ikluft $ + * + * Comments changed and some code/comments reformatted for file command by Ian + * Darwin. + */ + +#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') ) + +/* + * Return 0 if the checksum is bad (i.e., probably not a tar archive), 1 for + * old UNIX tar file, 2 for Unix Std (POSIX) tar file. + */ + +static int is_tar(unsigned char *buf, int nbytes) +{ + register union record *header = (union record *) buf; + register int i; + register long sum, recsum; + register char *p; + + if (nbytes < sizeof(union record)) + return 0; + + recsum = from_oct(8, header->header.chksum); + + sum = 0; + p = header->charptr; + for (i = sizeof(union record); --i >= 0;) { + /* + * We can't use unsigned char here because of old compilers, e.g. V7. + */ + sum += 0xFF & *p++; + } + + /* Adjust checksum to count the "chksum" field as blanks. */ + for (i = sizeof(header->header.chksum); --i >= 0;) + sum -= 0xFF & header->header.chksum[i]; + sum += ' ' * sizeof header->header.chksum; + + if (sum != recsum) + return 0; /* Not a tar archive */ + + if (0 == strcmp(header->header.magic, TMAGIC)) + return 2; /* Unix Standard tar archive */ + + return 1; /* Old fashioned tar archive */ +} + + +/* + * Quick and dirty octal conversion. + * + * Result is -1 if the field is invalid (all blank, or nonoctal). + */ +static long from_oct(int digs, char *where) +{ + register long value; + + while (isspace(*where)) { /* Skip spaces */ + where++; + if (--digs <= 0) + return -1; /* All blank field */ + } + value = 0; + while (digs > 0 && isodigit(*where)) { /* Scan til nonoctal */ + value = (value << 3) | (*where++ - '0'); + --digs; + } + + if (digs > 0 && *where && !isspace(*where)) + return -1; /* Ended on non-space/nul */ + + return value; +} + +/* + * Check for file-revision suffix + * + * This is for an obscure document control system used on an intranet. + * The web representation of each file's revision has an @1, @2, etc + * appended with the revision number. This needs to be stripped off to + * find the file suffix, which can be recognized by sending the name back + * through a sub-request. The base file name (without the @num suffix) + * must exist because its type will be used as the result. + */ +static int revision_suffix(request_rec *r) +{ + int suffix_pos, result; + char *sub_filename; + request_rec *sub; + +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": revision_suffix checking %s", r->filename); +#endif /* MIME_MAGIC_DEBUG */ + + /* check for recognized revision suffix */ + suffix_pos = strlen(r->filename) - 1; + if (!isdigit(r->filename[suffix_pos])) { + return 0; + } + while (suffix_pos >= 0 && isdigit(r->filename[suffix_pos])) + suffix_pos--; + if (suffix_pos < 0 || r->filename[suffix_pos] != '@') { + return 0; + } + + /* perform sub-request for the file name without the suffix */ + result = 0; + sub_filename = ap_pstrndup(r->pool, r->filename, suffix_pos); +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": subrequest lookup for %s", sub_filename); +#endif /* MIME_MAGIC_DEBUG */ + sub = ap_sub_req_lookup_file(sub_filename, r); + + /* extract content type/encoding/language from sub-request */ + if (sub->content_type) { + r->content_type = ap_pstrdup(r->pool, sub->content_type); +#if MIME_MAGIC_DEBUG + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, r->server, + MODNAME ": subrequest %s got %s", + sub_filename, r->content_type); +#endif /* MIME_MAGIC_DEBUG */ + if (sub->content_encoding) + r->content_encoding = + ap_pstrdup(r->pool, sub->content_encoding); + if (sub->content_language) + r->content_language = + ap_pstrdup(r->pool, sub->content_language); + result = 1; + } + + /* clean up */ + ap_destroy_sub_req(sub); + + return result; +} + +/* + * initialize the module + */ + +static void magic_init(server_rec *main_server, pool *p) +{ + int result; + magic_server_config_rec *conf; + magic_server_config_rec *main_conf; + server_rec *s; +#if MIME_MAGIC_DEBUG + struct magic *m, *prevm; +#endif /* MIME_MAGIC_DEBUG */ + + main_conf = ap_get_module_config(main_server->module_config, &mime_magic_module); + for (s = main_server; s; s = s->next) { + conf = ap_get_module_config(s->module_config, &mime_magic_module); + if (conf->magicfile == NULL && s != main_server) { + /* inherits from the parent */ + *conf = *main_conf; + } + else if (conf->magicfile) { + result = apprentice(s, p); + if (result == -1) + return; +#if MIME_MAGIC_DEBUG + prevm = 0; + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s, + MODNAME ": magic_init 1 test"); + for (m = conf->magic; m; m = m->next) { + if (isprint((((unsigned long) m) >> 24) & 255) && + isprint((((unsigned long) m) >> 16) & 255) && + isprint((((unsigned long) m) >> 8) & 255) && + isprint(((unsigned long) m) & 255)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, s, + MODNAME ": magic_init 1: POINTER CLOBBERED! " + "m=\"%c%c%c%c\" line=%d", + (((unsigned long) m) >> 24) & 255, + (((unsigned long) m) >> 16) & 255, + (((unsigned long) m) >> 8) & 255, + ((unsigned long) m) & 255, + prevm ? prevm->lineno : -1); + break; + } + prevm = m; + } +#endif + } + } +} + +/* + * Find the Content-Type from any resource this module has available + */ + +static int magic_find_ct(request_rec *r) +{ + int result; + magic_server_config_rec *conf; + + /* the file has to exist */ + if (r->finfo.st_mode == 0 || !r->filename) { + return DECLINED; + } + + /* was someone else already here? */ + if (r->content_type) { + return DECLINED; + } + + conf = ap_get_module_config(r->server->module_config, &mime_magic_module); + if (!conf || !conf->magic) { + return DECLINED; + } + + /* initialize per-request info */ + if (!magic_set_config(r)) { + return HTTP_INTERNAL_SERVER_ERROR; + } + + /* try excluding file-revision suffixes */ + if (revision_suffix(r) != 1) { + /* process it based on the file contents */ + if ((result = magic_process(r)) != OK) { + return result; + } + } + + /* if we have any results, put them in the request structure */ + return magic_rsl_to_request(r); +} + +/* + * Apache API module interface + */ + +module mime_magic_module = +{ + STANDARD_MODULE_STUFF, + magic_init, /* initializer */ + NULL, /* dir config creator */ + NULL, /* dir merger --- default is to override */ + create_magic_server_config, /* server config */ + merge_magic_server_config, /* merge server config */ + mime_magic_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + magic_find_ct, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_negotiation.c b/APACHE_1_3b7/src/modules/standard/mod_negotiation.c new file mode 100644 index 0000000000..f91902189c --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_negotiation.c @@ -0,0 +1,2302 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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_negotiation.c: keeps track of MIME types the client is willing to + * accept, and contains code to handle type arbitration. + * + * rst + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_log.h" +#include "util_script.h" + +/* define TCN_02 to allow for Holtman I-D transparent negotiation. + * This file currently implements the draft-02, except for + * anything to do with features and cache-control (max-age etc) + * + * Since the draft is just that, and we don't yet implement + * everything, regard the transparent negotiation stuff as experimental. + */ +/*#define TCN_02 */ + +/* Commands --- configuring document caching on a per (virtual?) + * server basis... + */ + +typedef struct { + array_header *language_priority; +} neg_dir_config; + +module MODULE_VAR_EXPORT negotiation_module; + +static char *merge_string_array(pool *p, array_header *arr, char *sep) +{ + int i; + char *t = ""; + + for (i = 0; i < arr->nelts; i++) { + t = ap_pstrcat(p, t, (i ? sep : ""), ((char **) arr->elts)[i], NULL); + } + return t; +} + +static void *create_neg_dir_config(pool *p, char *dummy) +{ + neg_dir_config *new = (neg_dir_config *) ap_palloc(p, sizeof(neg_dir_config)); + + new->language_priority = ap_make_array(p, 4, sizeof(char *)); + return new; +} + +static void *merge_neg_dir_configs(pool *p, void *basev, void *addv) +{ + neg_dir_config *base = (neg_dir_config *) basev; + neg_dir_config *add = (neg_dir_config *) addv; + neg_dir_config *new = (neg_dir_config *) ap_palloc(p, sizeof(neg_dir_config)); + + /* give priority to the config in the subdirectory */ + new->language_priority = ap_append_arrays(p, add->language_priority, + base->language_priority); + return new; +} + +static const char *set_language_priority(cmd_parms *cmd, void *n, char *lang) +{ + array_header *arr = ((neg_dir_config *) n)->language_priority; + char **langp = (char **) ap_push_array(arr); + + *langp = lang; + return NULL; +} + +static const char *cache_negotiated_docs(cmd_parms *cmd, void *dummy, + char *dummy2) +{ + void *server_conf = cmd->server->module_config; + + ap_set_module_config(server_conf, &negotiation_module, "Cache"); + return NULL; +} + +static int do_cache_negotiated_docs(server_rec *s) +{ + return (ap_get_module_config(s->module_config, &negotiation_module) != NULL); +} + +static const command_rec negotiation_cmds[] = +{ + {"CacheNegotiatedDocs", cache_negotiated_docs, NULL, RSRC_CONF, NO_ARGS, + "no arguments (either present or absent)"}, + {"LanguagePriority", set_language_priority, NULL, OR_FILEINFO, ITERATE, + "space-delimited list of MIME language abbreviations"}, + {NULL} +}; + +/* + * Record of available info on a media type specified by the client + * (we also use 'em for encodings and languages) + */ + +typedef struct accept_rec { + char *type_name; /* MUST be lowercase */ + float quality; + float max_bytes; + float level; + char *charset; /* for content-type only */ +} accept_rec; + +/* + * Record of available info on a particular variant + * + * Note that a few of these fields are updated by the actual negotiation + * code. These are: + * + * level_matched --- initialized to zero. Set to the value of level + * if the client actually accepts this media type at that + * level (and *not* if it got in on a wildcard). See level_cmp + * below. + */ + +typedef struct var_rec { + request_rec *sub_req; /* May be NULL (is, for map files) */ + char *type_name; /* MUST be lowercase */ + char *file_name; + char *content_encoding; + array_header *content_languages; /* list of languages for this variant */ + char *content_charset; + char *description; + + /* The next five items give the quality values for the dimensions + * of negotiation for this variant. They are obtained from the + * appropriate header lines, except for accept_type_quality, which + * is obtained from the variant itself (the 'qs' parameter value + * from the variant's mime-type). Apart from type_quality, + * these values are set when we find the quality for each variant + * (see best_match()). type_quality is set from the 'qs' parameter + * of the variant description or mime type: see set_mime_fields(). + */ + float lang_quality; /* quality of this variant's language */ + int encoding_quality; /* ditto encoding (1 or 0 only) */ + float charset_quality; /* ditto charset */ + float accept_type_quality; /* ditto media type */ + float type_quality; /* quality of source for this type */ + + /* Now some special values */ + float level; /* Auxiliary to content-type... */ + float bytes; /* content length, if known */ + int lang_index; /* pre HTTP/1.1 language priority stuff */ + int is_pseudo_html; /* text/html, *or* the INCLUDES_MAGIC_TYPEs */ + + /* Above are all written-once properties of the variant. The + * three fields below are changed during negotiation: + */ + + float level_matched; + int mime_stars; + int definite; +} var_rec; + +/* Something to carry around the state of negotiation (and to keep + * all of this thread-safe)... + */ + +typedef struct { + pool *pool; + request_rec *r; + char *dir_name; + int accept_q; /* 1 if an Accept item has a q= param */ + float default_lang_quality; /* fiddle lang q for variants with no lang */ + + + array_header *accepts; /* accept_recs */ + int have_accept_header; /* 1 if Accept-Header present */ + array_header *accept_encodings; /* accept_recs */ + array_header *accept_charsets; /* accept_recs */ + array_header *accept_langs; /* accept_recs */ + array_header *avail_vars; /* available variants */ + + int count_multiviews_variants; /* number of variants found on disk */ + + int ua_can_negotiate; /* 1 if ua can do transparent negotiate */ + int use_transparent_neg; /* 1 if we are using transparent neg */ + int short_accept_headers; /* 1 if ua does trans neg & sent short accpt */ +} negotiation_state; + +/* A few functions to manipulate var_recs. + * Cleaning out the fields... + */ + +static void clean_var_rec(var_rec *mime_info) +{ + mime_info->sub_req = NULL; + mime_info->type_name = ""; + mime_info->file_name = ""; + mime_info->content_encoding = NULL; + mime_info->content_languages = NULL; + mime_info->content_charset = ""; + mime_info->description = ""; + + mime_info->is_pseudo_html = 0; + mime_info->level = 0.0f; + mime_info->level_matched = 0.0f; + mime_info->bytes = 0.0f; + mime_info->lang_index = -1; + mime_info->mime_stars = 0; + mime_info->definite = 1; + + mime_info->charset_quality = 1.0f; + mime_info->type_quality = 0.0f; + mime_info->encoding_quality = 1; + mime_info->lang_quality = 1.0f; + mime_info->accept_type_quality = 1.0f; +} + +/* Initializing the relevant fields of a variant record from the + * accept_info read out of its content-type, one way or another. + */ + +static void set_mime_fields(var_rec *var, accept_rec *mime_info) +{ + var->type_name = mime_info->type_name; + var->type_quality = mime_info->quality; + var->level = mime_info->level; + var->content_charset = mime_info->charset; + + var->is_pseudo_html = (!strcmp(var->type_name, "text/html") + || !strcmp(var->type_name, INCLUDES_MAGIC_TYPE) + || !strcmp(var->type_name, INCLUDES_MAGIC_TYPE3)); +} + +/***************************************************************** + * + * Parsing (lists of) media types and their parameters, as seen in + * HTTPD header lines and elsewhere. + */ + +/* + * Get a single mime type entry --- one media type and parameters; + * enter the values we recognize into the argument accept_rec + */ + +static char *get_entry(pool *p, accept_rec *result, char *accept_line) +{ + result->quality = 1.0f; + result->max_bytes = 0.0f; + result->level = 0.0f; + result->charset = ""; + + /* + * Note that this handles what I gather is the "old format", + * + * Accept: text/html text/plain moo/zot + * + * without any compatibility kludges --- if the token after the + * MIME type begins with a semicolon, we know we're looking at parms, + * otherwise, we know we aren't. (So why all the pissing and moaning + * in the CERN server code? I must be missing something). + */ + + result->type_name = ap_get_token(p, &accept_line, 0); + ap_str_tolower(result->type_name); /* You want case-insensitive, + * you'll *get* case-insensitive. + */ + + /* KLUDGE!!! Default HTML to level 2.0 unless the browser + * *explicitly* says something else. + */ + + if (!strcmp(result->type_name, "text/html") && (result->level == 0.0)) { + result->level = 2.0f; + } + else if (!strcmp(result->type_name, INCLUDES_MAGIC_TYPE)) { + result->level = 2.0f; + } + else if (!strcmp(result->type_name, INCLUDES_MAGIC_TYPE3)) { + result->level = 3.0f; + } + + while (*accept_line == ';') { + /* Parameters ... */ + + char *parm; + char *cp; + char *end; + + ++accept_line; + parm = ap_get_token(p, &accept_line, 1); + + /* Look for 'var = value' --- and make sure the var is in lcase. */ + + for (cp = parm; (*cp && !isspace(*cp) && *cp != '='); ++cp) { + *cp = tolower(*cp); + } + + if (!*cp) { + continue; /* No '='; just ignore it. */ + } + + *cp++ = '\0'; /* Delimit var */ + while (*cp && (isspace(*cp) || *cp == '=')) { + ++cp; + } + + if (*cp == '"') { + ++cp; + for (end = cp; + (*end && *end != '\n' && *end != '\r' && *end != '\"'); + end++); + } + else { + for (end = cp; (*end && !isspace(*end)); end++); + } + if (*end) { + *end = '\0'; /* strip ending quote or return */ + } + ap_str_tolower(cp); + + if (parm[0] == 'q' + && (parm[1] == '\0' || (parm[1] == 's' && parm[2] == '\0'))) { + result->quality = atof(cp); + } + else if (parm[0] == 'm' && parm[1] == 'x' && + parm[2] == 'b' && parm[3] == '\0') { + result->max_bytes = atof(cp); + } + else if (parm[0] == 'l' && !strcmp(&parm[1], "evel")) { + result->level = atof(cp); + } + else if (!strcmp(parm, "charset")) { + result->charset = cp; + } + } + + if (*accept_line == ',') { + ++accept_line; + } + + return accept_line; +} + +/***************************************************************** + * + * Dealing with header lines ... + * + * Accept, Accept-Charset, Accept-Language and Accept-Encoding + * are handled by do_header_line() - they all have the same + * basic structure of a list of items of the format + * name; q=N; charset=TEXT + * + * where q is only valid in Accept, Accept-Charset and Accept-Languages, + * and charset is only valid in Accept. + */ + +static array_header *do_header_line(pool *p, char *accept_line) +{ + array_header *accept_recs = ap_make_array(p, 40, sizeof(accept_rec)); + + if (!accept_line) { + return accept_recs; + } + + while (*accept_line) { + accept_rec *new = (accept_rec *) ap_push_array(accept_recs); + accept_line = get_entry(p, new, accept_line); + } + + return accept_recs; +} + +/* Given the text of the Content-Languages: line from the var map file, + * return an array containing the languages of this variant + */ + +static array_header *do_languages_line(pool *p, char **lang_line) +{ + array_header *lang_recs = ap_make_array(p, 2, sizeof(char *)); + + if (!lang_line) { + return lang_recs; + } + + while (**lang_line) { + char **new = (char **) ap_push_array(lang_recs); + *new = ap_get_token(p, lang_line, 0); + ap_str_tolower(*new); + if (**lang_line == ',' || **lang_line == ';') { + ++(*lang_line); + } + } + + return lang_recs; +} + +/***************************************************************** + * + * Handling header lines from clients... + */ + +static negotiation_state *parse_accept_headers(request_rec *r) +{ + negotiation_state *new = (negotiation_state *) ap_pcalloc(r->pool, + sizeof(negotiation_state)); + accept_rec *elts; + table *hdrs = r->headers_in; + int i; + char *hdr; + + new->pool = r->pool; + new->r = r; + new->dir_name = ap_make_dirstr_parent(r->pool, r->filename); + + new->accepts = do_header_line(r->pool, ap_table_get(hdrs, "Accept")); + + hdr = ap_table_get(hdrs, "Accept-encoding"); + if (hdr) { + new->have_accept_header = 1; + } + new->accept_encodings = do_header_line(r->pool, hdr); + + new->accept_langs = do_header_line(r->pool, + ap_table_get(hdrs, "Accept-language")); + new->accept_charsets = do_header_line(r->pool, + ap_table_get(hdrs, "Accept-charset")); + new->avail_vars = ap_make_array(r->pool, 40, sizeof(var_rec)); + +#ifdef TCN_02 + if (ap_table_get(r->headers_in, "Negotiate")) { + /* Negotiate: header tells us UA does transparent negotiation + * We have to decide whether we want to ... for now, yes, + * we do */ + + new->ua_can_negotiate = 1; + if (r->method_number == M_GET) { + new->use_transparent_neg = 1; /* should be configurable */ + } + + /* Check for 'Short Accept', ie either no Accept: header, + * or just "Accept: * / *" */ + if (new->accepts->nelts == 0 || + (new->accepts->nelts == 1 && + (!strcmp(((accept_rec *) new->accepts->elts)[0].type_name, + "*/*")))) { + /* Using short accept header */ + new->short_accept_headers = 1; + } + } +#endif + + if (!new->use_transparent_neg) { + /* Now we check for q-values. If they're all 1.0, we assume the + * client is "broken", and we are allowed to fiddle with the + * values later. Otherwise, we leave them alone. + */ + + elts = (accept_rec *) new->accepts->elts; + + for (i = 0; i < new->accepts->nelts; ++i) { + if (elts[i].quality < 1.0) { + new->accept_q = 1; + } + } + } + else { + new->accept_q = 1; + } + + return new; +} + +/* Sometimes clients will give us no Accept info at all; this routine sets + * up the standard default for that case, and also arranges for us to be + * willing to run a CGI script if we find one. (In fact, we set up to + * dramatically prefer CGI scripts in cases where that's appropriate, + * e.g., POST). + */ + +static void maybe_add_default_encodings(negotiation_state *neg, int prefer_scripts) +{ + accept_rec *new_accept = (accept_rec *) ap_push_array(neg->accepts); + + new_accept->type_name = CGI_MAGIC_TYPE; + new_accept->quality = prefer_scripts ? 1e-20f : 1e20f; + new_accept->level = 0.0f; + new_accept->max_bytes = 0.0f; + + if (neg->accepts->nelts > 1) { + return; + } + + new_accept = (accept_rec *) ap_push_array(neg->accepts); + + new_accept->type_name = "*/*"; + new_accept->quality = 1.0f; + new_accept->level = 0.0f; + new_accept->max_bytes = 0.0f; +} + +/***************************************************************** + * + * Parsing type-map files, in Roy's meta/http format augmented with + * #-comments. + */ + +/* Reading RFC822-style header lines, ignoring #-comments and + * handling continuations. + */ + +enum header_state { + header_eof, header_seen, header_sep +}; + +static enum header_state get_header_line(char *buffer, int len, FILE *map) +{ + char *buf_end = buffer + len; + char *cp; + int c; + + /* Get a noncommented line */ + + do { + if (fgets(buffer, MAX_STRING_LEN, map) == NULL) { + return header_eof; + } + } while (buffer[0] == '#'); + + /* If blank, just return it --- this ends information on this variant */ + + for (cp = buffer; (*cp && isspace(*cp)); ++cp) { + continue; + } + + if (*cp == '\0') { + return header_sep; + } + + /* If non-blank, go looking for header lines, but note that we still + * have to treat comments specially... + */ + + cp += strlen(cp); + + while ((c = getc(map)) != EOF) { + if (c == '#') { + /* Comment line */ + while ((c = getc(map)) != EOF && c != '\n') { + continue; + } + } + else if (isspace(c)) { + /* Leading whitespace. POSSIBLE continuation line + * Also, possibly blank --- if so, we ungetc() the final newline + * so that we will pick up the blank line the next time 'round. + */ + + while (c != EOF && c != '\n' && isspace(c)) { + c = getc(map); + } + + ungetc(c, map); + + if (c == '\n') { + return header_seen; /* Blank line */ + } + + /* Continuation */ + + while (cp < buf_end - 2 && (c = getc(map)) != EOF && c != '\n') { + *cp++ = c; + } + + *cp++ = '\n'; + *cp = '\0'; + } + else { + + /* Line beginning with something other than whitespace */ + + ungetc(c, map); + return header_seen; + } + } + + return header_seen; +} + +/* Stripping out RFC822 comments */ + +static void strip_paren_comments(char *hdr) +{ + /* Hmmm... is this correct? In Roy's latest draft, (comments) can nest! */ + + while (*hdr) { + if (*hdr == '"') { + hdr = strchr(hdr, '"'); + if (hdr == NULL) { + return; + } + ++hdr; + } + else if (*hdr == '(') { + while (*hdr && *hdr != ')') { + *hdr++ = ' '; + } + + if (*hdr) { + *hdr++ = ' '; + } + } + else { + ++hdr; + } + } +} + +/* Getting to a header body from the header */ + +static char *lcase_header_name_return_body(char *header, request_rec *r) +{ + char *cp = header; + + for ( ; *cp && *cp != ':' ; ++cp) { + *cp = tolower(*cp); + } + + if (!*cp) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Syntax error in type map --- no ':': %s", r->filename); + return NULL; + } + + do { + ++cp; + } while (*cp && isspace(*cp)); + + if (!*cp) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Syntax error in type map --- no header body: %s", + r->filename); + return NULL; + } + + return cp; +} + +static int read_type_map(negotiation_state *neg, request_rec *rr) +{ + request_rec *r = neg->r; + FILE *map; + char buffer[MAX_STRING_LEN]; + enum header_state hstate; + struct var_rec mime_info; + + /* We are not using multiviews */ + neg->count_multiviews_variants = 0; + + if (rr->status != HTTP_OK) { + return rr->status; + } + map = ap_pfopen(neg->pool, rr->filename, "r"); + if (map == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "cannot access type map file: %s", rr->filename); + return HTTP_FORBIDDEN; + } + + clean_var_rec(&mime_info); + + do { + hstate = get_header_line(buffer, MAX_STRING_LEN, map); + + if (hstate == header_seen) { + char *body = lcase_header_name_return_body(buffer, neg->r); + + if (body == NULL) { + return SERVER_ERROR; + } + + strip_paren_comments(body); + + if (!strncmp(buffer, "uri:", 4)) { + mime_info.file_name = ap_get_token(neg->pool, &body, 0); + } + else if (!strncmp(buffer, "content-type:", 13)) { + struct accept_rec accept_info; + + get_entry(neg->pool, &accept_info, body); + set_mime_fields(&mime_info, &accept_info); + } + else if (!strncmp(buffer, "content-length:", 15)) { + mime_info.bytes = atof(body); + } + else if (!strncmp(buffer, "content-language:", 17)) { + mime_info.content_languages = do_languages_line(neg->pool, + &body); + } + else if (!strncmp(buffer, "content-encoding:", 17)) { + mime_info.content_encoding = ap_get_token(neg->pool, &body, 0); + } + else if (!strncmp(buffer, "description:", 12)) { + mime_info.description = ap_get_token(neg->pool, &body, 0); + } + } + else { + if (mime_info.type_quality > 0 && *mime_info.file_name) { + void *new_var = ap_push_array(neg->avail_vars); + + memcpy(new_var, (void *) &mime_info, sizeof(var_rec)); + } + + clean_var_rec(&mime_info); + } + } while (hstate != header_eof); + + ap_pfclose(neg->pool, map); + return OK; +} + +/***************************************************************** + * + * Same, except we use a filtered directory listing as the map... + */ + +static int read_types_multi(negotiation_state *neg) +{ + request_rec *r = neg->r; + + char *filp; + int prefix_len; + DIR *dirp; + struct DIR_TYPE *dir_entry; + struct var_rec mime_info; + struct accept_rec accept_info; + void *new_var; + + clean_var_rec(&mime_info); + + if (!(filp = strrchr(r->filename, '/'))) { + return DECLINED; /* Weird... */ + } + + if (strncmp(r->filename, "proxy:", 6) == 0) { + return DECLINED; + } + + ++filp; + prefix_len = strlen(filp); + + dirp = ap_popendir(neg->pool, neg->dir_name); + + if (dirp == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "cannot read directory for multi: %s", neg->dir_name); + return HTTP_FORBIDDEN; + } + + while ((dir_entry = readdir(dirp))) { + request_rec *sub_req; + + /* Do we have a match? */ + + if (strncmp(dir_entry->d_name, filp, prefix_len)) { + continue; + } + if (dir_entry->d_name[prefix_len] != '.') { + continue; + } + + /* Yep. See if it's something which we have access to, and + * which has a known type and encoding (as opposed to something + * which we'll be slapping default_type on later). + */ + + sub_req = ap_sub_req_lookup_file(dir_entry->d_name, r); + + /* If it has a handler, we'll pretend it's a CGI script, + * since that's a good indication of the sort of thing it + * might be doing. + */ + if (sub_req->handler && !sub_req->content_type) { + sub_req->content_type = CGI_MAGIC_TYPE; + } + + if (sub_req->status != HTTP_OK || !sub_req->content_type) { + ap_destroy_sub_req(sub_req); + continue; + } + + /* If it's a map file, we use that instead of the map + * we're building... + */ + + if (((sub_req->content_type) && + !strcmp(sub_req->content_type, MAP_FILE_MAGIC_TYPE)) || + ((sub_req->handler) && + !strcmp(sub_req->handler, "type-map"))) { + + ap_pclosedir(neg->pool, dirp); + neg->avail_vars->nelts = 0; + return read_type_map(neg, sub_req); + } + + /* Have reasonable variant --- gather notes. + */ + + mime_info.sub_req = sub_req; + mime_info.file_name = ap_pstrdup(neg->pool, dir_entry->d_name); + if (sub_req->content_encoding) { + mime_info.content_encoding = sub_req->content_encoding; + } + if (sub_req->content_languages) { + mime_info.content_languages = sub_req->content_languages; + } + + get_entry(neg->pool, &accept_info, sub_req->content_type); + set_mime_fields(&mime_info, &accept_info); + + new_var = ap_push_array(neg->avail_vars); + memcpy(new_var, (void *) &mime_info, sizeof(var_rec)); + + neg->count_multiviews_variants++; + + clean_var_rec(&mime_info); + } + + ap_pclosedir(neg->pool, dirp); + return OK; +} + + +/***************************************************************** + * And now for the code you've been waiting for... actually + * finding a match to the client's requirements. + */ + +/* Matching MIME types ... the star/star and foo/star commenting conventions + * are implemented here. (You know what I mean by star/star, but just + * try mentioning those three characters in a C comment). Using strcmp() + * is legit, because everything has already been smashed to lowercase. + * + * Note also that if we get an exact match on the media type, we update + * level_matched for use in level_cmp below... + * + * We also give a value for mime_stars, which is used later. It should + * be 1 for star/star, 2 for type/star and 3 for type/subtype. + */ + +static int mime_match(accept_rec *accept_r, var_rec *avail) +{ + char *accept_type = accept_r->type_name; + char *avail_type = avail->type_name; + int len = strlen(accept_type); + + if (accept_type[0] == '*') { /* Anything matches star/star */ + if (avail->mime_stars < 1) { + avail->mime_stars = 1; + } + return 1; + } + else if ((accept_type[len - 1] == '*') && + !strncmp(accept_type, avail_type, len - 2)) { + if (avail->mime_stars < 2) { + avail->mime_stars = 2; + } + return 1; + } + else if (!strcmp(accept_type, avail_type) + || (!strcmp(accept_type, "text/html") + && (!strcmp(avail_type, INCLUDES_MAGIC_TYPE) + || !strcmp(avail_type, INCLUDES_MAGIC_TYPE3)))) { + if (accept_r->level >= avail->level) { + avail->level_matched = avail->level; + avail->mime_stars = 3; + return 1; + } + } + + return OK; +} + +/* This code implements a piece of the tie-breaking algorithm between + * variants of equal quality. This piece is the treatment of variants + * of the same base media type, but different levels. What we want to + * return is the variant at the highest level that the client explicitly + * claimed to accept. + * + * If all the variants available are at a higher level than that, or if + * the client didn't say anything specific about this media type at all + * and these variants just got in on a wildcard, we prefer the lowest + * level, on grounds that that's the one that the client is least likely + * to choke on. + * + * (This is all motivated by treatment of levels in HTML --- we only + * want to give level 3 to browsers that explicitly ask for it; browsers + * that don't, including HTTP/0.9 browsers that only get the implicit + * "Accept: * / *" [space added to avoid confusing cpp --- no, that + * syntax doesn't really work] should get HTML2 if available). + * + * (Note that this code only comes into play when we are choosing among + * variants of equal quality, where the draft standard gives us a fair + * bit of leeway about what to do. It ain't specified by the standard; + * rather, it is a choice made by this server about what to do in cases + * where the standard does not specify a unique course of action). + */ + +static int level_cmp(var_rec *var1, var_rec *var2) +{ + /* Levels are only comparable between matching media types */ + + if (var1->is_pseudo_html && !var2->is_pseudo_html) { + return 0; + } + + if (!var1->is_pseudo_html && strcmp(var1->type_name, var2->type_name)) { + return 0; + } + + /* Take highest level that matched, if either did match. */ + + if (var1->level_matched > var2->level_matched) { + return 1; + } + if (var1->level_matched < var2->level_matched) { + return -1; + } + + /* Neither matched. Take lowest level, if there's a difference. */ + + if (var1->level < var2->level) { + return 1; + } + if (var1->level > var2->level) { + return -1; + } + + /* Tied */ + + return 0; +} + +/* Finding languages. The main entry point is set_language_quality() + * which is called for each variant. It sets two elements in the + * variant record: + * language_quality - the 'q' value of the 'best' matching language + * from Accept-Language: header (HTTP/1.1) + * lang_index - Pre HTTP/1.1 language priority, using + * position of language on the Accept-Language: + * header, if present, else LanguagePriority + * directive order. + * + * When we do the variant checking for best variant, we use language + * quality first, and if a tie, language_index next (this only + * applies when _not_ using the network algorithm). If using + * network algorithm, lang_index is never used. + * + * set_language_quality() calls find_lang_index() and find_default_index() + * to set lang_index. + */ + +static int find_lang_index(array_header *accept_langs, char *lang) +{ + accept_rec *accs; + int i; + + if (!lang) { + return -1; + } + + accs = (accept_rec *) accept_langs->elts; + + for (i = 0; i < accept_langs->nelts; ++i) { + if (!strncmp(lang, accs[i].type_name, strlen(accs[i].type_name))) { + return i; + } + } + + return -1; +} + +/* This function returns the priority of a given language + * according to LanguagePriority. It is used in case of a tie + * between several languages. + */ + +static int find_default_index(neg_dir_config *conf, char *lang) +{ + array_header *arr; + int nelts; + char **elts; + int i; + + if (!lang) { + return -1; + } + + arr = conf->language_priority; + nelts = arr->nelts; + elts = (char **) arr->elts; + + for (i = 0; i < nelts; ++i) { + if (!strcasecmp(elts[i], lang)) { + return i; + } + } + + return -1; +} + +/* set_default_lang_quality() sets the quality we apply to variants + * which have no language assigned to them. If none of the variants + * have a language, we are not negotiating on language, so all are + * acceptable, and we set the default q value to 1.0. However if + * some of the variants have languages, we set this default to 0.001. + * The value of this default will be applied to all variants with + * no explicit language -- which will have the effect of making them + * acceptable, but only if no variants with an explicit language + * are acceptable. The default q value set here is assigned to variants + * with no language type in set_language_quality(). + * + * Note that if using the transparent negotiation network algorythm, + * we don't use this fiddle. + */ + +static void set_default_lang_quality(negotiation_state *neg) +{ + var_rec *avail_recs = (var_rec *) neg->avail_vars->elts; + int j; + + if (!neg->use_transparent_neg) { + for (j = 0; j < neg->avail_vars->nelts; ++j) { + var_rec *variant = &avail_recs[j]; + if (variant->content_languages && + variant->content_languages->nelts) { + neg->default_lang_quality = 0.001f; + return; + } + } + } + + neg->default_lang_quality = 1.0f; +} + +/* Set the language_quality value in the variant record. Also + * assigns lang_index for back-compat. + * + * To find the language_quality value, we look for the 'q' value + * of the 'best' matching language on the Accept-Language: + * header. The'best' match is the language on Accept-Language: + * header which matches the language of this variant either fully, + * or as far as the prefix marker (-). If two or more languages + * match, use the longest string from the Accept-Language: header + * (see HTTP/1.1 [14.4]) + * + * When a variant has multiple languages, we find the 'best' + * match for each variant language tag as above, then select the + * one with the highest q value. Because both the accept-header + * and variant can have multiple languages, we now have a hairy + * loop-within-a-loop here. + * + * If the variant has no language and we have no Accept-Language + * items, leave the quality at 1.0 and return. + * + * If the variant has no language, we use the default as set by + * set_default_lang_quality() (1.0 if we are not negotiating on + * language, 0.001 if we are). + * + * Following the setting of the language quality, we drop through to + * set the old 'lang_index'. This is set based on either the order + * of the languages on the Accept-Language header, or the + * order on the LanguagePriority directive. This is only used + * in the negotiation if the language qualities tie. + */ + +static void set_language_quality(negotiation_state *neg, var_rec *variant) +{ + int i; + int naccept = neg->accept_langs->nelts; + int idx; + neg_dir_config *conf = NULL; + char *firstlang; + + if (naccept == 0) { + conf = (neg_dir_config *) ap_get_module_config(neg->r->per_dir_config, + &negotiation_module); + } + + if (naccept == 0 && (!variant->content_languages || + !variant->content_languages->nelts)) { + return; /* no accept-language and no variant lang */ + } + + if (!variant->content_languages || !variant->content_languages->nelts) { + /* This variant has no content-language, so use the default + * quality factor for variants with no content-language + * (previously set by set_default_lang_quality()). */ + variant->lang_quality = neg->default_lang_quality; + + if (naccept == 0) { + return; /* no accept-language items */ + } + + } + else if (naccept) { + /* Variant has one (or more) languages, and we have one (or more) + * language ranges on the Accept-Language header. Look for + * the best match. We do this by going through each language + * on the variant description looking for a match on the + * Accept-Language header. The best match is the longest matching + * language on the header. The final result is the best q value + * from all the languages on the variant description. + */ + int j; + float fiddle_q = 0.0f; + accept_rec *accs = (accept_rec *) neg->accept_langs->elts; + accept_rec *best = NULL, *star = NULL; + char *p; + + for (j = 0; j < variant->content_languages->nelts; ++j) { + char *lang; /* language from variant description */ + accept_rec *bestthistag = NULL; + int prefixlen = 0; + int longest_lang_range_len = 0; + int len; + + /* lang is the variant's language-tag, which is the one + * we are allowed to use the prefix of in HTTP/1.1 + */ + lang = ((char **) (variant->content_languages->elts))[j]; + p = strchr(lang, '-'); /* find prefix part (if any) */ + if (p) { + prefixlen = p - lang; + } + + /* now find the best (i.e. longest) matching Accept-Language + * header language. We put the best match for this tag in + * bestthistag. We cannot update the overall best (based on + * q value) because the best match for this tag is the longest + * language item on the accept header, not necessarily the + * highest q. + */ + for (i = 0; i < neg->accept_langs->nelts; ++i) { + if (!strcmp(accs[i].type_name, "*")) { + if (!star) { + star = &accs[i]; + } + continue; + } + + /* Find language. We match if either the variant language + * tag exactly matches, or the prefix of the tag up to the + * '-' character matches the whole of the language in the + * Accept-Language header. We only use this accept-language + * item as the best match for the current tag if it + * is longer than the previous best match */ + if ((!strcmp(lang, accs[i].type_name) || + (prefixlen && + !strncmp(lang, accs[i].type_name, prefixlen) && + (accs[i].type_name[prefixlen] == '\0'))) && + ((len = strlen(accs[i].type_name)) > + longest_lang_range_len)) { + longest_lang_range_len = len; + bestthistag = &accs[i]; + } + + if (!bestthistag) { + /* The next bit is a fiddle. Some browsers might be + * configured to send more specific language ranges + * than desirable. For example, an Accept-Language of + * en-US should never match variants with languages en + * or en-GB. But US English speakers might pick en-US + * as their language choice. So this fiddle checks if + * the language range has a prefix, and if so, it + * matches variants which match that prefix with a + * priority of 0.001. So a request for en-US would + * match variants of types en and en-GB, but at much + * lower priority than matches of en-US directly, or + * of any other language listed on the Accept-Language + * header + */ + if ((p = strchr(accs[i].type_name, '-'))) { + int plen = p - accs[i].type_name; + if (!strncmp(lang, accs[i].type_name, plen)) { + fiddle_q = 0.001f; + } + } + } + } + /* Finished looking at Accept-Language headers, the best + * (longest) match is in bestthistag, or NULL if no match + */ + if (!best || + (bestthistag && bestthistag->quality > best->quality)) { + best = bestthistag; + } + } + + variant->lang_quality = best + ? best->quality + : (star ? star->quality : fiddle_q); + } + + /* Now set the old lang_index field. Since this is old + * stuff anyway, don't both with handling multiple languages + * per variant, just use the first one assigned to it + */ + idx = 0; + if (variant->content_languages && variant->content_languages->nelts) { + firstlang = ((char **) variant->content_languages->elts)[0]; + } + else { + firstlang = ""; + } + if (naccept == 0) { /* Client doesn't care */ + idx = find_default_index(conf, firstlang); + } + else { /* Client has Accept-Language */ + idx = find_lang_index(neg->accept_langs, firstlang); + } + variant->lang_index = idx; + + return; +} + +/* Determining the content length --- if the map didn't tell us, + * we have to do a stat() and remember for next time. + * + * Grump. For Apache, even the first stat here may well be + * redundant (for multiviews) with a stat() done by the sub_req + * machinery. At some point, that ought to be fixed. + */ + +static float find_content_length(negotiation_state *neg, var_rec *variant) +{ + struct stat statb; + + if (variant->bytes == 0) { + char *fullname = ap_make_full_path(neg->pool, neg->dir_name, + variant->file_name); + + if (stat(fullname, &statb) >= 0) { + /* Note, precision may be lost */ + variant->bytes = (float) statb.st_size; + } + } + + return variant->bytes; +} + +/* For a given variant, find the best matching Accept: header + * and assign the Accept: header's quality value to the + * accept_type_quality field of the variant, for later use in + * determining the best matching variant. + */ + +static void set_accept_quality(negotiation_state *neg, var_rec *variant) +{ + int i; + accept_rec *accept_recs = (accept_rec *) neg->accepts->elts; + float q = 0.0f; + int q_definite = 1; + + /* if no Accept: header, leave quality alone (will + * remain at the default value of 1) */ + if (!neg->accepts || neg->accepts->nelts == 0) { + return; + } + + /* + * Go through each of the ranges on the Accept: header, + * looking for the 'best' match with this variant's + * content-type. We use the best match's quality + * value (from the Accept: header) for this variant's + * accept_type_quality field. + * + * The best match is determined like this: + * type/type is better than type/ * is better than * / * + * if match is type/type, use the level mime param if available + */ + for (i = 0; i < neg->accepts->nelts; ++i) { + + accept_rec *type = &accept_recs[i]; + int prev_mime_stars; + + prev_mime_stars = variant->mime_stars; + + if (!mime_match(type, variant)) { + continue; /* didn't match the content type at all */ + } + else { + /* did match - see if there were less or more stars than + * in previous match + */ + if (prev_mime_stars == variant->mime_stars) { + continue; /* more stars => not as good a match */ + } + } + + /* Check maxbytes -- not in HTTP/1.1 or Holtman */ + + if (type->max_bytes > 0 + && (find_content_length(neg, variant) > type->max_bytes)) { + continue; + } + + /* If we are allowed to mess with the q-values, + * make wildcards very low, so we have a low chance + * of ending up with them if there's something better. + */ + + if (!neg->accept_q && variant->mime_stars == 1) { + q = 0.01f; + } + else if (!neg->accept_q && variant->mime_stars == 2) { + q = 0.02f; + } + else { + q = type->quality; + } + + q_definite = (variant->mime_stars == 3); + } + variant->accept_type_quality = q; + variant->definite = variant->definite && q_definite; + + /* if the _best_ quality we got for this variant was 0.0, + * eliminate it now */ +} + +/* For a given variant, find the 'q' value of the charset given + * on the Accept-Charset line. If not charsets are listed, + * assume value of '1'. + */ + +static void set_charset_quality(negotiation_state *neg, var_rec *variant) +{ + int i; + accept_rec *accept_recs = (accept_rec *) neg->accept_charsets->elts; + char *charset = variant->content_charset; + accept_rec *star = NULL; + + /* if no Accept-Charset: header, leave quality alone (will + * remain at the default value of 1) */ + if (!neg->accept_charsets || neg->accept_charsets->nelts == 0) { + return; + } + + if (charset == NULL || !*charset) { + charset = "iso-8859-1"; + } + + /* + * Go through each of the items on the Accept-Charset: header, + * looking for a match with this variant's charset. If none + * match, charset is unacceptable, so set quality to 0. + */ + for (i = 0; i < neg->accept_charsets->nelts; ++i) { + + accept_rec *type = &accept_recs[i]; + + if (!strcmp(type->type_name, charset)) { + variant->charset_quality = type->quality; + return; + } + else if (strcmp(type->type_name, "*") == 0) { + star = type; + } + } + /* No explicit match */ + if (star) { + variant->charset_quality = star->quality; + return; + } + /* If this variant is in charset iso-8859-1, the default is 1.0 */ + if (strcmp(charset, "iso-8859-1") == 0) { + variant->charset_quality = 1.0f; + } + else { + variant->charset_quality = 0.0f; + } +} + +/* For a given variant, find the best matching Accept: header + * and assign the Accept: header's quality value to the + * accept_type_quality field of the variant, for later use in + * determining the best matching variant. + */ + +/* is_identity_encoding is included for back-compat, but does anyone + * use 7bit, 8bin or binary in their var files?? + */ + +static int is_identity_encoding(char *enc) +{ + return (!enc || !enc[0] || !strcmp(enc, "7bit") || !strcmp(enc, "8bit") + || !strcmp(enc, "binary")); +} + +static void set_encoding_quality(negotiation_state *neg, var_rec *variant) +{ + int i; + accept_rec *accept_recs = (accept_rec *) neg->accept_encodings->elts; + char *enc = variant->content_encoding; + + if (!enc || is_identity_encoding(enc)) { + return; + } + + /* if no Accept: header, leave quality alone (will + * remain at the default value of 1) */ + if (neg->accept_encodings->nelts == 0) { + /* If we had an empty Accept-Encoding header, assume that + * no encodings are acceptable, else all encodings are ok */ + variant->encoding_quality = neg->have_accept_header ? 0 : 1; + return; + } + + /* Go through each of the encodings on the Accept-Encoding: header, + * looking for a match with our encoding. x- prefixes are ignored. + */ + if (enc[0] == 'x' && enc[1] == '-') { + enc += 2; + } + for (i = 0; i < neg->accept_encodings->nelts; ++i) { + char *name = accept_recs[i].type_name; + + if (name[0] == 'x' && name[1] == '-') { + name += 2; + } + + if (!strcmp(name, enc)) { + variant->encoding_quality = 1; + return; + } + } + + /* Encoding not found on Accept-Encoding: header, so it is + * _not_ acceptable */ + variant->encoding_quality = 0; +} + +/* Possible results of the network algorithm */ +enum algorithm_results { + na_not_applied = -1, /* net algorithm not used */ + na_choice = 1, /* choose variant */ + na_list /* list variants */ +}; + +/* + * This is a heavily-rewritten 'best_match' function. For a start, it + * now returns an int, which has one of the three values: na_not_applied, + * na_choice or na_list, which give the result of the network algorithm + * (if it was not applied, the return value is na_not_applied). + * The best variable is returned in *pbest. It also has two possible + * algorithms for determining the best match: the network algorithm, + * and the standard Apache algorithm. These are split out into + * separate functions (is_variant_better_na() and is_variant_better()). + * + * Previously, best_match iterated first through the content_types + * in the Accept: header, then checked each variant, and eliminated + * those that didn't match the variant's type. We cannot do this because + * we need full information, including language, charset, etc + * quality for _every_ variant, for the Alternates: header, + * and (possibly) the human-readable choice responses or 406 errors. + * + * After the 'best' (if any) is determined, the overall result of + * the negotiation is obtained. If the network algorithm was not + * in use, the result is na_not_applied. Else the result is + * na_list if 'short accept header' is in use, else na_list + * if _no_ best match was found, or na_choice if a best match + * was found. + */ + +/* Firstly, the negotiation 'network algorithm' from Holtman. + */ + +static int is_variant_better_na(negotiation_state *neg, var_rec *variant, + var_rec *best, float *p_bestq) +{ + float bestq = *p_bestq, q; + + /* Note: Encoding is not negotiated in the Holtman + * transparent neg draft, so we ignored it here. But + * it does mean we could return encodings the UA + * or proxy cannot handle. Eek. */ + + q = variant->accept_type_quality * + variant->type_quality * + variant->charset_quality * + variant->lang_quality; + +#ifdef NEG_DEBUG + fprintf(stderr, "Variant: file=%s type=%s lang=%s acceptq=%1.3f " + "langq=%1.3f typeq=%1.3f q=%1.3f definite=%d\n", + (variant->file_name ? variant->file_name : ""), + (variant->type_name ? variant->type_name : ""), + (variant->content_languages + ? merge_string_array(neg->pool, variant->content_languages, ",") + : ""), + variant->accept_type_quality, + variant->lang_quality, + variant->type_quality, + q, + variant->definite); +#endif + + if (q > bestq) { + *p_bestq = q; + return 1; + } + if (q == bestq) { + /* If the best variant's charset is ISO-8859-1 and this variant has + * the same charset quality, then we prefer this variant + */ + if (variant->charset_quality == best->charset_quality && + (variant->content_charset != NULL && + *variant->content_charset != '\0' && + strcmp(variant->content_charset, "iso-8859-1") != 0) && + (best->content_charset == NULL || + *best->content_charset == '\0' || + strcmp(best->content_charset, "iso-8859-1") == 0)) { + *p_bestq = q; + return 1; + } + } + return 0; +} + +/* Negotiation algorithm as used by previous versions of Apache + * (just about). + */ + +static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec *best, float *p_bestq) +{ + float bestq = *p_bestq, q; + int levcmp; + + /* + * For non-transparent negotiation, server can choose how + * to handle the negotiation. We'll use the following in + * order: content-type, language, content-type level, charset, + * content length. + * + * For each check, we have three possible outcomes: + * This variant is worse than current best: return 0 + * This variant is better than the current best: + * assign this variant's q to *p_bestq, and return 1 + * This variant is just as desirable as the current best: + * drop through to the next test. + * + * This code is written in this long-winded way to allow future + * customisation, either by the addition of additional + * checks, or to allow the order of the checks to be determined + * by configuration options (e.g. we might prefer to check + * language quality _before_ content type). + */ + + /* First though, eliminate this variant if it is not + * acceptable by type, charset, encoding or language. + */ + + if (variant->encoding_quality == 0 || + variant->lang_quality == 0 || + variant->type_quality == 0 || + variant->charset_quality == 0 || + variant->accept_type_quality == 0) { + return 0; /* don't consider unacceptables */ + } + + q = variant->accept_type_quality * variant->type_quality; + if (q == 0.0 || q < bestq) { + return 0; + } + if (q > bestq || !best) { + *p_bestq = q; + return 1; + } + + /* language */ + if (variant->lang_quality < best->lang_quality) { + return 0; + } + if (variant->lang_quality > best->lang_quality) { + *p_bestq = q; + return 1; + } + + /* if language qualities were equal, try the LanguagePriority + * stuff */ + if (best->lang_index != -1 && variant->lang_index > best->lang_index) { + return 0; + } + if (variant->lang_index != -1 && + (variant->lang_index < best->lang_index || best->lang_index == -1)) { + *p_bestq = q; + return 1; + } + + /* content-type level (text/html only?) */ + levcmp = level_cmp(variant, best); + if (levcmp == -1) { + return 0; + } + if (levcmp == 1) { + *p_bestq = q; + return 1; + } + + /* encoding -- can only be 1 or 0, and if 0 we eliminated this + * variant at the start of this function. However we + * prefer variants with no encoding over those with encoding */ + if (best->content_encoding == NULL && variant->content_encoding) { + return 0; + } + if (best->content_encoding && variant->content_encoding == NULL) { + *p_bestq = q; + return 1; + } + + /* charset */ + if (variant->charset_quality < best->charset_quality) { + return 0; + } + /* If the best variant's charset is ISO-8859-1 and this variant has + * the same charset quality, then we prefer this variant + */ + if (variant->charset_quality > best->charset_quality || + ((variant->content_charset != NULL && + *variant->content_charset != '\0' && + strcmp(variant->content_charset, "iso-8859-1") != 0) && + (best->content_charset == NULL || + *best->content_charset == '\0' || + strcmp(best->content_charset, "iso-8859-1") == 0))) { + *p_bestq = q; + return 1; + } + + + /* content length if all else equal */ + if (find_content_length(neg, variant) >= find_content_length(neg, best)) { + return 0; + } + + /* ok, to get here means every thing turned out equal, except + * we have a shorter content length, so use this variant */ + *p_bestq = q; + return 1; +} + +static int best_match(negotiation_state *neg, var_rec **pbest) +{ + int j; + var_rec *best = NULL; + float bestq = 0.0f; + enum algorithm_results algorithm_result = na_not_applied; + + var_rec *avail_recs = (var_rec *) neg->avail_vars->elts; + + set_default_lang_quality(neg); + + /* + * Find the 'best' variant + */ + + for (j = 0; j < neg->avail_vars->nelts; ++j) { + var_rec *variant = &avail_recs[j]; + + /* Find all the relevant 'quality' values from the + * Accept... headers, and store in the variant + */ + set_accept_quality(neg, variant); + set_language_quality(neg, variant); + set_encoding_quality(neg, variant); + set_charset_quality(neg, variant); + + /* Now find out if this variant is better than the current + * best, either using the network algorithm, or Apache's + * internal server-driven algorithm. Presumably other + * server-driven algorithms are possible, and could be + * implemented here. + */ + + if (neg->use_transparent_neg) { + if (is_variant_better_na(neg, variant, best, &bestq)) { + best = variant; + } + } + else { + if (is_variant_better(neg, variant, best, &bestq)) { + best = variant; + } + } + } + + /* We now either have a best variant, or no best variant + */ + if (neg->use_transparent_neg) { + if (neg->short_accept_headers) { + algorithm_result = na_list; + } + else { + /* From Holtman, result is: + * If variant & URI are not neigbors, list_ua or list_os + * Else + * If UA can do trans neg + * IF best is definite && best q > 0, choice_ua + * ELSE list_ua + * ELSE + * IF best q > 0, choose_os + * ELSE list_os (or forward_os on proxy) + */ + + /* assume variant and URI are neigbors (since URI in + * var map must be in same directory) */ + + if (neg->use_transparent_neg) { + algorithm_result = (best && best->definite) && (bestq > 0) + ? na_choice : na_list; + } + else { + algorithm_result = bestq > 0 ? na_choice : na_list; + } + } + } + + *pbest = best; + return algorithm_result; +} + +/* + * Sets the Alternates and Vary headers, used if we are going to + * return 406 Not Acceptable status, a 300 Multiple Choice status, + * or a Choice response. + * + * 'type' is the result of the network algorithm, if applied. + * We do different things if the network algorithm was not applied + * (type == na_not_applied): no Alternates header, and Vary: + * does not include 'negotiate'. + * + * We should also add a max-age lifetime for the Alternates header, + * but how long we we give it? Presumably this should be + * configurable in the map file. + */ + +static void set_neg_headers(request_rec *r, negotiation_state *neg, + int na_result) +{ + int j; + var_rec *avail_recs = (var_rec *) neg->avail_vars->elts; + char *sample_type = NULL; + char *sample_language = NULL; + char *sample_encoding = NULL; + char *sample_charset = NULL; + int vary_by_type = 0; + int vary_by_language = 0; + int vary_by_charset = 0; + int vary_by_encoding = 0; + table *hdrs; + + /* Put headers into err_headers_out, new send_http_header() + * outputs both headers_out and err_headers_out */ + hdrs = r->err_headers_out; + + for (j = 0; j < neg->avail_vars->nelts; ++j) { + var_rec *variant = &avail_recs[j]; + char *rec; + char qstr[6]; + long len; + char lenstr[22]; /* enough for 2^64 */ + + ap_snprintf(qstr, sizeof(qstr), "%1.3f", variant->type_quality); + + /* Strip trailing zeros (saves those valuable network bytes) */ + if (qstr[4] == '0') { + qstr[4] = '\0'; + if (qstr[3] == '0') { + qstr[3] = '\0'; + if (qstr[2] == '0') { + qstr[1] = '\0'; + } + } + } + + rec = ap_pstrcat(r->pool, "{\"", variant->file_name, "\" ", qstr, NULL); + if (variant->type_name) { + if (*variant->type_name) { + rec = ap_pstrcat(r->pool, rec, " {type ", + variant->type_name, "}", NULL); + } + if (!sample_type) { + sample_type = variant->type_name; + } + else if (strcmp(sample_type, variant->type_name)) { + vary_by_type = 1; + } + } + if (variant->content_languages && variant->content_languages->nelts) { + char *langs = merge_string_array(r->pool, + variant->content_languages, ","); + rec = ap_pstrcat(r->pool, rec, " {language ", langs, "}", NULL); + if (!sample_language) { + sample_language = langs; + } + else if (strcmp(sample_language, langs)) { + vary_by_language = 1; + } + } + if (variant->content_encoding) { + if (!sample_encoding) { + sample_encoding = variant->content_encoding; + } + else if (strcmp(sample_encoding, variant->content_encoding)) { + vary_by_encoding = 1; + } + } + if (variant->content_charset) { + if (*variant->content_charset) { + rec = ap_pstrcat(r->pool, rec, " {charset ", + variant->content_charset, "}", NULL); + } + if (!sample_charset) { + sample_charset = variant->content_charset; + } + else if (strcmp(sample_charset, variant->content_charset)) { + vary_by_charset = 1; + } + } + if ((len = find_content_length(neg, variant)) != 0) { + ap_snprintf(lenstr, sizeof(lenstr), "%ld", len); + rec = ap_pstrcat(r->pool, rec, " {length ", lenstr, "}", NULL); + } + + rec = ap_pstrcat(r->pool, rec, "}", NULL); + + if (na_result != na_not_applied) { + ap_table_mergen(hdrs, "Alternates", rec); + } + } + + if (na_result != na_not_applied) { + ap_table_mergen(hdrs, "Vary", "negotiate"); + } + if (vary_by_type) { + ap_table_mergen(hdrs, "Vary", "accept"); + } + if (vary_by_language) { + ap_table_mergen(hdrs, "Vary", "accept-language"); + } + if (vary_by_charset) { + ap_table_mergen(hdrs, "Vary", "accept-charset"); + } + if (vary_by_encoding && na_result == na_not_applied) { + ap_table_mergen(hdrs, "Vary", "accept-encoding"); + } +} + +/********************************************************************** + * + * Return an HTML list of variants. This is output as part of the + * 300 or 406 status body. + */ + +/* XXX: this is disgusting, this has O(n^2) behaviour! -djg */ +static char *make_variant_list(request_rec *r, negotiation_state *neg) +{ + int i; + char *t; + + t = ap_pstrdup(r->pool, "Available variants:\n<ul>\n"); + for (i = 0; i < neg->avail_vars->nelts; ++i) { + var_rec *variant = &((var_rec *) neg->avail_vars->elts)[i]; + char *filename = variant->file_name ? variant->file_name : ""; + array_header *languages = variant->content_languages; + char *description = variant->description ? variant->description : ""; + + /* The format isn't very neat, and it would be nice to make + * the tags human readable (eg replace 'language en' with + * 'English'). */ + t = ap_pstrcat(r->pool, t, "<li><a href=\"", filename, "\">", + filename, "</a> ", description, NULL); + if (variant->type_name && *variant->type_name) { + t = ap_pstrcat(r->pool, t, ", type ", variant->type_name, NULL); + } + if (languages && languages->nelts) { + t = ap_pstrcat(r->pool, t, ", language ", + merge_string_array(r->pool, languages, ", "), + NULL); + } + if (variant->content_charset && *variant->content_charset) { + t = ap_pstrcat(r->pool, t, ", charset ", variant->content_charset, + NULL); + } + t = ap_pstrcat(r->pool, t, "\n", NULL); + } + t = ap_pstrcat(r->pool, t, "</ul>\n", NULL); + + return t; +} + +static void store_variant_list(request_rec *r, negotiation_state *neg) +{ + if (r->main == NULL) { + ap_table_setn(r->notes, "variant-list", make_variant_list(r, neg)); + } + else { + ap_table_setn(r->main->notes, "variant-list", + make_variant_list(r->main, neg)); + } +} + +/* Called if we got a "Choice" response from the network algorithm. + * It checks the result of the chosen variant to see if it + * is itself negotiated (if so, return error VARIANT_ALSO_VARIES). + * Otherwise, add the appropriate headers to the current response. + */ + +static int setup_choice_response(request_rec *r, negotiation_state *neg, var_rec *variant) +{ + request_rec *sub_req; + char *sub_vary; + + if (!variant->sub_req) { + int status; + + sub_req = ap_sub_req_lookup_file(variant->file_name, r); + status = sub_req->status; + if (status != HTTP_OK && status != HTTP_MULTIPLE_CHOICES) { + ap_destroy_sub_req(sub_req); + return status; + } + variant->sub_req = sub_req; + } + else { + sub_req = variant->sub_req; + } + + /* The network algorithm told us to return a "Choice" + * response. This is the normal variant response, with + * some extra headers. First, ensure that the chosen + * variant did not itself return a "List" or "Choice" response. + * If not, set the appropriate headers, and fall through to + * the normal variant handling + */ + + if ((sub_req->status == HTTP_MULTIPLE_CHOICES) || + (ap_table_get(sub_req->err_headers_out, "Alternates")) || + (ap_table_get(sub_req->err_headers_out, "Content-Location"))) { + return VARIANT_ALSO_VARIES; + } + + if ((sub_vary = ap_table_get(sub_req->err_headers_out, "Vary")) != NULL) { + ap_table_setn(r->err_headers_out, "Variant-Vary", sub_vary); + } + ap_table_setn(r->err_headers_out, "Content-Location", + ap_pstrdup(r->pool, variant->file_name)); + set_neg_headers(r, neg, na_choice); /* add Alternates and Vary */ + /* to do: add Expires */ + + return 0; +} + +/**************************************************************** + * + * Executive... + */ + +static int handle_map_file(request_rec *r) +{ + negotiation_state *neg = parse_accept_headers(r); + var_rec *best; + int res; + int na_result; + + char *udir; + + if ((res = read_type_map(neg, r))) { + return res; + } + + maybe_add_default_encodings(neg, 0); + + na_result = best_match(neg, &best); + + /* na_result is one of + * na_not_applied: we didn't use the network algorithm + * na_choice: return a "Choice" response + * na_list: return a "List" response (no variant chosen) + */ + + if (na_result == na_list) { + set_neg_headers(r, neg, na_list); + store_variant_list(r, neg); + return MULTIPLE_CHOICES; + } + + if (!best) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "no acceptable variant: %s", r->filename); + + set_neg_headers(r, neg, na_result); + store_variant_list(r, neg); + return NOT_ACCEPTABLE; + } + + if (na_result == na_choice) { + if ((res = setup_choice_response(r, neg, best)) != 0) { + return res; + } + } + + /* Make sure caching works - Vary should handle HTTP/1.1, but for + * HTTP/1.0, we can't allow caching at all. NB that we merge the + * header in case some other module negotiates on something else. + */ + if (!do_cache_negotiated_docs(r->server) && (r->proto_num < HTTP_VERSION(1,1))) { + r->no_cache = 1; + } + + if (na_result == na_not_applied) { + set_neg_headers(r, neg, na_not_applied); + } + + if (r->path_info && *r->path_info) { + r->uri[ap_find_path_info(r->uri, r->path_info)] = '\0'; + } + udir = ap_make_dirstr_parent(r->pool, r->uri); + udir = escape_uri(r->pool, udir); + ap_internal_redirect(ap_pstrcat(r->pool, udir, best->file_name, r->path_info, + NULL), r); + return OK; +} + +static int handle_multi(request_rec *r) +{ + negotiation_state *neg; + var_rec *best, *avail_recs; + request_rec *sub_req; + int res; + int j; + int na_result; /* result of network algorithm */ + + if (r->finfo.st_mode != 0 || !(ap_allow_options(r) & OPT_MULTI)) { + return DECLINED; + } + + neg = parse_accept_headers(r); + + if ((res = read_types_multi(neg))) { + return_from_multi: + /* free all allocated memory from subrequests */ + avail_recs = (var_rec *) neg->avail_vars->elts; + for (j = 0; j < neg->avail_vars->nelts; ++j) { + var_rec *variant = &avail_recs[j]; + if (variant->sub_req) { + ap_destroy_sub_req(variant->sub_req); + } + } + return res; + } + if (neg->avail_vars->nelts == 0) { + return DECLINED; + } + + maybe_add_default_encodings(neg, + (r->method_number != M_GET) || + r->args || r->path_info); + + na_result = best_match(neg, &best); + if (na_result == na_list) { + /* + * Network algorithm tols us to output a "List" response. + * This is output at a 300 status code, which we will + * return. The list of variants will be stored in r->notes + * under the name "variants-list". + */ + set_neg_headers(r, neg, na_list); /* set Alternates: and Vary: */ + + store_variant_list(r, neg); + res = MULTIPLE_CHOICES; + goto return_from_multi; + } + + if (!best) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "no acceptable variant: %s", r->filename); + + set_neg_headers(r, neg, na_result); + store_variant_list(r, neg); + res = NOT_ACCEPTABLE; + goto return_from_multi; + } + + if (na_result == na_choice) { + if ((res = setup_choice_response(r, neg, best)) != 0) { + goto return_from_multi; + } + } + + if (!(sub_req = best->sub_req)) { + /* We got this out of a map file, so we don't actually have + * a sub_req structure yet. Get one now. + */ + + sub_req = ap_sub_req_lookup_file(best->file_name, r); + if (sub_req->status != HTTP_OK) { + res = sub_req->status; + ap_destroy_sub_req(sub_req); + goto return_from_multi; + } + } + + /* BLETCH --- don't multi-resolve non-ordinary files */ + + if (!S_ISREG(sub_req->finfo.st_mode)) { + res = NOT_FOUND; + goto return_from_multi; + } + + /* Otherwise, use it. */ + + if ((!do_cache_negotiated_docs(r->server) && (r->proto_num < HTTP_VERSION(1,1))) + && neg->count_multiviews_variants != 1) { + r->no_cache = 1; + } + + if (na_result == na_not_applied) { + set_neg_headers(r, neg, na_not_applied); + } + + /* now do a "fast redirect" ... promote the sub_req into the main req */ + /* We need to tell POOL_DEBUG that we're guaranteeing that sub_req->pool + * will exist as long as r->pool. Otherwise we run into troubles because + * some values in this request will be allocated in r->pool, and others in + * sub_req->pool. + */ + ap_pool_join(r->pool, sub_req->pool); + r->filename = sub_req->filename; + r->handler = sub_req->handler; + r->content_type = sub_req->content_type; + r->content_encoding = sub_req->content_encoding; + r->content_languages = sub_req->content_languages; + r->content_language = sub_req->content_language; + r->finfo = sub_req->finfo; + r->per_dir_config = sub_req->per_dir_config; + /* copy output headers from subrequest, but leave negotiation headers */ + r->notes = ap_overlay_tables(r->pool, sub_req->notes, r->notes); + r->headers_out = ap_overlay_tables(r->pool, sub_req->headers_out, + r->headers_out); + r->err_headers_out = ap_overlay_tables(r->pool, sub_req->err_headers_out, + r->err_headers_out); + r->subprocess_env = ap_overlay_tables(r->pool, sub_req->subprocess_env, + r->subprocess_env); + avail_recs = (var_rec *) neg->avail_vars->elts; + for (j = 0; j < neg->avail_vars->nelts; ++j) { + var_rec *variant = &avail_recs[j]; + if (variant != best && variant->sub_req) { + ap_destroy_sub_req(variant->sub_req); + } + } + return OK; +} + +/* There is a problem with content-encoding, as some clients send and + * expect an x- token (e.g. x-gzip) while others expect the plain token + * (i.e. gzip). To try and deal with this as best as possible we do + * the following: if the client sent an Accept-Encoding header and it + * contains a plain token corresponding to the content encoding of the + * response, then set content encoding using the plain token. Else if + * the A-E header contains the x- token use the x- token in the C-E + * header. Else don't do anything. + * + * Note that if no A-E header was sent, or it does not contain a token + * compatible with the final content encoding, then the token in the + * C-E header will be whatever was specified in the AddEncoding + * directive. + */ +static int fix_encoding(request_rec *r) +{ + char *enc = r->content_encoding; + char *x_enc = NULL; + array_header *accept_encodings; + accept_rec *accept_recs; + int i; + + if (!enc || !*enc) { + return DECLINED; + } + + if (enc[0] == 'x' && enc[1] == '-') { + enc += 2; + } + + accept_encodings = do_header_line(r->pool, + ap_table_get(r->headers_in, "Accept-encoding")); + accept_recs = (accept_rec *) accept_encodings->elts; + + for (i = 0; i < accept_encodings->nelts; ++i) { + char *name = accept_recs[i].type_name; + + if (!strcmp(name, enc)) { + r->content_encoding = name; + return OK; + } + + if (name[0] == 'x' && name[1] == '-' && !strcmp(name+2, enc)) { + x_enc = name; + } + } + + if (x_enc) { + r->content_encoding = x_enc; + return OK; + } + + return DECLINED; +} + +static const handler_rec negotiation_handlers[] = +{ + {MAP_FILE_MAGIC_TYPE, handle_map_file}, + {"type-map", handle_map_file}, + {NULL} +}; + +module MODULE_VAR_EXPORT negotiation_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + create_neg_dir_config, /* dir config creater */ + merge_neg_dir_configs, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + negotiation_cmds, /* command table */ + negotiation_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + handle_multi, /* type_checker */ + fix_encoding, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_rewrite.c b/APACHE_1_3b7/src/modules/standard/mod_rewrite.c new file mode 100644 index 0000000000..6dfcc3f806 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_rewrite.c @@ -0,0 +1,3923 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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/>. + * + */ + + +/* _ _ _ +** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___ +** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \ +** | | | | | | (_) | (_| | | | | __/\ V V /| | | | || __/ +** |_| |_| |_|\___/ \__,_|___|_| \___| \_/\_/ |_| |_|\__\___| +** |_____| +** +** URL Rewriting Module +** +** This module uses a rule-based rewriting engine (based on a +** regular-expression parser) to rewrite requested URLs on the fly. +** +** It supports an unlimited number of additional rule conditions (which can +** operate on a lot of variables, even on HTTP headers) for granular +** matching and even external database lookups (either via plain text +** tables, DBM hash files or even external processes) for advanced URL +** substitution. +** +** It operates on the full URLs (including the PATH_INFO part) both in +** per-server context (httpd.conf) and per-dir context (.htaccess) and even +** can generate QUERY_STRING parts on result. The rewriting result finally +** can lead to internal subprocessing, external request redirection or even +** to internal proxy throughput. +** +** This module was originally written in April 1996 and +** gifted exclusively to the The Apache Group in July 1997 by +** +** Ralf S. Engelschall +** rse@engelschall.com +** www.engelschall.com +*/ + + +#include "mod_rewrite.h" + + +/* +** +-------------------------------------------------------+ +** | | +** | static module configuration +** | | +** +-------------------------------------------------------+ +*/ + + +/* +** Our interface to the Apache server kernel: +** +** o Runtime logic of a request is as following: +** while(request or subrequest) +** foreach(stage #0...#9) +** foreach(module) (**) +** try to run hook +** +** o the order of modules at (**) is the inverted order as +** given in the "Configuration" file, i.e. the last module +** specified is the first one called for each hook! +** The core module is always the last! +** +** o there are two different types of result checking and +** continue processing: +** for hook #0,#1,#4,#5,#6,#8: +** hook run loop stops on first modules which gives +** back a result != DECLINED, i.e. it usually returns OK +** which says "OK, module has handled this _stage_" and for #1 +** this have not to mean "Ok, the filename is now valid". +** for hook #2,#3,#7,#9: +** all hooks are run, independend of result +** +** o at the last stage, the core module always +** - says "BAD_REQUEST" if r->filename does not begin with "/" +** - prefix URL with document_root or replaced server_root +** with document_root and sets r->filename +** - always return a "OK" independed if the file really exists +** or not! +*/ + + /* The section for the Configure script: + * MODULE-DEFINITION-START + * Name: rewrite_module + * ConfigStart + . ./helpers/find-dbm-lib + if [ "x$found_dbm" = "x1" ]; then + echo " enabling DBM support for mod_rewrite" + else + echo " disabling DBM support for mod_rewrite" + echo " (perhaps you need to add -ldbm, -lndbm or -lgdbm to EXTRA_LIBS)" + CFLAGS="$CFLAGS -DNO_DBM_REWRITEMAP" + fi + * ConfigEnd + * MODULE-DEFINITION-END + */ + + /* the table of commands we provide */ +static const command_rec command_table[] = { + { "RewriteEngine", cmd_rewriteengine, NULL, OR_FILEINFO, FLAG, + "On or Off to enable or disable (default) the whole rewriting engine" }, + { "RewriteOptions", cmd_rewriteoptions, NULL, OR_FILEINFO, ITERATE, + "List of option strings to set" }, + { "RewriteBase", cmd_rewritebase, NULL, OR_FILEINFO, TAKE1, + "the base URL of the per-directory context" }, + { "RewriteCond", cmd_rewritecond, NULL, OR_FILEINFO, RAW_ARGS, + "a input string and a to be applied regexp-pattern" }, + { "RewriteRule", cmd_rewriterule, NULL, OR_FILEINFO, RAW_ARGS, + "a URL-applied regexp-pattern and a substitution URL" }, + { "RewriteMap", cmd_rewritemap, NULL, RSRC_CONF, TAKE2, + "a mapname and a filename" }, + { "RewriteLock", cmd_rewritelock, NULL, RSRC_CONF, TAKE1, + "the filename of a lockfile used for inter-process synchronization"}, + { "RewriteLog", cmd_rewritelog, NULL, RSRC_CONF, TAKE1, + "the filename of the rewriting logfile" }, + { "RewriteLogLevel", cmd_rewriteloglevel, NULL, RSRC_CONF, TAKE1, + "the level of the rewriting logfile verbosity " + "(0=none, 1=std, .., 9=max)" }, + { NULL } +}; + + /* the table of content handlers we provide */ +static const handler_rec handler_table[] = { + { "redirect-handler", handler_redirect }, + { NULL } +}; + + /* the main config structure */ +module MODULE_VAR_EXPORT rewrite_module = { + STANDARD_MODULE_STUFF, + init_module, /* module initializer */ + config_perdir_create, /* create per-dir config structures */ + config_perdir_merge, /* merge per-dir config structures */ + config_server_create, /* create per-server config structures */ + config_server_merge, /* merge per-server config structures */ + command_table, /* table of config file commands */ + handler_table, /* [#8] MIME-typed-dispatched handlers */ + hook_uri2file, /* [#1] URI to filename translation */ + NULL, /* [#4] validate user id from request */ + NULL, /* [#5] check if the user is ok _here_ */ + NULL, /* [#2] check access by host address */ + hook_mimetype, /* [#6] determine MIME type */ + hook_fixup, /* [#7] pre-run fixups */ + NULL, /* [#9] log a transaction */ + NULL, /* [#3] header parser */ + init_child, /* child_init */ + NULL, /* child_exit */ + NULL /* [#0] post read-request */ +}; + + /* the cache */ +static cache *cachep; + + /* whether proxy module is available or not */ +static int proxy_available; + + /* the txt mapfile parsing stuff */ +static regex_t *lookup_map_txtfile_regexp = NULL; +static regmatch_t lookup_map_txtfile_regmatch[MAX_NMATCH]; + + +/* +** +-------------------------------------------------------+ +** | | +** | configuration directive handling +** | | +** +-------------------------------------------------------+ +*/ + +/* +** +** per-server configuration structure handling +** +*/ + +static void *config_server_create(pool *p, server_rec *s) +{ + rewrite_server_conf *a; + + a = (rewrite_server_conf *)ap_pcalloc(p, sizeof(rewrite_server_conf)); + + a->state = ENGINE_DISABLED; + a->options = OPTION_NONE; + a->rewritelogfile = NULL; + a->rewritelogfp = -1; + a->rewriteloglevel = 0; + a->rewritelockfile = NULL; + a->rewritelockfp = -1; + a->rewritemaps = ap_make_array(p, 2, sizeof(rewritemap_entry)); + a->rewriteconds = ap_make_array(p, 2, sizeof(rewritecond_entry)); + a->rewriterules = ap_make_array(p, 2, sizeof(rewriterule_entry)); + a->server = s; + + return (void *)a; +} + +static void *config_server_merge(pool *p, void *basev, void *overridesv) +{ + rewrite_server_conf *a, *base, *overrides; + + a = (rewrite_server_conf *)ap_pcalloc(p, sizeof(rewrite_server_conf)); + base = (rewrite_server_conf *)basev; + overrides = (rewrite_server_conf *)overridesv; + + a->state = overrides->state; + a->options = overrides->options; + a->server = overrides->server; + + if (a->options & OPTION_INHERIT) { + /* + * local directives override + * and anything else is inherited + */ + a->rewriteloglevel = overrides->rewriteloglevel != 0 ? + overrides->rewriteloglevel : base->rewriteloglevel; + a->rewritelogfile = overrides->rewritelogfile != NULL ? + overrides->rewritelogfile : base->rewritelogfile; + a->rewritelogfp = overrides->rewritelogfp != -1 ? + overrides->rewritelogfp : base->rewritelogfp; + a->rewritelockfile = overrides->rewritelockfile != NULL ? + overrides->rewritelockfile : base->rewritelockfile; + a->rewritelockfp = overrides->rewritelockfp != -1 ? + overrides->rewritelockfp : base->rewritelockfp; + a->rewritemaps = ap_append_arrays(p, overrides->rewritemaps, + base->rewritemaps); + a->rewriteconds = ap_append_arrays(p, overrides->rewriteconds, + base->rewriteconds); + a->rewriterules = ap_append_arrays(p, overrides->rewriterules, + base->rewriterules); + } + else { + /* + * local directives override + * and anything else gets defaults + */ + a->rewriteloglevel = overrides->rewriteloglevel; + a->rewritelogfile = overrides->rewritelogfile; + a->rewritelogfp = overrides->rewritelogfp; + a->rewritelockfile = overrides->rewritelockfile; + a->rewritelockfp = overrides->rewritelockfp; + a->rewritemaps = overrides->rewritemaps; + a->rewriteconds = overrides->rewriteconds; + a->rewriterules = overrides->rewriterules; + } + + return (void *)a; +} + + +/* +** +** per-directory configuration structure handling +** +*/ + +static void *config_perdir_create(pool *p, char *path) +{ + rewrite_perdir_conf *a; + + a = (rewrite_perdir_conf *)ap_pcalloc(p, sizeof(rewrite_perdir_conf)); + + a->state = ENGINE_DISABLED; + a->options = OPTION_NONE; + a->baseurl = NULL; + a->rewriteconds = ap_make_array(p, 2, sizeof(rewritecond_entry)); + a->rewriterules = ap_make_array(p, 2, sizeof(rewriterule_entry)); + + if (path == NULL) + a->directory = NULL; + else { + /* make sure it has a trailing slash */ + if (path[strlen(path)-1] == '/') + a->directory = ap_pstrdup(p, path); + else + a->directory = ap_pstrcat(p, path, "/", NULL); + } + + return (void *)a; +} + +static void *config_perdir_merge(pool *p, void *basev, void *overridesv) +{ + rewrite_perdir_conf *a, *base, *overrides; + + a = (rewrite_perdir_conf *)ap_pcalloc(p, sizeof(rewrite_perdir_conf)); + base = (rewrite_perdir_conf *)basev; + overrides = (rewrite_perdir_conf *)overridesv; + + a->state = overrides->state; + a->options = overrides->options; + a->directory = overrides->directory; + a->baseurl = overrides->baseurl; + + if (a->options & OPTION_INHERIT) { + a->rewriteconds = ap_append_arrays(p, overrides->rewriteconds, + base->rewriteconds); + a->rewriterules = ap_append_arrays(p, overrides->rewriterules, + base->rewriterules); + } + else { + a->rewriteconds = overrides->rewriteconds; + a->rewriterules = overrides->rewriterules; + } + + return (void *)a; +} + + +/* +** +** the configuration commands +** +*/ + +static const char *cmd_rewriteengine(cmd_parms *cmd, + rewrite_perdir_conf *dconf, int flag) +{ + rewrite_server_conf *sconf; + + sconf = (rewrite_server_conf *) + ap_get_module_config(cmd->server->module_config, &rewrite_module); + + if (cmd->path == NULL) /* is server command */ + sconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED); + else /* is per-directory command */ + dconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED); + + return NULL; +} + +static const char *cmd_rewriteoptions(cmd_parms *cmd, + rewrite_perdir_conf *dconf, char *option) +{ + rewrite_server_conf *sconf; + const char *err; + + sconf = (rewrite_server_conf *) + ap_get_module_config(cmd->server->module_config, &rewrite_module); + + if (cmd->path == NULL) /* is server command */ + err = cmd_rewriteoptions_setoption(cmd->pool, + &(sconf->options), option); + else /* is per-directory command */ + err = cmd_rewriteoptions_setoption(cmd->pool, + &(dconf->options), option); + + return err; +} + +static const char *cmd_rewriteoptions_setoption(pool *p, int *options, + char *name) +{ + if (strcasecmp(name, "inherit") == 0) + *options |= OPTION_INHERIT; + else + return ap_pstrcat(p, "RewriteOptions: unknown option '", + name, "'\n", NULL); + return NULL; +} + +static const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, char *a1) +{ + rewrite_server_conf *sconf; + + sconf = (rewrite_server_conf *) + ap_get_module_config(cmd->server->module_config, &rewrite_module); + + sconf->rewritelogfile = a1; + + return NULL; +} + +static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1) +{ + rewrite_server_conf *sconf; + + sconf = (rewrite_server_conf *) + ap_get_module_config(cmd->server->module_config, &rewrite_module); + + sconf->rewriteloglevel = atoi(a1); + + return NULL; +} + +static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1, + char *a2) +{ + rewrite_server_conf *sconf; + rewritemap_entry *new; + struct stat st; + + sconf = (rewrite_server_conf *) + ap_get_module_config(cmd->server->module_config, &rewrite_module); + + new = ap_push_array(sconf->rewritemaps); + + new->name = a1; + new->func = NULL; + if (strncmp(a2, "txt:", 4) == 0) { + new->type = MAPTYPE_TXT; + new->datafile = a2+4; + new->checkfile = a2+4; + } + else if (strncmp(a2, "rnd:", 4) == 0) { + new->type = MAPTYPE_RND; + new->datafile = a2+4; + new->checkfile = a2+4; + } + else if (strncmp(a2, "dbm:", 4) == 0) { +#ifndef NO_DBM_REWRITEMAP + new->type = MAPTYPE_DBM; + new->datafile = a2+4; + new->checkfile = ap_pstrcat(cmd->pool, a2+4, NDBM_FILE_SUFFIX, NULL); +#else + return ap_pstrdup(cmd->pool, "RewriteMap: cannot use NDBM mapfile, " + "because no NDBM support is compiled in"); +#endif + } + else if (strncmp(a2, "prg:", 4) == 0) { + new->type = MAPTYPE_PRG; + new->datafile = a2+4; + new->checkfile = a2+4; + } + else if (strncmp(a2, "int:", 4) == 0) { + new->type = MAPTYPE_INT; + new->datafile = NULL; + new->checkfile = NULL; + if (strcmp(a2+4, "tolower") == 0) + new->func = rewrite_mapfunc_tolower; + else if (strcmp(a2+4, "toupper") == 0) + new->func = rewrite_mapfunc_toupper; + else if (sconf->state == ENGINE_ENABLED) + return ap_pstrcat(cmd->pool, "RewriteMap: internal map not found:", + a2+4, NULL); + } + else { + new->type = MAPTYPE_TXT; + new->datafile = a2; + new->checkfile = a2; + } + new->fpin = -1; + new->fpout = -1; + + if (new->checkfile && (sconf->state == ENGINE_ENABLED) + && (stat(new->checkfile, &st) == -1)) + return ap_pstrcat(cmd->pool, "RewriteMap: map file or program not found:", + new->checkfile, NULL); + + return NULL; +} + +static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1) +{ + rewrite_server_conf *sconf; + + sconf = (rewrite_server_conf *) + ap_get_module_config(cmd->server->module_config, &rewrite_module); + + sconf->rewritelockfile = a1; + + return NULL; +} + +static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, + char *a1) +{ + if (cmd->path == NULL || dconf == NULL) + return "RewriteBase: only valid in per-directory config files"; + if (a1[0] == '\0') + return "RewriteBase: empty URL not allowed"; + if (a1[0] != '/') + return "RewriteBase: argument is not a valid URL"; + + dconf->baseurl = a1; + + return NULL; +} + +static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf, + char *str) +{ + rewrite_server_conf *sconf; + rewritecond_entry *new; + regex_t *regexp; + char *a1; + char *a2; + char *a3; + char *cp; + const char *err; + int rc; + + sconf = (rewrite_server_conf *) + ap_get_module_config(cmd->server->module_config, &rewrite_module); + + /* make a new entry in the internal temporary rewrite rule list */ + if (cmd->path == NULL) /* is server command */ + new = ap_push_array(sconf->rewriteconds); + else /* is per-directory command */ + new = ap_push_array(dconf->rewriteconds); + + /* parse the argument line ourself */ + if (parseargline(str, &a1, &a2, &a3)) + return ap_pstrcat(cmd->pool, "RewriteCond: bad argument line '", str, + "'\n", NULL); + + /* arg1: the input string */ + new->input = ap_pstrdup(cmd->pool, a1); + + /* arg3: optional flags field + (this have to be first parsed, because we need to + know if the regex should be compiled with ICASE!) */ + new->flags = CONDFLAG_NONE; + if (a3 != NULL) { + if ((err = cmd_rewritecond_parseflagfield(cmd->pool, new, a3)) != NULL) + return err; + } + + /* arg2: the pattern + try to compile the regexp to test if is ok */ + cp = a2; + if (cp[0] == '!') { + new->flags |= CONDFLAG_NOTMATCH; + cp++; + } + + /* now be careful: Under the POSIX regex library + we can compile the pattern for case-insensitive matching, + under the old V8 library we have to do it self via a hack */ + if (new->flags & CONDFLAG_NOCASE) + rc = ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED|REG_ICASE)) + == NULL); + else + rc = ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED)) == NULL); + if (rc) + return ap_pstrcat(cmd->pool, + "RewriteCond: cannot compile regular expression '", a2, + "'\n", NULL); + + new->pattern = ap_pstrdup(cmd->pool, cp); + new->regexp = regexp; + + return NULL; +} + +static const char *cmd_rewritecond_parseflagfield(pool *p, + rewritecond_entry *cfg, + char *str) +{ + char *cp; + char *cp1; + char *cp2; + char *cp3; + char *key; + char *val; + const char *err; + + if (str[0] != '[' || str[strlen(str)-1] != ']') + return "RewriteCond: bad flag delimiters"; + + cp = str+1; + str[strlen(str)-1] = ','; /* for simpler parsing */ + for ( ; *cp != '\0'; ) { + /* skip whitespaces */ + for ( ; (*cp == ' ' || *cp == '\t') && *cp != '\0'; cp++) + ; + if (*cp == '\0') + break; + cp1 = cp; + if ((cp2 = strchr(cp, ',')) != NULL) { + cp = cp2+1; + for ( ; (*(cp2-1) == ' ' || *(cp2-1) == '\t'); cp2--) + ; + *cp2 = '\0'; + if ((cp3 = strchr(cp1, '=')) != NULL) { + *cp3 = '\0'; + key = cp1; + val = cp3+1; + } + else { + key = cp1; + val = ""; + } + if ((err = cmd_rewritecond_setflag(p, cfg, key, val)) != NULL) + return err; + } + else + break; + } + + return NULL; +} + +static const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg, + char *key, char *val) +{ + if ( strcasecmp(key, "nocase") == 0 + || strcasecmp(key, "NC") == 0 ) { + cfg->flags |= CONDFLAG_NOCASE; + } + else if ( strcasecmp(key, "ornext") == 0 + || strcasecmp(key, "OR") == 0 ) { + cfg->flags |= CONDFLAG_ORNEXT; + } + else { + return ap_pstrcat(p, "RewriteCond: unknown flag '", key, "'\n", NULL); + } + return NULL; +} + +static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf, + char *str) +{ + rewrite_server_conf *sconf; + rewriterule_entry *new; + regex_t *regexp; + char *a1; + char *a2; + char *a3; + char *cp; + const char *err; + + sconf = (rewrite_server_conf *) + ap_get_module_config(cmd->server->module_config, &rewrite_module); + + /* make a new entry in the internal rewrite rule list */ + if (cmd->path == NULL) /* is server command */ + new = ap_push_array(sconf->rewriterules); + else /* is per-directory command */ + new = ap_push_array(dconf->rewriterules); + + /* parse the argument line ourself */ + if (parseargline(str, &a1, &a2, &a3)) + return ap_pstrcat(cmd->pool, "RewriteRule: bad argument line '", str, + "'\n", NULL); + + /* arg1: the pattern + * try to compile the regexp to test if is ok + */ + new->flags = RULEFLAG_NONE; + cp = a1; + if (cp[0] == '!') { + new->flags |= RULEFLAG_NOTMATCH; + cp++; + } + if ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED)) == NULL) + return ap_pstrcat(cmd->pool, + "RewriteRule: cannot compile regular expression '", a1, + "'\n", NULL); + new->pattern = ap_pstrdup(cmd->pool, cp); + new->regexp = regexp; + + /* arg2: the output string + * replace the $<N> by \<n> which is needed by the currently + * used Regular Expression library + */ + new->output = ap_pstrdup(cmd->pool, a2); + + /* arg3: optional flags field */ + new->forced_mimetype = NULL; + new->forced_responsecode = HTTP_MOVED_TEMPORARILY; + new->env[0] = NULL; + new->skip = 0; + if (a3 != NULL) { + if ((err = cmd_rewriterule_parseflagfield(cmd->pool, new, a3)) != NULL) + return err; + } + + /* now, if the server or per-dir config holds an + * array of RewriteCond entries, we take it for us + * and clear the array + */ + if (cmd->path == NULL) { /* is server command */ + new->rewriteconds = sconf->rewriteconds; + sconf->rewriteconds = ap_make_array(cmd->pool, 2, + sizeof(rewritecond_entry)); + } + else { /* is per-directory command */ + new->rewriteconds = dconf->rewriteconds; + dconf->rewriteconds = ap_make_array(cmd->pool, 2, + sizeof(rewritecond_entry)); + } + + return NULL; +} + +static const char *cmd_rewriterule_parseflagfield(pool *p, + rewriterule_entry *cfg, + char *str) +{ + char *cp; + char *cp1; + char *cp2; + char *cp3; + char *key; + char *val; + const char *err; + + if (str[0] != '[' || str[strlen(str)-1] != ']') + return "RewriteRule: bad flag delimiters"; + + cp = str+1; + str[strlen(str)-1] = ','; /* for simpler parsing */ + for ( ; *cp != '\0'; ) { + /* skip whitespaces */ + for ( ; (*cp == ' ' || *cp == '\t') && *cp != '\0'; cp++) + ; + if (*cp == '\0') + break; + cp1 = cp; + if ((cp2 = strchr(cp, ',')) != NULL) { + cp = cp2+1; + for ( ; (*(cp2-1) == ' ' || *(cp2-1) == '\t'); cp2--) + ; + *cp2 = '\0'; + if ((cp3 = strchr(cp1, '=')) != NULL) { + *cp3 = '\0'; + key = cp1; + val = cp3+1; + } + else { + key = cp1; + val = ""; + } + if ((err = cmd_rewriterule_setflag(p, cfg, key, val)) != NULL) + return err; + } + else + break; + } + + return NULL; +} + +static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg, + char *key, char *val) +{ + int status = 0; + int i; + + if ( strcasecmp(key, "redirect") == 0 + || strcasecmp(key, "R") == 0 ) { + cfg->flags |= RULEFLAG_FORCEREDIRECT; + if (strlen(val) > 0) { + if (strcasecmp(val, "permanent") == 0) + status = HTTP_MOVED_PERMANENTLY; + else if (strcasecmp(val, "temp") == 0) + status = HTTP_MOVED_TEMPORARILY; + else if (strcasecmp(val, "seeother") == 0) + status = HTTP_SEE_OTHER; + else if (isdigit(*val)) + status = atoi(val); + if (!is_HTTP_REDIRECT(status)) + return "RewriteRule: invalid HTTP response code " + "for flag 'R'"; + cfg->forced_responsecode = status; + } + } + else if ( strcasecmp(key, "last") == 0 + || strcasecmp(key, "L") == 0 ) { + cfg->flags |= RULEFLAG_LASTRULE; + } + else if ( strcasecmp(key, "next") == 0 + || strcasecmp(key, "N") == 0 ) { + cfg->flags |= RULEFLAG_NEWROUND; + } + else if ( strcasecmp(key, "chain") == 0 + || strcasecmp(key, "C") == 0 ) { + cfg->flags |= RULEFLAG_CHAIN; + } + else if ( strcasecmp(key, "type") == 0 + || strcasecmp(key, "T") == 0 ) { + cfg->forced_mimetype = ap_pstrdup(p, val); + ap_str_tolower(cfg->forced_mimetype); + } + else if ( strcasecmp(key, "env") == 0 + || strcasecmp(key, "E") == 0 ) { + for (i = 0; (cfg->env[i] != NULL) && (i < MAX_ENV_FLAGS); i++) + ; + if (i < MAX_ENV_FLAGS) { + cfg->env[i] = ap_pstrdup(p, val); + cfg->env[i+1] = NULL; + } + else + return "RewriteRule: to many environment flags 'E'"; + } + else if ( strcasecmp(key, "nosubreq") == 0 + || strcasecmp(key, "NS") == 0 ) { + cfg->flags |= RULEFLAG_IGNOREONSUBREQ; + } + else if ( strcasecmp(key, "proxy") == 0 + || strcasecmp(key, "P") == 0 ) { + cfg->flags |= RULEFLAG_PROXY; + } + else if ( strcasecmp(key, "passthrough") == 0 + || strcasecmp(key, "PT") == 0 ) { + cfg->flags |= RULEFLAG_PASSTHROUGH; + } + else if ( strcasecmp(key, "skip") == 0 + || strcasecmp(key, "S") == 0 ) { + cfg->skip = atoi(val); + } + else if ( strcasecmp(key, "forbidden") == 0 + || strcasecmp(key, "F") == 0 ) { + cfg->flags |= RULEFLAG_FORBIDDEN; + } + else if ( strcasecmp(key, "gone") == 0 + || strcasecmp(key, "G") == 0 ) { + cfg->flags |= RULEFLAG_GONE; + } + else if ( strcasecmp(key, "qsappend") == 0 + || strcasecmp(key, "QSA") == 0 ) { + cfg->flags |= RULEFLAG_QSAPPEND; + } + else { + return ap_pstrcat(p, "RewriteRule: unknown flag '", key, "'\n", NULL); + } + return NULL; +} + + +/* +** +** Global Module Initialization +** [called from read_config() after all +** config commands were already called] +** +*/ + +static void init_module(server_rec *s, pool *p) +{ + /* check if proxy module is available */ + proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL); + + /* precompile a static pattern + for the txt mapfile parsing */ + lookup_map_txtfile_regexp = ap_pregcomp(p, MAPFILE_PATTERN, REG_EXTENDED); + + /* create the rewriting lockfile in the parent */ + rewritelock_create(s, p); + ap_register_cleanup(p, (void *)s, rewritelock_remove, ap_null_cleanup); + + /* step through the servers and + * - open each rewriting logfile + * - open the RewriteMap prg:xxx programs + */ + for (; s; s = s->next) { + open_rewritelog(s, p); + run_rewritemap_programs(s, p); + } +} + + +/* +** +** Per-Child Module Initialization +** [called after a child process is spawned] +** +*/ + +static void init_child(server_rec *s, pool *p) +{ + /* open the rewriting lockfile */ + rewritelock_open(s, p); + + /* create the lookup cache */ + cachep = init_cache(p); +} + + +/* +** +-------------------------------------------------------+ +** | | +** | runtime hooks +** | | +** +-------------------------------------------------------+ +*/ + +/* +** +** URI-to-filename hook +** +** [used for the rewriting engine triggered by +** the per-server 'RewriteRule' directives] +** +*/ + +static int hook_uri2file(request_rec *r) +{ + void *sconf; + rewrite_server_conf *conf; + char *var; + const char *thisserver; + char *thisport, *thisurl; + char buf[512]; + char docroot[512]; + char *cp, *cp2; + struct stat finfo; + unsigned int port; + int n; + int l; + + /* + * retrieve the config structures + */ + sconf = r->server->module_config; + conf = (rewrite_server_conf *)ap_get_module_config(sconf, &rewrite_module); + + /* + * only do something under runtime if the engine is really enabled, + * else return immediately! + */ + if (conf->state == ENGINE_DISABLED) + return DECLINED; + + /* + * check for the ugly API case of a virtual host section where no + * mod_rewrite directives exists. In this situation we became no chance + * by the API to setup our default per-server config so we have to + * on-the-fly assume we have the default config. But because the default + * config has a disabled rewriting engine we are lucky because can + * just stop operating now. + */ + if (conf->server != r->server) + return DECLINED; + + /* + * add the SCRIPT_URL variable to the env. this is a bit complicated + * due to the fact that apache uses subrequests and internal redirects + */ + + if (r->main == NULL) { + var = ap_pstrcat(r->pool, "REDIRECT_", ENVVAR_SCRIPT_URL, NULL); + var = ap_table_get(r->subprocess_env, var); + if (var == NULL) + ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, r->uri); + else + ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var); + } + else { + var = ap_table_get(r->main->subprocess_env, ENVVAR_SCRIPT_URL); + ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var); + } + + /* + * create the SCRIPT_URI variable for the env + */ + + /* add the canonical URI of this URL */ + thisserver = ap_get_server_name(r); + port = ap_get_server_port(r); + if (is_default_port(port, r)) + thisport = ""; + else { + ap_snprintf(buf, sizeof(buf), ":%u", port); + thisport = buf; + } + thisurl = ap_table_get(r->subprocess_env, ENVVAR_SCRIPT_URL); + + /* set the variable */ + var = ap_pstrcat(r->pool, http_method(r), "://", thisserver, thisport, + thisurl, NULL); + ap_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URI, var); + + /* if filename was not initially set, + * we start with the requested URI + */ + if (r->filename == NULL) { + r->filename = ap_pstrdup(r->pool, r->uri); + rewritelog(r, 2, "init rewrite engine with requested uri %s", + r->filename); + } + + /* + * now apply the rules ... + */ + if (apply_rewrite_list(r, conf->rewriterules, NULL)) { + + if (strlen(r->filename) > 6 && + strncmp(r->filename, "proxy:", 6) == 0) { + /* it should be go on as an internal proxy request */ + + /* check if the proxy module is enabled, so + * we can actually use it! + */ + if (!proxy_available) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "attempt to make remote request from mod_rewrite " + "without proxy enabled: %s", r->filename); + return FORBIDDEN; + } + + /* make sure the QUERY_STRING and + * PATH_INFO parts get incorporated + */ + if (r->path_info != NULL) + r->filename = ap_pstrcat(r->pool, r->filename, r->path_info, NULL); + if (r->args != NULL && + r->uri == r->unparsed_uri /* see proxy_http:proxy_http_canon() */) + r->filename = ap_pstrcat(r->pool, r->filename, "?", r->args, NULL); + + /* now make sure the request gets handled by the proxy handler */ + r->proxyreq = 1; + r->handler = "proxy-server"; + + rewritelog(r, 1, "go-ahead with proxy request %s [OK]", + r->filename); + return OK; + } + else if ( (strlen(r->filename) > 7 && + strncasecmp(r->filename, "http://", 7) == 0) + || (strlen(r->filename) > 8 && + strncasecmp(r->filename, "https://", 8) == 0) + || (strlen(r->filename) > 9 && + strncasecmp(r->filename, "gopher://", 9) == 0) + || (strlen(r->filename) > 6 && + strncasecmp(r->filename, "ftp://", 6) == 0) ) { + /* it was finally rewritten to a remote URL */ + + /* skip 'scheme:' */ + for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++) + ; + /* skip '://' */ + cp += 3; + /* skip host part */ + for ( ; *cp != '/' && *cp != '\0'; cp++) + ; + if (*cp != '\0') { + rewritelog(r, 1, "escaping %s for redirect", r->filename); + cp2 = escape_uri(r->pool, cp); + *cp = '\0'; + r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL); + } + + /* append the QUERY_STRING part */ + if (r->args != NULL) + r->filename = ap_pstrcat(r->pool, r->filename, "?", r->args, NULL); + + /* determine HTTP redirect response code */ + if (is_HTTP_REDIRECT(r->status)) { + n = r->status; + r->status = HTTP_OK; /* make Apache kernel happy */ + } + else + n = REDIRECT; + + /* now do the redirection */ + ap_table_setn(r->headers_out, "Location", r->filename); + rewritelog(r, 1, "redirect to %s [REDIRECT/%d]", r->filename, n); + return n; + } + else if (strlen(r->filename) > 10 && + strncmp(r->filename, "forbidden:", 10) == 0) { + /* This URLs is forced to be forbidden for the requester */ + return FORBIDDEN; + } + else if (strlen(r->filename) > 5 && + strncmp(r->filename, "gone:", 5) == 0) { + /* This URLs is forced to be gone */ + return HTTP_GONE; + } + else if (strlen(r->filename) > 12 && + strncmp(r->filename, "passthrough:", 12) == 0) { + /* + * Hack because of underpowered API: passing the current + * rewritten filename through to other URL-to-filename handlers + * just as it were the requested URL. This is to enable + * post-processing by mod_alias, etc. which always act on + * r->uri! The difference here is: We do not try to + * add the document root + */ + r->uri = ap_pstrdup(r->pool, r->filename+12); + return DECLINED; + } + else { + /* it was finally rewritten to a local path */ + + /* expand "/~user" prefix */ +#ifndef WIN32 + r->filename = expand_tildepaths(r, r->filename); +#endif + rewritelog(r, 2, "local path result: %s", r->filename); + + /* the filename has to start with a slash! */ + if (r->filename[0] != '/') + return BAD_REQUEST; + + /* if there is no valid prefix, we have + * to emulate the translator from the core and + * prefix the filename with document_root + * + * NOTICE: + * We cannot leave out the prefix_stat because + * - when we always prefix with document_root + * then no absolute path can be created, e.g. via + * emulating a ScriptAlias directive, etc. + * - when we always NOT prefix with document_root + * then the files under document_root have to + * be references directly and document_root + * gets never used and will be a dummy parameter - + * this is also bad + * + * BUT: + * Under real Unix systems this is no problem, + * because we only do stat() on the first directory + * and this gets cached by the kernel for along time! + */ + n = prefix_stat(r->filename, &finfo); + if (n == 0) { + if ((cp = ap_document_root(r)) != NULL) { + l = ap_cpystrn(docroot, cp, sizeof(docroot)) - docroot; + + /* always NOT have a trailing slash */ + if (docroot[l-1] == '/') { + docroot[l-1] = '\0'; + } + if (r->server->path + && !strncmp(r->filename, r->server->path, + r->server->pathlen)) + r->filename = ap_pstrcat(r->pool, docroot, + (r->filename + r->server->pathlen), NULL); + else + r->filename = ap_pstrcat(r->pool, docroot, r->filename, + NULL); + rewritelog(r, 2, "prefixed with document_root to %s", + r->filename); + } + } + + rewritelog(r, 1, "go-ahead with %s [OK]", r->filename); + return OK; + } + } + else { + rewritelog(r, 1, "pass through %s", r->filename); + return DECLINED; + } +} + + +/* +** +** MIME-type hook +** +** [used to support the forced-MIME-type feature] +** +*/ + +static int hook_mimetype(request_rec *r) +{ + char *t; + + /* now check if we have to force a MIME-type */ + t = ap_table_get(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR); + if (t == NULL) + return DECLINED; + else { + rewritelog(r, 1, "force filename %s to have MIME-type '%s'", + r->filename, t); + r->content_type = t; + return OK; + } +} + + +/* +** +** Fixup hook +** +** [used for the rewriting engine triggered by +** the per-directory 'RewriteRule' directives] +** +*/ + +static int hook_fixup(request_rec *r) +{ + rewrite_perdir_conf *dconf; + char *cp; + char *cp2; + char *prefix; + int l; + int n; + char *ofilename; + + dconf = (rewrite_perdir_conf *) + ap_get_module_config(r->per_dir_config, &rewrite_module); + + /* if there is no per-dir config we return immediately */ + if (dconf == NULL) + return DECLINED; + + /* we shouldn't do anything in subrequests */ + if (r->main != NULL) + return DECLINED; + + /* if there are no real (i.e. no RewriteRule directives!) + per-dir config of us, we return also immediately */ + if (dconf->directory == NULL) + return DECLINED; + + /* + * only do something under runtime if the engine is really enabled, + * for this directory, else return immediately! + */ + if (!(ap_allow_options(r) & (OPT_SYM_LINKS | OPT_SYM_OWNER))) { + /* FollowSymLinks is mandatory! */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Options FollowSymLinks or SymLinksIfOwnerMatch is off " + "which implies that RewriteRule directive is forbidden: " + "%s", r->filename); + return FORBIDDEN; + } + else { + /* FollowSymLinks is given, but the user can + * still turn off the rewriting engine + */ + if (dconf->state == ENGINE_DISABLED) + return DECLINED; + } + + /* + * remember the current filename before rewriting for later check + * to prevent deadlooping because of internal redirects + * on final URL/filename which can be equal to the inital one. + */ + ofilename = r->filename; + + /* + * now apply the rules ... + */ + if (apply_rewrite_list(r, dconf->rewriterules, dconf->directory)) { + + if (strlen(r->filename) > 6 && + strncmp(r->filename, "proxy:", 6) == 0) { + /* it should go on as an internal proxy request */ + + /* make sure the QUERY_STRING and + * PATH_INFO parts get incorporated + * (r->path_info was already appended by the + * rewriting engine because of the per-dir context!) + */ + if (r->args != NULL && + r->uri == r->unparsed_uri /* see proxy_http:proxy_http_canon() */) + r->filename = ap_pstrcat(r->pool, r->filename, "?", r->args, NULL); + + /* now make sure the request gets handled by the proxy handler */ + r->proxyreq = 1; + r->handler = "proxy-server"; + + rewritelog(r, 1, "[per-dir %s] go-ahead with proxy request " + "%s [OK]", dconf->directory, r->filename); + return OK; + } + else if ( (strlen(r->filename) > 7 && + strncmp(r->filename, "http://", 7) == 0) + || (strlen(r->filename) > 8 && + strncmp(r->filename, "https://", 8) == 0) + || (strlen(r->filename) > 9 && + strncmp(r->filename, "gopher://", 9) == 0) + || (strlen(r->filename) > 6 && + strncmp(r->filename, "ftp://", 6) == 0) ) { + /* it was finally rewritten to a remote URL */ + + /* because we are in a per-dir context + * first try to replace the directory with its base-URL + * if there is a base-URL available + */ + if (dconf->baseurl != NULL) { + /* skip 'scheme:' */ + for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++) + ; + /* skip '://' */ + cp += 3; + if ((cp = strchr(cp, '/')) != NULL) { + rewritelog(r, 2, + "[per-dir %s] trying to replace prefix %s with %s", + dconf->directory, dconf->directory, dconf->baseurl); + cp2 = subst_prefix_path(r, cp, dconf->directory, + dconf->baseurl); + if (strcmp(cp2, cp) != 0) { + *cp = '\0'; + r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL); + } + } + } + + /* now prepare the redirect... */ + + /* skip 'scheme:' */ + for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++) + ; + /* skip '://' */ + cp += 3; + /* skip host part */ + for ( ; *cp != '/' && *cp != '\0'; cp++) + ; + if (*cp != '\0') { + rewritelog(r, 1, "[per-dir %s] escaping %s for redirect", + dconf->directory, r->filename); + cp2 = escape_uri(r->pool, cp); + *cp = '\0'; + r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL); + } + + /* append the QUERY_STRING part */ + if (r->args != NULL) + r->filename = ap_pstrcat(r->pool, r->filename, "?", r->args, NULL); + + /* determine HTTP redirect response code */ + if (is_HTTP_REDIRECT(r->status)) { + n = r->status; + r->status = HTTP_OK; /* make Apache kernel happy */ + } + else + n = REDIRECT; + + /* now do the redirection */ + ap_table_setn(r->headers_out, "Location", r->filename); + rewritelog(r, 1, "[per-dir %s] redirect to %s [REDIRECT/%d]", + dconf->directory, r->filename, n); + return n; + } + else if (strlen(r->filename) > 10 && + strncmp(r->filename, "forbidden:", 10) == 0) { + /* This URLs is forced to be forbidden for the requester */ + return FORBIDDEN; + } + else if (strlen(r->filename) > 5 && + strncmp(r->filename, "gone:", 5) == 0) { + /* This URLs is forced to be gone */ + return HTTP_GONE; + } + else { + /* it was finally rewritten to a local path */ + + /* if someone used the PASSTHROUGH flag in per-dir + * context we just ignore it. It is only useful + * in per-server context + */ + if (strlen(r->filename) > 12 && + strncmp(r->filename, "passthrough:", 12) == 0) { + r->filename = ap_pstrdup(r->pool, r->filename+12); + } + + /* the filename has to start with a slash! */ + if (r->filename[0] != '/') + return BAD_REQUEST; + + /* Check for deadlooping: + * At this point we KNOW that at least one rewriting + * rule was applied, but when the resulting URL is + * the same as the initial URL, we are not allowed to + * use the following internal redirection stuff because + * this would lead to a deadloop. + */ + if (strcmp(r->filename, ofilename) == 0) { + rewritelog(r, 1, "[per-dir %s] initial URL equal rewritten " + "URL: %s [IGNORING REWRITE]", + dconf->directory, r->filename); + return OK; + } + + /* if there is a valid base-URL then substitute + * the per-dir prefix with this base-URL if the + * current filename still is inside this per-dir + * context. If not then treat the result as a + * plain URL + */ + if (dconf->baseurl != NULL) { + rewritelog(r, 2, + "[per-dir %s] trying to replace prefix %s with %s", + dconf->directory, dconf->directory, dconf->baseurl); + r->filename = subst_prefix_path(r, r->filename, + dconf->directory, + dconf->baseurl); + } + else { + /* if no explicit base-URL exists we assume + * that the directory prefix is also a valid URL + * for this webserver and only try to remove the + * document_root if it is prefix + */ + if ((cp = ap_document_root(r)) != NULL) { + prefix = ap_pstrdup(r->pool, cp); + /* always NOT have a trailing slash */ + l = strlen(prefix); + if (prefix[l-1] == '/') { + prefix[l-1] = '\0'; + l--; + } + if (strncmp(r->filename, prefix, l) == 0) { + rewritelog(r, 2, + "[per-dir %s] strip document_root prefix: %s -> %s", + dconf->directory, r->filename, r->filename+l); + r->filename = ap_pstrdup(r->pool, r->filename+l); + } + } + } + + /* now initiate the internal redirect */ + rewritelog(r, 1, + "[per-dir %s] internal redirect with %s [INTERNAL REDIRECT]", + dconf->directory, r->filename); + r->filename = ap_pstrcat(r->pool, "redirect:", r->filename, NULL); + r->handler = "redirect-handler"; + return OK; + } + } + else { + rewritelog(r, 1, "[per-dir %s] pass through %s", dconf->directory, + r->filename); + return DECLINED; + } +} + + +/* +** +** Content-Handlers +** +** [used for redirect support] +** +*/ + +static int handler_redirect(request_rec *r) +{ + /* just make sure that we are really meant! */ + if (strncmp(r->filename, "redirect:", 9) != 0) + return DECLINED; + + /* now do the internal redirect */ + ap_internal_redirect(ap_pstrcat(r->pool, r->filename+9, + r->args ? "?" : NULL, r->args, NULL), r); + + /* and return gracefully */ + return OK; +} + + +/* +** +-------------------------------------------------------+ +** | | +** | the rewriting engine +** | | +** +-------------------------------------------------------+ +*/ + +/* + * Apply a complete rule set, + * i.e. a list of rewrite rules + */ +static int apply_rewrite_list(request_rec *r, array_header *rewriterules, + char *perdir) +{ + rewriterule_entry *entries; + rewriterule_entry *p; + int i; + int changed; + int rc; + int s; + + /* + * Iterate over all existing rules + */ + entries = (rewriterule_entry *)rewriterules->elts; + changed = 0; + loop: + for (i = 0; i < rewriterules->nelts; i++) { + p = &entries[i]; + + /* + * Ignore this rule on subrequests if we are explicitly + * asked to do so or this is a proxy-throughput or a + * forced redirect rule. + */ + if (r->main != NULL && + (p->flags & RULEFLAG_IGNOREONSUBREQ || + p->flags & RULEFLAG_PROXY || + p->flags & RULEFLAG_FORCEREDIRECT )) + continue; + + /* + * Apply the current rule. + */ + rc = apply_rewrite_rule(r, p, perdir); + if (rc) { + /* + * Indicate a change if this was not a match-only rule. + */ + if (rc != 2) + changed = 1; + + /* + * Pass-Through Feature (`RewriteRule .. .. [PT]'): + * Because the Apache 1.x API is very limited we + * need this hack to pass the rewritten URL to other + * modules like mod_alias, mod_userdir, etc. + */ + if (p->flags & RULEFLAG_PASSTHROUGH) { + rewritelog(r, 2, "forcing '%s' to get passed through " + "to next API URI-to-filename handler", r->filename); + r->filename = ap_pstrcat(r->pool, "passthrough:", + r->filename, NULL); + changed = 1; + break; + } + + /* + * Rule has the "forbidden" flag set which means that + * we stop processing and indicate this to the caller. + */ + if (p->flags & RULEFLAG_FORBIDDEN) { + rewritelog(r, 2, "forcing '%s' to be forbidden", r->filename); + r->filename = ap_pstrcat(r->pool, "forbidden:", + r->filename, NULL); + changed = 1; + break; + } + + /* + * Rule has the "gone" flag set which means that + * we stop processing and indicate this to the caller. + */ + if (p->flags & RULEFLAG_GONE) { + rewritelog(r, 2, "forcing '%s' to be gone", r->filename); + r->filename = ap_pstrcat(r->pool, "gone:", r->filename, NULL); + changed = 1; + break; + } + + /* + * Stop processing also on proxy pass-through and + * last-rule and new-round flags. + */ + if (p->flags & RULEFLAG_PROXY) + break; + if (p->flags & RULEFLAG_LASTRULE) + break; + + /* + * On "new-round" flag we just start from the top of + * the rewriting ruleset again. + */ + if (p->flags & RULEFLAG_NEWROUND) + goto loop; + + /* + * If we are forced to skip N next rules, do it now. + */ + if (p->skip > 0) { + s = p->skip; + while ( i < rewriterules->nelts + && s > 0) { + i++; + p = &entries[i]; + s--; + } + } + } + else { + /* + * If current rule is chained with next rule(s), + * skip all this next rule(s) + */ + while ( i < rewriterules->nelts + && p->flags & RULEFLAG_CHAIN) { + i++; + p = &entries[i]; + } + } + } + return changed; +} + +/* + * Apply a single(!) rewrite rule + */ +static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p, + char *perdir) +{ + char *uri; + char *output; + char newuri[MAX_STRING_LEN]; + char env[MAX_STRING_LEN]; + regex_t *regexp; + regmatch_t regmatch[MAX_NMATCH]; + backrefinfo *briRR = NULL; + backrefinfo *briRC = NULL; + int prefixstrip; + int failed; + array_header *rewriteconds; + rewritecond_entry *conds; + rewritecond_entry *c; + int i; + int rc; + + /* + * Initialisation + */ + uri = r->filename; + regexp = p->regexp; + output = p->output; + + /* + * Add (perhaps splitted away) PATH_INFO postfix to URL to + * make sure we really match against the complete URL. + */ + if (perdir != NULL && r->path_info != NULL && r->path_info[0] != '\0') { + rewritelog(r, 3, "[per-dir %s] add path-info postfix: %s -> %s%s", + perdir, uri, uri, r->path_info); + uri = ap_pstrcat(r->pool, uri, r->path_info, NULL); + } + + /* + * On per-directory context (.htaccess) strip the location + * prefix from the URL to make sure patterns apply only to + * the local part. Additionally indicate this special + * threatment in the logfile. + */ + prefixstrip = 0; + if (perdir != NULL) { + if ( strlen(uri) >= strlen(perdir) + && strncmp(uri, perdir, strlen(perdir)) == 0) { + rewritelog(r, 3, "[per-dir %s] strip per-dir prefix: %s -> %s", + perdir, uri, uri+strlen(perdir)); + uri = uri+strlen(perdir); + prefixstrip = 1; + } + } + + /* + * Try to match the URI against the RewriteRule pattern + * and exit immeddiately if it didn't apply. + */ + if (perdir == NULL) + rewritelog(r, 3, "applying pattern '%s' to uri '%s'", + p->pattern, uri); + else + rewritelog(r, 3, "[per-dir %s] applying pattern '%s' to uri '%s'", + perdir, p->pattern, uri); + rc = (regexec(regexp, uri, regexp->re_nsub+1, regmatch, 0) == 0); + if (! (( rc && !(p->flags & RULEFLAG_NOTMATCH)) || + (!rc && (p->flags & RULEFLAG_NOTMATCH)) ) ) + return 0; + + /* + * Else create the RewriteRule `regsubinfo' structure which + * holds the substitution information. + */ + briRR = (backrefinfo *)ap_palloc(r->pool, sizeof(backrefinfo)); + if (!rc && (p->flags & RULEFLAG_NOTMATCH)) { + /* empty info on negative patterns */ + briRR->source = ""; + briRR->nsub = 0; + } + else { + briRR->source = ap_pstrdup(r->pool, uri); + briRR->nsub = regexp->re_nsub; + memcpy((void *)(briRR->regmatch), (void *)(regmatch), + sizeof(regmatch)); + } + + /* + * Initiallally create the RewriteCond backrefinfo with + * empty backrefinfo, i.e. not subst parts + * (this one is adjusted inside apply_rewrite_cond() later!!) + */ + briRC = (backrefinfo *)ap_pcalloc(r->pool, sizeof(backrefinfo)); + briRC->source = ""; + briRC->nsub = 0; + + /* + * Ok, we already know the pattern has matched, but we now + * additionally have to check for all existing preconditions + * (RewriteCond) which have to be also true. We do this at + * this very late stage to avoid unnessesary checks which + * would slow down the rewriting engine!! + */ + rewriteconds = p->rewriteconds; + conds = (rewritecond_entry *)rewriteconds->elts; + failed = 0; + for (i = 0; i < rewriteconds->nelts; i++) { + c = &conds[i]; + rc = apply_rewrite_cond(r, c, perdir, briRR, briRC); + if (c->flags & CONDFLAG_ORNEXT) { + /* + * The "OR" case + */ + if (rc == 0) { + /* One condition is false, but another can be + * still true, so we have to continue... + */ + continue; + } + else { + /* One true condition is enough in "or" case, so + * skip the other conditions which are "ornext" + * chained + */ + while ( i < rewriteconds->nelts + && c->flags & CONDFLAG_ORNEXT) { + i++; + c = &conds[i]; + } + continue; + } + } + else { + /* + * The "AND" case, i.e. no "or" flag, + * so a single failure means total failure. + */ + if (rc == 0) { + failed = 1; + break; + } + } + } + /* if any condition fails the complete rule fails */ + if (failed) + return 0; + + /* + * If this is a pure matching rule (`RewriteRule <pat> -') + * we stop processing and return immediately. The only thing + * we have not to forget are the environment variables + * (`RewriteRule <pat> - [E=...]') + */ + if (strcmp(output, "-") == 0) { + for (i = 0; p->env[i] != NULL; i++) { + /* 1. take the string */ + ap_cpystrn(env, p->env[i], sizeof(env)); + /* 2. expand $N (i.e. backrefs to RewriteRule pattern) */ + expand_backref_inbuffer(r->pool, env, sizeof(env), briRR, '$'); + /* 3. expand %N (i.e. backrefs to latest RewriteCond pattern) */ + expand_backref_inbuffer(r->pool, env, sizeof(env), briRC, '%'); + /* 4. expand %{...} (i.e. variables) */ + expand_variables_inbuffer(r, env, sizeof(env)); + /* 5. expand ${...} (RewriteMap lookups) */ + expand_map_lookups(r, env, sizeof(env)); + /* and add the variable to Apache's structures */ + add_env_variable(r, env); + } + if (p->forced_mimetype != NULL) { + if (perdir == NULL) { + /* In the per-server context we can force the MIME-type + * the correct way by notifying our MIME-type hook handler + * to do the job when the MIME-type API stage is reached. + */ + rewritelog(r, 2, "remember %s to have MIME-type '%s'", + r->filename, p->forced_mimetype); + ap_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR, + p->forced_mimetype); + } + else { + /* In per-directory context we operate in the Fixup API hook + * which is after the MIME-type hook, so our MIME-type handler + * has no chance to set r->content_type. And because we are + * in the situation where no substitution takes place no + * sub-request will happen (which could solve the + * restriction). As a workaround we do it ourself now + * immediately although this is not strictly API-conforming. + * But it's the only chance we have... + */ + rewritelog(r, 1, "[per-dir %s] force %s to have MIME-type " + "'%s'", perdir, r->filename, p->forced_mimetype); + r->content_type = p->forced_mimetype; + } + } + return 2; + } + + /* + * Ok, now we finally know all patterns have matched and + * that there is something to replace, so we create the + * substitution URL string in `newuri'. + */ + /* 1. take the output string */ + ap_cpystrn(newuri, output, sizeof(newuri)); + /* 2. expand $N (i.e. backrefs to RewriteRule pattern) */ + expand_backref_inbuffer(r->pool, newuri, sizeof(newuri), briRR, '$'); + /* 3. expand %N (i.e. backrefs to latest RewriteCond pattern) */ + expand_backref_inbuffer(r->pool, newuri, sizeof(newuri), briRC, '%'); + /* 4. expand %{...} (i.e. variables) */ + expand_variables_inbuffer(r, newuri, sizeof(newuri)); + /* 5. expand ${...} (RewriteMap lookups) */ + expand_map_lookups(r, newuri, sizeof(newuri)); + /* and log the result... */ + if (perdir == NULL) + rewritelog(r, 2, "rewrite %s -> %s", uri, newuri); + else + rewritelog(r, 2, "[per-dir %s] rewrite %s -> %s", perdir, uri, newuri); + + /* + * Additionally do expansion for the environment variable + * strings (`RewriteRule .. .. [E=<string>]'). + */ + for (i = 0; p->env[i] != NULL; i++) { + /* 1. take the string */ + ap_cpystrn(env, p->env[i], sizeof(env)); + /* 2. expand $N (i.e. backrefs to RewriteRule pattern) */ + expand_backref_inbuffer(r->pool, env, sizeof(env), briRR, '$'); + /* 3. expand %N (i.e. backrefs to latest RewriteCond pattern) */ + expand_backref_inbuffer(r->pool, env, sizeof(env), briRC, '%'); + /* 4. expand %{...} (i.e. variables) */ + expand_variables_inbuffer(r, env, sizeof(env)); + /* 5. expand ${...} (RewriteMap lookups) */ + expand_map_lookups(r, env, sizeof(env)); + /* and add the variable to Apache's structures */ + add_env_variable(r, env); + } + + /* + * Now replace API's knowledge of the current URI: + * Replace r->filename with the new URI string and split out + * an on-the-fly generated QUERY_STRING part into r->args + */ + r->filename = ap_pstrdup(r->pool, newuri); + splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND); + + /* + * Again add the previously stripped per-directory location + * prefix if the new URI is not a new one for this + * location, i.e. if it's not starting with either a slash + * or a fully qualified URL scheme. + */ + i = strlen(r->filename); + if ( prefixstrip + && !( r->filename[0] == '/' + || ( (i > 7 && strncasecmp(r->filename, "http://", 7) == 0) + || (i > 8 && strncasecmp(r->filename, "https://", 8) == 0) + || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0) + || (i > 6 && strncasecmp(r->filename, "ftp://", 6) == 0)))) { + rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s", + perdir, r->filename, perdir, r->filename); + r->filename = ap_pstrcat(r->pool, perdir, r->filename, NULL); + } + + /* + * If this rule is forced for proxy throughput + * (`RewriteRule ... ... [P]') then emulate mod_proxy's + * URL-to-filename handler to be sure mod_proxy is triggered + * for this URL later in the Apache API. But make sure it is + * a fully-qualified URL. (If not it is qualified with + * ourself). + */ + if (p->flags & RULEFLAG_PROXY) { + fully_qualify_uri(r); + if (perdir == NULL) + rewritelog(r, 2, "forcing proxy-throughput with %s", r->filename); + else + rewritelog(r, 2, "[per-dir %s] forcing proxy-throughput with %s", + perdir, r->filename); + r->filename = ap_pstrcat(r->pool, "proxy:", r->filename, NULL); + return 1; + } + + /* + * If this rule is explicitly forced for HTTP redirection + * (`RewriteRule .. .. [R]') then force an external HTTP + * redirect. But make sure it is a fully-qualified URL. (If + * not it is qualified with ourself). + */ + if (p->flags & RULEFLAG_FORCEREDIRECT) { + fully_qualify_uri(r); + if (perdir == NULL) + rewritelog(r, 2, + "explicitly forcing redirect with %s", r->filename); + else + rewritelog(r, 2, + "[per-dir %s] explicitly forcing redirect with %s", + perdir, r->filename); + r->status = p->forced_responsecode; + return 1; + } + + /* + * Special Rewriting Feature: Self-Reduction + * We reduce the URL by stripping a possible + * http[s]://<ourhost>[:<port>] prefix, i.e. a prefix which + * corresponds to ourself. This is to simplify rewrite maps + * and to avoid recursion, etc. When this prefix is not a + * coincidence then the user has to use [R] explicitly (see + * above). + */ + reduce_uri(r); + + /* + * If this rule is still implicitly forced for HTTP + * redirection (`RewriteRule .. <scheme>://...') then + * directly force an external HTTP redirect. + */ + i = strlen(r->filename); + if ( (i > 7 && strncasecmp(r->filename, "http://", 7) == 0) + || (i > 8 && strncasecmp(r->filename, "https://", 8) == 0) + || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0) + || (i > 6 && strncasecmp(r->filename, "ftp://", 6) == 0)) { + if (perdir == NULL) + rewritelog(r, 2, + "implicitly forcing redirect (rc=%d) with %s", + p->forced_responsecode, r->filename); + else + rewritelog(r, 2, "[per-dir %s] implicitly forcing redirect " + "(rc=%d) with %s", perdir, p->forced_responsecode, + r->filename); + r->status = p->forced_responsecode; + return 1; + } + + /* + * Now we are sure it is not a fully qualified URL. But + * there is still one special case left: A local rewrite in + * per-directory context, i.e. a substitution URL which does + * not start with a slash. Here we add again the initially + * stripped per-directory prefix. + */ + if (prefixstrip && r->filename[0] != '/') { + rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s", + perdir, r->filename, perdir, r->filename); + r->filename = ap_pstrcat(r->pool, perdir, r->filename, NULL); + } + + /* + * Finally we had to remember if a MIME-type should be + * forced for this URL (`RewriteRule .. .. [T=<type>]') + * Later in the API processing phase this is forced by our + * MIME API-hook function. This time its no problem even for + * the per-directory context (where the MIME-type hook was + * already processed) because a sub-request happens ;-) + */ + if (p->forced_mimetype != NULL) { + ap_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR, + p->forced_mimetype); + if (perdir == NULL) + rewritelog(r, 2, "remember %s to have MIME-type '%s'", + r->filename, p->forced_mimetype); + else + rewritelog(r, 2, + "[per-dir %s] remember %s to have MIME-type '%s'", + perdir, r->filename, p->forced_mimetype); + } + + /* + * Puuhhhhhhhh... WHAT COMPLICATED STUFF ;_) + * But now we're done for this particular rule. + */ + return 1; +} + +static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p, + char *perdir, backrefinfo *briRR, + backrefinfo *briRC) +{ + char input[MAX_STRING_LEN]; + struct stat sb; + request_rec *rsub; + regmatch_t regmatch[MAX_NMATCH]; + int rc; + + /* + * Construct the string we match against + */ + + /* 1. take the string */ + ap_cpystrn(input, p->input, sizeof(input)); + /* 2. expand $N (i.e. backrefs to RewriteRule pattern) */ + expand_backref_inbuffer(r->pool, input, sizeof(input), briRR, '$'); + /* 3. expand %N (i.e. backrefs to latest RewriteCond pattern) */ + expand_backref_inbuffer(r->pool, input, sizeof(input), briRC, '%'); + /* 4. expand %{...} (i.e. variables) */ + expand_variables_inbuffer(r, input, sizeof(input)); + /* 5. expand ${...} (RewriteMap lookups) */ + expand_map_lookups(r, input, sizeof(input)); + + /* + * Apply the patterns + */ + + rc = 0; + if (strcmp(p->pattern, "-f") == 0) { + if (stat(input, &sb) == 0) + if (S_ISREG(sb.st_mode)) + rc = 1; + } + else if (strcmp(p->pattern, "-s") == 0) { + if (stat(input, &sb) == 0) + if (S_ISREG(sb.st_mode) && sb.st_size > 0) + rc = 1; + } + else if (strcmp(p->pattern, "-l") == 0) { +#if !defined(__EMX__) && !defined(WIN32) + if (lstat(input, &sb) == 0) + if (S_ISLNK(sb.st_mode)) + rc = 1; +#endif + } + else if (strcmp(p->pattern, "-d") == 0) { + if (stat(input, &sb) == 0) + if (S_ISDIR(sb.st_mode)) + rc = 1; + } + else if (strcmp(p->pattern, "-U") == 0) { + /* avoid infinite subrequest recursion */ + if (strlen(input) > 0 /* nonempty path, and */ + && ( r->main == NULL /* - either not in a subrequest */ + || ( r->main->uri != NULL /* - or in a subrequest... */ + && r->uri != NULL /* ...and URIs aren't NULL... */ + /* ...and sub/main URIs differ */ + && strcmp(r->main->uri, r->uri) != 0) ) ) { + + /* run a URI-based subrequest */ + rsub = ap_sub_req_lookup_uri(input, r); + + /* URI exists for any result up to 3xx, redirects allowed */ + if (rsub->status < 400) + rc = 1; + + /* log it */ + rewritelog(r, 5, "RewriteCond URI (-U) check: " + "path=%s -> status=%d", input, rsub->status); + + /* cleanup by destroying the subrequest */ + ap_destroy_sub_req(rsub); + } + } + else if (strcmp(p->pattern, "-F") == 0) { + /* avoid infinite subrequest recursion */ + if (strlen(input) > 0 /* nonempty path, and */ + && ( r->main == NULL /* - either not in a subrequest */ + || ( r->main->uri != NULL /* - or in a subrequest... */ + && r->uri != NULL /* ...and URIs aren't NULL... */ + /* ...and sub/main URIs differ */ + && strcmp(r->main->uri, r->uri) != 0) ) ) { + + /* process a file-based subrequest: + * this differs from -U in that no path translation is done. + */ + rsub = ap_sub_req_lookup_file(input, r); + + /* file exists for any result up to 2xx, no redirects */ + if (rsub->status < 300 && + /* double-check that file exists since default result is 200 */ + stat(rsub->filename, &sb) == 0) + rc = 1; + + /* log it */ + rewritelog(r, 5, + "RewriteCond file (-F) check: path=%s -> file=%s status=%d", + input, rsub->filename, rsub->status); + + /* cleanup by destroying the subrequest */ + ap_destroy_sub_req(rsub); + } + } + else if (strlen(p->pattern) > 1 && *(p->pattern) == '>') { + rc = (compare_lexicography(input, p->pattern+1) == 1 ? 1 : 0); + } + else if (strlen(p->pattern) > 1 && *(p->pattern) == '<') { + rc = (compare_lexicography(input, p->pattern+1) == -1 ? 1 : 0); + } + else if (strlen(p->pattern) > 1 && *(p->pattern) == '=') { + if (strcmp(p->pattern+1, "\"\"") == 0) + rc = (*input == '\0'); + else + rc = (strcmp(input, p->pattern+1) == 0 ? 1 : 0); + } + else { + /* it is really a regexp pattern, so apply it */ + rc = (regexec(p->regexp, input, + p->regexp->re_nsub+1, regmatch,0) == 0); + + /* if it isn't a negated pattern and really matched + we update the passed-through regex subst info structure */ + if (rc && !(p->flags & CONDFLAG_NOTMATCH)) { + briRC->source = ap_pstrdup(r->pool, input); + briRC->nsub = p->regexp->re_nsub; + memcpy((void *)(briRC->regmatch), (void *)(regmatch), + sizeof(regmatch)); + } + } + + /* if this is a non-matching regexp, just negate the result */ + if (p->flags & CONDFLAG_NOTMATCH) + rc = !rc; + + rewritelog(r, 4, "RewriteCond: input='%s' pattern='%s%s' => %s", + input, (p->flags & CONDFLAG_NOTMATCH ? "!" : ""), + p->pattern, rc ? "matched" : "not-matched"); + + /* end just return the result */ + return rc; +} + + +/* +** +-------------------------------------------------------+ +** | | +** | URL transformation functions +** | | +** +-------------------------------------------------------+ +*/ + +/* +** +** split out a QUERY_STRING part from +** the current URI string +** +*/ + +static void splitout_queryargs(request_rec *r, int qsappend) +{ + char *q; + char *olduri; + + q = strchr(r->filename, '?'); + if (q != NULL) { + olduri = ap_pstrdup(r->pool, r->filename); + *q++ = '\0'; + if (qsappend) + r->args = ap_pstrcat(r->pool, q, "&", r->args, NULL); + else + r->args = ap_pstrdup(r->pool, q); + if (strlen(r->args) == 0) { + r->args = NULL; + rewritelog(r, 3, "split uri=%s -> uri=%s, args=<none>", olduri, + r->filename); + } + else { + if (r->args[strlen(r->args)-1] == '&') + r->args[strlen(r->args)-1] = '\0'; + rewritelog(r, 3, "split uri=%s -> uri=%s, args=%s", olduri, + r->filename, r->args); + } + } + return; +} + + +/* +** +** strip 'http[s]://ourhost/' from URI +** +*/ + +static void reduce_uri(request_rec *r) +{ + char *cp; + unsigned short port; + char *portp; + char *hostp; + char *url; + char c; + char host[LONG_STRING_LEN]; + char buf[MAX_STRING_LEN]; + char *olduri; + +#ifdef APACHE_SSL + if ( (!r->connection->client->ssl && + strncasecmp(r->filename, "http://", 7) == 0) + || (r->connection->client->ssl && + strncasecmp(r->filename, "https://", 8) == 0)) { +#else + if (strncasecmp(r->filename, "http://", 7) == 0) { +#endif + /* there was really a rewrite to a remote path */ + + olduri = ap_pstrdup(r->pool, r->filename); /* save for logging */ + + /* cut the hostname and port out of the URI */ + ap_cpystrn(buf, r->filename+strlen(http_method(r))+3, sizeof(buf)); + hostp = buf; + for (cp = hostp; *cp != '\0' && *cp != '/' && *cp != ':'; cp++) + ; + if (*cp == ':') { + /* set host */ + *cp++ = '\0'; + ap_cpystrn(host, hostp, sizeof(host)); + /* set port */ + portp = cp; + for (; *cp != '\0' && *cp != '/'; cp++) + ; + c = *cp; + *cp = '\0'; + port = atoi(portp); + *cp = c; + /* set remaining url */ + url = cp; + } + else if (*cp == '/') { + /* set host */ + *cp = '\0'; + ap_cpystrn(host, hostp, sizeof(host)); + *cp = '/'; + /* set port */ + port = default_port(r); + /* set remaining url */ + url = cp; + } + else { + /* set host */ + ap_cpystrn(host, hostp, sizeof(host)); + /* set port */ + port = default_port(r); + /* set remaining url */ + url = "/"; + } + + /* now check whether we could reduce it to a local path... */ + if (ap_matches_request_vhost(r, host, port)) { + /* this is our host, so only the URL remains */ + r->filename = ap_pstrdup(r->pool, url); + rewritelog(r, 3, "reduce %s -> %s", olduri, r->filename); + } + } + return; +} + + +/* +** +** add 'http[s]://ourhost[:ourport]/' to URI +** if URI is still not fully qualified +** +*/ + +static void fully_qualify_uri(request_rec *r) +{ + int i; + char buf[32]; + const char *thisserver; + char *thisport; + int port; + + i = strlen(r->filename); + if (!( (i > 7 && strncasecmp(r->filename, "http://", 7) == 0) + || (i > 8 && strncasecmp(r->filename, "https://", 8) == 0) + || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0) + || (i > 6 && strncasecmp(r->filename, "ftp://", 6) == 0))) { + + thisserver = ap_get_server_name(r); + port = ap_get_server_port(r); + if (is_default_port(port,r)) + thisport = ""; + else { + ap_snprintf(buf, sizeof(buf), ":%u", port); + thisport = buf; + } + + if (r->filename[0] == '/') + r->filename = ap_psprintf(r->pool, "%s://%s%s%s", + http_method(r), thisserver, + thisport, r->filename); + else + r->filename = ap_psprintf(r->pool, "%s://%s%s/%s", + http_method(r), thisserver, + thisport, r->filename); + } + return; +} + + +/* +** +** Expand the %0-%9 or $0-$9 regex backreferences +** +*/ + +static void expand_backref_inbuffer(pool *p, char *buf, int nbuf, + backrefinfo *bri, char c) +{ + int i; + + if (bri->nsub < 1) + return; + + if (c != '$') { + /* safe existing $N backrefs and replace <c>N with $N backrefs */ + for (i = 0; buf[i] != '\0' && i < nbuf; i++) { + if (buf[i] == '$' && (buf[i+1] >= '0' && buf[i+1] <= '9')) + buf[i++] = '\001'; + else if (buf[i] == c && (buf[i+1] >= '0' && buf[i+1] <= '9')) + buf[i++] = '$'; + } + } + + /* now apply the pregsub() function */ + ap_cpystrn(buf, ap_pregsub(p, buf, bri->source, + bri->nsub+1, bri->regmatch), nbuf); + + if (c != '$') { + /* restore the original $N backrefs */ + for (i = 0; buf[i] != '\0' && i < nbuf; i++) + if (buf[i] == '\001' && (buf[i+1] >= '0' && buf[i+1] <= '9')) + buf[i++] = '$'; + } +} + + +/* +** +** Expand tilde-paths (/~user) through +** Unix /etc/passwd database information +** +*/ +#ifndef WIN32 +static char *expand_tildepaths(request_rec *r, char *uri) +{ + char user[LONG_STRING_LEN]; + struct passwd *pw; + char *newuri; + int i, j; + + newuri = uri; + if (uri != NULL && strlen(uri) > 2 && uri[0] == '/' && uri[1] == '~') { + /* cut out the username */ + for (j = 0, i = 2; j < sizeof(user)-1 + && uri[i] != '\0' + && uri[i] != '/' ; ) + user[j++] = uri[i++]; + user[j] = '\0'; + + /* lookup username in systems passwd file */ + if ((pw = getpwnam(user)) != NULL) { + /* ok, user was found, so expand the ~user string */ + if (uri[i] != '\0') { + /* ~user/anything... has to be expanded */ + if (pw->pw_dir[strlen(pw->pw_dir)-1] == '/') + pw->pw_dir[strlen(pw->pw_dir)-1] = '\0'; + newuri = ap_pstrcat(r->pool, pw->pw_dir, uri+i, NULL); + } + else { + /* only ~user has to be expanded */ + newuri = ap_pstrdup(r->pool, pw->pw_dir); + } + } + } + return newuri; +} +#endif + +/* +** +** mapfile expansion support +** i.e. expansion of MAP lookup directives +** ${<mapname>:<key>} in RewriteRule rhs +** +*/ + +#define limit_length(n) (n > LONG_STRING_LEN-1 ? LONG_STRING_LEN-1 : n) + +static void expand_map_lookups(request_rec *r, char *uri, int uri_len) +{ + char newuri[MAX_STRING_LEN]; + char *cpI; + char *cpIE; + char *cpO; + char *cpT; + char *cpT2; + char mapname[LONG_STRING_LEN]; + char mapkey[LONG_STRING_LEN]; + char defaultvalue[LONG_STRING_LEN]; + int n; + + cpI = uri; + cpIE = cpI+strlen(cpI); + cpO = newuri; + while (cpI < cpIE) { + if (cpI+6 < cpIE && strncmp(cpI, "${", 2) == 0) { + /* missing delimiter -> take it as plain text */ + if ( strchr(cpI+2, ':') == NULL + || strchr(cpI+2, '}') == NULL) { + memcpy(cpO, cpI, 2); + cpO += 2; + cpI += 2; + continue; + } + cpI += 2; + + cpT = strchr(cpI, ':'); + n = cpT-cpI; + memcpy(mapname, cpI, limit_length(n)); + mapname[limit_length(n)] = '\0'; + cpI += n+1; + + cpT2 = strchr(cpI, '|'); + cpT = strchr(cpI, '}'); + if (cpT2 != NULL && cpT2 < cpT) { + n = cpT2-cpI; + memcpy(mapkey, cpI, limit_length(n)); + mapkey[limit_length(n)] = '\0'; + cpI += n+1; + + n = cpT-cpI; + memcpy(defaultvalue, cpI, limit_length(n)); + defaultvalue[limit_length(n)] = '\0'; + cpI += n+1; + } + else { + n = cpT-cpI; + memcpy(mapkey, cpI, limit_length(n)); + mapkey[limit_length(n)] = '\0'; + cpI += n+1; + + defaultvalue[0] = '\0'; + } + + cpT = lookup_map(r, mapname, mapkey); + if (cpT != NULL) { + n = strlen(cpT); + if (cpO + n >= newuri + sizeof(newuri)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "insufficient space in expand_map_lookups, " + "aborting"); + return; + } + memcpy(cpO, cpT, n); + cpO += n; + } + else { + n = strlen(defaultvalue); + if (cpO + n >= newuri + sizeof(newuri)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "insufficient space in expand_map_lookups, " + "aborting"); + return; + } + memcpy(cpO, defaultvalue, n); + cpO += n; + } + } + else { + cpT = strstr(cpI, "${"); + if (cpT == NULL) + cpT = cpI+strlen(cpI); + n = cpT-cpI; + if (cpO + n >= newuri + sizeof(newuri)) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "insufficient space in expand_map_lookups, " + "aborting"); + return; + } + memcpy(cpO, cpI, n); + cpO += n; + cpI += n; + } + } + *cpO = '\0'; + ap_cpystrn(uri, newuri, uri_len); + return; +} + +#undef limit_length + + + +/* +** +-------------------------------------------------------+ +** | | +** | DBM hashfile support +** | | +** +-------------------------------------------------------+ +*/ + + +static char *lookup_map(request_rec *r, char *name, char *key) +{ + void *sconf; + rewrite_server_conf *conf; + array_header *rewritemaps; + rewritemap_entry *entries; + rewritemap_entry *s; + char *value; + struct stat st; + int i; + + /* get map configuration */ + sconf = r->server->module_config; + conf = (rewrite_server_conf *)ap_get_module_config(sconf, &rewrite_module); + rewritemaps = conf->rewritemaps; + + entries = (rewritemap_entry *)rewritemaps->elts; + for (i = 0; i < rewritemaps->nelts; i++) { + s = &entries[i]; + if (strcmp(s->name, name) == 0) { + if (s->type == MAPTYPE_TXT) { + if (stat(s->checkfile, &st) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "mod_rewrite: can't access text RewriteMap " + "file %s", s->checkfile); + rewritelog(r, 1, + "can't open RewriteMap file, see error log"); + return NULL; + } + value = get_cache_string(cachep, s->name, CACHEMODE_TS, + st.st_mtime, key); + if (value == NULL) { + rewritelog(r, 6, "cache lookup FAILED, forcing new " + "map lookup"); + if ((value = + lookup_map_txtfile(r, s->datafile, key)) != NULL) { + rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] " + "-> val=%s", s->name, key, value); + set_cache_string(cachep, s->name, CACHEMODE_TS, + st.st_mtime, key, value); + return value; + } + else { + rewritelog(r, 5, "map lookup FAILED: map=%s[txt] " + "key=%s", s->name, key); + return NULL; + } + } + else { + rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s " + "-> val=%s", s->name, key, value); + return value; + } + } + else if (s->type == MAPTYPE_DBM) { +#ifndef NO_DBM_REWRITEMAP + if (stat(s->checkfile, &st) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "mod_rewrite: can't access DBM RewriteMap " + "file %s", s->checkfile); + rewritelog(r, 1, + "can't open DBM RewriteMap file, see error log"); + return NULL; + } + value = get_cache_string(cachep, s->name, CACHEMODE_TS, + st.st_mtime, key); + if (value == NULL) { + rewritelog(r, 6, + "cache lookup FAILED, forcing new map lookup"); + if ((value = + lookup_map_dbmfile(r, s->datafile, key)) != NULL) { + rewritelog(r, 5, "map lookup OK: map=%s[dbm] key=%s " + "-> val=%s", s->name, key, value); + set_cache_string(cachep, s->name, CACHEMODE_TS, + st.st_mtime, key, value); + return value; + } + else { + rewritelog(r, 5, "map lookup FAILED: map=%s[dbm] " + "key=%s", s->name, key); + return NULL; + } + } + else { + rewritelog(r, 5, "cache lookup OK: map=%s[dbm] key=%s " + "-> val=%s", s->name, key, value); + return value; + } +#else + return NULL; +#endif + } + else if (s->type == MAPTYPE_PRG) { + if ((value = + lookup_map_program(r, s->fpin, s->fpout, key)) != NULL) { + rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s", + s->name, key, value); + return value; + } + else { + rewritelog(r, 5, "map lookup FAILED: map=%s key=%s", + s->name, key); + } + } + else if (s->type == MAPTYPE_INT) { + if ((value = lookup_map_internal(r, s->func, key)) != NULL) { + rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s", + s->name, key, value); + return value; + } + else { + rewritelog(r, 5, "map lookup FAILED: map=%s key=%s", + s->name, key); + } + } + else if (s->type == MAPTYPE_RND) { + if (stat(s->checkfile, &st) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "mod_rewrite: can't access text RewriteMap " + "file %s", s->checkfile); + rewritelog(r, 1, + "can't open RewriteMap file, see error log"); + return NULL; + } + value = get_cache_string(cachep, s->name, CACHEMODE_TS, + st.st_mtime, key); + if (value == NULL) { + rewritelog(r, 6, "cache lookup FAILED, forcing new " + "map lookup"); + if ((value = + lookup_map_txtfile(r, s->datafile, key)) != NULL) { + rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] " + "-> val=%s", s->name, key, value); + set_cache_string(cachep, s->name, CACHEMODE_TS, + st.st_mtime, key, value); + } + else { + rewritelog(r, 5, "map lookup FAILED: map=%s[txt] " + "key=%s", s->name, key); + return NULL; + } + } + else { + rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s " + "-> val=%s", s->name, key, value); + } + value = select_random_value_part(r, value); + rewritelog(r, 5, "randomly choosen the subvalue `%s'", value); + return value; + } + } + } + return NULL; +} + + +static char *lookup_map_txtfile(request_rec *r, char *file, char *key) +{ + FILE *fp = NULL; + char line[1024]; + char output[1024]; + char result[1024]; + char *value = NULL; + char *cpT; + char *curkey; + char *curval; + + if ((fp = ap_pfopen(r->pool, file, "r")) == NULL) + return NULL; + + ap_cpystrn(output, MAPFILE_OUTPUT, sizeof(output)); + while (fgets(line, sizeof(line), fp) != NULL) { + if (line[strlen(line)-1] == '\n') + line[strlen(line)-1] = '\0'; + if (regexec(lookup_map_txtfile_regexp, line, + lookup_map_txtfile_regexp->re_nsub+1, + lookup_map_txtfile_regmatch, 0) == 0) { + ap_cpystrn(result, ap_pregsub(r->pool, output, line, + lookup_map_txtfile_regexp->re_nsub+1, + lookup_map_txtfile_regmatch), + sizeof(result)); /* substitute in output */ + cpT = strchr(result, ','); + *cpT = '\0'; + curkey = result; + curval = cpT+1; + + if (strcmp(curkey, key) == 0) { + value = ap_pstrdup(r->pool, curval); + break; + } + } + } + ap_pfclose(r->pool, fp); + return value; +} + +#ifndef NO_DBM_REWRITEMAP +static char *lookup_map_dbmfile(request_rec *r, char *file, char *key) +{ + DBM *dbmfp = NULL; + datum dbmkey; + datum dbmval; + char *value = NULL; + char buf[MAX_STRING_LEN]; + + dbmkey.dptr = key; + dbmkey.dsize = (strlen(key) < sizeof(buf) - 1 ? + strlen(key) : sizeof(buf)-1); + if ((dbmfp = dbm_open(file, O_RDONLY, 0666)) != NULL) { + dbmval = dbm_fetch(dbmfp, dbmkey); + if (dbmval.dptr != NULL) { + memcpy(buf, dbmval.dptr, dbmval.dsize); + buf[dbmval.dsize] = '\0'; + value = ap_pstrdup(r->pool, buf); + } + dbm_close(dbmfp); + } + return value; +} +#endif + +static char *lookup_map_program(request_rec *r, int fpin, int fpout, char *key) +{ + char buf[LONG_STRING_LEN]; + char c; + int i; + + /* when `RewriteEngine off' was used in the per-server + * context then the rewritemap-programs were not spawned. + * In this case using such a map (usually in per-dir context) + * is useless because it is not available. + */ + if (fpin == -1 || fpout == -1) + return NULL; + + /* take the lock */ + rewritelock_alloc(r); + + /* write out the request key */ + write(fpin, key, strlen(key)); + write(fpin, "\n", 1); + + /* read in the response value */ + i = 0; + while (read(fpout, &c, 1) == 1 && (i < LONG_STRING_LEN-1)) { + if (c == '\n') + break; + buf[i++] = c; + } + buf[i] = '\0'; + + /* give the lock back */ + rewritelock_free(r); + + if (strcasecmp(buf, "NULL") == 0) + return NULL; + else + return ap_pstrdup(r->pool, buf); +} + +static char *lookup_map_internal(request_rec *r, + char *(*func)(request_rec *, char *), + char *key) +{ + /* currently we just let the function convert + the key to a corresponding value */ + return func(r, key); +} + +static char *rewrite_mapfunc_toupper(request_rec *r, char *key) +{ + char *value, *cp; + + for (cp = value = ap_pstrdup(r->pool, key); cp != NULL && *cp != '\0'; cp++) + *cp = toupper(*cp); + return value; +} + +static char *rewrite_mapfunc_tolower(request_rec *r, char *key) +{ + char *value, *cp; + + for (cp = value = ap_pstrdup(r->pool, key); cp != NULL && *cp != '\0'; cp++) + *cp = tolower(*cp); + return value; +} + +static int rewrite_rand_init_done = 0; + +static void rewrite_rand_init(void) +{ + if (!rewrite_rand_init_done) { + srand((unsigned)(getpid())); + rewrite_rand_init_done = 1; + } + return; +} + +static int rewrite_rand(int l, int h) +{ + int i; + char buf[50]; + + rewrite_rand_init(); + sprintf(buf, "%.0f", (((double)(rand()%RAND_MAX)/RAND_MAX)*(h-l))); + i = atoi(buf)+1; + if (i < l) i = l; + if (i > h) i = h; + return i; +} + +static char *select_random_value_part(request_rec *r, char *value) +{ + char *buf; + int n, i, k; + + /* count number of distinct values */ + for (n = 1, i = 0; value[i] != '\0'; i++) + if (value[i] == '|') + n++; + + /* when only one value we have no option to choose */ + if (n == 1) + return value; + + /* else randomly select one */ + k = rewrite_rand(1, n); + + /* and grep it out */ + for (n = 1, i = 0; value[i] != '\0'; i++) { + if (n == k) + break; + if (value[i] == '|') + n++; + } + buf = ap_pstrdup(r->pool, &value[i]); + for (i = 0; buf[i] != '\0' && buf[i] != '|'; i++) + ; + buf[i] = '\0'; + return buf; +} + + +/* +** +-------------------------------------------------------+ +** | | +** | rewriting logfile support +** | | +** +-------------------------------------------------------+ +*/ + + +static void open_rewritelog(server_rec *s, pool *p) +{ + rewrite_server_conf *conf; + char *fname; + piped_log *pl; + int rewritelog_flags = ( O_WRONLY|O_APPEND|O_CREAT ); +#ifdef WIN32 + mode_t rewritelog_mode=_S_IREAD|_S_IWRITE; +#else + mode_t rewritelog_mode = ( S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ); +#endif + + conf = ap_get_module_config(s->module_config, &rewrite_module); + + if (conf->rewritelogfile == NULL) + return; + if (*(conf->rewritelogfile) == '\0') + return; + if (conf->rewritelogfp > 0) + return; /* virtual log shared w/ main server */ + + fname = ap_server_root_relative(p, conf->rewritelogfile); + + if (*conf->rewritelogfile == '|') { + if ((pl = ap_open_piped_log(p, conf->rewritelogfile+1)) == NULL) { + perror("ap_open_piped_log"); + fprintf(stderr, + "mod_rewrite: could not open reliable piped log for " + "RewriteLog\n"); + exit (1); + } + conf->rewritelogfp = ap_piped_log_write_fd(pl); + } + else if (*conf->rewritelogfile != '\0') { + if ((conf->rewritelogfp = ap_popenf(p, fname, rewritelog_flags, + rewritelog_mode)) < 0) { + perror("open"); + fprintf(stderr, + "mod_rewrite: could not open RewriteLog file %s.\n", + fname); + exit(1); + } + } + return; +} + +static void rewritelog(request_rec *r, int level, const char *text, ...) +{ + rewrite_server_conf *conf; + conn_rec *conn; + char *str1; + char str2[512]; + char str3[1024]; + char type[20]; + char redir[20]; + va_list ap; + int i; + request_rec *req; + char *ruser; + const char *rhost; + + va_start(ap, text); + conf = ap_get_module_config(r->server->module_config, &rewrite_module); + conn = r->connection; + + if (conf->rewritelogfp < 0) + return; + if (conf->rewritelogfile == NULL) + return; + if (*(conf->rewritelogfile) == '\0') + return; + + if (level > conf->rewriteloglevel) + return; + + if (conn->user == NULL) { + ruser = "-"; + } + else if (strlen(conn->user) != 0) { + ruser = conn->user; + } + else { + ruser = "\"\""; + } + + rhost = ap_get_remote_host(conn, r->server->module_config, REMOTE_NOLOOKUP); + if (rhost == NULL) + rhost = "UNKNOWN-HOST"; + + str1 = ap_pstrcat(r->pool, rhost, " ", + (conn->remote_logname != NULL ? + conn->remote_logname : "-"), " ", + ruser, NULL); + ap_vsnprintf(str2, sizeof(str2), text, ap); + + if (r->main == NULL) + strcpy(type, "initial"); + else + strcpy(type, "subreq"); + + for (i = 0, req = r; req->prev != NULL; req = req->prev) + i++; + if (i == 0) + redir[0] = '\0'; + else + ap_snprintf(redir, sizeof(redir), "/redir#%d", i); + + ap_snprintf(str3, sizeof(str3), + "%s %s [%s/sid#%lx][rid#%lx/%s%s] (%d) %s\n", str1, + current_logtime(r), ap_get_server_name(r), + (unsigned long)(r->server), (unsigned long)r, + type, redir, level, str2); + + fd_lock(conf->rewritelogfp); + write(conf->rewritelogfp, str3, strlen(str3)); + fd_unlock(conf->rewritelogfp); + + va_end(ap); + return; +} + +static char *current_logtime(request_rec *r) +{ + int timz; + struct tm *t; + char tstr[80]; + char sign; + + t = ap_get_gmtoff(&timz); + sign = (timz < 0 ? '-' : '+'); + if(timz < 0) + timz = -timz; + + strftime(tstr, 80, "[%d/%b/%Y:%H:%M:%S ", t); + ap_snprintf(tstr + strlen(tstr), 80-strlen(tstr), "%c%.2d%.2d]", + sign, timz/60, timz%60); + return ap_pstrdup(r->pool, tstr); +} + + + + +/* +** +-------------------------------------------------------+ +** | | +** | rewriting lockfile support +** | | +** +-------------------------------------------------------+ +*/ + +#ifdef WIN32 +#define REWRITELOCK_MODE ( _S_IREAD|_S_IWRITE ) +#else +#define REWRITELOCK_MODE ( S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ) +#endif + +static void rewritelock_create(server_rec *s, pool *p) +{ + rewrite_server_conf *conf; + + conf = ap_get_module_config(s->module_config, &rewrite_module); + + /* only operate if a lockfile is used */ + if (conf->rewritelockfile == NULL + || *(conf->rewritelockfile) == '\0') + return; + + /* fixup the path, especially for rewritelock_remove() */ + conf->rewritelockfile = ap_server_root_relative(p, conf->rewritelockfile); + + /* create the lockfile */ + unlink(conf->rewritelockfile); + if ((conf->rewritelockfp = ap_popenf(p, conf->rewritelockfile, + O_WRONLY|O_CREAT, + REWRITELOCK_MODE)) < 0) { + perror("open"); + fprintf(stderr, "mod_rewrite: Parent could not create RewriteLock" + " file %s.\n", conf->rewritelockfile); + exit(1); + } + return; +} + +static void rewritelock_open(server_rec *s, pool *p) +{ + rewrite_server_conf *conf; + + conf = ap_get_module_config(s->module_config, &rewrite_module); + + /* only operate if a lockfile is used */ + if (conf->rewritelockfile == NULL + || *(conf->rewritelockfile) == '\0') + return; + + /* open the lockfile (once per child) to get a unique fd */ + if ((conf->rewritelockfp = ap_popenf(p, conf->rewritelockfile, + O_WRONLY, + REWRITELOCK_MODE)) < 0) { + perror("open"); + fprintf(stderr, "mod_rewrite: Child could not open RewriteLock" + " file %s.\n", conf->rewritelockfile); + exit(1); + } + return; +} + +static void rewritelock_remove(void *data) +{ + server_rec *s; + rewrite_server_conf *conf; + + /* the data is really the server_rec */ + s = (server_rec *)data; + conf = ap_get_module_config(s->module_config, &rewrite_module); + + /* only operate if a lockfile is used */ + if (conf->rewritelockfile == NULL + || *(conf->rewritelockfile) == '\0') + return; + + /* remove the lockfile */ + unlink(conf->rewritelockfile); +} + +static void rewritelock_alloc(request_rec *r) +{ + rewrite_server_conf *conf; + + conf = ap_get_module_config(r->server->module_config, &rewrite_module); + + if (conf->rewritelockfp != -1) + fd_lock(conf->rewritelockfp); + return; +} + +static void rewritelock_free(request_rec *r) +{ + rewrite_server_conf *conf; + + conf = ap_get_module_config(r->server->module_config, &rewrite_module); + + if (conf->rewritelockfp != -1) + fd_unlock(conf->rewritelockfp); + return; +} + + +/* +** +-------------------------------------------------------+ +** | | +** | program map support +** | | +** +-------------------------------------------------------+ +*/ + +static void run_rewritemap_programs(server_rec *s, pool *p) +{ + rewrite_server_conf *conf; + FILE *fpin; + FILE *fpout; + array_header *rewritemaps; + rewritemap_entry *entries; + rewritemap_entry *map; + int i; + int rc; + + conf = ap_get_module_config(s->module_config, &rewrite_module); + + /* If the engine isn't turned on, + * don't even try to do anything. + */ + if (conf->state == ENGINE_DISABLED) + return; + + rewritemaps = conf->rewritemaps; + entries = (rewritemap_entry *)rewritemaps->elts; + for (i = 0; i < rewritemaps->nelts; i++) { + map = &entries[i]; + if (map->type != MAPTYPE_PRG) + continue; + if (map->datafile == NULL + || *(map->datafile) == '\0' + || map->fpin != -1 + || map->fpout != -1 ) + continue; + fpin = NULL; + fpout = NULL; + rc = spawn_child(p, rewritemap_program_child, (void *)map->datafile, + kill_after_timeout, &fpin, &fpout); + if (rc == 0 || fpin == NULL || fpout == NULL) { + perror("spawn_child"); + fprintf(stderr, "mod_rewrite: " + "could not fork child for RewriteMap process\n"); + exit(1); + } + map->fpin = fileno(fpin); + map->fpout = fileno(fpout); + } + return; +} + +/* child process code */ +static int rewritemap_program_child(void *cmd, child_info *pinfo) +{ + int child_pid = 1; + + ap_cleanup_for_exec(); +#ifdef SIGHUP + signal(SIGHUP, SIG_IGN); +#endif +#if defined(WIN32) + child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH, + "/c", (char *)cmd, NULL); +#elif defined(__EMX__) + /* OS/2 needs a '/' */ + execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL); +#else + execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL); +#endif + return(child_pid); +} + + + + +/* +** +-------------------------------------------------------+ +** | | +** | environment variable support +** | | +** +-------------------------------------------------------+ +*/ + + +static void expand_variables_inbuffer(request_rec *r, char *buf, int buf_len) +{ + char *newbuf; + newbuf = expand_variables(r, buf); + if (strcmp(newbuf, buf) != 0) { + ap_cpystrn(buf, newbuf, buf_len); + } + return; +} + +static char *expand_variables(request_rec *r, char *str) +{ + char output[MAX_STRING_LEN]; + char input[MAX_STRING_LEN]; + char *cp; + char *cp2; + char *cp3; + int expanded; + char *outp; + char *endp; + + ap_cpystrn(input, str, sizeof(input)); + output[0] = '\0'; + outp = output; + endp = output + sizeof(output); + expanded = 0; + for (cp = input; cp < input+MAX_STRING_LEN; ) { + if ((cp2 = strstr(cp, "%{")) != NULL) { + if ((cp3 = strstr(cp2, "}")) != NULL) { + *cp2 = '\0'; + outp = ap_cpystrn(outp, cp, endp - outp); + + cp2 += 2; + *cp3 = '\0'; + outp = ap_cpystrn(outp, lookup_variable(r, cp2), endp - outp); + + cp = cp3+1; + expanded = 1; + continue; + } + } + outp = ap_cpystrn(outp, cp, endp - outp); + break; + } + return expanded ? ap_pstrdup(r->pool, output) : str; +} + +static char *lookup_variable(request_rec *r, char *var) +{ + const char *result; + char resultbuf[LONG_STRING_LEN]; + time_t tc; + struct tm *tm; + request_rec *rsub; +#ifndef WIN32 + struct passwd *pw; + struct group *gr; + struct stat finfo; +#endif + + result = NULL; + + /* HTTP headers */ + if (strcasecmp(var, "HTTP_USER_AGENT") == 0) { + result = lookup_header(r, "User-Agent"); + } + else if (strcasecmp(var, "HTTP_REFERER") == 0) { + result = lookup_header(r, "Referer"); + } + else if (strcasecmp(var, "HTTP_COOKIE") == 0) { + result = lookup_header(r, "Cookie"); + } + else if (strcasecmp(var, "HTTP_FORWARDED") == 0) { + result = lookup_header(r, "Forwarded"); + } + else if (strcasecmp(var, "HTTP_HOST") == 0) { + result = lookup_header(r, "Host"); + } + else if (strcasecmp(var, "HTTP_PROXY_CONNECTION") == 0) { + result = lookup_header(r, "Proxy-Connection"); + } + else if (strcasecmp(var, "HTTP_ACCEPT") == 0) { + result = lookup_header(r, "Accept"); + } + /* all other headers from which we are still not know about */ + else if (strlen(var) > 5 && strncasecmp(var, "HTTP:", 5) == 0) { + result = lookup_header(r, var+5); + } + + /* connection stuff */ + else if (strcasecmp(var, "REMOTE_ADDR") == 0) { + result = r->connection->remote_ip; + } + else if (strcasecmp(var, "REMOTE_HOST") == 0) { + result = (char *)ap_get_remote_host(r->connection, + r->per_dir_config, REMOTE_NAME); + } + else if (strcasecmp(var, "REMOTE_USER") == 0) { + result = r->connection->user; + } + else if (strcasecmp(var, "REMOTE_IDENT") == 0) { + result = (char *)ap_get_remote_logname(r); + } + + /* request stuff */ + else if (strcasecmp(var, "THE_REQUEST") == 0) { /* non-standard */ + result = r->the_request; + } + else if (strcasecmp(var, "REQUEST_METHOD") == 0) { + result = r->method; + } + else if (strcasecmp(var, "REQUEST_URI") == 0) { /* non-standard */ + result = r->uri; + } + else if (strcasecmp(var, "SCRIPT_FILENAME") == 0 || + strcasecmp(var, "REQUEST_FILENAME") == 0 ) { + result = r->filename; + } + else if (strcasecmp(var, "PATH_INFO") == 0) { + result = r->path_info; + } + else if (strcasecmp(var, "QUERY_STRING") == 0) { + result = r->args; + } + else if (strcasecmp(var, "AUTH_TYPE") == 0) { + result = r->connection->ap_auth_type; + } + else if (strcasecmp(var, "IS_SUBREQ") == 0) { /* non-standard */ + result = (r->main != NULL ? "true" : "false"); + } + + /* internal server stuff */ + else if (strcasecmp(var, "DOCUMENT_ROOT") == 0) { + result = ap_document_root(r); + } + else if (strcasecmp(var, "SERVER_ADMIN") == 0) { + result = r->server->server_admin; + } + else if (strcasecmp(var, "SERVER_NAME") == 0) { + result = ap_get_server_name(r); + } + else if (strcasecmp(var, "SERVER_PORT") == 0) { + ap_snprintf(resultbuf, sizeof(resultbuf), "%u", ap_get_server_port(r)); + result = resultbuf; + } + else if (strcasecmp(var, "SERVER_PROTOCOL") == 0) { + result = r->protocol; + } + else if (strcasecmp(var, "SERVER_SOFTWARE") == 0) { + result = ap_get_server_version(); + } + else if (strcasecmp(var, "API_VERSION") == 0) { /* non-standard */ + ap_snprintf(resultbuf, sizeof(resultbuf), "%d", MODULE_MAGIC_NUMBER); + result = resultbuf; + } + + /* underlaying Unix system stuff */ + else if (strcasecmp(var, "TIME_YEAR") == 0) { + tc = time(NULL); + tm = localtime(&tc); + ap_snprintf(resultbuf, sizeof(resultbuf), "%02d%02d", + (tm->tm_year / 100) + 19, tm->tm_year % 100); + result = resultbuf; + } +#define MKTIMESTR(format, tmfield) \ + tc = time(NULL); \ + tm = localtime(&tc); \ + ap_snprintf(resultbuf, sizeof(resultbuf), format, tm->tmfield); \ + result = resultbuf; + else if (strcasecmp(var, "TIME_MON") == 0) { + MKTIMESTR("%02d", tm_mon+1) + } + else if (strcasecmp(var, "TIME_DAY") == 0) { + MKTIMESTR("%02d", tm_mday) + } + else if (strcasecmp(var, "TIME_HOUR") == 0) { + MKTIMESTR("%02d", tm_hour) + } + else if (strcasecmp(var, "TIME_MIN") == 0) { + MKTIMESTR("%02d", tm_min) + } + else if (strcasecmp(var, "TIME_SEC") == 0) { + MKTIMESTR("%02d", tm_sec) + } + else if (strcasecmp(var, "TIME_WDAY") == 0) { + MKTIMESTR("%d", tm_wday) + } + else if (strcasecmp(var, "TIME") == 0) { + tc = time(NULL); + tm = localtime(&tc); + ap_snprintf(resultbuf, sizeof(resultbuf), + "%02d%02d%02d%02d%02d%02d%02d", (tm->tm_year / 100) + 19, + (tm->tm_year % 100), tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + result = resultbuf; + rewritelog(r, 1, "RESULT='%s'", result); + } + + /* all other env-variables from the parent Apache process */ + else if (strlen(var) > 4 && strncasecmp(var, "ENV:", 4) == 0) { + /* first try the internal Apache notes structure */ + result = ap_table_get(r->notes, var+4); + /* second try the internal Apache env structure */ + if (result == NULL) + result = ap_table_get(r->subprocess_env, var+4); + /* third try the external OS env */ + if (result == NULL) + result = getenv(var+4); + } + +#define LOOKAHEAD(subrecfunc) \ + if ( \ + /* filename is safe to use */ \ + r->filename != NULL \ + /* - and we're either not in a subrequest */ \ + && ( r->main == NULL \ + /* - or in a subrequest where paths are non-NULL... */ \ + || ( r->main->uri != NULL && r->uri != NULL \ + /* ...and sub and main paths differ */ \ + && strcmp(r->main->uri, r->uri) != 0))) { \ + /* process a file-based subrequest */ \ + rsub = subrecfunc(r->filename, r); \ + /* now recursively lookup the variable in the sub_req */ \ + result = lookup_variable(rsub, var+5); \ + /* copy it up to our scope before we destroy sub_req's pool */ \ + result = ap_pstrdup(r->pool, result); \ + /* cleanup by destroying the subrequest */ \ + ap_destroy_sub_req(rsub); \ + /* log it */ \ + rewritelog(r, 5, "lookahead: path=%s var=%s -> val=%s", \ + r->filename, var+5, result); \ + /* return ourself to prevent re-pstrdup */ \ + return (char *)result; \ + } + + /* look-ahead for parameter through URI-based sub-request */ + else if (strlen(var) > 5 && strncasecmp(var, "LA-U:", 5) == 0) { + LOOKAHEAD(ap_sub_req_lookup_uri) + } + /* look-ahead for parameter through file-based sub-request */ + else if (strlen(var) > 5 && strncasecmp(var, "LA-F:", 5) == 0) { + LOOKAHEAD(ap_sub_req_lookup_file) + } + +#ifndef WIN32 + /* Win32 has a rather different view of file ownerships. + For now, just forget it */ + + /* file stuff */ + else if (strcasecmp(var, "SCRIPT_USER") == 0) { + result = "<unknown>"; + if (r->finfo.st_mode != 0) { + if ((pw = getpwuid(r->finfo.st_uid)) != NULL) { + result = pw->pw_name; + } + } + else { + if (stat(r->filename, &finfo) == 0) { + if ((pw = getpwuid(finfo.st_uid)) != NULL) { + result = pw->pw_name; + } + } + } + } + else if (strcasecmp(var, "SCRIPT_GROUP") == 0) { + result = "<unknown>"; + if (r->finfo.st_mode != 0) { + if ((gr = getgrgid(r->finfo.st_gid)) != NULL) { + result = gr->gr_name; + } + } + else { + if (stat(r->filename, &finfo) == 0) { + if ((gr = getgrgid(finfo.st_gid)) != NULL) { + result = gr->gr_name; + } + } + } + } +#endif /* ndef WIN32 */ + + if (result == NULL) + return ap_pstrdup(r->pool, ""); + else + return ap_pstrdup(r->pool, result); +} + +static char *lookup_header(request_rec *r, const char *name) +{ + array_header *hdrs_arr; + table_entry *hdrs; + int i; + + hdrs_arr = table_elts(r->headers_in); + hdrs = (table_entry *)hdrs_arr->elts; + for (i = 0; i < hdrs_arr->nelts; ++i) { + if (hdrs[i].key == NULL) + continue; + if (strcasecmp(hdrs[i].key, name) == 0) + return hdrs[i].val; + } + return NULL; +} + + + + +/* +** +-------------------------------------------------------+ +** | | +** | caching support +** | | +** +-------------------------------------------------------+ +*/ + + +static cache *init_cache(pool *p) +{ + cache *c; + + c = (cache *)ap_palloc(p, sizeof(cache)); + c->pool = ap_make_sub_pool(p); + c->lists = ap_make_array(c->pool, 2, sizeof(cachelist)); + return c; +} + +static void set_cache_string(cache *c, char *res, int mode, time_t t, + char *key, char *value) +{ + cacheentry ce; + + ce.time = t; + ce.key = key; + ce.value = value; + store_cache_string(c, res, &ce); + return; +} + +static char *get_cache_string(cache *c, char *res, int mode, + time_t t, char *key) +{ + cacheentry *ce; + + ce = retrieve_cache_string(c, res, key); + if (ce == NULL) + return NULL; + if (mode & CACHEMODE_TS) { + if (t != ce->time) + return NULL; + } + else if (mode & CACHEMODE_TTL) { + if (t > ce->time) + return NULL; + } + return ap_pstrdup(c->pool, ce->value); +} + +static void store_cache_string(cache *c, char *res, cacheentry *ce) +{ + int i; + int j; + cachelist *l; + cacheentry *e; + int found_list; + + found_list = 0; + /* first try to edit an existing entry */ + for (i = 0; i < c->lists->nelts; i++) { + l = &(((cachelist *)c->lists->elts)[i]); + if (strcmp(l->resource, res) == 0) { + found_list = 1; + for (j = 0; j < l->entries->nelts; j++) { + e = &(((cacheentry *)l->entries->elts)[j]); + if (strcmp(e->key, ce->key) == 0) { + e->time = ce->time; + e->value = ap_pstrdup(c->pool, ce->value); + return; + } + } + } + } + + /* create a needed new list */ + if (!found_list) { + l = ap_push_array(c->lists); + l->resource = ap_pstrdup(c->pool, res); + l->entries = ap_make_array(c->pool, 2, sizeof(cacheentry)); + } + + /* create the new entry */ + for (i = 0; i < c->lists->nelts; i++) { + l = &(((cachelist *)c->lists->elts)[i]); + if (strcmp(l->resource, res) == 0) { + e = ap_push_array(l->entries); + e->time = ce->time; + e->key = ap_pstrdup(c->pool, ce->key); + e->value = ap_pstrdup(c->pool, ce->value); + return; + } + } + + /* not reached, but when it is no problem... */ + return; +} + +static cacheentry *retrieve_cache_string(cache *c, char *res, char *key) +{ + int i; + int j; + cachelist *l; + cacheentry *e; + + for (i = 0; i < c->lists->nelts; i++) { + l = &(((cachelist *)c->lists->elts)[i]); + if (strcmp(l->resource, res) == 0) { + for (j = 0; j < l->entries->nelts; j++) { + e = &(((cacheentry *)l->entries->elts)[j]); + if (strcmp(e->key, key) == 0) { + return e; + } + } + } + } + return NULL; +} + + + + +/* +** +-------------------------------------------------------+ +** | | +** | misc functions +** | | +** +-------------------------------------------------------+ +*/ + +static char *subst_prefix_path(request_rec *r, char *input, char *match, + char *subst) +{ + char matchbuf[LONG_STRING_LEN]; + char substbuf[LONG_STRING_LEN]; + char *output; + int l; + + output = input; + + /* first create a match string which always has a trailing slash */ + l = ap_cpystrn(matchbuf, match, sizeof(matchbuf)) - matchbuf; + if (matchbuf[l-1] != '/') { + matchbuf[l] = '/'; + matchbuf[l+1] = '\0'; + l++; + } + /* now compare the prefix */ + if (strncmp(input, matchbuf, l) == 0) { + rewritelog(r, 5, "strip matching prefix: %s -> %s", output, output+l); + output = ap_pstrdup(r->pool, output+l); + + /* and now add the base-URL as replacement prefix */ + l = ap_cpystrn(substbuf, subst, sizeof(substbuf)) - substbuf; + if (substbuf[l-1] != '/') { + substbuf[l] = '/'; + substbuf[l+1] = '\0'; + l++; + } + if (output[0] == '/') { + rewritelog(r, 4, "add subst prefix: %s -> %s%s", + output, substbuf, output+1); + output = ap_pstrcat(r->pool, substbuf, output+1, NULL); + } + else { + rewritelog(r, 4, "add subst prefix: %s -> %s%s", + output, substbuf, output); + output = ap_pstrcat(r->pool, substbuf, output, NULL); + } + } + return output; +} + + +/* +** +** own command line parser which don't have the '\\' problem +** +*/ + +static int parseargline(char *str, char **a1, char **a2, char **a3) +{ + char *cp; + int isquoted; + +#define SKIP_WHITESPACE(cp) \ + for ( ; *cp == ' ' || *cp == '\t'; ) \ + cp++; + +#define CHECK_QUOTATION(cp,isquoted) \ + isquoted = 0; \ + if (*cp == '"') { \ + isquoted = 1; \ + cp++; \ + } + +#define DETERMINE_NEXTSTRING(cp,isquoted) \ + for ( ; *cp != '\0'; cp++) { \ + if ( (isquoted && (*cp == ' ' || *cp == '\t')) \ + || (*cp == '\\' && (*(cp+1) == ' ' || *(cp+1) == '\t'))) { \ + cp++; \ + continue; \ + } \ + if ( (!isquoted && (*cp == ' ' || *cp == '\t')) \ + || (isquoted && *cp == '"') ) \ + break; \ + } + + cp = str; + SKIP_WHITESPACE(cp); + + /* determine first argument */ + CHECK_QUOTATION(cp, isquoted); + *a1 = cp; + DETERMINE_NEXTSTRING(cp, isquoted); + if (*cp == '\0') + return 1; + *cp++ = '\0'; + + SKIP_WHITESPACE(cp); + + /* determine second argument */ + CHECK_QUOTATION(cp, isquoted); + *a2 = cp; + DETERMINE_NEXTSTRING(cp, isquoted); + if (*cp == '\0') { + *cp++ = '\0'; + *a3 = NULL; + return 0; + } + *cp++ = '\0'; + + SKIP_WHITESPACE(cp); + + /* again check if there are only two arguments */ + if (*cp == '\0') { + *cp++ = '\0'; + *a3 = NULL; + return 0; + } + + /* determine second argument */ + CHECK_QUOTATION(cp, isquoted); + *a3 = cp; + DETERMINE_NEXTSTRING(cp, isquoted); + *cp++ = '\0'; + + return 0; +} + + +static void add_env_variable(request_rec *r, char *s) +{ + char var[MAX_STRING_LEN]; + char val[MAX_STRING_LEN]; + char *cp; + int n; + + if ((cp = strchr(s, ':')) != NULL) { + n = ((cp-s) > MAX_STRING_LEN-1 ? MAX_STRING_LEN-1 : (cp-s)); + memcpy(var, s, n); + var[n] = '\0'; + ap_cpystrn(val, cp+1, sizeof(val)); + ap_table_set(r->subprocess_env, var, val); + rewritelog(r, 5, "setting env variable '%s' to '%s'", var, val); + } +} + + + +/* +** +** stat() for only the prefix of a path +** +*/ + +static int prefix_stat(const char *path, struct stat *sb) +{ + char curpath[LONG_STRING_LEN]; + char *cp; + + ap_cpystrn(curpath, path, sizeof(curpath)); + if (curpath[0] != '/') + return 0; + if ((cp = strchr(curpath+1, '/')) != NULL) + *cp = '\0'; + if (stat(curpath, sb) == 0) + return 1; + else + return 0; +} + + +/* +** +** File locking +** +*/ + +#ifdef USE_FCNTL +static struct flock lock_it; +static struct flock unlock_it; +#endif + +static void fd_lock(int fd) +{ + int rc; + +#ifdef USE_FCNTL + lock_it.l_whence = SEEK_SET; /* from current point */ + lock_it.l_start = 0; /* -"- */ + lock_it.l_len = 0; /* until end of file */ + lock_it.l_type = F_WRLCK; /* set exclusive/write lock */ + lock_it.l_pid = 0; /* pid not actually interesting */ + + while ( ((rc = fcntl(fd, F_SETLKW, &lock_it)) < 0) + && (errno == EINTR) ) + continue; +#endif +#ifdef USE_FLOCK + while ( ((rc = flock(fd, LOCK_EX)) < 0) + && (errno == EINTR) ) + continue; +#endif +#ifdef USE_LOCKING + /* Lock the first byte, always, assume we want to append + and seek to the end afterwards */ + lseek(fd, 0, SEEK_SET); + rc = _locking(fd, _LK_LOCK, 1); + lseek(fd, 0, SEEK_END); +#endif + + if (rc < 0) { +#ifdef USE_FLOCK + perror("flock"); +#endif +#ifdef USE_FCNTL + perror("fcntl"); +#endif +#ifdef USE_LOCKING + perror("_locking"); +#endif + fprintf(stderr, "mod_rewrite: Error getting lock. Exiting!"); + exit(1); + } + return; +} + +static void fd_unlock(int fd) +{ + int rc; + +#ifdef USE_FCNTL + unlock_it.l_whence = SEEK_SET; /* from current point */ + unlock_it.l_start = 0; /* -"- */ + unlock_it.l_len = 0; /* until end of file */ + unlock_it.l_type = F_UNLCK; /* unlock */ + unlock_it.l_pid = 0; /* pid not actually interesting */ + + rc = fcntl(fd, F_SETLKW, &unlock_it); +#endif +#ifdef USE_FLOCK + rc = flock(fd, LOCK_UN); +#endif +#ifdef USE_LOCKING + lseek(fd, 0, SEEK_SET); + rc = _locking(fd, _LK_UNLCK, 1); + lseek(fd, 0, SEEK_END); +#endif + + if (rc < 0) { +#ifdef USE_FLOCK + perror("flock"); +#endif +#ifdef USE_FCNTL + perror("fcntl"); +#endif +#ifdef USE_LOCKING + perror("_locking"); +#endif + fprintf(stderr, "mod_rewrite: Error freeing lock. Exiting!"); + exit(1); + } +} + +/* +** +** Lexicographic Compare +** +*/ + +static int compare_lexicography(char *cpNum1, char *cpNum2) +{ + int i; + int n1, n2; + + n1 = strlen(cpNum1); + n2 = strlen(cpNum2); + if (n1 > n2) + return 1; + if (n1 < n2) + return -1; + for (i = 0; i < n1; i++) { + if (cpNum1[i] > cpNum2[i]) + return 1; + if (cpNum1[i] < cpNum2[i]) + return -1; + } + return 0; +} + + +/*EOF*/ diff --git a/APACHE_1_3b7/src/modules/standard/mod_rewrite.h b/APACHE_1_3b7/src/modules/standard/mod_rewrite.h new file mode 100644 index 0000000000..637aecc082 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_rewrite.h @@ -0,0 +1,473 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 _MOD_REWRITE_H +#define _MOD_REWRITE_H 1 + +/* +** _ _ _ +** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___ +** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \ +** | | | | | | (_) | (_| | | | | __/\ V V /| | | | || __/ +** |_| |_| |_|\___/ \__,_|___|_| \___| \_/\_/ |_| |_|\__\___| +** |_____| +** +** URL Rewriting Module +** +** This module uses a rule-based rewriting engine (based on a +** regular-expression parser) to rewrite requested URLs on the fly. +** +** It supports an unlimited number of additional rule conditions (which can +** operate on a lot of variables, even on HTTP headers) for granular +** matching and even external database lookups (either via plain text +** tables, DBM hash files or even external processes) for advanced URL +** substitution. +** +** It operates on the full URLs (including the PATH_INFO part) both in +** per-server context (httpd.conf) and per-dir context (.htaccess) and even +** can generate QUERY_STRING parts on result. The rewriting result finally +** can lead to internal subprocessing, external request redirection or even +** to internal proxy throughput. +** +** This module was originally written in April 1996 and +** gifted exclusively to the The Apache Group in July 1997 by +** +** Ralf S. Engelschall +** rse@engelschall.com +** www.engelschall.com +*/ + + + /* Include from the underlaying Unix system ... */ +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include <time.h> +#include <signal.h> +#include <errno.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> + + /* Include from the Apache server ... */ +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_log.h" +#include "http_vhost.h" + + /* The NDBM support: + * We support only NDBM files. + * But we have to stat the file for the mtime, + * so we also need to know the file extension + */ +#ifndef NO_DBM_REWRITEMAP +#include <ndbm.h> +#if (__FreeBSD__) +#define NDBM_FILE_SUFFIX ".db" +#else +#define NDBM_FILE_SUFFIX ".pag" +#endif +#endif + + + /* The locking support: + * Try to determine whether we should use fcntl() or flock(). + * Would be better conf.h could provide this... :-( + */ +#if defined(USE_FCNTL_SERIALIZED_ACCEPT) +#define USE_FCNTL 1 +#include <fcntl.h> +#endif +#if defined(USE_FLOCK_SERIALIZED_ACCEPT) +#define USE_FLOCK 1 +#include <sys/file.h> +#endif +#if !defined(USE_FCNTL) && !defined(USE_FLOCK) +#define USE_FLOCK 1 +#if !defined(MPE) && !defined(WIN32) +#include <sys/file.h> +#endif +#ifndef LOCK_UN +#undef USE_FLOCK +#define USE_FCNTL 1 +#include <fcntl.h> +#endif +#endif +#ifdef AIX +#undef USE_FLOCK +#define USE_FCNTL 1 +#include <fcntl.h> +#endif +#ifdef WIN32 +#undef USE_FCNTL +#define USE_LOCKING +#include <sys/locking.h> +#endif + + +/* +** +** Some defines +** +*/ + +#define ENVVAR_SCRIPT_URL "SCRIPT_URL" +#define ENVVAR_SCRIPT_URI "SCRIPT_URI" + +#ifndef SUPPORT_DBM_REWRITEMAP +#define SUPPORT_DBM_REWRITEMAP 0 +#endif + +#define REWRITE_FORCED_MIMETYPE_NOTEVAR "rewrite-forced-mimetype" + +#define CONDFLAG_NONE 1<<0 +#define CONDFLAG_NOCASE 1<<1 +#define CONDFLAG_NOTMATCH 1<<2 +#define CONDFLAG_ORNEXT 1<<3 + +#define RULEFLAG_NONE 1<<0 +#define RULEFLAG_FORCEREDIRECT 1<<1 +#define RULEFLAG_LASTRULE 1<<2 +#define RULEFLAG_NEWROUND 1<<3 +#define RULEFLAG_CHAIN 1<<4 +#define RULEFLAG_IGNOREONSUBREQ 1<<5 +#define RULEFLAG_NOTMATCH 1<<6 +#define RULEFLAG_PROXY 1<<7 +#define RULEFLAG_PASSTHROUGH 1<<8 +#define RULEFLAG_FORBIDDEN 1<<9 +#define RULEFLAG_GONE 1<<10 +#define RULEFLAG_QSAPPEND 1<<11 + +#define MAPTYPE_TXT 1<<0 +#define MAPTYPE_DBM 1<<1 +#define MAPTYPE_PRG 1<<2 +#define MAPTYPE_INT 1<<3 +#define MAPTYPE_RND 1<<4 + +#define ENGINE_DISABLED 1<<0 +#define ENGINE_ENABLED 1<<1 + +#define OPTION_NONE 1<<0 +#define OPTION_INHERIT 1<<1 + +#define CACHEMODE_TS 1<<0 +#define CACHEMODE_TTL 1<<1 + +#ifndef FALSE +#define FALSE 0 +#define TRUE !FALSE +#endif + +#ifndef NO +#define NO FALSE +#define YES TRUE +#endif + +#ifndef RAND_MAX +#define RAND_MAX 32767 +#endif + +#ifndef LONG_STRING_LEN +#define LONG_STRING_LEN 2048 +#endif + +#define MAX_ENV_FLAGS 5 + +#define MAX_NMATCH 10 + +#define MAPFILE_PATTERN "^([^ \t]+)[ \t]+([^ \t]+).*$" +#define MAPFILE_OUTPUT "$1,$2" + + +/* +** +** our private data structures we handle with +** +*/ + + /* the list structures for holding the mapfile information + * and the rewrite rules + */ +typedef struct { + char *name; /* the name of the map */ + char *datafile; /* filename for map data files */ + char *checkfile; /* filename to check for map existence */ + int type; /* the type of the map */ + int fpin; /* in file pointer for program maps */ + int fpout; /* out file pointer for program maps */ + char *(*func)(request_rec *, /* function pointer for internal maps */ + char *); +} rewritemap_entry; + +typedef struct { + char *input; /* Input string of RewriteCond */ + char *pattern; /* the RegExp pattern string */ + regex_t *regexp; + int flags; /* Flags which control the match */ +} rewritecond_entry; + +typedef struct { + array_header *rewriteconds; /* the corresponding RewriteCond entries */ + char *pattern; /* the RegExp pattern string */ + regex_t *regexp; /* the RegExp pattern compilation */ + char *output; /* the Substitution string */ + int flags; /* Flags which control the substitution */ + char *forced_mimetype; /* forced MIME type of substitution */ + int forced_responsecode; /* forced HTTP redirect response status */ + char *env[MAX_ENV_FLAGS+1]; /* added environment variables */ + int skip; /* number of next rules to skip */ +} rewriterule_entry; + + + /* the per-server or per-virtual-server configuration + * statically generated once on startup for every server + */ +typedef struct { + int state; /* the RewriteEngine state */ + int options; /* the RewriteOption state */ + char *rewritelogfile; /* the RewriteLog filename */ + int rewritelogfp; /* the RewriteLog open filepointer */ + int rewriteloglevel; /* the RewriteLog level of verbosity */ + char *rewritelockfile; /* the RewriteLock filename */ + int rewritelockfp; /* the RewriteLock open filepointer */ + array_header *rewritemaps; /* the RewriteMap entries */ + array_header *rewriteconds; /* the RewriteCond entries (temporary) */ + array_header *rewriterules; /* the RewriteRule entries */ + server_rec *server; /* the corresponding server indicator */ +} rewrite_server_conf; + + + /* the per-directory configuration + * generated on-the-fly by Apache server for current request + */ +typedef struct { + int state; /* the RewriteEngine state */ + int options; /* the RewriteOption state */ + array_header *rewriteconds; /* the RewriteCond entries (temporary) */ + array_header *rewriterules; /* the RewriteRule entries */ + char *directory; /* the directory where it applies */ + char *baseurl; /* the base-URL where it applies */ +} rewrite_perdir_conf; + + + /* the cache structures */ + +typedef struct cacheentry { + time_t time; + char *key; + char *value; +} cacheentry; + +typedef struct cachelist { + char *resource; + array_header *entries; +} cachelist; + +typedef struct cache { + pool *pool; + array_header *lists; +} cache; + + /* the regex structure for the + substitution of backreferences */ + +typedef struct backrefinfo { + char *source; + int nsub; + regmatch_t regmatch[10]; +} backrefinfo; + + +/* +** +** forward declarations +** +*/ + + /* config structure handling */ +static void *config_server_create(pool *p, server_rec *s); +static void *config_server_merge (pool *p, void *basev, void *overridesv); +static void *config_perdir_create(pool *p, char *path); +static void *config_perdir_merge (pool *p, void *basev, void *overridesv); + + /* config directive handling */ +static const char *cmd_rewriteengine(cmd_parms *cmd, + rewrite_perdir_conf *dconf, int flag); +static const char *cmd_rewriteoptions(cmd_parms *cmd, + rewrite_perdir_conf *dconf, + char *option); +static const char *cmd_rewriteoptions_setoption(pool *p, int *options, + char *name); +static const char *cmd_rewritelog (cmd_parms *cmd, void *dconf, char *a1); +static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1); +static const char *cmd_rewritemap (cmd_parms *cmd, void *dconf, char *a1, + char *a2); +static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1); +static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, + char *a1); +static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf, + char *str); +static const char *cmd_rewritecond_parseflagfield(pool *p, + rewritecond_entry *new, + char *str); +static const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg, + char *key, char *val); +static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf, + char *str); +static const char *cmd_rewriterule_parseflagfield(pool *p, + rewriterule_entry *new, + char *str); +static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg, + char *key, char *val); + + /* initialisation */ +static void init_module(server_rec *s, pool *p); +static void init_child(server_rec *s, pool *p); + + /* runtime hooks */ +static int hook_uri2file (request_rec *r); +static int hook_mimetype (request_rec *r); +static int hook_fixup (request_rec *r); +static int handler_redirect(request_rec *r); + + /* rewriting engine */ +static int apply_rewrite_list(request_rec *r, array_header *rewriterules, + char *perdir); +static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p, + char *perdir); +static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p, + char *perdir, backrefinfo *briRR, + backrefinfo *briRC); + + /* URI transformation function */ +static void splitout_queryargs(request_rec *r, int qsappend); +static void fully_qualify_uri(request_rec *r); +static void reduce_uri(request_rec *r); +static void expand_backref_inbuffer(pool *p, char *buf, int nbuf, + backrefinfo *bri, char c); +static char *expand_tildepaths(request_rec *r, char *uri); +static void expand_map_lookups(request_rec *r, char *uri, int uri_len); + + /* rewrite map support functions */ +static char *lookup_map(request_rec *r, char *name, char *key); +static char *lookup_map_txtfile(request_rec *r, char *file, char *key); +#ifndef NO_DBM_REWRITEMAP +static char *lookup_map_dbmfile(request_rec *r, char *file, char *key); +#endif +static char *lookup_map_program(request_rec *r, int fpin, + int fpout, char *key); +static char *lookup_map_internal(request_rec *r, + char *(*func)(request_rec *r, char *key), + char *key); +static char *rewrite_mapfunc_toupper(request_rec *r, char *key); +static char *rewrite_mapfunc_tolower(request_rec *r, char *key); +static char *select_random_value_part(request_rec *r, char *value); +static void rewrite_rand_init(void); +static int rewrite_rand(int l, int h); + + /* rewriting logfile support */ +static void open_rewritelog(server_rec *s, pool *p); +static void rewritelog(request_rec *r, int level, const char *text, ...) + __attribute__((format(printf,3,4))); +static char *current_logtime(request_rec *r); + + /* rewriting lockfile support */ +static void rewritelock_create(server_rec *s, pool *p); +static void rewritelock_open(server_rec *s, pool *p); +static void rewritelock_remove(void *data); +static void rewritelock_alloc(request_rec *r); +static void rewritelock_free(request_rec *r); + + /* program map support */ +static void run_rewritemap_programs(server_rec *s, pool *p); +static int rewritemap_program_child(void *cmd, child_info *pinfo); + + /* env variable support */ +static void expand_variables_inbuffer(request_rec *r, char *buf, int buf_len); +static char *expand_variables(request_rec *r, char *str); +static char *lookup_variable(request_rec *r, char *var); +static char *lookup_header(request_rec *r, const char *name); + + /* caching functions */ +static cache *init_cache(pool *p); +static char *get_cache_string(cache *c, char *res, int mode, time_t mtime, + char *key); +static void set_cache_string(cache *c, char *res, int mode, time_t mtime, + char *key, char *value); +static cacheentry *retrieve_cache_string(cache *c, char *res, char *key); +static void store_cache_string(cache *c, char *res, cacheentry *ce); + + /* misc functions */ +static char *subst_prefix_path(request_rec *r, char *input, char *match, + char *subst); +static int parseargline(char *str, char **a1, char **a2, char **a3); +static int prefix_stat(const char *path, struct stat *sb); +static void add_env_variable(request_rec *r, char *s); + + /* File locking */ +static void fd_lock(int fd); +static void fd_unlock(int fd); + + /* Lexicographic Comparison */ +static int compare_lexicography(char *cpNum1, char *cpNum2); + +#endif /* _MOD_REWRITE_H */ + +/*EOF*/ diff --git a/APACHE_1_3b7/src/modules/standard/mod_setenvif.c b/APACHE_1_3b7/src/modules/standard/mod_setenvif.c new file mode 100644 index 0000000000..3452a714f7 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_setenvif.c @@ -0,0 +1,402 @@ +/* ==================================================================== + * Copyright (c) 1996-1998 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 + * IT'S 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_setenvif.c + * Set environment variables based on matching request headers or + * attributes against regex strings + * + * Paul Sutton <paul@ukweb.com> 27 Oct 1996 + * Based on mod_browser by Alexei Kosut <akosut@organic.com> + */ + +/* + * Used to set environment variables based on the incoming request headers, + * or some selected other attributes of the request (e.g., the remote host + * name). + * + * Usage: + * + * SetEnvIf name regex var ... + * + * where name is either a HTTP request header name, or one of the + * special values (see below). The 'value' of the header (or the + * value of the special value from below) are compared against the + * regex argument. If this is a simple string, a simple sub-string + * match is performed. Otherwise, a request expression match is + * done. If the value matches the string or regular expression, the + * environment variables listed as var ... are set. Each var can + * be in one of three formats: var, which sets the named variable + * (the value value "1"); var=value, which sets the variable to + * the given value; or !var, which unsets the variable is it has + * been previously set. + * + * Normally the strings are compared with regard to case. To ignore + * case, use the directive SetEnvIfNoCase instead. + * + * Special values for 'name' are: + * + * remote_host Remote host name (if available) + * remote_addr Remote IP address + * remote_user Remote authenticated user (if any) + * request_method Request method (GET, POST, etc) + * request_uri Requested URI + * + * Examples: + * + * To set the enviroment variable LOCALHOST if the client is the local + * machine: + * + * SetEnvIf remote_addr 127.0.0.1 LOCALHOST + * + * To set LOCAL if the client is the local host, or within our company's + * domain (192.168.10): + * + * SetEnvIf remote_addr 192.168.10. LOCAL + * SetEnvIf remote_addr 127.0.0.1 LOCALHOST + * + * This could be written as: + * + * SetEnvIf remote_addr (127.0.0.1|192.168.10.) LOCAL + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" + +enum special { + SPECIAL_NOT, + SPECIAL_REMOTE_ADDR, + SPECIAL_REMOTE_HOST, + SPECIAL_REMOTE_USER, + SPECIAL_REQUEST_URI, + SPECIAL_REQUEST_METHOD +}; +typedef struct { + char *name; /* header name */ + char *regex; /* regex to match against */ + regex_t *preg; /* compiled regex */ + table *features; /* env vars to set (or unset) */ + ENUM_BITFIELD( /* is it a "special" header ? */ + enum special, + special_type,4); + unsigned icase : 1; /* ignoring case? */ +} sei_entry; + +typedef struct { + array_header *conditionals; +} sei_cfg_rec; + +module MODULE_VAR_EXPORT setenvif_module; + +static void *create_setenvif_config(pool *p, server_rec *dummy) +{ + sei_cfg_rec *new = (sei_cfg_rec *) ap_palloc(p, sizeof(sei_cfg_rec)); + + new->conditionals = ap_make_array(p, 20, sizeof(sei_entry)); + return (void *) new; +} + +static void *merge_setenvif_config(pool *p, void *basev, void *overridesv) +{ + sei_cfg_rec *a = ap_pcalloc(p, sizeof(sei_cfg_rec)); + sei_cfg_rec *base = basev, *overrides = overridesv; + + a->conditionals = ap_append_arrays(p, base->conditionals, + overrides->conditionals); + return a; +} + +/* any non-NULL magic constant will do... used to indicate if REG_ICASE should be + * used */ +#define ICASE_MAGIC ((void *)(&setenvif_module)) + +static const char *add_setenvif_core(cmd_parms *cmd, void *mconfig, + char *fname, const char *args) +{ + char *regex; + const char *feature; + sei_cfg_rec *sconf = ap_get_module_config(cmd->server->module_config, + &setenvif_module); + sei_entry *new, *entries = (sei_entry *) sconf->conditionals->elts; + char *var; + int i; + int beenhere = 0; + unsigned icase; + + /* get regex */ + regex = ap_getword_conf(cmd->pool, &args); + if (!*regex) { + return ap_pstrcat(cmd->pool, "Missing regular expression for ", + cmd->cmd->name, NULL); + } + + /* + * If we've already got a sei_entry with the same name we want to + * just copy the name pointer... so that later on we can compare + * two header names just by comparing the pointers. + */ + + for (i = 0; i < sconf->conditionals->nelts; ++i) { + new = &entries[i]; + if (!strcasecmp(new->name, fname)) { + fname = new->name; + break; + } + } + + /* if the last entry has an idential headername and regex then + * merge with it + */ + i = sconf->conditionals->nelts - 1; + icase = cmd->info == ICASE_MAGIC; + if (i < 0 + || entries[i].name != fname + || entries[i].icase != icase + || strcmp(entries[i].regex, regex)) { + + /* no match, create a new entry */ + + new = ap_push_array(sconf->conditionals); + new->name = fname; + new->regex = regex; + new->icase = icase; + new->preg = ap_pregcomp(cmd->pool, regex, + (REG_EXTENDED | REG_NOSUB + | (icase ? REG_ICASE : 0))); + if (new->preg == NULL) { + return ap_pstrcat(cmd->pool, cmd->cmd->name, + " regex could not be compiled.", NULL); + } + new->features = ap_make_table(cmd->pool, 2); + + if (!strcasecmp(fname, "remote_addr")) { + new->special_type = SPECIAL_REMOTE_ADDR; + } + else if (!strcasecmp(fname, "remote_host")) { + new->special_type = SPECIAL_REMOTE_HOST; + } + else if (!strcasecmp(fname, "remote_user")) { + new->special_type = SPECIAL_REMOTE_USER; + } + else if (!strcasecmp(fname, "request_uri")) { + new->special_type = SPECIAL_REQUEST_URI; + } + else if (!strcasecmp(fname, "request_method")) { + new->special_type = SPECIAL_REQUEST_METHOD; + } + else { + new->special_type = SPECIAL_NOT; + } + } + else { + new = &entries[i]; + } + + for (;;) { + feature = ap_getword_conf(cmd->pool, &args); + if(!*feature) + break; + beenhere++; + + var = ap_getword(cmd->pool, &feature, '='); + if (*feature) { + ap_table_setn(new->features, var, feature); + } + else if (*var == '!') { + ap_table_setn(new->features, var + 1, "!"); + } + else { + ap_table_setn(new->features, var, "1"); + } + } + + if (!beenhere) { + return ap_pstrcat(cmd->pool, "Missing envariable expression for ", + cmd->cmd->name, NULL); + } + + return NULL; +} + +static const char *add_setenvif(cmd_parms *cmd, void *mconfig, const char *args) +{ + char *fname; + + /* get header name */ + fname = ap_getword_conf(cmd->pool, &args); + if (!*fname) { + return ap_pstrcat(cmd->pool, "Missing header-field name for ", + cmd->cmd->name, NULL); + } + return add_setenvif_core(cmd, mconfig, fname, args); +} + +/* + * This routine handles the BrowserMatch* directives. It simply turns around + * and feeds them, with the appropriate embellishments, to the general-purpose + * command handler. + */ +static const char *add_browser(cmd_parms *cmd, void *mconfig, const char *args) +{ + return add_setenvif_core(cmd, mconfig, "User-Agent", args); +} + +static const command_rec setenvif_module_cmds[] = +{ + {"SetEnvIf", add_setenvif, NULL, + RSRC_CONF, RAW_ARGS, "A header-name, regex and a list of variables."}, + {"SetEnvIfNoCase", add_setenvif, ICASE_MAGIC, + RSRC_CONF, RAW_ARGS, "a header-name, regex and a list of variables."}, + {"BrowserMatch", add_browser, NULL, + RSRC_CONF, RAW_ARGS, "A browser regex and a list of variables."}, + {"BrowserMatchNoCase", add_browser, ICASE_MAGIC, + RSRC_CONF, RAW_ARGS, "A browser regex and a list of variables."}, + {NULL}, +}; + +static int match_headers(request_rec *r) +{ + server_rec *s = r->server; + sei_cfg_rec *sconf = (sei_cfg_rec *) ap_get_module_config(s->module_config, + &setenvif_module); + sei_entry *entries = (sei_entry *) sconf->conditionals->elts; + table_entry *elts; + const char *val; + int i, j; + char *last_name; + + last_name = NULL; + val = NULL; + for (i = 0; i < sconf->conditionals->nelts; ++i) { + sei_entry *b = &entries[i]; + + /* Optimize the case where a bunch of directives in a row use the + * same header. Remember we don't need to strcmp the two header + * names because we made sure the pointers were equal during + * configuration. + */ + if (b->name != last_name) { + last_name = b->name; + switch (b->special_type) { + case SPECIAL_REMOTE_ADDR: + val = r->connection->remote_ip; + break; + case SPECIAL_REMOTE_HOST: + val = ap_get_remote_host(r->connection, r->per_dir_config, + REMOTE_NAME); + break; + case SPECIAL_REMOTE_USER: + val = r->connection->user; + break; + case SPECIAL_REQUEST_URI: + val = r->uri; + break; + case SPECIAL_REQUEST_METHOD: + val = r->method; + break; + case SPECIAL_NOT: + val = ap_table_get(r->headers_in, b->name); + break; + } + } + + if (!val) { + continue; + } + + if (!regexec(b->preg, val, 0, NULL, 0)) { + array_header *arr = table_elts(b->features); + elts = (table_entry *) arr->elts; + + for (j = 0; j < arr->nelts; ++j) { + if (!strcmp(elts[j].val, "!")) { + ap_table_unset(r->subprocess_env, elts[j].key); + } + else { + ap_table_setn(r->subprocess_env, elts[j].key, elts[j].val); + } + } + } + } + + return DECLINED; +} + +module MODULE_VAR_EXPORT setenvif_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + create_setenvif_config, /* server config */ + merge_setenvif_config, /* merge server configs */ + setenvif_module_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* input header parse */ + NULL, /* child (process) initialization */ + NULL, /* child (process) rundown */ + match_headers /* post_read_request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_so.c b/APACHE_1_3b7/src/modules/standard/mod_so.c new file mode 100644 index 0000000000..c3060163f6 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_so.c @@ -0,0 +1,350 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 module is used to load Apache modules at runtime. This means that the + * server functionality can be extended without recompiling and even without + * taking the server down at all. Only a HUP or USR1 signal needs to be send + * to the server to reload the dynamically loaded modules. + * + * To use, you'll first need to build your module as a shared library, then + * update your configuration (httpd.conf) to get the Apache core to load the + * module at start-up. + * + * The easiest way to build a module as a shared library is to use the + * `SharedModule' command in the Configuration file, instead of `AddModule'. + * You should also change the file extension from `.o' to `.so'. So, for + * example, to build the status module as a shared library edit Configuration + * and change + * AddModule modules/standard/mod_status.o + * to + * SharedModule modules/standard/mod_status.so + * + * Run Configure and make. Now Apache's httpd binary will _not_ include + * mod_status. Instead a shared object called mod_status.so will be build, in + * the modules/standard directory. You can build most of the modules as shared + * libraries like this. + * + * To use the shared module, move the .so file(s) into an appropriate + * directory. You might like to create a directory called "modules" under you + * server root for this (e.g. /usr/local/httpd/modules). + * + * Then edit your conf/httpd.conf file, and add LoadModule lines. For + * example + * LoadModule status_module modules/mod_status.so + * + * The first argument is the module's structure name (look at the end of the + * module source to find this). The second option is the path to the module + * file, relative to the server root. Put these directives right at the top + * of your httpd.conf file. + * + * Now you can start Apache. A message will be logged at "debug" level to your + * error_log to confirm that the module(s) are loaded (use "LogLevel debug" + * directive to get these log messages). + * + * If you edit the LoadModule directives while the server is live you can get + * Apache to re-load the modules by sending it a HUP or USR1 signal as normal. + * You can use this to dynamically change the capability of your server + * without bringing it down. + * + * Because currently there is only limited built-in support in the Configure + * script for creating the shared library files (`.so'), please consult your + * vendors cc(1), ld(1) and dlopen(3) manpages to find out the appropriate + * compiler and linker flags and insert them manually into the Configuration + * file under CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT. + * + * If you still have problems figuring out the flags both try the paper + * http://developer.netscape.com/library/documentation/enterprise + * /unix/svrplug.htm#1013807 + * or install a Perl 5 interpreter on your platform and then run the command + * + * $ perl -V:usedl -V:ccdlflags -V:cccdlflags -V:lddlflags + * + * This gives you what type of dynamic loading Perl 5 uses on your platform + * and which compiler and linker flags Perl 5 uses to create the shared object + * files. + * + * Another location where you can find useful hints is the `ltconfig' script + * of the GNU libtool 1.2 package. Search for your platform name inside the + * various "case" constructs. + * + */ + + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" + +module MODULE_VAR_EXPORT so_module; + + +/* + * Server configuration to keep track of actually + * loaded modules and the corresponding module name. + */ + +typedef struct moduleinfo { + char *name; + module *modp; +} moduleinfo; + +typedef struct so_server_conf { + array_header *loaded_modules; +} so_server_conf; + +static void *so_sconf_create(pool *p, server_rec *s) +{ + so_server_conf *soc; + + soc = (so_server_conf *)ap_pcalloc(p, sizeof(so_server_conf)); + soc->loaded_modules = ap_make_array(p, DYNAMIC_MODULE_LIMIT, + sizeof(moduleinfo)); + return (void *)soc; +} + +#ifndef NO_DLOPEN + +/* + * This is the cleanup for a loaded shared object. It unloads the module. + * This is called as a cleanup function from the core. + */ + +static void unload_module(moduleinfo *modi) +{ + /* only unload if module information is still existing */ + if (modi->modp == NULL) + return; + + /* remove the module pointer from the core structure */ + ap_remove_loaded_module(modi->modp); + + /* unload the module space itself */ + ap_os_dso_unload((ap_os_dso_handle_t)modi->modp->dynamic_load_handle); + + /* destroy the module information */ + modi->modp = NULL; + modi->name = NULL; +} + +/* + * This is the cleanup routine for files loaded by + * load_file(). Unfortunately we don't keep a record of the filename + * that was loaded, so we can't report the unload for debug purposes + * or include the filename in error message. + */ + +static void unload_file(void *handle) +{ + ap_os_dso_unload((ap_os_dso_handle_t)handle); +} + +/* + * This is called for the directive LoadModule and actually loads + * a shared object file into the address space of the server process. + */ + +static const char *load_module(cmd_parms *cmd, void *dummy, + char *modname, char *filename) +{ + ap_os_dso_handle_t modhandle; + module *modp; + const char *szModuleFile=ap_server_root_relative(cmd->pool, filename); + so_server_conf *sconf; + moduleinfo *modi; + moduleinfo *modie; + int i; + + /* + * check for already existing module + * If it already exists, we have nothing to do + */ + sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config, + &so_module); + modie = (moduleinfo *)sconf->loaded_modules->elts; + for (i = 0; i < sconf->loaded_modules->nelts; i++) { + modi = &modie[i]; + if (modi->name != NULL && strcmp(modi->name, modname) == 0) + return NULL; + } + modi = ap_push_array(sconf->loaded_modules); + modi->name = modname; + + /* + * Load the file into the Apache address space + */ + if (!(modhandle = ap_os_dso_load(szModuleFile))) { + const char *my_error = ap_os_dso_error(); + return ap_pstrcat (cmd->pool, "Cannot load ", szModuleFile, + " into server: ", + my_error ? my_error : "(reason unknown)", + NULL); + } + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, + "loaded module %s", modname); + + /* + * Retrieve the pointer to the module structure through the module name: + * First with the hidden variant (prefix `AP_') and then with the plain + * symbol name. + */ + if (!(modp = (module *)(ap_os_dso_sym(modhandle, modname)))) { + return ap_pstrcat(cmd->pool, "Can't find module ", modname, + " in file ", filename, ":", ap_os_dso_error(), NULL); + } + modi->modp = modp; + modp->dynamic_load_handle = modhandle; + + /* + * Add this module to the Apache core structures + */ + ap_add_loaded_module(modp); + + /* + * Register a cleanup in the config pool (normally pconf). When + * we do a restart (or shutdown) this cleanup will cause the + * shared object to be unloaded. + */ + ap_register_cleanup(cmd->pool, modi, + (void (*)(void*))unload_module, ap_null_cleanup); + + /* + * Finally we need to run the configuration functions + * in new modules now. + */ + if (modp->create_server_config) + ((void**)cmd->server->module_config)[modp->module_index] = + (*modp->create_server_config)(cmd->pool, cmd->server); + if (modp->create_dir_config) + ((void**)cmd->server->lookup_defaults)[modp->module_index] = + (*modp->create_dir_config)(cmd->pool, NULL); + + return NULL; +} + +/* + * This implements the LoadFile directive and loads an arbitrary + * shared object file into the adress space of the server process. + */ + +static const char *load_file(cmd_parms *cmd, void *dummy, char *filename) +{ + void *handle; + char *file; + + file = ap_server_root_relative(cmd->pool, filename); + + if (!(handle = ap_os_dso_load(file))) { + const char *my_error = ap_os_dso_error(); + return ap_pstrcat (cmd->pool, "Cannot load ", filename, + " into server:", + my_error ? my_error : "(reason unknown)", + NULL); + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL, + "loaded file %s", filename); + + ap_register_cleanup(cmd->pool, handle, unload_file, ap_null_cleanup); + + return NULL; +} + +#else /* not NO_DLOPEN */ + +static const char *load_file(cmd_parms *cmd, void *dummy, char *filename) +{ + fprintf(stderr, "WARNING: LoadFile not supported on this platform\n"); + return NULL; +} + +static const char *load_module(cmd_parms *cmd, void *dummy, + char *modname, char *filename) +{ + fprintf(stderr, "WARNING: LoadModule not supported on this platform\n"); + return NULL; +} + +#endif /* NO_DLOPEN */ + +static const command_rec so_cmds[] = { + { "LoadModule", load_module, NULL, RSRC_CONF, TAKE2, + "a module name and the name of a shared object file to load it from"}, + { "LoadFile", load_file, NULL, RSRC_CONF, ITERATE, + "shared object file or library to load into the server at runtime"}, + { NULL } +}; + +module MODULE_VAR_EXPORT so_module = { + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + so_sconf_create, /* server config */ + NULL, /* merge server config */ + so_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_speling.c b/APACHE_1_3b7/src/modules/standard/mod_speling.c new file mode 100644 index 0000000000..84762dc126 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_speling.c @@ -0,0 +1,451 @@ +#define WANT_BASENAME_MATCH +/* ==================================================================== + * Copyright (c) 1996-1998 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/>. + * + */ + +#include "httpd.h" +#include "http_core.h" +#include "http_config.h" +#include "http_log.h" + +/* mod_speling.c - by Alexei Kosut <akosut@organic.com> June, 1996 + * + * This module is transparent, and simple. It attempts to correct + * misspellings of URLs that users might have entered, namely by checking + * capitalizations. If it finds a match, it sends a redirect. + * + * 08-Aug-1997 <Martin.Kraemer@Mch.SNI.De> + * o Upgraded module interface to apache_1.3a2-dev API (more NULL's in speling_module). + * o Integrated tcsh's "spelling correction" routine which allows one + * misspelling (character insertion/omission/typo/transposition). + * Rewrote it to ignore case as well. This ought to catch the majority + * of misspelled requests. + * o Commented out the second pass where files' suffixes are stripped. + * Given the better hit rate of the first pass, this rather ugly + * (request index.html, receive index.db ?!?!) solution can be + * omitted. + * o wrote a "kind of" html page for mod_speling + * + * Activate it with "CheckSpelling On" + */ + +MODULE_VAR_EXPORT module speling_module; + +/* We use the "unconventional" mod_userdir approach here. And heck, + * here it's just one int! + */ + +static void *create_speling_config(pool *dummy, server_rec *s) +{ + return (void *) 0; +} + +static const char *set_speling(cmd_parms *cmd, void *dummy, int arg) +{ + void *server_conf = cmd->server->module_config; + + /* any non-NULL pointer means speling is enabled */ + ap_set_module_config(server_conf, &speling_module, arg ? (void *) &speling_module : NULL); + return NULL; +} + +static const command_rec speling_cmds[] = +{ + {"CheckSpelling", set_speling, NULL, RSRC_CONF, FLAG, + "whether or not to fix miscapitalized/misspelled requests"}, + {NULL} +}; + +typedef enum { + SP_IDENTICAL = 0, + SP_MISCAPITALIZED = 1, + SP_TRANSPOSITION = 2, + SP_MISSINGCHAR = 3, + SP_EXTRACHAR = 4, + SP_SIMPLETYPO = 5, + SP_VERYDIFFERENT = 6 +} sp_reason; + +static const char *sp_reason_str[] = +{ + "identical", + "miscapitalized", + "transposed characters", + "character missing", + "extra character", + "mistyped character", + "common basename", +}; + +typedef struct { + const char *name; + sp_reason quality; +} misspelled_file; + +/* + * spdist() is taken from Kernighan & Pike, + * _The_UNIX_Programming_Environment_ + * and adapted somewhat to correspond better to psychological reality. + * (Note the changes to the return values) + * + * According to Pollock and Zamora, CACM April 1984 (V. 27, No. 4), + * page 363, the correct order for this is: + * OMISSION = TRANSPOSITION > INSERTION > SUBSTITUTION + * thus, it was exactly backwards in the old version. -- PWP + * + * This routine was taken out of tcsh's spelling correction code + * (tcsh-6.07.04) and re-converted to apache data types ("char" type + * instead of tcsh's NLS'ed "Char"). Plus it now ignores the case + * during comparisons, so is a "approximate strcasecmp()". + * NOTE that is still allows only _one_ real "typo", + * it does NOT try to correct multiple errors. + */ + +static sp_reason spdist(const char *s, const char *t) +{ + for (; tolower(*s) == tolower(*t); t++, s++) + if (*t == '\0') + return SP_MISCAPITALIZED; /* exact match (sans case) */ + if (*s) { + if (*t) { + if (s[1] && t[1] && tolower(*s) == tolower(t[1]) && + tolower(*t) == tolower(s[1]) && strcasecmp(s + 2, t + 2) == 0) + return SP_TRANSPOSITION; /* transposition */ + if (strcasecmp(s + 1, t + 1) == 0) + return SP_SIMPLETYPO; /* 1 char mismatch */ + } + if (strcasecmp(s + 1, t) == 0) + return SP_EXTRACHAR; /* extra character */ + } + if (*t && strcasecmp(s, t + 1) == 0) + return SP_MISSINGCHAR; /* missing character */ + return SP_VERYDIFFERENT; /* distance too large to fix. */ +} + +static int sort_by_quality(const void *left, const void *rite) +{ + return (int) (((misspelled_file *) left)->quality) + - (int) (((misspelled_file *) rite)->quality); +} + +static int check_speling(request_rec *r) +{ + void *server_conf = r->server->module_config; + char *good, *bad, *postgood, *url; + int filoc, dotloc, urlen, pglen; + DIR *dirp; + struct DIR_TYPE *dir_entry; + array_header *candidates = NULL; + + if (!ap_get_module_config(server_conf, &speling_module)) + return DECLINED; + + /* We only want to worry about GETs */ + if (r->method_number != M_GET) + return DECLINED; + + /* We've already got a file of some kind or another */ + if (r->proxyreq || (r->finfo.st_mode != 0)) + return DECLINED; + + /* This is a sub request - don't mess with it */ + if (r->main) + return DECLINED; + + /* + * The request should end up looking like this: + * r->uri: /correct-url/mispelling/more + * r->filename: /correct-file/mispelling r->path_info: /more + * + * So we do this in steps. First break r->filename into two pieces + */ + + filoc = ap_rind(r->filename, '/'); + /* Don't do anything if the request doesn't contain a slash, or requests "/" */ + if (filoc == -1 || strcmp(r->uri, "/") == 0) + return DECLINED; + + /* good = /correct-file */ + good = ap_pstrndup(r->pool, r->filename, filoc); + /* bad = mispelling */ + bad = ap_pstrdup(r->pool, r->filename + filoc + 1); + /* postgood = mispelling/more */ + postgood = ap_pstrcat(r->pool, bad, r->path_info, NULL); + + urlen = strlen(r->uri); + pglen = strlen(postgood); + + /* Check to see if the URL pieces add up */ + if (strcmp(postgood, r->uri + (urlen - pglen))) + return DECLINED; + + /* url = /correct-url */ + url = ap_pstrndup(r->pool, r->uri, (urlen - pglen)); + + /* Now open the directory and do ourselves a check... */ + dirp = ap_popendir(r->pool, good); + if (dirp == NULL) /* Oops, not a directory... */ + return DECLINED; + + candidates = ap_make_array(r->pool, 2, sizeof(misspelled_file)); + + dotloc = ap_ind(bad, '.'); + if (dotloc == -1) + dotloc = strlen(bad); + + while ((dir_entry = readdir(dirp)) != NULL) { + sp_reason q; + + /* + * If we end up with a "fixed" URL which is identical to the + * requested one, we must have found a broken symlink or some such. + * Do _not_ try to redirect this, it causes a loop! + */ + if (strcmp(bad, dir_entry->d_name) == 0) { + ap_pclosedir(r->pool, dirp); + return OK; + } + /* + * miscapitalization errors are checked first (like, e.g., lower case + * file, upper case request) + */ + else if (strcasecmp(bad, dir_entry->d_name) == 0) { + misspelled_file *sp_new = (misspelled_file *) ap_push_array(candidates); + sp_new->name = ap_pstrdup(r->pool, dir_entry->d_name); + sp_new->quality = SP_MISCAPITALIZED; + } + /* + * simple typing errors are checked next (like, e.g., + * missing/extra/transposed char) + */ + else if ((q = spdist(bad, dir_entry->d_name)) != SP_VERYDIFFERENT) { + misspelled_file *sp_new = (misspelled_file *) ap_push_array(candidates); + sp_new->name = ap_pstrdup(r->pool, dir_entry->d_name); + sp_new->quality = q; + } + /* The spdist() should have found the majority of the misspelled requests. + * it is of questionable use to continue looking for files with the same + * base name, but potentially of totally wrong type (index.html <-> index.db) + * I would propose to not set the WANT_BASENAME_MATCH define. + * 08-Aug-1997 <Martin.Kraemer@Mch.SNI.De> + * + * However, Alexei replied giving some reasons to add it anyway: + * > Oh, by the way, I remembered why having the + * > extension-stripping-and-matching stuff is a good idea: + * > + * > If you're using MultiViews, and have a file named foobar.html, which you + * > refer to as "foobar", and someone tried to access "Foobar", mod_speling + * > won't find it, because it won't find anything matching that + * > spelling. With the extension-munging, it would locate "foobar.html". Not + * > perfect, but I ran into that problem when I first wrote the module. + */ + else { +#ifdef WANT_BASENAME_MATCH + /* + * Okay... we didn't find anything. Now we take out the hard-core + * power tools. There are several cases here. Someone might have + * entered a wrong extension (.htm instead of .html or vice + * versa) or the document could be negotiated. At any rate, now + * we just compare stuff before the first dot. If it matches, we + * figure we got us a match. This can result in wrong things if + * there are files of different content types but the same prefix + * (e.g. foo.gif and foo.html) This code will pick the first one + * it finds. Better than a Not Found, though. + */ + int entloc = ap_ind(dir_entry->d_name, '.'); + if (entloc == -1) + entloc = strlen(dir_entry->d_name); + + if ((dotloc == entloc) + && !strncasecmp(bad, dir_entry->d_name, dotloc)) { + misspelled_file *sp_new = (misspelled_file *) ap_push_array(candidates); + sp_new->name = ap_pstrdup(r->pool, dir_entry->d_name); + sp_new->quality = SP_VERYDIFFERENT; + } +#endif + } + } + ap_pclosedir(r->pool, dirp); + + if (candidates->nelts != 0) { + /* Wow... we found us a mispelling. Construct a fixed url */ + char *nuri, *ref; + misspelled_file *variant = (misspelled_file *) candidates->elts; + int i; + + ref = ap_table_get(r->headers_in, "Referer"); + + qsort((void *) candidates->elts, candidates->nelts, + sizeof(misspelled_file), sort_by_quality); + + /* + * Conditions for immediate redirection: + * a) the first candidate was not found by stripping the suffix + * AND b) there exists only one candidate OR the best match is not ambigous + * then return a redirection right away. + */ + if (variant[0].quality != SP_VERYDIFFERENT && + (candidates->nelts == 1 || variant[0].quality != variant[1].quality)) { + + nuri = ap_pstrcat(r->pool, url, variant[0].name, + r->path_info, NULL); + + ap_table_setn(r->headers_out, "Location", + ap_construct_url(r->pool, nuri, r)); + + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, r->server, + ref ? "Fixed spelling: %s to %s from %s" + : "Fixed spelling: %s to %s", + r->uri, nuri, ref); + + return HTTP_MOVED_PERMANENTLY; + } + /* + * Otherwise, a "[300] Multiple Choices" list with the variants is + * returned. + */ + else { + char *t; + pool *p; + table *notes; + + if (r->main == NULL) { + p = r->pool; + notes = r->notes; + } + else { + p = r->main->pool; + notes = r->main->notes; + } + + /* Generate the response text. */ + /* Since the text is expanded by repeated calls of + * t = pstrcat(p, t, ".."), we can avoid a little waste + * of memory by adding the header AFTER building the list. + * XXX: FIXME: find a way to build a string concatenation + * without repeatedly requesting new memory + * XXX: FIXME: Limit the list to a maximum number of entries + */ + t = ""; + + for (i = 0; i < candidates->nelts; ++i) { + + /* The format isn't very neat... */ + t = ap_pstrcat(p, t, "<li><a href=\"", url, + variant[i].name, r->path_info, "\">", + variant[i].name, r->path_info, "</a> (", + sp_reason_str[(int) (variant[i].quality)], ")\n", NULL); + + /* + * when we have printed the "close matches" and there are + * more "distant matches" (matched by stripping the suffix), + * then we insert an additional separator text to suggest + * that the user LOOK CLOSELY whether these are really the + * files she wanted. + */ + if (i > 0 && i < candidates->nelts - 1 + && variant[i].quality != SP_VERYDIFFERENT + && variant[i + 1].quality == SP_VERYDIFFERENT) { + t = ap_pstrcat(p, t, "</ul>\nFurthermore, the following related documents were found:\n<ul>\n", NULL); + } + } + t = ap_pstrcat(p, "The document name you requested (<code>", + r->uri, "</code>) could not be found on this server.\n" + "However, we found documents with names similar to the one you requested.<p>" + "Available documents:\n<ul>\n", t, "</ul>\n", NULL); + + /* If we know there was a referring page, add a note: */ + if (ref != NULL) + t = ap_pstrcat(p, t, "Please consider informing the owner of the <a href=\"", + ref, "\">referring page</a> about the broken link.\n", NULL); + + /* Pass our table to http_protocol.c (see mod_negotiation): */ + ap_table_setn(notes, "variant-list", t); + + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, r->server, + ref ? "Spelling fix: %s: %d candidates from %s" + : "Spelling fix: %s: %d candidates", + r->uri, candidates->nelts, ref); + + return HTTP_MULTIPLE_CHOICES; + } + } + + return OK; +} + +module MODULE_VAR_EXPORT speling_module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + create_speling_config, /* server config */ + NULL, /* merge server config */ + speling_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + check_speling, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_status.c b/APACHE_1_3b7/src/modules/standard/mod_status.c new file mode 100644 index 0000000000..d7a6ea5075 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_status.c @@ -0,0 +1,709 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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/>. + * + */ + +/* Status Module. Display lots of internal data about how Apache is + * performing and the state of all children processes. + * + * To enable this, add the following lines into any config file: + * + * <Location /server-status> + * SetHandler server-status + * </Location> + * + * You may want to protect this location by password or domain so no one + * else can look at it. Then you can access the statistics with a URL like: + * + * http://your_server_name/server-status + * + * /server-status - Returns page using tables + * /server-status?notable - Returns page for browsers without table support + * /server-status?refresh - Returns page with 1 second refresh + * /server-status?refresh=6 - Returns page with refresh every 6 seconds + * /server-status?auto - Returns page with data for automatic parsing + * + * Mark Cox, mark@ukweb.com, November 1995 + * + * 12.11.95 Initial version for www.telescope.org + * 13.3.96 Updated to remove rprintf's [Mark] + * 18.3.96 Added CPU usage, process information, and tidied [Ben Laurie] + * 18.3.96 Make extra Scoreboard variables #definable + * 25.3.96 Make short report have full precision [Ben Laurie suggested] + * 25.3.96 Show uptime better [Mark/Ben Laurie] + * 29.3.96 Better HTML and explanation [Mark/Rob Hartill suggested] + * 09.4.96 Added message for non-STATUS compiled version + * 18.4.96 Added per child and per slot counters [Jim Jagielski] + * 01.5.96 Table format, cleanup, even more spiffy data [Chuck Murcko/Jim J.] + * 18.5.96 Adapted to use new rprintf() routine, incidentally fixing a missing + * piece in short reports [Ben Laurie] + * 21.5.96 Additional Status codes (DNS and LOGGING only enabled if + * extended STATUS is enabled) [George Burgyan/Jim J.] + */ + +/* + * Module definition information - the part between the -START and -END + * lines below is used by Configure. This could be stored in a separate + * instead. + * + * MODULE-DEFINITION-START + * Name: status_module + * ConfigStart + if [ "$RULE_STATUS" = "yes" ]; then + CFLAGS="$CFLAGS -DSTATUS" + fi + * ConfigEnd + * MODULE-DEFINITION-END + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_main.h" +#include "util_script.h" +#include <time.h> +#include "scoreboard.h" +#include "http_log.h" + +#ifdef NEXT +#if NX_CURRENT_COMPILER_RELEASE == 410 +#if __ARCHITECTURE__ == m68k +#define HZ 64 +#else +#define HZ 100 +#endif +#else +#include <machine/param.h> +#endif +#endif + +#define STATUS_MAXLINE 64 + +#define KBYTE 1024 +#define MBYTE 1048576L +#define GBYTE 1073741824L + +#ifndef DEFAULT_TIME_FORMAT +#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z" +#endif + +module MODULE_VAR_EXPORT status_module; + +#ifdef STATUS +/* Format the number of bytes nicely */ + +static void format_byte_out(request_rec *r, unsigned long bytes) +{ + if (bytes < (5 * KBYTE)) + ap_rprintf(r, "%d B", (int) bytes); + else if (bytes < (MBYTE / 2)) + ap_rprintf(r, "%.1f kB", (float) bytes / KBYTE); + else if (bytes < (GBYTE / 2)) + ap_rprintf(r, "%.1f MB", (float) bytes / MBYTE); + else + ap_rprintf(r, "%.1f GB", (float) bytes / GBYTE); +} + +static void format_kbyte_out(request_rec *r, unsigned long kbytes) +{ + if (kbytes < KBYTE) + ap_rprintf(r, "%d kB", (int) kbytes); + else if (kbytes < MBYTE) + ap_rprintf(r, "%.1f MB", (float) kbytes / KBYTE); + else + ap_rprintf(r, "%.1f GB", (float) kbytes / MBYTE); +} + +#endif + +static void show_time(request_rec *r, time_t tsecs) +{ + long days, hrs, mins, secs; + + secs = tsecs % 60; + tsecs /= 60; + mins = tsecs % 60; + tsecs /= 60; + hrs = tsecs % 24; + days = tsecs / 24; + if (days) + ap_rprintf(r, " %ld day%s", days, days == 1 ? "" : "s"); + if (hrs) + ap_rprintf(r, " %ld hour%s", hrs, hrs == 1 ? "" : "s"); + if (mins) + ap_rprintf(r, " %ld minute%s", mins, mins == 1 ? "" : "s"); + if (secs) + ap_rprintf(r, " %ld second%s", secs, secs == 1 ? "" : "s"); +} + +/* Main handler for x-httpd-status requests */ + +/* ID values for command table */ + +#define STAT_OPT_END -1 +#define STAT_OPT_REFRESH 0 +#define STAT_OPT_NOTABLE 1 +#define STAT_OPT_AUTO 2 + +struct stat_opt { + int id; + const char *form_data_str; + const char *hdr_out_str; +}; + +static const struct stat_opt status_options[] = /* see #defines above */ +{ + {STAT_OPT_REFRESH, "refresh", "Refresh"}, + {STAT_OPT_NOTABLE, "notable", NULL}, + {STAT_OPT_AUTO, "auto", NULL}, + {STAT_OPT_END, NULL, NULL} +}; + +static char status_flags[SERVER_NUM_STATUS]; + +static int status_handler(request_rec *r) +{ + char *loc; + time_t nowtime = time(NULL); + time_t up_time; + int i, res; + int ready = 0; + int busy = 0; +#if defined(STATUS) + unsigned long count = 0; + unsigned long lres, bytes; + unsigned long my_lres, my_bytes, conn_bytes; + unsigned short conn_lres; + unsigned long bcount = 0; + unsigned long kbcount = 0; + long req_time; +#if defined(NEXT) + float tick = HZ; +#elif !defined(WIN32) + float tick = sysconf(_SC_CLK_TCK); +#endif +#endif /* STATUS */ + int short_report = 0; + int no_table_report = 0; + short_score score_record; + parent_score ps_record; + char stat_buffer[HARD_SERVER_LIMIT]; + clock_t tu, ts, tcu, tcs; + + tu = ts = tcu = tcs = 0; + + if (!ap_exists_scoreboard_image()) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + "Server status unavailable in inetd mode"); + return HTTP_INTERNAL_SERVER_ERROR; + } + r->allowed = (1 << M_GET); + if (r->method_number != M_GET) + return DECLINED; + + r->content_type = "text/html"; + + /* + * Simple table-driven form data set parser that lets you alter the header + */ + + if (r->args) { + i = 0; + while (status_options[i].id != STAT_OPT_END) { + if ((loc = strstr(r->args, status_options[i].form_data_str)) != NULL) { + switch (status_options[i].id) { + case STAT_OPT_REFRESH: + if (*(loc + strlen(status_options[i].form_data_str)) == '=') + ap_table_set(r->headers_out, status_options[i].hdr_out_str, + loc + strlen(status_options[i].hdr_out_str) + 1); + else + ap_table_set(r->headers_out, status_options[i].hdr_out_str, "1"); + break; + case STAT_OPT_NOTABLE: + no_table_report = 1; + break; + case STAT_OPT_AUTO: + r->content_type = "text/plain"; + short_report = 1; + break; + } + } + i++; + } + } + + ap_send_http_header(r); + + if (r->header_only) + return 0; + + ap_sync_scoreboard_image(); + for (i = 0; i < HARD_SERVER_LIMIT; ++i) { + score_record = ap_scoreboard_image->servers[i]; + ps_record = ap_scoreboard_image->parent[i]; + res = score_record.status; + stat_buffer[i] = status_flags[res]; + if (res == SERVER_READY) + ready++; + else if (res != SERVER_DEAD) + busy++; +#if defined(STATUS) + lres = score_record.access_count; + bytes = score_record.bytes_served; + if (lres != 0 || (res != SERVER_READY && res != SERVER_DEAD)) { +#ifndef NO_TIMES + tu += score_record.times.tms_utime; + ts += score_record.times.tms_stime; + tcu += score_record.times.tms_cutime; + tcs += score_record.times.tms_cstime; +#endif /* NO_TIMES */ + count += lres; + bcount += bytes; + if (bcount >= KBYTE) { + kbcount += (bcount >> 10); + bcount = bcount & 0x3ff; + } + } +#endif /* STATUS */ + } + + up_time = nowtime - ap_restart_time; + + ap_hard_timeout("send status info", r); + + if (!short_report) { + ap_rputs("<HTML><HEAD>\n<TITLE>Apache Status\n\n", r); + ap_rputs("

    Apache Server Status for ", r); + ap_rvputs(r, ap_get_server_name(r), "

    \n\n", NULL); + ap_rvputs(r, "Server Version: ", ap_get_server_version(), "
    \n", + NULL); + ap_rvputs(r, "Server Built: ", ap_get_server_built(), "
    \n
    \n", + NULL); + ap_rvputs(r, "Current Time: ", ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), + "
    \n", NULL); + ap_rvputs(r, "Restart Time: ", ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0), + "
    \n", NULL); + ap_rputs("Server uptime: ", r); + show_time(r, up_time); + ap_rputs("
    \n", r); + } + +#if defined(STATUS) + if (short_report) { + ap_rprintf(r, "Total Accesses: %lu\nTotal kBytes: %lu\n", count, kbcount); + +#ifndef NO_TIMES + /* Allow for OS/2 not having CPU stats */ + if (ts || tu || tcu || tcs) + ap_rprintf(r, "CPULoad: %g\n", (tu + ts + tcu + tcs) / tick / up_time * 100.); +#endif + + ap_rprintf(r, "Uptime: %ld\n", (long) (up_time)); + if (up_time > 0) + ap_rprintf(r, "ReqPerSec: %g\n", (float) count / (float) up_time); + + if (up_time > 0) + ap_rprintf(r, "BytesPerSec: %g\n", KBYTE * (float) kbcount / (float) up_time); + + if (count > 0) + ap_rprintf(r, "BytesPerReq: %g\n", KBYTE * (float) kbcount / (float) count); + } + else { /* !short_report */ + ap_rprintf(r, "Total accesses: %lu - Total Traffic: ", count); + format_kbyte_out(r, kbcount); + +#ifndef NO_TIMES + /* Allow for OS/2 not having CPU stats */ + ap_rputs("
    \n", r); + ap_rprintf(r, "CPU Usage: u%g s%g cu%g cs%g", + tu / tick, ts / tick, tcu / tick, tcs / tick); + + if (ts || tu || tcu || tcs) + ap_rprintf(r, " - %.3g%% CPU load", (tu + ts + tcu + tcs) / tick / up_time * 100.); +#endif + + ap_rputs("
    \n", r); + + if (up_time > 0) + ap_rprintf(r, "%.3g requests/sec - ", + (float) count / (float) up_time); + + if (up_time > 0) { + format_byte_out(r, KBYTE * (float) kbcount / (float) up_time); + ap_rputs("/second - ", r); + } + + if (count > 0) { + format_byte_out(r, KBYTE * (float) kbcount / (float) count); + ap_rputs("/request", r); + } + + ap_rputs("
    \n", r); + } /* short_report */ +#endif /* STATUS */ + + if (!short_report) + ap_rprintf(r, "\n%d requests currently being processed, %d idle servers\n" + ,busy, ready); + else + ap_rprintf(r, "BusyServers: %d\nIdleServers: %d\n", busy, ready); + + /* send the scoreboard 'table' out */ + + if (!short_report) + ap_rputs("
    ", r);
    +    else
    +	ap_rputs("Scoreboard: ", r);
    +
    +    for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
    +	ap_rputc(stat_buffer[i], r);
    +	if ((i % STATUS_MAXLINE == (STATUS_MAXLINE - 1)) && !short_report)
    +	    ap_rputs("\n", r);
    +    }
    +
    +    if (short_report)
    +	ap_rputs("\n", r);
    +    else {
    +	ap_rputs("
    \n", r); + ap_rputs("Scoreboard Key:
    \n", r); + ap_rputs("\"_\" Waiting for Connection, \n", r); + ap_rputs("\"S\" Starting up, \n", r); + ap_rputs("\"R\" Reading Request,
    \n", r); + ap_rputs("\"W\" Sending Reply, \n", r); + ap_rputs("\"K\" Keepalive (read), \n", r); + ap_rputs("\"D\" DNS Lookup,
    \n", r); + ap_rputs("\"L\" Logging, \n", r); + ap_rputs("\"G\" Gracefully finishing, \n", r); + ap_rputs("\".\" Open slot with no current process

    \n", r); + } + +#if defined(STATUS) + if (!short_report) { + if (no_table_report) + ap_rputs("


    Server Details

    \n\n", r); + else +#ifdef NO_TIMES + /* Allow for OS/2 not having CPU stats */ + ap_rputs("

    \n\n\n\n", r); +#else + ap_rputs("

    \n\n

    SrvPIDAccM\nSSReqConnChildSlotHostVHostRequest
    \n\n", r); +#endif + } + + for (i = 0; i < HARD_SERVER_LIMIT; ++i) { + score_record = ap_scoreboard_image->servers[i]; + ps_record = ap_scoreboard_image->parent[i]; + +#if defined(NO_GETTIMEOFDAY) +#ifndef NO_TIMES + if (score_record.start_time == (clock_t) 0) +#endif /* NO_TIMES */ + req_time = 0L; +#ifndef NO_TIMES + else { + req_time = score_record.stop_time - score_record.start_time; + req_time = (req_time * 1000) / (int) tick; + } +#endif /* NO_TIMES */ +#else + if (score_record.start_time.tv_sec == 0L && + score_record.start_time.tv_usec == 0L) + req_time = 0L; + else + req_time = + ((score_record.stop_time.tv_sec - score_record.start_time.tv_sec) * 1000) + + ((score_record.stop_time.tv_usec - score_record.start_time.tv_usec) / 1000); +#endif + if (req_time < 0L) + req_time = 0L; + + lres = score_record.access_count; + my_lres = score_record.my_access_count; + conn_lres = score_record.conn_count; + bytes = score_record.bytes_served; + my_bytes = score_record.my_bytes_served; + conn_bytes = score_record.conn_bytes; + if (lres != 0 || (score_record.status != SERVER_READY + && score_record.status != SERVER_DEAD)) { + if (!short_report) { + if (no_table_report) { + if (score_record.status == SERVER_DEAD) + ap_rprintf(r, "Server %d (-): %d|%lu|%lu [", + i, (int) conn_lres, my_lres, lres); + else + ap_rprintf(r, "Server %d (%d): %d|%lu|%lu [", + i, (int) ps_record.pid, (int) conn_lres, my_lres, lres); + + switch (score_record.status) { + case SERVER_READY: + ap_rputs("Ready", r); + break; + case SERVER_STARTING: + ap_rputs("Starting", r); + break; + case SERVER_BUSY_READ: + ap_rputs("Read", r); + break; + case SERVER_BUSY_WRITE: + ap_rputs("Write", r); + break; + case SERVER_BUSY_KEEPALIVE: + ap_rputs("Keepalive", r); + break; + case SERVER_BUSY_LOG: + ap_rputs("Logging", r); + break; + case SERVER_BUSY_DNS: + ap_rputs("DNS lookup", r); + break; + case SERVER_DEAD: + ap_rputs("Dead", r); + break; + case SERVER_GRACEFUL: + ap_rputs("Graceful", r); + break; + default: + ap_rputs("?STATE?", r); + break; + } +#ifdef NO_TIMES + /* Allow for OS/2 not having CPU stats */ + ap_rprintf(r, "]\n %.0f %ld (", +#else + + ap_rprintf(r, "] u%g s%g cu%g cs%g\n %.0f %ld (", + score_record.times.tms_utime / tick, + score_record.times.tms_stime / tick, + score_record.times.tms_cutime / tick, + score_record.times.tms_cstime / tick, +#endif +#ifdef OPTIMIZE_TIMEOUTS + difftime(nowtime, ps_record.last_rtime), +#else + difftime(nowtime, score_record.last_used), +#endif + (long) req_time); + format_byte_out(r, conn_bytes); + ap_rputs("|", r); + format_byte_out(r, my_bytes); + ap_rputs("|", r); + format_byte_out(r, bytes); + ap_rputs(")\n", r); + ap_rprintf(r, " %s {%s}
    \n\n", + score_record.client, + ap_escape_html(r->pool, score_record.request)); + } + else { /* !no_table_report */ + if (score_record.status == SERVER_DEAD) + ap_rprintf(r, "\n\n", + score_record.client, score_record.vhost, + ap_escape_html(r->pool, score_record.request)); + } /* no_table_report */ + } /* !short_report */ + } /* if () */ + } /* for () */ + + if (!(short_report || no_table_report)) { +#ifdef __EMX__ + ap_rputs("
    SrvPIDAccMCPU\nSSReqConnChildSlotHostVHostRequest
    %d-%d/%lu/%lu", + i, (int) conn_lres, my_lres, lres); + else + ap_rprintf(r, "
    %d%d%d/%lu/%lu", + i, (int) ps_record.pid, (int) conn_lres, my_lres, lres); + + switch (score_record.status) { + case SERVER_READY: + ap_rputs("_", r); + break; + case SERVER_STARTING: + ap_rputs("S", r); + break; + case SERVER_BUSY_READ: + ap_rputs("R", r); + break; + case SERVER_BUSY_WRITE: + ap_rputs("W", r); + break; + case SERVER_BUSY_KEEPALIVE: + ap_rputs("K", r); + break; + case SERVER_BUSY_LOG: + ap_rputs("L", r); + break; + case SERVER_BUSY_DNS: + ap_rputs("D", r); + break; + case SERVER_DEAD: + ap_rputs(".", r); + break; + case SERVER_GRACEFUL: + ap_rputs("G", r); + break; + default: + ap_rputs("?", r); + break; + } +#ifdef NO_TIMES + /* Allow for OS/2 not having CPU stats */ + ap_rprintf(r, "\n%.0f%ld", +#else + ap_rprintf(r, "\n%.2f%.0f%ld", + (score_record.times.tms_utime + + score_record.times.tms_stime + + score_record.times.tms_cutime + + score_record.times.tms_cstime) / tick, +#endif +#ifdef OPTIMIZE_TIMEOUTS + difftime(nowtime, ps_record.last_rtime), +#else + difftime(nowtime, score_record.last_used), +#endif + (long) req_time); + ap_rprintf(r, "%-1.1f%-2.2f%-2.2f\n", + (float) conn_bytes / KBYTE, (float) my_bytes / MBYTE, + (float) bytes / MBYTE); + ap_rprintf(r, "%s%s%s
    \n \ +


    \ +\n \ +
    SrvServer number\n \ +
    PIDOS process ID\n \ +
    AccNumber of accesses this connection / this child / this slot\n \ +
    MMode of operation\n \ +
    SSSeconds since beginning of most recent request\n \ +
    ReqMilliseconds required to process most recent request\n \ +
    ConnKilobytes transferred this connection\n \ +
    ChildMegabytes transferred this child\n \ +
    SlotTotal megabytes transferred this slot\n \ +
    \n", r); +#else + ap_rputs("\n \ +
    \ +\n \ +
    SrvServer number\n \ +
    PIDOS process ID\n \ +
    AccNumber of accesses this connection / this child / this slot\n \ +
    MMode of operation\n \ +
    CPUCPU usage, number of seconds\n \ +
    SSSeconds since beginning of most recent request\n \ +
    ReqMilliseconds required to process most recent request\n \ +
    ConnKilobytes transferred this connection\n \ +
    ChildMegabytes transferred this child\n \ +
    SlotTotal megabytes transferred this slot\n \ +
    \n", r); +#endif + } + +#else /* !defined(STATUS) */ + + ap_rputs("
    To obtain a full report with current status information and", r); + ap_rputs(" DNS and LOGGING status codes \n", r); + ap_rputs("you need to recompile Apache after adding the line
    ", r);
    +    ap_rputs("Rule STATUS=yes
    into the file Configuration\n", r); + +#endif /* STATUS */ + + if (!short_report) { + ap_rputs(ap_psignature("
    \n",r), r); + ap_rputs("\n", r); + } + + ap_kill_timeout(r); + return 0; +} + + +static void status_init(server_rec *s, pool *p) +{ + status_flags[SERVER_DEAD] = '.'; /* We don't want to assume these are in */ + status_flags[SERVER_READY] = '_'; /* any particular order in scoreboard.h */ + status_flags[SERVER_STARTING] = 'S'; + status_flags[SERVER_BUSY_READ] = 'R'; + status_flags[SERVER_BUSY_WRITE] = 'W'; + status_flags[SERVER_BUSY_KEEPALIVE] = 'K'; + status_flags[SERVER_BUSY_LOG] = 'L'; + status_flags[SERVER_BUSY_DNS] = 'D'; + status_flags[SERVER_GRACEFUL] = 'G'; +} + +static const handler_rec status_handlers[] = +{ + {STATUS_MAGIC_TYPE, status_handler}, + {"server-status", status_handler}, + {NULL} +}; + +module MODULE_VAR_EXPORT status_module = +{ + STANDARD_MODULE_STUFF, + status_init, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + NULL, /* command table */ + status_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_unique_id.c b/APACHE_1_3b7/src/modules/standard/mod_unique_id.c new file mode 100644 index 0000000000..e26add7cab --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_unique_id.c @@ -0,0 +1,357 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * mod_unique_id.c: generate a unique identifier for each request + * + * Original author: Dean Gaudet + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include "multithread.h" + +#ifdef MULTITHREAD +#error sorry this module does not support multithreaded servers yet +#endif + +typedef struct { + time_t stamp; + unsigned int in_addr; + unsigned int pid; + unsigned short counter; +} unique_id_rec; + +/* Comments: + * + * We want an identifier which is unique across all hits, everywhere. + * "everywhere" includes multiple httpd instances on the same machine, or on + * multiple machines. Essentially "everywhere" should include all possible + * httpds across all servers at a particular "site". We make some assumptions + * that if the site has a cluster of machines then their time is relatively + * synchronized. We also assume that the first address returned by a + * gethostbyname (gethostname()) is unique across all the machines at the + * "site". + * + * We also further assume that pids fit in 32-bits. If something uses more + * than 32-bits, the fix is trivial, but it requires the unrolled uuencoding + * loop to be extended. * A similar fix is needed to support multithreaded + * servers, using a pid/tid combo. + * + * Together, the in_addr and pid are assumed to absolutely uniquely identify + * this one child from all other currently running children on all servers + * (including this physical server if it is running multiple httpds) from each + * other. + * + * The stamp and counter are used to distinguish all hits for a particular + * (in_addr,pid) pair. The stamp is updated using r->request_time, + * saving cpu cycles. The counter is never reset, and is used to permit up to + * 64k requests in a single second by a single child. + * + * The 112-bits of unique_id_rec are uuencoded using the alphabet + * [A-Za-z0-9@-], resulting in 19 bytes of printable characters. That is then + * stuffed into the environment variable UNIQUE_ID so that it is available to + * other modules. The alphabet choice differs from normal base64 encoding + * [A-Za-z0-9+/] because + and / are special characters in URLs and we want to + * make it easy to use UNIQUE_ID in URLs. + * + * Note that UNIQUE_ID should be considered an opaque token by other + * applications. No attempt should be made to dissect its internal components. + * It is an abstraction that may change in the future as the needs of this + * module change. + * + * It is highly desirable that identifiers exist for "eternity". But future + * needs (such as much faster webservers, moving to 64-bit pids, or moving to a + * multithreaded server) may dictate a need to change the contents of + * unique_id_rec. Such a future implementation should ensure that the first + * field is still a time_t stamp. By doing that, it is possible for a site to + * have a "flag second" in which they stop all of their old-format servers, + * wait one entire second, and then start all of their new-servers. This + * procedure will ensure that the new space of identifiers is completely unique + * from the old space. (Since the first four unencoded bytes always differ.) + */ + +static unsigned global_in_addr; + +static APACHE_TLS unique_id_rec cur_unique_id; + +static void unique_id_global_init(server_rec *s, pool *p) +{ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + char str[MAXHOSTNAMELEN + 1]; + struct hostent *hent; +#ifndef NO_GETTIMEOFDAY + struct timeval tv; +#endif + + /* + * First of all, verify some assumptions that have been made about the + * contents of unique_id_rec. We do it this way because it isn't + * affected by trailing padding. + */ + if (XtOffsetOf(unique_id_rec, counter) + sizeof(cur_unique_id.counter) + != 14) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s, + "mod_unique_id: sorry the size assumptions are wrong " + "in mod_unique_id.c, please remove it from your server " + "or fix the code!"); + exit(1); + } + + /* + * Now get the global in_addr. Note that it is not sufficient to use one + * of the addresses from the main_server, since those aren't as likely to + * be unique as the physical address of the machine + */ + if (gethostname(str, sizeof(str) - 1) != 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s, + "gethostname: mod_unique_id requires the hostname of the server"); + exit(1); + } + str[sizeof(str) - 1] = '\0'; + + if ((hent = gethostbyname(str)) == NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s, + "mod_unique_id: unable to gethostbyname(\"%s\")", str); + exit(1); + } + + global_in_addr = ((struct in_addr *) hent->h_addr_list[0])->s_addr; + + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s, + "mod_unique_id: using ip addr %s", + inet_ntoa(*(struct in_addr *) hent->h_addr_list[0])); + + /* + * If the server is pummelled with restart requests we could possibly end + * up in a situation where we're starting again during the same second + * that has been used in previous identifiers. Avoid that situation. + * + * In truth, for this to actually happen not only would it have to restart + * in the same second, but it would have to somehow get the same pids as + * one of the other servers that was running in that second. Which would + * mean a 64k wraparound on pids ... not very likely at all. + * + * But protecting against it is relatively cheap. We just sleep into the + * next second. + */ +#ifdef NO_GETTIMEOFDAY + sleep(1); +#else + if (gettimeofday(&tv, NULL) == -1) { + sleep(1); + } + else if (tv.tv_usec) { + tv.tv_sec = 0; + tv.tv_usec = 1000000 - tv.tv_usec; + select(0, NULL, NULL, NULL, &tv); + } +#endif +} + +static void unique_id_child_init(server_rec *s, pool *p) +{ + pid_t pid; +#ifndef NO_GETTIMEOFDAY + struct timeval tv; +#endif + + /* + * Note that we use the pid because it's possible that on the same + * physical machine there are multiple servers (i.e. using Listen). But + * it's guaranteed that none of them will share the same pids between + * children. + * + * XXX: for multithread this needs to use a pid/tid combo and probably + * needs to be expanded to 32 bits + */ + pid = getpid(); + cur_unique_id.pid = pid; + + /* + * Test our assumption that the pid is 32-bits. It's possible that + * 64-bit machines will declare pid_t to be 64 bits but only use 32 + * of them. It would have been really nice to test this during + * global_init ... but oh well. + */ + if (cur_unique_id.pid != pid) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, + "oh no! pids are greater than 32-bits! I'm broken!"); + } + + cur_unique_id.in_addr = global_in_addr; + + /* + * If we use 0 as the initial counter we have a little less protection + * against restart problems, and a little less protection against a clock + * going backwards in time. + */ +#ifndef NO_GETTIMEOFDAY + if (gettimeofday(&tv, NULL) == -1) { + cur_unique_id.counter = 0; + } + else { + /* Some systems have very low variance on the low end of their + * system counter, defend against that. + */ + cur_unique_id.counter = tv.tv_usec / 10; + } +#else + cur_unique_id.counter = 0; +#endif + + /* + * We must always use network ordering for these bytes, so that + * identifiers are comparable between machines of different byte + * orderings. Note in_addr is already in network order. + */ + cur_unique_id.pid = htons(cur_unique_id.pid); + cur_unique_id.counter = htons(cur_unique_id.counter); +} + +/* NOTE: This is *NOT* the same encoding used by uuencode ... the last two + * characters should be + and /. But those two characters have very special + * meanings in URLs, and we want to make it easy to use identifiers in + * URLs. So we replace them with @ and -. + */ +static const char uuencoder[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '@', '-', +}; + +static int gen_unique_id(request_rec *r) +{ + /* when we uuencode it will take 19 bytes plus \0 */ + char str[19 + 1]; + const unsigned char *x; + unsigned short counter; + char *e; + + /* copy the unique_id if this is an internal redirect (we're never + * actually called for sub requests, so we don't need to test for + * them) */ + if (r->prev && (e = ap_table_get(r->subprocess_env, "REDIRECT_UNIQUE_ID"))) { + ap_table_setn(r->subprocess_env, "UNIQUE_ID", e); + return DECLINED; + } + + cur_unique_id.stamp = htonl(r->request_time); + + /* do the uuencoding */ + x = (const unsigned char *) &cur_unique_id; + str[0] = uuencoder[x[0] >> 2]; + str[1] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)]; + str[2] = uuencoder[((x[1] & 0x0f) << 2) | ((x[2] & 0xc0) >> 6)]; + str[3] = uuencoder[x[2] & 0x3f]; + x += 3; + str[4] = uuencoder[x[0] >> 2]; + str[5] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)]; + str[6] = uuencoder[((x[1] & 0x0f) << 2) | ((x[2] & 0xc0) >> 6)]; + str[7] = uuencoder[x[2] & 0x3f]; + x += 3; + str[8] = uuencoder[x[0] >> 2]; + str[9] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)]; + str[10] = uuencoder[((x[1] & 0x0f) << 2) | ((x[2] & 0xc0) >> 6)]; + str[11] = uuencoder[x[2] & 0x3f]; + x += 3; + str[12] = uuencoder[x[0] >> 2]; + str[13] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)]; + str[14] = uuencoder[((x[1] & 0x0f) << 2) | ((x[2] & 0xc0) >> 6)]; + str[15] = uuencoder[x[2] & 0x3f]; + x += 3; + str[16] = uuencoder[x[0] >> 2]; + str[17] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)]; + str[18] = uuencoder[((x[1] & 0x0f) << 2) | ((0 & 0xc0) >> 6)]; + str[19] = '\0'; + + ap_table_setn(r->subprocess_env, "UNIQUE_ID", ap_pstrdup(r->pool, str)); + + /* and increment the identifier for the next call */ + counter = ntohs(cur_unique_id.counter) + 1; + cur_unique_id.counter = htons(counter); + + return DECLINED; +} + + +module MODULE_VAR_EXPORT unique_id_module = { + STANDARD_MODULE_STUFF, + unique_id_global_init, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server configs */ + NULL, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + unique_id_child_init, /* child_init */ + NULL, /* child_exit */ + gen_unique_id /* post_read_request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_userdir.c b/APACHE_1_3b7/src/modules/standard/mod_userdir.c new file mode 100644 index 0000000000..92d2cfa92b --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_userdir.c @@ -0,0 +1,349 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * mod_userdir... implement the UserDir command. Broken away from the + * Alias stuff for a couple of good and not-so-good reasons: + * + * 1) It shows a real minimal working example of how to do something like + * this. + * 2) I know people who are actually interested in changing this *particular* + * aspect of server functionality without changing the rest of it. That's + * what this whole modular arrangement is supposed to be good at... + * + * Modified by Alexei Kosut to support the following constructs + * (server running at www.foo.com, request for /~bar/one/two.html) + * + * UserDir public_html -> ~bar/public_html/one/two.html + * UserDir /usr/web -> /usr/web/bar/one/two.html + * UserDir /home/ * /www -> /home/bar/www/one/two.html + * NOTE: theses ^ ^ space only added allow it to work in a comment, ignore + * UserDir http://x/users -> (302) http://x/users/bar/one/two.html + * UserDir http://x/ * /y -> (302) http://x/bar/y/one/two.html + * NOTE: here also ^ ^ + * + * In addition, you can use multiple entries, to specify alternate + * user directories (a la Directory Index). For example: + * + * UserDir public_html /usr/web http://www.xyz.com/users + * + * Modified by Ken Coar to provide for the following: + * + * UserDir disable[d] username ... + * UserDir enable[d] username ... + * + * If "disabled" has no other arguments, *all* ~ references are + * disabled, except those explicitly turned on with the "enabled" keyword. + */ + +#include "httpd.h" +#include "http_config.h" + +module userdir_module; + +typedef struct userdir_config { + int globally_disabled; + char *userdir; + table *enabled_users; + table *disabled_users; +} userdir_config; + +/* + * Server config for this module: global disablement flag, a list of usernames + * ineligible for UserDir access, a list of those immune to global (but not + * explicit) disablement, and the replacement string for all others. + */ + +static void *create_userdir_config(pool *p, server_rec *s) +{ + userdir_config + * newcfg = (userdir_config *) ap_pcalloc(p, sizeof(userdir_config)); + + newcfg->globally_disabled = 0; + newcfg->userdir = DEFAULT_USER_DIR; + newcfg->enabled_users = ap_make_table(p, 4); + newcfg->disabled_users = ap_make_table(p, 4); + return (void *) newcfg; +} + +#define O_DEFAULT 0 +#define O_ENABLE 1 +#define O_DISABLE 2 + +static const char *set_user_dir(cmd_parms *cmd, void *dummy, char *arg) +{ + userdir_config + * s_cfg = (userdir_config *) ap_get_module_config + ( + cmd->server->module_config, + &userdir_module + ); + char *username; + const char + *usernames = arg; + char *kw = ap_getword_conf(cmd->pool, &usernames); + table *usertable; + + /* + * Let's do the comparisons once. + */ + if ((!strcasecmp(kw, "disable")) || (!strcasecmp(kw, "disabled"))) { + /* + * If there are no usernames specified, this is a global disable - we + * need do no more at this point than record the fact. + */ + if (strlen(usernames) == 0) { + s_cfg->globally_disabled = 1; + return NULL; + } + usertable = s_cfg->disabled_users; + } + else if ((!strcasecmp(kw, "enable")) || (!strcasecmp(kw, "enabled"))) { + /* + * The "disable" keyword can stand alone or take a list of names, but + * the "enable" keyword requires the list. Whinge if it doesn't have + * it. + */ + if (strlen(usernames) == 0) { + return "UserDir \"enable\" keyword requires a list of usernames"; + } + usertable = s_cfg->enabled_users; + } + else { + /* + * If the first (only?) value isn't one of our keywords, just copy + * the string to the userdir string. + */ + s_cfg->userdir = ap_pstrdup(cmd->pool, arg); + return NULL; + } + /* + * Now we just take each word in turn from the command line and add it to + * the appropriate table. + */ + while (*usernames) { + username = ap_getword_conf(cmd->pool, &usernames); + ap_table_setn(usertable, username, kw); + } + return NULL; +} + +static const command_rec userdir_cmds[] = { + {"UserDir", set_user_dir, NULL, RSRC_CONF, RAW_ARGS, + "the public subdirectory in users' home directories, or 'disabled', or 'disabled username username...', or 'enabled username username...'"}, + {NULL} +}; + +static int translate_userdir(request_rec *r) +{ + void *server_conf = r->server->module_config; + const userdir_config *s_cfg = + (userdir_config *) ap_get_module_config(server_conf, &userdir_module); + char *name = r->uri; + const char *userdirs = s_cfg->userdir; + const char *w, *dname; + char *redirect; + char *x = NULL; + struct stat statbuf; + + /* + * If the URI doesn't match our basic pattern, we've nothing to do with + * it. + */ + if ( + (s_cfg->userdir == NULL) || + (name[0] != '/') || + (name[1] != '~') + ) { + return DECLINED; + } + + dname = name + 2; + w = ap_getword(r->pool, &dname, '/'); + + /* + * The 'dname' funny business involves backing it up to capture the '/' + * delimiting the "/~user" part from the rest of the URL, in case there + * was one (the case where there wasn't being just "GET /~user HTTP/1.0", + * for which we don't want to tack on a '/' onto the filename). + */ + + if (dname[-1] == '/') { + --dname; + } + + /* + * If there's no username, it's not for us. Ignore . and .. as well. + */ + if (w[0] == '\0' || (w[1] == '.' && (w[2] == '\0' || (w[2] == '.' && w[3] == '\0')))) { + return DECLINED; + } + /* + * Nor if there's an username but it's in the disabled list. + */ + if (ap_table_get(s_cfg->disabled_users, w) != NULL) { + return DECLINED; + } + /* + * If there's a global interdiction on UserDirs, check to see if this + * name is one of the Blessed. + */ + if ( + s_cfg->globally_disabled && + (ap_table_get(s_cfg->enabled_users, w) == NULL) + ) { + return DECLINED; + } + + /* + * Special cases all checked, onward to normal substitution processing. + */ + + while (*userdirs) { + const char *userdir = ap_getword_conf(r->pool, &userdirs); + char *filename = NULL; + + if (strchr(userdir, '*')) + x = ap_getword(r->pool, &userdir, '*'); + + if (userdir[0] == '\0' || ap_os_is_path_absolute(userdir)) { + if (x) { +#ifdef WIN32 + /* + * Crummy hack. Need to figure out whether we have been + * redirected to a URL or to a file on some drive. Since I + * know of no protocols that are a single letter, if the : is + * the second character, I will assume a file was specified + */ + if (strchr(x + 2, ':')) +#else + if (strchr(x, ':')) +#endif /* WIN32 */ + { + redirect = ap_pstrcat(r->pool, x, w, userdir, dname, NULL); + ap_table_setn(r->headers_out, "Location", redirect); + return REDIRECT; + } + else + filename = ap_pstrcat(r->pool, x, w, userdir, NULL); + } + else + filename = ap_pstrcat(r->pool, userdir, "/", w, NULL); + } + else if (strchr(userdir, ':')) { + redirect = ap_pstrcat(r->pool, userdir, "/", w, dname, NULL); + ap_table_setn(r->headers_out, "Location", redirect); + return REDIRECT; + } + else { +#ifdef WIN32 + /* Need to figure out home dirs on NT */ + return DECLINED; +#else /* WIN32 */ + struct passwd *pw; + if ((pw = getpwnam(w))) { +#ifdef __EMX__ + /* Need to manually add user name for OS/2 */ + filename = ap_pstrcat(r->pool, pw->pw_dir, w, "/", userdir, NULL); +#else + filename = ap_pstrcat(r->pool, pw->pw_dir, "/", userdir, NULL); +#endif + } +#endif /* WIN32 */ + } + + /* + * Now see if it exists, or we're at the last entry. If we are at the + * last entry, then use the filename generated (if there is one) + * anyway, in the hope that some handler might handle it. This can be + * used, for example, to run a CGI script for the user. + */ + if (filename && (!*userdirs || stat(filename, &statbuf) != -1)) { + r->filename = ap_pstrcat(r->pool, filename, dname, NULL); + /* when statbuf contains info on r->filename we can save a syscall + * by copying it to r->finfo + */ + if (*userdirs && dname[0] == 0) + r->finfo = statbuf; + return OK; + } + } + + return DECLINED; +} + +module userdir_module = { + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + create_userdir_config, /* server config */ + NULL, /* merge server config */ + userdir_cmds, /* command table */ + NULL, /* handlers */ + translate_userdir, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/standard/mod_usertrack.c b/APACHE_1_3b7/src/modules/standard/mod_usertrack.c new file mode 100644 index 0000000000..55daeb0c48 --- /dev/null +++ b/APACHE_1_3b7/src/modules/standard/mod_usertrack.c @@ -0,0 +1,350 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* User Tracking Module (Was mod_cookies.c) + * + * This Apache module is designed to track users paths through a site. + * It uses the client-side state ("Cookie") protocol developed by Netscape. + * It is known to work on Netscape browsers, Microsoft Internet + * Explorer and others currently being developed. + * + * Each time a page is requested we look to see if the browser is sending + * us a Cookie: header that we previously generated. + * + * If we don't find one then the user hasn't been to this site since + * starting their browser or their browser doesn't support cookies. So + * we generate a unique Cookie for the transaction and send it back to + * the browser (via a "Set-Cookie" header) + * Future requests from the same browser should keep the same Cookie line. + * + * By matching up all the requests with the same cookie you can + * work out exactly what path a user took through your site. To log + * the cookie use the " %{Cookie}n " directive in a custom access log; + * + * Example 1 : If you currently use the standard Log file format (CLF) + * and use the command "TransferLog somefilename", add the line + * LogFormat "%h %l %u %t \"%r\" %s %b %{Cookie}n" + * to your config file. + * + * Example 2 : If you used to use the old "CookieLog" directive, you + * can emulate it by adding the following command to your config file + * CustomLog filename "%{Cookie}n \"%r\" %t" + * + * Notes: + * 1. This code now logs the initial transaction (the one that created + * the cookie to start with). + * 2. This module has been designed to not interfere with other Cookies + * your site may be using; just avoid sending out cookies with + * the name "Apache=" or things will get confused. + * 3. If you want you can modify the Set-Cookie line so that the Cookie + * never expires. You would then get the same Cookie each time the + * user revisits your site. + * + * Mark Cox, mark@ukweb.com, 6 July 95 + * + * This file replaces mod_cookies.c + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#if !defined(WIN32) && !defined(MPE) +#include +#endif + +module MODULE_VAR_EXPORT usertrack_module; + +typedef struct { + int always; + time_t expires; +} cookie_log_state; + +/* Define this to allow post-2000 cookies. Cookies use two-digit dates, + * so it might be dicey. (Netscape does it correctly, but others may not) + */ +#define MILLENIAL_COOKIES + +/* Make Cookie: Now we have to generate something that is going to be + * pretty unique. We can base it on the pid, time, hostip */ + +#define COOKIE_NAME "Apache=" + +static void make_cookie(request_rec *r) +{ + cookie_log_state *cls = ap_get_module_config(r->server->module_config, + &usertrack_module); +#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES) + clock_t mpe_times; + struct tms mpe_tms; +#elif !defined(WIN32) + struct timeval tv; + struct timezone tz = {0, 0}; +#endif + /* 1024 == hardcoded constant */ + char cookiebuf[1024]; + char *new_cookie; + char *dot; + const char *rname = ap_get_remote_host(r->connection, r->per_dir_config, + REMOTE_NAME); + + if ((dot = strchr(rname, '.'))) + *dot = '\0'; /* First bit of hostname */ + +#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES) +/* We lack gettimeofday(), so we must use time() to obtain the epoch + seconds, and then times() to obtain CPU clock ticks (milliseconds). + Combine this together to obtain a hopefully unique cookie ID. */ + + mpe_times = times(&mpe_tms); + + ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s%d%ld%ld", rname, (int) getpid(), + (long) r->request_time, (long) mpe_tms.tms_utime); +#elif defined(WIN32) + /* + * We lack gettimeofday() and we lack times(). So we'll use a combination + * of time() and GetTickCount(), which returns milliseconds since Windows + * was started. It should be relatively unique. + */ + + ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s%d%ld%ld", rname, (int) getpid(), + (long) r->request_time, (long) GetTickCount()); + +#else + gettimeofday(&tv, &tz); + + ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s%d%ld%d", rname, (int) getpid(), + (long) tv.tv_sec, (int) tv.tv_usec / 1000); +#endif + + if (cls->expires) { + struct tm *tms; + time_t when = r->request_time + cls->expires; + +#ifndef MILLENIAL_COOKIES + /* + * Only two-digit date string, so we can't trust "00" or more. + * Therefore, we knock it all back to just before midnight on + * 1/1/2000 (which is 946684799) + */ + + if (when > 946684799) + when = 946684799; +#endif + tms = gmtime(&when); + + /* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */ + new_cookie = ap_psprintf(r->pool, + "%s%s; path=/; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", + COOKIE_NAME, cookiebuf, ap_day_snames[tms->tm_wday], + tms->tm_mday, ap_month_snames[tms->tm_mon], + tms->tm_year % 100, + tms->tm_hour, tms->tm_min, tms->tm_sec); + } + else + new_cookie = ap_psprintf(r->pool, "%s%s; path=/", COOKIE_NAME, cookiebuf); + + ap_table_setn(r->headers_out, "Set-Cookie", new_cookie); + ap_table_setn(r->notes, "cookie", ap_pstrdup(r->pool, cookiebuf)); /* log first time */ + return; +} + +static int spot_cookie(request_rec *r) +{ + int *enable = (int *) ap_get_module_config(r->per_dir_config, + &usertrack_module); + char *cookie; + char *value; + + if (!*enable) + return DECLINED; + + if ((cookie = ap_table_get(r->headers_in, "Cookie"))) + if ((value = strstr(cookie, COOKIE_NAME))) { + char *cookiebuf, *cookieend; + + value += strlen(COOKIE_NAME); + cookiebuf = ap_pstrdup(r->pool, value); + cookieend = strchr(cookiebuf, ';'); + if (cookieend) + *cookieend = '\0'; /* Ignore anything after a ; */ + + /* Set the cookie in a note, for logging */ + ap_table_setn(r->notes, "cookie", cookiebuf); + + return DECLINED; /* Theres already a cookie, no new one */ + } + make_cookie(r); + return OK; /* We set our cookie */ +} + +static void *make_cookie_log_state(pool *p, server_rec *s) +{ + cookie_log_state *cls = + (cookie_log_state *) ap_palloc(p, sizeof(cookie_log_state)); + + cls->expires = 0; + + return (void *) cls; +} + +static void *make_cookie_dir(pool *p, char *d) +{ + return (void *) ap_pcalloc(p, sizeof(int)); +} + +static const char *set_cookie_enable(cmd_parms *cmd, int *c, int arg) +{ + *c = arg; + return NULL; +} + +static const char *set_cookie_exp(cmd_parms *parms, void *dummy, const char *arg) +{ + cookie_log_state *cls = ap_get_module_config(parms->server->module_config, + &usertrack_module); + time_t factor, modifier = 0; + time_t num = 0; + char *word; + + /* The simple case first - all numbers (we assume) */ + if (isdigit(arg[0]) && isdigit(arg[strlen(arg) - 1])) { + cls->expires = atol(arg); + return NULL; + } + + /* + * The harder case - stolen from mod_expires + * + * CookieExpires "[plus] { }*" + */ + + word = ap_getword_conf(parms->pool, &arg); + if (!strncasecmp(word, "plus", 1)) { + word = ap_getword_conf(parms->pool, &arg); + }; + + /* { }* */ + while (word[0]) { + /* */ + if (isdigit(word[0])) + num = atoi(word); + else + return "bad expires code, numeric value expected."; + + /* */ + word = ap_getword_conf(parms->pool, &arg); + if (!word[0]) + return "bad expires code, missing "; + + factor = 0; + if (!strncasecmp(word, "years", 1)) + factor = 60 * 60 * 24 * 365; + else if (!strncasecmp(word, "months", 2)) + factor = 60 * 60 * 24 * 30; + else if (!strncasecmp(word, "weeks", 1)) + factor = 60 * 60 * 24 * 7; + else if (!strncasecmp(word, "days", 1)) + factor = 60 * 60 * 24; + else if (!strncasecmp(word, "hours", 1)) + factor = 60 * 60; + else if (!strncasecmp(word, "minutes", 2)) + factor = 60; + else if (!strncasecmp(word, "seconds", 1)) + factor = 1; + else + return "bad expires code, unrecognized type"; + + modifier = modifier + factor * num; + + /* next */ + word = ap_getword_conf(parms->pool, &arg); + } + + cls->expires = modifier; + + return NULL; +} + +static const command_rec cookie_log_cmds[] = { + {"CookieExpires", set_cookie_exp, NULL, RSRC_CONF, TAKE1, + "an expiry date code"}, + {"CookieTracking", set_cookie_enable, NULL, OR_FILEINFO, FLAG, + "whether or not to enable cookies"}, + {NULL} +}; + +module MODULE_VAR_EXPORT usertrack_module = { + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + make_cookie_dir, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + make_cookie_log_state, /* server config */ + NULL, /* merge server configs */ + cookie_log_cmds, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + spot_cookie, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* post read-request */ +}; diff --git a/APACHE_1_3b7/src/modules/test/.cvsignore b/APACHE_1_3b7/src/modules/test/.cvsignore new file mode 100644 index 0000000000..8b4c6e3da4 --- /dev/null +++ b/APACHE_1_3b7/src/modules/test/.cvsignore @@ -0,0 +1,3 @@ +Makefile +*.lo +*.so diff --git a/APACHE_1_3b7/src/modules/test/.indent.pro b/APACHE_1_3b7/src/modules/test/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3b7/src/modules/test/.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/APACHE_1_3b7/src/modules/test/Makefile.tmpl b/APACHE_1_3b7/src/modules/test/Makefile.tmpl new file mode 100644 index 0000000000..eed37d49fe --- /dev/null +++ b/APACHE_1_3b7/src/modules/test/Makefile.tmpl @@ -0,0 +1,18 @@ + +#Dependencies + +$(OBJS) $(OBJS_PIC): Makefile + +# DO NOT REMOVE +mod_rndchunk.o: mod_rndchunk.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h ../../os/unix/os.h \ + $(INCDIR)/hsregex.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_protocol.h $(INCDIR)/http_config.h \ + $(INCDIR)/http_main.h +mod_test_util_uri.o: mod_test_util_uri.c $(INCDIR)/httpd.h \ + $(INCDIR)/conf.h ../../os/unix/os.h \ + $(INCDIR)/hsregex.h $(INCDIR)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h \ + $(INCDIR)/http_protocol.h $(INCDIR)/http_config.h \ + $(INCDIR)/http_main.h diff --git a/APACHE_1_3b7/src/modules/test/README b/APACHE_1_3b7/src/modules/test/README new file mode 100644 index 0000000000..c61763c1dd --- /dev/null +++ b/APACHE_1_3b7/src/modules/test/README @@ -0,0 +1,3 @@ +This directory is intended to house modules which are used for testing +server functionality. They're unsupported, and not guaranteed to remain +consistant between releases. You're on your own completely with these. diff --git a/APACHE_1_3b7/src/modules/test/mod_rndchunk.c b/APACHE_1_3b7/src/modules/test/mod_rndchunk.c new file mode 100644 index 0000000000..eadbae4d2f --- /dev/null +++ b/APACHE_1_3b7/src/modules/test/mod_rndchunk.c @@ -0,0 +1,179 @@ +/* ==================================================================== + * Copyright (c) 1998 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 . + * + */ + +/* + * This module is intended to be used for testing chunked encoding. It + * generates a whole whack of output using ap_bputc() and ap_bputs(). It + * also exercises start_chunk() and end_chunk() in buff.c. To use it + * you should use a tool like netcat and the src/test/check_chunked + * tool. Add something like this to your access.conf file: + * + * + * SetHandler rndchunk + * + * + * Then fake requests such as: + * + * GET /rndchunk?0,1000000 HTTP/1.1 + * Host: localhost + * + * The first arg is the random seed, the second is the number of + * "things" to do. You should try a few seeds. + * + * You should also edit main/buff.c and change DEFAULT_BUFSIZE (and + * CHUNK_HEADER_SIZE). Small values are particularly useful for + * finding bugs. Try a few different values. + * + * -djg + */ + +#include "httpd.h" +#include "http_protocol.h" +#include "http_config.h" +#include "http_main.h" + +#define MAX_SEGMENT 32 +#define ONE_WEIGHT (256-32) + +static int send_rndchunk(request_rec *r) +{ + const char *args; + char *endptr; + unsigned int seed; + unsigned int count; + int i; + char buf[MAX_SEGMENT + 1]; + unsigned int len; + + r->allowed |= (1 << M_GET); + if (r->method_number != M_GET) + return DECLINED; + + r->content_type = "text/html"; + ap_send_http_header(r); + if(r->header_only) { + return 0; + } + ap_hard_timeout("send_rndchunk", r); + + if (!r->chunked) { + ap_rputs("Not chunked!", r); + ap_kill_timeout(r); + return 0; + } + + args = r->args; + if (!args) { +error: + ap_rputs("Must include args! ... of the form ?seed,count", r); + ap_kill_timeout(r); + return 0; + } + seed = strtol(args, &endptr, 0); + if (!endptr || *endptr != ',') { + goto error; + } + ++endptr; + count = strtol(endptr, &endptr, 0); + + srandom(seed); + for (i = 0; i < count; ++i) { + len = random() % (MAX_SEGMENT + ONE_WEIGHT); + if (len >= MAX_SEGMENT) { + ap_rputc((i & 1) ? '0' : '1', r); + } + else if (len == 0) { + /* not a really nice thing to do, but we need to test + * beginning/ending chunks as well + */ + ap_bsetflag(r->connection->client, B_CHUNK, 0); + ap_bsetflag(r->connection->client, B_CHUNK, 1); + } + else { + memset(buf, '2' + len, len); + buf[len] = 0; + ap_rputs(buf, r); + } + } + ap_kill_timeout(r); + return 0; +} + +static const handler_rec rndchunk_handlers[] = +{ + {"rndchunk", send_rndchunk}, + {NULL} +}; + +module rndchunk_module = { + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + NULL, /* command table */ + rndchunk_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL /* header parser */ +}; diff --git a/APACHE_1_3b7/src/modules/test/mod_test_util_uri.c b/APACHE_1_3b7/src/modules/test/mod_test_util_uri.c new file mode 100644 index 0000000000..2df4cb54cc --- /dev/null +++ b/APACHE_1_3b7/src/modules/test/mod_test_util_uri.c @@ -0,0 +1,353 @@ +/* ==================================================================== + * Copyright (c) 1998 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 . + * + */ + +/* + * This module is intended to test the util_uri routines by parsing a + * bunch of urls and comparing the results with what we expect to + * see. + * + * Usage: + * + * + * SetHandler test-util-uri + * + * + * Then make a request to /test-util-uri. An html table of errors will + * be output... and a total count of errors. + */ + +#include "httpd.h" +#include "http_protocol.h" +#include "http_config.h" +#include "http_main.h" + +typedef struct { + const char *scheme; + const char *user; + const char *password; + const char *hostname; + const char *port_str; + const char *path; + const char *query; + const char *fragment; +} test_uri_t; + +#define T_scheme 0x01 +#define T_user 0x02 +#define T_password 0x04 +#define T_hostname 0x08 +#define T_port_str 0x10 +#define T_path 0x20 +#define T_query 0x40 +#define T_fragment 0x80 +#define T_MAX 0x100 + +/* The idea is that we list here a bunch of url pieces that we want + * stitched together in every way that's valid. + */ +static const test_uri_t uri_tests[] = { + { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" }, + { "http", "", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" }, + { "http", "userid", "", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" }, + { "http", "userid", "passwd", "", "80", "/path/goes/here", "query-here", "frag-here" }, + { "http", "userid", "passwd", "hostname.goes.here", "", "/path/goes/here", "query-here", "frag-here" }, +#if 0 + /* An empty path means two different things depending on whether this is a + * relative or an absolute uri... consider versus "GET + * http://hostname HTTP/1.1". So this is why parse_uri_components returns + * a NULL for path when it doesn't find one, instead of returning an empty + * string. + * + * We don't really need to test it explicitly since path has no explicit + * character that indicates its precense, and so we test empty paths all + * the time by varying T_path in the loop. It would just cost us extra + * code to special case the empty path string... + */ + { "http", "userid", "passwd", "hostname.goes.here", "80", "", "query-here", "frag-here" }, +#endif + { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "", "frag-here" }, + { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "" }, + { "https", "user@d", "pa:swd", "hostname.goes.here.", "", "/~path/goes/here", "query&query?crud", "frag-here?baby" } + +}; + +static char *my_stpcpy(char *d, const char *s) +{ + while((*d = *s)) { + ++d; + ++s; + } + return d; +} + +/* return the number of failures */ +static unsigned iterate_pieces(request_rec *r, const test_uri_t *pieces, int row) +{ + unsigned u; + pool *sub; + char *input_uri; + char *strp; + uri_components result; + unsigned expect; + int status; + unsigned failures; + + failures = 0; + + input_uri = ap_palloc(r->pool, + strlen(pieces->scheme) + 3 + + strlen(pieces->user) + 1 + + strlen(pieces->password) + 1 + + strlen(pieces->hostname) + 1 + + strlen(pieces->port_str) + 1 + + strlen(pieces->path) + + + strlen(pieces->query) + 1 + + strlen(pieces->fragment) + 1 + + 1); + + for (u = 0; u < T_MAX; ++u) { + strp = input_uri; + expect = 0; + + /* a scheme requires a hostinfo and vice versa */ + /* a hostinfo requires a hostname */ + if (u & (T_scheme|T_user|T_password|T_hostname|T_port_str)) { + expect |= T_scheme; + strp = my_stpcpy(strp, pieces->scheme); + *strp++ = ':'; + *strp++ = '/'; + *strp++ = '/'; + /* can't have password without user */ + if (u & (T_user|T_password)) { + expect |= T_user; + strp = my_stpcpy(strp, pieces->user); + if (u & T_password) { + expect |= T_password; + *strp++ = ':'; + strp = my_stpcpy(strp, pieces->password); + } + *strp++ = '@'; + } + expect |= T_hostname; + strp = my_stpcpy(strp, pieces->hostname); + if (u & T_port_str) { + expect |= T_port_str; + *strp++ = ':'; + strp = my_stpcpy(strp, pieces->port_str); + } + } + if (u & T_path) { + expect |= T_path; + strp = my_stpcpy(strp, pieces->path); + } + if (u & T_query) { + expect |= T_query; + *strp++ = '?'; + strp = my_stpcpy(strp, pieces->query); + } + if (u & T_fragment) { + expect |= T_fragment; + *strp++ = '#'; + strp = my_stpcpy(strp, pieces->fragment); + } + *strp = 0; + + sub = ap_make_sub_pool(r->pool); + status = ap_parse_uri_components(sub, input_uri, &result); + if (status == HTTP_OK) { +#define CHECK(f) \ + if ((expect & T_##f) \ + && (result.f == NULL || strcmp(result.f, pieces->f))) { \ + status = HTTP_INTERNAL_SERVER_ERROR; \ + } \ + else if (!(expect & T_##f) && result.f != NULL) { \ + status = HTTP_INTERNAL_SERVER_ERROR; \ + } + CHECK(scheme) + CHECK(user) + CHECK(password) + CHECK(hostname) + CHECK(port_str) + CHECK(path) + CHECK(query) + CHECK(fragment) +#undef CHECK + } + if (status != HTTP_OK) { + ap_rprintf(r, "%d0x%02x0x%02x%d\"%s\"", row, u, expect, status, input_uri); +#define DUMP(f) \ + if (result.f) { \ + ap_rvputs(r, "\"", result.f, "\"
    ", NULL); \ + } \ + else { \ + ap_rputs("NULL
    ", r); \ + } \ + if (expect & T_##f) { \ + ap_rvputs(r, "\"", pieces->f, "\"", NULL); \ + } \ + else { \ + ap_rputs("NULL", r); \ + } + DUMP(scheme); + DUMP(user); + DUMP(password); + DUMP(hostname); + DUMP(port_str); + DUMP(path); + DUMP(query); + DUMP(fragment); +#undef DUMP + ap_rputs("\n", r); + ++failures; + } + ap_destroy_pool(sub); + } + return failures; +} + +static int test_util_uri(request_rec *r) +{ + unsigned total_failures; + int i; + + r->allowed |= (1 << M_GET); + if (r->method_number != M_GET) + return DECLINED; + + r->content_type = "text/html"; + ap_send_http_header(r); + if(r->header_only) { + return 0; + } + ap_hard_timeout("test_util_uri", r); + + ap_rputs(" + +

    Key: +

    +
    row +
    entry number in the uri_tests array +
    u +
    fields under test +
    expected +
    fields expected in the result +
    status +
    response from parse_uri_components, or 500 if unexpected results +
    input uri +
    the uri given to parse_uri_components +
    +

    The remaining fields are the pieces returned from parse_uri_components, and +the values we expected for each piece (resp.). +

    Only failures are displayed. +

    +", r); +#define HEADER(f) ap_rprintf(r, "", T_##f) + HEADER(scheme); + HEADER(user); + HEADER(password); + HEADER(hostname); + HEADER(port_str); + HEADER(path); + HEADER(query); + HEADER(fragment); +#undef HEADER + + if (r->args) { + i = atoi(r->args); + total_failures = iterate_pieces(r, &uri_tests[i], i); + } + else { + total_failures = 0; + for (i = 0; i < sizeof(uri_tests) / sizeof(uri_tests[0]); ++i) { + total_failures += iterate_pieces(r, &uri_tests[i], i); + if (total_failures > 256) { + ap_rprintf(r, "
    rowuexpectstatusinput uri" #f "
    0x%02x
    \nStopped early to save your browser " + "from certain death!\nTOTAL FAILURES = %u\n", + total_failures); + return OK; + } + } + } + ap_rprintf(r, "\nTOTAL FAILURES = %u\n", total_failures); + + return OK; +} + +static const handler_rec test_util_uri_handlers[] = +{ + {"test-util-uri", test_util_uri}, + {NULL} +}; + +module test_util_uri_module = { + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + NULL, /* command table */ + test_util_uri_handlers, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL /* header parser */ +}; diff --git a/APACHE_1_3b7/src/os/.indent.pro b/APACHE_1_3b7/src/os/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3b7/src/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/APACHE_1_3b7/src/os/bs2000/.cvsignore b/APACHE_1_3b7/src/os/bs2000/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/APACHE_1_3b7/src/os/bs2000/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/APACHE_1_3b7/src/os/bs2000/Makefile.tmpl b/APACHE_1_3b7/src/os/bs2000/Makefile.tmpl new file mode 100644 index 0000000000..962b6d624f --- /dev/null +++ b/APACHE_1_3b7/src/os/bs2000/Makefile.tmpl @@ -0,0 +1,42 @@ +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) +LIBS=$(EXTRA_LIBS) $(LIBS1) +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES) +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) + +OBJS= os.o os-inline.o ebcdic.o bs2login.o + +LIB= libos.a + +all: $(LIB) + +$(LIB): $(OBJS) + rm -f $@ + ar cr $@ $(OBJS) + $(RANLIB) $@ + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $< + +clean: + rm -f $(OBJS) $(LIB) + +distclean: clean + -rm -f Makefile + +# We really don't expect end users to use this rule. It works only with +# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after +# using it. +depend: + cp Makefile.tmpl Makefile.tmpl.bak \ + && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \ + && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \ + && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \ + -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \ + > Makefile.tmpl \ + && rm Makefile.new + +$(OBJS): Makefile +os.o: os.c os-inline.c +ebcdic.o: ebcdic.c +# DO NOT REMOVE +os.o: os.c diff --git a/APACHE_1_3b7/src/os/bs2000/bs2login.c b/APACHE_1_3b7/src/os/bs2000/bs2login.c new file mode 100644 index 0000000000..e13905b808 --- /dev/null +++ b/APACHE_1_3b7/src/os/bs2000/bs2login.c @@ -0,0 +1,190 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +#ifdef _OSD_POSIX +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" + +static const char *bs2000_authfile = NULL; + + +/* This routine is called by http_core for the BS2000AuthFile directive */ +/* It stores the file name (after a quick check for validity) for later use */ +const char *os_set_authfile(pool *p, const char *name) +{ + struct stat stbuf; + char *filename; + + filename = ap_server_root_relative(p, name); + + /* auth file must exist */ + if (stat(filename, &stbuf) != 0) { + return ap_pstrcat(p, "Unable to access bs2000 auth file ", + filename, NULL); + exit(APEXIT_CHILDFATAL); + } + + /* auth file must be owned by root, and not readable/writable by everyone else */ + if (stbuf.st_uid != 0) { + return ap_pstrcat(p, "BS2000 auth file ", filename, + " is not owned by SYSROOT - " + "change owner!", NULL); + } + + if (stbuf.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) { + return ap_pstrcat(p, "BS2000 auth file ", filename, + " is readable/writable by others - " + "check permissions!", NULL); + } + + bs2000_authfile = filename; + return NULL; +} + +int os_init_job_environment(server_rec *server, const char *user_name) +{ + _checkuser_struct chk_usr; + _rini_struct inittask; + struct { + char username[8+1]; /* Length of a user name including \0 */ + char password[8+1]; /* Length of a password including \0 */ + char account [8+1]; /* Length of a account number including \0 */ + char exp_date[10+1]; /* Length of a date including \0 */ + char exp_pass[10+1]; /* Length of a date including \0 */ + char processor[8+1]; + } lcl_data; + char *cp; + FILE *pwfile; + struct stat stbuf; + + memset (&lcl_data, '\0', sizeof lcl_data); + + /* BS2000 requires the user name to be in upper case for authentication */ + ap_snprintf(lcl_data.username, sizeof lcl_data.username, + "%s", user_name); + for (cp = lcl_data.username; *cp; ++cp) { + *cp = toupper(*cp); + } + + if (bs2000_authfile == NULL) { + ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server, + "Use the 'BS2000AuthFile ' directive to specify " + "an authorization file for User %s", + user_name); + exit(APEXIT_CHILDFATAL); + } + + if ((pwfile = fopen(bs2000_authfile, "r")) == NULL) { + ap_log_error(APLOG_MARK, APLOG_ALERT, server, + "Unable to open bs2000 auth file %s for User %s", + bs2000_authfile, user_name); + exit(APEXIT_CHILDFATAL); + } + + if (fgets(lcl_data.password, sizeof lcl_data.password, pwfile) == NULL + || strlen(lcl_data.password) == 0) { + ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server, + "Unable ro read BS2000 auth file %s", + bs2000_authfile); + exit(APEXIT_CHILDFATAL); + } + + fclose(pwfile); + + chk_usr.username = lcl_data.username; + chk_usr.password = lcl_data.password; + chk_usr.account = lcl_data.account; /* Account and Expiration go here*/ + chk_usr.logon_expdate = lcl_data.exp_date; + chk_usr.pw_expdate = lcl_data.exp_pass; + + /* Now perform validity check of user and password, filling in account */ + if(_checkuser(&chk_usr) != 0) { + ap_log_error(APLOG_MARK, APLOG_ALERT, server, + "_checkuser: BS2000 auth failed for user %s", chk_usr.username); + exit(APEXIT_CHILDFATAL); + } + + inittask.username = chk_usr.username; + inittask.account = chk_usr.account; + inittask.processor_name = strncpy(lcl_data.processor, + " ", + sizeof lcl_data.processor); + + /* And switch to the new logon user (setuid() and setgid() are done later) */ + if (_rini(&inittask) != 0) { + ap_log_error(APLOG_MARK, APLOG_ALERT, server, + "_rini: BS2000 auth failed for user %s", + inittask.username); + exit(APEXIT_CHILDFATAL); + } + + /*ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, server, + "BS2000 logon for user %s account=%s completed, pid=%d.", + inittask.username, inittask.account, getpid());*/ + + /* Don't leave the password on the stack */ + memset (&lcl_data, '\0', sizeof lcl_data); + + return 0; +} + +#else /* _OSD_POSIX */ +void bs2login_is_not_here() +{ +} +#endif /* _OSD_POSIX */ diff --git a/APACHE_1_3b7/src/os/bs2000/ebcdic.c b/APACHE_1_3b7/src/os/bs2000/ebcdic.c new file mode 100644 index 0000000000..e1894801d7 --- /dev/null +++ b/APACHE_1_3b7/src/os/bs2000/ebcdic.c @@ -0,0 +1,253 @@ +/* ==================================================================== + * Copyright (c) 1998 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 . + * + */ + + +#ifdef CHARSET_EBCDIC +#include "conf.h" +#include "ebcdic.h" +/* + Initial Port for Apache-1.3 by + +"BS2000 OSD" is a POSIX on a main frame. +It is made by Siemens Nixdorf 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/APACHE_1_3b7/src/os/bs2000/ebcdic.h b/APACHE_1_3b7/src/os/bs2000/ebcdic.h new file mode 100644 index 0000000000..267f9786df --- /dev/null +++ b/APACHE_1_3b7/src/os/bs2000/ebcdic.h @@ -0,0 +1,8 @@ +#include + +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/APACHE_1_3b7/src/os/bs2000/os-inline.c b/APACHE_1_3b7/src/os/bs2000/os-inline.c new file mode 100644 index 0000000000..e1a19ee3ad --- /dev/null +++ b/APACHE_1_3b7/src/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 "conf.h" + +#endif + +INLINE int ap_os_is_path_absolute(const char *file) +{ + return (file && file[0] == '/' ? 1 : 0); +} diff --git a/APACHE_1_3b7/src/os/bs2000/os.c b/APACHE_1_3b7/src/os/bs2000/os.c new file mode 100644 index 0000000000..57a1486d5e --- /dev/null +++ b/APACHE_1_3b7/src/os/bs2000/os.c @@ -0,0 +1,98 @@ +/* ==================================================================== + * Copyright (c) 1998 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 . + * + */ + +/* + * 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 "os.h" + +/* Check the Content-Type to decide if conversion is needed */ +int ap_checkconv(struct request_rec *r) +{ + int convert_to_ascii; + + /* 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. + */ + + /* If no content type is set then treat it as (ebcdic) text/plain */ + convert_to_ascii = (r->content_type == NULL); + + /* Conversion is applied to text/ files only, if ever. */ + if (r->content_type && + (strncmp(r->content_type, "text/", 5) == 0 + || strncmp(r->content_type, "message/", 8) == 0)) { + if (strncmp(r->content_type, ASCIITEXT_MAGIC_TYPE_PREFIX, + sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0) + r->content_type = ap_pstrcat(r->pool, "text/", + r->content_type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1, NULL); + else + /* translate EBCDIC to ASCII */ + convert_to_ascii = 1; + } + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert_to_ascii); + + return convert_to_ascii; +} + diff --git a/APACHE_1_3b7/src/os/bs2000/os.h b/APACHE_1_3b7/src/os/bs2000/os.h new file mode 100644 index 0000000000..58a6225d8d --- /dev/null +++ b/APACHE_1_3b7/src/os/bs2000/os.h @@ -0,0 +1,34 @@ +#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 + */ + +#include "conf.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 + +/* 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); + +#endif /*! APACHE_OS_H*/ diff --git a/APACHE_1_3b7/src/os/emx/.cvsignore b/APACHE_1_3b7/src/os/emx/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/APACHE_1_3b7/src/os/emx/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/APACHE_1_3b7/src/os/emx/Makefile.tmpl b/APACHE_1_3b7/src/os/emx/Makefile.tmpl new file mode 100644 index 0000000000..fe4cb3a352 --- /dev/null +++ b/APACHE_1_3b7/src/os/emx/Makefile.tmpl @@ -0,0 +1,49 @@ +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) +LIBS=$(EXTRA_LIBS) $(LIBS1) +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES) +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) + +OBJS= os.o os-inline.o +COPY= os.h os-inline.c + +LIB= libos.a + +all: $(LIB) copy + +copy: + for i in $(COPY); do \ + rm -f $(INCDIR)/$$i ;\ + cp `pwd`/$$i $(INCDIR)/$$i ;\ + done + +$(LIB): $(OBJS) + rm -f $@ + ar cr $@ $(OBJS) + $(RANLIB) $@ + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $< + +clean: + for i in $(COPY); do rm -f $(INCDIR)/$$i ; done + rm -f $(OBJS) $(LIB) + +distclean: clean + -rm -f Makefile + +$(OBJS): Makefile + +# We really don't expect end users to use this rule. It works only with +# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after +# using it. +depend: + cp Makefile.tmpl Makefile.tmpl.bak \ + && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \ + && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \ + && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \ + -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \ + > Makefile.tmpl \ + && rm Makefile.new + +# DO NOT REMOVE +os.o: os.c os-inline.c diff --git a/APACHE_1_3b7/src/os/emx/os-inline.c b/APACHE_1_3b7/src/os/emx/os-inline.c new file mode 100644 index 0000000000..f39b68a967 --- /dev/null +++ b/APACHE_1_3b7/src/os/emx/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 "conf.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/APACHE_1_3b7/src/os/emx/os.c b/APACHE_1_3b7/src/os/emx/os.c new file mode 100644 index 0000000000..2b5de32e46 --- /dev/null +++ b/APACHE_1_3b7/src/os/emx/os.c @@ -0,0 +1,6 @@ +/* + * This file will include OS specific functions which are not inlineable. + * Any inlineable functions should be defined in os-inline.c instead. + */ + +#include "os.h" diff --git a/APACHE_1_3b7/src/os/emx/os.h b/APACHE_1_3b7/src/os/emx/os.h new file mode 100644 index 0000000000..a171f357eb --- /dev/null +++ b/APACHE_1_3b7/src/os/emx/os.h @@ -0,0 +1,30 @@ +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "OS/2" + +/* + * 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__ +#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 + +/* OS/2 doesn't have symlinks so S_ISLNK is always false */ +#define S_ISLNK(m) 0 + +#endif /* ! APACHE_OS_H */ diff --git a/APACHE_1_3b7/src/os/os2/.cvsignore b/APACHE_1_3b7/src/os/os2/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/APACHE_1_3b7/src/os/os2/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/APACHE_1_3b7/src/os/os2/Makefile.tmpl b/APACHE_1_3b7/src/os/os2/Makefile.tmpl new file mode 100644 index 0000000000..fe4cb3a352 --- /dev/null +++ b/APACHE_1_3b7/src/os/os2/Makefile.tmpl @@ -0,0 +1,49 @@ +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) +LIBS=$(EXTRA_LIBS) $(LIBS1) +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES) +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) + +OBJS= os.o os-inline.o +COPY= os.h os-inline.c + +LIB= libos.a + +all: $(LIB) copy + +copy: + for i in $(COPY); do \ + rm -f $(INCDIR)/$$i ;\ + cp `pwd`/$$i $(INCDIR)/$$i ;\ + done + +$(LIB): $(OBJS) + rm -f $@ + ar cr $@ $(OBJS) + $(RANLIB) $@ + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $< + +clean: + for i in $(COPY); do rm -f $(INCDIR)/$$i ; done + rm -f $(OBJS) $(LIB) + +distclean: clean + -rm -f Makefile + +$(OBJS): Makefile + +# We really don't expect end users to use this rule. It works only with +# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after +# using it. +depend: + cp Makefile.tmpl Makefile.tmpl.bak \ + && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \ + && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \ + && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \ + -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \ + > Makefile.tmpl \ + && rm Makefile.new + +# DO NOT REMOVE +os.o: os.c os-inline.c diff --git a/APACHE_1_3b7/src/os/os2/os-inline.c b/APACHE_1_3b7/src/os/os2/os-inline.c new file mode 100644 index 0000000000..f39b68a967 --- /dev/null +++ b/APACHE_1_3b7/src/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 "conf.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/APACHE_1_3b7/src/os/os2/os.c b/APACHE_1_3b7/src/os/os2/os.c new file mode 100644 index 0000000000..2b5de32e46 --- /dev/null +++ b/APACHE_1_3b7/src/os/os2/os.c @@ -0,0 +1,6 @@ +/* + * This file will include OS specific functions which are not inlineable. + * Any inlineable functions should be defined in os-inline.c instead. + */ + +#include "os.h" diff --git a/APACHE_1_3b7/src/os/os2/os.h b/APACHE_1_3b7/src/os/os2/os.h new file mode 100644 index 0000000000..a171f357eb --- /dev/null +++ b/APACHE_1_3b7/src/os/os2/os.h @@ -0,0 +1,30 @@ +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "OS/2" + +/* + * 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__ +#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 + +/* OS/2 doesn't have symlinks so S_ISLNK is always false */ +#define S_ISLNK(m) 0 + +#endif /* ! APACHE_OS_H */ diff --git a/APACHE_1_3b7/src/os/unix/.cvsignore b/APACHE_1_3b7/src/os/unix/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/APACHE_1_3b7/src/os/unix/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/APACHE_1_3b7/src/os/unix/Makefile.tmpl b/APACHE_1_3b7/src/os/unix/Makefile.tmpl new file mode 100644 index 0000000000..7635c3b6ba --- /dev/null +++ b/APACHE_1_3b7/src/os/unix/Makefile.tmpl @@ -0,0 +1,43 @@ +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) +LIBS=$(EXTRA_LIBS) $(LIBS1) +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES) +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) + +OBJS= os.o os-inline.o + +LIB= libos.a + +all: $(LIB) + +$(LIB): $(OBJS) + rm -f $@ + ar cr $@ $(OBJS) + $(RANLIB) $@ + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $< + +clean: + rm -f $(OBJS) $(LIB) + +distclean: clean + -rm -f Makefile + +# We really don't expect end users to use this rule. It works only with +# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after +# using it. +depend: + cp Makefile.tmpl Makefile.tmpl.bak \ + && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \ + && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \ + && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \ + -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \ + > Makefile.tmpl \ + && rm Makefile.new + +$(OBJS): Makefile + +# DO NOT REMOVE +os-aix-dso.o: os-aix-dso.c +os-inline.o: os-inline.c $(INCDIR)/conf.h $(OSDIR)/os.h +os.o: os.c $(INCDIR)/conf.h $(OSDIR)/os.h os.h diff --git a/APACHE_1_3b7/src/os/unix/os-aix-dso.c b/APACHE_1_3b7/src/os/unix/os-aix-dso.c new file mode 100644 index 0000000000..6f4176d565 --- /dev/null +++ b/APACHE_1_3b7/src/os/unix/os-aix-dso.c @@ -0,0 +1,668 @@ +/* ==================================================================== + * Copyright (c) 1998 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 . + * + */ + +/* +** os-aix-dso.c -- DSO system function emulation for AIX + */ + +/* +** Based on libdl (dlfcn.c/dlfcn.h) which is +** Copyright (c) 1992,1993,1995,1996,1997,1988 +** Jens-Uwe Mager, Helios Software GmbH, Hannover, Germany. +** +** Not derived from licensed software. +** +** Permission is granted to freely use, copy, modify, and redistribute +** this software, provided that the author is not construed to be liable +** for any results of using the software, alterations are clearly marked +** as such, and this notice is not modified. +** +** Changes marked with `--jwe' were made on April 7 1996 by +** John W. Eaton to support g++ +** +** Bundled, stripped and adjusted on April 1998 as one single source file +** for inclusion into the Apache HTTP server by +** Ralf S. Engelschall +*/ + +#include +#include +#include +#include +#include +#include +#include + +#undef FREAD +#undef FWRITE +#include + +/* + * AIX 4.3 does remove some useful definitions from ldfcn.h. Define + * these here to compensate for that lossage. + */ +#ifndef BEGINNING +#define BEGINNING SEEK_SET +#endif +#ifndef FSEEK +#define FSEEK(ldptr,o,p) fseek(IOPTR(ldptr),(p==BEGINNING)?(OFFSET(ldptr) +o):o,p) +#endif +#ifndef FREAD +#define FREAD(p,s,n,ldptr) fread(p,s,n,IOPTR(ldptr)) +#endif + +/* + * Mode flags for the dlopen routine. + */ +#undef RTLD_LAZY +#define RTLD_LAZY 1 /* lazy function call binding */ +#undef RTLD_NOW +#define RTLD_NOW 2 /* immediate function call binding */ +#undef RTLD_GLOBAL +#define RTLD_GLOBAL 0x100 /* allow symbols to be global */ + +/* + * To be able to intialize, a library may provide a dl_info structure + * that contains functions to be called to initialize and terminate. + */ +struct dl_info { + void (*init) (void); + void (*fini) (void); +}; + + +/* + * Forward declarations + */ +void *dlopen(const char *path, int mode); +void *dlsym(void *handle, const char *symbol); +const char *dlerror(void); +int dlclose(void *handle); + +/* + * We simulate dlopen() et al. through a call to load. Because AIX has + * no call to find an exported symbol we read the loader section of the + * loaded module and build a list of exported symbols and their virtual + * address. + */ + +typedef struct { + char *name; /* the symbols's name */ + void *addr; /* its relocated virtual address */ +} Export, *ExportPtr; + +/* + * xlC uses the following structure to list its constructors and + * destructors. This is gleaned from the output of munch. + */ +typedef struct { + void (*init) (void); /* call static constructors */ + void (*term) (void); /* call static destructors */ +} Cdtor, *CdtorPtr; + +typedef void (*GccCDtorPtr) (void); + +/* + * The void * handle returned from dlopen is actually a ModulePtr. + */ +typedef struct Module { + struct Module *next; + char *name; /* module name for refcounting */ + int refCnt; /* the number of references */ + void *entry; /* entry point from load */ + struct dl_info *info; /* optional init/terminate functions */ + CdtorPtr cdtors; /* optional C++ constructors */ + GccCDtorPtr gcc_ctor; /* g++ constructors --jwe */ + GccCDtorPtr gcc_dtor; /* g++ destructors --jwe */ + int nExports; /* the number of exports found */ + ExportPtr exports; /* the array of exports */ +} Module, *ModulePtr; + +/* + * We keep a list of all loaded modules to be able to call the fini + * handlers and destructors at atexit() time. + */ +static ModulePtr modList; + +/* + * The last error from one of the dl* routines is kept in static + * variables here. Each error is returned only once to the caller. + */ +static char errbuf[BUFSIZ]; +static int errvalid; + +/* + * The `fixed' gcc header files on AIX 3.2.5 provide a prototype for + * strdup(). --jwe + */ +extern char *strdup(const char *); +static void caterr(char *); +static int readExports(ModulePtr); +static void terminate(void); +static void *findMain(void); + +void *dlopen(const char *path, int mode) +{ + register ModulePtr mp; + static void *mainModule; + + /* + * Upon the first call register a terminate handler that will + * close all libraries. Also get a reference to the main module + * for use with loadbind. + */ + if (!mainModule) { + if ((mainModule = findMain()) == NULL) + return NULL; + atexit(terminate); + } + /* + * Scan the list of modules if we have the module already loaded. + */ + for (mp = modList; mp; mp = mp->next) + if (strcmp(mp->name, path) == 0) { + mp->refCnt++; + return mp; + } + if ((mp = (ModulePtr) calloc(1, sizeof(*mp))) == NULL) { + errvalid++; + strcpy(errbuf, "calloc: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + if ((mp->name = strdup(path)) == NULL) { + errvalid++; + strcpy(errbuf, "strdup: "); + strcat(errbuf, strerror(errno)); + free(mp); + return NULL; + } + /* + * load should be declared load(const char *...). Thus we + * cast the path to a normal char *. Ugly. + */ + if ((mp->entry = (void *) load((char *) path, L_NOAUTODEFER, NULL)) == NULL) { + free(mp->name); + free(mp); + errvalid++; + strcpy(errbuf, "dlopen: "); + strcat(errbuf, path); + strcat(errbuf, ": "); + /* + * If AIX says the file is not executable, the error + * can be further described by querying the loader about + * the last error. + */ + if (errno == ENOEXEC) { + char *tmp[BUFSIZ / sizeof(char *)]; + if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1) + strcpy(errbuf, strerror(errno)); + else { + char **p; + for (p = tmp; *p; p++) + caterr(*p); + } + } + else + strcat(errbuf, strerror(errno)); + return NULL; + } + mp->refCnt = 1; + mp->next = modList; + modList = mp; + if (loadbind(0, mainModule, mp->entry) == -1) { + dlclose(mp); + errvalid++; + strcpy(errbuf, "loadbind: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + /* + * If the user wants global binding, loadbind against all other + * loaded modules. + */ + if (mode & RTLD_GLOBAL) { + register ModulePtr mp1; + for (mp1 = mp->next; mp1; mp1 = mp1->next) + if (loadbind(0, mp1->entry, mp->entry) == -1) { + dlclose(mp); + errvalid++; + strcpy(errbuf, "loadbind: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + } + if (readExports(mp) == -1) { + dlclose(mp); + return NULL; + } + /* + * If there is a dl_info structure, call the init function. + */ + if (mp->info = (struct dl_info *) dlsym(mp, "dl_info")) { + if (mp->info->init) + (*mp->info->init) (); + } + else + errvalid = 0; + /* + * If the shared object was compiled using xlC we will need + * to call static constructors (and later on dlclose destructors). + */ + if (mp->cdtors = (CdtorPtr) dlsym(mp, "__cdtors")) { + CdtorPtr cp = mp->cdtors; + while (cp->init || cp->term) { + if (cp->init && cp->init != (void (*)(void)) 0xffffffff) + (*cp->init) (); + cp++; + } + /* + * If the shared object was compiled using g++, we will need + * to call global constructors using the _GLOBAL__DI function, + * and later, global destructors using the _GLOBAL_DD + * funciton. --jwe + */ + } + else if (mp->gcc_ctor = (GccCDtorPtr) dlsym(mp, "_GLOBAL__DI")) { + (*mp->gcc_ctor) (); + mp->gcc_dtor = (GccCDtorPtr) dlsym(mp, "_GLOBAL__DD"); + } + else + errvalid = 0; + return mp; +} + +/* + * Attempt to decipher an AIX loader error message and append it + * to our static error message buffer. + */ +static void caterr(char *s) +{ + register char *p = s; + + while (*p >= '0' && *p <= '9') + p++; + switch (atoi(s)) { + case L_ERROR_TOOMANY: + strcat(errbuf, "to many errors"); + break; + case L_ERROR_NOLIB: + strcat(errbuf, "can't load library"); + strcat(errbuf, p); + break; + case L_ERROR_UNDEF: + strcat(errbuf, "can't find symbol"); + strcat(errbuf, p); + break; + case L_ERROR_RLDBAD: + strcat(errbuf, "bad RLD"); + strcat(errbuf, p); + break; + case L_ERROR_FORMAT: + strcat(errbuf, "bad exec format in"); + strcat(errbuf, p); + break; + case L_ERROR_ERRNO: + strcat(errbuf, strerror(atoi(++p))); + break; + default: + strcat(errbuf, s); + break; + } +} + +void *dlsym(void *handle, const char *symbol) +{ + register ModulePtr mp = (ModulePtr) handle; + register ExportPtr ep; + register int i; + + /* + * Could speed up the search, but I assume that one assigns + * the result to function pointers anyways. + */ + for (ep = mp->exports, i = mp->nExports; i; i--, ep++) + if (strcmp(ep->name, symbol) == 0) + return ep->addr; + errvalid++; + strcpy(errbuf, "dlsym: undefined symbol "); + strcat(errbuf, symbol); + return NULL; +} + +const char *dlerror(void) +{ + if (errvalid) { + errvalid = 0; + return errbuf; + } + return NULL; +} + +int dlclose(void *handle) +{ + register ModulePtr mp = (ModulePtr) handle; + int result; + register ModulePtr mp1; + + if (--mp->refCnt > 0) + return 0; + if (mp->info && mp->info->fini) + (*mp->info->fini) (); + if (mp->cdtors) { + CdtorPtr cp = mp->cdtors; + while (cp->init || cp->term) { + if (cp->term && cp->init != (void (*)(void)) 0xffffffff) + (*cp->term) (); + cp++; + } + /* + * If the function to handle global destructors for g++ + * exists, call it. --jwe + */ + } + else if (mp->gcc_dtor) { + (*mp->gcc_dtor) (); + } + result = unload(mp->entry); + if (result == -1) { + errvalid++; + strcpy(errbuf, strerror(errno)); + } + if (mp->exports) { + register ExportPtr ep; + register int i; + for (ep = mp->exports, i = mp->nExports; i; i--, ep++) + if (ep->name) + free(ep->name); + free(mp->exports); + } + if (mp == modList) + modList = mp->next; + else { + for (mp1 = modList; mp1; mp1 = mp1->next) + if (mp1->next == mp) { + mp1->next = mp->next; + break; + } + } + free(mp->name); + free(mp); + return result; +} + +static void terminate(void) +{ + while (modList) + dlclose(modList); +} + +/* + * Build the export table from the XCOFF .loader section. + */ +static int readExports(ModulePtr mp) +{ + LDFILE *ldp = NULL; + SCNHDR sh, shdata; + LDHDR *lhp; + char *ldbuf; + LDSYM *ls; + int i; + ExportPtr ep; + struct ld_info *lp; + char *buf; + int size = 4 * 1024; + void *dataorg; + + /* + * The module might be loaded due to the LIBPATH + * environment variable. Search for the loaded + * module using L_GETINFO. + */ + if ((buf = malloc(size)) == NULL) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + return -1; + } + while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { + free(buf); + size += 4 * 1024; + if ((buf = malloc(size)) == NULL) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + return -1; + } + } + if (i == -1) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + free(buf); + return -1; + } + /* + * Traverse the list of loaded modules. The entry point + * returned by load() does actually point to the TOC + * entry contained in the data segment. + */ + lp = (struct ld_info *) buf; + while (lp) { + if ((unsigned long) mp->entry >= (unsigned long) lp->ldinfo_dataorg && + (unsigned long) mp->entry < (unsigned long) lp->ldinfo_dataorg + + lp->ldinfo_datasize) { + dataorg = lp->ldinfo_dataorg; + ldp = ldopen(lp->ldinfo_filename, ldp); + break; + } + if (lp->ldinfo_next == 0) + lp = NULL; + else + lp = (struct ld_info *) ((char *) lp + lp->ldinfo_next); + } + free(buf); + if (!ldp) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + return -1; + } + if (TYPE(ldp) != U802TOCMAGIC) { + errvalid++; + strcpy(errbuf, "readExports: bad magic"); + while (ldclose(ldp) == FAILURE); + return -1; + } + /* + * Get the padding for the data section. This is needed for + * AIX 4.1 compilers. This is used when building the final + * function pointer to the exported symbol. + */ + if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) { + errvalid++; + strcpy(errbuf, "readExports: cannot read data section header"); + while (ldclose(ldp) == FAILURE); + return -1; + } + if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) { + errvalid++; + strcpy(errbuf, "readExports: cannot read loader section header"); + while (ldclose(ldp) == FAILURE); + return -1; + } + /* + * We read the complete loader section in one chunk, this makes + * finding long symbol names residing in the string table easier. + */ + if ((ldbuf = (char *) malloc(sh.s_size)) == NULL) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + while (ldclose(ldp) == FAILURE); + return -1; + } + if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) { + errvalid++; + strcpy(errbuf, "readExports: cannot seek to loader section"); + free(ldbuf); + while (ldclose(ldp) == FAILURE); + return -1; + } + if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) { + errvalid++; + strcpy(errbuf, "readExports: cannot read loader section"); + free(ldbuf); + while (ldclose(ldp) == FAILURE); + return -1; + } + lhp = (LDHDR *) ldbuf; + ls = (LDSYM *) (ldbuf + LDHDRSZ); + /* + * Count the number of exports to include in our export table. + */ + for (i = lhp->l_nsyms; i; i--, ls++) { + if (!LDR_EXPORT(*ls)) + continue; + mp->nExports++; + } + if ((mp->exports = (ExportPtr) calloc(mp->nExports, sizeof(*mp->exports))) == NULL) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + free(ldbuf); + while (ldclose(ldp) == FAILURE); + return -1; + } + /* + * Fill in the export table. All entries are relative to + * the beginning of the data origin. + */ + ep = mp->exports; + ls = (LDSYM *) (ldbuf + LDHDRSZ); + for (i = lhp->l_nsyms; i; i--, ls++) { + char *symname; + char tmpsym[SYMNMLEN + 1]; + if (!LDR_EXPORT(*ls)) + continue; + if (ls->l_zeroes == 0) + symname = ls->l_offset + lhp->l_stoff + ldbuf; + else { + /* + * The l_name member is not zero terminated, we + * must copy the first SYMNMLEN chars and make + * sure we have a zero byte at the end. + */ + strncpy(tmpsym, ls->l_name, SYMNMLEN); + tmpsym[SYMNMLEN] = '\0'; + symname = tmpsym; + } + ep->name = strdup(symname); + ep->addr = (void *) ((unsigned long) dataorg + + ls->l_value - shdata.s_vaddr); + ep++; + } + free(ldbuf); + while (ldclose(ldp) == FAILURE); + return 0; +} + +/* + * Find the main modules data origin. This is used as export pointer + * for loadbind() to be able to resolve references to the main part. + */ +static void *findMain(void) +{ + struct ld_info *lp; + char *buf; + int size = 4 * 1024; + int i; + void *ret; + + if ((buf = malloc(size)) == NULL) { + errvalid++; + strcpy(errbuf, "findMain: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { + free(buf); + size += 4 * 1024; + if ((buf = malloc(size)) == NULL) { + errvalid++; + strcpy(errbuf, "findMain: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + } + if (i == -1) { + errvalid++; + strcpy(errbuf, "findMain: "); + strcat(errbuf, strerror(errno)); + free(buf); + return NULL; + } + /* + * The first entry is the main module. The data segment + * starts with the TOC entries for all exports, so the + * data segment origin works as argument for loadbind. + */ + lp = (struct ld_info *) buf; + ret = lp->ldinfo_dataorg; + free(buf); + return ret; +} diff --git a/APACHE_1_3b7/src/os/unix/os-inline.c b/APACHE_1_3b7/src/os/unix/os-inline.c new file mode 100644 index 0000000000..b67f3f2f16 --- /dev/null +++ b/APACHE_1_3b7/src/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 "conf.h" + +#endif + +INLINE int ap_os_is_path_absolute(const char *file) +{ + return file[0] == '/'; +} diff --git a/APACHE_1_3b7/src/os/unix/os.c b/APACHE_1_3b7/src/os/unix/os.c new file mode 100644 index 0000000000..71dab2d830 --- /dev/null +++ b/APACHE_1_3b7/src/os/unix/os.c @@ -0,0 +1,85 @@ +/* + * This file will include OS specific functions which are not inlineable. + * Any inlineable functions should be defined in os-inline.c instead. + */ + +#include "conf.h" +#include "os.h" + + +/* some linkers complain unless there's at least one function in each + * .o file... and extra prototype is for gcc -Wmissing-prototypes + */ +extern void ap_is_not_here(void); +void ap_is_not_here(void) {} + +/* + * Insert the DSO emulation code for AIX + */ +#ifdef AIX +#include "os-aix-dso.c" +#endif + +/* + * Abstraction layer for loading + * Apache modules under run-time via + * dynamic shared object (DSO) mechanism + */ + +void *ap_os_dso_load(const char *path) +{ +#if defined(HPUX) || defined(HPUX10) + shl_t handle; + handle = shl_load(path, BIND_IMMEDIATE|BIND_VERBOSE|BIND_NOSTART, 0L); + return (void *)handle; +#else +#if defined(OSF1) ||\ + (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) + return dlopen((char *)path, RTLD_NOW); +#else + return dlopen(path, RTLD_NOW); +#endif +#endif +} + +void ap_os_dso_unload(void *handle) +{ +#if defined(HPUX) || defined(HPUX10) + shl_unload((shl_t)handle); +#else + dlclose(handle); +#endif + return; +} + +void *ap_os_dso_sym(void *handle, const char *symname) +{ +#if defined(HPUX) || defined(HPUX10) + void *symaddr = NULL; + int status; + + errno = 0; + status = shl_findsym((shl_t *)&handle, symname, TYPE_PROCEDURE, &symaddr); + if (status == -1 && errno == 0) /* try TYPE_DATA instead */ + status = shl_findsym((shl_t *)&handle, symname, TYPE_DATA, &symaddr); + return (status == -1 ? NULL : symaddr); +#else /* ndef HPUX */ +#ifdef DLSYM_NEEDS_UNDERSCORE + char symbol[256]; + sprintf(symbol, "_%s", symname); + return dlsym(handle, symbol); +#else + return dlsym(handle, symname); +#endif +#endif /* ndef HPUX */ +} + +const char *ap_os_dso_error(void) +{ +#if defined(HPUX) || defined(HPUX10) + return strerror(errno); +#else + return dlerror(); +#endif +} + diff --git a/APACHE_1_3b7/src/os/unix/os.h b/APACHE_1_3b7/src/os/unix/os.h new file mode 100644 index 0000000000..8c63f6cf2f --- /dev/null +++ b/APACHE_1_3b7/src/os/unix/os.h @@ -0,0 +1,132 @@ +/* ==================================================================== + * Copyright (c) 1998 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 . + * + */ + +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "Unix" + +/* + * 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 +#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 *f); +#endif + +/* + * Abstraction layer for loading + * Apache modules under run-time via + * dynamic shared object (DSO) mechanism + */ + +#if defined(HPUX) || defined(HPUX10) +#define HAVE_DL_H 1 +#endif + +#if defined(LINUX) || defined(__FreeBSD__) ||\ + defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(SOLARIS2) || defined(__bsdi__) || \ + defined(IRIX) || defined(SVR4) || defined(OSF1) +#define HAVE_DLFCN_H 1 +#endif + +#ifdef HAVE_DL_H +#include +#endif + +#ifdef HAVE_DLFCN_H +#include +#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 + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#define DLSYM_NEEDS_UNDERSCORE +#endif + +#define ap_os_dso_handle_t 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/APACHE_1_3b7/src/os/win32/.cvsignore b/APACHE_1_3b7/src/os/win32/.cvsignore new file mode 100644 index 0000000000..17564450e9 --- /dev/null +++ b/APACHE_1_3b7/src/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/APACHE_1_3b7/src/os/win32/ApacheModuleAuthAnon.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleAuthAnon.dsp new file mode 100644 index 0000000000..afe8cc7e2f --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleAuthAnon.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleAuthAnon" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleAuthAnon - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleAuthAnon.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleAuthAnon.mak"\ + CFG="ApacheModuleAuthAnon - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleAuthAnon - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleAuthAnon - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleAuthAnon - 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 ".\ApacheModuleAuthAnonR" +# PROP Intermediate_Dir ".\ApacheModuleAuthAnonR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleAuthAnon - 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 ".\ApacheModuleAuthAnonD" +# PROP Intermediate_Dir ".\ApacheModuleAuthAnonD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleAuthAnon - Win32 Release" +# Name "ApacheModuleAuthAnon - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_auth_anon.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleAuthAnon.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleAuthAnon.mak new file mode 100644 index 0000000000..dd86d0cf14 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleAuthAnon.mak @@ -0,0 +1,239 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleAuthAnon.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleAuthAnon - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleAuthAnon - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleAuthAnon - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleAuthAnon - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleAuthAnon.mak"\ + CFG="ApacheModuleAuthAnon - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleAuthAnon - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleAuthAnon - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Release" + +OUTDIR=.\ApacheModuleAuthAnonR +INTDIR=.\ApacheModuleAuthAnonR +# Begin Custom Macros +OutDir=.\.\ApacheModuleAuthAnonR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleAuthAnon.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleAuthAnon.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_auth_anon.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.dll" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.exp" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleAuthAnon.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleAuthAnonR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleAuthAnon.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleAuthAnon.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleAuthAnon.dll"\ + /implib:"$(OUTDIR)\ApacheModuleAuthAnon.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_anon.obj" + +"$(OUTDIR)\ApacheModuleAuthAnon.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Debug" + +OUTDIR=.\ApacheModuleAuthAnonD +INTDIR=.\ApacheModuleAuthAnonD +# Begin Custom Macros +OutDir=.\.\ApacheModuleAuthAnonD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleAuthAnon.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleAuthAnon.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_auth_anon.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.dll" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.exp" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.ilk" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.lib" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE"\ + /Fp"$(INTDIR)\ApacheModuleAuthAnon.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleAuthAnonD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleAuthAnon.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleAuthAnon.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleAuthAnon.dll"\ + /implib:"$(OUTDIR)\ApacheModuleAuthAnon.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_anon.obj" + +"$(OUTDIR)\ApacheModuleAuthAnon.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleAuthAnon - Win32 Debug" +SOURCE=..\..\modules\standard\mod_auth_anon.c + +!IF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Release" + +DEP_CPP_MOD_A=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_A=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_auth_anon.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Debug" + +DEP_CPP_MOD_A=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_auth_anon.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleCERNMeta.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleCERNMeta.dsp new file mode 100644 index 0000000000..3564c0e2ef --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleCERNMeta.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleCERNMeta" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleCERNMeta - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleCERNMeta.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleCERNMeta.mak"\ + CFG="ApacheModuleCERNMeta - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleCERNMeta - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleCERNMeta - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleCERNMeta - 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 ".\ApacheModuleCERNMetaR" +# PROP Intermediate_Dir ".\ApacheModuleCERNMetaR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleCERNMeta - 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 ".\ApacheModuleCERNMetaD" +# PROP Intermediate_Dir ".\ApacheModuleCERNMetaD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleCERNMeta - Win32 Release" +# Name "ApacheModuleCERNMeta - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_cern_meta.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleCERNMeta.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleCERNMeta.mak new file mode 100644 index 0000000000..0d7a9069c4 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleCERNMeta.mak @@ -0,0 +1,237 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleCERNMeta.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleCERNMeta - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleCERNMeta - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleCERNMeta - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleCERNMeta - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleCERNMeta.mak"\ + CFG="ApacheModuleCERNMeta - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleCERNMeta - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleCERNMeta - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Release" + +OUTDIR=.\ApacheModuleCERNMetaR +INTDIR=.\ApacheModuleCERNMetaR +# Begin Custom Macros +OutDir=.\.\ApacheModuleCERNMetaR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleCERNMeta.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleCERNMeta.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_cern_meta.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.dll" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.exp" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleCERNMeta.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleCERNMetaR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleCERNMeta.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleCERNMeta.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleCERNMeta.dll"\ + /implib:"$(OUTDIR)\ApacheModuleCERNMeta.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_cern_meta.obj" + +"$(OUTDIR)\ApacheModuleCERNMeta.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Debug" + +OUTDIR=.\ApacheModuleCERNMetaD +INTDIR=.\ApacheModuleCERNMetaD +# Begin Custom Macros +OutDir=.\.\ApacheModuleCERNMetaD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleCERNMeta.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleCERNMeta.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_cern_meta.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.dll" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.exp" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.ilk" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.lib" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE"\ + /Fp"$(INTDIR)\ApacheModuleCERNMeta.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleCERNMetaD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleCERNMeta.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleCERNMeta.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleCERNMeta.dll"\ + /implib:"$(OUTDIR)\ApacheModuleCERNMeta.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_cern_meta.obj" + +"$(OUTDIR)\ApacheModuleCERNMeta.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleCERNMeta - Win32 Debug" +SOURCE=..\..\modules\standard\mod_cern_meta.c + +!IF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Release" + +DEP_CPP_MOD_C=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_script.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_C=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_cern_meta.obj" : $(SOURCE) $(DEP_CPP_MOD_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Debug" + +DEP_CPP_MOD_C=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_script.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_cern_meta.obj" : $(SOURCE) $(DEP_CPP_MOD_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleDigest.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleDigest.dsp new file mode 100644 index 0000000000..fd18022582 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleDigest.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleDigest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleDigest - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleDigest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleDigest.mak"\ + CFG="ApacheModuleDigest - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleDigest - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleDigest - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleDigest - 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 ".\ApacheModuleDigestR" +# PROP Intermediate_Dir ".\ApacheModuleDigestR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleDigest - 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 ".\ApacheModuleDigestD" +# PROP Intermediate_Dir ".\ApacheModuleDigestD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleDigest - Win32 Release" +# Name "ApacheModuleDigest - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_digest.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleDigest.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleDigest.mak new file mode 100644 index 0000000000..9319965798 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleDigest.mak @@ -0,0 +1,240 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleDigest.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleDigest - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleDigest - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleDigest - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleDigest - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleDigest.mak"\ + CFG="ApacheModuleDigest - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleDigest - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleDigest - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleDigest - Win32 Release" + +OUTDIR=.\ApacheModuleDigestR +INTDIR=.\ApacheModuleDigestR +# Begin Custom Macros +OutDir=.\.\ApacheModuleDigestR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleDigest.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleDigest.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_digest.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleDigest.dll" + -@erase "$(OUTDIR)\ApacheModuleDigest.exp" + -@erase "$(OUTDIR)\ApacheModuleDigest.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleDigest.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleDigestR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleDigest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleDigest.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleDigest.dll"\ + /implib:"$(OUTDIR)\ApacheModuleDigest.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_digest.obj" + +"$(OUTDIR)\ApacheModuleDigest.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleDigest - Win32 Debug" + +OUTDIR=.\ApacheModuleDigestD +INTDIR=.\ApacheModuleDigestD +# Begin Custom Macros +OutDir=.\.\ApacheModuleDigestD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleDigest.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleDigest.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_digest.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleDigest.dll" + -@erase "$(OUTDIR)\ApacheModuleDigest.exp" + -@erase "$(OUTDIR)\ApacheModuleDigest.ilk" + -@erase "$(OUTDIR)\ApacheModuleDigest.lib" + -@erase "$(OUTDIR)\ApacheModuleDigest.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleDigest.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleDigestD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleDigest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleDigest.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleDigest.dll"\ + /implib:"$(OUTDIR)\ApacheModuleDigest.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_digest.obj" + +"$(OUTDIR)\ApacheModuleDigest.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleDigest - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleDigest - Win32 Debug" +SOURCE=..\..\modules\standard\mod_digest.c + +!IF "$(CFG)" == "ApacheModuleDigest - Win32 Release" + +DEP_CPP_MOD_D=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\md5.h"\ + "..\..\include\util_md5.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_D=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_digest.obj" : $(SOURCE) $(DEP_CPP_MOD_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleDigest - Win32 Debug" + +DEP_CPP_MOD_D=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\md5.h"\ + "..\..\include\util_md5.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_digest.obj" : $(SOURCE) $(DEP_CPP_MOD_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleExpires.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleExpires.dsp new file mode 100644 index 0000000000..0b2fe902bb --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleExpires.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleExpires" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleExpires - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleExpires.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleExpires.mak"\ + CFG="ApacheModuleExpires - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleExpires - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleExpires - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleExpires - 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 ".\ApacheModuleExpiresR" +# PROP Intermediate_Dir ".\ApacheModuleExpiresR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleExpires - 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 ".\ApacheModuleExpiresD" +# PROP Intermediate_Dir ".\ApacheModuleExpiresD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleExpires - Win32 Release" +# Name "ApacheModuleExpires - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_expires.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleExpires.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleExpires.mak new file mode 100644 index 0000000000..b8c9513a54 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleExpires.mak @@ -0,0 +1,232 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleExpires.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleExpires - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleExpires - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleExpires - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleExpires - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleExpires.mak"\ + CFG="ApacheModuleExpires - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleExpires - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleExpires - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleExpires - Win32 Release" + +OUTDIR=.\ApacheModuleExpiresR +INTDIR=.\ApacheModuleExpiresR +# Begin Custom Macros +OutDir=.\.\ApacheModuleExpiresR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleExpires.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleExpires.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_expires.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleExpires.dll" + -@erase "$(OUTDIR)\ApacheModuleExpires.exp" + -@erase "$(OUTDIR)\ApacheModuleExpires.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleExpires.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleExpiresR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleExpires.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleExpires.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleExpires.dll"\ + /implib:"$(OUTDIR)\ApacheModuleExpires.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_expires.obj" + +"$(OUTDIR)\ApacheModuleExpires.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleExpires - Win32 Debug" + +OUTDIR=.\ApacheModuleExpiresD +INTDIR=.\ApacheModuleExpiresD +# Begin Custom Macros +OutDir=.\.\ApacheModuleExpiresD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleExpires.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleExpires.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_expires.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleExpires.dll" + -@erase "$(OUTDIR)\ApacheModuleExpires.exp" + -@erase "$(OUTDIR)\ApacheModuleExpires.ilk" + -@erase "$(OUTDIR)\ApacheModuleExpires.lib" + -@erase "$(OUTDIR)\ApacheModuleExpires.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleExpires.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleExpiresD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleExpires.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleExpires.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleExpires.dll"\ + /implib:"$(OUTDIR)\ApacheModuleExpires.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_expires.obj" + +"$(OUTDIR)\ApacheModuleExpires.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleExpires - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleExpires - Win32 Debug" +SOURCE=..\..\modules\standard\mod_expires.c + +!IF "$(CFG)" == "ApacheModuleExpires - Win32 Release" + +DEP_CPP_MOD_E=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_E=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_expires.obj" : $(SOURCE) $(DEP_CPP_MOD_E) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleExpires - Win32 Debug" + +DEP_CPP_MOD_E=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_expires.obj" : $(SOURCE) $(DEP_CPP_MOD_E) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleHeaders.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleHeaders.dsp new file mode 100644 index 0000000000..1dc76027b3 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleHeaders.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleHeaders" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleHeaders - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleHeaders.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleHeaders.mak"\ + CFG="ApacheModuleHeaders - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleHeaders - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleHeaders - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleHeaders - 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 ".\ApacheModuleHeadersR" +# PROP Intermediate_Dir ".\ApacheModuleHeadersR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleHeaders - 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 ".\ApacheModuleHeadersD" +# PROP Intermediate_Dir ".\ApacheModuleHeadersD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleHeaders - Win32 Release" +# Name "ApacheModuleHeaders - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_headers.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleHeaders.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleHeaders.mak new file mode 100644 index 0000000000..f778acc1a3 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleHeaders.mak @@ -0,0 +1,230 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleHeaders.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleHeaders - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleHeaders - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleHeaders - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleHeaders - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleHeaders.mak"\ + CFG="ApacheModuleHeaders - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleHeaders - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleHeaders - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleHeaders - Win32 Release" + +OUTDIR=.\ApacheModuleHeadersR +INTDIR=.\ApacheModuleHeadersR +# Begin Custom Macros +OutDir=.\.\ApacheModuleHeadersR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleHeaders.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleHeaders.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_headers.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleHeaders.dll" + -@erase "$(OUTDIR)\ApacheModuleHeaders.exp" + -@erase "$(OUTDIR)\ApacheModuleHeaders.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleHeaders.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleHeadersR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleHeaders.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleHeaders.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleHeaders.dll"\ + /implib:"$(OUTDIR)\ApacheModuleHeaders.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_headers.obj" + +"$(OUTDIR)\ApacheModuleHeaders.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleHeaders - Win32 Debug" + +OUTDIR=.\ApacheModuleHeadersD +INTDIR=.\ApacheModuleHeadersD +# Begin Custom Macros +OutDir=.\.\ApacheModuleHeadersD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleHeaders.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleHeaders.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_headers.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleHeaders.dll" + -@erase "$(OUTDIR)\ApacheModuleHeaders.exp" + -@erase "$(OUTDIR)\ApacheModuleHeaders.ilk" + -@erase "$(OUTDIR)\ApacheModuleHeaders.lib" + -@erase "$(OUTDIR)\ApacheModuleHeaders.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleHeaders.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleHeadersD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleHeaders.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleHeaders.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleHeaders.dll"\ + /implib:"$(OUTDIR)\ApacheModuleHeaders.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_headers.obj" + +"$(OUTDIR)\ApacheModuleHeaders.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleHeaders - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleHeaders - Win32 Debug" +SOURCE=..\..\modules\standard\mod_headers.c + +!IF "$(CFG)" == "ApacheModuleHeaders - Win32 Release" + +DEP_CPP_MOD_H=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_H=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_headers.obj" : $(SOURCE) $(DEP_CPP_MOD_H) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleHeaders - Win32 Debug" + +DEP_CPP_MOD_H=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_headers.obj" : $(SOURCE) $(DEP_CPP_MOD_H) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleInfo.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleInfo.dsp new file mode 100644 index 0000000000..cf85646335 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleInfo.dsp @@ -0,0 +1,112 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleInfo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleInfo - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleInfo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleInfo.mak" CFG="ApacheModuleInfo - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleInfo - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleInfo - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleInfo - 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 ".\ApacheModuleInfoR" +# PROP Intermediate_Dir ".\ApacheModuleInfoR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleInfo - 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 ".\ApacheModuleInfoD" +# PROP Intermediate_Dir ".\ApacheModuleInfoD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleInfo - Win32 Release" +# Name "ApacheModuleInfo - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_info.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleInfo.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleInfo.mak new file mode 100644 index 0000000000..3336549e9a --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleInfo.mak @@ -0,0 +1,210 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleInfo.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleInfo - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleInfo - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleInfo - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleInfo - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleInfo.mak" CFG="ApacheModuleInfo - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleInfo - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleInfo - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleInfo - Win32 Release" + +OUTDIR=.\ApacheModuleInfoR +INTDIR=.\ApacheModuleInfoR +# Begin Custom Macros +OutDir=.\.\ApacheModuleInfoR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleInfo.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleInfo.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_info.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleInfo.dll" + -@erase "$(OUTDIR)\ApacheModuleInfo.exp" + -@erase "$(OUTDIR)\ApacheModuleInfo.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleInfo.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleInfoR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleInfo.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleInfo.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleInfo.dll" /implib:"$(OUTDIR)\ApacheModuleInfo.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_info.obj" + +"$(OUTDIR)\ApacheModuleInfo.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleInfo - Win32 Debug" + +OUTDIR=.\ApacheModuleInfoD +INTDIR=.\ApacheModuleInfoD +# Begin Custom Macros +OutDir=.\.\ApacheModuleInfoD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleInfo.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleInfo.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_info.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleInfo.dll" + -@erase "$(OUTDIR)\ApacheModuleInfo.exp" + -@erase "$(OUTDIR)\ApacheModuleInfo.ilk" + -@erase "$(OUTDIR)\ApacheModuleInfo.lib" + -@erase "$(OUTDIR)\ApacheModuleInfo.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleInfo.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleInfoD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleInfo.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleInfo.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleInfo.dll"\ + /implib:"$(OUTDIR)\ApacheModuleInfo.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_info.obj" + +"$(OUTDIR)\ApacheModuleInfo.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleInfo - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleInfo - Win32 Debug" +SOURCE=..\..\modules\standard\mod_info.c +DEP_CPP_MOD_I=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_conf_globals.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_script.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_I=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_info.obj" : $(SOURCE) $(DEP_CPP_MOD_I) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleRewrite.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleRewrite.dsp new file mode 100644 index 0000000000..91de834bc4 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleRewrite.dsp @@ -0,0 +1,117 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleRewrite" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleRewrite - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleRewrite.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleRewrite.mak"\ + CFG="ApacheModuleRewrite - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleRewrite - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleRewrite - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleRewrite - 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 ".\ApacheModuleRewriteR" +# PROP Intermediate_Dir ".\ApacheModuleRewriteR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 wsock32.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleRewrite - 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 ".\ApacheModuleRewriteD" +# PROP Intermediate_Dir ".\ApacheModuleRewriteD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleRewrite - Win32 Release" +# Name "ApacheModuleRewrite - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_rewrite.c +# End Source File +# Begin Source File + +SOURCE=.\passwd.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleRewrite.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleRewrite.mak new file mode 100644 index 0000000000..0579ba2727 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleRewrite.mak @@ -0,0 +1,248 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleRewrite.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleRewrite - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleRewrite - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleRewrite - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleRewrite - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleRewrite.mak"\ + CFG="ApacheModuleRewrite - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleRewrite - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleRewrite - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleRewrite - Win32 Release" + +OUTDIR=.\ApacheModuleRewriteR +INTDIR=.\ApacheModuleRewriteR +# Begin Custom Macros +OutDir=.\.\ApacheModuleRewriteR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleRewrite.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleRewrite.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_rewrite.obj" + -@erase "$(INTDIR)\passwd.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleRewrite.dll" + -@erase "$(OUTDIR)\ApacheModuleRewrite.exp" + -@erase "$(OUTDIR)\ApacheModuleRewrite.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE"\ + /Fp"$(INTDIR)\ApacheModuleRewrite.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleRewriteR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleRewrite.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo\ + /subsystem:windows /dll /incremental:no\ + /pdb:"$(OUTDIR)\ApacheModuleRewrite.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleRewrite.dll"\ + /implib:"$(OUTDIR)\ApacheModuleRewrite.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_rewrite.obj" \ + "$(INTDIR)\passwd.obj" + +"$(OUTDIR)\ApacheModuleRewrite.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleRewrite - Win32 Debug" + +OUTDIR=.\ApacheModuleRewriteD +INTDIR=.\ApacheModuleRewriteD +# Begin Custom Macros +OutDir=.\.\ApacheModuleRewriteD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleRewrite.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleRewrite.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_rewrite.obj" + -@erase "$(INTDIR)\passwd.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleRewrite.dll" + -@erase "$(OUTDIR)\ApacheModuleRewrite.exp" + -@erase "$(OUTDIR)\ApacheModuleRewrite.ilk" + -@erase "$(OUTDIR)\ApacheModuleRewrite.lib" + -@erase "$(OUTDIR)\ApacheModuleRewrite.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE"\ + /Fp"$(INTDIR)\ApacheModuleRewrite.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleRewriteD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleRewrite.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo\ + /subsystem:windows /dll /incremental:yes\ + /pdb:"$(OUTDIR)\ApacheModuleRewrite.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleRewrite.dll"\ + /implib:"$(OUTDIR)\ApacheModuleRewrite.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_rewrite.obj" \ + "$(INTDIR)\passwd.obj" + +"$(OUTDIR)\ApacheModuleRewrite.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleRewrite - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleRewrite - Win32 Debug" +SOURCE=..\..\modules\standard\mod_rewrite.c + +!IF "$(CFG)" == "ApacheModuleRewrite - Win32 Release" + +DEP_CPP_MOD_R=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_request.h"\ + "..\..\include\httpd.h"\ + "..\..\modules\standard\mod_rewrite.h"\ + ".\os.h"\ + ".\passwd.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_rewrite.obj" : $(SOURCE) $(DEP_CPP_MOD_R) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleRewrite - Win32 Debug" + +DEP_CPP_MOD_R=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_request.h"\ + "..\..\include\http_vhost.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + "..\..\modules\standard\mod_rewrite.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_rewrite.obj" : $(SOURCE) $(DEP_CPP_MOD_R) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\passwd.c +DEP_CPP_PASSW=\ + ".\passwd.h"\ + + +"$(INTDIR)\passwd.obj" : $(SOURCE) $(DEP_CPP_PASSW) "$(INTDIR)" + + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleSpeling.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleSpeling.dsp new file mode 100644 index 0000000000..499a72f3f7 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleSpeling.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleSpeling" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleSpeling - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleSpeling.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleSpeling.mak"\ + CFG="ApacheModuleSpeling - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleSpeling - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleSpeling - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleSpeling - 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 ".\ApacheModuleSpelingR" +# PROP Intermediate_Dir ".\ApacheModuleSpelingR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleSpeling - 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 ".\ApacheModuleSpelingD" +# PROP Intermediate_Dir ".\ApacheModuleSpelingD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleSpeling - Win32 Release" +# Name "ApacheModuleSpeling - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_speling.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleSpeling.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleSpeling.mak new file mode 100644 index 0000000000..12edeee2e7 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleSpeling.mak @@ -0,0 +1,234 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleSpeling.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleSpeling - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleSpeling - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleSpeling - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleSpeling - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleSpeling.mak"\ + CFG="ApacheModuleSpeling - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleSpeling - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleSpeling - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleSpeling - Win32 Release" + +OUTDIR=.\ApacheModuleSpelingR +INTDIR=.\ApacheModuleSpelingR +# Begin Custom Macros +OutDir=.\.\ApacheModuleSpelingR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleSpeling.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleSpeling.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_speling.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleSpeling.dll" + -@erase "$(OUTDIR)\ApacheModuleSpeling.exp" + -@erase "$(OUTDIR)\ApacheModuleSpeling.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleSpeling.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleSpelingR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleSpeling.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleSpeling.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleSpeling.dll"\ + /implib:"$(OUTDIR)\ApacheModuleSpeling.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_speling.obj" + +"$(OUTDIR)\ApacheModuleSpeling.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleSpeling - Win32 Debug" + +OUTDIR=.\ApacheModuleSpelingD +INTDIR=.\ApacheModuleSpelingD +# Begin Custom Macros +OutDir=.\.\ApacheModuleSpelingD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleSpeling.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleSpeling.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_speling.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleSpeling.dll" + -@erase "$(OUTDIR)\ApacheModuleSpeling.exp" + -@erase "$(OUTDIR)\ApacheModuleSpeling.ilk" + -@erase "$(OUTDIR)\ApacheModuleSpeling.lib" + -@erase "$(OUTDIR)\ApacheModuleSpeling.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleSpeling.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleSpelingD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleSpeling.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleSpeling.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleSpeling.dll"\ + /implib:"$(OUTDIR)\ApacheModuleSpeling.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_speling.obj" + +"$(OUTDIR)\ApacheModuleSpeling.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleSpeling - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleSpeling - Win32 Debug" +SOURCE=..\..\modules\standard\mod_speling.c + +!IF "$(CFG)" == "ApacheModuleSpeling - Win32 Release" + +DEP_CPP_MOD_S=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_S=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_speling.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleSpeling - Win32 Debug" + +DEP_CPP_MOD_S=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_speling.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleStatus.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleStatus.dsp new file mode 100644 index 0000000000..8bc9271959 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleStatus.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleStatus" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleStatus - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleStatus.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleStatus.mak"\ + CFG="ApacheModuleStatus - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleStatus - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleStatus - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleStatus - 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 ".\ApacheModuleStatusR" +# PROP Intermediate_Dir ".\ApacheModuleStatusR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleStatus - 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 ".\ApacheModuleStatusD" +# PROP Intermediate_Dir ".\ApacheModuleStatusD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleStatus - Win32 Release" +# Name "ApacheModuleStatus - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_status.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleStatus.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleStatus.mak new file mode 100644 index 0000000000..00e7df6398 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleStatus.mak @@ -0,0 +1,242 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleStatus.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleStatus - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleStatus - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleStatus - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleStatus - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleStatus.mak"\ + CFG="ApacheModuleStatus - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleStatus - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleStatus - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleStatus - Win32 Release" + +OUTDIR=.\ApacheModuleStatusR +INTDIR=.\ApacheModuleStatusR +# Begin Custom Macros +OutDir=.\.\ApacheModuleStatusR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleStatus.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleStatus.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_status.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleStatus.dll" + -@erase "$(OUTDIR)\ApacheModuleStatus.exp" + -@erase "$(OUTDIR)\ApacheModuleStatus.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleStatus.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleStatusR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleStatus.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleStatus.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleStatus.dll"\ + /implib:"$(OUTDIR)\ApacheModuleStatus.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_status.obj" + +"$(OUTDIR)\ApacheModuleStatus.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleStatus - Win32 Debug" + +OUTDIR=.\ApacheModuleStatusD +INTDIR=.\ApacheModuleStatusD +# Begin Custom Macros +OutDir=.\.\ApacheModuleStatusD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleStatus.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleStatus.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_status.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleStatus.dll" + -@erase "$(OUTDIR)\ApacheModuleStatus.exp" + -@erase "$(OUTDIR)\ApacheModuleStatus.ilk" + -@erase "$(OUTDIR)\ApacheModuleStatus.lib" + -@erase "$(OUTDIR)\ApacheModuleStatus.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleStatus.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleStatusD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleStatus.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleStatus.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleStatus.dll"\ + /implib:"$(OUTDIR)\ApacheModuleStatus.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_status.obj" + +"$(OUTDIR)\ApacheModuleStatus.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleStatus - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleStatus - Win32 Debug" +SOURCE=..\..\modules\standard\mod_status.c + +!IF "$(CFG)" == "ApacheModuleStatus - Win32 Release" + +DEP_CPP_MOD_S=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\scoreboard.h"\ + "..\..\include\util_script.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_S=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_status.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleStatus - Win32 Debug" + +DEP_CPP_MOD_S=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\scoreboard.h"\ + "..\..\include\util_script.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_status.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleUserTrack.dsp b/APACHE_1_3b7/src/os/win32/ApacheModuleUserTrack.dsp new file mode 100644 index 0000000000..e3aee558ce --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleUserTrack.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleUserTrack" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleUserTrack - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleUserTrack.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleUserTrack.mak"\ + CFG="ApacheModuleUserTrack - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleUserTrack - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleUserTrack - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleUserTrack - 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 ".\ApacheModuleUserTrackR" +# PROP Intermediate_Dir ".\ApacheModuleUserTrackR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleUserTrack - 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 ".\ApacheModuleUserTrackD" +# PROP Intermediate_Dir ".\ApacheModuleUserTrackD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleUserTrack - Win32 Release" +# Name "ApacheModuleUserTrack - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=..\..\modules\standard\mod_usertrack.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheModuleUserTrack.mak b/APACHE_1_3b7/src/os/win32/ApacheModuleUserTrack.mak new file mode 100644 index 0000000000..7429095215 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheModuleUserTrack.mak @@ -0,0 +1,233 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleUserTrack.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleUserTrack - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleUserTrack -\ + Win32 Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleUserTrack - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleUserTrack - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheModuleUserTrack.mak"\ + CFG="ApacheModuleUserTrack - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleUserTrack - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleUserTrack - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleUserTrack - Win32 Release" + +OUTDIR=.\ApacheModuleUserTrackR +INTDIR=.\ApacheModuleUserTrackR +# Begin Custom Macros +OutDir=.\.\ApacheModuleUserTrackR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleUserTrack.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleUserTrack.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_usertrack.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.dll" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.exp" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleUserTrack.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleUserTrackR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleUserTrack.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleUserTrack.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleUserTrack.dll"\ + /implib:"$(OUTDIR)\ApacheModuleUserTrack.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_usertrack.obj" + +"$(OUTDIR)\ApacheModuleUserTrack.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleUserTrack - Win32 Debug" + +OUTDIR=.\ApacheModuleUserTrackD +INTDIR=.\ApacheModuleUserTrackD +# Begin Custom Macros +OutDir=.\.\ApacheModuleUserTrackD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleUserTrack.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleUserTrack.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_usertrack.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.dll" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.exp" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.ilk" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.lib" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE"\ + /Fp"$(INTDIR)\ApacheModuleUserTrack.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleUserTrackD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleUserTrack.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleUserTrack.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleUserTrack.dll"\ + /implib:"$(OUTDIR)\ApacheModuleUserTrack.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_usertrack.obj" + +"$(OUTDIR)\ApacheModuleUserTrack.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleUserTrack - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleUserTrack - Win32 Debug" +SOURCE=..\..\modules\standard\mod_usertrack.c + +!IF "$(CFG)" == "ApacheModuleUserTrack - Win32 Release" + +DEP_CPP_MOD_U=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_U=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_usertrack.obj" : $(SOURCE) $(DEP_CPP_MOD_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleUserTrack - Win32 Debug" + +DEP_CPP_MOD_U=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_usertrack.obj" : $(SOURCE) $(DEP_CPP_MOD_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/ApacheOS.dsp b/APACHE_1_3b7/src/os/win32/ApacheOS.dsp new file mode 100755 index 0000000000..55b814873e --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheOS.dsp @@ -0,0 +1,86 @@ +# Microsoft Developer Studio Project File - Name="ApacheOS" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=ApacheOS - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ApacheOS.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheOS.mak" CFG="ApacheOS - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheOS - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ApacheOS - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "ApacheOS - 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 "ApacheOSR" +# PROP Intermediate_Dir "ApacheOSR" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "ApacheOS - 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 "ApacheOSD" +# PROP Intermediate_Dir "ApacheOSD" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "ApacheOS - Win32 Release" +# Name "ApacheOS - Win32 Debug" +# Begin Source File + +SOURCE=.\os.c +# End Source File +# Begin Source File + +SOURCE=.\os.h +# End Source File +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/ApacheOS.mak b/APACHE_1_3b7/src/os/win32/ApacheOS.mak new file mode 100755 index 0000000000..4630d8c54b --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/ApacheOS.mak @@ -0,0 +1,164 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheOS.dsp +!IF "$(CFG)" == "" +CFG=ApacheOS - Win32 Debug +!MESSAGE No configuration specified. Defaulting to ApacheOS - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "ApacheOS - Win32 Release" && "$(CFG)" !=\ + "ApacheOS - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ApacheOS.mak" CFG="ApacheOS - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheOS - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ApacheOS - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe + +!IF "$(CFG)" == "ApacheOS - Win32 Release" + +OUTDIR=.\ApacheOSR +INTDIR=.\ApacheOSR +# Begin Custom Macros +OutDir=.\ApacheOSR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheOS.lib" + +!ELSE + +ALL : "$(OUTDIR)\ApacheOS.lib" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\os.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheOS.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)\ApacheOS.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheOSR/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheOS.bsc" +BSC32_SBRS= \ + +LIB32=link.exe -lib +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ApacheOS.lib" +LIB32_OBJS= \ + "$(INTDIR)\os.obj" + +"$(OUTDIR)\ApacheOS.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheOS - Win32 Debug" + +OUTDIR=.\ApacheOSD +INTDIR=.\ApacheOSD +# Begin Custom Macros +OutDir=.\ApacheOSD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheOS.lib" + +!ELSE + +ALL : "$(OUTDIR)\ApacheOS.lib" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\os.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheOS.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)\ApacheOS.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheOSD/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheOS.bsc" +BSC32_SBRS= \ + +LIB32=link.exe -lib +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ApacheOS.lib" +LIB32_OBJS= \ + "$(INTDIR)\os.obj" + +"$(OUTDIR)\ApacheOS.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_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) $< +<< + + +!IF "$(CFG)" == "ApacheOS - Win32 Release" || "$(CFG)" ==\ + "ApacheOS - Win32 Debug" +SOURCE=.\os.c +DEP_CPP_OS_C0=\ + ".\os.h"\ + + +"$(INTDIR)\os.obj" : $(SOURCE) $(DEP_CPP_OS_C0) "$(INTDIR)" + + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/MakeModuleMak.cpp b/APACHE_1_3b7/src/os/win32/MakeModuleMak.cpp new file mode 100644 index 0000000000..9ab9f27221 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/MakeModuleMak.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +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] << " [ ]+\n"; + exit(1); + } + for(int n=1 ; n < argc ; n+=2) + MakeMake(argv[n],argv[n+1]); + } + diff --git a/APACHE_1_3b7/src/os/win32/MakeModuleMak.mak b/APACHE_1_3b7/src/os/win32/MakeModuleMak.mak new file mode 100644 index 0000000000..6b51ed0834 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/MakeModuleMak.mak @@ -0,0 +1,195 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=MakeModuleMak - Win32 Debug +!MESSAGE No configuration specified. Defaulting to MakeModuleMak - Win32\ + Debug. +!ENDIF + +!IF "$(CFG)" != "MakeModuleMak - Win32 Release" && "$(CFG)" !=\ + "MakeModuleMak - 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 "MakeModuleMak.mak" CFG="MakeModuleMak - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "MakeModuleMak - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "MakeModuleMak - Win32 Debug" (based on\ + "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +RSC=rc.exe +CPP=cl.exe + +!IF "$(CFG)" == "MakeModuleMak - 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 "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "$(OUTDIR)\MakeModuleMak.exe" + +CLEAN : + -@erase "$(INTDIR)\MakeModuleMak.obj" + -@erase "$(OUTDIR)\MakeModuleMak.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)/MakeModuleMak.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS=.\. +# 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)/MakeModuleMak.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:console /machine:I386 +# ADD 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:console /machine:I386 +LINK32_FLAGS=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:console /incremental:no\ + /pdb:"$(OUTDIR)/MakeModuleMak.pdb" /machine:I386\ + /out:"$(OUTDIR)/MakeModuleMak.exe" +LINK32_OBJS= \ + "$(INTDIR)\MakeModuleMak.obj" + +"$(OUTDIR)\MakeModuleMak.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "MakeModuleMak - 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 "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : "$(OUTDIR)\MakeModuleMak.exe" + +CLEAN : + -@erase "$(INTDIR)\MakeModuleMak.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\MakeModuleMak.exe" + -@erase "$(OUTDIR)\MakeModuleMak.ilk" + -@erase "$(OUTDIR)\MakeModuleMak.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)/MakeModuleMak.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS=.\. +# 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)/MakeModuleMak.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:console /debug /machine:I386 +# ADD 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:console /debug /machine:I386 +LINK32_FLAGS=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:console /incremental:yes\ + /pdb:"$(OUTDIR)/MakeModuleMak.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)/MakeModuleMak.exe" +LINK32_OBJS= \ + "$(INTDIR)\MakeModuleMak.obj" + +"$(OUTDIR)\MakeModuleMak.exe" : "$(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 "MakeModuleMak - Win32 Release" +# Name "MakeModuleMak - Win32 Debug" + +!IF "$(CFG)" == "MakeModuleMak - Win32 Release" + +!ELSEIF "$(CFG)" == "MakeModuleMak - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\MakeModuleMak.cpp + +"$(INTDIR)\MakeModuleMak.obj" : $(SOURCE) "$(INTDIR)" + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/APACHE_1_3b7/src/os/win32/Module.mak.tmpl b/APACHE_1_3b7/src/os/win32/Module.mak.tmpl new file mode 100644 index 0000000000..cb9c4418a3 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/Module.mak.tmpl @@ -0,0 +1,229 @@ +# 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"\ + ".\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/APACHE_1_3b7/src/os/win32/getopt.c b/APACHE_1_3b7/src/os/win32/getopt.c new file mode 100644 index 0000000000..187807216a --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/getopt.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include + +#ifdef WIN32 + +#define OPTERRCOLON (1) +#define OPTERRNF (2) +#define OPTERRARG (3) + +char *optarg; +int optind = 1; +int opterr = 1; +int optopt; + +static int +optiserr(int argc, char * const *argv, int oint, const char *optstr, + int optchr, int err) +{ + if(opterr) + { + fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1); + switch(err) + { + case OPTERRCOLON: + fprintf(stderr, ": in flags\n"); + break; + case OPTERRNF: + fprintf(stderr, "option not found %c\n", argv[oint][optchr]); + break; + case OPTERRARG: + fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]); + break; + default: + fprintf(stderr, "unknown\n"); + break; + } + } + optopt = argv[oint][optchr]; + return('?'); +} + + + +int +getopt(int argc, char* const *argv, const char *optstr) +{ + static int optchr = 0; + static int dash = 0; /* have already seen the - */ + + char *cp; + + if(optind >= argc) + return(EOF); + if(!dash && (argv[optind][0] != '-')) + return(EOF); + if(!dash && (argv[optind][0] == '-') && !argv[optind][1]) + { + /* + * use to specify stdin. Need to let pgm process this and + * the following args + */ + return(EOF); + } + if((argv[optind][0] == '-') && (argv[optind][1] == '-')) + { + /* -- indicates end of args */ + optind++; + return(EOF); + } + if(!dash) + { + assert((argv[optind][0] == '-') && argv[optind][1]); + dash = 1; + optchr = 1; + } + + /* Check if the guy tries to do a -: kind of flag */ + assert(dash); + if(argv[optind][optchr] == ':') + { + dash = 0; + optind++; + return(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRCOLON)); + } + if(!(cp = strchr(optstr, argv[optind][optchr]))) + { + int errind = optind; + int errchr = optchr; + + if(!argv[optind][optchr+1]) + { + dash = 0; + optind++; + } + else + optchr++; + return(optiserr(argc, argv, errind, optstr, errchr, OPTERRNF)); + } + if(cp[1] == ':') + { + dash = 0; + optind++; + if(optind == argc) + return(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRARG)); + optarg = argv[optind++]; + return(*cp); + } + else + { + if(!argv[optind][optchr+1]) + { + dash = 0; + optind++; + } + else + optchr++; + return(*cp); + } + assert(0); + return(0); +} + +#endif /* WIN32 */ + +#ifdef TESTGETOPT +int + main (int argc, char **argv) + { + int c; + extern char *optarg; + extern int optind; + int aflg = 0; + int bflg = 0; + int errflg = 0; + char *ofile = NULL; + + while ((c = getopt(argc, argv, "abo:")) != EOF) + switch (c) { + case 'a': + if (bflg) + errflg++; + else + aflg++; + break; + case 'b': + if (aflg) + errflg++; + else + bflg++; + break; + case 'o': + ofile = optarg; + (void)printf("ofile = %s\n", ofile); + break; + case '?': + errflg++; + } + if (errflg) { + (void)fprintf(stderr, + "usage: cmd [-a|-b] [-o ] files...\n"); + exit (2); + } + for ( ; optind < argc; optind++) + (void)printf("%s\n", argv[optind]); + return 0; + } + +#endif /* TESTGETOPT */ \ No newline at end of file diff --git a/APACHE_1_3b7/src/os/win32/getopt.h b/APACHE_1_3b7/src/os/win32/getopt.h new file mode 100644 index 0000000000..f0a4e696ce --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/getopt.h @@ -0,0 +1,10 @@ +#ifndef GETOPT_H +#define GETOPT_H + +extern char *optarg; +extern int optind; +extern int opterr; +extern int optopt; +int getopt(int argc, char* const *argv, const char *optstr); + +#endif /* GETOPT_H */ \ No newline at end of file diff --git a/APACHE_1_3b7/src/os/win32/installer/README.TXT b/APACHE_1_3b7/src/os/win32/installer/README.TXT new file mode 100644 index 0000000000..247cdd1fe3 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/README.TXT @@ -0,0 +1,6 @@ +Read the Apache for Windows how to release document at + + http://dev.apache.org/how-to-release-win32.html + +for details of how to use this IS2 configuration file and +the installer DLL to build an Apache release. diff --git a/APACHE_1_3b7/src/os/win32/installer/apache.iwz b/APACHE_1_3b7/src/os/win32/installer/apache.iwz new file mode 100644 index 0000000000..c4a4ddfe32 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/apache.iwz @@ -0,0 +1,842 @@ + +[InstallShield Wizard] +iDate=1 +iTime=1 +Flag=fe000000 +ISX.EXE Size=686080 +ISX.EXE Date=16:54:10 28/4/1997 +ISX.EXE Ver=2.0.0.129 +SETUP.EXE Size=45312 +SETUP.EXE Date=11:53:32 18/1/1997 +SETUP.EXE Ver=3.0.111.0 +SETUP.INS Size=68971 +SETUP.INS Date=21:43:00 28/4/1997 +SETUP.INS Ver=Not available +_INST16.EX_ Size=282766 +_INST16.EX_ Date=11:56:04 18/1/1997 +_INST16.EX_ Ver=Not available +_INST32I.EX_ Size=320411 +_INST32I.EX_ Date=12:04:08 18/1/1997 +_INST32I.EX_ Ver=Not available +ISDEPEND.INI Size=320411 +ISDEPEND.INI Date=12:04:08 18/1/1997 +ISDEPEND.INI Ver=Not available +SWDEPEND.INI Size=320411 +SWDEPEND.INI Date=12:04:08 18/1/1997 +SWDEPEND.INI Ver=Not available +ICOMP.EXE Size=119808 +ICOMP.EXE Date=16:05:10 15/1/1996 +ICOMP.EXE Ver=3.00.062 +SPLIT.EXE Size=90624 +SPLIT.EXE Date=16:09:36 15/1/1996 +SPLIT.EXE Ver=3.00.060 +PACKLIST.EXE Size=87552 +PACKLIST.EXE Date=16:10:30 15/1/1996 +PACKLIST.EXE Ver=3.00.060 +Version=2.0 +DevTool=Generic Windows +Platform=Win32 +DisksBuilt=1 +DisksDir=apache\650MB\ +TabsVisit=1111001110000111100011 +LangNum=451 +LangDir=LANG\ENG\ + +[VisualDesign] +AppName=Apache +AppExe= +AppExeFile= +Version=1.3b6 +Company=Apache Group +Title=Apache Web Server 1.3b6 +TitleType=1 +BackgrndBmp= +BackgrndAlign=4 +Backgrnd=1 +BackgrndColor=10 +Uninstall=1 +Silent=1 +SmsMode=0 + +[Types] +Types=3 +Type1Components=6 +Type1Name=Custom +Type1ComponentList=1 2 3 4 5 6 +Type2Components=5 +Type2Name=Typical +Type2ComponentList=1 3 4 5 6 +Type3Components=2 +Type3Name=Compact +Type3ComponentList=1 6 + +[Components] +Components=6 +Component1Groups=5 +Component1Name=Application Files +Component1Description=Application files needed to run the application +Component1GroupList=1 3 24 25 4 +Component2Groups=14 +Component2Name=Source Code +Component2Description=Source code for Apache and support tools +Component2GroupList=10 11 12 13 14 15 16 17 18 19 20 21 22 23 +Component3Groups=5 +Component3Name=Apache Manual +Component3Description=Apache documentation +Component3GroupList=5 6 7 8 9 +Component4Groups=1 +Component4Name=Additional Modules +Component4Description=Apache modules to extend the server +Component4GroupList=2 +Component5Groups=1 +Component5Name=Icons +Component5Description=Icons for directory indexes +Component5GroupList=27 +Component6Groups=4 +Component6Name=Required Directories +Component6Description= +Component6GroupList=26 28 29 30 + +[Groups] +Groups=30 +Group1Size=478242 +Group1Files=10 +Group1Name=Program Executables +Group1Dir= +Group1Update=0 +Group1File1=C:\Apache\Apache.exe +Group1File2=C:\Apache\ApacheCore.dll +Group1File3=C:\Apache\Announcement +Group1File4=C:\Apache\ABOUT_APACHE +Group1File5=C:\Apache\CHANGES +Group1File6=C:\Apache\KEYS +Group1File7=C:\Apache\LICENSE +Group1File8=C:\Apache\README +Group1File9=C:\Apache\README.NT +Group1File10=C:\apache\Makefile.tmpl +Group2Size=258048 +Group2Files=10 +Group2Name=Additional Modules +Group2Dir=\modules +Group2Update=0 +Group2File1=C:\Apache\modules\ApacheModuleDigest.dll +Group2File2=C:\Apache\modules\ApacheModuleCERNMeta.dll +Group2File3=C:\Apache\modules\ApacheModuleAuthAnon.dll +Group2File4=C:\Apache\modules\ApacheModuleExpires.dll +Group2File5=C:\Apache\modules\ApacheModuleHeaders.dll +Group2File6=C:\Apache\modules\ApacheModuleProxy.dll +Group2File7=C:\Apache\modules\ApacheModuleSpeling.dll +Group2File8=C:\Apache\modules\ApacheModuleStatus.dll +Group2File9=C:\Apache\modules\ApacheModuleUserTrack.dll +Group2File10=C:\apache\modules\ApacheModuleRewrite.dll +Group3Size=34849 +Group3Files=6 +Group3Name=Configuration Files +Group3Dir=\.tmp +Group3Update=0 +Group3File1=C:\Apache\conf\httpd.conf-dist-win +Group3File2=C:\Apache\conf\access.conf-dist-win +Group3File3=C:\Apache\conf\magic +Group3File4=C:\Apache\conf\mime.types +Group3File5=C:\Apache\conf\srm.conf-dist-win +Group3File6=C:\apache\conf\highperformance.conf-dist +Group4Size=3642 +Group4Files=2 +Group4Name=Initial Document Root Files +Group4Dir=\.tmp +Group4Update=0 +Group4File1=C:\Apache\htdocs\apache_pb.gif +Group4File2=C:\Apache\htdocs\index.html +Group5Size=216846 +Group5Files=31 +Group5Name=Manual +Group5Dir=\htdocs\manual +Group5Update=0 +Group5File1=C:\Apache\htdocs\manual\bind.html +Group5File2=C:\Apache\htdocs\manual\cgi_path.html +Group5File3=C:\Apache\htdocs\manual\content-negotiation.html +Group5File4=C:\Apache\htdocs\manual\custom-error.html +Group5File5=C:\Apache\htdocs\manual\dns-caveats.html +Group5File6=C:\Apache\htdocs\manual\env.html +Group5File7=C:\Apache\htdocs\manual\footer.html +Group5File8=C:\Apache\htdocs\manual\handler.html +Group5File9=C:\Apache\htdocs\manual\header.html +Group5File10=C:\Apache\htdocs\manual\index.html +Group5File11=C:\Apache\htdocs\manual\install.html +Group5File12=C:\Apache\htdocs\manual\invoking.html +Group5File13=C:\Apache\htdocs\manual\keepalive.html +Group5File14=C:\Apache\htdocs\manual\LICENSE +Group5File15=C:\Apache\htdocs\manual\location.html +Group5File16=C:\Apache\htdocs\manual\man-template.html +Group5File17=C:\Apache\htdocs\manual\multilogs.html +Group5File18=C:\Apache\htdocs\manual\new_features_1_0.html +Group5File19=C:\Apache\htdocs\manual\new_features_1_1.html +Group5File20=C:\Apache\htdocs\manual\new_features_1_2.html +Group5File21=C:\Apache\htdocs\manual\new_features_1_3.html +Group5File22=C:\Apache\htdocs\manual\process-model.html +Group5File23=C:\Apache\htdocs\manual\sections.html +Group5File24=C:\Apache\htdocs\manual\sourcereorg.html +Group5File25=C:\Apache\htdocs\manual\stopping.html +Group5File26=C:\Apache\htdocs\manual\suexec.html +Group5File27=C:\Apache\htdocs\manual\TODO +Group5File28=C:\Apache\htdocs\manual\unixware.html +Group5File29=C:\Apache\htdocs\manual\upgrading_to_1_3.html +Group5File30=C:\Apache\htdocs\manual\windows.html +Group5File31=C:\apache\htdocs\manual\ebcdic.html +Group6Size=42368 +Group6Files=8 +Group6Name=images +Group6Dir=[Manual]\images +Group6Update=0 +Group6File1=C:\Apache\htdocs\manual\images\custom_errordocs.gif +Group6File2=C:\Apache\htdocs\manual\images\home.gif +Group6File3=C:\Apache\htdocs\manual\images\index.gif +Group6File4=C:\Apache\htdocs\manual\images\sub.gif +Group6File5=C:\apache\htdocs\manual\images\mod_rewrite_fig1.fig +Group6File6=C:\apache\htdocs\manual\images\mod_rewrite_fig1.gif +Group6File7=C:\apache\htdocs\manual\images\mod_rewrite_fig2.fig +Group6File8=C:\apache\htdocs\manual\images\mod_rewrite_fig2.gif +Group7Size=312558 +Group7Files=22 +Group7Name=misc +Group7Dir=[Manual]\misc +Group7Update=0 +Group7File1=C:\Apache\htdocs\manual\misc\API.html +Group7File2=C:\Apache\htdocs\manual\misc\client_block_api.html +Group7File3=C:\Apache\htdocs\manual\misc\compat_notes.html +Group7File4=C:\Apache\htdocs\manual\misc\custom_errordocs.html +Group7File5=C:\Apache\htdocs\manual\misc\descriptors.html +Group7File6=C:\Apache\htdocs\manual\misc\FAQ.html +Group7File7=C:\Apache\htdocs\manual\misc\fin_wait_2.html +Group7File8=C:\Apache\htdocs\manual\misc\footer.html +Group7File9=C:\Apache\htdocs\manual\misc\header.html +Group7File10=C:\Apache\htdocs\manual\misc\howto.html +Group7File11=C:\Apache\htdocs\manual\misc\index.html +Group7File12=C:\Apache\htdocs\manual\misc\known_bugs.html +Group7File13=C:\Apache\htdocs\manual\misc\known_client_problems.html +Group7File14=C:\Apache\htdocs\manual\misc\nopgp.html +Group7File15=C:\Apache\htdocs\manual\misc\perf-bsd44.html +Group7File16=C:\Apache\htdocs\manual\misc\perf-dec.html +Group7File17=C:\Apache\htdocs\manual\misc\perf-hp.html +Group7File18=C:\Apache\htdocs\manual\misc\perf-tuning.html +Group7File19=C:\Apache\htdocs\manual\misc\perf.html +Group7File20=C:\Apache\htdocs\manual\misc\security_tips.html +Group7File21=C:\Apache\htdocs\manual\misc\vif-info.html +Group7File22=C:\Apache\htdocs\manual\misc\windoz_keepalive.html +Group8Size=487855 +Group8Files=48 +Group8Name=mod +Group8Dir=[Manual]\mod +Group8Update=0 +Group8File1=C:\Apache\htdocs\manual\mod\core.html +Group8File2=C:\Apache\htdocs\manual\mod\directive-dict.html +Group8File3=C:\Apache\htdocs\manual\mod\directives.html +Group8File4=C:\Apache\htdocs\manual\mod\footer.html +Group8File5=C:\Apache\htdocs\manual\mod\header.html +Group8File6=C:\Apache\htdocs\manual\mod\index.html +Group8File7=C:\Apache\htdocs\manual\mod\mod_access.html +Group8File8=C:\Apache\htdocs\manual\mod\mod_actions.html +Group8File9=C:\Apache\htdocs\manual\mod\mod_alias.html +Group8File10=C:\Apache\htdocs\manual\mod\mod_asis.html +Group8File11=C:\Apache\htdocs\manual\mod\mod_auth.html +Group8File12=C:\Apache\htdocs\manual\mod\mod_auth_anon.html +Group8File13=C:\Apache\htdocs\manual\mod\mod_auth_db.html +Group8File14=C:\Apache\htdocs\manual\mod\mod_auth_dbm.html +Group8File15=C:\Apache\htdocs\manual\mod\mod_autoindex.html +Group8File16=C:\Apache\htdocs\manual\mod\mod_browser.html +Group8File17=C:\Apache\htdocs\manual\mod\mod_cern_meta.html +Group8File18=C:\Apache\htdocs\manual\mod\mod_cgi.html +Group8File19=C:\Apache\htdocs\manual\mod\mod_cookies.html +Group8File20=C:\Apache\htdocs\manual\mod\mod_digest.html +Group8File21=C:\Apache\htdocs\manual\mod\mod_dir.html +Group8File22=C:\Apache\htdocs\manual\mod\mod_dld.html +Group8File23=C:\Apache\htdocs\manual\mod\mod_dll.html +Group8File24=C:\Apache\htdocs\manual\mod\mod_env.html +Group8File25=C:\Apache\htdocs\manual\mod\mod_example.html +Group8File26=C:\Apache\htdocs\manual\mod\mod_expires.html +Group8File27=C:\Apache\htdocs\manual\mod\mod_headers.html +Group8File28=C:\Apache\htdocs\manual\mod\mod_imap.html +Group8File29=C:\Apache\htdocs\manual\mod\mod_include.html +Group8File30=C:\Apache\htdocs\manual\mod\mod_info.html +Group8File31=C:\Apache\htdocs\manual\mod\mod_isapi.html +Group8File32=C:\Apache\htdocs\manual\mod\mod_log_agent.html +Group8File33=C:\Apache\htdocs\manual\mod\mod_log_common.html +Group8File34=C:\Apache\htdocs\manual\mod\mod_log_config.html +Group8File35=C:\Apache\htdocs\manual\mod\mod_log_referer.html +Group8File36=C:\Apache\htdocs\manual\mod\mod_mime.html +Group8File37=C:\Apache\htdocs\manual\mod\mod_mime_magic.html +Group8File38=C:\Apache\htdocs\manual\mod\mod_negotiation.html +Group8File39=C:\Apache\htdocs\manual\mod\mod_proxy.html +Group8File40=C:\Apache\htdocs\manual\mod\mod_rewrite.html +Group8File41=C:\Apache\htdocs\manual\mod\mod_setenvif.html +Group8File42=C:\Apache\htdocs\manual\mod\mod_so.html +Group8File43=C:\Apache\htdocs\manual\mod\mod_speling.html +Group8File44=C:\Apache\htdocs\manual\mod\mod_status.html +Group8File45=C:\Apache\htdocs\manual\mod\mod_unique_id.html +Group8File46=C:\Apache\htdocs\manual\mod\mod_userdir.html +Group8File47=C:\Apache\htdocs\manual\mod\mod_usertrack.html +Group8File48=C:\apache\htdocs\manual\mod\mod_mmap_static.html +Group9Size=94293 +Group9Files=12 +Group9Name=vhosts +Group9Dir=[Manual]\vhosts +Group9Update=0 +Group9File1=C:\Apache\htdocs\manual\vhosts\details.html +Group9File2=C:\Apache\htdocs\manual\vhosts\details_1_2.html +Group9File3=C:\Apache\htdocs\manual\vhosts\examples.html +Group9File4=C:\Apache\htdocs\manual\vhosts\fd-limits.html +Group9File5=C:\Apache\htdocs\manual\vhosts\footer.html +Group9File6=C:\Apache\htdocs\manual\vhosts\header.html +Group9File7=C:\Apache\htdocs\manual\vhosts\host.html +Group9File8=C:\Apache\htdocs\manual\vhosts\index.html +Group9File9=C:\Apache\htdocs\manual\vhosts\ip-based.html +Group9File10=C:\Apache\htdocs\manual\vhosts\name-based.html +Group9File11=C:\Apache\htdocs\manual\vhosts\vhosts-in-depth.html +Group9File12=C:\Apache\htdocs\manual\vhosts\virtual-host.html +Group10Size=403016 +Group10Files=17 +Group10Name=src +Group10Dir=\src +Group10Update=0 +Group10File1=C:\Apache\src\.gdbinit +Group10File2=C:\Apache\src\Apache.dsp +Group10File3=C:\Apache\src\Apache.mak +Group10File4=C:\Apache\src\ApacheCore.def +Group10File5=C:\Apache\src\ApacheCore.dsp +Group10File6=C:\Apache\src\ApacheCore.mak +Group10File7=C:\Apache\src\buildmark.c +Group10File8=C:\Apache\src\CHANGES +Group10File9=C:\Apache\src\Configuration.tmpl +Group10File10=C:\Apache\src\Configure +Group10File11=C:\Apache\src\INSTALL +Group10File12=C:\Apache\src\Makefile.nt +Group10File13=C:\Apache\src\Makefile.tmpl +Group10File14=C:\Apache\src\PORTING +Group10File15=C:\Apache\src\README +Group10File16=C:\Apache\src\README.EBCDIC +Group10File17=C:\apache\src\README.DSO +Group11Size=60553 +Group11Files=9 +Group11Name=ap +Group11Dir=[src]\ap +Group11Update=0 +Group11File1=C:\Apache\src\ap\ap.dsp +Group11File2=C:\Apache\src\ap\ap.mak +Group11File3=C:\Apache\src\ap\ap_cpystrn.c +Group11File4=C:\Apache\src\ap\ap_execve.c +Group11File5=C:\Apache\src\ap\ap_signal.c +Group11File6=C:\Apache\src\ap\ap_slack.c +Group11File7=C:\Apache\src\ap\ap_snprintf.c +Group11File8=C:\Apache\src\ap\ap_strings.c +Group11File9=C:\Apache\src\ap\Makefile.tmpl +Group12Size=213647 +Group12Files=25 +Group12Name=include +Group12Dir=[src]\include +Group12Update=0 +Group12File1=C:\Apache\src\include\alloc.h +Group12File2=C:\Apache\src\include\ap.h +Group12File3=C:\Apache\src\include\buff.h +Group12File4=C:\Apache\src\include\conf.h +Group12File5=C:\Apache\src\include\explain.h +Group12File6=C:\Apache\src\include\fnmatch.h +Group12File7=C:\Apache\src\include\hsregex.h +Group12File8=C:\Apache\src\include\httpd.h +Group12File9=C:\Apache\src\include\http_config.h +Group12File10=C:\Apache\src\include\http_conf_globals.h +Group12File11=C:\Apache\src\include\http_core.h +Group12File12=C:\Apache\src\include\http_log.h +Group12File13=C:\Apache\src\include\http_main.h +Group12File14=C:\Apache\src\include\http_protocol.h +Group12File15=C:\Apache\src\include\http_request.h +Group12File16=C:\Apache\src\include\http_vhost.h +Group12File17=C:\Apache\src\include\md5.h +Group12File18=C:\Apache\src\include\multithread.h +Group12File19=C:\Apache\src\include\rfc1413.h +Group12File20=C:\Apache\src\include\scoreboard.h +Group12File21=C:\Apache\src\include\util_date.h +Group12File22=C:\Apache\src\include\util_md5.h +Group12File23=C:\Apache\src\include\util_script.h +Group12File24=C:\apache\src\include\compat.h +Group12File25=C:\apache\src\include\util_uri.h +Group13Size=677557 +Group13Files=25 +Group13Name=main +Group13Dir=[src]\main +Group13Update=0 +Group13File1=C:\apache\src\main\.indent.pro +Group13File2=C:\apache\src\main\alloc.c +Group13File3=C:\apache\src\main\buff.c +Group13File4=C:\apache\src\main\fnmatch.c +Group13File5=C:\apache\src\main\gen_test_char.c +Group13File6=C:\apache\src\main\gen_test_char.dsp +Group13File7=C:\apache\src\main\gen_test_char.mak +Group13File8=C:\apache\src\main\gen_uri_delims.c +Group13File9=C:\apache\src\main\gen_uri_delims.dsp +Group13File10=C:\apache\src\main\gen_uri_delims.mak +Group13File11=C:\apache\src\main\http_config.c +Group13File12=C:\apache\src\main\http_core.c +Group13File13=C:\apache\src\main\http_log.c +Group13File14=C:\apache\src\main\http_main.c +Group13File15=C:\apache\src\main\http_protocol.c +Group13File16=C:\apache\src\main\http_request.c +Group13File17=C:\apache\src\main\http_vhost.c +Group13File18=C:\apache\src\main\Makefile.tmpl +Group13File19=C:\apache\src\main\md5c.c +Group13File20=C:\apache\src\main\rfc1413.c +Group13File21=C:\apache\src\main\util.c +Group13File22=C:\apache\src\main\util_date.c +Group13File23=C:\apache\src\main\util_md5.c +Group13File24=C:\apache\src\main\util_script.c +Group13File25=C:\apache\src\main\util_uri.c +Group14Size=886 +Group14Files=1 +Group14Name=modules +Group14Dir=[src]\modules +Group14Update=0 +Group14File1=C:\Apache\src\modules\README +Group15Size=47178 +Group15Files=3 +Group15Name=example +Group15Dir=[modules]\example +Group15Update=0 +Group15File1=C:\Apache\src\modules\example\Makefile.tmpl +Group15File2=C:\Apache\src\modules\example\mod_example.c +Group15File3=C:\Apache\src\modules\example\README +Group16Size=13008 +Group16Files=2 +Group16Name=experimental +Group16Dir=[modules]\experimental +Group16Update=0 +Group16File1=C:\Apache\src\modules\experimental\Makefile.tmpl +Group16File2=C:\Apache\src\modules\experimental\mod_mmap_static.c +Group17Size=494 +Group17Files=1 +Group17Name=extra +Group17Dir=[modules]\extra +Group17Update=0 +Group17File1=C:\Apache\src\modules\extra\Makefile.tmpl +Group18Size=176607 +Group18Files=12 +Group18Name=proxy +Group18Dir=[modules]\proxy +Group18Update=0 +Group18File1=C:\apache\src\modules\proxy\.indent.pro +Group18File2=C:\apache\src\modules\proxy\ApacheModuleProxy.dsp +Group18File3=C:\apache\src\modules\proxy\ApacheModuleProxy.mak +Group18File4=C:\apache\src\modules\proxy\Makefile.libdir +Group18File5=C:\apache\src\modules\proxy\Makefile.tmpl +Group18File6=C:\apache\src\modules\proxy\mod_proxy.c +Group18File7=C:\apache\src\modules\proxy\mod_proxy.h +Group18File8=C:\apache\src\modules\proxy\proxy_cache.c +Group18File9=C:\apache\src\modules\proxy\proxy_connect.c +Group18File10=C:\apache\src\modules\proxy\proxy_ftp.c +Group18File11=C:\apache\src\modules\proxy\proxy_http.c +Group18File12=C:\apache\src\modules\proxy\proxy_util.c +Group19Size=785797 +Group19Files=37 +Group19Name=standard +Group19Dir=[modules]\standard +Group19Update=0 +Group19File1=C:\apache\src\modules\standard\.indent.pro +Group19File2=C:\apache\src\modules\standard\Makefile.tmpl +Group19File3=C:\apache\src\modules\standard\mod_access.c +Group19File4=C:\apache\src\modules\standard\mod_actions.c +Group19File5=C:\apache\src\modules\standard\mod_alias.c +Group19File6=C:\apache\src\modules\standard\mod_asis.c +Group19File7=C:\apache\src\modules\standard\mod_auth.c +Group19File8=C:\apache\src\modules\standard\mod_auth_anon.c +Group19File9=C:\apache\src\modules\standard\mod_auth_db.c +Group19File10=C:\apache\src\modules\standard\mod_auth_db.module +Group19File11=C:\apache\src\modules\standard\mod_auth_dbm.c +Group19File12=C:\apache\src\modules\standard\mod_autoindex.c +Group19File13=C:\apache\src\modules\standard\mod_cern_meta.c +Group19File14=C:\apache\src\modules\standard\mod_cgi.c +Group19File15=C:\apache\src\modules\standard\mod_digest.c +Group19File16=C:\apache\src\modules\standard\mod_dir.c +Group19File17=C:\apache\src\modules\standard\mod_env.c +Group19File18=C:\apache\src\modules\standard\mod_expires.c +Group19File19=C:\apache\src\modules\standard\mod_headers.c +Group19File20=C:\apache\src\modules\standard\mod_imap.c +Group19File21=C:\apache\src\modules\standard\mod_include.c +Group19File22=C:\apache\src\modules\standard\mod_info.c +Group19File23=C:\apache\src\modules\standard\mod_log_agent.c +Group19File24=C:\apache\src\modules\standard\mod_log_config.c +Group19File25=C:\apache\src\modules\standard\mod_log_referer.c +Group19File26=C:\apache\src\modules\standard\mod_mime.c +Group19File27=C:\apache\src\modules\standard\mod_mime_magic.c +Group19File28=C:\apache\src\modules\standard\mod_negotiation.c +Group19File29=C:\apache\src\modules\standard\mod_rewrite.c +Group19File30=C:\apache\src\modules\standard\mod_rewrite.h +Group19File31=C:\apache\src\modules\standard\mod_setenvif.c +Group19File32=C:\apache\src\modules\standard\mod_so.c +Group19File33=C:\apache\src\modules\standard\mod_speling.c +Group19File34=C:\apache\src\modules\standard\mod_status.c +Group19File35=C:\apache\src\modules\standard\mod_unique_id.c +Group19File36=C:\apache\src\modules\standard\mod_userdir.c +Group19File37=C:\apache\src\modules\standard\mod_usertrack.c +Group20Size=164226 +Group20Files=25 +Group20Name=regex +Group20Dir=[src]\regex +Group20Update=0 +Group20File1=C:\Apache\src\regex\cclass.h +Group20File2=C:\Apache\src\regex\cname.h +Group20File3=C:\Apache\src\regex\COPYRIGHT +Group20File4=C:\Apache\src\regex\debug.c +Group20File5=C:\Apache\src\regex\engine.c +Group20File6=C:\Apache\src\regex\engine.ih +Group20File7=C:\Apache\src\regex\main.c +Group20File8=C:\Apache\src\regex\Makefile.tmpl +Group20File9=C:\Apache\src\regex\mkh +Group20File10=C:\Apache\src\regex\README +Group20File11=C:\Apache\src\regex\regcomp.c +Group20File12=C:\Apache\src\regex\regcomp.ih +Group20File13=C:\Apache\src\regex\regerror.c +Group20File14=C:\Apache\src\regex\regerror.ih +Group20File15=C:\Apache\src\regex\regex.3 +Group20File16=C:\Apache\src\regex\regex.7 +Group20File17=C:\Apache\src\regex\regex.dsp +Group20File18=C:\Apache\src\regex\regex.mak +Group20File19=C:\Apache\src\regex\regex2.h +Group20File20=C:\Apache\src\regex\regexec.c +Group20File21=C:\Apache\src\regex\regfree.c +Group20File22=C:\Apache\src\regex\split.c +Group20File23=C:\Apache\src\regex\tests +Group20File24=C:\Apache\src\regex\utils.h +Group20File25=C:\Apache\src\regex\WHATSNEW +Group21Size=162448 +Group21Files=26 +Group21Name=support +Group21Dir=[src]\support +Group21Update=0 +Group21File1=C:\apache\src\support\.indent.pro +Group21File2=C:\apache\src\support\ab.1 +Group21File3=C:\apache\src\support\ab.c +Group21File4=C:\apache\src\support\apachectl +Group21File5=C:\apache\src\support\apachectl.1 +Group21File6=C:\apache\src\support\apxs.8 +Group21File7=C:\apache\src\support\apxs.pl +Group21File8=C:\apache\src\support\dbmmanage +Group21File9=C:\apache\src\support\dbmmanage.1 +Group21File10=C:\apache\src\support\htdigest.1 +Group21File11=C:\apache\src\support\htdigest.c +Group21File12=C:\apache\src\support\htpasswd.1 +Group21File13=C:\apache\src\support\htpasswd.c +Group21File14=C:\apache\src\support\httpd.8 +Group21File15=C:\apache\src\support\log_server_status +Group21File16=C:\apache\src\support\logresolve.8 +Group21File17=C:\apache\src\support\logresolve.c +Group21File18=C:\apache\src\support\logresolve.pl +Group21File19=C:\apache\src\support\Makefile.tmpl +Group21File20=C:\apache\src\support\phf_abuse_log.cgi +Group21File21=C:\apache\src\support\rotatelogs.8 +Group21File22=C:\apache\src\support\rotatelogs.c +Group21File23=C:\apache\src\support\split-logfile +Group21File24=C:\apache\src\support\suexec.8 +Group21File25=C:\apache\src\support\suexec.c +Group21File26=C:\apache\src\support\suexec.h +Group22Size=0 +Group22Files=0 +Group22Name=os +Group22Dir=[src]\os +Group22Update=0 +Group23Size=190860 +Group23Files=43 +Group23Name=win32 +Group23Dir=[os]\win32 +Group23Update=0 +Group23File1=C:\apache\src\os\win32\ApacheModuleAuthAnon.dsp +Group23File2=C:\apache\src\os\win32\ApacheModuleAuthAnon.mak +Group23File3=C:\apache\src\os\win32\ApacheModuleCERNMeta.dsp +Group23File4=C:\apache\src\os\win32\ApacheModuleCERNMeta.mak +Group23File5=C:\apache\src\os\win32\ApacheModuleDigest.dsp +Group23File6=C:\apache\src\os\win32\ApacheModuleDigest.mak +Group23File7=C:\apache\src\os\win32\ApacheModuleExpires.dsp +Group23File8=C:\apache\src\os\win32\ApacheModuleExpires.mak +Group23File9=C:\apache\src\os\win32\ApacheModuleHeaders.dsp +Group23File10=C:\apache\src\os\win32\ApacheModuleHeaders.mak +Group23File11=C:\apache\src\os\win32\ApacheModuleInfo.dsp +Group23File12=C:\apache\src\os\win32\ApacheModuleInfo.mak +Group23File13=C:\apache\src\os\win32\ApacheModuleRewrite.dsp +Group23File14=C:\apache\src\os\win32\ApacheModuleRewrite.mak +Group23File15=C:\apache\src\os\win32\ApacheModuleSpeling.dsp +Group23File16=C:\apache\src\os\win32\ApacheModuleSpeling.mak +Group23File17=C:\apache\src\os\win32\ApacheModuleStatus.dsp +Group23File18=C:\apache\src\os\win32\ApacheModuleStatus.mak +Group23File19=C:\apache\src\os\win32\ApacheModuleUserTrack.dsp +Group23File20=C:\apache\src\os\win32\ApacheModuleUserTrack.mak +Group23File21=C:\apache\src\os\win32\ApacheOS.dsp +Group23File22=C:\apache\src\os\win32\ApacheOS.mak +Group23File23=C:\apache\src\os\win32\getopt.c +Group23File24=C:\apache\src\os\win32\getopt.h +Group23File25=C:\apache\src\os\win32\main_win32.c +Group23File26=C:\apache\src\os\win32\MakeModuleMak.cpp +Group23File27=C:\apache\src\os\win32\MakeModuleMak.mak +Group23File28=C:\apache\src\os\win32\mod_dll.c +Group23File29=C:\apache\src\os\win32\mod_isapi.c +Group23File30=C:\apache\src\os\win32\Module.mak.tmpl +Group23File31=C:\apache\src\os\win32\modules.c +Group23File32=C:\apache\src\os\win32\multithread.c +Group23File33=C:\apache\src\os\win32\os.c +Group23File34=C:\apache\src\os\win32\os.h +Group23File35=C:\apache\src\os\win32\passwd.c +Group23File36=C:\apache\src\os\win32\passwd.h +Group23File37=C:\apache\src\os\win32\readdir.c +Group23File38=C:\apache\src\os\win32\readdir.h +Group23File39=C:\apache\src\os\win32\registry.c +Group23File40=C:\apache\src\os\win32\registry.h +Group23File41=C:\apache\src\os\win32\service.c +Group23File42=C:\apache\src\os\win32\service.h +Group23File43=C:\apache\src\os\win32\util_win32.c +Group24Size=142848 +Group24Files=1 +Group24Name=Installer DLL +Group24Dir= +Group24Update=0 +Group24File1=C:\Apache\install.dll +Group25Size=280576 +Group25Files=1 +Group25Name=Shared DLLs +Group25Dir= +Group25Update=0 +Group25File1=C:\Apache\MSVCRT.DLL +Group26Size=0 +Group26Files=0 +Group26Name=logs +Group26Dir=\logs +Group26Update=0 +Group27Size=36913 +Group27Files=76 +Group27Name=icons +Group27Dir=\icons +Group27Update=0 +Group27File1=C:\apache\icons\a.gif +Group27File2=C:\apache\icons\alert.black.gif +Group27File3=C:\apache\icons\alert.red.gif +Group27File4=C:\apache\icons\apache_pb.gif +Group27File5=C:\apache\icons\back.gif +Group27File6=C:\apache\icons\ball.gray.gif +Group27File7=C:\apache\icons\ball.red.gif +Group27File8=C:\apache\icons\binary.gif +Group27File9=C:\apache\icons\binhex.gif +Group27File10=C:\apache\icons\blank.gif +Group27File11=C:\apache\icons\bomb.gif +Group27File12=C:\apache\icons\box1.gif +Group27File13=C:\apache\icons\box2.gif +Group27File14=C:\apache\icons\broken.gif +Group27File15=C:\apache\icons\burst.gif +Group27File16=C:\apache\icons\c.gif +Group27File17=C:\apache\icons\comp.blue.gif +Group27File18=C:\apache\icons\comp.gray.gif +Group27File19=C:\apache\icons\compressed.gif +Group27File20=C:\apache\icons\continued.gif +Group27File21=C:\apache\icons\dir.gif +Group27File22=C:\apache\icons\down.gif +Group27File23=C:\apache\icons\dvi.gif +Group27File24=C:\apache\icons\f.gif +Group27File25=C:\apache\icons\folder.gif +Group27File26=C:\apache\icons\folder.open.gif +Group27File27=C:\apache\icons\folder.sec.gif +Group27File28=C:\apache\icons\forward.gif +Group27File29=C:\apache\icons\generic.gif +Group27File30=C:\apache\icons\generic.red.gif +Group27File31=C:\apache\icons\generic.sec.gif +Group27File32=C:\apache\icons\hand.right.gif +Group27File33=C:\apache\icons\hand.up.gif +Group27File34=C:\apache\icons\icon.sheet.gif +Group27File35=C:\apache\icons\image1.gif +Group27File36=C:\apache\icons\image2.gif +Group27File37=C:\apache\icons\image3.gif +Group27File38=C:\apache\icons\index.gif +Group27File39=C:\apache\icons\layout.gif +Group27File40=C:\apache\icons\left.gif +Group27File41=C:\apache\icons\link.gif +Group27File42=C:\apache\icons\movie.gif +Group27File43=C:\apache\icons\p.gif +Group27File44=C:\apache\icons\patch.gif +Group27File45=C:\apache\icons\pdf.gif +Group27File46=C:\apache\icons\pie0.gif +Group27File47=C:\apache\icons\pie1.gif +Group27File48=C:\apache\icons\pie2.gif +Group27File49=C:\apache\icons\pie3.gif +Group27File50=C:\apache\icons\pie4.gif +Group27File51=C:\apache\icons\pie5.gif +Group27File52=C:\apache\icons\pie6.gif +Group27File53=C:\apache\icons\pie7.gif +Group27File54=C:\apache\icons\pie8.gif +Group27File55=C:\apache\icons\portal.gif +Group27File56=C:\apache\icons\ps.gif +Group27File57=C:\apache\icons\quill.gif +Group27File58=C:\apache\icons\README +Group27File59=C:\apache\icons\right.gif +Group27File60=C:\apache\icons\screw1.gif +Group27File61=C:\apache\icons\screw2.gif +Group27File62=C:\apache\icons\script.gif +Group27File63=C:\apache\icons\sound1.gif +Group27File64=C:\apache\icons\sound2.gif +Group27File65=C:\apache\icons\sphere1.gif +Group27File66=C:\apache\icons\sphere2.gif +Group27File67=C:\apache\icons\tar.gif +Group27File68=C:\apache\icons\tex.gif +Group27File69=C:\apache\icons\text.gif +Group27File70=C:\apache\icons\transfer.gif +Group27File71=C:\apache\icons\unknown.gif +Group27File72=C:\apache\icons\up.gif +Group27File73=C:\apache\icons\uu.gif +Group27File74=C:\apache\icons\uuencoded.gif +Group27File75=C:\apache\icons\world1.gif +Group27File76=C:\apache\icons\world2.gif +Group28Size=0 +Group28Files=0 +Group28Name=conf +Group28Dir=\conf +Group28Update=0 +Group29Size=0 +Group29Files=0 +Group29Name=htdocs +Group29Dir=\htdocs +Group29Update=0 +Group30Size=0 +Group30Files=0 +Group30Name=cgi-bin +Group30Dir=\cgi-bin +Group30Update=0 + +[Sequence] +DestinationLocationDir=\Apache Group\Apache +SelectProgramFolderName=Apache Web Server +WelcomeMessage=1 +WelcomeMessageFile= +LicenseAgreement=1 +LicenseAgreementFile=C:\Apache\LICENSE +DestinationLocation=1 +SetupType=1 +CustomSetup=1 +SelectProgramFolder=1 +ProgressBar=1 +SetupComplete=1 +SetupCompleteExec= +SetupCompleteExecParam= +SetupCompleteExecReadme=[Program Executables]\README.NT + +[RegEntries] +Reg1Path=HKEY_CLASSES_ROOT +Reg1Val1Type=0 +Reg1Val1Name=(Default) +Reg1Val1Data=(value not set) +Reg1Vals=1 +Reg2Path=HKEY_CURRENT_USER +Reg2Val1Type=0 +Reg2Val1Name=(Default) +Reg2Val1Data=(value not set) +Reg2Vals=1 +Reg3Path=HKEY_LOCAL_MACHINE +Reg3Val1Type=0 +Reg3Val1Name=(Default) +Reg3Val1Data=(value not set) +Reg3Vals=1 +Reg4Path=HKEY_USERS +Reg4Val1Type=0 +Reg4Val1Name=(Default) +Reg4Val1Data=(value not set) +Reg4Vals=1 +Reg5Path=HKEY_CURRENT_CONFIG +Reg5Val1Type=0 +Reg5Val1Name=(Default) +Reg5Val1Data=(value not set) +Reg5Vals=1 +Reg6Path=HKEY_DYN_DATA +Reg6Val1Type=0 +Reg6Val1Name=(Default) +Reg6Val1Data=(value not set) +Reg6Vals=1 +Reg7Path=HKEY_LOCAL_MACHINE\SOFTWARE +Reg7Val1Type=0 +Reg7Val1Name=(Default) +Reg7Val1Data=(value not set) +Reg7Vals=1 +Reg8Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group +Reg8Val1Type=0 +Reg8Val1Name=(Default) +Reg8Val1Data=(value not set) +Reg8Vals=1 +Reg9Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache +Reg9Val1Type=0 +Reg9Val1Name=(Default) +Reg9Val1Data=(value not set) +Reg9Vals=1 +Reg10Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3 beta +Reg10Val1Type=0 +Reg10Val1Name=(Default) +Reg10Val1Data=(value not set) +Reg10Val2Type=0 +Reg10Val2Name=ServerRoot +Reg10Val2Data= +Reg10Vals=2 +Regs=10 + +[Registry] +Reg1Path=HKEY_LOCAL_MACHINE\SOFTWARE +Reg2Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group +Reg3Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache +Reg4Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3 beta +Reg5Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3 beta +Reg5ValName=ServerRoot +Reg5ValType=0 +Reg5ValData= +Regs=5 + +[Icons] +Icons=3 +Icon1Param=-d "" +Icon1Cmd=[Program Executables]\Apache.exe +Icon1Description=Apache Server +Icon1WorkingDir=[Program Executables] +Icon1IconFile= +Icon1RealFile=C:\Apache\Apache.exe +Icon1WhichIcon=0 +Icon1KeyVirtual=0 +Icon1KeyFlags=0 +Icon1StartMenu=0 +Icon1Window=0 +Icon2Param= +Icon2Cmd=[Manual]\index.html +Icon2Description=Apache Documentation +Icon2WorkingDir=[Manual] +Icon2IconFile= +Icon2RealFile=C:\Apache\htdocs\manual\index.html +Icon2WhichIcon=0 +Icon2KeyVirtual=0 +Icon2KeyFlags=0 +Icon2StartMenu=0 +Icon2Window=0 +Icon3Param=-d "" -i +Icon3Cmd=[Program Executables]\Apache.exe +Icon3Description=Install Apache as Service (NT only) +Icon3WorkingDir=[Program Executables] +Icon3IconFile= +Icon3RealFile=C:\Apache\Apache.exe +Icon3WhichIcon=0 +Icon3KeyVirtual=0 +Icon3KeyFlags=0 +Icon3StartMenu=0 +Icon3Window=0 + +[VisualBasic] +PRJFile= + +[Ext] +Ext1Dlg=Exit Install +Ext1Param1=[Installer DLL]\install.dll +Ext1Param2=BeforeExit +Ext1Op=DLL + +[Temp Files] +File1=C:\Apache\install.dll + +[Autoexec] +PathDir= +ShareLocks= +ShareFiles= +Command= diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/install.c b/APACHE_1_3b7/src/os/win32/installer/installdll/install.c new file mode 100644 index 0000000000..f6f775ec94 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/installdll/install.c @@ -0,0 +1,543 @@ +/* Apache Installer */ + +/* + * 26/06/97 PCS 1.000 Initial version + * 22/02/98 PCS 1.001 Used the excellent NTemacs to apply proper formating + * 04/05/98 PCS 1.002 Copy conf files to *.conf.default, then to *.conf + */ + +#include +#include +#include +#include +#include + +/* Global to store the instance handle */ +HINSTANCE hInstance = NULL; + +/* + * MessageBox_error() is a helper function to display an error in a + * message box, optionally including a Win32 error message. If + * the "opt" argument is value AP_WIN32ERROR then get the last Win32 + * error (with GetLastError()) and add it on to the end of + * the output string. The output string is given as a printf-format + * and replacement arguments. The hWnd, title and mb_opt fields are + * passed on to the Win32 MessageBox() call. + * + * We shouldn't use a fixed length buffer to build up the printf + * text. Umm. + */ + +#define AP_WIN32ERROR 1 + +int MessageBox_error(HWND hWnd, int opt, char *title, + int mb_opt, char *fmt, ...) +{ + char buf[4000]; + va_list ap; + + va_start(ap, fmt); + wvsprintf(buf, fmt, ap); + va_end(ap); + + if (opt & AP_WIN32ERROR) { + char *p; + + strcat(buf, "\r\r("); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + 0, + buf + strlen(buf), + 4000 - strlen(buf), + NULL); + p = buf+strlen(buf)-1; + while (*p == '\r' || *p == '\n') + p--; + p++; + *p = '\0'; + strcat(buf, ")"); + } + + return MessageBox(hWnd, buf, title, mb_opt); +} + +/* + * The next few functions handle expanding the @@ServerRoot@@ type + * sequences found in the distribution files. The main entry point + * is expandFile(), which is given a file to expand and the filename + * to write the expanded file it. It reads a line at a time, and + * if the line includes an "@@" sequence, calls expandLine() to + * expand the sequences. + * + * expandLine() looks for @@ sequences in the line, and when it finds + * one, looks for a corresponding entry in the replaceTable[]. If it + * finds one it writes the replacement value from the table into + * an output string. + * + * The helper function appendText() is used when expanding strings. It + * is called to copy text into an output buffer. If the output buffer + * is not big enough, it is expanded. This function also ensures that + * the output buffer is null terminated after each append operation. + * + * A table is used of values to replace, rather than just hardcoding + * the functionality, so we could replace additional values in the + * future. We also take care to ensure that the expanded line can be + * arbitrary length (though at the moment the lines read from the + * configuration files can only be up to 2000 characters). + */ + +/* + * Table of items to replace. The "value" elements are filled in at runtime + * by FillInReplaceTable(). Note that the "tmpl" element is case + * sensitive. + */ + +typedef struct { + char *tmpl; + char *value; +} REPLACEITEM; +typedef REPLACEITEM *REPLACETABLE; + +REPLACEITEM replaceHttpd[] = { + { "@@ServerRoot@@", NULL }, /* ServerRoot directory (i.e. install dir) */ + { NULL, NULL } +}; + +/* + * A relatively intelligent version of strcat, that expands the destination + * buffer if needed. + * + * On entry, ppBuf points to the output buffer, pnPos points to the offset + * of the current position within that buffer, and pnSize points to the + * current size of *ppBuf. pSrc points to the string to copy into the buffer, + * and nToCopy gives the number of characters to copy from pSrc. + * + * On exit, *ppBuf, *pnPos and *pnSize may have been updated if the output + * buffer needed to be expanded. The output buffer will be null terminated. + * Returns 0 on success, -1 on error. Does not report errors to the user. + */ + +int appendText(char **ppBuf, int *pnPos, int *pnSize, char *pSrc, int nToCopy) +{ + char *pBuf = *ppBuf; /* output buffer */ + int nPos = *pnPos; /* current offset into pBuf */ + int nSize = *pnSize; /* current size of pBuf */ + + while (nPos + nToCopy >= nSize) { + /* Not enough space, double size of output buffer. Note we use + * >= not > so that we have enough space for the NULL character + * in the output buffer */ + char *pBufNew; + + pBufNew = realloc(pBuf, nSize * 2); + if (!pBufNew) + return -1; + nSize *= 2; + + /* Update the max size and buffer pointer */ + *pnSize = nSize; + *ppBuf = pBuf = pBufNew; + } + + /* Ok, now we have enough space, copy the stuff */ + + strncpy(pBuf+nPos, pSrc, nToCopy); + nPos += nToCopy; + *pnPos = nPos; /* update current position */ + pBuf[nPos] = '\0'; /* append trailing NULL */ + + return 0; +} + +/* + * Expand all the sequences in an input line. Returns a pointer to the + * expanded line. The caller should free the returned data. + * The replaceTable argument is a table of sequences to expand. + * + * Returns NULL on error. Does not report errors to the user. + */ + +char *expandLine(char *in, REPLACETABLE replaceTable) +{ + REPLACEITEM *item; + char *pos; /* current position in input buffer */ + char *outbuf; /* output buffer */ + int outbuf_size; /* current size of output buffer */ + int outbuf_position; /* current position in output buffer */ + char *start; /* position to copy from in input buffer */ + + /* Create an initial output buffer. Guess that twice the input size + * is a good length, after expansion. Don't worry if we need more + * though, appendText() will expand as needed. + */ + outbuf_size = strlen(in) * 2; + outbuf_position = 0; + outbuf = malloc(outbuf_size); + if (!outbuf) + return NULL; + + start = in; /* mark the start of uncopied data */ + pos = in; /* current position in input buffer */ + + while (1) { + + /* Look for '@@' sequence, or end of input */ + if (*pos && !(*pos == '@' && *(pos+1) == '@')) { + pos++; + continue; + } + + if (!*pos) { + /* End of input string, copy the uncopied data */ + if (appendText(&outbuf, &outbuf_position, &outbuf_size, + start, pos-start) < 0) { + return NULL; + } + break; + } + + /* Found first @ of a possible token to replace. Look for end + * of the token + */ + for (item = replaceTable; item->tmpl; ++item) { + if (!strncmp(pos, item->tmpl, strlen(item->tmpl))) + break; + } + + if (item->tmpl) { + /* Found match. First copy the uncopied data from the input + * buffer (start through to pos-1), then copy the expanded + * value. */ + if (appendText(&outbuf, &outbuf_position, &outbuf_size, + start, pos-start) < 0) { + return NULL; + } + if (appendText(&outbuf, &outbuf_position, &outbuf_size, + item->value, strlen(item->value)) < 0) { + return NULL; + } + + /* Update current position to skip over the input buffer + * @@...@@ sequence, and update the "start" pointer to uncopied + * data + */ + pos += strlen(item->tmpl); + start = pos; + } + else { + /* The sequence did not exist in the replace table, so copy + * it as-is to the output. + */ + pos++; + } + } + + return outbuf; +} + +/* + * Some options to determine how we copy a file. Apart from OPT_NONE, these should + * be OR'able + */ + +typedef enum { + OPT_NONE = 0, + OPT_OVERWRITE = 1, /* Always overwrite destination file */ + OPT_EXPAND = 2, /* Expand any @@...@@ tokens in replaceHttpd */ + OPT_DELETESOURCE = 4, /* Delete the source file after the copy */ + OPT_SILENT = 8, /* Don't tell use about failures */ +} options_t; + +/* + * Copy a file, expanding sequences from the replaceTable argument. + * Returns 0 on success, -1 on error. Reports errors to user. + */ +#define MAX_INPUT_LINE 2000 +int WINAPI ExpandConfFile(HWND hwnd, LPSTR szInst, LPSTR szinFile, LPSTR szoutFile, REPLACETABLE replaceTable, options_t options) +{ + char inFile[_MAX_PATH]; + char outFile[_MAX_PATH]; + char inbuf[MAX_INPUT_LINE]; + FILE *infp; + FILE *outfp; + + sprintf(inFile, "%s\\%s", szInst, szinFile); + sprintf(outFile, "%s\\%s", szInst, szoutFile); + + if (!(infp = fopen(inFile, "r"))) { + MessageBox_error(hwnd, + AP_WIN32ERROR, + "Installation Problem", + MB_OK | MB_ICONSTOP, + "Cannot read file %s", inFile); + return -1; + } + if (! (options & OPT_OVERWRITE)) { + /* Overwrite not allowed if file does not exist */ + if ((outfp = fopen(outFile, "r"))) { + if (! (options & OPT_SILENT)) { + MessageBox_error(hwnd, + 0, + "File not overwritten", + MB_OK | MB_ICONWARNING, + "Preserving existing file %s.\r\r" + "The new version of this file has been left in %s", + outFile, inFile); + } + fclose(outfp); + fclose(infp); + return 0; + } + /* To get here, output file does not exist */ + } + if (!(outfp = fopen(outFile, "w"))) { + MessageBox_error(hwnd, + AP_WIN32ERROR, + "Installation Problem", + MB_OK | MB_ICONSTOP, + "Cannot write to file %s", outFile); + fclose(infp); + return -1; + } + + while (fgets(inbuf, MAX_INPUT_LINE, infp)) { + char *pos; + char *outbuf; + + /* Quickly look to see if this line contains any + * @@ tokens. If it doesn't, we don't need to bother + * called expandLine() or taking a copy of the input + * buffer. + */ + if (options & OPT_EXPAND) { + for (pos = inbuf; *pos; ++pos) + if (*pos == '@' && *(pos+1) == '@') + break; + } + + if (options & OPT_EXPAND && *pos) { + /* The input line contains at least one '@@' sequence, so + * call expandLine() to expand any sequences we know about. + */ + outbuf = expandLine(inbuf, replaceTable); + if (outbuf == NULL) { + fclose(infp); + fclose(outfp); + MessageBox_error(hwnd, + 0, + "Installation Problem", + MB_OK|MB_ICONSTOP, + "An error occurred during installation"); + return -1; + } + } + else { + outbuf = NULL; + } + + /* If outbuf is NULL, we did not need to expand sequences, so + * just output the contents of the input buffer. + */ + fwrite(outbuf ? outbuf : inbuf, 1, + strlen(outbuf ? outbuf : inbuf), outfp); + + if (outbuf) + free(outbuf); + } + fclose(infp); + fclose(outfp); + + if (options & OPT_DELETESOURCE) { + unlink(inFile); + } + + return 0; +} + +int FillInReplaceTable(HWND hwnd, REPLACETABLE table, char *szInst) +{ + REPLACEITEM *item; + for (item = table; item->tmpl; ++item) { + if (!strcmp(item->tmpl, "@@ServerRoot@@")) { + char *p; + +#if NEED_SHORT_PATHS + int len; + len = GetShortPathName(szInst, NULL, 0); + if (len > 0) { + item->value = (char*)malloc(len+1); + GetShortPathName(szInst, item->value, len); + } +#else + if ((item->value = strdup(szInst)) == NULL) + return -1; +#endif + for (p = item->value; *p; p++) + if (*p == '\\') *p = '/'; + continue; + } +#if NEED_FQDN + if (!strcmp(item->tmpl, "FQDN")) { + item->value = GetHostName(hwnd); + continue; + } +#endif + } + return 0; +} + +/* + * actionTable[] contains things we do when this DLL is called by InstallShield + * during the install. It is like a simple script, without us having to + * worry about parsing, error checking, etc. + * + * Each item in the table is of type ACTIONITEM. The first element is the action + * to perform (e.g. CMD_COPY). The second and third elements are filenames + * (e.g. for CMD_COPY, the first filename is the source and the second filename + * is the destination). The final element of ACTIONITEM is a set of options + * which apply to the current "command". For example, OPT_EXPAND on a CMD_COPY + * line, tells the copy function to expand @@ServerRoot@@ tokens found in the + * source file. + * + * The contents of this table are performed in order, top to bottom. This lets + * us expand the files to the *.conf.default names, then copy to *.conf only + * if the corresponding *.conf file does not already exist. If it does exist, + * it is not overwritten. + * + * Return 1 on success, 0 on error. + */ + +typedef enum { + CMD_COPY = 0, + CMD_RMDIR, + CMD_RM, + CMD_END +} cmd_t; + +typedef struct { + cmd_t command; + char *in; + char *out; + options_t options; +} ACTIONITEM; +typedef ACTIONITEM *ACTIONTABLE; + +ACTIONITEM actionTable[] = { + /* + * Installation of the configuraton files. These are installed into the ".tmp" + * directory by the installer. We first move them to conf\*.default (overwriting + * any *.default file from a previous install). The *.conf-dist-win files + * are also expanded for any @@...@@ tokens. Then we copy the conf\*.default + * file to corresponding conf\* file, unless that would overwrite an existing file. + */ + { CMD_COPY, ".tmp\\mime.types", "conf\\mime.types.default", + OPT_OVERWRITE|OPT_DELETESOURCE }, + { CMD_COPY, ".tmp\\magic", "conf\\magic.default", + OPT_OVERWRITE|OPT_DELETESOURCE }, + { CMD_COPY, ".tmp\\httpd.conf-dist-win", "conf\\httpd.conf.default", + OPT_OVERWRITE|OPT_EXPAND|OPT_DELETESOURCE }, + { CMD_COPY, ".tmp\\srm.conf-dist-win", "conf\\srm.conf.default", + OPT_OVERWRITE|OPT_EXPAND|OPT_DELETESOURCE }, + { CMD_COPY, ".tmp\\access.conf-dist-win", "conf\\access.conf.default", + OPT_OVERWRITE|OPT_EXPAND|OPT_DELETESOURCE }, + + /* Now copy to the 'live' files, unless they already exist */ + { CMD_COPY, "conf\\httpd.conf.default", "conf\\httpd.conf", OPT_NONE }, + { CMD_COPY, "conf\\srm.conf.default", "conf\\srm.conf", OPT_NONE }, + { CMD_COPY, "conf\\access.conf.default", "conf\\access.conf", OPT_NONE }, + { CMD_COPY, "conf\\magic.default", "conf\\magic", OPT_NONE }, + { CMD_COPY, "conf\\mime.types.default", "conf\\mime.types", OPT_NONE }, + + { CMD_COPY, ".tmp\\highperformance.conf-dist", "conf\\highperformance.conf-dist", + OPT_EXPAND|OPT_OVERWRITE|OPT_DELETESOURCE }, + + /* Move the default htdocs files into place, provided they don't already + * exist. + */ + { CMD_COPY, ".tmp\\index.html", "htdocs\\index.html", OPT_DELETESOURCE|OPT_SILENT }, + { CMD_RM, ".tmp\\index.html", NULL, OPT_SILENT }, + { CMD_COPY, ".tmp\\apache_pb.gif", "htdocs\\apache_pb.gif", OPT_DELETESOURCE|OPT_SILENT }, + { CMD_RM, ".tmp\\apache_pb.gif", NULL, OPT_SILENT }, + + { CMD_RMDIR, ".tmp", NULL }, + + { CMD_END, NULL, NULL, OPT_NONE } +}; + +/* + * BeforeExit() is the DLL call from InstallShield. The arguments and + * return value as defined by the installer. We are only interested + * in the install directory, szInst. Return 0 on error and 1 on + * success (!?). + */ + +CHAR WINAPI BeforeExit(HWND hwnd, LPSTR szSrcDir, LPSTR szSupport, LPSTR szInst, LPSTR szRes) +{ + ACTIONITEM *pactionItem; + int end = 0; + + FillInReplaceTable(hwnd, replaceHttpd, szInst); + + pactionItem = actionTable; + while (!end) { + switch(pactionItem->command) { + case CMD_END: + end = 1; + break; + case CMD_COPY: + if (ExpandConfFile(hwnd, szInst, + pactionItem->in, + pactionItem->out, + replaceHttpd, + pactionItem->options) < 0) { + /* Error has already been reported to the user */ + return 0; + } + break; + case CMD_RM: { + char inFile[MAX_INPUT_LINE]; + + sprintf(inFile, "%s\\%s", szInst, pactionItem->in); + if (unlink(inFile) < 0 && !(pactionItem->options & OPT_SILENT)) { + MessageBox_error(hwnd, AP_WIN32ERROR, "Error during configuration", + MB_ICONHAND, + "Could not remove file %s", + inFile); + return 0; + } + break; + } + case CMD_RMDIR: { + char inFile[MAX_INPUT_LINE]; + + sprintf(inFile, "%s\\%s", szInst, pactionItem->in); + if (rmdir(inFile) < 0) { + MessageBox_error(hwnd, AP_WIN32ERROR, "Error during configuration", + MB_ICONHAND, + "Could not delete temporary directory %s", + inFile); + return 0; + } + break; + } + default: + MessageBox_error(hwnd, 0, "Error during configuration", + MB_ICONHAND, + "An error has occurred during configuration\r" + "(Error: unknown command %d)", (int)pactionItem->command); + end = 1; + break; + } + pactionItem++; + } + return 1; +} + + +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + if (fdwReason == DLL_PROCESS_ATTACH) + hInstance = hInstDLL; + return TRUE; +} diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/install.def b/APACHE_1_3b7/src/os/win32/installer/installdll/install.def new file mode 100644 index 0000000000..aae6ded275 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/installdll/install.def @@ -0,0 +1,6 @@ +LIBRARY INSTALL +DESCRIPTION 'Installer DLL For Apache' + +EXPORTS + BeforeExit @1 + DllMain @2 diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/install.dsp b/APACHE_1_3b7/src/os/win32/installer/installdll/install.dsp new file mode 100644 index 0000000000..26ea521ab6 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/installdll/install.dsp @@ -0,0 +1,103 @@ +# Microsoft Developer Studio Project File - Name="install" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=install - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "install.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "install.mak" CFG="install - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "install - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "install - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "install - 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 "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "install - 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 "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "install - Win32 Release" +# Name "install - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\install.c +# End Source File +# Begin Source File + +SOURCE=.\install.def +# End Source File +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/install.mak b/APACHE_1_3b7/src/os/win32/installer/installdll/install.mak new file mode 100644 index 0000000000..db4ad3a82d --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/installdll/install.mak @@ -0,0 +1,184 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on install.dsp +!IF "$(CFG)" == "" +CFG=install - Win32 Debug +!MESSAGE No configuration specified. Defaulting to install - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "install - Win32 Release" && "$(CFG)" !=\ + "install - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "install.mak" CFG="install - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "install - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "install - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "install - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\install.dll" + +!ELSE + +ALL : "$(OUTDIR)\install.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\install.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\install.dll" + -@erase "$(OUTDIR)\install.exp" + -@erase "$(OUTDIR)\install.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)\install.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Release/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\install.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\ + /incremental:no /pdb:"$(OUTDIR)\install.pdb" /machine:I386 /def:".\install.def"\ + /out:"$(OUTDIR)\install.dll" /implib:"$(OUTDIR)\install.lib" +DEF_FILE= \ + ".\install.def" +LINK32_OBJS= \ + "$(INTDIR)\install.obj" + +"$(OUTDIR)\install.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "install - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\install.dll" + +!ELSE + +ALL : "$(OUTDIR)\install.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\install.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\install.dll" + -@erase "$(OUTDIR)\install.exp" + -@erase "$(OUTDIR)\install.ilk" + -@erase "$(OUTDIR)\install.lib" + -@erase "$(OUTDIR)\install.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)\install.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\install.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\ + /incremental:yes /pdb:"$(OUTDIR)\install.pdb" /debug /machine:I386\ + /def:".\install.def" /out:"$(OUTDIR)\install.dll"\ + /implib:"$(OUTDIR)\install.lib" /pdbtype:sept +DEF_FILE= \ + ".\install.def" +LINK32_OBJS= \ + "$(INTDIR)\install.obj" + +"$(OUTDIR)\install.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) $< +<< + + +!IF "$(CFG)" == "install - Win32 Release" || "$(CFG)" ==\ + "install - Win32 Debug" +SOURCE=.\install.c + +"$(INTDIR)\install.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/test/resource.h b/APACHE_1_3b7/src/os/win32/installer/installdll/test/resource.h new file mode 100644 index 0000000000..2b47ca12b5 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/installdll/test/resource.h @@ -0,0 +1,23 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by test.rc +// +#define IDM_TEST 102 +#define IDI_TEST 106 +#define IDD_ABOUT 107 +#define IDM_BEFOREEXIT 40001 +#define IDM_EXIT 106 +#define IDM_ABOUT 303 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 109 +#define _APS_NEXT_COMMAND_VALUE 40002 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.c b/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.c new file mode 100644 index 0000000000..c2b5ed4366 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.c @@ -0,0 +1,154 @@ +/* + * Tester for the Apache Install DLL + */ + +#include + +#include "test.h" + +#define APPNAME "Test" + +HINSTANCE hInst; // current instance +char szAppName[100]; // Name of the app +char szTitle[100]; // The title bar text + +extern CHAR WINAPI BeforeExit(HWND, LPSTR,LPSTR,LPSTR,LPSTR); + +BOOL InitApplication(HINSTANCE); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + MSG msg; + HANDLE hAccelTable; + + lstrcpy (szAppName, APPNAME); + lstrcpy (szTitle, APPNAME); + + if (!hPrevInstance) { + if (!InitApplication(hInstance)) { + return (FALSE); + } + } + + if (!InitInstance(hInstance, nCmdShow)) { + return (FALSE); + } + + hAccelTable = LoadAccelerators (hInstance, szAppName); + + while (GetMessage(&msg, NULL, 0, 0)) { + if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (msg.wParam); + + lpCmdLine; // This will prevent 'unused formal parameter' warnings +} + +BOOL InitApplication(HINSTANCE hInstance) +{ + WNDCLASS wc; + HWND hwnd; + + hwnd = FindWindow (szAppName, szTitle); + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_TEST)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wc.lpszMenuName = MAKEINTRESOURCE(IDM_TEST); + wc.lpszClassName = szAppName; + + return RegisterClass(&wc); +} + +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + HWND hWnd; + + hInst = hInstance; + + hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, + NULL, NULL, hInstance, NULL); + + if (!hWnd) { + return (FALSE); + } + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + return (TRUE); +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + + switch (message) { + + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + + switch (wmId) { + + case IDM_ABOUT: + DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About); + break; + + case IDM_BEFOREEXIT: + BeforeExit(hWnd, "C:\\", "C:\\", "C:\\Apache", NULL); + break; + + case IDM_EXIT: + DestroyWindow (hWnd); + break; + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + return (0); +} + +LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + switch (message) { + case WM_INITDIALOG: + return (TRUE); + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + return (TRUE); + } + break; + } + + return FALSE; +} + diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.def b/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.def new file mode 100644 index 0000000000..30ab5c666c --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.def @@ -0,0 +1,2 @@ +NAME Test +DESCRIPTION 'Test Installer DLL' diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.dsp b/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.dsp new file mode 100644 index 0000000000..9ce6921ae3 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.dsp @@ -0,0 +1,121 @@ +# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "test - 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 "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /machine:I386 +# ADD LINK32 ..\Release\install.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "test - 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 "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +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 /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ..\Debug\install.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "test - Win32 Release" +# Name "test - Win32 Debug" +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\test.c +# End Source File +# Begin Source File + +SOURCE=.\test.def +# End Source File +# Begin Source File + +SOURCE=.\test.h +# End Source File +# Begin Source File + +SOURCE=.\test.ico +# End Source File +# Begin Source File + +SOURCE=.\test.rc + +!IF "$(CFG)" == "test - Win32 Release" + +!ELSEIF "$(CFG)" == "test - Win32 Debug" + +!ENDIF + +# End Source File +# End Target +# End Project diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.h b/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.h new file mode 100644 index 0000000000..93a871ff59 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.h @@ -0,0 +1,4 @@ +#include "resource.h" + + + diff --git a/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.ico b/APACHE_1_3b7/src/os/win32/installer/installdll/test/test.ico new file mode 100644 index 0000000000000000000000000000000000000000..0011934f782320bd4289a914cef8713d8a0fd8d1 GIT binary patch literal 766 zcmc&yyAi`643%?fd@h_Swabi=g2r1h0)-p)NJrywQfdR`Nj?lFxl55E0-@h~0_#lF zVNKJ8RGufIE9?zALGRFx&NzuYYM;fUh>G`{!3mevb%oV}*d`J6pjevH_-7fl)hO7) z+6>lQ1XXN7j`iv{JgB)|@p*f_^;h@10HwXNa7r. + * + */ + +/* + * mod_dll.c - DLL module loader for Windows + * by Alexei Kosut, based on mod_dld.c by rst + * + * This module loads another module into the server that has been + * compiled as a DLL. It doesn't work perfectly, but well enough. + * + * To use, compile the module into a DLL. Then add the following to the + * server's config file (before any directives belonging to the loaded module): + * + * LoadModule module_name mod_name.dll + * + * module_name should be the name of the module (e.g. includes_module), + * and mod_name.dll should be the name of the DLL, relative to the server + * root. + * + * There is also a directive that will load a non-module DLL, if you'd + * like to load additional libraries into the server: + * + * LoadFile filename.dll + * + * Compiling a module as a DLL (using Microsoft Visual C++): + * + * 1. Add the following to the module source file's module record + * definition: MODULE_VAR_EXPORT. i.e. if you have + * "module foo_module;", replace it with + * "module MODULE_VAR_EXPORT foo_module;". If your module is to be + * compiled with both Windows and Unix, you may wish to use an #ifdef + * WIN32 + * + * Note that your module should still work just fine compiled-in + * with this code bit there. It only activates when using the module + * as a DLL. + * + * 2. Create a DLL file with just the module source file (and any associated + * files). Be sure to link it against the ApacheCore.lib created when + * compiling ApacheCore.dll. You may also have to tweak the settings to + * find all of the Apache includes files correctly. After creating the + * DLL, follow the above instructions to load it into Apache. + */ + +#include "httpd.h" +#include "http_config.h" + +/* + * The hard part of implementing LoadModule is deciding what to do about + * rereading the config files. This proof-of-concept implementation takes the + * cheap way out: we only actually load the modules the first time through. + */ + +static int been_there_done_that = 0; /* Loaded the modules yet? */ +static int have_symbol_table = 0; + +char *load_module (cmd_parms *cmd, void *dummy, char *modname, char *filename) +{ + HINSTANCE modhandle; + module *modp; + const char *szModuleFile=ap_server_root_relative(cmd->pool, filename); + + if (been_there_done_that) return NULL; + + if (!(modhandle = LoadLibraryEx(szModuleFile, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH))) + return ap_pstrcat (cmd->pool, "Cannot load ", szModuleFile, " into server", + NULL); + + /* If I knew what the correct cast is here, I'd be happy. But + * I don't. So I'll use (void *). It works. + */ + if (!(modp = (module *)(GetProcAddress (modhandle, modname)))) { + return ap_pstrcat (cmd->pool, "Can't find module ", modname, + " in file ", filename, NULL); + } + + ap_add_module (modp); + + /* Alethea Patch (rws,djw2) - need to run configuration functions + in new modules */ + + if (modp->create_server_config) + ((void**)cmd->server->module_config)[modp->module_index]= + (*modp->create_server_config)(cmd->pool, cmd->server); + + if (modp->create_dir_config) + ((void**)cmd->server->lookup_defaults)[modp->module_index]= + (*modp->create_dir_config)(cmd->pool, NULL); + + + return NULL; +} + +char *load_file (cmd_parms *cmd, void *dummy, char *filename) +{ + if (been_there_done_that) return NULL; + + if (!LoadLibrary(ap_server_root_relative(cmd->pool, filename))) + return ap_pstrcat (cmd->pool, "Cannot load ", filename, " into server", NULL); + + return NULL; +} + +void check_loaded_modules (server_rec *dummy, pool *p) +{ + if (been_there_done_that) return; + + been_there_done_that = 1; +} + +command_rec dll_cmds[] = { +{ "LoadModule", load_module, NULL, RSRC_CONF, TAKE2, + "a module name, and the name of a file to load it from"}, +{ "LoadFile", load_file, NULL, RSRC_CONF, ITERATE, + "files or libraries to link into the server at runtime"}, +{ NULL } +}; + +module dll_module = { + STANDARD_MODULE_STUFF, + check_loaded_modules, /* initializer */ + NULL, /* create per-dir config */ + NULL, /* merge per-dir config */ + NULL, /* server config */ + NULL, /* merge server config */ + dll_cmds, /* command table */ + NULL, /* 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/APACHE_1_3b7/src/os/win32/mod_isapi.c b/APACHE_1_3b7/src/os/win32/mod_isapi.c new file mode 100644 index 0000000000..2730c0b9e8 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/mod_isapi.c @@ -0,0 +1,566 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * mod_isapi.c - Internet Server Application (ISA) module for Apache + * by Alexei Kosut + * + * 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 + +/* 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_error(APLOG_MARK, APLOG_ALERT, r->server, + "Could not load DLL: %s", r->filename); + return SERVER_ERROR; + } + + if (!(isapi_version = + (void *)(GetProcAddress(isapi_handle, "GetExtensionVersion")))) { + ap_log_error(APLOG_MARK, APLOG_ALERT, r->server, + "DLL could not load GetExtensionVersion(): %s", r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + if (!(isapi_entry = + (void *)(GetProcAddress(isapi_handle, "HttpExtensionProc")))) { + ap_log_error(APLOG_MARK, APLOG_ALERT, r->server, + "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_error(APLOG_MARK, APLOG_ALERT, r->server, + "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_error(APLOG_MARK, APLOG_ERR, r->server, + "%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_error(APLOG_MARK, APLOG_WARNING, r->server, + "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; + 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_error(APLOG_MARK, APLOG_WARNING, r->server, + "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; +} + +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_error(APLOG_MARK, APLOG_ERR, r->server, + "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_error(APLOG_MARK, APLOG_ERR, r->server, + "ISA sent invalid headers", r->filename); + return FALSE; + } + + *value++ = '\0'; + while (*value && isspace(*value)) ++value; + + /* Check all the special-case headers. Similar to what + * scan_script_header() does (see that function for + * more detail) + */ + + if (!strcasecmp(data, "Content-Type")) { + /* Nuke trailing whitespace */ + + char *endp = value + strlen(value) - 1; + while (endp > value && isspace(*endp)) *endp-- = '\0'; + + r->content_type = ap_pstrdup (r->pool, value); + ap_str_tolower(r->content_type); + } + 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_error(APLOG_MARK, APLOG_WARNING, r->server, + "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/APACHE_1_3b7/src/os/win32/modules.c b/APACHE_1_3b7/src/os/win32/modules.c new file mode 100644 index 0000000000..183fdc5822 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/modules.c @@ -0,0 +1,71 @@ +/* modules.c --- automatically generated by Apache + * configuration script. DO NOT HAND EDIT!!!!! + */ + +#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/APACHE_1_3b7/src/os/win32/multithread.c b/APACHE_1_3b7/src/os/win32/multithread.c new file mode 100644 index 0000000000..efa9bffc75 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/multithread.c @@ -0,0 +1,258 @@ + +#include "conf.h" +#include "multithread.h" + +#ifdef WIN32 +#include +#include + + +static int +map_rv(int rv) +{ + switch(rv) + { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + return(MULTI_OK); + case WAIT_TIMEOUT: + return(MULTI_TIMEOUT); + case WAIT_FAILED: + return(MULTI_ERR); + default: + assert(0); + } + + assert(0); + return(0); +} + + +thread * +create_thread(void (thread_fn)(void *), void *thread_arg) +{ + int id; + int rv; + + rv = _beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE)thread_fn, + thread_arg, 0, &id); + + return((thread *)rv); +} + + +int +kill_thread(thread *thread_id) +{ + return(TerminateThread(thread_id, 1)); +} + + +int +await_thread(thread *thread_id, int sec_to_wait) +{ + int rv; + + rv = WaitForSingleObject(thread_id, sec_to_wait*1000); + + return(map_rv(rv)); +} + +void +exit_thread(int status) +{ + _endthreadex(status); +} + +void +free_thread(thread *thread_id) +{ + CloseHandle(thread_id); +} + + + +API_EXPORT(mutex *) ap_create_mutex(char *name) +{ + return(CreateMutex(NULL, FALSE, name)); +} + +API_EXPORT(mutex *) ap_open_mutex(char *name) +{ + return(OpenMutex(MUTEX_ALL_ACCESS, FALSE, name)); +} + + +API_EXPORT(int) ap_acquire_mutex(mutex *mutex_id) +{ + int rv; + + rv = WaitForSingleObject(mutex_id, INFINITE); + + return(map_rv(rv)); +} + +API_EXPORT(int) ap_release_mutex(mutex *mutex_id) +{ + return(ReleaseMutex(mutex_id)); +} + +API_EXPORT(void) ap_destroy_mutex(mutex *mutex_id) +{ + CloseHandle(mutex_id); +} + + +semaphore * +create_semaphore(int initial) +{ + return(CreateSemaphore(NULL, initial, 1000000, NULL)); +} + +int acquire_semaphore(semaphore *semaphore_id) +{ + int rv; + + rv = WaitForSingleObject(semaphore_id, INFINITE); + + return(map_rv(rv)); +} + +int release_semaphore(semaphore *semaphore_id) +{ + return(ReleaseSemaphore(semaphore_id, 1, NULL)); +} + +void destroy_semaphore(semaphore *semaphore_id) +{ + CloseHandle(semaphore_id); +} + + +event * +create_event(int manual, int initial, char *name) +{ + return(CreateEvent(NULL, manual, initial, name)); +} + +event * +open_event(char *name) +{ + return(OpenEvent(EVENT_ALL_ACCESS, FALSE, name)); +} + + +int acquire_event(event *event_id) +{ + int rv; + + rv = WaitForSingleObject(event_id, INFINITE); + + return(map_rv(rv)); +} + +int set_event(event *event_id) +{ + return(SetEvent(event_id)); +} + +int reset_event(event *event_id) +{ + return(ResetEvent(event_id)); +} + + +void destroy_event(event *event_id) +{ + CloseHandle(event_id); +} + +#else + + +thread *create_thread(void (thread_fn)(void *thread_arg), + void *thread_arg) +{ + return(NULL); +} + +int kill_thread(thread *thread_id) +{ + return(0); +} + +int await_thread(thread *thread_id, int sec_to_wait) +{ + return(0); +} + +void exit_thread(int status) +{} + +void free_thread(thread *thread_id) +{} + + +mutex *ap_create_mutex(char *name) +{ + return(NULL); +} + +mutex *ap_open_mutex(char *name) +{ + return(NULL); +} + +int ap_acquire_mutex(mutex *mutex_id) +{ + return(0); +} +int ap_release_mutex(mutex *mutex_id) +{ + return(0); +} +void ap_destroy_mutex(mutex *mutex_id) +{} + + +semaphore *create_semaphore(int initial) +{ + return(NULL); +} +int acquire_semaphore(semaphore *semaphore_id) +{ + return(0); +} +int release_semaphore(semaphore *semaphore_id) +{ + return(0); +} +void destroy_semaphore(semaphore *semaphore_id) +{} + +event *create_event(int manual, int initial, char *name) +{ + return(NULL); +} +event *open_event(char *name) +{ + return(NULL); +} +int acquire_event(event *event_id) +{ + return(0); +} +int set_event(event *event_id) +{ + return(0); +} +int reset_event(event *event_id) +{ + return(0); +} +void destroy_event(event *event_id) +{} + + +#endif /* WIN32 */ + diff --git a/APACHE_1_3b7/src/os/win32/os.c b/APACHE_1_3b7/src/os/win32/os.c new file mode 100755 index 0000000000..8877f50bc8 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/os.c @@ -0,0 +1,7 @@ +/* + * OS abstraction functions. Small functions should be defined + * as "__inline" in os.h. + */ + +#include "os.h" + diff --git a/APACHE_1_3b7/src/os/win32/os.h b/APACHE_1_3b7/src/os/win32/os.h new file mode 100755 index 0000000000..e013d8762c --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/os.h @@ -0,0 +1,115 @@ +#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 + +#define STATUS +#define WIN32_LEAN_AND_MEAN +#ifndef STRICT + #define STRICT +#endif +#define NO_UNISTD_H +#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 conf.h +#define USE_LONGJMP +#define HAVE_MMAP +#define USE_MMAP_SCOREBOARD +#define MULTITHREAD +#define HAVE_CANONICAL_FILENAME +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 + +#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); + +#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,...); + +/* 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_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 */ + +#endif /* ! APACHE_OS_H */ diff --git a/APACHE_1_3b7/src/os/win32/passwd.c b/APACHE_1_3b7/src/os/win32/passwd.c new file mode 100644 index 0000000000..bde691cf29 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/passwd.c @@ -0,0 +1,16 @@ +#include +#include "passwd.h" + +/* Very tacky implementation */ + +struct passwd *getpwnam(const char *szUser) +{ + static struct passwd pw; + + if(strlen(szUser) > _MAX_PATH-10) + return NULL; + + sprintf(pw.pw_dir,"c:/users/%s",szUser); + + return &pw; +} diff --git a/APACHE_1_3b7/src/os/win32/passwd.h b/APACHE_1_3b7/src/os/win32/passwd.h new file mode 100644 index 0000000000..784ab6f6ff --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/passwd.h @@ -0,0 +1,8 @@ +#include + +struct passwd +{ + char pw_dir[_MAX_PATH]; +}; + +struct passwd *getpwnam(const char *szUser); diff --git a/APACHE_1_3b7/src/os/win32/readdir.c b/APACHE_1_3b7/src/os/win32/readdir.c new file mode 100644 index 0000000000..c03c90d998 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/readdir.c @@ -0,0 +1,80 @@ +#include +#include +#include + +#include "readdir.h" + +/********************************************************************** + * Implement dirent-style opendir/readdir/closedir on Window 95/NT + * + * Functions defined are opendir(), readdir() and closedir() with the + * same prototypes as the normal dirent.h implementation. + * + * Does not implement telldir(), seekdir(), rewinddir() or scandir(). + * The dirent struct is compatible with Unix, except that d_ino is + * always 1 and d_off is made up as we go along. + * + * The DIR typedef is not compatible with Unix. + **********************************************************************/ + +API_EXPORT(DIR *) opendir(const char *dir) +{ + DIR *dp; + char *filespec; + long handle; + int index; + + filespec = malloc(strlen(dir) + 2 + 1); + strcpy(filespec, dir); + index = strlen(filespec) - 1; + if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\')) + filespec[index] = '\0'; + strcat(filespec, "/*"); + + dp = (DIR *)malloc(sizeof(DIR)); + dp->offset = 0; + dp->finished = 0; + dp->dir = strdup(dir); + + if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) { + if (errno == ENOENT) + dp->finished = 1; + else + return NULL; + } + + dp->handle = handle; + free(filespec); + + return dp; +} + +API_EXPORT(struct dirent *) readdir(DIR *dp) +{ + if (!dp || dp->finished) return NULL; + + if (dp->offset != 0) { + if (_findnext(dp->handle, &(dp->fileinfo)) < 0) { + dp->finished = 1; + return NULL; + } + } + dp->offset++; + + strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME); + dp->dent.d_ino = 1; + dp->dent.d_reclen = strlen(dp->dent.d_name); + dp->dent.d_off = dp->offset; + + return &(dp->dent); +} + +API_EXPORT(int) closedir(DIR *dp) +{ + if (!dp) return 0; + _findclose(dp->handle); + if (dp->dir) free(dp->dir); + if (dp) free(dp); + + return 0; +} diff --git a/APACHE_1_3b7/src/os/win32/readdir.h b/APACHE_1_3b7/src/os/win32/readdir.h new file mode 100644 index 0000000000..d87fd1987e --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/readdir.h @@ -0,0 +1,36 @@ +/* + * Structures and types used to implement opendir/readdir/closedir + * on Windows 95/NT. + */ + +#include +#include +#include +#include + +#ifndef API_EXPORT +# define API_EXPORT(type) __declspec(dllexport) type __stdcall +#endif + +/* struct dirent - same as Unix */ +struct dirent { + long d_ino; /* inode (always 1 in WIN32) */ + off_t d_off; /* offset to this dirent */ + unsigned short d_reclen; /* length of d_name */ + char d_name[_MAX_FNAME+1]; /* filename (null terminated) */ +}; + +/* typedef DIR - not the same as Unix */ +typedef struct { + long handle; /* _findfirst/_findnext handle */ + short offset; /* offset into directory */ + short finished; /* 1 if there are not more files */ + struct _finddata_t fileinfo; /* from _findfirst/_findnext */ + char *dir; /* the dir we are reading */ + struct dirent dent; /* the dirent to return */ +} DIR; + +/* Function prototypes */ +API_EXPORT(DIR *) opendir(const char *); +API_EXPORT(struct dirent *) readdir(DIR *); +API_EXPORT(int) closedir(DIR *); diff --git a/APACHE_1_3b7/src/os/win32/registry.c b/APACHE_1_3b7/src/os/win32/registry.c new file mode 100755 index 0000000000..b3eb41f9dc --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/registry.c @@ -0,0 +1,395 @@ +/* + * Functions to handle interacting with the Win32 registry + */ + +/* + * Apache registry key structure + * + * Apache's registry information is stored in the HKEY_LOCAL_MACHINE + * key, under + * + * HKLM\SOFTWARE\Apache Group\Apache\version + * + * These keys are defined in this file. The definition of the "version" part + * will need updating each time Apache moves from beta to non-beta or from a + * release to a development or beta version. + */ + +#include +#include + +#include "httpd.h" +#include "http_log.h" + +/* Define where the Apache values are stored in the registry. In general + * VERSION will be the same across all beta releases for a particular + * major release, but will change when the final release is made. + */ + +#define VENDOR "Apache Group" +#define SOFTWARE "Apache" +#define VERSION "1.3 beta" + +#define REGKEY "SOFTWARE\\" VENDOR "\\" SOFTWARE "\\" VERSION + +/* + * The Windows API registry key functions don't set the last error + * value (the windows equivalent of errno). So we need to set it + * with SetLastError() before calling the aplog_error() function. + * Because this is common, let's have a macro. + */ +#define do_error(rv,fmt,arg) do { \ + SetLastError(rv); \ + ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_ERR, NULL, fmt,arg); \ + } while (0); + +/* + * Get the data for registry key value. This is a generic function that + * can either get a value into a caller-supplied buffer, or it can + * allocate space for the value from the pass-in pool. It will normally + * be used by other functions within this file to get specific key values + * (e.g. registry_get_server_root()). This function returns a number of + * different error statuses, allowing the caller to differentiate + * between a key or value not existing and other kinds of errors. Depending + * on the type of data being obtained the caller can then either ignore + * the key-not-existing error, or treat it as a real error. + * + * If ppValue is NULL, allocate space for the value and return it in + * *pValue. The return value is the number of bytes in the value. + * The first argument is the pool to use to allocate space for the value. + * + * If pValue is not NULL, assume it is a buffer of nSizeValue bytes, + * and write the value into the buffer. The return value is the number + * of bytes in the value (so if the return value is greater than + * the supplied nSizeValue, the caller knows that *pValue is truncated). + * The pool argument is ignored. + * + * The return value is the number of bytes in the successfully retreived + * key if everything worked, or: + * + * -1 the key does not exists + * -2 if out of memory during the function + * -3 if the buffer specified by *pValue/nSizeValue was not large enough + * for the value. + * -4 if an error occurred + * + * If the return value is negative a message will be logged to the error + * log (aplog_error) function. If the return value is -2, -3 or -4 the message + * will be logged at priority "error", while if the return value is -1 the + * message will be logged at priority "warning". + */ + +static int ap_registry_get_key_int(pool *p, char *key, char *pBuffer, int nSizeBuffer, char **ppValue) +{ + long rv; + HKEY hKey; + char *pValue; + int nSize; + int retval; + + rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + REGKEY, + 0, + KEY_READ, + &hKey); + + if (rv == ERROR_FILE_NOT_FOUND) { + ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL, + "Registry does not contain key " REGKEY); + return -1; + } + if (rv != ERROR_SUCCESS) { + do_error(rv, "RegOpenKeyEx HKLM\\" REGKEY, + NULL); + return -4; + } + + if (pBuffer == NULL) { + /* Find the size required for the data by passing NULL as the buffer + * pointer. On return nSize will contain the size required for the + * buffer if the return value is ERROR_SUCCESS. + */ + rv = RegQueryValueEx(hKey, + key, /* key name */ + NULL, /* reserved */ + NULL, /* type */ + NULL, /* for value */ + &nSize); /* for size of "value" */ + + if (rv != ERROR_SUCCESS) { + do_error(rv, "RegQueryValueEx(key %s)", key); + return -1; + } + + pValue = ap_palloc(p, nSize); + *ppValue = pValue; + if (!pValue) { + /* Eek, out of memory, probably not worth trying to carry on, + * but let's give it a go + */ + ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,NULL, + "Error getting registry key: out of memory"); + return -2; + } + } + else { + /* Get the value into the existing buffer of length nSizeBuffer */ + pValue = pBuffer; + nSize = nSizeBuffer; + } + + rv = RegQueryValueEx(hKey, + key, /* key name */ + NULL, /* reserved */ + NULL, /* type */ + pValue, /* for value */ + &nSize); /* for size of "value" */ + + retval = 0; /* Return value */ + + if (rv == ERROR_FILE_NOT_FOUND) { + ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL, + "Registry does not contain value " REGKEY "\\%s", key); + retval = -1; + } + else if (rv == ERROR_MORE_DATA) { + /* This should only happen if we got passed a pre-existing buffer + * (pBuffer, nSizeBuffer). But I suppose it could also happen if we + * allocate a buffer if another process changed the length of the + * value since we found out its length above. Umm. + */ + ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,NULL, + "Error getting registry value %s: buffer not big enough", key); + retval = -3; + } + else if (rv != ERROR_SUCCESS) { + do_error(rv, "RegQueryValueEx(key %s)", key); + retval = -4; + } + + rv = RegCloseKey(hKey); + if (rv != ERROR_SUCCESS) { + do_error(rv, "RegCloseKey HKLM\\" REGKEY, NULL); + if (retval == 0) { + /* Keep error status from RegQueryValueEx, if any */ + retval = -4; + } + } + + return retval < 0 ? retval : nSize; +} + +/* + * Get the server root from the registry into 'dir' which is + * size bytes long. Returns 0 if the server root was found + * or if the serverroot key does not exist (in which case + * dir will contain an empty string), or -1 if there was + * an error getting the key. + */ + +int ap_registry_get_server_root(pool *p, char *dir, int size) +{ + int rv; + + rv = ap_registry_get_key_int(p, "ServerRoot", dir, size, NULL); + if (rv < 0) { + dir[0] = '\0'; + } + + return (rv < -1) ? -1 : 0; +} + +/********************************************************************** + * The rest of this file deals with storing keys or values in the registry + */ + +/* + * ap_registry_create_apache_key() creates the Apache registry key + * (HLKM\SOFTWARE\Apache Group\Apache\version, as defined at the start + * of this file), if it does not already exist. It will be called by + * ap_registry_store_key_int() if it cannot open this key. This + * function is intended to be called by ap_registry_store_key_int() if + * the Apache key does not exist when it comes to store a data item. + * + * Returns 0 on success or -1 on error. If -1 is returned, the error will + * already have been logged. + */ + +static int ap_registry_create_apache_key(void) +{ + static char *keys[] = + { "SOFTWARE", + VENDOR, + SOFTWARE, + VERSION, + NULL + }; + int index; + HKEY hKey; + HKEY hKeyNext; + int retval; + int rv; + + hKey = HKEY_LOCAL_MACHINE; + index = 0; + retval = 0; + + /* Walk the tree, creating at each stage if necessary */ + while (keys[index]) { + int result; + + rv = RegCreateKeyEx(hKey, + keys[index], /* subkey */ + 0, /* reserved */ + NULL, /* class */ + REG_OPTION_NON_VOLATILE, + KEY_WRITE, + NULL, + &hKeyNext, + &result); + if (rv != ERROR_SUCCESS) { + do_error(rv, "RegCreateKeyEx(%s)", keys[index]); + retval = -4; + } + + /* Close the old key */ + rv = RegCloseKey(hKey); + if (rv != ERROR_SUCCESS) { + do_error(rv, "RegCloseKey", NULL); + if (retval == 0) { + /* Keep error status from RegCreateKeyEx, if any */ + retval = -4; + } + } + + if (retval) { + break; + } + + hKey = hKeyNext; + index++; + } + + if (keys[index] == NULL) { + /* Close the final key we opened, if we walked the entire + * tree + */ + rv = RegCloseKey(hKey); + if (rv != ERROR_SUCCESS) { + do_error(rv, "RegCloseKey", NULL); + if (retval == 0) { + /* Keep error status from RegCreateKeyEx, if any */ + retval = -4; + } + } + } + + return retval; +} + +/* + * ap_registry_store_key_int() stores a value name and value under the + * Apache registry key. If the Apache key does not exist it is created + * first. This function is intended to be called from a wrapper function + * in this file to set particular data values, such as + * ap_registry_set_server_root() below. + * + * Returns 0 if the value name and data was stored successfully, or + * returns -1 if the Apache key does not exist (since we try to create + * this key, this should never happen), or -4 if any other error occurred + * (these values are consistent with ap_registry_get_key_int()). + * If the return value is negative then the error will already have been + * logged via aplog_error(). + */ + +static int ap_registry_store_key_int(char *key, DWORD type, void *value, int value_size) +{ + long rv; + HKEY hKey; + int retval; + + rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + REGKEY, + 0, + KEY_WRITE, + &hKey); + + if (rv == ERROR_FILE_NOT_FOUND) { + /* Key could not be opened -- try to create it + */ + if (ap_registry_create_apache_key() < 0) { + /* Creation failed (error already reported) */ + return -4; + } + + /* Now it has been created we should be able to open it + */ + rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + REGKEY, + 0, + KEY_WRITE, + &hKey); + + if (rv == ERROR_FILE_NOT_FOUND) { + ap_log_error(APLOG_MARK,APLOG_WARNING|APLOG_NOERRNO,NULL, + "Registry does not contain key " REGKEY " after creation"); + + return -1; + } + } + + if (rv != ERROR_SUCCESS) { + do_error(rv, "RegOpenKeyEx HKLM\\" REGKEY, + NULL); + return -4; + } + + /* Now set the value and data */ + rv = RegSetValueEx(hKey, + key, /* value key name */ + 0, /* reserved */ + type, /* type */ + value, /* value data */ + (DWORD)value_size); /* for size of "value" */ + + retval = 0; /* Return value */ + + if (rv != ERROR_SUCCESS) { + do_error(rv, "RegQueryValueEx(key %s)", key); + retval = -4; + } + else { + ap_log_error(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO,NULL, + "Registry stored HKLM\\" REGKEY "\\%s value %s", key, + type == REG_SZ ? value : "(not displayable)"); + } + + /* Make sure we close the key even if there was an error storing + * the data + */ + rv = RegCloseKey(hKey); + if (rv != ERROR_SUCCESS) { + do_error(rv, "RegCloseKey HKLM\\" REGKEY, NULL); + if (retval == 0) { + /* Keep error status from RegQueryValueEx, if any */ + retval = -4; + } + } + + return retval; +} + +/* + * Sets the serverroot value within the registry. Returns 0 on success + * or -1 on error. If -1 is return the error will already have been + * logged via aplog_error(). + */ + +int ap_registry_set_server_root(char *dir) +{ + int rv; + + rv = ap_registry_store_key_int("ServerRoot", REG_SZ, dir, strlen(dir)+1); + + return rv < 0 ? -1 : 0; +} diff --git a/APACHE_1_3b7/src/os/win32/registry.h b/APACHE_1_3b7/src/os/win32/registry.h new file mode 100755 index 0000000000..cb603184af --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/registry.h @@ -0,0 +1,6 @@ +/* + * Declarations for users of the functions defined in registry.c + */ + +extern int ap_registry_get_server_root(pool *p, char *dir, int size); +extern int ap_registry_set_server_root(char *dir); diff --git a/APACHE_1_3b7/src/os/win32/service.c b/APACHE_1_3b7/src/os/win32/service.c new file mode 100644 index 0000000000..8888aa1449 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/service.c @@ -0,0 +1,316 @@ +#ifdef WIN32 + +#include +#include +#include +#include +#include + +#include "httpd.h" +#include "http_conf_globals.h" +#include "http_log.h" +#include "http_main.h" +#include "multithread.h" +#include "service.h" +#include "registry.h" + +static struct +{ + int (*main_fn)(int, char **); + event *stop_event; + int connected; + SERVICE_STATUS_HANDLE hServiceStatus; + char *name; + int exit_status; + SERVICE_STATUS ssStatus; + FILE *logFile; +} globdat; + +static void WINAPI service_main_fn(DWORD, char **); +static void WINAPI service_ctrl(DWORD ctrlCode); +static int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint); +static void InstallService(); +static void RemoveService(); + + +int service_main(int (*main_fn)(int, char **), int argc, char **argv, + char *service_name, + int install_flag, int run_as_service) +{ + SERVICE_TABLE_ENTRY dispatchTable[] = + { + { service_name, service_main_fn }, + { NULL, NULL } + }; + + globdat.name = service_name; + + if(install_flag > 0) + { + InstallService(); + return(0); + } + else if(install_flag < 0) + { + RemoveService(); + return(0); + } + else + { + globdat.main_fn = main_fn; + globdat.stop_event = create_event(0, 0, "apache-signal"); + + if(run_as_service) + { + globdat.connected = 1; + if(!StartServiceCtrlDispatcher(dispatchTable)) + { + return((*main_fn)(argc, argv)); + } + else + { + return(globdat.exit_status); + } + } + else + { + globdat.connected = 0; + return((*main_fn)(argc, argv)); + } + } + +} + +void service_cd() +{ + /* change to the drive with the executable */ + char buf[300]; + GetModuleFileName(NULL, buf, 300); + buf[2] = 0; + chdir(buf); +} + +void __stdcall service_main_fn(DWORD argc, char **argv) +{ + + + if(!(globdat.hServiceStatus = RegisterServiceCtrlHandler( globdat.name, service_ctrl))) + { + globdat.exit_status = -1; + return; + } + + + ReportStatusToSCMgr( + SERVICE_START_PENDING, // service state + NO_ERROR, // exit code + 3000); // wait hint + + globdat.exit_status = (*globdat.main_fn)( argc, argv ); + + + ReportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 0); + + return; +} + +void service_set_status(int status) +{ + ReportStatusToSCMgr(status, NO_ERROR, 3000); +} + + + +// +// FUNCTION: service_ctrl +// +// PURPOSE: This function is called by the SCM whenever +// ControlService() is called on this service. +// +// PARAMETERS: +// dwCtrlCode - type of control requested +// +// RETURN VALUE: +// none +// +// COMMENTS: +// +VOID WINAPI service_ctrl(DWORD dwCtrlCode) +{ + int state; + + + state = globdat.ssStatus.dwCurrentState; + switch(dwCtrlCode) + { + // Stop the service. + // + case SERVICE_CONTROL_STOP: + state = SERVICE_STOP_PENDING; + ap_start_shutdown(); + break; + + // Update the service status. + // + case SERVICE_CONTROL_INTERROGATE: + break; + + // invalid control code + // + default: + break; + + } + + ReportStatusToSCMgr(state, NO_ERROR, 0); +} + + +int ReportStatusToSCMgr(int currentState, int exitCode, int waitHint) +{ + static int firstTime = 1; + static int checkPoint = 1; + int rv; + + if(firstTime) + { + firstTime = 0; + globdat.ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + globdat.ssStatus.dwServiceSpecificExitCode = 0; + globdat.ssStatus.dwCheckPoint = 1; + } + + if(globdat.connected) + { + if (currentState == SERVICE_START_PENDING) + globdat.ssStatus.dwControlsAccepted = 0; + else + globdat.ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + globdat.ssStatus.dwCurrentState = currentState; + globdat.ssStatus.dwWin32ExitCode = exitCode; + if(waitHint) + globdat.ssStatus.dwWaitHint = waitHint; + + if ( ( currentState == SERVICE_RUNNING ) || + ( currentState == SERVICE_STOPPED ) ) + { + globdat.ssStatus.dwWaitHint = 0; + globdat.ssStatus.dwCheckPoint = 0; + } + else + globdat.ssStatus.dwCheckPoint = ++checkPoint; + + rv = SetServiceStatus(globdat.hServiceStatus, &globdat.ssStatus); + + } + return(1); +} + + +void InstallService() +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + + TCHAR szPath[512]; + + if (GetModuleFileName( NULL, szPath, 512 ) == 0) + { + exit(1); + return; + } + + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + if (!schSCManager) { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "OpenSCManager failed"); + } + else { + schService = CreateService( + schSCManager, // SCManager database + globdat.name, // name of service + globdat.name, // name to display + SERVICE_ALL_ACCESS, // desired access + SERVICE_WIN32_OWN_PROCESS, // service type + SERVICE_AUTO_START, // start type + SERVICE_ERROR_NORMAL, // error control type + szPath, // service's binary + NULL, // no load ordering group + NULL, // no tag identifier + NULL, // dependencies + NULL, // LocalSystem account + NULL); // no password + + if (schService) { + CloseServiceHandle(schService); + + /* Now store the server_root in the registry */ + ap_registry_set_server_root(ap_server_root); + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "CreateService failed"); + } + + CloseServiceHandle(schSCManager); + } + +} + + + + +void RemoveService() +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + if (!schSCManager) { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "OpenSCManager failed"); + } + else { + schService = OpenService(schSCManager, globdat.name, SERVICE_ALL_ACCESS); + + if (schService == NULL) { + /* Could not open the service */ + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "OpenService failed"); + } + else { + /* try to stop the service */ + if (ControlService(schService, SERVICE_CONTROL_STOP, &globdat.ssStatus)) { + Sleep(1000); + while(QueryServiceStatus(schService, &globdat.ssStatus)) { + if(globdat.ssStatus.dwCurrentState == SERVICE_STOP_PENDING) + Sleep(1000); + else + break; + } + } + + // now remove the service + if (DeleteService(schService) == 0) + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "DeleteService failed"); + CloseServiceHandle(schService); + } + + CloseServiceHandle(schSCManager); + } + +} + +#endif /* WIN32 */ + + diff --git a/APACHE_1_3b7/src/os/win32/service.h b/APACHE_1_3b7/src/os/win32/service.h new file mode 100644 index 0000000000..e8b3316ea3 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/service.h @@ -0,0 +1,13 @@ + +#ifndef SERVICE_H +#define SERVICE_H + +#ifdef WIN32 +int service_main(int (*main_fn)(int, char **), int argc, char **argv, + char *service_name, + int install_flag, int run_as_service); +void service_set_status(int status); +void service_cd(); +#endif /* WIN32 */ + +#endif /* SERVICE_H */ diff --git a/APACHE_1_3b7/src/os/win32/util_win32.c b/APACHE_1_3b7/src/os/win32/util_win32.c new file mode 100644 index 0000000000..f1ff1acda6 --- /dev/null +++ b/APACHE_1_3b7/src/os/win32/util_win32.c @@ -0,0 +1,281 @@ +#include +#include +#include + +#include "httpd.h" + +static void sub_canonical_filename(char *szCanon, unsigned nCanon, const char *szFile) +{ + char buf[HUGE_STRING_LEN]; + int n; + char *szFilePart; + WIN32_FIND_DATA d; + HANDLE h; + + n = GetFullPathName(szFile, sizeof buf, buf, &szFilePart); + ap_assert(n); + ap_assert(n < sizeof buf); + + /* If we have \\machine\share, convert to \\machine\share\ */ + if (buf[0] == '\\' && buf[1] == '\\') { + char *s=strchr(buf+2,'\\'); + if(s && !strchr(s+1,'\\')) + strcat(s+1,"\\"); + } + + if (!strchr(buf, '*') && !strchr(buf, '?')) { + h = FindFirstFile(buf, &d); + if(h != INVALID_HANDLE_VALUE) + FindClose(h); + } + else { + h=INVALID_HANDLE_VALUE; + } + + if (szFilePart < buf+3) { + ap_assert(strlen(buf) < nCanon); + strcpy(szCanon, buf); + if(szCanon[0] != '\\') { /* a \ at the start means it is UNC, otherwise it is x: */ + ap_assert(isalpha(szCanon[0])); + ap_assert(szCanon[1] == ':'); + szCanon[2] = '/'; + } + else { + char *s; + + ap_assert(szCanon[1] == '\\'); + for(s=szCanon ; *s ; ++s) + if(*s == '\\') + *s='/'; + } + return; + } + if (szFilePart != buf+3) { + char b2[_MAX_PATH]; + ap_assert(szFilePart > buf+3); + + szFilePart[-1]='\0'; + sub_canonical_filename(b2, sizeof b2, buf); + + ap_assert(strlen(b2)+1 < nCanon); + strcpy(szCanon, b2); + strcat(szCanon, "/"); + } + else { + ap_assert(strlen(buf) < nCanon); + strcpy(szCanon, buf); + szCanon[2] = '/'; + szCanon[3] = '\0'; + } + if (h == INVALID_HANDLE_VALUE) { + ap_assert(strlen(szCanon)+strlen(szFilePart) < nCanon); + strcat(szCanon, szFilePart); + } + else { + ap_assert(strlen(szCanon)+strlen(d.cFileName) < nCanon); + strlwr(d.cFileName); + strcat(szCanon, d.cFileName); + } +} + +/* UNC requires backslashes, hence the conversion before canonicalisation. Not sure how + * many backslashes (could be that \\machine\share\some/path/is/ok for example). For now, do + * them all. + */ +API_EXPORT(char *) ap_os_canonical_filename(pool *pPool, const char *szFile) +{ + char buf[HUGE_STRING_LEN]; + char b2[HUGE_STRING_LEN]; + char *s; + + ap_assert(strlen(szFile) < sizeof b2); + strcpy(b2,szFile); + for(s=b2 ; *s ; ++s) + if(*s == '/') + *s='\\'; + + sub_canonical_filename(buf, sizeof buf, b2); + buf[0]=tolower(buf[0]); + + if (*szFile && szFile[strlen(szFile)-1] == '/' && buf[strlen(buf)-1] != '/') { + ap_assert(strlen(buf)+1 < sizeof buf); + strcat(buf, "/"); + } + + return ap_pstrdup(pPool, buf); +} + +/* 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; + + ap_assert(szPath[1] == ':' || szPath[1] == '/'); // we are dealing with either UNC or a drive + + if(szPath[0] == '/') { + 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; + } + if(nSlashes == 3) /* then we need to add one more to get \\machine\share\ */ + *s++='\\'; + *s='\0'; + return stat(buf,pStat); + } + + n = strlen(szPath); + if(szPath[n-1] == '\\' || szPath[n-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); +} diff --git a/APACHE_1_3b7/src/regex/.cvsignore b/APACHE_1_3b7/src/regex/.cvsignore new file mode 100644 index 0000000000..4487e89a7e --- /dev/null +++ b/APACHE_1_3b7/src/regex/.cvsignore @@ -0,0 +1,6 @@ +re +Debug +Release +regex.mdp +regex.ncb +Makefile diff --git a/APACHE_1_3b7/src/regex/COPYRIGHT b/APACHE_1_3b7/src/regex/COPYRIGHT new file mode 100644 index 0000000000..d43362fbfc --- /dev/null +++ b/APACHE_1_3b7/src/regex/COPYRIGHT @@ -0,0 +1,20 @@ +Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. +This software is not subject to any license of the American Telephone +and Telegraph Company or of the Regents of the University of California. + +Permission is granted to anyone to use this software for any purpose on +any computer system, and to alter it and redistribute it, subject +to the following restrictions: + +1. The author is not responsible for the consequences of use of this + software, no matter how awful, even if they arise from flaws in it. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. Since few users ever read sources, + credits must appear in the documentation. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. Since few users + ever read sources, credits must appear in the documentation. + +4. This notice may not be removed or altered. diff --git a/APACHE_1_3b7/src/regex/Makefile.tmpl b/APACHE_1_3b7/src/regex/Makefile.tmpl new file mode 100644 index 0000000000..fc0aa5ad95 --- /dev/null +++ b/APACHE_1_3b7/src/regex/Makefile.tmpl @@ -0,0 +1,143 @@ + +# You probably want to take -DREDEBUG out of CFLAGS, and put something like +# -O in, *after* testing (-DREDEBUG strengthens testing by enabling a lot of +# internal assertion checking and some debugging facilities). +# Put -Dconst= in for a pre-ANSI compiler. +# Do not take -DPOSIX_MISTAKE out. +# REGCFLAGS isn't important to you (it's for my use in some special contexts). +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES) +CFLAGS=-I. $(INCLUDES) $(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) -DPOSIX_MISTAKE + +# If you have a pre-ANSI compiler, put -o into MKHFLAGS. If you want +# the Berkeley __P macro, put -b in. +MKHFLAGS= + +# Flags for linking but not compiling, if any. +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) -L$(SRCDIR)/ap + +# Extra libraries for linking, if any. +LIBS=$(EXTRA_LIBS) $(LIBS1) -lap + +# Internal stuff, should not need changing. +OBJPRODN=regcomp.o regexec.o regerror.o regfree.o +OBJS=$(OBJPRODN) split.o debug.o main.o +H=cclass.h cname.h regex2.h utils.h +REGSRC=regcomp.c regerror.c regexec.c regfree.c +ALLSRC=$(REGSRC) engine.c debug.c main.c split.c + +# Stuff that matters only if you're trying to lint the package. +LINTFLAGS=-I. -Dstatic= -Dconst= -DREDEBUG +LINTC=regcomp.c regexec.c regerror.c regfree.c debug.c main.c +JUNKLINT=possible pointer alignment|null effect + +# arrangements to build forward-reference header files +.SUFFIXES: .ih .h +.c.ih: + sh ./mkh $(MKHFLAGS) -p $< >$@ + +all lib: libregex.a + +libregex.a: $(OBJPRODN) + rm -f libregex.a + ar cr libregex.a $(OBJPRODN) + $(RANLIB) libregex.a + +default: r + +purge: + rm -f *.o + +# stuff to build regex.h +REGEXH=../include/hsregex.h +REGEXHSRC=regex2.h $(REGSRC) +$(REGEXH): $(REGEXHSRC) mkh + sh ./mkh $(MKHFLAGS) -i _REGEX_H_ $(REGEXHSRC) > $(REGEXH) + +# cmp -s regex.tmp regex.h 2>/dev/null || cp regex.tmp regex.h +# rm -f regex.tmp + +# no automatic dependencies here +depend: + +# dependencies +$(OBJPRODN) debug.o: utils.h $(REGEXH) regex2.h +regcomp.o: cclass.h cname.h regcomp.ih +regexec.o: engine.c engine.ih +regerror.o: regerror.ih +debug.o: debug.ih +main.o: main.ih + +# tester +re: $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ + +# regression test +r: re tests + ./re &1 | egrep -v '$(JUNKLINT)' | tee lint + +fullprint: + ti README WHATSNEW notes todo | list + ti *.h | list + list *.c + list regex.3 regex.7 + +print: + ti README WHATSNEW notes todo | list + ti *.h | list + list reg*.c engine.c + + +mf.tmp: Makefile + sed '/^REGEXH=/s/=.*/=..\/include\\hsregex.h/' Makefile \ + | sed '/#DEL$$/d' >$@ + +DTRH=cclass.h cname.h regex2.h utils.h +PRE=COPYRIGHT README WHATSNEW +POST=mkh regex.3 regex.7 tests $(DTRH) $(ALLSRC) fake/*.[ch] +FILES=$(PRE) Makefile $(POST) +DTR=$(PRE) Makefile=mf.tmp $(POST) +dtr: $(FILES) mf.tmp + makedtr $(DTR) >$@ + rm mf.tmp + +cio: $(FILES) + cio $(FILES) + +rdf: $(FILES) + rcsdiff -c $(FILES) 2>&1 | p + +# various forms of cleanup +tidy: + rm -f junk* core core.* *.core dtr *.tmp lint + +clean: tidy + rm -f *.o *.s re libregex.a + +distclean: clean + -rm -f Makefile + +# don't do this one unless you know what you're doing +spotless: clean + rm -f mkh ../include/hsregex.h diff --git a/APACHE_1_3b7/src/regex/README b/APACHE_1_3b7/src/regex/README new file mode 100644 index 0000000000..cea9b67b66 --- /dev/null +++ b/APACHE_1_3b7/src/regex/README @@ -0,0 +1,32 @@ +alpha3.4 release. +Thu Mar 17 23:17:18 EST 1994 +henry@zoo.toronto.edu + +See WHATSNEW for change listing. + +installation notes: +-------- +Read the comments at the beginning of Makefile before running. + +Utils.h contains some things that just might have to be modified on +some systems, as well as a nested include (ugh) of . + +The "fake" directory contains quick-and-dirty fakes for some header +files and routines that old systems may not have. Note also that +-DUSEBCOPY will make utils.h substitute bcopy() for memmove(). + +After that, "make r" will build regcomp.o, regexec.o, regfree.o, +and regerror.o (the actual routines), bundle them together into a test +program, and run regression tests on them. No output is good output. + +"make lib" builds just the .o files for the actual routines (when +you're happy with testing and have adjusted CFLAGS for production), +and puts them together into libregex.a. You can pick up either the +library or *.o ("make lib" makes sure there are no other .o files left +around to confuse things). + +Main.c, debug.c, split.c are used for regression testing but are not part +of the RE routines themselves. + +Regex.h goes in /usr/include. All other .h files are internal only. +-------- diff --git a/APACHE_1_3b7/src/regex/WHATSNEW b/APACHE_1_3b7/src/regex/WHATSNEW new file mode 100644 index 0000000000..6e82e1dae0 --- /dev/null +++ b/APACHE_1_3b7/src/regex/WHATSNEW @@ -0,0 +1,92 @@ +New in alpha3.4: The complex bug alluded to below has been fixed (in a +slightly kludgey temporary way that may hurt efficiency a bit; this is +another "get it out the door for 4.4" release). The tests at the end of +the tests file have accordingly been uncommented. The primary sign of +the bug was that something like a?b matching ab matched b rather than ab. +(The bug was essentially specific to this exact situation, else it would +have shown up earlier.) + +New in alpha3.3: The definition of word boundaries has been altered +slightly, to more closely match the usual programming notion that "_" +is an alphabetic. Stuff used for pre-ANSI systems is now in a subdir, +and the makefile no longer alludes to it in mysterious ways. The +makefile has generally been cleaned up some. Fixes have been made +(again!) so that the regression test will run without -DREDEBUG, at +the cost of weaker checking. A workaround for a bug in some folks' + has been added. And some more things have been added to +tests, including a couple right at the end which are commented out +because the code currently flunks them (complex bug; fix coming). +Plus the usual minor cleanup. + +New in alpha3.2: Assorted bits of cleanup and portability improvement +(the development base is now a BSDI system using GCC instead of an ancient +Sun system, and the newer compiler exposed some glitches). Fix for a +serious bug that affected REs using many [] (including REG_ICASE REs +because of the way they are implemented), *sometimes*, depending on +memory-allocation patterns. The header-file prototypes no longer name +the parameters, avoiding possible name conflicts. The possibility that +some clot has defined CHAR_MIN as (say) `-128' instead of `(-128)' is +now handled gracefully. "uchar" is no longer used as an internal type +name (too many people have the same idea). Still the same old lousy +performance, alas. + +New in alpha3.1: Basically nothing, this release is just a bookkeeping +convenience. Stay tuned. + +New in alpha3.0: Performance is no better, alas, but some fixes have been +made and some functionality has been added. (This is basically the "get +it out the door in time for 4.4" release.) One bug fix: regfree() didn't +free the main internal structure (how embarrassing). It is now possible +to put NULs in either the RE or the target string, using (resp.) a new +REG_PEND flag and the old REG_STARTEND flag. The REG_NOSPEC flag to +regcomp() makes all characters ordinary, so you can match a literal +string easily (this will become more useful when performance improves!). +There are now primitives to match beginnings and ends of words, although +the syntax is disgusting and so is the implementation. The REG_ATOI +debugging interface has changed a bit. And there has been considerable +internal cleanup of various kinds. + +New in alpha2.3: Split change list out of README, and moved flags notes +into Makefile. Macro-ized the name of regex(7) in regex(3), since it has +to change for 4.4BSD. Cleanup work in engine.c, and some new regression +tests to catch tricky cases thereof. + +New in alpha2.2: Out-of-date manpages updated. Regerror() acquires two +small extensions -- REG_ITOA and REG_ATOI -- which avoid debugging kludges +in my own test program and might be useful to others for similar purposes. +The regression test will now compile (and run) without REDEBUG. The +BRE \$ bug is fixed. Most uses of "uchar" are gone; it's all chars now. +Char/uchar parameters are now written int/unsigned, to avoid possible +portability problems with unpromoted parameters. Some unsigned casts have +been introduced to minimize portability problems with shifting into sign +bits. + +New in alpha2.1: Lots of little stuff, cleanup and fixes. The one big +thing is that regex.h is now generated, using mkh, rather than being +supplied in the distribution; due to circularities in dependencies, +you have to build regex.h explicitly by "make h". The two known bugs +have been fixed (and the regression test now checks for them), as has a +problem with assertions not being suppressed in the absence of REDEBUG. +No performance work yet. + +New in alpha2: Backslash-anything is an ordinary character, not an +error (except, of course, for the handful of backslashed metacharacters +in BREs), which should reduce script breakage. The regression test +checks *where* null strings are supposed to match, and has generally +been tightened up somewhat. Small bug fixes in parameter passing (not +harmful, but technically errors) and some other areas. Debugging +invoked by defining REDEBUG rather than not defining NDEBUG. + +New in alpha+3: full prototyping for internal routines, using a little +helper program, mkh, which extracts prototypes given in stylized comments. +More minor cleanup. Buglet fix: it's CHAR_BIT, not CHAR_BITS. Simple +pre-screening of input when a literal string is known to be part of the +RE; this does wonders for performance. + +New in alpha+2: minor bits of cleanup. Notably, the number "32" for the +word width isn't hardwired into regexec.c any more, the public header +file prototypes the functions if __STDC__ is defined, and some small typos +in the manpages have been fixed. + +New in alpha+1: improvements to the manual pages, and an important +extension, the REG_STARTEND option to regexec(). diff --git a/APACHE_1_3b7/src/regex/cclass.h b/APACHE_1_3b7/src/regex/cclass.h new file mode 100644 index 0000000000..727cbb9255 --- /dev/null +++ b/APACHE_1_3b7/src/regex/cclass.h @@ -0,0 +1,31 @@ +/* character-class table */ +static struct cclass { + char *name; + char *chars; + char *multis; +} cclasses[] = { + { "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789", "" }, + { "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + "" }, + { "blank", " \t", "" }, + { "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\ +\25\26\27\30\31\32\33\34\35\36\37\177", "" }, + { "digit", "0123456789", "" }, + { "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "" }, + { "lower", "abcdefghijklmnopqrstuvwxyz", + "" }, + { "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ", + "" }, + { "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + "" }, + { "space", "\t\n\v\f\r ", "" }, + { "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "" }, + { "xdigit", "0123456789ABCDEFabcdef", + "" }, + { NULL, 0, "" } +}; diff --git a/APACHE_1_3b7/src/regex/cname.h b/APACHE_1_3b7/src/regex/cname.h new file mode 100644 index 0000000000..ff116e55e2 --- /dev/null +++ b/APACHE_1_3b7/src/regex/cname.h @@ -0,0 +1,102 @@ +/* character-name table */ +static struct cname { + char *name; + char code; +} cnames[] = { + { "NUL", '\0' }, + { "SOH", '\001' }, + { "STX", '\002' }, + { "ETX", '\003' }, + { "EOT", '\004' }, + { "ENQ", '\005' }, + { "ACK", '\006' }, + { "BEL", '\007' }, + { "alert", '\007' }, + { "BS", '\010' }, + { "backspace", '\b' }, + { "HT", '\011' }, + { "tab", '\t' }, + { "LF", '\012' }, + { "newline", '\n' }, + { "VT", '\013' }, + { "vertical-tab", '\v' }, + { "FF", '\014' }, + { "form-feed", '\f' }, + { "CR", '\015' }, + { "carriage-return", '\r' }, + { "SO", '\016' }, + { "SI", '\017' }, + { "DLE", '\020' }, + { "DC1", '\021' }, + { "DC2", '\022' }, + { "DC3", '\023' }, + { "DC4", '\024' }, + { "NAK", '\025' }, + { "SYN", '\026' }, + { "ETB", '\027' }, + { "CAN", '\030' }, + { "EM", '\031' }, + { "SUB", '\032' }, + { "ESC", '\033' }, + { "IS4", '\034' }, + { "FS", '\034' }, + { "IS3", '\035' }, + { "GS", '\035' }, + { "IS2", '\036' }, + { "RS", '\036' }, + { "IS1", '\037' }, + { "US", '\037' }, + { "space", ' ' }, + { "exclamation-mark", '!' }, + { "quotation-mark", '"' }, + { "number-sign", '#' }, + { "dollar-sign", '$' }, + { "percent-sign", '%' }, + { "ampersand", '&' }, + { "apostrophe", '\'' }, + { "left-parenthesis", '(' }, + { "right-parenthesis", ')' }, + { "asterisk", '*' }, + { "plus-sign", '+' }, + { "comma", ',' }, + { "hyphen", '-' }, + { "hyphen-minus", '-' }, + { "period", '.' }, + { "full-stop", '.' }, + { "slash", '/' }, + { "solidus", '/' }, + { "zero", '0' }, + { "one", '1' }, + { "two", '2' }, + { "three", '3' }, + { "four", '4' }, + { "five", '5' }, + { "six", '6' }, + { "seven", '7' }, + { "eight", '8' }, + { "nine", '9' }, + { "colon", ':' }, + { "semicolon", ';' }, + { "less-than-sign", '<' }, + { "equals-sign", '=' }, + { "greater-than-sign", '>' }, + { "question-mark", '?' }, + { "commercial-at", '@' }, + { "left-square-bracket", '[' }, + { "backslash", '\\' }, + { "reverse-solidus", '\\' }, + { "right-square-bracket", ']' }, + { "circumflex", '^' }, + { "circumflex-accent", '^' }, + { "underscore", '_' }, + { "low-line", '_' }, + { "grave-accent", '`' }, + { "left-brace", '{' }, + { "left-curly-bracket", '{' }, + { "vertical-line", '|' }, + { "right-brace", '}' }, + { "right-curly-bracket", '}' }, + { "tilde", '~' }, + { "DEL", '\177' }, + { NULL, 0 } +}; diff --git a/APACHE_1_3b7/src/regex/debug.c b/APACHE_1_3b7/src/regex/debug.c new file mode 100644 index 0000000000..f54778881a --- /dev/null +++ b/APACHE_1_3b7/src/regex/debug.c @@ -0,0 +1,242 @@ +#include +#include +#include +#include +#include +#include + +#include "hsregex.h" +#include "utils.h" +#include "regex2.h" +#include "debug.ih" + +/* + - regprint - print a regexp for debugging + == void regprint(regex_t *r, FILE *d); + */ +void +regprint(r, d) +regex_t *r; +FILE *d; +{ + register struct re_guts *g = r->re_g; + register int i; + register int c; + register int last; + int nincat[NC]; + + fprintf(d, "%ld states, %d categories", (long)g->nstates, + g->ncategories); + fprintf(d, ", first %ld last %ld", (long)g->firststate, + (long)g->laststate); + if (g->iflags&USEBOL) + fprintf(d, ", USEBOL"); + if (g->iflags&USEEOL) + fprintf(d, ", USEEOL"); + if (g->iflags&BAD) + fprintf(d, ", BAD"); + if (g->nsub > 0) + fprintf(d, ", nsub=%ld", (long)g->nsub); + if (g->must != NULL) + fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen, + g->must); + if (g->backrefs) + fprintf(d, ", backrefs"); + if (g->nplus > 0) + fprintf(d, ", nplus %ld", (long)g->nplus); + fprintf(d, "\n"); + s_print(g, d); + for (i = 0; i < g->ncategories; i++) { + nincat[i] = 0; + for (c = CHAR_MIN; c <= CHAR_MAX; c++) + if (g->categories[c] == i) + nincat[i]++; + } + fprintf(d, "cc0#%d", nincat[0]); + for (i = 1; i < g->ncategories; i++) + if (nincat[i] == 1) { + for (c = CHAR_MIN; c <= CHAR_MAX; c++) + if (g->categories[c] == i) + break; + fprintf(d, ", %d=%s", i, regchar(c)); + } + fprintf(d, "\n"); + for (i = 1; i < g->ncategories; i++) + if (nincat[i] != 1) { + fprintf(d, "cc%d\t", i); + last = -1; + for (c = CHAR_MIN; c <= CHAR_MAX+1; c++) /* +1 does flush */ + if (c <= CHAR_MAX && g->categories[c] == i) { + if (last < 0) { + fprintf(d, "%s", regchar(c)); + last = c; + } + } else { + if (last >= 0) { + if (last != c-1) + fprintf(d, "-%s", + regchar(c-1)); + last = -1; + } + } + fprintf(d, "\n"); + } +} + +/* + - s_print - print the strip for debugging + == static void s_print(register struct re_guts *g, FILE *d); + */ +static void +s_print(g, d) +register struct re_guts *g; +FILE *d; +{ + register sop *s; + register cset *cs; + register int i; + register int done = 0; + register sop opnd; + register int col = 0; + register int last; + register sopno offset = 2; +# define GAP() { if (offset % 5 == 0) { \ + if (col > 40) { \ + fprintf(d, "\n\t"); \ + col = 0; \ + } else { \ + fprintf(d, " "); \ + col++; \ + } \ + } else \ + col++; \ + offset++; \ + } + + if (OP(g->strip[0]) != OEND) + fprintf(d, "missing initial OEND!\n"); + for (s = &g->strip[1]; !done; s++) { + opnd = OPND(*s); + switch (OP(*s)) { + case OEND: + fprintf(d, "\n"); + done = 1; + break; + case OCHAR: + if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL) + fprintf(d, "\\%c", (char)opnd); + else + fprintf(d, "%s", regchar((char)opnd)); + break; + case OBOL: + fprintf(d, "^"); + break; + case OEOL: + fprintf(d, "$"); + break; + case OBOW: + fprintf(d, "\\{"); + break; + case OEOW: + fprintf(d, "\\}"); + break; + case OANY: + fprintf(d, "."); + break; + case OANYOF: + fprintf(d, "[(%ld)", (long)opnd); + cs = &g->sets[opnd]; + last = -1; + for (i = 0; i < g->csetsize+1; i++) /* +1 flushes */ + if (CHIN(cs, i) && i < g->csetsize) { + if (last < 0) { + fprintf(d, "%s", regchar(i)); + last = i; + } + } else { + if (last >= 0) { + if (last != i-1) + fprintf(d, "-%s", + regchar(i-1)); + last = -1; + } + } + fprintf(d, "]"); + break; + case OBACK_: + fprintf(d, "(\\<%ld>", (long)opnd); + break; + case O_BACK: + fprintf(d, "<%ld>\\)", (long)opnd); + break; + case OPLUS_: + fprintf(d, "(+"); + if (OP(*(s+opnd)) != O_PLUS) + fprintf(d, "<%ld>", (long)opnd); + break; + case O_PLUS: + if (OP(*(s-opnd)) != OPLUS_) + fprintf(d, "<%ld>", (long)opnd); + fprintf(d, "+)"); + break; + case OQUEST_: + fprintf(d, "(?"); + if (OP(*(s+opnd)) != O_QUEST) + fprintf(d, "<%ld>", (long)opnd); + break; + case O_QUEST: + if (OP(*(s-opnd)) != OQUEST_) + fprintf(d, "<%ld>", (long)opnd); + fprintf(d, "?)"); + break; + case OLPAREN: + fprintf(d, "((<%ld>", (long)opnd); + break; + case ORPAREN: + fprintf(d, "<%ld>))", (long)opnd); + break; + case OCH_: + fprintf(d, "<"); + if (OP(*(s+opnd)) != OOR2) + fprintf(d, "<%ld>", (long)opnd); + break; + case OOR1: + if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_) + fprintf(d, "<%ld>", (long)opnd); + fprintf(d, "|"); + break; + case OOR2: + fprintf(d, "|"); + if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH) + fprintf(d, "<%ld>", (long)opnd); + break; + case O_CH: + if (OP(*(s-opnd)) != OOR1) + fprintf(d, "<%ld>", (long)opnd); + fprintf(d, ">"); + break; + default: + fprintf(d, "!%ld(%ld)!", OP(*s), opnd); + break; + } + if (!done) + GAP(); + } +} + +/* + - regchar - make a character printable + == static char *regchar(int ch); + */ +static char * /* -> representation */ +regchar(ch) +int ch; +{ + static char buf[10]; + + if (isprint(ch) || ch == ' ') + sprintf(buf, "%c", ch); + else + sprintf(buf, "\\%o", ch); + return(buf); +} diff --git a/APACHE_1_3b7/src/regex/engine.c b/APACHE_1_3b7/src/regex/engine.c new file mode 100644 index 0000000000..f3b36b3e01 --- /dev/null +++ b/APACHE_1_3b7/src/regex/engine.c @@ -0,0 +1,1019 @@ +/* + * The matching engine and friends. This file is #included by regexec.c + * after suitable #defines of a variety of macros used herein, so that + * different state representations can be used without duplicating masses + * of code. + */ + +#ifdef SNAMES +#define matcher smatcher +#define fast sfast +#define slow sslow +#define dissect sdissect +#define backref sbackref +#define step sstep +#define print sprint +#define at sat +#define match smat +#endif +#ifdef LNAMES +#define matcher lmatcher +#define fast lfast +#define slow lslow +#define dissect ldissect +#define backref lbackref +#define step lstep +#define print lprint +#define at lat +#define match lmat +#endif + +/* another structure passed up and down to avoid zillions of parameters */ +struct match { + struct re_guts *g; + int eflags; + regmatch_t *pmatch; /* [nsub+1] (0 element unused) */ + char *offp; /* offsets work from here */ + char *beginp; /* start of string -- virtual NUL precedes */ + char *endp; /* end of string -- virtual NUL here */ + char *coldp; /* can be no match starting before here */ + char **lastpos; /* [nplus+1] */ + STATEVARS; + states st; /* current states */ + states fresh; /* states for a fresh start */ + states tmp; /* temporary */ + states empty; /* empty set of states */ +}; + +#include "engine.ih" + +#ifdef REDEBUG +#define SP(t, s, c) print(m, t, s, c, stdout) +#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2) +#define NOTE(str) { if (m->eflags®_TRACE) printf("=%s\n", (str)); } +#else +#define SP(t, s, c) /* nothing */ +#define AT(t, p1, p2, s1, s2) /* nothing */ +#define NOTE(s) /* nothing */ +#endif + +/* + - matcher - the actual matching engine + == static int matcher(register struct re_guts *g, char *string, \ + == size_t nmatch, regmatch_t pmatch[], int eflags); + */ +static int /* 0 success, REG_NOMATCH failure */ +matcher(g, string, nmatch, pmatch, eflags) +register struct re_guts *g; +char *string; +size_t nmatch; +regmatch_t pmatch[]; +int eflags; +{ + register char *endp; + register int i; + struct match mv; + register struct match *m = &mv; + register char *dp; + register const sopno gf = g->firststate+1; /* +1 for OEND */ + register const sopno gl = g->laststate; + char *start; + char *stop; + + /* simplify the situation where possible */ + if (g->cflags®_NOSUB) + nmatch = 0; + if (eflags®_STARTEND) { + start = string + pmatch[0].rm_so; + stop = string + pmatch[0].rm_eo; + } else { + start = string; + stop = start + strlen(start); + } + if (stop < start) + return(REG_INVARG); + + /* prescreening; this does wonders for this rather slow code */ + if (g->must != NULL) { + for (dp = start; dp < stop; dp++) + if (*dp == g->must[0] && stop - dp >= g->mlen && + memcmp(dp, g->must, (size_t)g->mlen) == 0) + break; + if (dp == stop) /* we didn't find g->must */ + return(REG_NOMATCH); + } + + /* match struct setup */ + m->g = g; + m->eflags = eflags; + m->pmatch = NULL; + m->lastpos = NULL; + m->offp = string; + m->beginp = start; + m->endp = stop; + STATESETUP(m, 4); + SETUP(m->st); + SETUP(m->fresh); + SETUP(m->tmp); + SETUP(m->empty); + CLEAR(m->empty); + + /* this loop does only one repetition except for backrefs */ + for (;;) { + endp = fast(m, start, stop, gf, gl); + if (endp == NULL) { /* a miss */ + STATETEARDOWN(m); + return(REG_NOMATCH); + } + if (nmatch == 0 && !g->backrefs) + break; /* no further info needed */ + + /* where? */ + assert(m->coldp != NULL); + for (;;) { + NOTE("finding start"); + endp = slow(m, m->coldp, stop, gf, gl); + if (endp != NULL) + break; + assert(m->coldp < m->endp); + m->coldp++; + } + if (nmatch == 1 && !g->backrefs) + break; /* no further info needed */ + + /* oh my, he wants the subexpressions... */ + if (m->pmatch == NULL) + m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) * + sizeof(regmatch_t)); + if (m->pmatch == NULL) { + STATETEARDOWN(m); + return(REG_ESPACE); + } + for (i = 1; i <= m->g->nsub; i++) + m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1; + if (!g->backrefs && !(m->eflags®_BACKR)) { + NOTE("dissecting"); + dp = dissect(m, m->coldp, endp, gf, gl); + } else { + if (g->nplus > 0 && m->lastpos == NULL) + m->lastpos = (char **)malloc((g->nplus+1) * + sizeof(char *)); + if (g->nplus > 0 && m->lastpos == NULL) { + free(m->pmatch); + STATETEARDOWN(m); + return(REG_ESPACE); + } + NOTE("backref dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0); + } + if (dp != NULL) + break; + + /* uh-oh... we couldn't find a subexpression-level match */ + assert(g->backrefs); /* must be back references doing it */ + assert(g->nplus == 0 || m->lastpos != NULL); + for (;;) { + if (dp != NULL || endp <= m->coldp) + break; /* defeat */ + NOTE("backoff"); + endp = slow(m, m->coldp, endp-1, gf, gl); + if (endp == NULL) + break; /* defeat */ + /* try it on a shorter possibility */ +#ifndef NDEBUG + for (i = 1; i <= m->g->nsub; i++) { + assert(m->pmatch[i].rm_so == -1); + assert(m->pmatch[i].rm_eo == -1); + } +#endif + NOTE("backoff dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0); + } + assert(dp == NULL || dp == endp); + if (dp != NULL) /* found a shorter one */ + break; + + /* despite initial appearances, there is no match here */ + NOTE("false alarm"); + start = m->coldp + 1; /* recycle starting later */ + assert(start <= stop); + } + + /* fill in the details if requested */ + if (nmatch > 0) { + pmatch[0].rm_so = m->coldp - m->offp; + pmatch[0].rm_eo = endp - m->offp; + } + if (nmatch > 1) { + assert(m->pmatch != NULL); + for (i = 1; i < nmatch; i++) + if (i <= m->g->nsub) + pmatch[i] = m->pmatch[i]; + else { + pmatch[i].rm_so = -1; + pmatch[i].rm_eo = -1; + } + } + + if (m->pmatch != NULL) + free((char *)m->pmatch); + if (m->lastpos != NULL) + free((char *)m->lastpos); + STATETEARDOWN(m); + return(0); +} + +/* + - dissect - figure out what matched what, no back references + == static char *dissect(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst); + */ +static char * /* == stop (success) always */ +dissect(m, start, stop, startst, stopst) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + register int i; + register sopno ss; /* start sop of current subRE */ + register sopno es; /* end sop of current subRE */ + register char *sp; /* start of string matched by it */ + register char *stp; /* string matched by it cannot pass here */ + register char *rest; /* start of rest of string */ + register char *tail; /* string unmatched by rest of RE */ + register sopno ssub; /* start sop of subsubRE */ + register sopno esub; /* end sop of subsubRE */ + register char *ssp; /* start of string matched by subsubRE */ + register char *sep; /* end of string matched by subsubRE */ + register char *oldssp; /* previous ssp */ + register char *dp; + + AT("diss", start, stop, startst, stopst); + sp = start; + for (ss = startst; ss < stopst; ss = es) { + /* identify end of subRE */ + es = ss; + switch (OP(m->g->strip[es])) { + case OPLUS_: + case OQUEST_: + es += OPND(m->g->strip[es]); + break; + case OCH_: + while (OP(m->g->strip[es]) != O_CH) + es += OPND(m->g->strip[es]); + break; + } + es++; + + /* figure out what it matched */ + switch (OP(m->g->strip[ss])) { + case OEND: + assert(nope); + break; + case OCHAR: + sp++; + break; + case OBOL: + case OEOL: + case OBOW: + case OEOW: + break; + case OANY: + case OANYOF: + sp++; + break; + case OBACK_: + case O_BACK: + assert(nope); + break; + /* cases where length of match is hard to find */ + case OQUEST_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + /* did innards match? */ + if (slow(m, sp, rest, ssub, esub) != NULL) { + dp = dissect(m, sp, rest, ssub, esub); + assert(dp == rest); + } else /* no */ + assert(sp == rest); + sp = rest; + break; + case OPLUS_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + ssp = sp; + oldssp = ssp; + for (;;) { /* find last match of innards */ + sep = slow(m, ssp, rest, ssub, esub); + if (sep == NULL || sep == ssp) + break; /* failed or matched null */ + oldssp = ssp; /* on to next try */ + ssp = sep; + } + if (sep == NULL) { + /* last successful match */ + sep = ssp; + ssp = oldssp; + } + assert(sep == rest); /* must exhaust substring */ + assert(slow(m, ssp, sep, ssub, esub) == rest); + dp = dissect(m, ssp, sep, ssub, esub); + assert(dp == sep); + sp = rest; + break; + case OCH_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = ss + OPND(m->g->strip[ss]) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + if (slow(m, sp, rest, ssub, esub) == rest) + break; /* it matched all of it */ + /* that one missed, try next one */ + assert(OP(m->g->strip[esub]) == OOR1); + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + dp = dissect(m, sp, rest, ssub, esub); + assert(dp == rest); + sp = rest; + break; + case O_PLUS: + case O_QUEST: + case OOR1: + case OOR2: + case O_CH: + assert(nope); + break; + case OLPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_so = sp - m->offp; + break; + case ORPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_eo = sp - m->offp; + break; + default: /* uh oh */ + assert(nope); + break; + } + } + + assert(sp == stop); + return(sp); +} + +/* + - backref - figure out what matched what, figuring in back references + == static char *backref(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst, sopno lev); + */ +static char * /* == stop (success) or NULL (failure) */ +backref(m, start, stop, startst, stopst, lev) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +sopno lev; /* PLUS nesting level */ +{ + register int i; + register sopno ss; /* start sop of current subRE */ + register char *sp; /* start of string matched by it */ + register sopno ssub; /* start sop of subsubRE */ + register sopno esub; /* end sop of subsubRE */ + register char *ssp; /* start of string matched by subsubRE */ + register char *dp; + register size_t len; + register int hard; + register sop s; + register regoff_t offsave; + register cset *cs; + + AT("back", start, stop, startst, stopst); + sp = start; + + /* get as far as we can with easy stuff */ + hard = 0; + for (ss = startst; !hard && ss < stopst; ss++) + switch (OP(s = m->g->strip[ss])) { + case OCHAR: + if (sp == stop || *sp++ != (char)OPND(s)) + return(NULL); + break; + case OANY: + if (sp == stop) + return(NULL); + sp++; + break; + case OANYOF: + cs = &m->g->sets[OPND(s)]; + if (sp == stop || !CHIN(cs, *sp++)) + return(NULL); + break; + case OBOL: + if ( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOL: + if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OBOW: + if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp > m->beginp && + !ISWORD(*(sp-1))) ) && + (sp < m->endp && ISWORD(*sp)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOW: + if (( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp < m->endp && !ISWORD(*sp)) ) && + (sp > m->beginp && ISWORD(*(sp-1))) ) + { /* yes */ } + else + return(NULL); + break; + case O_QUEST: + break; + case OOR1: /* matches null but needs to skip */ + ss++; + s = m->g->strip[ss]; + do { + assert(OP(s) == OOR2); + ss += OPND(s); + } while (OP(s = m->g->strip[ss]) != O_CH); + /* note that the ss++ gets us past the O_CH */ + break; + default: /* have to make a choice */ + hard = 1; + break; + } + if (!hard) { /* that was it! */ + if (sp != stop) + return(NULL); + return(sp); + } + ss--; /* adjust for the for's final increment */ + + /* the hard stuff */ + AT("hard", sp, stop, ss, stopst); + s = m->g->strip[ss]; + switch (OP(s)) { + case OBACK_: /* the vilest depths */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + if (m->pmatch[i].rm_eo == -1) + return(NULL); + assert(m->pmatch[i].rm_so != -1); + len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so; + assert(stop - m->beginp >= len); + if (sp > stop - len) + return(NULL); /* not enough left to match */ + ssp = m->offp + m->pmatch[i].rm_so; + if (memcmp(sp, ssp, len) != 0) + return(NULL); + while (m->g->strip[ss] != SOP(O_BACK, i)) + ss++; + return(backref(m, sp+len, stop, ss+1, stopst, lev)); + break; + case OQUEST_: /* to null or not */ + dp = backref(m, sp, stop, ss+1, stopst, lev); + if (dp != NULL) + return(dp); /* not */ + return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev)); + break; + case OPLUS_: + assert(m->lastpos != NULL); + assert(lev+1 <= m->g->nplus); + m->lastpos[lev+1] = sp; + return(backref(m, sp, stop, ss+1, stopst, lev+1)); + break; + case O_PLUS: + if (sp == m->lastpos[lev]) /* last pass matched null */ + return(backref(m, sp, stop, ss+1, stopst, lev-1)); + /* try another pass */ + m->lastpos[lev] = sp; + dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev); + if (dp == NULL) + return(backref(m, sp, stop, ss+1, stopst, lev-1)); + else + return(dp); + break; + case OCH_: /* find the right one, if any */ + ssub = ss + 1; + esub = ss + OPND(s) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + dp = backref(m, sp, stop, ssub, esub, lev); + if (dp != NULL) + return(dp); + /* that one missed, try next one */ + if (OP(m->g->strip[esub]) == O_CH) + return(NULL); /* there is none */ + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + break; + case OLPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_so; + m->pmatch[i].rm_so = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_so = offsave; + return(NULL); + break; + case ORPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_eo; + m->pmatch[i].rm_eo = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_eo = offsave; + return(NULL); + break; + default: /* uh oh */ + assert(nope); + break; + } + + /* "can't happen" */ + assert(nope); + /* NOTREACHED */ + return( NULL ); +} + +/* + - fast - step through the string at top speed + == static char *fast(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst); + */ +static char * /* where tentative match ended, or NULL */ +fast(m, start, stop, startst, stopst) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + register states st = m->st; + register states fresh = m->fresh; + register states tmp = m->tmp; + register char *p = start; + register int c = (start == m->beginp) ? OUT : *(start-1); + register int lastc; /* previous c */ + register int flagch; + register int i; + register char *coldp; /* last p after which no match was underway */ + + CLEAR(st); + SET1(st, startst); + st = step(m->g, startst, stopst, st, NOTHING, st); + ASSIGN(fresh, st); + SP("start", st, *p); + coldp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + if (EQ(st, fresh)) + coldp = p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("boleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("boweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, fresh); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("aft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + assert(coldp != NULL); + m->coldp = coldp; + if (ISSET(st, stopst)) + return(p+1); + else + return(NULL); +} + +/* + - slow - step through the string more deliberately + == static char *slow(register struct match *m, char *start, \ + == char *stop, sopno startst, sopno stopst); + */ +static char * /* where it ended */ +slow(m, start, stop, startst, stopst) +register struct match *m; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + register states st = m->st; + register states empty = m->empty; + register states tmp = m->tmp; + register char *p = start; + register int c = (start == m->beginp) ? OUT : *(start-1); + register int lastc; /* previous c */ + register int flagch; + register int i; + register char *matchp; /* last p at which a match ended */ + + AT("slow", start, stop, startst, stopst); + CLEAR(st); + SET1(st, startst); + SP("sstart", st, *p); + st = step(m->g, startst, stopst, st, NOTHING, st); + matchp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst)) + matchp = p; + if (EQ(st, empty) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, empty); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("saft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + return(matchp); +} + + +/* + - step - map set of states reachable before char to set reachable after + == static states step(register struct re_guts *g, sopno start, sopno stop, \ + == register states bef, int ch, register states aft); + == #define BOL (OUT+1) + == #define EOL (BOL+1) + == #define BOLEOL (BOL+2) + == #define NOTHING (BOL+3) + == #define BOW (BOL+4) + == #define EOW (BOL+5) + == #define CODEMAX (BOL+5) // highest code used + == #define NONCHAR(c) ((c) > CHAR_MAX) + == #define NNONCHAR (CODEMAX-CHAR_MAX) + */ +static states +step(g, start, stop, bef, ch, aft) +register struct re_guts *g; +sopno start; /* start state within strip */ +sopno stop; /* state after stop state within strip */ +register states bef; /* states reachable before */ +int ch; /* character or NONCHAR code */ +register states aft; /* states already known reachable after */ +{ + register cset *cs; + register sop s; + register sopno pc; + register onestate here; /* note, macros know this name */ + register sopno look; + register int i; + + for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) { + s = g->strip[pc]; + switch (OP(s)) { + case OEND: + assert(pc == stop-1); + break; + case OCHAR: + /* only characters can match */ + assert(!NONCHAR(ch) || ch != (char)OPND(s)); + if (ch == (char)OPND(s)) + FWD(aft, bef, 1); + break; + case OBOL: + if (ch == BOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OEOL: + if (ch == EOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OBOW: + if (ch == BOW) + FWD(aft, bef, 1); + break; + case OEOW: + if (ch == EOW) + FWD(aft, bef, 1); + break; + case OANY: + if (!NONCHAR(ch)) + FWD(aft, bef, 1); + break; + case OANYOF: + cs = &g->sets[OPND(s)]; + if (!NONCHAR(ch) && CHIN(cs, ch)) + FWD(aft, bef, 1); + break; + case OBACK_: /* ignored here */ + case O_BACK: + FWD(aft, aft, 1); + break; + case OPLUS_: /* forward, this is just an empty */ + FWD(aft, aft, 1); + break; + case O_PLUS: /* both forward and back */ + FWD(aft, aft, 1); + i = ISSETBACK(aft, OPND(s)); + BACK(aft, aft, OPND(s)); + if (!i && ISSETBACK(aft, OPND(s))) { + /* oho, must reconsider loop body */ + pc -= OPND(s) + 1; + INIT(here, pc); + } + break; + case OQUEST_: /* two branches, both forward */ + FWD(aft, aft, 1); + FWD(aft, aft, OPND(s)); + break; + case O_QUEST: /* just an empty */ + FWD(aft, aft, 1); + break; + case OLPAREN: /* not significant here */ + case ORPAREN: + FWD(aft, aft, 1); + break; + case OCH_: /* mark the first two branches */ + FWD(aft, aft, 1); + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + break; + case OOR1: /* done a branch, find the O_CH */ + if (ISSTATEIN(aft, here)) { + for (look = 1; + OP(s = g->strip[pc+look]) != O_CH; + look += OPND(s)) + assert(OP(s) == OOR2); + FWD(aft, aft, look); + } + break; + case OOR2: /* propagate OCH_'s marking */ + FWD(aft, aft, 1); + if (OP(g->strip[pc+OPND(s)]) != O_CH) { + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + } + break; + case O_CH: /* just empty */ + FWD(aft, aft, 1); + break; + default: /* ooooops... */ + assert(nope); + break; + } + } + + return(aft); +} + +#ifdef REDEBUG +/* + - print - print a set of states + == #ifdef REDEBUG + == static void print(struct match *m, char *caption, states st, \ + == int ch, FILE *d); + == #endif + */ +static void +print(m, caption, st, ch, d) +struct match *m; +char *caption; +states st; +int ch; +FILE *d; +{ + register struct re_guts *g = m->g; + register int i; + register int first = 1; + + if (!(m->eflags®_TRACE)) + return; + + fprintf(d, "%s", caption); + if (ch != '\0') + fprintf(d, " %s", pchar(ch)); + for (i = 0; i < g->nstates; i++) + if (ISSET(st, i)) { + fprintf(d, "%s%d", (first) ? "\t" : ", ", i); + first = 0; + } + fprintf(d, "\n"); +} + +/* + - at - print current situation + == #ifdef REDEBUG + == static void at(struct match *m, char *title, char *start, char *stop, \ + == sopno startst, sopno stopst); + == #endif + */ +static void +at(m, title, start, stop, startst, stopst) +struct match *m; +char *title; +char *start; +char *stop; +sopno startst; +sopno stopst; +{ + if (!(m->eflags®_TRACE)) + return; + + printf("%s %s-", title, pchar(*start)); + printf("%s ", pchar(*stop)); + printf("%ld-%ld\n", (long)startst, (long)stopst); +} + +#ifndef PCHARDONE +#define PCHARDONE /* never again */ +/* + - pchar - make a character printable + == #ifdef REDEBUG + == static char *pchar(int ch); + == #endif + * + * Is this identical to regchar() over in debug.c? Well, yes. But a + * duplicate here avoids having a debugging-capable regexec.o tied to + * a matching debug.o, and this is convenient. It all disappears in + * the non-debug compilation anyway, so it doesn't matter much. + */ +static char * /* -> representation */ +pchar(ch) +int ch; +{ + static char pbuf[10]; + + if (isprint(ch) || ch == ' ') + sprintf(pbuf, "%c", ch); + else + sprintf(pbuf, "\\%o", ch); + return(pbuf); +} +#endif +#endif + +#undef matcher +#undef fast +#undef slow +#undef dissect +#undef backref +#undef step +#undef print +#undef at +#undef match diff --git a/APACHE_1_3b7/src/regex/engine.ih b/APACHE_1_3b7/src/regex/engine.ih new file mode 100644 index 0000000000..cc98334e75 --- /dev/null +++ b/APACHE_1_3b7/src/regex/engine.ih @@ -0,0 +1,35 @@ +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === engine.c === */ +static int matcher(register struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags); +static char *dissect(register struct match *m, char *start, char *stop, sopno startst, sopno stopst); +static char *backref(register struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev); +static char *fast(register struct match *m, char *start, char *stop, sopno startst, sopno stopst); +static char *slow(register struct match *m, char *start, char *stop, sopno startst, sopno stopst); +static states step(register struct re_guts *g, sopno start, sopno stop, register states bef, int ch, register states aft); +#define BOL (OUT+1) +#define EOL (BOL+1) +#define BOLEOL (BOL+2) +#define NOTHING (BOL+3) +#define BOW (BOL+4) +#define EOW (BOL+5) +#define CODEMAX (BOL+5) /* highest code used */ +#define NONCHAR(c) ((c) > CHAR_MAX) +#define NNONCHAR (CODEMAX-CHAR_MAX) +#ifdef REDEBUG +static void print(struct match *m, char *caption, states st, int ch, FILE *d); +#endif +#ifdef REDEBUG +static void at(struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst); +#endif +#ifdef REDEBUG +static char *pchar(int ch); +#endif + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ diff --git a/APACHE_1_3b7/src/regex/main.c b/APACHE_1_3b7/src/regex/main.c new file mode 100644 index 0000000000..3d33304014 --- /dev/null +++ b/APACHE_1_3b7/src/regex/main.c @@ -0,0 +1,510 @@ +#include +#include +#include +#include +#include + +#include "hsregex.h" +#include "main.ih" + +char *progname; +int debug = 0; +int line = 0; +int status = 0; + +int copts = REG_EXTENDED; +int eopts = 0; +regoff_t startoff = 0; +regoff_t endoff = 0; + + +extern int split(); +extern void regprint(); + +/* + - main - do the simple case, hand off to regress() for regression + */ +int main(argc, argv) +int argc; +char *argv[]; +{ + regex_t re; +# define NS 10 + regmatch_t subs[NS]; + char erbuf[100]; + int err; + size_t len; + int c; + int errflg = 0; + register int i; + extern int optind; + extern char *optarg; + + progname = argv[0]; + + while ((c = getopt(argc, argv, "c:e:S:E:x")) != EOF) + switch (c) { + case 'c': /* compile options */ + copts = options('c', optarg); + break; + case 'e': /* execute options */ + eopts = options('e', optarg); + break; + case 'S': /* start offset */ + startoff = (regoff_t)atoi(optarg); + break; + case 'E': /* end offset */ + endoff = (regoff_t)atoi(optarg); + break; + case 'x': /* Debugging. */ + debug++; + break; + case '?': + default: + errflg++; + break; + } + if (errflg) { + fprintf(stderr, "usage: %s ", progname); + fprintf(stderr, "[-c copt][-C][-d] [re]\n"); + exit(2); + } + + if (optind >= argc) { + regress(stdin); + exit(status); + } + + err = regcomp(&re, argv[optind++], copts); + if (err) { + len = regerror(err, &re, erbuf, sizeof(erbuf)); + fprintf(stderr, "error %s, %d/%d `%s'\n", + eprint(err), len, sizeof(erbuf), erbuf); + exit(status); + } + regprint(&re, stdout); + + if (optind >= argc) { + regfree(&re); + exit(status); + } + + if (eopts®_STARTEND) { + subs[0].rm_so = startoff; + subs[0].rm_eo = strlen(argv[optind]) - endoff; + } + err = regexec(&re, argv[optind], (size_t)NS, subs, eopts); + if (err) { + len = regerror(err, &re, erbuf, sizeof(erbuf)); + fprintf(stderr, "error %s, %d/%d `%s'\n", + eprint(err), len, sizeof(erbuf), erbuf); + exit(status); + } + if (!(copts®_NOSUB)) { + len = (int)(subs[0].rm_eo - subs[0].rm_so); + if (subs[0].rm_so != -1) { + if (len != 0) + printf("match `%.*s'\n", (int)len, + argv[optind] + subs[0].rm_so); + else + printf("match `'@%.1s\n", + argv[optind] + subs[0].rm_so); + } + for (i = 1; i < NS; i++) + if (subs[i].rm_so != -1) + printf("(%d) `%.*s'\n", i, + (int)(subs[i].rm_eo - subs[i].rm_so), + argv[optind] + subs[i].rm_so); + } + exit(status); +} + +/* + - regress - main loop of regression test + == void regress(FILE *in); + */ +void +regress(in) +FILE *in; +{ + char inbuf[1000]; +# define MAXF 10 + char *f[MAXF]; + int nf; + int i; + char erbuf[100]; + size_t ne; + char *badpat = "invalid regular expression"; +# define SHORT 10 + char *bpname = "REG_BADPAT"; + regex_t re; + + while (fgets(inbuf, sizeof(inbuf), in) != NULL) { + line++; + if (inbuf[0] == '#' || inbuf[0] == '\n') + continue; /* NOTE CONTINUE */ + inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */ + if (debug) + fprintf(stdout, "%d:\n", line); + nf = split(inbuf, f, MAXF, "\t\t"); + if (nf < 3) { + fprintf(stderr, "bad input, line %d\n", line); + exit(1); + } + for (i = 0; i < nf; i++) + if (strcmp(f[i], "\"\"") == 0) + f[i] = ""; + if (nf <= 3) + f[3] = NULL; + if (nf <= 4) + f[4] = NULL; + try(f[0], f[1], f[2], f[3], f[4], options('c', f[1])); + if (opt('&', f[1])) /* try with either type of RE */ + try(f[0], f[1], f[2], f[3], f[4], + options('c', f[1]) &~ REG_EXTENDED); + } + + ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf)); + if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) { + fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n", + erbuf, badpat); + status = 1; + } + ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, (size_t)SHORT); + if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' || + ne != strlen(badpat)+1) { + fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n", + erbuf, SHORT-1, badpat); + status = 1; + } + ne = regerror(REG_ITOA|REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf)); + if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) { + fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n", + erbuf, bpname); + status = 1; + } + re.re_endp = bpname; + ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf)); + if (atoi(erbuf) != (int)REG_BADPAT) { + fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n", + erbuf, (long)REG_BADPAT); + status = 1; + } else if (ne != strlen(erbuf)+1) { + fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n", + erbuf, (long)REG_BADPAT); + status = 1; + } +} + +/* + - try - try it, and report on problems + == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts); + */ +void +try(f0, f1, f2, f3, f4, opts) +char *f0; +char *f1; +char *f2; +char *f3; +char *f4; +int opts; /* may not match f1 */ +{ + regex_t re; +# define NSUBS 10 + regmatch_t subs[NSUBS]; +# define NSHOULD 15 + char *should[NSHOULD]; + int nshould; + char erbuf[100]; + int err; + int len; + char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE"; + register int i; + char *grump; + char f0copy[1000]; + char f2copy[1000]; + + strcpy(f0copy, f0); + re.re_endp = (opts®_PEND) ? f0copy + strlen(f0copy) : NULL; + fixstr(f0copy); + err = regcomp(&re, f0copy, opts); + if (err != 0 && (!opt('C', f1) || err != efind(f2))) { + /* unexpected error or wrong error */ + len = regerror(err, &re, erbuf, sizeof(erbuf)); + fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n", + line, type, eprint(err), len, + sizeof(erbuf), erbuf); + status = 1; + } else if (err == 0 && opt('C', f1)) { + /* unexpected success */ + fprintf(stderr, "%d: %s should have given REG_%s\n", + line, type, f2); + status = 1; + err = 1; /* so we won't try regexec */ + } + + if (err != 0) { + regfree(&re); + return; + } + + strcpy(f2copy, f2); + fixstr(f2copy); + + if (options('e', f1)®_STARTEND) { + if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL) + fprintf(stderr, "%d: bad STARTEND syntax\n", line); + subs[0].rm_so = strchr(f2, '(') - f2 + 1; + subs[0].rm_eo = strchr(f2, ')') - f2; + } + err = regexec(&re, f2copy, NSUBS, subs, options('e', f1)); + + if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) { + /* unexpected error or wrong error */ + len = regerror(err, &re, erbuf, sizeof(erbuf)); + fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n", + line, type, eprint(err), len, + sizeof(erbuf), erbuf); + status = 1; + } else if (err != 0) { + /* nothing more to check */ + } else if (f3 == NULL) { + /* unexpected success */ + fprintf(stderr, "%d: %s exec should have failed\n", + line, type); + status = 1; + err = 1; /* just on principle */ + } else if (opts®_NOSUB) { + /* nothing more to check */ + } else if ((grump = check(f2, subs[0], f3)) != NULL) { + fprintf(stderr, "%d: %s %s\n", line, type, grump); + status = 1; + err = 1; + } + + if (err != 0 || f4 == NULL) { + regfree(&re); + return; + } + + for (i = 1; i < NSHOULD; i++) + should[i] = NULL; + nshould = split(f4, should+1, NSHOULD-1, ","); + if (nshould == 0) { + nshould = 1; + should[1] = ""; + } + for (i = 1; i < NSUBS; i++) { + grump = check(f2, subs[i], should[i]); + if (grump != NULL) { + fprintf(stderr, "%d: %s $%d %s\n", line, + type, i, grump); + status = 1; + err = 1; + } + } + + regfree(&re); +} + +/* + - options - pick options out of a regression-test string + == int options(int type, char *s); + */ +int +options(type, s) +int type; /* 'c' compile, 'e' exec */ +char *s; +{ + register char *p; + register int o = (type == 'c') ? copts : eopts; + register char *legal = (type == 'c') ? "bisnmp" : "^$#tl"; + + for (p = s; *p != '\0'; p++) + if (strchr(legal, *p) != NULL) + switch (*p) { + case 'b': + o &= ~REG_EXTENDED; + break; + case 'i': + o |= REG_ICASE; + break; + case 's': + o |= REG_NOSUB; + break; + case 'n': + o |= REG_NEWLINE; + break; + case 'm': + o &= ~REG_EXTENDED; + o |= REG_NOSPEC; + break; + case 'p': + o |= REG_PEND; + break; + case '^': + o |= REG_NOTBOL; + break; + case '$': + o |= REG_NOTEOL; + break; + case '#': + o |= REG_STARTEND; + break; + case 't': /* trace */ + o |= REG_TRACE; + break; + case 'l': /* force long representation */ + o |= REG_LARGE; + break; + case 'r': /* force backref use */ + o |= REG_BACKR; + break; + } + return(o); +} + +/* + - opt - is a particular option in a regression string? + == int opt(int c, char *s); + */ +int /* predicate */ +opt(c, s) +int c; +char *s; +{ + return(strchr(s, c) != NULL); +} + +/* + - fixstr - transform magic characters in strings + == void fixstr(register char *p); + */ +void +fixstr(p) +register char *p; +{ + if (p == NULL) + return; + + for (; *p != '\0'; p++) + if (*p == 'N') + *p = '\n'; + else if (*p == 'T') + *p = '\t'; + else if (*p == 'S') + *p = ' '; + else if (*p == 'Z') + *p = '\0'; +} + +/* + - check - check a substring match + == char *check(char *str, regmatch_t sub, char *should); + */ +char * /* NULL or complaint */ +check(str, sub, should) +char *str; +regmatch_t sub; +char *should; +{ + register int len; + register int shlen; + register char *p; + static char grump[500]; + register char *at = NULL; + + if (should != NULL && strcmp(should, "-") == 0) + should = NULL; + if (should != NULL && should[0] == '@') { + at = should + 1; + should = ""; + } + + /* check rm_so and rm_eo for consistency */ + if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) || + (sub.rm_so != -1 && sub.rm_eo == -1) || + (sub.rm_so != -1 && sub.rm_so < 0) || + (sub.rm_eo != -1 && sub.rm_eo < 0) ) { + sprintf(grump, "start %ld end %ld", (long)sub.rm_so, + (long)sub.rm_eo); + return(grump); + } + + /* check for no match */ + if (sub.rm_so == -1 && should == NULL) + return(NULL); + if (sub.rm_so == -1) + return("did not match"); + + /* check for in range */ + if (sub.rm_eo > strlen(str)) { + sprintf(grump, "start %ld end %ld, past end of string", + (long)sub.rm_so, (long)sub.rm_eo); + return(grump); + } + + len = (int)(sub.rm_eo - sub.rm_so); + shlen = (int)strlen(should); + p = str + sub.rm_so; + + /* check for not supposed to match */ + if (should == NULL) { + sprintf(grump, "matched `%.*s'", len, p); + return(grump); + } + + /* check for wrong match */ + if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) { + sprintf(grump, "matched `%.*s' instead", len, p); + return(grump); + } + if (shlen > 0) + return(NULL); + + /* check null match in right place */ + if (at == NULL) + return(NULL); + shlen = strlen(at); + if (shlen == 0) + shlen = 1; /* force check for end-of-string */ + if (strncmp(p, at, shlen) != 0) { + sprintf(grump, "matched null at `%.20s'", p); + return(grump); + } + return(NULL); +} + +/* + - eprint - convert error number to name + == static char *eprint(int err); + */ +static char * +eprint(err) +int err; +{ + static char epbuf[100]; + size_t len; + + len = regerror(REG_ITOA|err, (regex_t *)NULL, epbuf, sizeof(epbuf)); + assert(len <= sizeof(epbuf)); + return(epbuf); +} + +/* + - efind - convert error name to number + == static int efind(char *name); + */ +static int +efind(name) +char *name; +{ + static char efbuf[100]; + regex_t re; + + sprintf(efbuf, "REG_%s", name); + assert(strlen(efbuf) < sizeof(efbuf)); + re.re_endp = efbuf; + (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf)); + return(atoi(efbuf)); +} diff --git a/APACHE_1_3b7/src/regex/mkh b/APACHE_1_3b7/src/regex/mkh new file mode 100644 index 0000000000..5939d3482a --- /dev/null +++ b/APACHE_1_3b7/src/regex/mkh @@ -0,0 +1,75 @@ +#! /bin/sh +# mkh - pull headers out of C source + +# egrep pattern to pick out marked lines +egrep='^ =([ ]|$)' + +# Sed program to process marked lines into lines for the header file. +# The markers have already been removed. Two things are done here: removal +# of backslashed newlines, and some fudging of comments. The first is done +# because -o needs to have prototypes on one line to strip them down. +# Getting comments into the output is tricky; we turn C++-style // comments +# into /* */ comments, after altering any existing */'s to avoid trouble. +peel=' /\\$/N + /\\\n[ ]*/s///g + /\/\//s;\*/;* /;g + /\/\//s;//\(.*\);/*\1 */;' + +for a +do + case "$a" in + -o) # old (pre-function-prototype) compiler + # add code to comment out argument lists + peel="$peel + "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1(/*\2*/);' + shift + ;; + -b) # funny Berkeley __P macro + peel="$peel + "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1 __P((\2));' + shift + ;; + -s) # compiler doesn't like `static foo();' + # add code to get rid of the `static' + peel="$peel + "'/^static[ ][^\/]*[a-zA-Z0-9_)](.*)/s;static.;;' + shift + ;; + -p) # private declarations + egrep='^ ==([ ]|$)' + shift + ;; + -i) # wrap in #ifndef, argument is name + ifndef="$2" + shift ; shift + ;; + *) break + ;; + esac +done + +if test " $ifndef" != " " +then + echo "#ifndef $ifndef" + echo "#define $ifndef /* never again */" +fi +echo "/* ========= begin header generated by $0 ========= */" +echo '#ifdef __cplusplus' +echo 'extern "C" {' +echo '#endif' +for f +do + echo + echo "/* === $f === */" + egrep "$egrep" $f | sed 's/^ ==*[ ]//;s/^ ==*$//' | sed "$peel" + echo +done +echo '#ifdef __cplusplus' +echo '}' +echo '#endif' +echo "/* ========= end header generated by $0 ========= */" +if test " $ifndef" != " " +then + echo "#endif" +fi +exit 0 diff --git a/APACHE_1_3b7/src/regex/regcomp.c b/APACHE_1_3b7/src/regex/regcomp.c new file mode 100644 index 0000000000..ebb2a0cbb9 --- /dev/null +++ b/APACHE_1_3b7/src/regex/regcomp.c @@ -0,0 +1,1546 @@ +#include +#include +#include +#include +#include +#include + +#include "hsregex.h" +#include "utils.h" +#include "regex2.h" + +#include "cclass.h" +#include "cname.h" + +/* + * parse structure, passed up and down to avoid global variables and + * other clumsinesses + */ +struct parse { + char *next; /* next character in RE */ + char *end; /* end of string (-> NUL normally) */ + int error; /* has an error been seen? */ + sop *strip; /* malloced strip */ + sopno ssize; /* malloced strip size (allocated) */ + sopno slen; /* malloced strip length (used) */ + int ncsalloc; /* number of csets allocated */ + struct re_guts *g; +# define NPAREN 10 /* we need to remember () 1-9 for back refs */ + sopno pbegin[NPAREN]; /* -> ( ([0] unused) */ + sopno pend[NPAREN]; /* -> ) ([0] unused) */ +}; + +#include "regcomp.ih" + +static char nuls[10]; /* place to point scanner in event of error */ + +/* + * macros for use with parse structure + * BEWARE: these know that the parse structure is named `p' !!! + */ +#define PEEK() (*p->next) +#define PEEK2() (*(p->next+1)) +#define MORE() (p->next < p->end) +#define MORE2() (p->next+1 < p->end) +#define SEE(c) (MORE() && PEEK() == (c)) +#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b)) +#define EAT(c) ((SEE(c)) ? (NEXT1(), 1) : 0) +#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0) +#define NEXT1() (p->next++) +#define NEXT2() (p->next += 2) +#define NEXTn(n) (p->next += (n)) +#define GETNEXT() (*p->next++) +#define SETERROR(e) seterr(p, (e)) +#define REQUIRE(co, e) ((void)((co) || SETERROR(e))) +#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e)) +#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e)) +#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e)) +#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd)) +#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos) +#define AHEAD(pos) dofwd(p, pos, HERE()-(pos)) +#define ASTERN(sop, pos) EMIT(sop, HERE()-pos) +#define HERE() (p->slen) +#define THERE() (p->slen - 1) +#define THERETHERE() (p->slen - 2) +#define DROP(n) (p->slen -= (n)) + +#ifndef NDEBUG +static int never = 0; /* for use in asserts; shuts lint up */ +#else +#define never 0 /* some s have bugs too */ +#endif + +/* + - regcomp - interface for parser and compilation + = API_EXPORT(int) regcomp(regex_t *, const char *, int); + = #define REG_BASIC 0000 + = #define REG_EXTENDED 0001 + = #define REG_ICASE 0002 + = #define REG_NOSUB 0004 + = #define REG_NEWLINE 0010 + = #define REG_NOSPEC 0020 + = #define REG_PEND 0040 + = #define REG_DUMP 0200 + */ +API_EXPORT(int) /* 0 success, otherwise REG_something */ +regcomp(preg, pattern, cflags) +regex_t *preg; +const char *pattern; +int cflags; +{ + struct parse pa; + register struct re_guts *g; + register struct parse *p = &pa; + register int i; + register size_t len; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&~REG_DUMP) +#endif + + cflags = GOODFLAGS(cflags); + if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) + return(REG_INVARG); + + if (cflags®_PEND) { + if (preg->re_endp < pattern) + return(REG_INVARG); + len = preg->re_endp - pattern; + } else + len = strlen((char *)pattern); + + /* do the mallocs early so failure handling is easy */ + g = (struct re_guts *)malloc(sizeof(struct re_guts) + + (NC-1)*sizeof(cat_t)); + if (g == NULL) + return(REG_ESPACE); + p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ + p->strip = (sop *)malloc(p->ssize * sizeof(sop)); + p->slen = 0; + if (p->strip == NULL) { + free((char *)g); + return(REG_ESPACE); + } + + /* set things up */ + p->g = g; + p->next = (char *)pattern; /* convenience; we do not modify it */ + p->end = p->next + len; + p->error = 0; + p->ncsalloc = 0; + for (i = 0; i < NPAREN; i++) { + p->pbegin[i] = 0; + p->pend[i] = 0; + } + g->csetsize = NC; + g->sets = NULL; + g->setbits = NULL; + g->ncsets = 0; + g->cflags = cflags; + g->iflags = 0; + g->nbol = 0; + g->neol = 0; + g->must = NULL; + g->mlen = 0; + g->nsub = 0; + g->ncategories = 1; /* category 0 is "everything else" */ + g->categories = &g->catspace[-(CHAR_MIN)]; + (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t)); + g->backrefs = 0; + + /* do it */ + EMIT(OEND, 0); + g->firststate = THERE(); + if (cflags®_EXTENDED) + p_ere(p, OUT); + else if (cflags®_NOSPEC) + p_str(p); + else + p_bre(p, OUT, OUT); + EMIT(OEND, 0); + g->laststate = THERE(); + + /* tidy up loose ends and fill things in */ + categorize(p, g); + stripsnug(p, g); + findmust(p, g); + g->nplus = pluscount(p, g); + g->magic = MAGIC2; + preg->re_nsub = g->nsub; + preg->re_g = g; + preg->re_magic = MAGIC1; +#ifndef REDEBUG + /* not debugging, so can't rely on the assert() in regexec() */ + if (g->iflags&BAD) + SETERROR(REG_ASSERT); +#endif + + /* win or lose, we're done */ + if (p->error != 0) /* lose */ + regfree(preg); + return(p->error); +} + +/* + - p_ere - ERE parser top level, concatenation and alternation + == static void p_ere(register struct parse *p, int stop); + */ +static void +p_ere(p, stop) +register struct parse *p; +int stop; /* character this ERE should end at */ +{ + register char c; + register sopno prevback = 0; + register sopno prevfwd = 0; + register sopno conc; + register int first = 1; /* is this the first alternative? */ + + for (;;) { + /* do a bunch of concatenated expressions */ + conc = HERE(); + while (MORE() && (c = PEEK()) != '|' && c != stop) + p_ere_exp(p); + REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ + + if (!EAT('|')) + break; /* NOTE BREAK OUT */ + + if (first) { + INSERT(OCH_, conc); /* offset is wrong */ + prevfwd = conc; + prevback = conc; + first = 0; + } + ASTERN(OOR1, prevback); + prevback = THERE(); + AHEAD(prevfwd); /* fix previous offset */ + prevfwd = HERE(); + EMIT(OOR2, 0); /* offset is very wrong */ + } + + if (!first) { /* tail-end fixups */ + AHEAD(prevfwd); + ASTERN(O_CH, prevback); + } + + assert(!MORE() || SEE(stop)); +} + +/* + - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op + == static void p_ere_exp(register struct parse *p); + */ +static void +p_ere_exp(p) +register struct parse *p; +{ + register char c; + register sopno pos; + register int count; + register int count2; + register sopno subno; + int wascaret = 0; + + assert(MORE()); /* caller should have ensured this */ + c = GETNEXT(); + + pos = HERE(); + switch (c) { + case '(': + REQUIRE(MORE(), REG_EPAREN); + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + if (!SEE(')')) + p_ere(p, ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + MUSTEAT(')', REG_EPAREN); + break; +#ifndef POSIX_MISTAKE + case ')': /* happens only if no current unmatched ( */ + /* + * You may ask, why the ifndef? Because I didn't notice + * this until slightly too late for 1003.2, and none of the + * other 1003.2 regular-expression reviewers noticed it at + * all. So an unmatched ) is legal POSIX, at least until + * we can get it fixed. + */ + SETERROR(REG_EPAREN); + break; +#endif + case '^': + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + wascaret = 1; + break; + case '$': + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + break; + case '|': + SETERROR(REG_EMPTY); + break; + case '*': + case '+': + case '?': + SETERROR(REG_BADRPT); + break; + case '.': + if (p->g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case '\\': + REQUIRE(MORE(), REG_EESCAPE); + c = GETNEXT(); + ordinary(p, c); + break; + case '{': /* okay as ordinary except if digit follows */ + REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, c); + break; + } + + if (!MORE()) + return; + c = PEEK(); + /* we call { a repetition if followed by a digit */ + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit(PEEK2())) )) + return; /* no repetition, we're done */ + NEXT1(); + + REQUIRE(!wascaret, REG_BADRPT); + switch (c) { + case '*': /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + break; + case '+': + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + break; + case '?': + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, pos); /* offset slightly wrong */ + ASTERN(OOR1, pos); /* this one's right */ + AHEAD(pos); /* fix the OCH_ */ + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + break; + case '{': + count = p_count(p); + if (EAT(',')) { + if (isdigit(PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EAT('}')) { /* error heuristics */ + while (MORE() && PEEK() != '}') + NEXT1(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + break; + } + + if (!MORE()) + return; + c = PEEK(); + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit(PEEK2())) ) ) + return; + SETERROR(REG_BADRPT); +} + +/* + - p_str - string (no metacharacters) "parser" + == static void p_str(register struct parse *p); + */ +static void +p_str(p) +register struct parse *p; +{ + REQUIRE(MORE(), REG_EMPTY); + while (MORE()) + ordinary(p, GETNEXT()); +} + +/* + - p_bre - BRE parser top level, anchoring and concatenation + == static void p_bre(register struct parse *p, register int end1, \ + == register int end2); + * Giving end1 as OUT essentially eliminates the end1/end2 check. + * + * This implementation is a bit of a kludge, in that a trailing $ is first + * taken as an ordinary character and then revised to be an anchor. The + * only undesirable side effect is that '$' gets included as a character + * category in such cases. This is fairly harmless; not worth fixing. + * The amount of lookahead needed to avoid this kludge is excessive. + */ +static void +p_bre(p, end1, end2) +register struct parse *p; +register int end1; /* first terminating character */ +register int end2; /* second terminating character */ +{ + register sopno start = HERE(); + register int first = 1; /* first subexpression? */ + register int wasdollar = 0; + + if (EAT('^')) { + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + } + while (MORE() && !SEETWO(end1, end2)) { + wasdollar = p_simp_re(p, first); + first = 0; + } + if (wasdollar) { /* oops, that was a trailing anchor */ + DROP(1); + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + } + + REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */ +} + +/* + - p_simp_re - parse a simple RE, an atom possibly followed by a repetition + == static int p_simp_re(register struct parse *p, int starordinary); + */ +static int /* was the simple RE an unbackslashed $? */ +p_simp_re(p, starordinary) +register struct parse *p; +int starordinary; /* is a leading * an ordinary character? */ +{ + register int c; + register int count; + register int count2; + register sopno pos; + register int i; + register sopno subno; +# define BACKSL (1<g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case BACKSL|'{': + SETERROR(REG_BADRPT); + break; + case BACKSL|'(': + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + /* the MORE here is an error heuristic */ + if (MORE() && !SEETWO('\\', ')')) + p_bre(p, '\\', ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + REQUIRE(EATTWO('\\', ')'), REG_EPAREN); + break; + case BACKSL|')': /* should not get here -- must be user */ + case BACKSL|'}': + SETERROR(REG_EPAREN); + break; + case BACKSL|'1': + case BACKSL|'2': + case BACKSL|'3': + case BACKSL|'4': + case BACKSL|'5': + case BACKSL|'6': + case BACKSL|'7': + case BACKSL|'8': + case BACKSL|'9': + i = (c&~BACKSL) - '0'; + assert(i < NPAREN); + if (p->pend[i] != 0) { + assert(i <= p->g->nsub); + EMIT(OBACK_, i); + assert(p->pbegin[i] != 0); + assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); + assert(OP(p->strip[p->pend[i]]) == ORPAREN); + (void) dupl(p, p->pbegin[i]+1, p->pend[i]); + EMIT(O_BACK, i); + } else + SETERROR(REG_ESUBREG); + p->g->backrefs = 1; + break; + case '*': + REQUIRE(starordinary, REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, c &~ BACKSL); + break; + } + + if (EAT('*')) { /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + } else if (EATTWO('\\', '{')) { + count = p_count(p); + if (EAT(',')) { + if (MORE() && isdigit(PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EATTWO('\\', '}')) { /* error heuristics */ + while (MORE() && !SEETWO('\\', '}')) + NEXT1(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + } else if (c == (unsigned char)'$') /* $ (but not \$) ends it */ + return(1); + + return(0); +} + +/* + - p_count - parse a repetition count + == static int p_count(register struct parse *p); + */ +static int /* the value */ +p_count(p) +register struct parse *p; +{ + register int count = 0; + register int ndigits = 0; + + while (MORE() && isdigit(PEEK()) && count <= DUPMAX) { + count = count*10 + (GETNEXT() - '0'); + ndigits++; + } + + REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); + return(count); +} + +/* + - p_bracket - parse a bracketed character list + == static void p_bracket(register struct parse *p); + * + * Note a significant property of this code: if the allocset() did SETERROR, + * no set operations are done. + */ +static void +p_bracket(p) +register struct parse *p; +{ + register cset *cs = allocset(p); + register int invert = 0; + + /* Dept of Truly Sickening Special-Case Kludges */ + if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) { + EMIT(OBOW, 0); + NEXTn(6); + return; + } + if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) { + EMIT(OEOW, 0); + NEXTn(6); + return; + } + + if (EAT('^')) + invert++; /* make note to invert set at end */ + if (EAT(']')) + CHadd(cs, ']'); + else if (EAT('-')) + CHadd(cs, '-'); + while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) + p_b_term(p, cs); + if (EAT('-')) + CHadd(cs, '-'); + MUSTEAT(']', REG_EBRACK); + + if (p->error != 0) /* don't mess things up further */ + return; + + if (p->g->cflags®_ICASE) { + register int i; + register int ci; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i) && isalpha(i)) { + ci = othercase(i); + if (ci != i) + CHadd(cs, ci); + } + if (cs->multis != NULL) + mccase(p, cs); + } + if (invert) { + register int i; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i)) + CHsub(cs, i); + else + CHadd(cs, i); + if (p->g->cflags®_NEWLINE) + CHsub(cs, '\n'); + if (cs->multis != NULL) + mcinvert(p, cs); + } + + assert(cs->multis == NULL); /* xxx */ + + if (nch(p, cs) == 1) { /* optimize singleton sets */ + ordinary(p, firstch(p, cs)); + freeset(p, cs); + } else + EMIT(OANYOF, freezeset(p, cs)); +} + +/* + - p_b_term - parse one term of a bracketed character list + == static void p_b_term(register struct parse *p, register cset *cs); + */ +static void +p_b_term(p, cs) +register struct parse *p; +register cset *cs; +{ + register char c; + register char start, finish; + register int i; + + /* classify what we've got */ + switch ((MORE()) ? PEEK() : '\0') { + case '[': + c = (MORE2()) ? PEEK2() : '\0'; + break; + case '-': + SETERROR(REG_ERANGE); + return; /* NOTE RETURN */ + break; + default: + c = '\0'; + break; + } + + switch (c) { + case ':': /* character class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECTYPE); + p_b_cclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO(':', ']'), REG_ECTYPE); + break; + case '=': /* equivalence class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECOLLATE); + p_b_eclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); + break; + default: /* symbol, ordinary character, or range */ +/* xxx revision needed for multichar stuff */ + start = p_b_symbol(p); + if (SEE('-') && MORE2() && PEEK2() != ']') { + /* range */ + NEXT1(); + if (EAT('-')) + finish = '-'; + else + finish = p_b_symbol(p); + } else + finish = start; +/* xxx what about signed chars here... */ + REQUIRE(start <= finish, REG_ERANGE); + for (i = start; i <= finish; i++) + CHadd(cs, i); + break; + } +} + +/* + - p_b_cclass - parse a character-class name and deal with it + == static void p_b_cclass(register struct parse *p, register cset *cs); + */ +static void +p_b_cclass(p, cs) +register struct parse *p; +register cset *cs; +{ + register char *sp = p->next; + register struct cclass *cp; + register size_t len; + register char *u; + register char c; + + while (MORE() && isalpha(PEEK())) + NEXT1(); + len = p->next - sp; + for (cp = cclasses; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + break; + if (cp->name == NULL) { + /* oops, didn't find it */ + SETERROR(REG_ECTYPE); + return; + } + + u = cp->chars; + while ((c = *u++) != '\0') + CHadd(cs, c); + for (u = cp->multis; *u != '\0'; u += strlen(u) + 1) + MCadd(p, cs, u); +} + +/* + - p_b_eclass - parse an equivalence-class name and deal with it + == static void p_b_eclass(register struct parse *p, register cset *cs); + * + * This implementation is incomplete. xxx + */ +static void +p_b_eclass(p, cs) +register struct parse *p; +register cset *cs; +{ + register char c; + + c = p_b_coll_elem(p, '='); + CHadd(cs, c); +} + +/* + - p_b_symbol - parse a character or [..]ed multicharacter collating symbol + == static char p_b_symbol(register struct parse *p); + */ +static char /* value of symbol */ +p_b_symbol(p) +register struct parse *p; +{ + register char value; + + REQUIRE(MORE(), REG_EBRACK); + if (!EATTWO('[', '.')) + return(GETNEXT()); + + /* collating symbol */ + value = p_b_coll_elem(p, '.'); + REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); + return(value); +} + +/* + - p_b_coll_elem - parse a collating-element name and look it up + == static char p_b_coll_elem(register struct parse *p, int endc); + */ +static char /* value of collating element */ +p_b_coll_elem(p, endc) +register struct parse *p; +int endc; /* name ended by endc,']' */ +{ + register char *sp = p->next; + register struct cname *cp; + register int len; + + while (MORE() && !SEETWO(endc, ']')) + NEXT1(); + if (!MORE()) { + SETERROR(REG_EBRACK); + return(0); + } + len = p->next - sp; + for (cp = cnames; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + return(cp->code); /* known name */ + if (len == 1) + return(*sp); /* single character */ + SETERROR(REG_ECOLLATE); /* neither */ + return(0); +} + +/* + - othercase - return the case counterpart of an alphabetic + == static char othercase(int ch); + */ +static char /* if no counterpart, return ch */ +othercase(ch) +int ch; +{ + assert(isalpha(ch)); + if (isupper(ch)) + return(tolower(ch)); + else if (islower(ch)) + return(toupper(ch)); + else /* peculiar, but could happen */ + return(ch); +} + +/* + - bothcases - emit a dualcase version of a two-case character + == static void bothcases(register struct parse *p, int ch); + * + * Boy, is this implementation ever a kludge... + */ +static void +bothcases(p, ch) +register struct parse *p; +int ch; +{ + register char *oldnext = p->next; + register char *oldend = p->end; + char bracket[3]; + + assert(othercase(ch) != ch); /* p_bracket() would recurse */ + p->next = bracket; + p->end = bracket+2; + bracket[0] = ch; + bracket[1] = ']'; + bracket[2] = '\0'; + p_bracket(p); + assert(p->next == bracket+2); + p->next = oldnext; + p->end = oldend; +} + +/* + - ordinary - emit an ordinary character + == static void ordinary(register struct parse *p, register int ch); + */ +static void +ordinary(p, ch) +register struct parse *p; +register int ch; +{ + register cat_t *cap = p->g->categories; + + if ((p->g->cflags®_ICASE) && isalpha(ch) && othercase(ch) != ch) + bothcases(p, ch); + else { + EMIT(OCHAR, (unsigned char)ch); + if (cap[ch] == 0) + cap[ch] = p->g->ncategories++; + } +} + +/* + - nonnewline - emit REG_NEWLINE version of OANY + == static void nonnewline(register struct parse *p); + * + * Boy, is this implementation ever a kludge... + */ +static void +nonnewline(p) +register struct parse *p; +{ + register char *oldnext = p->next; + register char *oldend = p->end; + char bracket[4]; + + p->next = bracket; + p->end = bracket+3; + bracket[0] = '^'; + bracket[1] = '\n'; + bracket[2] = ']'; + bracket[3] = '\0'; + p_bracket(p); + assert(p->next == bracket+3); + p->next = oldnext; + p->end = oldend; +} + +/* + - repeat - generate code for a bounded repetition, recursively if needed + == static void repeat(register struct parse *p, sopno start, int from, int to); + */ +static void +repeat(p, start, from, to) +register struct parse *p; +sopno start; /* operand from here to end of strip */ +int from; /* repeated from this number */ +int to; /* to this number of times (maybe INFINITY) */ +{ + register sopno finish = HERE(); +# define N 2 +# define INF 3 +# define REP(f, t) ((f)*8 + (t)) +# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) + register sopno copy; + + if (p->error != 0) /* head off possible runaway recursion */ + return; + + assert(from <= to); + + switch (REP(MAP(from), MAP(to))) { + case REP(0, 0): /* must be user doing this */ + DROP(finish-start); /* drop the operand */ + break; + case REP(0, 1): /* as x{1,1}? */ + case REP(0, N): /* as x{1,n}? */ + case REP(0, INF): /* as x{1,}? */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); /* offset is wrong... */ + repeat(p, start+1, 1, to); + ASTERN(OOR1, start); + AHEAD(start); /* ... fix it */ + EMIT(OOR2, 0); + AHEAD(THERE()); + ASTERN(O_CH, THERETHERE()); + break; + case REP(1, 1): /* trivial case */ + /* done */ + break; + case REP(1, N): /* as x?x{1,n-1} */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); + ASTERN(OOR1, start); + AHEAD(start); + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + copy = dupl(p, start+1, finish+1); + assert(copy == finish+4); + repeat(p, copy, 1, to-1); + break; + case REP(1, INF): /* as x+ */ + INSERT(OPLUS_, start); + ASTERN(O_PLUS, start); + break; + case REP(N, N): /* as xx{m-1,n-1} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to-1); + break; + case REP(N, INF): /* as xx{n-1,INF} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to); + break; + default: /* "can't happen" */ + SETERROR(REG_ASSERT); /* just in case */ + break; + } +} + +/* + - seterr - set an error condition + == static int seterr(register struct parse *p, int e); + */ +static int /* useless but makes type checking happy */ +seterr(p, e) +register struct parse *p; +int e; +{ + if (p->error == 0) /* keep earliest error condition */ + p->error = e; + p->next = nuls; /* try to bring things to a halt */ + p->end = nuls; + return(0); /* make the return value well-defined */ +} + +/* + - allocset - allocate a set of characters for [] + == static cset *allocset(register struct parse *p); + */ +static cset * +allocset(p) +register struct parse *p; +{ + register int no = p->g->ncsets++; + register size_t nc; + register size_t nbytes; + register cset *cs; + register size_t css = (size_t)p->g->csetsize; + register int i; + + if (no >= p->ncsalloc) { /* need another column of space */ + p->ncsalloc += CHAR_BIT; + nc = p->ncsalloc; + assert(nc % CHAR_BIT == 0); + nbytes = nc / CHAR_BIT * css; + if (p->g->sets == NULL) + p->g->sets = (cset *)malloc(nc * sizeof(cset)); + else + p->g->sets = (cset *)realloc((char *)p->g->sets, + nc * sizeof(cset)); + if (p->g->setbits == NULL) + p->g->setbits = (uch *)malloc(nbytes); + else { + p->g->setbits = (uch *)realloc((char *)p->g->setbits, + nbytes); + /* xxx this isn't right if setbits is now NULL */ + for (i = 0; i < no; i++) + p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); + } + if (p->g->sets != NULL && p->g->setbits != NULL) + (void) memset((char *)p->g->setbits + (nbytes - css), + 0, css); + else { + no = 0; + SETERROR(REG_ESPACE); + /* caller's responsibility not to do set ops */ + } + } + + assert(p->g->sets != NULL); /* xxx */ + cs = &p->g->sets[no]; + cs->ptr = p->g->setbits + css*((no)/CHAR_BIT); + cs->mask = 1 << ((no) % CHAR_BIT); + cs->hash = 0; + cs->smultis = 0; + cs->multis = NULL; + + return(cs); +} + +/* + - freeset - free a now-unused set + == static void freeset(register struct parse *p, register cset *cs); + */ +static void +freeset(p, cs) +register struct parse *p; +register cset *cs; +{ + register int i; + register cset *top = &p->g->sets[p->g->ncsets]; + register size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + CHsub(cs, i); + if (cs == top-1) /* recover only the easy case */ + p->g->ncsets--; +} + +/* + - freezeset - final processing on a set of characters + == static int freezeset(register struct parse *p, register cset *cs); + * + * The main task here is merging identical sets. This is usually a waste + * of time (although the hash code minimizes the overhead), but can win + * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash + * is done using addition rather than xor -- all ASCII [aA] sets xor to + * the same value! + */ +static int /* set number */ +freezeset(p, cs) +register struct parse *p; +register cset *cs; +{ + register uch h = cs->hash; + register int i; + register cset *top = &p->g->sets[p->g->ncsets]; + register cset *cs2; + register size_t css = (size_t)p->g->csetsize; + + /* look for an earlier one which is the same */ + for (cs2 = &p->g->sets[0]; cs2 < top; cs2++) + if (cs2->hash == h && cs2 != cs) { + /* maybe */ + for (i = 0; i < css; i++) + if (!!CHIN(cs2, i) != !!CHIN(cs, i)) + break; /* no */ + if (i == css) + break; /* yes */ + } + + if (cs2 < top) { /* found one */ + freeset(p, cs); + cs = cs2; + } + + return((int)(cs - p->g->sets)); +} + +/* + - firstch - return first character in a set (which must have at least one) + == static int firstch(register struct parse *p, register cset *cs); + */ +static int /* character; there is no "none" value */ +firstch(p, cs) +register struct parse *p; +register cset *cs; +{ + register int i; + register size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + return((char)i); + assert(never); + return(0); /* arbitrary */ +} + +/* + - nch - number of characters in a set + == static int nch(register struct parse *p, register cset *cs); + */ +static int +nch(p, cs) +register struct parse *p; +register cset *cs; +{ + register int i; + register size_t css = (size_t)p->g->csetsize; + register int n = 0; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + n++; + return(n); +} + +/* + - mcadd - add a collating element to a cset + == static void mcadd(register struct parse *p, register cset *cs, \ + == register char *cp); + */ +static void +mcadd(p, cs, cp) +register struct parse *p; +register cset *cs; +register char *cp; +{ + register size_t oldend = cs->smultis; + + cs->smultis += strlen(cp) + 1; + if (cs->multis == NULL) + cs->multis = malloc(cs->smultis); + else + cs->multis = realloc(cs->multis, cs->smultis); + if (cs->multis == NULL) { + SETERROR(REG_ESPACE); + return; + } + + (void) strcpy(cs->multis + oldend - 1, cp); + cs->multis[cs->smultis - 1] = '\0'; +} + + +/* + - mcinvert - invert the list of collating elements in a cset + == static void mcinvert(register struct parse *p, register cset *cs); + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +static void +mcinvert(p, cs) +register struct parse *p; +register cset *cs; +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - mccase - add case counterparts of the list of collating elements in a cset + == static void mccase(register struct parse *p, register cset *cs); + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +static void +mccase(p, cs) +register struct parse *p; +register cset *cs; +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - isinsets - is this character in any sets? + == static int isinsets(register struct re_guts *g, int c); + */ +static int /* predicate */ +isinsets(g, c) +register struct re_guts *g; +int c; +{ + register uch *col; + register int i; + register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + register unsigned uc = (unsigned char)c; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc] != 0) + return(1); + return(0); +} + +/* + - samesets - are these two characters in exactly the same sets? + == static int samesets(register struct re_guts *g, int c1, int c2); + */ +static int /* predicate */ +samesets(g, c1, c2) +register struct re_guts *g; +int c1; +int c2; +{ + register uch *col; + register int i; + register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + register unsigned uc1 = (unsigned char)c1; + register unsigned uc2 = (unsigned char)c2; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc1] != col[uc2]) + return(0); + return(1); +} + +/* + - categorize - sort out character categories + == static void categorize(struct parse *p, register struct re_guts *g); + */ +static void +categorize(p, g) +struct parse *p; +register struct re_guts *g; +{ + register cat_t *cats = g->categories; + register int c; + register int c2; + register cat_t cat; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + for (c = CHAR_MIN; c <= CHAR_MAX; c++) + if (cats[c] == 0 && isinsets(g, c)) { + cat = g->ncategories++; + cats[c] = cat; + for (c2 = c+1; c2 <= CHAR_MAX; c2++) + if (cats[c2] == 0 && samesets(g, c, c2)) + cats[c2] = cat; + } +} + +/* + - dupl - emit a duplicate of a bunch of sops + == static sopno dupl(register struct parse *p, sopno start, sopno finish); + */ +static sopno /* start of duplicate */ +dupl(p, start, finish) +register struct parse *p; +sopno start; /* from here */ +sopno finish; /* to this less one */ +{ + register sopno ret = HERE(); + register sopno len = finish - start; + + assert(finish >= start); + if (len == 0) + return(ret); + enlarge(p, p->ssize + len); /* this many unexpected additions */ + assert(p->ssize >= p->slen + len); + (void) memcpy((char *)(p->strip + p->slen), + (char *)(p->strip + start), (size_t)len*sizeof(sop)); + p->slen += len; + return(ret); +} + +/* + - doemit - emit a strip operator + == static void doemit(register struct parse *p, sop op, size_t opnd); + * + * It might seem better to implement this as a macro with a function as + * hard-case backup, but it's just too big and messy unless there are + * some changes to the data structures. Maybe later. + */ +static void +doemit(p, op, opnd) +register struct parse *p; +sop op; +size_t opnd; +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* deal with oversize operands ("can't happen", more or less) */ + assert(opnd < 1<slen >= p->ssize) + enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */ + assert(p->slen < p->ssize); + + /* finally, it's all reduced to the easy case */ + p->strip[p->slen++] = SOP(op, opnd); +} + +/* + - doinsert - insert a sop into the strip + == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos); + */ +static void +doinsert(p, op, opnd, pos) +register struct parse *p; +sop op; +size_t opnd; +sopno pos; +{ + register sopno sn; + register sop s; + register int i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + sn = HERE(); + EMIT(op, opnd); /* do checks, ensure space */ + assert(HERE() == sn+1); + s = p->strip[sn]; + + /* adjust paren pointers */ + assert(pos > 0); + for (i = 1; i < NPAREN; i++) { + if (p->pbegin[i] >= pos) { + p->pbegin[i]++; + } + if (p->pend[i] >= pos) { + p->pend[i]++; + } + } + + memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos], + (HERE()-pos-1)*sizeof(sop)); + p->strip[pos] = s; +} + +/* + - dofwd - complete a forward reference + == static void dofwd(register struct parse *p, sopno pos, sop value); + */ +static void +dofwd(p, pos, value) +register struct parse *p; +register sopno pos; +sop value; +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + assert(value < 1<strip[pos] = OP(p->strip[pos]) | value; +} + +/* + - enlarge - enlarge the strip + == static void enlarge(register struct parse *p, sopno size); + */ +static void +enlarge(p, size) +register struct parse *p; +register sopno size; +{ + register sop *sp; + + if (p->ssize >= size) + return; + + sp = (sop *)realloc(p->strip, size*sizeof(sop)); + if (sp == NULL) { + SETERROR(REG_ESPACE); + return; + } + p->strip = sp; + p->ssize = size; +} + +/* + - stripsnug - compact the strip + == static void stripsnug(register struct parse *p, register struct re_guts *g); + */ +static void +stripsnug(p, g) +register struct parse *p; +register struct re_guts *g; +{ + g->nstates = p->slen; + g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop)); + if (g->strip == NULL) { + SETERROR(REG_ESPACE); + g->strip = p->strip; + } +} + +/* + - findmust - fill in must and mlen with longest mandatory literal string + == static void findmust(register struct parse *p, register struct re_guts *g); + * + * This algorithm could do fancy things like analyzing the operands of | + * for common subsequences. Someday. This code is simple and finds most + * of the interesting cases. + * + * Note that must and mlen got initialized during setup. + */ +static void +findmust(p, g) +struct parse *p; +register struct re_guts *g; +{ + register sop *scan; + sop *start = NULL; + register sop *newstart = NULL; + register sopno newlen; + register sop s; + register char *cp; + register sopno i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* find the longest OCHAR sequence in strip */ + newlen = 0; + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OCHAR: /* sequence member */ + if (newlen == 0) /* new sequence */ + newstart = scan - 1; + newlen++; + break; + case OPLUS_: /* things that don't break one */ + case OLPAREN: + case ORPAREN: + break; + case OQUEST_: /* things that must be skipped */ + case OCH_: + scan--; + do { + scan += OPND(s); + s = *scan; + /* assert() interferes w debug printouts */ + if (OP(s) != O_QUEST && OP(s) != O_CH && + OP(s) != OOR2) { + g->iflags |= BAD; + return; + } + } while (OP(s) != O_QUEST && OP(s) != O_CH); + /* fallthrough */ + default: /* things that break a sequence */ + if (newlen > g->mlen) { /* ends one */ + start = newstart; + g->mlen = newlen; + } + newlen = 0; + break; + } + } while (OP(s) != OEND); + + if (g->mlen == 0) /* there isn't one */ + return; + + /* turn it into a character string */ + g->must = malloc((size_t)g->mlen + 1); + if (g->must == NULL) { /* argh; just forget it */ + g->mlen = 0; + return; + } + cp = g->must; + scan = start; + for (i = g->mlen; i > 0; i--) { + while (OP(s = *scan++) != OCHAR) + continue; + assert(cp < g->must + g->mlen); + *cp++ = (char)OPND(s); + } + assert(cp == g->must + g->mlen); + *cp++ = '\0'; /* just on general principles */ +} + +/* + - pluscount - count + nesting + == static sopno pluscount(register struct parse *p, register struct re_guts *g); + */ +static sopno /* nesting depth */ +pluscount(p, g) +struct parse *p; +register struct re_guts *g; +{ + register sop *scan; + register sop s; + register sopno plusnest = 0; + register sopno maxnest = 0; + + if (p->error != 0) + return(0); /* there may not be an OEND */ + + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OPLUS_: + plusnest++; + break; + case O_PLUS: + if (plusnest > maxnest) + maxnest = plusnest; + plusnest--; + break; + } + } while (OP(s) != OEND); + if (plusnest != 0) + g->iflags |= BAD; + return(maxnest); +} diff --git a/APACHE_1_3b7/src/regex/regcomp.ih b/APACHE_1_3b7/src/regex/regcomp.ih new file mode 100644 index 0000000000..f0eeb5f02d --- /dev/null +++ b/APACHE_1_3b7/src/regex/regcomp.ih @@ -0,0 +1,48 @@ +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === regcomp.c === */ +static void p_ere(register struct parse *p, int stop); +static void p_ere_exp(register struct parse *p); +static void p_str(register struct parse *p); +static void p_bre(register struct parse *p, register int end1, register int end2); +static int p_simp_re(register struct parse *p, int starordinary); +static int p_count(register struct parse *p); +static void p_bracket(register struct parse *p); +static void p_b_term(register struct parse *p, register cset *cs); +static void p_b_cclass(register struct parse *p, register cset *cs); +static void p_b_eclass(register struct parse *p, register cset *cs); +static char p_b_symbol(register struct parse *p); +static char p_b_coll_elem(register struct parse *p, int endc); +static char othercase(int ch); +static void bothcases(register struct parse *p, int ch); +static void ordinary(register struct parse *p, register int ch); +static void nonnewline(register struct parse *p); +static void repeat(register struct parse *p, sopno start, int from, int to); +static int seterr(register struct parse *p, int e); +static cset *allocset(register struct parse *p); +static void freeset(register struct parse *p, register cset *cs); +static int freezeset(register struct parse *p, register cset *cs); +static int firstch(register struct parse *p, register cset *cs); +static int nch(register struct parse *p, register cset *cs); +static void mcadd(register struct parse *p, register cset *cs, register char *cp); +static void mcinvert(register struct parse *p, register cset *cs); +static void mccase(register struct parse *p, register cset *cs); +static int isinsets(register struct re_guts *g, int c); +static int samesets(register struct re_guts *g, int c1, int c2); +static void categorize(struct parse *p, register struct re_guts *g); +static sopno dupl(register struct parse *p, sopno start, sopno finish); +static void doemit(register struct parse *p, sop op, size_t opnd); +static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos); +static void dofwd(register struct parse *p, sopno pos, sop value); +static void enlarge(register struct parse *p, sopno size); +static void stripsnug(register struct parse *p, register struct re_guts *g); +static void findmust(register struct parse *p, register struct re_guts *g); +static sopno pluscount(register struct parse *p, register struct re_guts *g); + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ diff --git a/APACHE_1_3b7/src/regex/regerror.c b/APACHE_1_3b7/src/regex/regerror.c new file mode 100644 index 0000000000..d056f38647 --- /dev/null +++ b/APACHE_1_3b7/src/regex/regerror.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include + +#include "hsregex.h" +#include "utils.h" +#include "regerror.ih" + +/* + = #define REG_NOMATCH 1 + = #define REG_BADPAT 2 + = #define REG_ECOLLATE 3 + = #define REG_ECTYPE 4 + = #define REG_EESCAPE 5 + = #define REG_ESUBREG 6 + = #define REG_EBRACK 7 + = #define REG_EPAREN 8 + = #define REG_EBRACE 9 + = #define REG_BADBR 10 + = #define REG_ERANGE 11 + = #define REG_ESPACE 12 + = #define REG_BADRPT 13 + = #define REG_EMPTY 14 + = #define REG_ASSERT 15 + = #define REG_INVARG 16 + = #define REG_ATOI 255 // convert name to number (!) + = #define REG_ITOA 0400 // convert number to name (!) + */ +static struct rerr { + int code; + char *name; + char *explain; +} rerrs[] = { + { REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match" }, + { REG_BADPAT, "REG_BADPAT", "invalid regular expression" }, + { REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element" }, + { REG_ECTYPE, "REG_ECTYPE", "invalid character class" }, + { REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)" }, + { REG_ESUBREG, "REG_ESUBREG", "invalid backreference number" }, + { REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced" }, + { REG_EPAREN, "REG_EPAREN", "parentheses not balanced" }, + { REG_EBRACE, "REG_EBRACE", "braces not balanced" }, + { REG_BADBR, "REG_BADBR", "invalid repetition count(s)" }, + { REG_ERANGE, "REG_ERANGE", "invalid character range" }, + { REG_ESPACE, "REG_ESPACE", "out of memory" }, + { REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid" }, + { REG_EMPTY, "REG_EMPTY", "empty (sub)expression" }, + { REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug" }, + { REG_INVARG, "REG_INVARG", "invalid argument to regex routine" }, + { 0, "", "*** unknown regexp error code ***" } +}; + +/* + - regerror - the interface to error numbers + = API_EXPORT(size_t) regerror(int, const regex_t *, char *, size_t); + */ +/* ARGSUSED */ +API_EXPORT(size_t) +regerror(errcode, preg, errbuf, errbuf_size) +int errcode; +const regex_t *preg; +char *errbuf; +size_t errbuf_size; +{ + register struct rerr *r; + register size_t len; + register int target = errcode &~ REG_ITOA; + register char *s; + char convbuf[50]; + + if (errcode == REG_ATOI) + s = regatoi(preg, convbuf); + else { + for (r = rerrs; r->code != 0; r++) + if (r->code == target) + break; + + if (errcode®_ITOA) { + if (r->code != 0) + (void) strcpy(convbuf, r->name); + else + sprintf(convbuf, "REG_0x%x", target); + assert(strlen(convbuf) < sizeof(convbuf)); + s = convbuf; + } else + s = r->explain; + } + + len = strlen(s) + 1; + if (errbuf_size > 0) { + if (errbuf_size > len) + (void) strcpy(errbuf, s); + else { + (void) strncpy(errbuf, s, errbuf_size-1); + errbuf[errbuf_size-1] = '\0'; + } + } + + return(len); +} + +/* + - regatoi - internal routine to implement REG_ATOI + == static char *regatoi(const regex_t *preg, char *localbuf); + */ +static char * +regatoi(preg, localbuf) +const regex_t *preg; +char *localbuf; +{ + register struct rerr *r; + + for (r = rerrs; r->code != 0; r++) + if (strcmp(r->name, preg->re_endp) == 0) + break; + if (r->code == 0) + return("0"); + + sprintf(localbuf, "%d", r->code); + return(localbuf); +} diff --git a/APACHE_1_3b7/src/regex/regerror.ih b/APACHE_1_3b7/src/regex/regerror.ih new file mode 100644 index 0000000000..2cb668c24f --- /dev/null +++ b/APACHE_1_3b7/src/regex/regerror.ih @@ -0,0 +1,12 @@ +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === regerror.c === */ +static char *regatoi(const regex_t *preg, char *localbuf); + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ diff --git a/APACHE_1_3b7/src/regex/regex.3 b/APACHE_1_3b7/src/regex/regex.3 new file mode 100644 index 0000000000..100c8a7f71 --- /dev/null +++ b/APACHE_1_3b7/src/regex/regex.3 @@ -0,0 +1,502 @@ +.TH REGEX 3 "17 May 1993" +.BY "Henry Spencer" +.de ZR +.\" one other place knows this name: the SEE ALSO section +.IR regex (7) \\$1 +.. +.SH NAME +regcomp, regexec, regerror, regfree \- regular-expression library +.SH SYNOPSIS +.ft B +.\".na +#include +.br +#include +.HP 10 +int regcomp(regex_t\ *preg, const\ char\ *pattern, int\ cflags); +.HP +int\ regexec(const\ regex_t\ *preg, const\ char\ *string, +size_t\ nmatch, regmatch_t\ pmatch[], int\ eflags); +.HP +size_t\ regerror(int\ errcode, const\ regex_t\ *preg, +char\ *errbuf, size_t\ errbuf_size); +.HP +void\ regfree(regex_t\ *preg); +.\".ad +.ft +.SH DESCRIPTION +These routines implement POSIX 1003.2 regular expressions (``RE''s); +see +.ZR . +.I Regcomp +compiles an RE written as a string into an internal form, +.I regexec +matches that internal form against a string and reports results, +.I regerror +transforms error codes from either into human-readable messages, +and +.I regfree +frees any dynamically-allocated storage used by the internal form +of an RE. +.PP +The header +.I +declares two structure types, +.I regex_t +and +.IR regmatch_t , +the former for compiled internal forms and the latter for match reporting. +It also declares the four functions, +a type +.IR regoff_t , +and a number of constants with names starting with ``REG_''. +.PP +.I Regcomp +compiles the regular expression contained in the +.I pattern +string, +subject to the flags in +.IR cflags , +and places the results in the +.I regex_t +structure pointed to by +.IR preg . +.I Cflags +is the bitwise OR of zero or more of the following flags: +.IP REG_EXTENDED \w'REG_EXTENDED'u+2n +Compile modern (``extended'') REs, +rather than the obsolete (``basic'') REs that +are the default. +.IP REG_BASIC +This is a synonym for 0, +provided as a counterpart to REG_EXTENDED to improve readability. +.IP REG_NOSPEC +Compile with recognition of all special characters turned off. +All characters are thus considered ordinary, +so the ``RE'' is a literal string. +This is an extension, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +REG_EXTENDED and REG_NOSPEC may not be used +in the same call to +.IR regcomp . +.IP REG_ICASE +Compile for matching that ignores upper/lower case distinctions. +See +.ZR . +.IP REG_NOSUB +Compile for matching that need only report success or failure, +not what was matched. +.IP REG_NEWLINE +Compile for newline-sensitive matching. +By default, newline is a completely ordinary character with no special +meaning in either REs or strings. +With this flag, +`[^' bracket expressions and `.' never match newline, +a `^' anchor matches the null string after any newline in the string +in addition to its normal function, +and the `$' anchor matches the null string before any newline in the +string in addition to its normal function. +.IP REG_PEND +The regular expression ends, +not at the first NUL, +but just before the character pointed to by the +.I re_endp +member of the structure pointed to by +.IR preg . +The +.I re_endp +member is of type +.IR const\ char\ * . +This flag permits inclusion of NULs in the RE; +they are considered ordinary characters. +This is an extension, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +.PP +When successful, +.I regcomp +returns 0 and fills in the structure pointed to by +.IR preg . +One member of that structure +(other than +.IR re_endp ) +is publicized: +.IR re_nsub , +of type +.IR size_t , +contains the number of parenthesized subexpressions within the RE +(except that the value of this member is undefined if the +REG_NOSUB flag was used). +If +.I regcomp +fails, it returns a non-zero error code; +see DIAGNOSTICS. +.PP +.I Regexec +matches the compiled RE pointed to by +.I preg +against the +.IR string , +subject to the flags in +.IR eflags , +and reports results using +.IR nmatch , +.IR pmatch , +and the returned value. +The RE must have been compiled by a previous invocation of +.IR regcomp . +The compiled form is not altered during execution of +.IR regexec , +so a single compiled RE can be used simultaneously by multiple threads. +.PP +By default, +the NUL-terminated string pointed to by +.I string +is considered to be the text of an entire line, minus any terminating +newline. +The +.I eflags +argument is the bitwise OR of zero or more of the following flags: +.IP REG_NOTBOL \w'REG_STARTEND'u+2n +The first character of +the string +is not the beginning of a line, so the `^' anchor should not match before it. +This does not affect the behavior of newlines under REG_NEWLINE. +.IP REG_NOTEOL +The NUL terminating +the string +does not end a line, so the `$' anchor should not match before it. +This does not affect the behavior of newlines under REG_NEWLINE. +.IP REG_STARTEND +The string is considered to start at +\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_so\fR +and to have a terminating NUL located at +\fIstring\fR\ + \fIpmatch\fR[0].\fIrm_eo\fR +(there need not actually be a NUL at that location), +regardless of the value of +.IR nmatch . +See below for the definition of +.IR pmatch +and +.IR nmatch . +This is an extension, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +Note that a non-zero \fIrm_so\fR does not imply REG_NOTBOL; +REG_STARTEND affects only the location of the string, +not how it is matched. +.PP +See +.ZR +for a discussion of what is matched in situations where an RE or a +portion thereof could match any of several substrings of +.IR string . +.PP +Normally, +.I regexec +returns 0 for success and the non-zero code REG_NOMATCH for failure. +Other non-zero error codes may be returned in exceptional situations; +see DIAGNOSTICS. +.PP +If REG_NOSUB was specified in the compilation of the RE, +or if +.I nmatch +is 0, +.I regexec +ignores the +.I pmatch +argument (but see below for the case where REG_STARTEND is specified). +Otherwise, +.I pmatch +points to an array of +.I nmatch +structures of type +.IR regmatch_t . +Such a structure has at least the members +.I rm_so +and +.IR rm_eo , +both of type +.I regoff_t +(a signed arithmetic type at least as large as an +.I off_t +and a +.IR ssize_t ), +containing respectively the offset of the first character of a substring +and the offset of the first character after the end of the substring. +Offsets are measured from the beginning of the +.I string +argument given to +.IR regexec . +An empty substring is denoted by equal offsets, +both indicating the character following the empty substring. +.PP +The 0th member of the +.I pmatch +array is filled in to indicate what substring of +.I string +was matched by the entire RE. +Remaining members report what substring was matched by parenthesized +subexpressions within the RE; +member +.I i +reports subexpression +.IR i , +with subexpressions counted (starting at 1) by the order of their opening +parentheses in the RE, left to right. +Unused entries in the array\(emcorresponding either to subexpressions that +did not participate in the match at all, or to subexpressions that do not +exist in the RE (that is, \fIi\fR\ > \fIpreg\fR\->\fIre_nsub\fR)\(emhave both +.I rm_so +and +.I rm_eo +set to \-1. +If a subexpression participated in the match several times, +the reported substring is the last one it matched. +(Note, as an example in particular, that when the RE `(b*)+' matches `bbb', +the parenthesized subexpression matches each of the three `b's and then +an infinite number of empty strings following the last `b', +so the reported substring is one of the empties.) +.PP +If REG_STARTEND is specified, +.I pmatch +must point to at least one +.I regmatch_t +(even if +.I nmatch +is 0 or REG_NOSUB was specified), +to hold the input offsets for REG_STARTEND. +Use for output is still entirely controlled by +.IR nmatch ; +if +.I nmatch +is 0 or REG_NOSUB was specified, +the value of +.IR pmatch [0] +will not be changed by a successful +.IR regexec . +.PP +.I Regerror +maps a non-zero +.I errcode +from either +.I regcomp +or +.I regexec +to a human-readable, printable message. +If +.I preg +is non-NULL, +the error code should have arisen from use of +the +.I regex_t +pointed to by +.IR preg , +and if the error code came from +.IR regcomp , +it should have been the result from the most recent +.I regcomp +using that +.IR regex_t . +.RI ( Regerror +may be able to supply a more detailed message using information +from the +.IR regex_t .) +.I Regerror +places the NUL-terminated message into the buffer pointed to by +.IR errbuf , +limiting the length (including the NUL) to at most +.I errbuf_size +bytes. +If the whole message won't fit, +as much of it as will fit before the terminating NUL is supplied. +In any case, +the returned value is the size of buffer needed to hold the whole +message (including terminating NUL). +If +.I errbuf_size +is 0, +.I errbuf +is ignored but the return value is still correct. +.PP +If the +.I errcode +given to +.I regerror +is first ORed with REG_ITOA, +the ``message'' that results is the printable name of the error code, +e.g. ``REG_NOMATCH'', +rather than an explanation thereof. +If +.I errcode +is REG_ATOI, +then +.I preg +shall be non-NULL and the +.I re_endp +member of the structure it points to +must point to the printable name of an error code; +in this case, the result in +.I errbuf +is the decimal digits of +the numeric value of the error code +(0 if the name is not recognized). +REG_ITOA and REG_ATOI are intended primarily as debugging facilities; +they are extensions, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +Be warned also that they are considered experimental and changes are possible. +.PP +.I Regfree +frees any dynamically-allocated storage associated with the compiled RE +pointed to by +.IR preg . +The remaining +.I regex_t +is no longer a valid compiled RE +and the effect of supplying it to +.I regexec +or +.I regerror +is undefined. +.PP +None of these functions references global variables except for tables +of constants; +all are safe for use from multiple threads if the arguments are safe. +.SH IMPLEMENTATION CHOICES +There are a number of decisions that 1003.2 leaves up to the implementor, +either by explicitly saying ``undefined'' or by virtue of them being +forbidden by the RE grammar. +This implementation treats them as follows. +.PP +See +.ZR +for a discussion of the definition of case-independent matching. +.PP +There is no particular limit on the length of REs, +except insofar as memory is limited. +Memory usage is approximately linear in RE size, and largely insensitive +to RE complexity, except for bounded repetitions. +See BUGS for one short RE using them +that will run almost any system out of memory. +.PP +A backslashed character other than one specifically given a magic meaning +by 1003.2 (such magic meanings occur only in obsolete [``basic''] REs) +is taken as an ordinary character. +.PP +Any unmatched [ is a REG_EBRACK error. +.PP +Equivalence classes cannot begin or end bracket-expression ranges. +The endpoint of one range cannot begin another. +.PP +RE_DUP_MAX, the limit on repetition counts in bounded repetitions, is 255. +.PP +A repetition operator (?, *, +, or bounds) cannot follow another +repetition operator. +A repetition operator cannot begin an expression or subexpression +or follow `^' or `|'. +.PP +`|' cannot appear first or last in a (sub)expression or after another `|', +i.e. an operand of `|' cannot be an empty subexpression. +An empty parenthesized subexpression, `()', is legal and matches an +empty (sub)string. +An empty string is not a legal RE. +.PP +A `{' followed by a digit is considered the beginning of bounds for a +bounded repetition, which must then follow the syntax for bounds. +A `{' \fInot\fR followed by a digit is considered an ordinary character. +.PP +`^' and `$' beginning and ending subexpressions in obsolete (``basic'') +REs are anchors, not ordinary characters. +.SH SEE ALSO +grep(1), regex(7) +.PP +POSIX 1003.2, sections 2.8 (Regular Expression Notation) +and +B.5 (C Binding for Regular Expression Matching). +.SH DIAGNOSTICS +Non-zero error codes from +.I regcomp +and +.I regexec +include the following: +.PP +.nf +.ta \w'REG_ECOLLATE'u+3n +REG_NOMATCH regexec() failed to match +REG_BADPAT invalid regular expression +REG_ECOLLATE invalid collating element +REG_ECTYPE invalid character class +REG_EESCAPE \e applied to unescapable character +REG_ESUBREG invalid backreference number +REG_EBRACK brackets [ ] not balanced +REG_EPAREN parentheses ( ) not balanced +REG_EBRACE braces { } not balanced +REG_BADBR invalid repetition count(s) in { } +REG_ERANGE invalid character range in [ ] +REG_ESPACE ran out of memory +REG_BADRPT ?, *, or + operand invalid +REG_EMPTY empty (sub)expression +REG_ASSERT ``can't happen''\(emyou found a bug +REG_INVARG invalid argument, e.g. negative-length string +.fi +.SH HISTORY +Written by Henry Spencer at University of Toronto, +henry@zoo.toronto.edu. +.SH BUGS +This is an alpha release with known defects. +Please report problems. +.PP +There is one known functionality bug. +The implementation of internationalization is incomplete: +the locale is always assumed to be the default one of 1003.2, +and only the collating elements etc. of that locale are available. +.PP +The back-reference code is subtle and doubts linger about its correctness +in complex cases. +.PP +.I Regexec +performance is poor. +This will improve with later releases. +.I Nmatch +exceeding 0 is expensive; +.I nmatch +exceeding 1 is worse. +.I Regexec +is largely insensitive to RE complexity \fIexcept\fR that back +references are massively expensive. +RE length does matter; in particular, there is a strong speed bonus +for keeping RE length under about 30 characters, +with most special characters counting roughly double. +.PP +.I Regcomp +implements bounded repetitions by macro expansion, +which is costly in time and space if counts are large +or bounded repetitions are nested. +An RE like, say, +`((((a{1,100}){1,100}){1,100}){1,100}){1,100}' +will (eventually) run almost any existing machine out of swap space. +.PP +There are suspected problems with response to obscure error conditions. +Notably, +certain kinds of internal overflow, +produced only by truly enormous REs or by multiply nested bounded repetitions, +are probably not handled well. +.PP +Due to a mistake in 1003.2, things like `a)b' are legal REs because `)' is +a special character only in the presence of a previous unmatched `('. +This can't be fixed until the spec is fixed. +.PP +The standard's definition of back references is vague. +For example, does +`a\e(\e(b\e)*\e2\e)*d' match `abbbd'? +Until the standard is clarified, +behavior in such cases should not be relied on. +.PP +The implementation of word-boundary matching is a bit of a kludge, +and bugs may lurk in combinations of word-boundary matching and anchoring. diff --git a/APACHE_1_3b7/src/regex/regex.7 b/APACHE_1_3b7/src/regex/regex.7 new file mode 100644 index 0000000000..d89012bda1 --- /dev/null +++ b/APACHE_1_3b7/src/regex/regex.7 @@ -0,0 +1,233 @@ +.TH REGEX 7 "7 Feb 1994" +.BY "Henry Spencer" +.SH NAME +regex \- POSIX 1003.2 regular expressions +.SH DESCRIPTION +Regular expressions (``RE''s), +as defined in POSIX 1003.2, come in two forms: +modern REs (roughly those of +.IR egrep ; +1003.2 calls these ``extended'' REs) +and obsolete REs (roughly those of +.IR ed ; +1003.2 ``basic'' REs). +Obsolete REs mostly exist for backward compatibility in some old programs; +they will be discussed at the end. +1003.2 leaves some aspects of RE syntax and semantics open; +`\(dg' marks decisions on these aspects that +may not be fully portable to other 1003.2 implementations. +.PP +A (modern) RE is one\(dg or more non-empty\(dg \fIbranches\fR, +separated by `|'. +It matches anything that matches one of the branches. +.PP +A branch is one\(dg or more \fIpieces\fR, concatenated. +It matches a match for the first, followed by a match for the second, etc. +.PP +A piece is an \fIatom\fR possibly followed +by a single\(dg `*', `+', `?', or \fIbound\fR. +An atom followed by `*' matches a sequence of 0 or more matches of the atom. +An atom followed by `+' matches a sequence of 1 or more matches of the atom. +An atom followed by `?' matches a sequence of 0 or 1 matches of the atom. +.PP +A \fIbound\fR is `{' followed by an unsigned decimal integer, +possibly followed by `,' +possibly followed by another unsigned decimal integer, +always followed by `}'. +The integers must lie between 0 and RE_DUP_MAX (255\(dg) inclusive, +and if there are two of them, the first may not exceed the second. +An atom followed by a bound containing one integer \fIi\fR +and no comma matches +a sequence of exactly \fIi\fR matches of the atom. +An atom followed by a bound +containing one integer \fIi\fR and a comma matches +a sequence of \fIi\fR or more matches of the atom. +An atom followed by a bound +containing two integers \fIi\fR and \fIj\fR matches +a sequence of \fIi\fR through \fIj\fR (inclusive) matches of the atom. +.PP +An atom is a regular expression enclosed in `()' (matching a match for the +regular expression), +an empty set of `()' (matching the null string)\(dg, +a \fIbracket expression\fR (see below), `.' +(matching any single character), `^' (matching the null string at the +beginning of a line), `$' (matching the null string at the +end of a line), a `\e' followed by one of the characters +`^.[$()|*+?{\e' +(matching that character taken as an ordinary character), +a `\e' followed by any other character\(dg +(matching that character taken as an ordinary character, +as if the `\e' had not been present\(dg), +or a single character with no other significance (matching that character). +A `{' followed by a character other than a digit is an ordinary +character, not the beginning of a bound\(dg. +It is illegal to end an RE with `\e'. +.PP +A \fIbracket expression\fR is a list of characters enclosed in `[]'. +It normally matches any single character from the list (but see below). +If the list begins with `^', +it matches any single character +(but see below) \fInot\fR from the rest of the list. +If two characters in the list are separated by `\-', this is shorthand +for the full \fIrange\fR of characters between those two (inclusive) in the +collating sequence, +e.g. `[0-9]' in ASCII matches any decimal digit. +It is illegal\(dg for two ranges to share an +endpoint, e.g. `a-c-e'. +Ranges are very collating-sequence-dependent, +and portable programs should avoid relying on them. +.PP +To include a literal `]' in the list, make it the first character +(following a possible `^'). +To include a literal `\-', make it the first or last character, +or the second endpoint of a range. +To use a literal `\-' as the first endpoint of a range, +enclose it in `[.' and `.]' to make it a collating element (see below). +With the exception of these and some combinations using `[' (see next +paragraphs), all other special characters, including `\e', lose their +special significance within a bracket expression. +.PP +Within a bracket expression, a collating element (a character, +a multi-character sequence that collates as if it were a single character, +or a collating-sequence name for either) +enclosed in `[.' and `.]' stands for the +sequence of characters of that collating element. +The sequence is a single element of the bracket expression's list. +A bracket expression containing a multi-character collating element +can thus match more than one character, +e.g. if the collating sequence includes a `ch' collating element, +then the RE `[[.ch.]]*c' matches the first five characters +of `chchcc'. +.PP +Within a bracket expression, a collating element enclosed in `[=' and +`=]' is an equivalence class, standing for the sequences of characters +of all collating elements equivalent to that one, including itself. +(If there are no other equivalent collating elements, +the treatment is as if the enclosing delimiters were `[.' and `.]'.) +For example, if o and \o'o^' are the members of an equivalence class, +then `[[=o=]]', `[[=\o'o^'=]]', and `[o\o'o^']' are all synonymous. +An equivalence class may not\(dg be an endpoint +of a range. +.PP +Within a bracket expression, the name of a \fIcharacter class\fR enclosed +in `[:' and `:]' stands for the list of all characters belonging to that +class. +Standard character class names are: +.PP +.RS +.nf +.ta 3c 6c 9c +alnum digit punct +alpha graph space +blank lower upper +cntrl print xdigit +.fi +.RE +.PP +These stand for the character classes defined in +.IR ctype (3). +A locale may provide others. +A character class may not be used as an endpoint of a range. +.PP +There are two special cases\(dg of bracket expressions: +the bracket expressions `[[:<:]]' and `[[:>:]]' match the null string at +the beginning and end of a word respectively. +A word is defined as a sequence of +word characters +which is neither preceded nor followed by +word characters. +A word character is an +.I alnum +character (as defined by +.IR ctype (3)) +or an underscore. +This is an extension, +compatible with but not specified by POSIX 1003.2, +and should be used with +caution in software intended to be portable to other systems. +.PP +In the event that an RE could match more than one substring of a given +string, +the RE matches the one starting earliest in the string. +If the RE could match more than one substring starting at that point, +it matches the longest. +Subexpressions also match the longest possible substrings, subject to +the constraint that the whole match be as long as possible, +with subexpressions starting earlier in the RE taking priority over +ones starting later. +Note that higher-level subexpressions thus take priority over +their lower-level component subexpressions. +.PP +Match lengths are measured in characters, not collating elements. +A null string is considered longer than no match at all. +For example, +`bb*' matches the three middle characters of `abbbc', +`(wee|week)(knights|nights)' matches all ten characters of `weeknights', +when `(.*).*' is matched against `abc' the parenthesized subexpression +matches all three characters, and +when `(a*)*' is matched against `bc' both the whole RE and the parenthesized +subexpression match the null string. +.PP +If case-independent matching is specified, +the effect is much as if all case distinctions had vanished from the +alphabet. +When an alphabetic that exists in multiple cases appears as an +ordinary character outside a bracket expression, it is effectively +transformed into a bracket expression containing both cases, +e.g. `x' becomes `[xX]'. +When it appears inside a bracket expression, all case counterparts +of it are added to the bracket expression, so that (e.g.) `[x]' +becomes `[xX]' and `[^x]' becomes `[^xX]'. +.PP +No particular limit is imposed on the length of REs\(dg. +Programs intended to be portable should not employ REs longer +than 256 bytes, +as an implementation can refuse to accept such REs and remain +POSIX-compliant. +.PP +Obsolete (``basic'') regular expressions differ in several respects. +`|', `+', and `?' are ordinary characters and there is no equivalent +for their functionality. +The delimiters for bounds are `\e{' and `\e}', +with `{' and `}' by themselves ordinary characters. +The parentheses for nested subexpressions are `\e(' and `\e)', +with `(' and `)' by themselves ordinary characters. +`^' is an ordinary character except at the beginning of the +RE or\(dg the beginning of a parenthesized subexpression, +`$' is an ordinary character except at the end of the +RE or\(dg the end of a parenthesized subexpression, +and `*' is an ordinary character if it appears at the beginning of the +RE or the beginning of a parenthesized subexpression +(after a possible leading `^'). +Finally, there is one new type of atom, a \fIback reference\fR: +`\e' followed by a non-zero decimal digit \fId\fR +matches the same sequence of characters +matched by the \fId\fRth parenthesized subexpression +(numbering subexpressions by the positions of their opening parentheses, +left to right), +so that (e.g.) `\e([bc]\e)\e1' matches `bb' or `cc' but not `bc'. +.SH SEE ALSO +regex(3) +.PP +POSIX 1003.2, section 2.8 (Regular Expression Notation). +.SH BUGS +Having two kinds of REs is a botch. +.PP +The current 1003.2 spec says that `)' is an ordinary character in +the absence of an unmatched `('; +this was an unintentional result of a wording error, +and change is likely. +Avoid relying on it. +.PP +Back references are a dreadful botch, +posing major problems for efficient implementations. +They are also somewhat vaguely defined +(does +`a\e(\e(b\e)*\e2\e)*d' match `abbbd'?). +Avoid using them. +.PP +1003.2's specification of case-independent matching is vague. +The ``one case implies all cases'' definition given above +is current consensus among implementors as to the right interpretation. +.PP +The syntax for word boundaries is incredibly ugly. diff --git a/APACHE_1_3b7/src/regex/regex.dsp b/APACHE_1_3b7/src/regex/regex.dsp new file mode 100644 index 0000000000..60dd109075 --- /dev/null +++ b/APACHE_1_3b7/src/regex/regex.dsp @@ -0,0 +1,114 @@ +# Microsoft Developer Studio Project File - Name="regex" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=regex - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "regex.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "regex.mak" CFG="regex - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "regex - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "regex - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "regex - 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 "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "regex - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "regex___" +# PROP BASE Intermediate_Dir "regex___" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "regex - Win32 Release" +# Name "regex - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "*.c" +# Begin Source File + +SOURCE=.\regcomp.c +# End Source File +# Begin Source File + +SOURCE=.\regerror.c +# End Source File +# Begin Source File + +SOURCE=.\regexec.c +# End Source File +# Begin Source File + +SOURCE=.\regfree.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "*.h" +# Begin Source File + +SOURCE=.\cclass.h +# End Source File +# Begin Source File + +SOURCE=.\cname.h +# End Source File +# Begin Source File + +SOURCE=.\regex2.h +# End Source File +# End Group +# End Target +# End Project diff --git a/APACHE_1_3b7/src/regex/regex.mak b/APACHE_1_3b7/src/regex/regex.mak new file mode 100644 index 0000000000..1484294ea4 --- /dev/null +++ b/APACHE_1_3b7/src/regex/regex.mak @@ -0,0 +1,266 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on regex.dsp +!IF "$(CFG)" == "" +CFG=regex - Win32 Debug +!MESSAGE No configuration specified. Defaulting to regex - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "regex - Win32 Release" && "$(CFG)" != "regex - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "regex.mak" CFG="regex - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "regex - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "regex - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe + +!IF "$(CFG)" == "regex - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\regex.lib" + +!ELSE + +ALL : "$(OUTDIR)\regex.lib" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\regcomp.obj" + -@erase "$(INTDIR)\regerror.obj" + -@erase "$(INTDIR)\regexec.obj" + -@erase "$(INTDIR)\regfree.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\regex.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D\ + "_WINDOWS" /Fp"$(INTDIR)\regex.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\ + /c +CPP_OBJS=.\Release/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\regex.bsc" +BSC32_SBRS= \ + +LIB32=link.exe -lib +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\regex.lib" +LIB32_OBJS= \ + "$(INTDIR)\regcomp.obj" \ + "$(INTDIR)\regerror.obj" \ + "$(INTDIR)\regexec.obj" \ + "$(INTDIR)\regfree.obj" + +"$(OUTDIR)\regex.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) +<< + +!ELSEIF "$(CFG)" == "regex - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\regex.lib" + +!ELSE + +ALL : "$(OUTDIR)\regex.lib" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\regcomp.obj" + -@erase "$(INTDIR)\regerror.obj" + -@erase "$(INTDIR)\regexec.obj" + -@erase "$(INTDIR)\regfree.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\regex.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /GX /Z7 /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D\ + "_WINDOWS" /Fp"$(INTDIR)\regex.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\ + /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\regex.bsc" +BSC32_SBRS= \ + +LIB32=link.exe -lib +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\regex.lib" +LIB32_OBJS= \ + "$(INTDIR)\regcomp.obj" \ + "$(INTDIR)\regerror.obj" \ + "$(INTDIR)\regexec.obj" \ + "$(INTDIR)\regfree.obj" + +"$(OUTDIR)\regex.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_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) $< +<< + + +!IF "$(CFG)" == "regex - Win32 Release" || "$(CFG)" == "regex - Win32 Debug" +SOURCE=.\regcomp.c + +!IF "$(CFG)" == "regex - Win32 Release" + +DEP_CPP_REGCO=\ + "..\include\hsregex.h"\ + ".\cclass.h"\ + ".\cname.h"\ + ".\regcomp.ih"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regcomp.obj" : $(SOURCE) $(DEP_CPP_REGCO) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "regex - Win32 Debug" + +DEP_CPP_REGCO=\ + "..\include\hsregex.h"\ + ".\cclass.h"\ + ".\cname.h"\ + ".\regcomp.ih"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regcomp.obj" : $(SOURCE) $(DEP_CPP_REGCO) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\regerror.c + +!IF "$(CFG)" == "regex - Win32 Release" + +DEP_CPP_REGER=\ + "..\include\hsregex.h"\ + ".\regerror.ih"\ + ".\utils.h"\ + + +"$(INTDIR)\regerror.obj" : $(SOURCE) $(DEP_CPP_REGER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "regex - Win32 Debug" + +DEP_CPP_REGER=\ + "..\include\hsregex.h"\ + ".\regerror.ih"\ + ".\utils.h"\ + + +"$(INTDIR)\regerror.obj" : $(SOURCE) $(DEP_CPP_REGER) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\regexec.c + +!IF "$(CFG)" == "regex - Win32 Release" + +DEP_CPP_REGEX=\ + "..\include\hsregex.h"\ + ".\engine.c"\ + ".\engine.ih"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regexec.obj" : $(SOURCE) $(DEP_CPP_REGEX) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "regex - Win32 Debug" + +DEP_CPP_REGEX=\ + "..\include\hsregex.h"\ + ".\engine.c"\ + ".\engine.ih"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regexec.obj" : $(SOURCE) $(DEP_CPP_REGEX) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\regfree.c +DEP_CPP_REGFR=\ + "..\include\hsregex.h"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regfree.obj" : $(SOURCE) $(DEP_CPP_REGFR) "$(INTDIR)" + + + +!ENDIF + diff --git a/APACHE_1_3b7/src/regex/regex2.h b/APACHE_1_3b7/src/regex/regex2.h new file mode 100644 index 0000000000..3e8c0d65c4 --- /dev/null +++ b/APACHE_1_3b7/src/regex/regex2.h @@ -0,0 +1,138 @@ +/* + * First, the stuff that ends up in the outside-world include file + = #ifdef WIN32 + = #define API_EXPORT(type) __declspec(dllexport) type __stdcall + = #else + = #define API_EXPORT(type) type + = #endif + = + = typedef off_t regoff_t; + = typedef struct { + = int re_magic; + = size_t re_nsub; // number of parenthesized subexpressions + = const char *re_endp; // end pointer for REG_PEND + = struct re_guts *re_g; // none of your business :-) + = } regex_t; + = typedef struct { + = regoff_t rm_so; // start of match + = regoff_t rm_eo; // end of match + = } regmatch_t; + */ +/* + * internals of regex_t + */ +#define MAGIC1 ((('r'^0200)<<8) | 'e') + +/* + * The internal representation is a *strip*, a sequence of + * operators ending with an endmarker. (Some terminology etc. is a + * historical relic of earlier versions which used multiple strips.) + * Certain oddities in the representation are there to permit running + * the machinery backwards; in particular, any deviation from sequential + * flow must be marked at both its source and its destination. Some + * fine points: + * + * - OPLUS_ and O_PLUS are *inside* the loop they create. + * - OQUEST_ and O_QUEST are *outside* the bypass they create. + * - OCH_ and O_CH are *outside* the multi-way branch they create, while + * OOR1 and OOR2 are respectively the end and the beginning of one of + * the branches. Note that there is an implicit OOR2 following OCH_ + * and an implicit OOR1 preceding O_CH. + * + * In state representations, an operator's bit is on to signify a state + * immediately *preceding* "execution" of that operator. + */ +typedef unsigned long sop; /* strip operator */ +typedef long sopno; +#define OPRMASK 0xf8000000 +#define OPDMASK 0x07ffffff +#define OPSHIFT ((unsigned)27) +#define OP(n) ((n)&OPRMASK) +#define OPND(n) ((n)&OPDMASK) +#define SOP(op, opnd) ((op)|(opnd)) +/* operators meaning operand */ +/* (back, fwd are offsets) */ +#define OEND (1< uch [csetsize] */ + uch mask; /* bit within array */ + uch hash; /* hash code */ + size_t smultis; + char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */ +} cset; +/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */ +#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c)) +#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c)) +#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask) +#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* regcomp() internal fns */ + +/* stuff for character categories */ +typedef unsigned char cat_t; + +/* + * main compiled-expression structure + */ +struct re_guts { + int magic; +# define MAGIC2 ((('R'^0200)<<8)|'E') + sop *strip; /* malloced area for strip */ + int csetsize; /* number of bits in a cset vector */ + int ncsets; /* number of csets in use */ + cset *sets; /* -> cset [ncsets] */ + uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */ + int cflags; /* copy of regcomp() cflags argument */ + sopno nstates; /* = number of sops */ + sopno firststate; /* the initial OEND (normally 0) */ + sopno laststate; /* the final OEND */ + int iflags; /* internal flags */ +# define USEBOL 01 /* used ^ */ +# define USEEOL 02 /* used $ */ +# define BAD 04 /* something wrong */ + int nbol; /* number of ^ used */ + int neol; /* number of $ used */ + int ncategories; /* how many character categories */ + cat_t *categories; /* ->catspace[-CHAR_MIN] */ + char *must; /* match must contain this string */ + int mlen; /* length of must */ + size_t nsub; /* copy of re_nsub */ + int backrefs; /* does it use back references? */ + sopno nplus; /* how deep does it nest +s? */ + /* catspace must be last */ + cat_t catspace[1]; /* actually [NC] */ +}; + +/* misc utilities */ +#define OUT (CHAR_MAX+1) /* a non-character value */ +#define ISWORD(c) (isalnum(c) || (c) == '_') diff --git a/APACHE_1_3b7/src/regex/regexec.c b/APACHE_1_3b7/src/regex/regexec.c new file mode 100644 index 0000000000..182e66730b --- /dev/null +++ b/APACHE_1_3b7/src/regex/regexec.c @@ -0,0 +1,140 @@ +/* + * the outer shell of regexec() + * + * This file includes engine.c *twice*, after muchos fiddling with the + * macros that code uses. This lets the same code operate on two different + * representations for state sets. + */ +#include +#include +#include +#include +#include +#include + +#include "hsregex.h" +#include "utils.h" +#include "regex2.h" + +#ifndef NDEBUG +static int nope = 0; /* for use in asserts; shuts lint up */ +#endif + +/* macros for manipulating states, small version */ +#define states long +#define states1 states /* for later use in regexec() decision */ +#define CLEAR(v) ((v) = 0) +#define SET0(v, n) ((v) &= ~(1 << (n))) +#define SET1(v, n) ((v) |= 1 << (n)) +#define ISSET(v, n) ((v) & (1 << (n))) +#define ASSIGN(d, s) ((d) = (s)) +#define EQ(a, b) ((a) == (b)) +#define STATEVARS int dummy /* dummy version */ +#define STATESETUP(m, n) /* nothing */ +#define STATETEARDOWN(m) /* nothing */ +#define SETUP(v) ((v) = 0) +#define onestate int +#define INIT(o, n) ((o) = (unsigned)1 << (n)) +#define INC(o) ((o) <<= 1) +#define ISSTATEIN(v, o) ((v) & (o)) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst) |= ((unsigned)(src)&(here)) << (n)) +#define BACK(dst, src, n) ((dst) |= ((unsigned)(src)&(here)) >> (n)) +#define ISSETBACK(v, n) ((v) & ((unsigned)here >> (n))) +/* function names */ +#define SNAMES /* engine.c looks after details */ + +#include "engine.c" + +/* now undo things */ +#undef states +#undef CLEAR +#undef SET0 +#undef SET1 +#undef ISSET +#undef ASSIGN +#undef EQ +#undef STATEVARS +#undef STATESETUP +#undef STATETEARDOWN +#undef SETUP +#undef onestate +#undef INIT +#undef INC +#undef ISSTATEIN +#undef FWD +#undef BACK +#undef ISSETBACK +#undef SNAMES + +/* macros for manipulating states, large version */ +#define states char * +#define CLEAR(v) memset(v, 0, m->g->nstates) +#define SET0(v, n) ((v)[n] = 0) +#define SET1(v, n) ((v)[n] = 1) +#define ISSET(v, n) ((v)[n]) +#define ASSIGN(d, s) memcpy(d, s, m->g->nstates) +#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0) +#define STATEVARS int vn; char *space +#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \ + if ((m)->space == NULL) return(REG_ESPACE); \ + (m)->vn = 0; } +#define STATETEARDOWN(m) { free((m)->space); } +#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates]) +#define onestate int +#define INIT(o, n) ((o) = (n)) +#define INC(o) ((o)++) +#define ISSTATEIN(v, o) ((v)[o]) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here]) +#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here]) +#define ISSETBACK(v, n) ((v)[here - (n)]) +/* function names */ +#define LNAMES /* flag */ + +#include "engine.c" + +/* + - regexec - interface for matching + = API_EXPORT(int) regexec(const regex_t *, const char *, size_t, \ + = regmatch_t [], int); + = #define REG_NOTBOL 00001 + = #define REG_NOTEOL 00002 + = #define REG_STARTEND 00004 + = #define REG_TRACE 00400 // tracing of execution + = #define REG_LARGE 01000 // force large representation + = #define REG_BACKR 02000 // force use of backref code + * + * We put this here so we can exploit knowledge of the state representation + * when choosing which matcher to call. Also, by this point the matchers + * have been prototyped. + */ +API_EXPORT(int) /* 0 success, REG_NOMATCH failure */ +regexec(preg, string, nmatch, pmatch, eflags) +const regex_t *preg; +const char *string; +size_t nmatch; +regmatch_t pmatch[]; +int eflags; +{ + register struct re_guts *g = preg->re_g; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND)) +#endif + + if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) + return(REG_BADPAT); + assert(!(g->iflags&BAD)); + if (g->iflags&BAD) /* backstop for no-debug case */ + return(REG_BADPAT); + eflags = GOODFLAGS(eflags); + + if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags®_LARGE)) + return(smatcher(g, (char *)string, nmatch, pmatch, eflags)); + else + return(lmatcher(g, (char *)string, nmatch, pmatch, eflags)); +} diff --git a/APACHE_1_3b7/src/regex/regfree.c b/APACHE_1_3b7/src/regex/regfree.c new file mode 100644 index 0000000000..ffe493158f --- /dev/null +++ b/APACHE_1_3b7/src/regex/regfree.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "hsregex.h" +#include "utils.h" +#include "regex2.h" + +/* + - regfree - free everything + = API_EXPORT(void) regfree(regex_t *); + */ +API_EXPORT(void) +regfree(preg) +regex_t *preg; +{ + register struct re_guts *g; + + if (preg->re_magic != MAGIC1) /* oops */ + return; /* nice to complain, but hard */ + + g = preg->re_g; + if (g == NULL || g->magic != MAGIC2) /* oops again */ + return; + preg->re_magic = 0; /* mark it invalid */ + g->magic = 0; /* mark it invalid */ + + if (g->strip != NULL) + free((char *)g->strip); + if (g->sets != NULL) + free((char *)g->sets); + if (g->setbits != NULL) + free((char *)g->setbits); + if (g->must != NULL) + free(g->must); + free((char *)g); +} diff --git a/APACHE_1_3b7/src/regex/split.c b/APACHE_1_3b7/src/regex/split.c new file mode 100644 index 0000000000..188bdb775b --- /dev/null +++ b/APACHE_1_3b7/src/regex/split.c @@ -0,0 +1,316 @@ +#include +#include + +/* + - split - divide a string into fields, like awk split() + = int split(char *string, char *fields[], int nfields, char *sep); + */ +int /* number of fields, including overflow */ +split(string, fields, nfields, sep) +char *string; +char *fields[]; /* list is not NULL-terminated */ +int nfields; /* number of entries available in fields[] */ +char *sep; /* "" white, "c" single char, "ab" [ab]+ */ +{ + register char *p = string; + register char c; /* latest character */ + register char sepc = sep[0]; + register char sepc2; + register int fn; + register char **fp = fields; + register char *sepp; + register int trimtrail; + + /* white space */ + if (sepc == '\0') { + while ((c = *p++) == ' ' || c == '\t') + continue; + p--; + trimtrail = 1; + sep = " \t"; /* note, code below knows this is 2 long */ + sepc = ' '; + } else + trimtrail = 0; + sepc2 = sep[1]; /* now we can safely pick this up */ + + /* catch empties */ + if (*p == '\0') + return(0); + + /* single separator */ + if (sepc2 == '\0') { + fn = nfields; + for (;;) { + *fp++ = p; + fn--; + if (fn == 0) + break; + while ((c = *p++) != sepc) + if (c == '\0') + return(nfields - fn); + *(p-1) = '\0'; + } + /* we have overflowed the fields vector -- just count them */ + fn = nfields; + for (;;) { + while ((c = *p++) != sepc) + if (c == '\0') + return(fn); + fn++; + } + /* not reached */ + } + + /* two separators */ + if (sep[2] == '\0') { + fn = nfields; + for (;;) { + *fp++ = p; + fn--; + while ((c = *p++) != sepc && c != sepc2) + if (c == '\0') { + if (trimtrail && **(fp-1) == '\0') + fn++; + return(nfields - fn); + } + if (fn == 0) + break; + *(p-1) = '\0'; + while ((c = *p++) == sepc || c == sepc2) + continue; + p--; + } + /* we have overflowed the fields vector -- just count them */ + fn = nfields; + while (c != '\0') { + while ((c = *p++) == sepc || c == sepc2) + continue; + p--; + fn++; + while ((c = *p++) != '\0' && c != sepc && c != sepc2) + continue; + } + /* might have to trim trailing white space */ + if (trimtrail) { + p--; + while ((c = *--p) == sepc || c == sepc2) + continue; + p++; + if (*p != '\0') { + if (fn == nfields+1) + *p = '\0'; + fn--; + } + } + return(fn); + } + + /* n separators */ + fn = 0; + for (;;) { + if (fn < nfields) + *fp++ = p; + fn++; + for (;;) { + c = *p++; + if (c == '\0') + return(fn); + sepp = sep; + while ((sepc = *sepp++) != '\0' && sepc != c) + continue; + if (sepc != '\0') /* it was a separator */ + break; + } + if (fn < nfields) + *(p-1) = '\0'; + for (;;) { + c = *p++; + sepp = sep; + while ((sepc = *sepp++) != '\0' && sepc != c) + continue; + if (sepc == '\0') /* it wasn't a separator */ + break; + } + p--; + } + + /* not reached */ +} + +#ifdef TEST_SPLIT + + +/* + * test program + * pgm runs regression + * pgm sep splits stdin lines by sep + * pgm str sep splits str by sep + * pgm str sep n splits str by sep n times + */ +int +main(argc, argv) +int argc; +char *argv[]; +{ + char buf[512]; + register int n; +# define MNF 10 + char *fields[MNF]; + + if (argc > 4) + for (n = atoi(argv[3]); n > 0; n--) { + (void) strcpy(buf, argv[1]); + } + else if (argc > 3) + for (n = atoi(argv[3]); n > 0; n--) { + (void) strcpy(buf, argv[1]); + (void) split(buf, fields, MNF, argv[2]); + } + else if (argc > 2) + dosplit(argv[1], argv[2]); + else if (argc > 1) + while (fgets(buf, sizeof(buf), stdin) != NULL) { + buf[strlen(buf)-1] = '\0'; /* stomp newline */ + dosplit(buf, argv[1]); + } + else + regress(); + + exit(0); +} + +dosplit(string, seps) +char *string; +char *seps; +{ +# define NF 5 + char *fields[NF]; + register int nf; + + nf = split(string, fields, NF, seps); + print(nf, NF, fields); +} + +print(nf, nfp, fields) +int nf; +int nfp; +char *fields[]; +{ + register int fn; + register int bound; + + bound = (nf > nfp) ? nfp : nf; + printf("%d:\t", nf); + for (fn = 0; fn < bound; fn++) + printf("\"%s\"%s", fields[fn], (fn+1 < nf) ? ", " : "\n"); +} + +#define RNF 5 /* some table entries know this */ +struct { + char *str; + char *seps; + int nf; + char *fi[RNF]; +} tests[] = { + "", " ", 0, { "" }, + " ", " ", 2, { "", "" }, + "x", " ", 1, { "x" }, + "xy", " ", 1, { "xy" }, + "x y", " ", 2, { "x", "y" }, + "abc def g ", " ", 5, { "abc", "def", "", "g", "" }, + " a bcd", " ", 4, { "", "", "a", "bcd" }, + "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" }, + " a b c d ", " ", 6, { "", "a", "b", "c", "d " }, + + "", " _", 0, { "" }, + " ", " _", 2, { "", "" }, + "x", " _", 1, { "x" }, + "x y", " _", 2, { "x", "y" }, + "ab _ cd", " _", 2, { "ab", "cd" }, + " a_b c ", " _", 5, { "", "a", "b", "c", "" }, + "a b c_d e f", " _", 6, { "a", "b", "c", "d", "e f" }, + " a b c d ", " _", 6, { "", "a", "b", "c", "d " }, + + "", " _~", 0, { "" }, + " ", " _~", 2, { "", "" }, + "x", " _~", 1, { "x" }, + "x y", " _~", 2, { "x", "y" }, + "ab _~ cd", " _~", 2, { "ab", "cd" }, + " a_b c~", " _~", 5, { "", "a", "b", "c", "" }, + "a b_c d~e f", " _~", 6, { "a", "b", "c", "d", "e f" }, + "~a b c d ", " _~", 6, { "", "a", "b", "c", "d " }, + + "", " _~-", 0, { "" }, + " ", " _~-", 2, { "", "" }, + "x", " _~-", 1, { "x" }, + "x y", " _~-", 2, { "x", "y" }, + "ab _~- cd", " _~-", 2, { "ab", "cd" }, + " a_b c~", " _~-", 5, { "", "a", "b", "c", "" }, + "a b_c-d~e f", " _~-", 6, { "a", "b", "c", "d", "e f" }, + "~a-b c d ", " _~-", 6, { "", "a", "b", "c", "d " }, + + "", " ", 0, { "" }, + " ", " ", 2, { "", "" }, + "x", " ", 1, { "x" }, + "xy", " ", 1, { "xy" }, + "x y", " ", 2, { "x", "y" }, + "abc def g ", " ", 4, { "abc", "def", "g", "" }, + " a bcd", " ", 3, { "", "a", "bcd" }, + "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" }, + " a b c d ", " ", 6, { "", "a", "b", "c", "d " }, + + "", "", 0, { "" }, + " ", "", 0, { "" }, + "x", "", 1, { "x" }, + "xy", "", 1, { "xy" }, + "x y", "", 2, { "x", "y" }, + "abc def g ", "", 3, { "abc", "def", "g" }, + "\t a bcd", "", 2, { "a", "bcd" }, + " a \tb\t c ", "", 3, { "a", "b", "c" }, + "a b c d e ", "", 5, { "a", "b", "c", "d", "e" }, + "a b\tc d e f", "", 6, { "a", "b", "c", "d", "e f" }, + " a b c d e f ", "", 6, { "a", "b", "c", "d", "e f " }, + + NULL, NULL, 0, { NULL }, +}; + +regress() +{ + char buf[512]; + register int n; + char *fields[RNF+1]; + register int nf; + register int i; + register int printit; + register char *f; + + for (n = 0; tests[n].str != NULL; n++) { + (void) strcpy(buf, tests[n].str); + fields[RNF] = NULL; + nf = split(buf, fields, RNF, tests[n].seps); + printit = 0; + if (nf != tests[n].nf) { + printf("split `%s' by `%s' gave %d fields, not %d\n", + tests[n].str, tests[n].seps, nf, tests[n].nf); + printit = 1; + } else if (fields[RNF] != NULL) { + printf("split() went beyond array end\n"); + printit = 1; + } else { + for (i = 0; i < nf && i < RNF; i++) { + f = fields[i]; + if (f == NULL) + f = "(NULL)"; + if (strcmp(f, tests[n].fi[i]) != 0) { + printf("split `%s' by `%s', field %d is `%s', not `%s'\n", + tests[n].str, tests[n].seps, + i, fields[i], tests[n].fi[i]); + printit = 1; + } + } + } + if (printit) + print(nf, RNF, fields); + } +} +#endif diff --git a/APACHE_1_3b7/src/regex/tests b/APACHE_1_3b7/src/regex/tests new file mode 100644 index 0000000000..c05846177f --- /dev/null +++ b/APACHE_1_3b7/src/regex/tests @@ -0,0 +1,475 @@ +# regular expression test set +# Lines are at least three fields, separated by one or more tabs. "" stands +# for an empty field. First field is an RE. Second field is flags. If +# C flag given, regcomp() is expected to fail, and the third field is the +# error name (minus the leading REG_). +# +# Otherwise it is expected to succeed, and the third field is the string to +# try matching it against. If there is no fourth field, the match is +# expected to fail. If there is a fourth field, it is the substring that +# the RE is expected to match. If there is a fifth field, it is a comma- +# separated list of what the subexpressions should match, with - indicating +# no match for that one. In both the fourth and fifth fields, a (sub)field +# starting with @ indicates that the (sub)expression is expected to match +# a null string followed by the stuff after the @; this provides a way to +# test where null strings match. The character `N' in REs and strings +# is newline, `S' is space, `T' is tab, `Z' is NUL. +# +# The full list of flags: +# - placeholder, does nothing +# b RE is a BRE, not an ERE +# & try it as both an ERE and a BRE +# C regcomp() error expected, third field is error name +# i REG_ICASE +# m ("mundane") REG_NOSPEC +# s REG_NOSUB (not really testable) +# n REG_NEWLINE +# ^ REG_NOTBOL +# $ REG_NOTEOL +# # REG_STARTEND (see below) +# p REG_PEND +# +# For REG_STARTEND, the start/end offsets are those of the substring +# enclosed in (). + +# basics +a & a a +abc & abc abc +abc|de - abc abc +a|b|c - abc a + +# parentheses and perversions thereof +a(b)c - abc abc +a\(b\)c b abc abc +a( C EPAREN +a( b a( a( +a\( - a( a( +a\( bC EPAREN +a\(b bC EPAREN +a(b C EPAREN +a(b b a(b a(b +# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly) +a) - a) a) +) - ) ) +# end gagging (in a just world, those *should* give EPAREN) +a) b a) a) +a\) bC EPAREN +\) bC EPAREN +a()b - ab ab +a\(\)b b ab ab + +# anchoring and REG_NEWLINE +^abc$ & abc abc +a^b - a^b +a^b b a^b a^b +a$b - a$b +a$b b a$b a$b +^ & abc @abc +$ & abc @ +^$ & "" @ +$^ - "" @ +\($\)\(^\) b "" @ +# stop retching, those are legitimate (although disgusting) +^^ - "" @ +$$ - "" @ +b$ & abNc +b$ &n abNc b +^b$ & aNbNc +^b$ &n aNbNc b +^$ &n aNNb @Nb +^$ n abc +^$ n abcN @ +$^ n aNNb @Nb +\($\)\(^\) bn aNNb @Nb +^^ n^ aNNb @Nb +$$ n aNNb @NN +^a ^ a +a$ $ a +^a ^n aNb +^b ^n aNb b +a$ $n bNa +b$ $n bNa b +a*(^b$)c* - b b +a*\(^b$\)c* b b b + +# certain syntax errors and non-errors +| C EMPTY +| b | | +* C BADRPT +* b * * ++ C BADRPT +? C BADRPT +"" &C EMPTY +() - abc @abc +\(\) b abc @abc +a||b C EMPTY +|ab C EMPTY +ab| C EMPTY +(|a)b C EMPTY +(a|)b C EMPTY +(*a) C BADRPT +(+a) C BADRPT +(?a) C BADRPT +({1}a) C BADRPT +\(\{1\}a\) bC BADRPT +(a|*b) C BADRPT +(a|+b) C BADRPT +(a|?b) C BADRPT +(a|{1}b) C BADRPT +^* C BADRPT +^* b * * +^+ C BADRPT +^? C BADRPT +^{1} C BADRPT +^\{1\} bC BADRPT + +# metacharacters, backslashes +a.c & abc abc +a[bc]d & abd abd +a\*c & a*c a*c +a\\b & a\b a\b +a\\\*b & a\*b a\*b +a\bc & abc abc +a\ &C EESCAPE +a\\bc & a\bc a\bc +\{ bC BADRPT +a\[b & a[b a[b +a[b &C EBRACK +# trailing $ is a peculiar special case for the BRE code +a$ & a a +a$ & a$ +a\$ & a +a\$ & a$ a$ +a\\$ & a +a\\$ & a$ +a\\$ & a\$ +a\\$ & a\ a\ + +# back references, ugh +a\(b\)\2c bC ESUBREG +a\(b\1\)c bC ESUBREG +a\(b*\)c\1d b abbcbbd abbcbbd bb +a\(b*\)c\1d b abbcbd +a\(b*\)c\1d b abbcbbbd +^\(.\)\1 b abc +a\([bc]\)\1d b abcdabbd abbd b +a\(\([bc]\)\2\)*d b abbccd abbccd +a\(\([bc]\)\2\)*d b abbcbd +# actually, this next one probably ought to fail, but the spec is unclear +a\(\(b\)*\2\)*d b abbbd abbbd +# here is a case that no NFA implementation does right +\(ab*\)[ab]*\1 b ababaaa ababaaa a +# check out normal matching in the presence of back refs +\(a\)\1bcd b aabcd aabcd +\(a\)\1bc*d b aabcd aabcd +\(a\)\1bc*d b aabd aabd +\(a\)\1bc*d b aabcccd aabcccd +\(a\)\1bc*[ce]d b aabcccd aabcccd +^\(a\)\1b\(c\)*cd$ b aabcccd aabcccd + +# ordinary repetitions +ab*c & abc abc +ab+c - abc abc +ab?c - abc abc +a\(*\)b b a*b a*b +a\(**\)b b ab ab +a\(***\)b bC BADRPT +*a b *a *a +**a b a a +***a bC BADRPT + +# the dreaded bounded repetitions +{ & { { +{abc & {abc {abc +{1 C BADRPT +{1} C BADRPT +a{b & a{b a{b +a{1}b - ab ab +a\{1\}b b ab ab +a{1,}b - ab ab +a\{1,\}b b ab ab +a{1,2}b - aab aab +a\{1,2\}b b aab aab +a{1 C EBRACE +a\{1 bC EBRACE +a{1a C EBRACE +a\{1a bC EBRACE +a{1a} C BADBR +a\{1a\} bC BADBR +a{,2} - a{,2} a{,2} +a\{,2\} bC BADBR +a{,} - a{,} a{,} +a\{,\} bC BADBR +a{1,x} C BADBR +a\{1,x\} bC BADBR +a{1,x C EBRACE +a\{1,x bC EBRACE +a{300} C BADBR +a\{300\} bC BADBR +a{1,0} C BADBR +a\{1,0\} bC BADBR +ab{0,0}c - abcac ac +ab\{0,0\}c b abcac ac +ab{0,1}c - abcac abc +ab\{0,1\}c b abcac abc +ab{0,3}c - abbcac abbc +ab\{0,3\}c b abbcac abbc +ab{1,1}c - acabc abc +ab\{1,1\}c b acabc abc +ab{1,3}c - acabc abc +ab\{1,3\}c b acabc abc +ab{2,2}c - abcabbc abbc +ab\{2,2\}c b abcabbc abbc +ab{2,4}c - abcabbc abbc +ab\{2,4\}c b abcabbc abbc +((a{1,10}){1,10}){1,10} - a a a,a + +# multiple repetitions +a** &C BADRPT +a++ C BADRPT +a?? C BADRPT +a*+ C BADRPT +a*? C BADRPT +a+* C BADRPT +a+? C BADRPT +a?* C BADRPT +a?+ C BADRPT +a{1}{1} C BADRPT +a*{1} C BADRPT +a+{1} C BADRPT +a?{1} C BADRPT +a{1}* C BADRPT +a{1}+ C BADRPT +a{1}? C BADRPT +a*{b} - a{b} a{b} +a\{1\}\{1\} bC BADRPT +a*\{1\} bC BADRPT +a\{1\}* bC BADRPT + +# brackets, and numerous perversions thereof +a[b]c & abc abc +a[ab]c & abc abc +a[^ab]c & adc adc +a[]b]c & a]c a]c +a[[b]c & a[c a[c +a[-b]c & a-c a-c +a[^]b]c & adc adc +a[^-b]c & adc adc +a[b-]c & a-c a-c +a[b &C EBRACK +a[] &C EBRACK +a[1-3]c & a2c a2c +a[3-1]c &C ERANGE +a[1-3-5]c &C ERANGE +a[[.-.]--]c & a-c a-c +a[1- &C ERANGE +a[[. &C EBRACK +a[[.x &C EBRACK +a[[.x. &C EBRACK +a[[.x.] &C EBRACK +a[[.x.]] & ax ax +a[[.x,.]] &C ECOLLATE +a[[.one.]]b & a1b a1b +a[[.notdef.]]b &C ECOLLATE +a[[.].]]b & a]b a]b +a[[:alpha:]]c & abc abc +a[[:notdef:]]c &C ECTYPE +a[[: &C EBRACK +a[[:alpha &C EBRACK +a[[:alpha:] &C EBRACK +a[[:alpha,:] &C ECTYPE +a[[:]:]]b &C ECTYPE +a[[:-:]]b &C ECTYPE +a[[:alph:]] &C ECTYPE +a[[:alphabet:]] &C ECTYPE +[[:alnum:]]+ - -%@a0X- a0X +[[:alpha:]]+ - -%@aX0- aX +[[:blank:]]+ - aSSTb SST +[[:cntrl:]]+ - aNTb NT +[[:digit:]]+ - a019b 019 +[[:graph:]]+ - Sa%bS a%b +[[:lower:]]+ - AabC ab +[[:print:]]+ - NaSbN aSb +[[:punct:]]+ - S%-&T %-& +[[:space:]]+ - aSNTb SNT +[[:upper:]]+ - aBCd BC +[[:xdigit:]]+ - p0f3Cq 0f3C +a[[=b=]]c & abc abc +a[[= &C EBRACK +a[[=b &C EBRACK +a[[=b= &C EBRACK +a[[=b=] &C EBRACK +a[[=b,=]] &C ECOLLATE +a[[=one=]]b & a1b a1b + +# complexities +a(((b)))c - abc abc +a(b|(c))d - abd abd +a(b*|c)d - abbd abbd +# just gotta have one DFA-buster, of course +a[ab]{20} - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab +# and an inline expansion in case somebody gets tricky +a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab +# and in case somebody just slips in an NFA... +a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) - aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights +# fish for anomalies as the number of states passes 32 +12345678901234567890123456789 - a12345678901234567890123456789b 12345678901234567890123456789 +123456789012345678901234567890 - a123456789012345678901234567890b 123456789012345678901234567890 +1234567890123456789012345678901 - a1234567890123456789012345678901b 1234567890123456789012345678901 +12345678901234567890123456789012 - a12345678901234567890123456789012b 12345678901234567890123456789012 +123456789012345678901234567890123 - a123456789012345678901234567890123b 123456789012345678901234567890123 +# and one really big one, beyond any plausible word width +1234567890123456789012345678901234567890123456789012345678901234567890 - a1234567890123456789012345678901234567890123456789012345678901234567890b 1234567890123456789012345678901234567890123456789012345678901234567890 +# fish for problems as brackets go past 8 +[ab][cd][ef][gh][ij][kl][mn] - xacegikmoq acegikm +[ab][cd][ef][gh][ij][kl][mn][op] - xacegikmoq acegikmo +[ab][cd][ef][gh][ij][kl][mn][op][qr] - xacegikmoqy acegikmoq +[ab][cd][ef][gh][ij][kl][mn][op][q] - xacegikmoqy acegikmoq + +# subtleties of matching +abc & xabcy abc +a\(b\)?c\1d b acd +aBc i Abc Abc +a[Bc]*d i abBCcd abBCcd +0[[:upper:]]1 &i 0a1 0a1 +0[[:lower:]]1 &i 0A1 0A1 +a[^b]c &i abc +a[^b]c &i aBc +a[^b]c &i adc adc +[a]b[c] - abc abc +[a]b[a] - aba aba +[abc]b[abc] - abc abc +[abc]b[abd] - abd abd +a(b?c)+d - accd accd +(wee|week)(knights|night) - weeknights weeknights +(we|wee|week|frob)(knights|night|day) - weeknights weeknights +a[bc]d - xyzaaabcaababdacd abd +a[ab]c - aaabc abc +abc s abc abc +a* & b @b + +# Let's have some fun -- try to match a C comment. +# first the obvious, which looks okay at first glance... +/\*.*\*/ - /*x*/ /*x*/ +# but... +/\*.*\*/ - /*x*/y/*z*/ /*x*/y/*z*/ +# okay, we must not match */ inside; try to do that... +/\*([^*]|\*[^/])*\*/ - /*x*/ /*x*/ +/\*([^*]|\*[^/])*\*/ - /*x*/y/*z*/ /*x*/ +# but... +/\*([^*]|\*[^/])*\*/ - /*x**/y/*z*/ /*x**/y/*z*/ +# and a still fancier version, which does it right (I think)... +/\*([^*]|\*+[^*/])*\*+/ - /*x*/ /*x*/ +/\*([^*]|\*+[^*/])*\*+/ - /*x*/y/*z*/ /*x*/ +/\*([^*]|\*+[^*/])*\*+/ - /*x**/y/*z*/ /*x**/ +/\*([^*]|\*+[^*/])*\*+/ - /*x****/y/*z*/ /*x****/ +/\*([^*]|\*+[^*/])*\*+/ - /*x**x*/y/*z*/ /*x**x*/ +/\*([^*]|\*+[^*/])*\*+/ - /*x***x/y/*z*/ /*x***x/y/*z*/ + +# subexpressions +a(b)(c)d - abcd abcd b,c +a(((b)))c - abc abc b,b,b +a(b|(c))d - abd abd b,- +a(b*|c|e)d - abbd abbd bb +a(b*|c|e)d - acd acd c +a(b*|c|e)d - ad ad @d +a(b?)c - abc abc b +a(b?)c - ac ac @c +a(b+)c - abc abc b +a(b+)c - abbbc abbbc bbb +a(b*)c - ac ac @c +(a|ab)(bc([de]+)f|cde) - abcdef abcdef a,bcdef,de +# the regression tester only asks for 9 subexpressions +a(b)(c)(d)(e)(f)(g)(h)(i)(j)k - abcdefghijk abcdefghijk b,c,d,e,f,g,h,i,j +a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l - abcdefghijkl abcdefghijkl b,c,d,e,f,g,h,i,j,k +a([bc]?)c - abc abc b +a([bc]?)c - ac ac @c +a([bc]+)c - abc abc b +a([bc]+)c - abcc abcc bc +a([bc]+)bc - abcbc abcbc bc +a(bb+|b)b - abb abb b +a(bbb+|bb+|b)b - abb abb b +a(bbb+|bb+|b)b - abbb abbb bb +a(bbb+|bb+|b)bb - abbb abbb b +(.*).* - abcdef abcdef abcdef +(a*)* - bc @b @b + +# do we get the right subexpression when it is used more than once? +a(b|c)*d - ad ad - +a(b|c)*d - abcd abcd c +a(b|c)+d - abd abd b +a(b|c)+d - abcd abcd c +a(b|c?)+d - ad ad @d +a(b|c?)+d - abcd abcd @d +a(b|c){0,0}d - ad ad - +a(b|c){0,1}d - ad ad - +a(b|c){0,1}d - abd abd b +a(b|c){0,2}d - ad ad - +a(b|c){0,2}d - abcd abcd c +a(b|c){0,}d - ad ad - +a(b|c){0,}d - abcd abcd c +a(b|c){1,1}d - abd abd b +a(b|c){1,1}d - acd acd c +a(b|c){1,2}d - abd abd b +a(b|c){1,2}d - abcd abcd c +a(b|c){1,}d - abd abd b +a(b|c){1,}d - abcd abcd c +a(b|c){2,2}d - acbd acbd b +a(b|c){2,2}d - abcd abcd c +a(b|c){2,4}d - abcd abcd c +a(b|c){2,4}d - abcbd abcbd b +a(b|c){2,4}d - abcbcd abcbcd c +a(b|c){2,}d - abcd abcd c +a(b|c){2,}d - abcbd abcbd b +a(b+|((c)*))+d - abd abd @d,@d,- +a(b+|((c)*))+d - abcd abcd @d,@d,- + +# check out the STARTEND option +[abc] &# a(b)c b +[abc] &# a(d)c +[abc] &# a(bc)d b +[abc] &# a(dc)d c +. &# a()c +b.*c &# b(bc)c bc +b.* &# b(bc)c bc +.*c &# b(bc)c bc + +# plain strings, with the NOSPEC flag +abc m abc abc +abc m xabcy abc +abc m xyz +a*b m aba*b a*b +a*b m ab +"" mC EMPTY + +# cases involving NULs +aZb & a a +aZb &p a +aZb &p# (aZb) aZb +aZ*b &p# (ab) ab +a.b &# (aZb) aZb +a.* &# (aZb)c aZb + +# word boundaries (ick) +[[:<:]]a & a a +[[:<:]]a & ba +[[:<:]]a & -a a +a[[:>:]] & a a +a[[:>:]] & ab +a[[:>:]] & a- a +[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc abc +[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc-q abc +[[:<:]]a.c[[:>:]] & axc-dayc-dazce-abc axc +[[:<:]]b.c[[:>:]] & a_bxc-byc_d-bzc-q bzc +[[:<:]].x..[[:>:]] & y_xa_-_xb_y-_xc_-axdc _xc_ +[[:<:]]a_b[[:>:]] & x_a_b + +# past problems, and suspected problems +(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A]) - A1 A1 +abcdefghijklmnop i abcdefghijklmnop abcdefghijklmnop +abcdefghijklmnopqrstuv i abcdefghijklmnopqrstuv abcdefghijklmnopqrstuv +(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN]) - CC11 CC11 +CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a - CC11 CC11 +Char \([a-z0-9_]*\)\[.* b Char xyz[k Char xyz[k xyz +a?b - ab ab +-\{0,1\}[0-9]*$ b -5 -5 diff --git a/APACHE_1_3b7/src/regex/utils.h b/APACHE_1_3b7/src/regex/utils.h new file mode 100644 index 0000000000..f271f759b1 --- /dev/null +++ b/APACHE_1_3b7/src/regex/utils.h @@ -0,0 +1,22 @@ +/* utility definitions */ +#ifndef _POSIX2_RE_DUP_MAX +#define _POSIX2_RE_DUP_MAX 255 +#endif + +#define DUPMAX _POSIX2_RE_DUP_MAX /* xxx is this right? */ +#define INFINITY (DUPMAX + 1) +#define NC (CHAR_MAX - CHAR_MIN + 1) +typedef unsigned char uch; + +/* switch off assertions (if not already off) if no REDEBUG */ +#ifndef REDEBUG +#ifndef NDEBUG +#define NDEBUG /* no assertions please */ +#endif +#endif +#include + +/* for old systems with bcopy() but no memmove() */ +#ifdef USEBCOPY +#define memmove(d, s, c) bcopy(s, d, c) +#endif diff --git a/APACHE_1_3b7/src/support/.cvsignore b/APACHE_1_3b7/src/support/.cvsignore new file mode 100644 index 0000000000..399f114e93 --- /dev/null +++ b/APACHE_1_3b7/src/support/.cvsignore @@ -0,0 +1,11 @@ +Makefile +rotatelogs +htpasswd +htdigest +unescape +inc2shtml +httpd_monitor +suexec +logresolve +ab +apxs diff --git a/APACHE_1_3b7/src/support/.indent.pro b/APACHE_1_3b7/src/support/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3b7/src/support/.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/APACHE_1_3b7/src/support/Makefile.tmpl b/APACHE_1_3b7/src/support/Makefile.tmpl new file mode 100644 index 0000000000..c52e722984 --- /dev/null +++ b/APACHE_1_3b7/src/support/Makefile.tmpl @@ -0,0 +1,71 @@ + +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) +LIBS=-lap $(EXTRA_LIBS) $(LIBS1) +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES) +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) -L$(SRCDIR)/ap + +TARGETS=htpasswd htdigest rotatelogs logresolve ab apxs + +OBJS=htpasswd.o htdigest.o rotatelogs.o logresolve.o ab.o + +.c.o: + $(CC) -c $(CFLAGS) $(INCLUDES) $< + +all: $(TARGETS) + +htpasswd: htpasswd.o + $(CC) $(CFLAGS) htpasswd.o -o htpasswd $(LDFLAGS) $(LIBS) + +htdigest: htdigest.o + $(CC) $(CFLAGS) htdigest.o -o htdigest $(LDFLAGS) $(LIBS) + +rotatelogs: rotatelogs.o + $(CC) $(CFLAGS) rotatelogs.o -o rotatelogs $(LDFLAGS) $(LIBS) + +logresolve: logresolve.o + $(CC) $(CFLAGS) logresolve.o -o logresolve $(LDFLAGS) $(LIBS) + +ab: ab.o + $(CC) $(CFLAGS) ab.o -o ab $(LDFLAGS) $(LIBS) + +apxs: apxs.pl + sed apxs \ + -e 's%@CC@%$(CC)%g' \ + -e 's%@LD_SHLIB@%$(LD_SHLIB)%g' \ + -e 's%@CFLAGS@%$(CFLAGS)%g' \ + -e 's%@CFLAGS_SHLIB@%$(CFLAGS_SHLIB)%g' \ + -e 's%@LDFLAGS_SHLIB@%$(LDFLAGS_SHLIB)%g' && chmod a+x apxs + +suexec: suexec.o + $(CC) $(CFLAGS) suexec.o -o suexec $(LDFLAGS) $(LIBS) + +clean: + rm -f $(TARGETS) *.o + +distclean: clean + -rm -f Makefile + +# We really don't expect end users to use this rule. It works only with +# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after +# using it. +depend: + cp Makefile.tmpl Makefile.tmpl.bak \ + && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \ + && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \ + && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \ + -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \ + > Makefile.tmpl \ + && rm Makefile.new + +#Dependencies + +$(OBJS): Makefile + +# DO NOT REMOVE +ab.o: ab.c $(INCDIR)/conf.h $(OSDIR)/os.h +htdigest.o: htdigest.c $(INCDIR)/conf.h $(OSDIR)/os.h \ + ../main/md5c.c $(INCDIR)/md5.h +htpasswd.o: htpasswd.c $(INCDIR)/conf.h $(OSDIR)/os.h +logresolve.o: logresolve.c $(INCDIR)/conf.h $(OSDIR)/os.h +rotatelogs.o: rotatelogs.c $(INCDIR)/conf.h $(OSDIR)/os.h +suexec.o: suexec.c $(INCDIR)/conf.h $(OSDIR)/os.h suexec.h diff --git a/APACHE_1_3b7/src/support/ab.1 b/APACHE_1_3b7/src/support/ab.1 new file mode 100644 index 0000000000..2405662f5a --- /dev/null +++ b/APACHE_1_3b7/src/support/ab.1 @@ -0,0 +1,114 @@ +.TH ab 1 "March 1998" +.\" Copyright (c) 1998 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. +.\" +.\" 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 . +.SH NAME +ab \- Apache HTTP server benchmarking tool +.SH SYNOPSIS +.B ab +[ +.B \-k +] [ +.BI \-n " requests" +] [ +.BI \-t " timelimit" +] [ +.BI \-c " concurrency" +] +.I [http://]hostname[:port]/path + +.B ab +[ +.B \-v +] [ +.B \-h +] +.PP +.SH DESCRIPTION +.B ab +is a tool for benchmarking your Apache HyperText Transfer Protocol (HTTP) +server. It is designed to give you an impression on how performant is your +current Apache installation. This especially shows you how much requests per +time your Apache installation is capable to serve. +.PP +.SH OPTIONS +.TP 12 +.B \-k +Enable the HTTP KeepAlive feature, i.e. perform multiple requests within one +HTTP session instead. Default is no KeepAlive. +.TP 12 +.BI \-n " requests" +Number of requests to perform for the benchmarking session. The default is to +just perform one single request which usually leads to not very representative +benchmarking results. +.TP 12 +.BI \-t " timelimit" +Seconds to max. spend for benchmarking. This implies +a +.B \-n +.B 50000 +internally. Use this to benchmark the server within a fixed total amount of +time. Per default there is no timelimit. +.TP 12 +.BI \-c " concurrency" +Number of multiple requests per time to perform. +Default is one request per time. +.TP 12 +.B \-v +Display version and copyright information. +.TP 12 +.B \-h +Display usage information. +.PD +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/ab.8 b/APACHE_1_3b7/src/support/ab.8 new file mode 100644 index 0000000000..2405662f5a --- /dev/null +++ b/APACHE_1_3b7/src/support/ab.8 @@ -0,0 +1,114 @@ +.TH ab 1 "March 1998" +.\" Copyright (c) 1998 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. +.\" +.\" 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 . +.SH NAME +ab \- Apache HTTP server benchmarking tool +.SH SYNOPSIS +.B ab +[ +.B \-k +] [ +.BI \-n " requests" +] [ +.BI \-t " timelimit" +] [ +.BI \-c " concurrency" +] +.I [http://]hostname[:port]/path + +.B ab +[ +.B \-v +] [ +.B \-h +] +.PP +.SH DESCRIPTION +.B ab +is a tool for benchmarking your Apache HyperText Transfer Protocol (HTTP) +server. It is designed to give you an impression on how performant is your +current Apache installation. This especially shows you how much requests per +time your Apache installation is capable to serve. +.PP +.SH OPTIONS +.TP 12 +.B \-k +Enable the HTTP KeepAlive feature, i.e. perform multiple requests within one +HTTP session instead. Default is no KeepAlive. +.TP 12 +.BI \-n " requests" +Number of requests to perform for the benchmarking session. The default is to +just perform one single request which usually leads to not very representative +benchmarking results. +.TP 12 +.BI \-t " timelimit" +Seconds to max. spend for benchmarking. This implies +a +.B \-n +.B 50000 +internally. Use this to benchmark the server within a fixed total amount of +time. Per default there is no timelimit. +.TP 12 +.BI \-c " concurrency" +Number of multiple requests per time to perform. +Default is one request per time. +.TP 12 +.B \-v +Display version and copyright information. +.TP 12 +.B \-h +Display usage information. +.PD +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/ab.c b/APACHE_1_3b7/src/support/ab.c new file mode 100644 index 0000000000..3d0dbeef37 --- /dev/null +++ b/APACHE_1_3b7/src/support/ab.c @@ -0,0 +1,689 @@ +/* ==================================================================== + * Copyright (c) 1998 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 . + * + */ + +/* +** This program is based on ZeusBench V1.0 written by Adam Twiss +** which is Copyright (c) 1996 by Zeus Technology Ltd. http://www.zeustech.net/ +** +** This software is provided "as is" and any express or implied waranties, +** including but not limited to, the implied warranties of merchantability and +** fitness for a particular purpose are disclaimed. In no event shall +** Zeus Technology Ltd. be liable for any direct, indirect, incidental, special, +** exemplary, or consequential damaged (including, but not limited to, +** procurement of substitute good or services; loss of use, data, or profits; +** or business interruption) however caused and on 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. +** +*/ + +/* +** HISTORY: +** - Originally written by Adam Twiss , March 1996 +** with input from Mike Belshe and +** Michael Campanella +** - Enhanced by Dean Gaudet , November 1997 +** - Cleaned up by Ralf S. Engelschall , March 1998 +** +*/ + +#define VERSION "1.1" + +/* -------------------------------------------------------------------- */ + +/* affects include files on Solaris */ +#define BSD_COMP + +#include "conf.h" +#include +#include + +/* ------------------- DEFINITIONS -------------------------- */ + +/* maximum number of requests on a time limited test */ +#define MAX_REQUESTS 50000 + +/* good old state hostname */ +#define STATE_UNCONNECTED 0 +#define STATE_CONNECTING 1 +#define STATE_READ 2 + +#define CBUFFSIZE 512 + +struct connection { + int fd; + int state; + int read; /* amount of bytes read */ + int bread; /* amount of body read */ + int length; /* Content-Length value used for keep-alive */ + char cbuff[CBUFFSIZE]; /* a buffer to store server response header */ + int cbx; /* offset in cbuffer */ + int keepalive; /* non-zero if a keep-alive request */ + int gotheader; /* non-zero if we have the entire header in cbuff */ + struct timeval start, connect, done; +}; + +struct data { + int read; /* number of bytes read */ + int ctime; /* time in ms to connect */ + int time; /* time in ms for connection */ +}; + +#define min(a,b) ((a)<(b))?(a):(b) +#define max(a,b) ((a)>(b))?(a):(b) + +/* --------------------- GLOBALS ---------------------------- */ + +int requests = 1; /* Number of requests to make */ +int concurrency = 1; /* Number of multiple requests to make */ +int tlimit = 0; /* time limit in cs */ +int keepalive = 0; /* try and do keepalive connections */ +char servername[1024]; /* name that server reports */ +char hostname[1024]; /* host name */ +char path[1024]; /* path name */ +int port = 80; /* port number */ + +int doclen = 0; /* the length the document should be */ +int totalread = 0; /* total number of bytes read */ +int totalbread = 0; /* totoal amount of entity body read */ +int done = 0; /* number of requests we have done */ +int doneka = 0; /* number of keep alive connections done */ +int good = 0, bad = 0; /* number of good and bad requests */ + +/* store error cases */ +int err_length = 0, err_conn = 0, err_except = 0; + +struct timeval start, endtime; + +/* global request (and its length) */ +char request[512]; +int reqlen; + +/* one global throw-away buffer to read stuff into */ +char buffer[4096]; + +struct connection *con; /* connection array */ +struct data *stats; /* date for each request */ + +fd_set readbits, writebits; /* bits for select */ +struct sockaddr_in server; /* server addr structure */ + +/* --------------------------------------------------------- */ + +/* simple little function to perror and exit */ + +static void err(char *s) +{ + perror(s); + exit(errno); +} + +/* --------------------------------------------------------- */ + +/* write out request to a connection - assumes we can write + (small) request out in one go into our new socket buffer */ + +static void write_request(struct connection *c) +{ + gettimeofday(&c->connect, 0); + write(c->fd, request, reqlen); + c->state = STATE_READ; + FD_SET(c->fd, &readbits); + FD_CLR(c->fd, &writebits); +} + +/* --------------------------------------------------------- */ + +/* make an fd non blocking */ + +static void nonblock(int fd) +{ + int i = 1; + ioctl(fd, FIONBIO, &i); +} + +/* --------------------------------------------------------- */ + +/* returns the time in ms between two timevals */ + +static int timedif(struct timeval a, struct timeval b) +{ + register int us, s; + + us = a.tv_usec - b.tv_usec; + us /= 1000; + s = a.tv_sec - b.tv_sec; + s *= 1000; + return s + us; +} + +/* --------------------------------------------------------- */ + +/* calculate and output results and exit */ + +static void output_results(void) +{ + int timetaken; + + gettimeofday(&endtime, 0); + timetaken = timedif(endtime, start); + + printf("\r \r"); + printf("Server Software: %s\n", servername); + printf("Server Hostname: %s\n", hostname); + printf("Server Port: %d\n", port); + printf("\n"); + printf("Document Path: %s\n", path); + printf("Document Length: %d bytes\n", doclen); + printf("\n"); + printf("Concurency Level: %d\n", concurrency); + printf("Time taken for tests: %d.%03d seconds\n", + timetaken / 1000, timetaken % 1000); + printf("Complete requests: %d\n", done); + printf("Failed requests: %d\n", bad); + if (bad) + printf(" (Connect: %d, Length: %d, Exceptions: %d)\n", + err_conn, err_length, err_except); + if (keepalive) + printf("Keep-Alive requests: %d\n", doneka); + printf("Total transfered: %d bytes\n", totalread); + printf("HTML transfered: %d bytes\n", totalbread); + + /* avoid divide by zero */ + if (timetaken) { + printf("Requests per seconds: %.2f\n", 1000 * (float) (done) / timetaken); + printf("Transfer rate: %.2f kb/s\n", + (float) (totalread) / timetaken); + } + + { + /* work out connection times */ + int i; + int totalcon = 0, total = 0; + int mincon = 9999999, mintot = 999999; + int maxcon = 0, maxtot = 0; + + for (i = 0; i < requests; i++) { + struct data s = stats[i]; + mincon = min(mincon, s.ctime); + mintot = min(mintot, s.time); + maxcon = max(maxcon, s.ctime); + maxtot = max(maxtot, s.time); + totalcon += s.ctime; + total += s.time; + } + printf("\nConnnection Times (ms)\n"); + printf(" min avg max\n"); + printf("Connect: %5d %5d %5d\n", mincon, totalcon / requests, maxcon); + printf("Total: %5d %5d %5d\n", mintot, total / requests, maxtot); + } + + exit(0); +} + +/* --------------------------------------------------------- */ + +/* start asnchronous non-blocking connection */ + +static void start_connect(struct connection *c) +{ + c->read = 0; + c->bread = 0; + c->keepalive = 0; + c->cbx = 0; + c->gotheader = 0; + + c->fd = socket(AF_INET, SOCK_STREAM, 0); + if (c->fd < 0) + err("socket"); + + nonblock(c->fd); + gettimeofday(&c->start, 0); + + if (connect(c->fd, (struct sockaddr *) &server, sizeof(server)) < 0) { + if (errno == EINPROGRESS) { + c->state = STATE_CONNECTING; + FD_SET(c->fd, &writebits); + return; + } + else { + close(c->fd); + err_conn++; + if (bad++ > 10) { + printf("\nTest aborted after 10 failures\n\n"); + exit(1); + } + start_connect(c); + } + } + + /* connected first time */ + write_request(c); +} + +/* --------------------------------------------------------- */ + +/* close down connection and save stats */ + +static void close_connection(struct connection *c) +{ + if (c->read == 0 && c->keepalive) { + /* server has legitiamately shut down an idle keep alive request */ + good--; /* connection never happend */ + } + else { + if (good == 1) { + /* first time here */ + doclen = c->bread; + } + else if (c->bread != doclen) { + bad++; + err_length++; + } + + /* save out time */ + if (done < requests) { + struct data s; + gettimeofday(&c->done, 0); + s.read = c->read; + s.ctime = timedif(c->connect, c->start); + s.time = timedif(c->done, c->start); + stats[done++] = s; + } + } + + close(c->fd); + FD_CLR(c->fd, &readbits); + FD_CLR(c->fd, &writebits); + + /* connect again */ + start_connect(c); + return; +} + +/* --------------------------------------------------------- */ + +/* read data from connection */ + +static void read_connection(struct connection *c) +{ + int r; + + r = read(c->fd, buffer, sizeof(buffer)); + if (r == 0 || (r < 0 && errno != EAGAIN)) { + good++; + close_connection(c); + return; + } + + if (r < 0 && errno == EAGAIN) + return; + + c->read += r; + totalread += r; + + if (!c->gotheader) { + char *s; + int l = 4; + int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator */ + int tocopy = (space < r) ? space : r; + memcpy(c->cbuff + c->cbx, buffer, space); + c->cbx += tocopy; + space -= tocopy; + c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */ + s = strstr(c->cbuff, "\r\n\r\n"); + /* this next line is so that we talk to NCSA 1.5 which blatantly breaks + the http specifaction */ + if (!s) { + s = strstr(c->cbuff, "\n\n"); + l = 2; + } + + if (!s) { + /* read rest next time */ + if (space) + return; + else { + /* header is in invalid or too big - close connection */ + close(c->fd); + if (bad++ > 10) { + printf("\nTest aborted after 10 failures\n\n"); + exit(1); + } + FD_CLR(c->fd, &writebits); + start_connect(c); + } + } + else { + /* have full header */ + if (!good) { + /* this is first time, extract some interesting info */ + char *p, *q; + p = strstr(c->cbuff, "Server:"); + q = servername; + if (p) { + p += 8; + while (*p > 32) + *q++ = *p++; + } + *q = 0; + } + + c->gotheader = 1; + *s = 0; /* terminate at end of header */ + if (keepalive && + (strstr(c->cbuff, "Keep-Alive") + || strstr(c->cbuff, "keep-alive"))) { /* for benefit of MSIIS */ + char *cl; + cl = strstr(c->cbuff, "Content-Length:"); + /* for cacky servers like NCSA which break the spec and send a + lower case 'l' */ + if (!cl) + cl = strstr(c->cbuff, "Content-length:"); + if (cl) { + c->keepalive = 1; + c->length = atoi(cl + 16); + } + } + c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy; + totalbread += c->bread; + } + } + else { + /* outside header, everything we have read is entity body */ + c->bread += r; + totalbread += r; + } + + if (c->keepalive && (c->bread >= c->length)) { + /* finished a keep-alive connection */ + good++; + doneka++; + /* save out time */ + if (good == 1) { + /* first time here */ + doclen = c->bread; + } + else if (c->bread != doclen) { + bad++; + err_length++; + } + if (done < requests) { + struct data s; + gettimeofday(&c->done, 0); + s.read = c->read; + s.ctime = timedif(c->connect, c->start); + s.time = timedif(c->done, c->start); + stats[done++] = s; + } + c->keepalive = 0; + c->length = 0; + c->gotheader = 0; + c->cbx = 0; + c->read = c->bread = 0; + write_request(c); + c->start = c->connect; /* zero connect time with keep-alive */ + } +} + +/* --------------------------------------------------------- */ + +/* run the tests */ + +static void test(void) +{ + struct timeval timeout, now; + fd_set sel_read, sel_except, sel_write; + int i; + + printf("Benchmarking %s (be patient)...", hostname); + fflush(stdout); + + { + /* get server information */ + struct hostent *he; + he = gethostbyname(hostname); + if (!he) + err("gethostbyname"); + server.sin_family = he->h_addrtype; + server.sin_port = htons(port); + server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0]; + } + + con = malloc(concurrency * sizeof(struct connection)); + memset(con, 0, concurrency * sizeof(struct connection)); + + stats = malloc(requests * sizeof(struct data)); + + FD_ZERO(&readbits); + FD_ZERO(&writebits); + + /* setup request */ + sprintf(request, "GET %s HTTP/1.0\r\n" + "User-Agent: ApacheBench/%s\r\n" + "%s" + "Host: %s\r\n" + "Accept: */*\r\n" + "\r\n", + path, + VERSION, + keepalive ? "Connection: Keep-Alive\r\n" : "", + hostname); + + reqlen = strlen(request); + + /* ok - lets start */ + gettimeofday(&start, 0); + + /* initialise lots of requests */ + for (i = 0; i < concurrency; i++) + start_connect(&con[i]); + + while (done < requests) { + int n; + /* setup bit arrays */ + memcpy(&sel_except, &readbits, sizeof(readbits)); + memcpy(&sel_read, &readbits, sizeof(readbits)); + memcpy(&sel_write, &writebits, sizeof(readbits)); + + /* check for time limit expiry */ + gettimeofday(&now, 0); + if (tlimit && timedif(now, start) > (tlimit * 1000)) { + requests = done; /* so stats are correct */ + output_results(); + } + + /* Timeout of 30 seconds. */ + timeout.tv_sec = 30; + timeout.tv_usec = 0; + n = select(256, &sel_read, &sel_write, &sel_except, &timeout); + if (!n) { + printf("\nServer timed out\n\n"); + exit(1); + } + if (n < 1) + err("select"); + + for (i = 0; i < concurrency; i++) { + int s = con[i].fd; + if (FD_ISSET(s, &sel_except)) { + bad++; + err_except++; + start_connect(&con[i]); + continue; + } + if (FD_ISSET(s, &sel_read)) + read_connection(&con[i]); + if (FD_ISSET(s, &sel_write)) + write_request(&con[i]); + } + if (done >= requests) + output_results(); + } +} + +/* ------------------------------------------------------- */ + +/* display copyright information */ +static void copyright(void) +{ + printf("This is ApacheBench, Version %s\n", VERSION); + printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n"); + printf("Copyright (c) 1998 The Apache Group, http://www.apache.org/\n"); + printf("\n"); +} + +/* display usage information */ +static void usage(char *progname) +{ + fprintf(stderr, "Usage: %s [options] [http://]hostname[:port]/path\n", progname); + fprintf(stderr, "Options are:\n"); + fprintf(stderr, " -n requests Number of requests to perform\n"); + fprintf(stderr, " -c concurrency Number of multiple requests to make\n"); + fprintf(stderr, " -t timelimit Seconds to max. wait for responses\n"); + fprintf(stderr, " -k Use HTTP KeepAlive feature\n"); + fprintf(stderr, " -v Display version and copyright information\n"); + fprintf(stderr, " -h Display usage information (this message)\n"); + exit(EINVAL); +} + +/* ------------------------------------------------------- */ + +/* split URL into parts */ + +static int parse_url(char *url) +{ + char *cp; + char *h; + char *p = NULL; + + if (strlen(url) > 7 && strncmp(url, "http://", 7) == 0) + url += 7; + h = url; + if ((cp = strchr(url, ':')) != NULL) { + *cp++ = '\0'; + p = cp; + url = cp; + } + if ((cp = strchr(url, '/')) == NULL) + return 1; + strcpy(path, cp); + *cp = '\0'; + strcpy(hostname, h); + if (p != NULL) + port = atoi(p); + return 0; +} + +/* ------------------------------------------------------- */ + +extern char *optarg; +extern int optind, opterr, optopt; + +/* sort out command-line args and call test */ +int main(int argc, char **argv) +{ + int c; + optind = 1; + while ((c = getopt(argc, argv, "n:c:t:kvh")) > 0) { + switch (c) { + case 'n': + requests = atoi(optarg); + if (!requests) { + printf("Invalid number of requests\n"); + exit(1); + } + break; + case 'k': + keepalive = 1; + break; + case 'c': + concurrency = atoi(optarg); + break; + case 't': + tlimit = atoi(optarg); + requests = MAX_REQUESTS; /* need to size data array on something */ + break; + case 'v': + copyright(); + exit(0); + break; + case 'h': + usage(argv[0]); + break; + default: + fprintf(stderr, "%s: invalid option `%c'\n", argv[0], c); + usage(argv[0]); + break; + } + } + if (optind != argc-1) { + fprintf(stderr, "%s: wrong number of arguments\n", argv[0]); + usage(argv[0]); + } + + if (parse_url(argv[optind++])) { + fprintf(stderr, "%s: invalid URL\n", argv[0]); + usage(argv[0]); + } + + copyright(); + test(); + exit(0); +} + diff --git a/APACHE_1_3b7/src/support/apachectl b/APACHE_1_3b7/src/support/apachectl new file mode 100755 index 0000000000..510d30ff56 --- /dev/null +++ b/APACHE_1_3b7/src/support/apachectl @@ -0,0 +1,209 @@ +#!/bin/sh +# +# Apache control script designed to allow an easy command line interface +# to controlling Apache. Written by Marc Slemko, 1997/08/23 +# +# The exit codes returned are: +# 0 - operation completed successfully +# 1 - +# 2 - usage error +# 3 - httpd could not be started +# 4 - httpd could not be stopped +# 5 - httpd could not be started during a restart +# 6 - httpd could not be restarted during a restart +# 7 - httpd could not be restarted during a graceful restart +# +# When multiple arguments are given, only the error from the _last_ +# one is reported. Run "apachectl help" for usage info +# +# +# |||||||||||||||||||| START CONFIGURATION SECTION |||||||||||||||||||| +# -------------------- -------------------- +# +# the path to your PID file +PIDFILE=/usr/local/apache/logs/httpd.pid +# +# the path to your httpd binary, including options if necessary +HTTPD='/usr/local/apache/src/httpd' +# +# a command that outputs a formatted text version of the HTML at the +# url given on the command line. Designed for lynx, however other +# programs may work. +LYNX="lynx -dump" +# +# the URL to your server's mod_status status page. If you do not +# have one, then status and fullstatus will not work. +STATUSURL="http://localhost/server-status" +# +# -------------------- -------------------- +# |||||||||||||||||||| END CONFIGURATION SECTION |||||||||||||||||||| + +ERROR=0 +ARGV="$@" +if [ "x$ARGV" = "x" ] ; then + ARGS="help" +fi + +for ARG in $@ $ARGS +do + # check for pidfile + if [ -f $PIDFILE ] ; then + PID=`cat $PIDFILE` + PS=`ps -p $PID 2>/dev/null | tail -1 | grep $PID` + if [ "x$PS" = "x" ]; then + STATUS="httpd (pid $PID?) not running" + RUNNING=0 + else + STATUS="httpd (pid $PID) running" + RUNNING=1 + fi + else + STATUS="httpd (no pid file) not running" + RUNNING=0 + fi + + case $ARG in + start) + if [ $RUNNING -eq 1 ]; then + echo "$0 $ARG: httpd (pid $PID) already running" + continue + fi + if $HTTPD ; then + echo "$0 $ARG: httpd started" + else + echo "$0 $ARG: httpd could not be started" + ERROR=3 + fi + ;; + stop) + if [ $RUNNING -eq 0 ]; then + echo "$0 $ARG: $STATUS" + continue + fi + if kill $PID ; then + echo "$0 $ARG: httpd stopped" + else + echo "$0 $ARG: httpd could not be stopped" + ERROR=4 + fi + ;; + restart) + if [ $RUNNING -eq 0 ]; then + echo "$0 $ARG: httpd not running, trying to start" + if $HTTPD ; then + echo "$0 $ARG: httpd started" + else + echo "$0 $ARG: httpd could not be started" + ERROR=5 + fi + else + if kill -HUP $PID ; then + echo "$0 $ARG: httpd restarted" + else + echo "$0 $ARG: httpd could not be restarted" + ERROR=6 + fi + fi + ;; + graceful) + if [ $RUNNING -eq 0 ]; then + echo "$0 $ARG: httpd not running, trying to start" + if $HTTPD ; then + echo "$0 $ARG: httpd started" + else + echo "$0 $ARG: httpd could not be started" + ERROR=5 + fi + else + if kill -USR1 $PID ; then + echo "$0 $ARG: httpd gracefully restarted" + else + echo "$0 $ARG: httpd could not be restarted" + ERROR=7 + fi + fi + ;; + status) + $LYNX $STATUSURL | awk ' { if (/current process/) { print; exit } else print } ' + ;; + fullstatus) + $LYNX $STATUSURL + ;; + *) + echo "usage: $0 (start|stop|restart|fullstatus|status|graceful|help)" + cat <. +# diff --git a/APACHE_1_3b7/src/support/apachectl.1 b/APACHE_1_3b7/src/support/apachectl.1 new file mode 100644 index 0000000000..e4ffb0f194 --- /dev/null +++ b/APACHE_1_3b7/src/support/apachectl.1 @@ -0,0 +1,122 @@ +.TH apachectl 1 "September 1997" +.\" Copyright (c) 1997-1998 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. +.\" +.\" 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 . +.SH NAME +apachectl \- Apache HTTP server control interface +.SH SYNOPSIS +.B apachectl +\fIcommand\fP [...] +.SH DESCRIPTION +.B apachectl +is a front end to the Apache HyperText Transfer Protocol (HTTP) +server. It is designed to help the administrator control the +functioning of the Apache +.B httpd +daemon. +.PP +.B NOTE: +If your Apache installation uses non-standard paths, you will need to +edit the +.B apachectl +script to set the appropriate paths to your PID file and your +.B httpd +binary. See the comments in the script for details. +.PP +The +.B apachectl +script returns a 0 exit value on success, and >0 if an error +occurs. For more details, view the comments in the script. +.PP +Full documentation for Apache is available at +.B http://www.apache.org/ +. +.SH OPTIONS +The \fIcommand\fP can be any one or more of the following options: +.TP 12 +.BI start +Start the Apache daemon. Gives an error if it is already running. +.TP +.BI stop +Stops the Apache daemon. +.TP +.BI restart +Restarts the Apache daemon by sending it a SIGHUP. If the daemon +is not running, it is started. +.TP +.BI fullstatus +Displays a full status report from +.B mod_status. +For this to work, you need to have mod_status enabled on your server +and a text-based browser such as \fIlynx\fP available on your system. The +URL used to access the status report can be set by editing the +.B STATUSURL +variable in the script. +.TP +.BI status +Displays a brief status report. Similar to the fullstatus option, +except that the list of requests currently being served is omitted. +.TP +.BI graceful +Gracefully restarts the Apache daemon by sending it a SIGUSR1. If +the daemon is not running, it is started. This differs from a +normal restart in that currently open connections are not aborted. +A side effect is that old log files will not be closed immediately. +This means that if used in a log rotation script, a substantial +delay may be necessary to ensure that the old log files are closed +before processing them. +.TP +.BI help +Displays a short help message. +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/apachectl.8 b/APACHE_1_3b7/src/support/apachectl.8 new file mode 100644 index 0000000000..e4ffb0f194 --- /dev/null +++ b/APACHE_1_3b7/src/support/apachectl.8 @@ -0,0 +1,122 @@ +.TH apachectl 1 "September 1997" +.\" Copyright (c) 1997-1998 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. +.\" +.\" 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 . +.SH NAME +apachectl \- Apache HTTP server control interface +.SH SYNOPSIS +.B apachectl +\fIcommand\fP [...] +.SH DESCRIPTION +.B apachectl +is a front end to the Apache HyperText Transfer Protocol (HTTP) +server. It is designed to help the administrator control the +functioning of the Apache +.B httpd +daemon. +.PP +.B NOTE: +If your Apache installation uses non-standard paths, you will need to +edit the +.B apachectl +script to set the appropriate paths to your PID file and your +.B httpd +binary. See the comments in the script for details. +.PP +The +.B apachectl +script returns a 0 exit value on success, and >0 if an error +occurs. For more details, view the comments in the script. +.PP +Full documentation for Apache is available at +.B http://www.apache.org/ +. +.SH OPTIONS +The \fIcommand\fP can be any one or more of the following options: +.TP 12 +.BI start +Start the Apache daemon. Gives an error if it is already running. +.TP +.BI stop +Stops the Apache daemon. +.TP +.BI restart +Restarts the Apache daemon by sending it a SIGHUP. If the daemon +is not running, it is started. +.TP +.BI fullstatus +Displays a full status report from +.B mod_status. +For this to work, you need to have mod_status enabled on your server +and a text-based browser such as \fIlynx\fP available on your system. The +URL used to access the status report can be set by editing the +.B STATUSURL +variable in the script. +.TP +.BI status +Displays a brief status report. Similar to the fullstatus option, +except that the list of requests currently being served is omitted. +.TP +.BI graceful +Gracefully restarts the Apache daemon by sending it a SIGUSR1. If +the daemon is not running, it is started. This differs from a +normal restart in that currently open connections are not aborted. +A side effect is that old log files will not be closed immediately. +This means that if used in a log rotation script, a substantial +delay may be necessary to ensure that the old log files are closed +before processing them. +.TP +.BI help +Displays a short help message. +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/apxs.8 b/APACHE_1_3b7/src/support/apxs.8 new file mode 100644 index 0000000000..904f26417f --- /dev/null +++ b/APACHE_1_3b7/src/support/apxs.8 @@ -0,0 +1,398 @@ +.TH apxs 8 "April 1998" +.\" Copyright (c) 1998 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. +.\" +.\" 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 . +.SH NAME +apxs \- APache eXtenSion tool +.SH SYNOPSIS +.B apxs +.B \-g +.BI \-n " modname" + +.B apxs +.B \-q +.IR query " ..." + +.B apxs +.B \-c +[ +.BI \-o " dsofile" +] +[ +.BI \-I " incdir" +] +[ +.BI \-D " name=value" +] +[ +.BI \-L " libdir" +] +[ +.BI \-l " libname" +] +.IR files " ..." + +.B apxs +.B \-i +[ +.BI \-n " modname" +] +[ +.B \-a +] +[ +.B \-A +] +.IR dsofile " ..." +.PP +.SH DESCRIPTION +.B apxs +is a tool for building and installing extension modules for the Apache +HyperText Transfer Protocol (HTTP) server. This is achieved by building a +dynamic shared object (DSO) from one or more source or object +.I files +which then can be loaded into +the Apache server under runtime via the +.B LoadModule +directive from +.BR mod_so. + +So to use this extension mechanism your platform has +to support the DSO feature and your +Apache +.B httpd +binary has to be built with the +.B mod_so +module. +The +.B apxs +tool automatically complains if this is not the case. +You can check this yourself by manually running the command + +.nf + $ httpd -l +.fi + +The module +.B mod_so +should be part of the displayed list. +If these requirements are fulfilled you can easily extend +your Apache server's functionality by installing your own +modules with the DSO mechanism by the help of this +.B apxs +tool: + +.nf + $ apxs -i -a -c mod_foo.c + gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c + ld -Bshareable -o mod_foo.so mod_foo.o + cp mod_foo.so /path/to/apache/libexec/mod_foo.so + chmod 755 /path/to/apache/libexec/mod_foo.so + [activating module `foo' in /path/to/apache/etc/httpd.conf] + $ apachectl restart + /path/to/apache/sbin/apachectl restart: httpd not running, trying to start + [Tue Mar 31 11:27:55 1998] [debug] mod_so.c(303): loaded module foo_module + /path/to/apache/sbin/apachectl restart: httpd started + $ _ +.fi + +The arguments +.I files +can be any C source file (.c), a object file (.o) or +even a library archive (.a). The +.B apxs +tool automatically recognizes these extensions and automtaically used the C +source files for compilation while just using the object and archive files for +the linking phase. But when using such pre-compiled objects make sure they are +compiled for position independend code (PIC) to be able to use them for a +dynamically loaded shared object. +For instance with GCC you always just have to use +.BR -fpic . +For other +C compilers consult its manual +page or at watch for the flags +.B apxs +uses to compile the object files. + +For more details about DSO support in Apache read the documentation +of +.B mod_so +or perhaps even read the +.B src/modules/standard/mod_so.c +source file. + +.PP +.SH OPTIONS +Common options: +.TP 12 +.BI \-n " modname" +This explicitly sets the module name for the +.B \-i +(install) +and +.B \-g +(template generation) option. Use this to explicitly specify the module name. +For option +.B \-g +this is required, for option +.B \-i +the +.B apxs +tool tries to determine the name from the source or (as a fallback) at least +by guessing it from the filename. +.PP +Query options: +.TP 12 +.B \-q +Performs a query for +.BR apxs 's +knowledge about certain settings. The +.I query +parameters can be one or more of the following strings: +.nf + CC PREFIX + LD SBINDIR + CFLAGS INCLUDEDIR + CFLAGS_SHLIB LIBEXECDIR + LDFLAGS_SHLIB SYSCONFDIR +.fi +Use this for manually determining settings. For instance use +.nf + INC=-I`apxs -q INCLUDEDIR` +.fi +inside your own Makefiles if you need manual access +to Apache's C header files. +.PP +Template Generation options: +.TP 12 +.B \-g +This generates a subdirectory +.I name +(see option +.BR \-n ")" +and there two files: A sample module source file named +.BI mod_ name.c +which can be used as a template for creating your own modules or +as a quick start for playing with the APXS mechanism. +And a corresponding +.B Makefile +for even easier build and installing of this module. +.PP +DSO compilation options: +.TP 12 +.B \-c +This indicates the compilation operation. It first compiles the C source +files (.c) of +.I files +into corresponding object files (.o) and then builds a dynamically shared object in +.I dsofile +by linking these object files plus the remaining +object files (.o and .a) of +.I files +If no +.B \-o +option is specified +the output file is guessed from the first filename in +.I files +and thus usually defaults to +.BI mod_ name.so +.TP 12 +.BI \-o " dsofile" +Explicitly specifies the filename of the created dynamically shared object. If +not specified and the name cannot be guessed from the +.I files +list, the fallback name +.B mod_unknown.so +is used. +.TP 12 +.BI \-D " name=value" +This option is directly passed through to the compilation command(s). +Use this to add your own defines to the build process. +.TP 12 +.BI \-I " incdir" +This option is directly passed through to the compilation command(s). +Use this to add your own include directories to search to the build process. +.TP 12 +.BI \-L " libdir" +This option is directly passed through to the linker command. +Use this to add your own library directories to search to the build process. +.TP 12 +.BI \-l " libname" +This option is directly passed through to the linker command. +Use this to add your own libraries to search to the build process. +.PP +DSO installation options: +.TP 12 +.B \-i +This indicates the installation operartion and installs one or more +dynamically shared objects into the +servers +.I libexec +directory. +.TP 12 +.B \-a +This additionally activates the module +by automatically adding a corresponding +.B LoadModule +line to Apache's +.B httpd.conf +configuration file (only if still no such entry exists). +.TP 12 +.B \-A +Same as option +.B \-a +but the created +.B LoadModule +directive is +prefixed with a hash sign (#), i.e. the module is +just prepared for later activation but initially disabled. +.PD +.SH EXAMPLES +Assume you have an Apache module named mod_foo.c available which should extend +Apache's server functionality. To accomplish this you first have to compile +the C source into a shared object suitable for loading into the Apache server +under runtime via the following command: + +.nf + $ apxs -c mod_foo.c + gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c + ld -Bshareable -o mod_foo.so mod_foo.o + $ _ +.fi + +Then you have to update the Apache configuration by making sure a +.B LoadModule +directive is present to load this shared object. To simplify this +step +.B apxs +provides an automatic way to install the shared object in its +"libexec" directory and updating the +.B httpd.conf +file accordingly. This can be achieved by running: + +.nf + $ apxs -i -a mod_foo.c + cp mod_foo.so /path/to/apache/libexec/mod_foo.so + chmod 755 /path/to/apache/libexec/mod_foo.so + [activating module `foo' in /path/to/apache/etc/httpd.conf] + $ _ +.fi + +This way a line named + +.nf + LoadModule foo_module libexec/mod_foo.so +.fi + +is added to the configuration file if still not present. +If you want to have this this disabled per default use the +.B \-A +option, i.e. + +.nf + $ apxs -i -A mod_foo.c +.fi + +For a quick test of the APXS mechanism you can create a sample Apache module +template plus a corresponding Makefile via: + +.nf + $ apxs -g -n foo + Creating [DIR] foo + Creating [FILE] foo/Makefile + Creating [FILE] foo/mod_foo.c + $ _ +.fi + +Then you can immediately compile this sample module into a shared object and +load it into the Apache server: + +.nf + $ cd foo + $ make all reload + apxs -c mod_foo.c + gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c + ld -Bshareable -o mod_foo.so mod_foo.o + apxs -i -a -n "foo" mod_foo.so + cp mod_foo.so /path/to/apache/libexec/mod_foo.so + chmod 755 /path/to/apache/libexec/mod_foo.so + [activating module `foo' in /path/to/apache/etc/httpd.conf] + apachectl restart + /path/to/apache/sbin/apachectl restart: httpd not running, trying to start + [Tue Mar 31 11:27:55 1998] [debug] mod_so.c(303): loaded module foo_module + /path/to/apache/sbin/apachectl restart: httpd started + $ _ +.fi + +You can even use +.B apxs +to compile complex modules outside the Apache source tree, like PHP3: + +.nf + $ cd php3 + $ ./configure --with-shared-apache=../apache-1.3 + $ apxs -c -o libphp3.so mod_php3.c libmodphp3-so.a + gcc -fpic -DSHARED_MODULE -I/tmp/apache/include -c mod_php3.c + ld -Bshareable -o libphp3.so mod_php3.o libmodphp3-so.a + $ _ +.fi + +because +.B apxs +automatically recognized C source files and object files. Only C source files +are compiled while remaining object files are used for the linking phase. + +.PD +.SH SEE ALSO +.BR apachectl(1), +.BR httpd(8). +. diff --git a/APACHE_1_3b7/src/support/apxs.pl b/APACHE_1_3b7/src/support/apxs.pl new file mode 100644 index 0000000000..b22ac2ee2b --- /dev/null +++ b/APACHE_1_3b7/src/support/apxs.pl @@ -0,0 +1,599 @@ +#!/usr/local/bin/perl +## ==================================================================== +## Copyright (c) 1998 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 . +## + +## +## apxs -- APache eXtenSion tool +## Written by Ralf S. Engelschall +## + +require 5.003; +use strict; +package apxs; + +## +## Configuration +## + +my $CFG_CC = '@CC@'; # substituted via Makefile.tmpl +my $CFG_CFLAGS = '@CFLAGS@'; # substituted via Makefile.tmpl +my $CFG_CFLAGS_SHLIB = '@CFLAGS_SHLIB@'; # substituted via Makefile.tmpl +my $CFG_LD_SHLIB = '@LD_SHLIB@'; # substituted via Makefile.tmpl +my $CFG_LDFLAGS_SHLIB = '@LDFLAGS_SHLIB@'; # substituted via Makefile.tmpl +my $CFG_PREFIX = '@prefix@'; # substituted via APACI install +my $CFG_SBINDIR = '@sbindir@'; # substituted via APACI install +my $CFG_INCLUDEDIR = '@includedir@'; # substituted via APACI install +my $CFG_LIBEXECDIR = '@libexecdir@'; # substituted via APACI install +my $CFG_SYSCONFDIR = '@sysconfdir@'; # substituted via APACI install + +## +## Cleanup the above stuff +## +$CFG_CFLAGS =~ s|^\s+||; +$CFG_CFLAGS =~ s|\s+$||; +$CFG_CFLAGS =~ s|\s+`.+apaci`||; + +## +## Initial shared object support check +## +if (not grep(/mod_so/, `$CFG_SBINDIR/httpd -l`)) { + print STDERR "apxs:Error: Sorry, no shared object support for Apache\n"; + print STDERR "apxs:Error: available under your platform. Make sure\n"; + print STDERR "apxs:Error: the Apache module mod_so is compiled into\n"; + print STDERR "apxs:Error: your server binary `$CFG_SBINDIR/httpd'.\n"; + exit(1); +} + +## +## parse argument line +## + +# defaults for parameters +my $opt_n = ''; +my $opt_g = ''; +my $opt_c = 0; +my $opt_o = ''; +my @opt_D = (); +my @opt_I = (); +my @opt_L = (); +my @opt_l = (); +my $opt_i = 0; +my $opt_a = 0; +my $opt_A = 0; +my $opt_q = 0; + +# this subroutine is derived from Perl's getopts.pl with the enhancement of +# the "+" metacharater at the format string to allow a list to be build by +# subsequent occurance of the same option. +sub Getopts { + my ($argumentative, @ARGV) = @_; + my (@args, $first, $rest, $pos); + my ($errs) = 0; + local ($_); + local ($[) = 0; + + @args = split( / */, $argumentative); + while(@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) { + ($first, $rest) = ($1,$2); + if ($_ =~ m|^--$|) { + shift(@ARGV); + last; + } + $pos = index($argumentative,$first); + if($pos >= $[) { + if($args[$pos+1] eq ':') { + shift(@ARGV); + if($rest eq '') { + unless (@ARGV) { + print STDERR "apxs:Error: Incomplete option: $first (needs an argument)\n"; + ++$errs; + } + $rest = shift(@ARGV); + } + eval "\$opt_$first = \$rest;"; + } + elsif ($args[$pos+1] eq '+') { + shift(@ARGV); + if($rest eq '') { + unless (@ARGV) { + print STDERR "apxs:Error: Incomplete option: $first (needs an argument)\n"; + ++$errs; + } + $rest = shift(@ARGV); + } + eval "push(\@opt_$first, \$rest);"; + } + else { + eval "\$opt_$first = 1"; + if($rest eq '') { + shift(@ARGV); + } + else { + $ARGV[0] = "-$rest"; + } + } + } + else { + print STDERR "apxs:Error: Unknown option: $first\n"; + ++$errs; + if($rest ne '') { + $ARGV[0] = "-$rest"; + } + else { + shift(@ARGV); + } + } + } + return ($errs == 0, @ARGV); +} + +sub usage { + print STDERR "Usage: apxs -g -n \n"; + print STDERR " apxs -q ...\n"; + print STDERR " apxs -c [-o ] [-D [=]] [-I ]\n"; + print STDERR " [-L ] [-l ] ...\n"; + print STDERR " apxs -i [-a] [-n ] ...\n"; + exit(1); +} + +# option handling +my $rc; +($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+iaA", @ARGV); +&usage if ($rc == 0); +&usage if ($#ARGV == -1 and not $opt_g); +&usage if (not $opt_q and not ($opt_g and $opt_n) and not $opt_i and not $opt_c); + +# argument handling +my @args = @ARGV; +my $name = 'unknown'; +$name = $opt_n if ($opt_n ne ''); + +## +## Operation +## + +# helper function for executing a list of +# system command with return code checks +sub execute_cmds { + my (@cmds) = @_; + my ($cmd, $rc); + + foreach $cmd (@cmds) { + print STDERR "$cmd\n"; + $rc = system("$cmd"); + if ($rc != 0) { + printf(STDERR "apxs:Break: Command failed with rc=%d\n", $rc << 8); + exit(1); + } + } +} + +if ($opt_g) { + ## + ## SAMPLE MODULE SOURCE GENERATION + ## + + if (-d $name) { + print STDERR "apxs:Error: Directory `$name' already exists. Remove first\n"; + exit(1); + } + + my $data = join('', ); + $data =~ s|%NAME%|$name|sg; + + my ($mkf, $src) = ($data =~ m|^(.+)-=#=-\n(.+)|s); + + print STDERR "Creating [DIR] $name\n"; + system("mkdir $name"); + print STDERR "Creating [FILE] $name/Makefile\n"; + open(FP, ">${name}/Makefile") || die; + print FP $mkf; + close(FP); + print STDERR "Creating [FILE] $name/mod_$name.c\n"; + open(FP, ">${name}/mod_${name}.c") || die; + print FP $src; + close(FP); + + exit(0); +} + + +if ($opt_q) { + ## + ## QUERY INFORMATION + ## + + my $result = ''; + my $arg; + foreach $arg (@args) { + my $ok = 0; + my $name; + foreach $name (qw( + CC LD_SHLIB CFLAGS CFLAGS_SHLIB LDFLAGS_SHLIB + PREFIX SBINDIR INCLUDEDIR LIBEXECDIR SYSCONFDIR + )) { + if ($arg eq $name or $arg eq lc($name)) { + my $val = eval "\$CFG_$name"; + $result .= "${val}::"; + $ok = 1; + } + } + if (not $ok) { + printf(STDERR "apxs:Error: Invalid query string `%s'\n", $arg); + exit(1); + } + } + $result =~ s|::$||; + $result =~ s|::| |; + print $result; +} + +if ($opt_c) { + ## + ## SHARED OBJECT COMPILATION + ## + + # split files into sources and objects + my @srcs = (); + my @objs = (); + my $f; + foreach $f (@args) { + if ($f =~ m|\.c$|) { + push(@srcs, $f); + } + else { + push(@objs, $f); + } + } + + # determine output file + my $dso_file; + if ($opt_o eq '') { + if ($#srcs > -1) { + $dso_file = $srcs[0]; + $dso_file =~ s|\.[^.]+$|.so|; + } + elsif ($#objs > -1) { + $dso_file = $objs[0]; + $dso_file =~ s|\.[^.]+$|.so|; + } + else { + $dso_file = "mod_unknown.so"; + } + } + else { + $dso_file = $opt_o; + } + + # create compilation commands + my @cmds = (); + my $opt = ''; + my ($opt_I, $opt_D); + foreach $opt_I (@opt_I) { + $opt .= "-I$opt_I "; + } + foreach $opt_D (@opt_D) { + $opt .= "-D$opt_D "; + } + my $cflags = "$CFG_CFLAGS $CFG_CFLAGS_SHLIB"; + my $s; + foreach $s (@srcs) { + my $o = $s; + $o =~ s|\.c$|.o|; + push(@cmds, "$CFG_CC $cflags -I$CFG_INCLUDEDIR $opt -c $s"); + unshift(@objs, $o); + } + + # create link command + my $cmd = "$CFG_LD_SHLIB $CFG_LDFLAGS_SHLIB -o $dso_file"; + my $o; + foreach $o (@objs) { + $cmd .= " $o"; + } + $opt = ''; + my ($opt_L, $opt_l); + foreach $opt_L (@opt_L) { + $opt .= " -L$opt_L"; + } + foreach $opt_l (@opt_l) { + $opt .= " -l$opt_l"; + } + $cmd .= $opt; + push(@cmds, $cmd); + + # execute the commands + &execute_cmds(@cmds); + + # allow one-step compilation and installation + if ($opt_i) { + @args = ( $dso_file ); + } +} + +if ($opt_i) { + ## + ## SHARED OBJECT INSTALLATION + ## + + # determine installation commands + # and corresponding LoadModule/AddModule directives + my @lmd = (); + my @amd = (); + my @cmds = (); + my $f; + foreach $f (@args) { + if ($f !~ m|\.so$|) { + print STDERR "apxs:Error: file $f is not a shared object\n"; + exit(1); + } + my $t = $f; + $t =~ s|^.+/([^/]+)$|$1|; + push(@cmds, "cp $f $CFG_LIBEXECDIR/$t"); + push(@cmds, "chmod 755 $CFG_LIBEXECDIR/$t"); + + # determine module symbolname and filename + my $filename = ''; + if ($name eq 'unknown') { + $name = ''; + my $base = $f; + $base =~ s|\.[^.]+$||; + if (-f "$base.c") { + open(FP, "<$base.c"); + my $content = join('', ); + close(FP); + if ($content =~ m|.*module\s+(?:MODULE_VAR_EXPORT\s+)?([a-zA-Z0-9_]+)_module\s*=\s*.*|s) { + $name = "$1"; + $filename = "$base.c"; + $filename =~ s|^[^/]+/||; + } + } + if ($name eq '') { + if ($base =~ m|.*mod_([a-zA-Z0-9_]+)\..+|) { + $name = "$1"; + $filename = $base; + $filename =~ s|^[^/]+/||; + } + } + if ($name eq '') { + print "apxs:Error: Sorry, cannot determine bootstrap symbol name\n"; + print "apxs:Error: Please specify one with option `-n'\n"; + exit(1); + } + } + if ($filename eq '') { + $filename = "mod_${name}.c"; + } + my $dir = $CFG_LIBEXECDIR; + $dir =~ s|^$CFG_PREFIX/?||; + $dir =~ s|(.)$|$1/|; + push(@lmd, sprintf("LoadModule %-18s %s", "${name}_module", "$dir$t")); + push(@amd, sprintf("AddModule %s", $filename)); + } + + # execute the commands + &execute_cmds(@cmds); + + # activate module via LoadModule/AddModule directive + if ($opt_a or $opt_A) { + if (not -f "$CFG_SYSCONFDIR/httpd.conf") { + print "apxs:Error: Config file $CFG_SYSCONFDIR/httpd.conf not found\n"; + exit(1); + } + + open(FP, "<$CFG_SYSCONFDIR/httpd.conf") || die; + my $content = join('', ); + close(FP); + + if ($content !~ m|\n#?\s*LoadModule\s+|) { + print STDERR "apxs:Error: Activation failed for custom $CFG_SYSCONFDIR/httpd.conf file.\n"; + print STDERR "apxs:Error: At least one `LoadModule' directive already has to exist.\n"; + exit(1); + } + + my $update = 0; + my $lmd; + foreach $lmd (@lmd) { + if ($content !~ m|\n#?\s*$lmd|) { + my $c = ''; + $c = '#' if ($opt_A); + $content =~ s|^(.*\n#?\s*LoadModule\s+[^\n]+\n)|$1$c$lmd\n|sg; + $update = 1; + $lmd =~ m|LoadModule\s+(.+?)_module.*|; + my $what = $opt_A ? "preparing" : "activating"; + print STDERR "[$what module `$1' in $CFG_SYSCONFDIR/httpd.conf]\n"; + } + } + my $amd; + foreach $amd (@amd) { + if ($content !~ m|\n#?\s*$amd|) { + my $c = ''; + $c = '#' if ($opt_A); + $content =~ s|^(.*\n#?\s*AddModule\s+[^\n]+\n)|$1$c$amd\n|sg; + $update = 1; + } + } + if ($update) { + open(FP, ">$CFG_SYSCONFDIR/httpd.conf.new") || die; + print FP $content; + close(FP); + system("cp $CFG_SYSCONFDIR/httpd.conf $CFG_SYSCONFDIR/httpd.conf.bak && " . + "cp $CFG_SYSCONFDIR/httpd.conf.new $CFG_SYSCONFDIR/httpd.conf && " . + "rm $CFG_SYSCONFDIR/httpd.conf.new"); + } + } +} + +##EOF## +__DATA__ +## +## Makefile -- Apache for sample %NAME% module +## Autogenerated via ``apxs -n %NAME% -g''. +## + +# additional defines and includes +#DEF=-Dmy_define=my_value +#INC=-Imy/include/dir + +# the default target +all: mod_%NAME%.so + +# compile the shared object file +mod_%NAME%.so: mod_%NAME%.c + apxs -c $(DEF) $(INC) mod_%NAME%.c + +# install the shared object file into Apache +install: all + apxs -i -a -n '%NAME%' mod_%NAME%.so + +# cleanup +clean: + -rm -f mod_%NAME%.o mod_%NAME%.so + +# install and activate shared object by reloading Apache to +# force a reload of the shared object file +reload: install restart + +# the general Apache start/restart/top # procedures +start: + apachectl start +restart: + apachectl restart +stop: + apachectl stop + +-=#=- +/* +** mod_%NAME%.c -- Apache sample %NAME% module +** [Autogenerated via ``apxs -n %NAME% -g''] +** +** To play with this sample module first compile it into a +** DSO file and install it into Apache's libexec directory +** by running: +** +** $ apxs -c -i mod_%NAME%.c +** +** Then activate it in Apache's httpd.conf file for instance +** for the URL /%NAME% in as follows: +** +** # httpd.conf +** LoadModule %NAME%_module libexec/mod_%NAME%.so +** +** SetHandler %NAME% +** +** +** Then after restarting Apache via +** +** $ apachectl restart +** +** you immediately can request the URL /%NAME and watch for the +** output of this module. This can be achieved for instance via: +** +** $ lynx -mime_header http://localhost/%NAME% +** +** The output should be similar to the following one: +** +** HTTP/1.1 200 OK +** Date: Tue, 31 Mar 1998 14:42:22 GMT +** Server: Apache/1.3b6-dev +** Connection: close +** Content-Type: text/html +** +** The sample page from mod_%NAME%.c +*/ + +#include "httpd.h" +#include "http_config.h" +#include "conf.h" + +/* The sample content handler */ +static int %NAME%_handler(request_rec *r) +{ + r->content_type = "text/html"; + ap_send_http_header(r); + if (!r->header_only) + ap_rputs("The sample page from mod_%NAME%.c\n", r); + return OK; +} + +/* Dispatch list of content handlers */ +static const handler_rec %NAME%_handlers[] = { + { "%NAME%", %NAME%_handler }, + { NULL, NULL } +}; + +/* Dispatch list for API hooks */ +module MODULE_VAR_EXPORT %NAME%_module = { + STANDARD_MODULE_STUFF, + NULL, /* module initializer */ + NULL, /* create per-dir config structures */ + NULL, /* merge per-dir config structures */ + NULL, /* create per-server config structures */ + NULL, /* merge per-server config structures */ + NULL, /* table of config file commands */ + %NAME%_handlers, /* [#8] MIME-typed-dispatched handlers */ + NULL, /* [#1] URI to filename translation */ + NULL, /* [#4] validate user id from request */ + NULL, /* [#5] check if the user is ok _here_ */ + NULL, /* [#2] check access by host address */ + NULL, /* [#6] determine MIME type */ + NULL, /* [#7] pre-run fixups */ + NULL, /* [#9] log a transaction */ + NULL, /* [#3] header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* [#0] post read-request */ +}; + diff --git a/APACHE_1_3b7/src/support/dbmmanage b/APACHE_1_3b7/src/support/dbmmanage new file mode 100644 index 0000000000..824cda540d --- /dev/null +++ b/APACHE_1_3b7/src/support/dbmmanage @@ -0,0 +1,189 @@ +#!/usr/local/bin/perl + +# ==================================================================== +# Copyright (c) 1995-1998 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 . + +#for more functionality see the HTTPD::UserAdmin module: +# http://www.perl.com/CPAN/modules/by-module/HTTPD/HTTPD-Tools-x.xx.tar.gz +# +# usage: dbmmanage + +package dbmmanage; +# -ldb -lndbm -lgdbm +BEGIN { @AnyDBM_File::ISA = qw(DB_File NDBM_File GDBM_File) } +use strict; +use Fcntl; +use AnyDBM_File (); + +my($file,$command,$key,$crypted_pwd) = @ARGV; + +usage() unless $file and $command and defined &{$dbmc::{$command}}; + +# if your osname is in $newstyle_salt, then use new style salt (starts with '_' and contains +# four bytes of iteration count and four bytes of salt). Otherwise, just use +# the traditional two-byte salt. +# see the man page on your system to decide if you have a newer crypt() lib. +# I believe that 4.4BSD derived systems do (at least BSD/OS 2.0 does). +# The new style crypt() allows up to 20 characters of the password to be +# significant rather than only 8. +my $newstyle_salt = join '|', qw{bsdos}; #others? + +# remove extension if any +my $chop = join '|', qw{db.? pag dir}; +$file =~ s/\.($chop)$//; + +my $is_update = $command eq "update"; +my $Is_Win32 = $^O eq "MSWin32"; +my %DB = (); +my @range = (); +my($mode, $flags) = $command =~ + /^(?:view|check)$/ ? (undef, O_RDONLY) : (0644, O_RDWR|O_CREAT); + +tie %DB, "AnyDBM_File", $file, $flags, $mode; +dbmc->$command(); +untie %DB; + +sub usage { + my $cmds = join "|", sort keys %dbmc::; + die "usage: $0 filename [$cmds] [username]\n"; +} + +my $x; +sub genseed { + my $psf; + for (qw(-xlwwa -le)) { + `ps $_ 2>/dev/null`; + $psf = $_, last unless $?; + } + srand (time ^ $$ ^ unpack("%L*", `ps $psf | gzip -f`)); + @range = (qw(. /), '0'..'9','a'..'z','A'..'Z'); + $x = int scalar @range; +} + +sub randchar { + join '', map $range[rand $x], 1..shift||1; +} + +sub salt { + my $newstyle = $^O =~ /(?:$newstyle_salt)/; + genseed() unless @range; + return $newstyle ? + join '', "_", randchar, "a..", randchar(4) : + randchar(2); +} + +sub getpass { + my $prompt = shift || "Enter password:"; + + unless($Is_Win32) { + open STDIN, "/dev/tty" or warn "couldn't open /dev/tty $!\n"; + system "stty -echo;"; + } + + my($c,$pwd); + print STDERR $prompt; + while (($c = getc(STDIN)) ne '' and $c ne "\n" and $c ne "\r") { + $pwd .= $c; + } + + system "stty echo" unless $Is_Win32; + print STDERR "\n"; + die "Can't use empty password!\n" unless length $pwd; + return $pwd; +} + +sub dbmc::update { + die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key}; + dbmc->adduser; +} + +sub dbmc::add { + die "Can't use empty password!\n" unless $crypted_pwd; + unless($is_update) { + die "Sorry, user `$key' already exists!\n" if $DB{$key}; + } + $DB{$key} = $crypted_pwd; + my $action = $is_update ? "updated" : "added"; + print "User $key $action with password encrypted to $DB{$key}\n"; +} + +sub dbmc::adduser { + my $value = getpass "New password:"; + die "They don't match, sorry.\n" unless getpass("Re-type new password:") eq $value; + $crypted_pwd = crypt $value, caller->salt; + dbmc->add; +} + +sub dbmc::delete { + die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key}; + delete $DB{$key}, print "`$key' deleted\n"; +} + +sub dbmc::view { + print $key ? "$key:$DB{$key}\n" : map { "$_:$DB{$_}\n" if $DB{$_} } keys %DB; +} + +sub dbmc::check { + die "Sorry, user `$key' doesn't exist!\n" unless $DB{$key}; + print crypt(getpass(), $DB{$key}) eq $DB{$key} ? "password ok\n" : "password mismatch\n"; +} + +sub dbmc::import { + while(defined($_ = ) and chomp) { + ($key,$crypted_pwd) = split /:/, $_, 2; + dbmc->add; + } +} + diff --git a/APACHE_1_3b7/src/support/dbmmanage.1 b/APACHE_1_3b7/src/support/dbmmanage.1 new file mode 100644 index 0000000000..da1f29d866 --- /dev/null +++ b/APACHE_1_3b7/src/support/dbmmanage.1 @@ -0,0 +1,119 @@ +.TH dbmmanage 1 "March 1998" +.\" Copyright (c) 1998 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. +.\" +.\" 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 . +.SH NAME +dbmmanage \- Create and update user authentication files in DBM format +.SH SYNOPSIS +.B dbmmanage +.I filename +[ +.I command +] [ +.I username +] +.PP +.SH DESCRIPTION +.B dbmmanage +is used to create and update the DBM format files used to store +usernames and password for basic authentication of HTTP users. +Resources available from the +.B httpd +Apache web server can be restricted to just the users listed +in the files created by +.B dbmmanage. +This program can only be used +when the usernames are stored in a DBM file. To use a +flat-file database see +\fBhtpasswd\fP. +.PP +This manual page only lists the command line arguments. For details of +the directives necessary to configure user authentication in +.B httpd +see +the Apache manual, which is part of the Apache distribution or can be +found at http://www.apache.org/. +.SH OPTIONS +.IP \fB\fIfilename\fP +The filename of the DBM format file. Usually without the extension .pag or +.dir. +.IP \fB\fIcommand\fP +This selects the operation to perform: +.TP 12 +.B adduser +Asks for a password and then adds an entry for \fIusername\fP to +\fIfilename\fP . +.TP 12 +.B check +Asks for a password and then checks if +\fIusername\fP is in \fIfilename\fP and if it's password matches +the specified one. +.TP 12 +.B delete +Deletes the \fIusername\fP entry from \fIfilename\fP. +.TP 12 +.B import +Reads username:password entries (one per line) from STDIN and adds them to +\fIfilename\fP. The passwords already has to be crypted. +.TP 12 +.B update +Same as the "adduser" command, except that it makes sure \fIusername\fP +already exists in \fIfilename\fP. +.TP 12 +.B view +Just displays the complete contents of the DBM file. +.IP \fB\fIusername\fP +The user for which the update operation is performed. +.PD +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/htdigest.1 b/APACHE_1_3b7/src/support/htdigest.1 new file mode 100644 index 0000000000..3c16d12f5c --- /dev/null +++ b/APACHE_1_3b7/src/support/htdigest.1 @@ -0,0 +1,97 @@ +.TH htdigest 1 "March 1998" +.\" Copyright (c) 1997-1998 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 . +.SH NAME +htdigest \- Create and update user authentication files +.SH SYNOPSIS +.B htdigest +[ +.B \-c +] +.I passwdfile +.I realm +.I username +.SH DESCRIPTION +.B htdigest +is used to create and update the flat-files used to store +usernames, realm and password for digest authentication of HTTP users. +Resources available from the +.B httpd +Apache web server can be restricted to just the users listed +in the files created by +.B htdigest. +.PP +This manual page only lists the command line arguments. For details of +the directives necessary to configure digest authentication in +.B httpd +see +the Apache manual, which is part of the Apache distribution or can be +found at http://www.apache.org/. +.SH OPTIONS +.IP \-c +Create the \fIpasswdfile\fP. If \fIpasswdfile\fP already exists, it +is deleted first. +.IP \fB\fIpasswdfile\fP +Name of the file to contain the username, realm and password. If \-c +is given, this file is created if it does not already exist, +or deleted and recreated if it does exist. +.IP \fB\fIrealm\fP +The realm name to which the user name belongs to. +.IP \fB\fIusername\fP +The user name to create or update in \fBpasswdfile\fP. If +\fIusername\fP does not exist is this file, an entry is added. If it +does exist, the password is changed. +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/htdigest.c b/APACHE_1_3b7/src/support/htdigest.c new file mode 100644 index 0000000000..c992d48806 --- /dev/null +++ b/APACHE_1_3b7/src/support/htdigest.c @@ -0,0 +1,207 @@ +/****************************************************************************** + ****************************************************************************** + * NOTE! This program is not safe as a setuid executable! Do not make it + * setuid! + ****************************************************************************** + *****************************************************************************/ +/* + * htdigest.c: simple program for manipulating digest passwd file for Apache + * + * by Alexei Kosut, based on htpasswd.c, by Rob McCool + */ + +#include "conf.h" +#include +#ifdef MPE +#include +#else +#include +#endif + +/* This is probably the easiest way to do it */ +#include "../main/md5c.c" + +#define LF 10 +#define CR 13 + +#define MAX_STRING_LEN 256 + +char *tn; + +static char *strd(char *s) +{ + char *d; + + d = (char *) malloc(strlen(s) + 1); + strcpy(d, s); + return (d); +} + +static void getword(char *word, char *line, char stop) +{ + int x = 0, y; + + for (x = 0; ((line[x]) && (line[x] != stop)); x++) + word[x] = line[x]; + + word[x] = '\0'; + if (line[x]) + ++x; + y = 0; + + while ((line[y++] = line[x++])); +} + +static int getline(char *s, int n, FILE *f) +{ + register int i = 0; + + while (1) { + s[i] = (char) fgetc(f); + + if (s[i] == CR) + s[i] = fgetc(f); + + if ((s[i] == 0x4) || (s[i] == LF) || (i == (n - 1))) { + s[i] = '\0'; + return (feof(f) ? 1 : 0); + } + ++i; + } +} + +static void putline(FILE *f, char *l) +{ + int x; + + for (x = 0; l[x]; x++) + fputc(l[x], f); + fputc('\n', f); +} + + +static void add_password(char *user, char *realm, FILE *f) +{ + char *pw; + AP_MD5_CTX context; + unsigned char digest[16]; + char string[MAX_STRING_LEN]; + unsigned int i; + + pw = strd((char *) getpass("New password:")); + if (strcmp(pw, (char *) getpass("Re-type new password:"))) { + fprintf(stderr, "They don't match, sorry.\n"); + if (tn) + unlink(tn); + exit(1); + } + fprintf(f, "%s:%s:", user, realm); + + /* Do MD5 stuff */ + sprintf(string, "%s:%s:%s", user, realm, pw); + + ap_MD5Init(&context); + ap_MD5Update(&context, (unsigned char *) string, strlen(string)); + ap_MD5Final(digest, &context); + + for (i = 0; i < 16; i++) + fprintf(f, "%02x", digest[i]); + + fprintf(f, "\n"); +} + +static void usage(void) +{ + fprintf(stderr, "Usage: htdigest [-c] passwordfile realm username\n"); + fprintf(stderr, "The -c flag creates a new file.\n"); + exit(1); +} + +static void interrupted(void) +{ + fprintf(stderr, "Interrupted.\n"); + if (tn) + unlink(tn); + exit(1); +} + +int main(int argc, char *argv[]) +{ + FILE *tfp, *f; + char user[MAX_STRING_LEN]; + char realm[MAX_STRING_LEN]; + char line[MAX_STRING_LEN]; + char l[MAX_STRING_LEN]; + char w[MAX_STRING_LEN]; + char x[MAX_STRING_LEN]; + char command[MAX_STRING_LEN]; + int found; + + tn = NULL; + signal(SIGINT, (void (*)()) interrupted); + if (argc == 5) { + if (strcmp(argv[1], "-c")) + usage(); + if (!(tfp = fopen(argv[2], "w"))) { + fprintf(stderr, "Could not open passwd file %s for writing.\n", + argv[2]); + perror("fopen"); + exit(1); + } + printf("Adding password for %s in realm %s.\n", argv[4], argv[3]); + add_password(argv[4], argv[3], tfp); + fclose(tfp); + exit(0); + } + else if (argc != 4) + usage(); + + tn = tmpnam(NULL); + if (!(tfp = fopen(tn, "w"))) { + fprintf(stderr, "Could not open temp file.\n"); + exit(1); + } + + if (!(f = fopen(argv[1], "r"))) { + fprintf(stderr, + "Could not open passwd file %s for reading.\n", argv[1]); + fprintf(stderr, "Use -c option to create new one.\n"); + exit(1); + } + strcpy(user, argv[3]); + strcpy(realm, argv[2]); + + found = 0; + while (!(getline(line, MAX_STRING_LEN, f))) { + if (found || (line[0] == '#') || (!line[0])) { + putline(tfp, line); + continue; + } + strcpy(l, line); + getword(w, l, ':'); + getword(x, l, ':'); + if (strcmp(user, w) || strcmp(realm, x)) { + putline(tfp, line); + continue; + } + else { + printf("Changing password for user %s in realm %s\n", user, realm); + add_password(user, realm, tfp); + found = 1; + } + } + if (!found) { + printf("Adding user %s in realm %s\n", user, realm); + add_password(user, realm, tfp); + } + fclose(f); + fclose(tfp); +#if defined(__EMX__) || defined(WIN32) + sprintf(command, "copy \"%s\" \"%s\"", tn, argv[1]); +#else + sprintf(command, "cp %s %s", tn, argv[1]); +#endif + system(command); + unlink(tn); + exit(0); +} diff --git a/APACHE_1_3b7/src/support/htpasswd.1 b/APACHE_1_3b7/src/support/htpasswd.1 new file mode 100644 index 0000000000..fdd4c2d8ff --- /dev/null +++ b/APACHE_1_3b7/src/support/htpasswd.1 @@ -0,0 +1,98 @@ +.TH htpasswd 1 "February 1997" +.\" Copyright (c) 1997-1998 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 . +.SH NAME +htpasswd \- Create and update user authentication files +.SH SYNOPSIS +.B htpasswd +[ +.B \-c +] +.I passwdfile +.I username +.SH DESCRIPTION +.B htpasswd +is used to create and update the flat-files used to store +usernames and password for basic authentication of HTTP users. +Resources available from the +.B httpd +Apache web server can be restricted to just the users listed +in the files created by +.B htpasswd. +This program can only be used +when the usernames are stored in a flat-file. To use a +DBM database see +\fBdbmmanage\fP. +.PP +This manual page only lists the command line arguments. For details of +the directives necessary to configure user authentication in +.B httpd +see +the Apache manual, which is part of the Apache distribution or can be +found at http://www.apache.org/. +.SH OPTIONS +.IP \-c +Create the \fIpasswdfile\fP. If \fIpasswdfile\fP already exists, it +is deleted first. +.IP \fB\fIpasswdfile\fP +Name of the file to contain the user name and password. If \-c +is given, this file is created if it does not already exist, +or deleted and recreated if it does exist. +.IP \fB\fIusername\fP +The username to create or update in \fBpasswdfile\fP. If +\fIusername\fP does not exist is this file, an entry is added. If it +does exist, the password is changed. +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/htpasswd.c b/APACHE_1_3b7/src/support/htpasswd.c new file mode 100644 index 0000000000..059e98f829 --- /dev/null +++ b/APACHE_1_3b7/src/support/htpasswd.c @@ -0,0 +1,224 @@ +/****************************************************************************** + ****************************************************************************** + * NOTE! This program is not safe as a setuid executable! Do not make it + * setuid! + ****************************************************************************** + *****************************************************************************/ +/* + * htpasswd.c: simple program for manipulating password file for NCSA httpd + * + * Rob McCool + */ + +#include "conf.h" +#include +#include + +#ifndef CHARSET_EBCDIC +#define LF 10 +#define CR 13 +#else /*CHARSET_EBCDIC*/ +#define LF '\n' +#define CR '\r' +#endif /*CHARSET_EBCDIC*/ + +#define MAX_STRING_LEN 256 + +char *tn; + +static char *strd(char *s) +{ + char *d; + + d = (char *) malloc(strlen(s) + 1); + strcpy(d, s); + return (d); +} + +static void getword(char *word, char *line, char stop) +{ + int x = 0, y; + + for (x = 0; ((line[x]) && (line[x] != stop)); x++) + word[x] = line[x]; + + word[x] = '\0'; + if (line[x]) + ++x; + y = 0; + + while ((line[y++] = line[x++])); +} + +static int getline(char *s, int n, FILE *f) +{ + register int i = 0; + + while (1) { + s[i] = (char) fgetc(f); + + if (s[i] == CR) + s[i] = fgetc(f); + + if ((s[i] == 0x4) || (s[i] == LF) || (i == (n - 1))) { + s[i] = '\0'; + return (feof(f) ? 1 : 0); + } + ++i; + } +} + +static void putline(FILE *f, char *l) +{ + int x; + + for (x = 0; l[x]; x++) + fputc(l[x], f); + fputc('\n', f); +} + + +/* From local_passwd.c (C) Regents of Univ. of California blah blah */ +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void to64(register char *s, register long v, register int n) +{ + while (--n >= 0) { + *s++ = itoa64[v & 0x3f]; + v >>= 6; + } +} + +#ifdef MPE +/* MPE lacks getpass() and a way to suppress stdin echo. So for now, just + * issue the prompt and read the results with echo. (Ugh). + */ + +static char *getpass(const char *prompt) +{ + + static char password[81]; + + fputs(prompt, stderr); + gets((char *) &password); + + if (strlen((char *) &password) > 8) { + password[8] = '\0'; + } + + return (char *) &password; +} + +#endif + +static void add_password(char *user, FILE *f) +{ + char *pw, *cpw, salt[3]; + + pw = strd((char *) getpass("New password:")); + if (strcmp(pw, (char *) getpass("Re-type new password:"))) { + fprintf(stderr, "They don't match, sorry.\n"); + if (tn) + unlink(tn); + exit(1); + } + (void) srand((int) time((time_t *) NULL)); + to64(&salt[0], rand(), 2); + salt[2] = '\0'; + cpw = (char *)crypt(pw, salt); + free(pw); + fprintf(f, "%s:%s\n", user, cpw); +} + +static void usage(void) +{ + fprintf(stderr, "Usage: htpasswd [-c] passwordfile username\n"); + fprintf(stderr, "The -c flag creates a new file.\n"); + exit(1); +} + +static void interrupted(void) +{ + fprintf(stderr, "Interrupted.\n"); + if (tn) + unlink(tn); + exit(1); +} + +int main(int argc, char *argv[]) +{ + FILE *tfp, *f; + char user[MAX_STRING_LEN]; + char line[MAX_STRING_LEN]; + char l[MAX_STRING_LEN]; + char w[MAX_STRING_LEN]; + char command[MAX_STRING_LEN]; + int found; + + tn = NULL; + signal(SIGINT, (void (*)()) interrupted); + if (argc == 4) { + if (strcmp(argv[1], "-c")) + usage(); + if (!(tfp = fopen(argv[2], "w"))) { + fprintf(stderr, "Could not open passwd file %s for writing.\n", + argv[2]); + perror("fopen"); + exit(1); + } + printf("Adding password for %s.\n", argv[3]); + add_password(argv[3], tfp); + fclose(tfp); + exit(0); + } + else if (argc != 3) + usage(); + + tn = tmpnam(NULL); + if (!(tfp = fopen(tn, "w"))) { + fprintf(stderr, "Could not open temp file.\n"); + exit(1); + } + + if (!(f = fopen(argv[1], "r"))) { + fprintf(stderr, + "Could not open passwd file %s for reading.\n", argv[1]); + fprintf(stderr, "Use -c option to create new one.\n"); + exit(1); + } + strcpy(user, argv[2]); + + found = 0; + while (!(getline(line, MAX_STRING_LEN, f))) { + if (found || (line[0] == '#') || (!line[0])) { + putline(tfp, line); + continue; + } + strcpy(l, line); + getword(w, l, ':'); + if (strcmp(user, w)) { + putline(tfp, line); + continue; + } + else { + printf("Changing password for user %s\n", user); + add_password(user, tfp); + found = 1; + } + } + if (!found) { + printf("Adding user %s\n", user); + add_password(user, tfp); + } + fclose(f); + fclose(tfp); +#if defined(__EMX__) || defined(WIN32) + sprintf(command, "copy \"%s\" \"%s\"", tn, argv[1]); +#else + sprintf(command, "cp %s %s", tn, argv[1]); +#endif + system(command); + unlink(tn); + exit(0); +} diff --git a/APACHE_1_3b7/src/support/httpd.8 b/APACHE_1_3b7/src/support/httpd.8 new file mode 100644 index 0000000000..6a7a7eaf44 --- /dev/null +++ b/APACHE_1_3b7/src/support/httpd.8 @@ -0,0 +1,190 @@ +.TH httpd 8 "February 1997" +.\" Copyright (c) 1995-1997 David Robinson. All rights reserved. +.\" Copyright (c) 1997-1998 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 . +.SH NAME +httpd \- Apache hypertext transfer protocol server +.SH SYNOPSIS +.B httpd +[ +.B \-X +] [ +.BI \-L " libexecdir" +] [ +.BI \-d " serverroot" +] [ +.BI \-f " config" +] [ +.BI \-C " directive" +] [ +.BI \-c " directive" +] + +.B httpd +[ +.B \-h +] +[ +.B \-l +] +[ +.B \-v +] +[ +.B \-V +] +[ +.B \-S +] +[ +.B \-? +] + +.SH DESCRIPTION +.B httpd +is the Apache HyperText Transfer Protocol (HTTP) server program. It is +designed to be run as a standalone daemon process. When used like this +is will create a pool of child processes to handle requests. To stop +it, send a TERM signal to the initial (parent) process. The PID of +this process is written to a file as given in the configuration file. +Alternatively +.B httpd +may be invoked by the Internet daemon inetd(8) each +time a connection to the HTTP service is made. +.PP +This manual page only lists the command line arguments. For details +of the directives necessary to configure +.B httpd +see the Apache manual, +which is part of the Apache distribution or can be found at +http://www.apache.org/. Paths in this manual may not reflect those +compiled into +.B httpd. +.SH OPTIONS +.TP 12 +.BI \-L " libexecdir" +This option is only available if Apache was built with +the +.I SHARED_CORE +rule enabled which forces the Apache core code to be +placed into a dynamic shared object (DSO) file. This file +is searched in a hardcoded path under ServerRoot per default. Use this +option if you want to override it. +.TP 12 +.BI \-d " serverroot" +Set the initial value for the ServerRoot directive to \fIserverroot\fP. This +can be overridden by the ServerRoot command in the configuration file. The +default is \fB/usr/local/apache\fP. +.TP +.BI \-f " config" +Execute the commands in the file \fIconfig\fP on startup. If \fIconfig\fP +does not begin with a /, then it is taken to be a path relative to +the ServerRoot. The default is \fBconf/httpd.conf\fP. +.TP +.BI \-C " directive" +Process the configuration \fIdirective\fP before reading config files. +.TP +.BI \-c " directive" +Process the configuration \fIdirective\fP after reading config files. +.TP +.B \-h +Output a list of directives together with expected arguments and +places where the directive is valid. +.TP +.B \-l +Output a list of modules compiled into the server. +.TP +.B \-S +Show the settings as parsed from the config file (currently only shows the +virtualhost settings). +.TP +.B \-X +Run in single-process mode, for internal debugging purposes only; the daemon +does not detach from the terminal or fork any children. Do NOT use this mode +to provide ordinary web service. +.TP +.B \-v +Print the version of +.B httpd +, and then exit. +.TP +.B \-V +Print the version and build parameters of +.B httpd +, and then exit. +.TP +.B \-? +Print a list of the +.B httpd +options, and then exit. +.SH FILES +.PD 0 +.B /usr/local/apache/conf/httpd.conf +.br +.B /usr/local/apache/conf/srm.conf +.br +.B /usr/local/apache/conf/access.conf +.br +.B /usr/local/apache/conf/mime.types +.br +.B /usr/local/apache/conf/magic +.br +.B /usr/local/apache/logs/error_log +.br +.B /usr/local/apache/logs/access_log +.br +.B /usr/local/apache/logs/httpd.pid +.PD +.SH SEE ALSO +.BR inetd (8). diff --git a/APACHE_1_3b7/src/support/httpd.exp b/APACHE_1_3b7/src/support/httpd.exp new file mode 100644 index 0000000000..9358cb2190 --- /dev/null +++ b/APACHE_1_3b7/src/support/httpd.exp @@ -0,0 +1,346 @@ +#! +ap_MD5Final +ap_MD5Init +ap_MD5Update +ap_add_cgi_vars +ap_add_common_vars +ap_add_module +ap_add_named_module +ap_add_per_dir_conf +ap_add_per_url_conf +ap_allow_options +ap_allow_overrides +ap_append_arrays +ap_array_cat +ap_auth_name +ap_auth_type +ap_basic_http_header +ap_bclose +ap_bcreate +ap_bfilbuf +ap_bfileno +ap_bflsbuf +ap_bflush +ap_bgetopt +ap_bgets +ap_bhalfduplex +ap_bind_address +ap_block_alarms +ap_blookc +ap_bnonblock +ap_bonerror +ap_bprintf +ap_bpushfd +ap_bputs +ap_bread +ap_bsetflag +ap_bsetopt +ap_bskiplf +ap_bvputs +ap_bwrite +ap_bytes_in_free_blocks +ap_bytes_in_pool +ap_call_exec +ap_can_exec +ap_cfg_closefile +ap_cfg_getc +ap_cfg_getline +ap_chdir_file +ap_check_access +ap_check_auth +ap_check_cmd_context +ap_check_user_id +ap_checkmask +ap_child_exit_modules +ap_child_init_modules +ap_child_terminate +ap_cleanup_for_exec +ap_clear_module_list +ap_clear_pool +ap_clear_table +ap_close_piped_log +ap_construct_server +ap_construct_url +ap_copy_array +ap_copy_array_hdr +ap_copy_table +ap_core_reorder_directories +ap_coredump_dir +ap_count_dirs +ap_cpystrn +ap_create_environment +ap_create_per_dir_config +ap_create_request_config +ap_daemons_limit +ap_daemons_max_free +ap_daemons_min_free +ap_daemons_to_start +ap_day_snames +ap_default_port_for_request +ap_default_port_for_scheme +ap_default_type +ap_destroy_pool +ap_destroy_sub_req +ap_die +ap_discard_request_body +ap_document_root +ap_dummy_mutex +ap_each_byterange +ap_error_log2stderr +ap_escape_html +ap_escape_path_segment +ap_escape_quotes +ap_escape_shell_cmd +ap_excess_requests_per_child +ap_exists_scoreboard_image +ap_finalize_request_protocol +ap_finalize_sub_req_protocol +ap_find_command +ap_find_command_in_modules +ap_find_last_token +ap_find_linked_module +ap_find_module_name +ap_find_path_info +ap_find_token +ap_find_types +ap_fini_vhost_config +ap_fnmatch +ap_force_library_loading +ap_get_basic_auth_pw +ap_get_client_block +ap_get_gmtoff +ap_get_local_host +ap_get_module_config +ap_get_remote_host +ap_get_remote_logname +ap_get_server_built +ap_get_server_name +ap_get_server_port +ap_get_server_version +ap_get_time +ap_get_token +ap_get_virthost_addr +ap_getparents +ap_getword +ap_getword_conf +ap_getword_conf_nc +ap_getword_nc +ap_getword_nulls +ap_getword_nulls_nc +ap_getword_white +ap_getword_white_nc +ap_gm_timestr_822 +ap_gname2id +ap_group_id +ap_handle_command +ap_hard_timeout +ap_header_parse +ap_ht_time +ap_ind +ap_index_of_response +ap_init_alloc +ap_init_modules +ap_init_vhost_config +ap_init_virtual_host +ap_internal_redirect +ap_internal_redirect_handler +ap_invoke_handler +ap_is_directory +ap_is_fnmatch +ap_is_initial_req +ap_is_matchexp +ap_is_url +ap_keepalive_timeout +ap_kill_cleanup +ap_kill_cleanups_for_fd +ap_kill_cleanups_for_socket +ap_kill_timeout +ap_limit_section +ap_listenbacklog +ap_listeners +ap_lock_fname +ap_log_assert +ap_log_error +ap_log_error_old +ap_log_pid +ap_log_printf +ap_log_reason +ap_log_transaction +ap_log_unixerr +ap_make_array +ap_make_dirstr +ap_make_dirstr_parent +ap_make_dirstr_prefix +ap_make_full_path +ap_make_sub_pool +ap_make_table +ap_matches_request_vhost +ap_max_requests_per_child +ap_md5 +ap_md5contextTo64 +ap_md5digest +ap_meets_conditions +ap_merge_per_dir_configs +ap_month_snames +ap_no2slash +ap_note_auth_failure +ap_note_basic_auth_failure +ap_note_cleanups_for_fd +ap_note_cleanups_for_file +ap_note_cleanups_for_socket +ap_note_digest_auth_failure +ap_note_subprocess +ap_null_cleanup +ap_open_logs +ap_open_piped_log +ap_os_escape_path +ap_os_is_path_absolute +ap_overlay_tables +ap_palloc +ap_parseHTTPdate +ap_parse_hostinfo_components +ap_parse_htaccess +ap_parse_uri +ap_parse_uri_components +ap_parse_vhost_addrs +ap_pcalloc +ap_pcfg_open_custom +ap_pcfg_openfile +ap_pclosedir +ap_pclosef +ap_pclosesocket +ap_pduphostent +ap_pfclose +ap_pfdopen +ap_pfopen +ap_pgethostbyname +ap_pid_fname +ap_popendir +ap_popenf +ap_pregcomp +ap_pregfree +ap_pregsub +ap_prelinked_modules +ap_preloaded_modules +ap_process_request +ap_process_resource_config +ap_psignature +ap_psocket +ap_psprintf +ap_pstrcat +ap_pstrdup +ap_pstrndup +ap_push_array +ap_pvsprintf +ap_rationalize_mtime +ap_read_config +ap_read_request +ap_register_cleanup +ap_register_other_child +ap_remove_module +ap_requires +ap_reset_timeout +ap_response_code_string +ap_restart_time +ap_rfc1413 +ap_rfc1413_timeout +ap_rflush +ap_rind +ap_rprintf +ap_rputc +ap_rputs +ap_run_cleanup +ap_run_fixups +ap_run_post_read_request +ap_run_sub_req +ap_rvputs +ap_rwrite +ap_satisfies +ap_scan_script_header_err +ap_scan_script_header_err_buff +ap_scoreboard_fname +ap_scoreboard_image +ap_send_error_response +ap_send_fb +ap_send_fb_length +ap_send_fd +ap_send_fd_length +ap_send_header_field +ap_send_http_header +ap_send_http_options +ap_send_http_trace +ap_send_mmap +ap_send_size +ap_server_argv0 +ap_server_confname +ap_server_post_read_config +ap_server_pre_read_config +ap_server_root +ap_server_root_relative +ap_set_byterange +ap_set_callback_and_alarm +ap_set_content_length +ap_set_etag +ap_set_file_slot +ap_set_flag_slot +ap_set_keepalive +ap_set_last_modified +ap_set_module_config +ap_set_name_virtual_host +ap_set_string_slot +ap_set_string_slot_lower +ap_set_sub_req_protocol +ap_setup_client_block +ap_setup_prelinked_modules +ap_should_client_block +ap_show_directives +ap_show_modules +ap_signal +ap_slack +ap_snprintf +ap_soft_timeout +ap_some_auth_required +ap_spawn_child_err +ap_spawn_child_err_buff +ap_srm_command_loop +ap_standalone +ap_start_restart +ap_start_shutdown +ap_str_tolower +ap_strcasecmp_match +ap_strcmp_match +ap_sub_req_lookup_file +ap_sub_req_lookup_uri +ap_suexec_enabled +ap_sync_scoreboard_image +ap_table_add +ap_table_addn +ap_table_do +ap_table_get +ap_table_merge +ap_table_mergen +ap_table_set +ap_table_setn +ap_table_unset +ap_threads_per_child +ap_tm2sec +ap_translate_name +ap_uname2id +ap_unblock_alarms +ap_unescape_url +ap_unparse_uri_components +ap_unregister_other_child +ap_update_child_status +ap_update_mtime +ap_update_vhost_from_headers +ap_update_vhost_given_ip +ap_user_id +ap_user_name +ap_util_init +ap_util_uri_init +ap_uudecode +ap_vbprintf +ap_vformatter +ap_vsnprintf +core_module +top_module diff --git a/APACHE_1_3b7/src/support/log_server_status b/APACHE_1_3b7/src/support/log_server_status new file mode 100755 index 0000000000..bbab375002 --- /dev/null +++ b/APACHE_1_3b7/src/support/log_server_status @@ -0,0 +1,115 @@ +#!/usr/local/bin/perl + +# ==================================================================== +# Copyright (c) 1995-1998 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 . + + +# Log Server Status +# Mark J Cox, UK Web Ltd 1996, mark@ukweb.com +# +# This script is designed to be run at a frequent interval by something +# like cron. It connects to the server and downloads the status +# information. It reformats the information to a single line and logs +# it to a file. Make sure the directory $wherelog is writable by the +# user who runs this script. +# +require 'sys/socket.ph'; + +$wherelog = "/var/log/graph/"; # Logs will be like "/var/log/graph/960312" +$server = "localhost"; # Name of server, could be "www.foo.com" +$port = "80"; # Port on server +$request = "/status/?auto"; # Request to send + +sub tcp_connect +{ + local($host,$port) =@_; + $sockaddr='S n a4 x8'; + chop($hostname=`hostname`); + $port=(getservbyname($port, 'tcp'))[2] unless $port =~ /^\d+$/; + $me=pack($sockaddr,&AF_INET,0,(gethostbyname($hostname))[4]); + $them=pack($sockaddr,&AF_INET,$port,(gethostbyname($host))[4]); + socket(S,&PF_INET,&SOCK_STREAM,(getprotobyname('tcp'))[2]) || + die "socket: $!"; + bind(S,$me) || return "bind: $!"; + connect(S,$them) || return "connect: $!"; + select(S); + $| = 1; + select(stdout); + return ""; +} + +### Main + +{ + $date=`date +%y%m%d:%H%M%S`; + chop($date); + ($day,$time)=split(/:/,$date); + $res=&tcp_connect($server,$port); + open(OUT,">>$wherelog$day"); + if ($res) { + print OUT "$time:-1:-1:-1:-1:$res\n"; + exit 1; + } + print S "GET $request\n"; + while () { + $requests=$1 if ( m|^BusyServers:\ (\S+)|); + $idle=$1 if ( m|^IdleServers:\ (\S+)|); + $number=$1 if ( m|sses:\ (\S+)|); + $cpu=$1 if (m|^CPULoad:\ (\S+)|); + } + print OUT "$time:$requests:$idle:$number:$cpu\n"; +} + + diff --git a/APACHE_1_3b7/src/support/logresolve.8 b/APACHE_1_3b7/src/support/logresolve.8 new file mode 100644 index 0000000000..cca3c7a49b --- /dev/null +++ b/APACHE_1_3b7/src/support/logresolve.8 @@ -0,0 +1,87 @@ +.TH logresolve 8 "March 1998" +.\" Copyright (c) 1998 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. +.\" +.\" 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 . +.SH NAME +logresolve \- resolve hostnames for IP-adresses in Apache logfiles +.SH SYNOPSIS +.B logresolve +[ +.BI \-s " filename" +] [ +.B \-c +] < +.I access_log +> +.I access_log.new +.PP +.SH DESCRIPTION +.B logresolve +is a post-processing program to resolve IP-adresses in Apache's access +logfiles. To minimize impact on your nameserver, logresolve has its very own +internal hash-table cache. This means that each IP number will only be looked +up the first time it is found in the log file. +.SH OPTIONS +.TP 12 +.BI \-s " filename" +Specifies a filename to record statistics. +.TP 12 +.B \-c +This causes +.B logresolve +to apply some DNS checks: after finding the hostname from the IP address, it +looks up the IP addresses for the hostname and checks that one of these +matches the original address. +.PD +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/logresolve.c b/APACHE_1_3b7/src/support/logresolve.c new file mode 100644 index 0000000000..1b8e072f30 --- /dev/null +++ b/APACHE_1_3b7/src/support/logresolve.c @@ -0,0 +1,344 @@ +/* + * logresolve 1.1 + * + * Tom Rathborne - tomr@uunet.ca - http://www.uunet.ca/~tomr/ + * UUNET Canada, April 16, 1995 + * + * Rewritten by David Robinson. (drtr@ast.cam.ac.uk) + * + * Usage: logresolve [-s filename] [-c] < access_log > new_log + * + * Arguments: + * -s filename name of a file to record statistics + * -c check the DNS for a matching A record for the host. + * + * Notes: + * + * To generate meaningful statistics from an HTTPD log file, it's good + * to have the domain name of each machine that accessed your site, but + * doing this on the fly can slow HTTPD down. + * + * Compiling NCSA HTTPD with the -DMINIMAL_DNS flag turns IP#->hostname + * resolution off. Before running your stats program, just run your log + * file through this program (logresolve) and all of your IP numbers will + * be resolved into hostnames (where possible). + * + * logresolve takes an HTTPD access log (in the COMMON log file format, + * or any other format that has the IP number/domain name as the first + * field for that matter), and outputs the same file with all of the + * domain names looked up. Where no domain name can be found, the IP + * number is left in. + * + * To minimize impact on your nameserver, logresolve has its very own + * internal hash-table cache. This means that each IP number will only + * be looked up the first time it is found in the log file. + * + * The -c option causes logresolve to apply the same check as httpd + * compiled with -DMAXIMUM_DNS; after finding the hostname from the IP + * address, it looks up the IP addresses for the hostname and checks + * that one of these matches the original address. + */ + +#include "conf.h" +#include + +#include + +#ifndef MPE +#include +#endif + +static void cgethost(struct in_addr ipnum, char *string, int check); +static int getline(char *s, int n); +static void stats(FILE *output); + + +/* maximum line length */ +#define MAXLINE 1024 + +/* maximum length of a domain name */ +#ifndef MAXDNAME +#define MAXDNAME 256 +#endif + +/* number of buckets in cache hash table */ +#define BUCKETS 256 + +#if defined(NEED_STRDUP) +char *strdup (const char *str) +{ + char *dup; + + if (!(dup = (char *) malloc(strlen(str) + 1))) + return NULL; + dup = strcpy(dup, str); + + return dup; +} +#endif + +/* + * struct nsrec - record of nameservice for cache linked list + * + * ipnum - IP number hostname - hostname noname - nonzero if IP number has no + * hostname, i.e. hostname=IP number + */ + +struct nsrec { + struct in_addr ipnum; + char *hostname; + int noname; + struct nsrec *next; +} *nscache[BUCKETS]; + +/* + * statistics - obvious + */ + +/* largeste value for h_errno */ +#define MAX_ERR (NO_ADDRESS) +#define UNKNOWN_ERR (MAX_ERR+1) +#define NO_REVERSE (MAX_ERR+2) + +static int cachehits = 0; +static int cachesize = 0; +static int entries = 0; +static int resolves = 0; +static int withname = 0; +static int errors[MAX_ERR + 3]; + +/* + * cgethost - gets hostname by IP address, caching, and adding unresolvable + * IP numbers with their IP number as hostname, setting noname flag + */ + +static void cgethost (struct in_addr ipnum, char *string, int check) +{ + struct nsrec **current, *new; + struct hostent *hostdata; + char *name; +#ifndef h_errno + extern int h_errno; /* some machines don't have this in their headers */ +#endif + + current = &nscache[((ipnum.s_addr + (ipnum.s_addr >> 8) + + (ipnum.s_addr >> 16) + (ipnum.s_addr >> 24)) % BUCKETS)]; + + while (*current != NULL && ipnum.s_addr != (*current)->ipnum.s_addr) + current = &(*current)->next; + + if (*current == NULL) { + cachesize++; + new = (struct nsrec *) malloc(sizeof(struct nsrec)); + if (new == NULL) { + perror("malloc"); + fprintf(stderr, "Insufficient memory\n"); + exit(1); + } + *current = new; + new->next = NULL; + + new->ipnum = ipnum; + + hostdata = gethostbyaddr((const char *) &ipnum, sizeof(struct in_addr), + AF_INET); + if (hostdata == NULL) { + if (h_errno > MAX_ERR) + errors[UNKNOWN_ERR]++; + else + errors[h_errno]++; + new->noname = h_errno; + name = strdup(inet_ntoa(ipnum)); + } + else { + new->noname = 0; + name = strdup(hostdata->h_name); + if (check) { + if (name == NULL) { + perror("strdup"); + fprintf(stderr, "Insufficient memory\n"); + exit(1); + } + hostdata = gethostbyname(name); + if (hostdata != NULL) { + char **hptr; + + for (hptr = hostdata->h_addr_list; *hptr != NULL; hptr++) + if (((struct in_addr *) (*hptr))->s_addr == ipnum.s_addr) + break; + if (*hptr == NULL) + hostdata = NULL; + } + if (hostdata == NULL) { + fprintf(stderr, "Bad host: %s != %s\n", name, + inet_ntoa(ipnum)); + new->noname = NO_REVERSE; + free(name); + name = strdup(inet_ntoa(ipnum)); + errors[NO_REVERSE]++; + } + } + } + new->hostname = name; + if (new->hostname == NULL) { + perror("strdup"); + fprintf(stderr, "Insufficient memory\n"); + exit(1); + } + } + else + cachehits++; + + /* size of string == MAXDNAME +1 */ + strncpy(string, (*current)->hostname, MAXDNAME); + string[MAXDNAME] = '\0'; +} + +/* + * prints various statistics to output + */ + +static void stats (FILE *output) +{ + int i; + char *ipstring; + struct nsrec *current; + char *errstring[MAX_ERR + 3]; + + for (i = 0; i < MAX_ERR + 3; i++) + errstring[i] = "Unknown error"; + errstring[HOST_NOT_FOUND] = "Host not found"; + errstring[TRY_AGAIN] = "Try again"; + errstring[NO_RECOVERY] = "Non recoverable error"; + errstring[NO_DATA] = "No data record"; + errstring[NO_ADDRESS] = "No address"; + errstring[NO_REVERSE] = "No reverse entry"; + + fprintf(output, "logresolve Statistics:\n"); + + fprintf(output, "Entries: %d\n", entries); + fprintf(output, " With name : %d\n", withname); + fprintf(output, " Resolves : %d\n", resolves); + if (errors[HOST_NOT_FOUND]) + fprintf(output, " - Not found : %d\n", errors[HOST_NOT_FOUND]); + if (errors[TRY_AGAIN]) + fprintf(output, " - Try again : %d\n", errors[TRY_AGAIN]); + if (errors[NO_DATA]) + fprintf(output, " - No data : %d\n", errors[NO_DATA]); + if (errors[NO_ADDRESS]) + fprintf(output, " - No address: %d\n", errors[NO_ADDRESS]); + if (errors[NO_REVERSE]) + fprintf(output, " - No reverse: %d\n", errors[NO_REVERSE]); + fprintf(output, "Cache hits : %d\n", cachehits); + fprintf(output, "Cache size : %d\n", cachesize); + fprintf(output, "Cache buckets : IP number * hostname\n"); + + for (i = 0; i < BUCKETS; i++) + for (current = nscache[i]; current != NULL; current = current->next) { + ipstring = inet_ntoa(current->ipnum); + if (current->noname == 0) + fprintf(output, " %3d %15s - %s\n", i, ipstring, + current->hostname); + else { + if (current->noname > MAX_ERR + 2) + fprintf(output, " %3d %15s : Unknown error\n", i, + ipstring); + else + fprintf(output, " %3d %15s : %s\n", i, ipstring, + errstring[current->noname]); + } + } +} + + +/* + * gets a line from stdin + */ + +static int getline (char *s, int n) +{ + char *cp; + + if (!fgets(s, n, stdin)) + return (0); + cp = strchr(s, '\n'); + if (cp) + *cp = '\0'; + return (1); +} + +int main (int argc, char *argv[]) +{ + struct in_addr ipnum; + char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile; + int i, check; + + check = 0; + statfile = NULL; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-c") == 0) + check = 1; + else if (strcmp(argv[i], "-s") == 0) { + if (i == argc - 1) { + fprintf(stderr, "logresolve: missing filename to -s\n"); + exit(1); + } + i++; + statfile = argv[i]; + } + else { + fprintf(stderr, "Usage: logresolve [-s statfile] [-c] < input > output"); + exit(0); + } + } + + + for (i = 0; i < BUCKETS; i++) + nscache[i] = NULL; + for (i = 0; i < MAX_ERR + 2; i++) + errors[i] = 0; + + while (getline(line, MAXLINE)) { + if (line[0] == '\0') + continue; + entries++; + if (!isdigit(line[0])) { /* short cut */ + puts(line); + withname++; + continue; + } + bar = strchr(line, ' '); + if (bar != NULL) + *bar = '\0'; + ipnum.s_addr = inet_addr(line); + if (ipnum.s_addr == 0xffffffffu) { + if (bar != NULL) + *bar = ' '; + puts(line); + withname++; + continue; + } + + resolves++; + + cgethost(ipnum, hoststring, check); + if (bar != NULL) + printf("%s %s\n", hoststring, bar + 1); + else + puts(hoststring); + } + + if (statfile != NULL) { + FILE *fp; + fp = fopen(statfile, "w"); + if (fp == NULL) { + fprintf(stderr, "logresolve: could not open statistics file '%s'\n" + ,statfile); + exit(1); + } + stats(fp); + fclose(fp); + } + + return (0); +} diff --git a/APACHE_1_3b7/src/support/logresolve.pl b/APACHE_1_3b7/src/support/logresolve.pl new file mode 100644 index 0000000000..06df30d65f --- /dev/null +++ b/APACHE_1_3b7/src/support/logresolve.pl @@ -0,0 +1,264 @@ +#!/usr/local/bin/perl + +# ==================================================================== +# Copyright (c) 1995-1998 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 . + +# logresolve.pl +# +# v 1.2 by robh @ imdb.com +# +# usage: logresolve.pl outfile +# +# input = Apache/NCSA/.. logfile with IP numbers at start of lines +# output = same logfile with IP addresses resolved to hostnames where +# name lookups succeeded. +# +# this differs from the C based 'logresolve' in that this script +# spawns a number ($CHILDREN) of subprocesses to resolve addresses +# concurrently and sets a short timeout ($TIMEOUT) for each lookup in +# order to keep things moving quickly. +# +# the parent process handles caching of IP->hostnames using a Perl hash +# it also avoids sending the same IP to multiple child processes to be +# resolved multiple times concurrently. +# +# Depending on the settings of $CHILDREN and $TIMEOUT you should see +# significant reductions in the overall time taken to resolve your +# logfiles. With $CHILDREN=40 and $TIMEOUT=5 I've seen 200,000 - 300,000 +# logfile lines processed per hour compared to ~45,000 per hour +# with 'logresolve'. +# +# I haven't yet seen any noticable reduction in the percentage of IPs +# that fail to get resolved. Your mileage will no doubt vary. 5s is long +# enough to wait IMO. +# +# Known to work with FreeBSD 2.2 +# Known to have problems with Solaris +# +# 980417 - use 'sockaddr_un' for bind/connect to make the script work +# with linux. Fix from Luuk de Boer + +require 5.004; + +$|=1; + +use FileHandle; +use Socket; + +use strict; +no strict 'refs'; + +use vars qw($PROTOCOL); +$PROTOCOL = 0; + +my $CHILDREN = 40; +my $TIMEOUT = 5; + +my $filename; +my %hash = (); +my $parent = $$; + +my @children = (); +for (my $child = 1; $child <=$CHILDREN; $child++) { + my $f = fork(); + if (!$f) { + $filename = "./.socket.$parent.$child"; + if (-e $filename) { unlink($filename) || warn "$filename .. $!\n";} + &child($child); + exit(0); + } + push(@children, $f); +} + +&parent; +&cleanup; + +## remove all temporary files before shutting down +sub cleanup { + # die kiddies, die + kill(15, @children); + for (my $child = 1; $child <=$CHILDREN; $child++) { + if (-e "./.socket.$parent.$child") { + unlink("./.socket.$parent.$child") + || warn ".socket.$parent.$child $!"; + } + } +} + +sub parent { + # Trap some possible signals to trigger temp file cleanup + $SIG{'KILL'} = $SIG{'INT'} = $SIG{'PIPE'} = \&cleanup; + + my %CHILDSOCK; + my $filename; + + ## fork child processes. Each child will create a socket connection + ## to this parent and use an unique temp filename to do so. + for (my $child = 1; $child <=$CHILDREN; $child++) { + $CHILDSOCK{$child}= FileHandle->new; + + if (!socket($CHILDSOCK{$child}, AF_UNIX, SOCK_STREAM, $PROTOCOL)) { + warn "parent socket to child failed $!"; + } + $filename = "./.socket.$parent.$child"; + my $response; + do { + $response = connect($CHILDSOCK{$child}, sockaddr_un($filename)); + if ($response != 1) { + sleep(1); + } + } while ($response != 1); + $CHILDSOCK{$child}->autoflush; + } + ## All child processes should now be ready or at worst warming up + + my (@buffer, $child, $ip, $rest, $hostname, $response); + ## read the logfile lines from STDIN + while() { + @buffer = (); # empty the logfile line buffer array. + $child = 1; # children are numbered 1..N, start with #1 + + # while we have a child to talk to and data to give it.. + do { + push(@buffer, $_); # buffer the line + ($ip, $rest) = split(/ /, $_, 2); # separate IP form rest + + unless ($hash{$ip}) { # resolve if unseen IP + $CHILDSOCK{$child}->print("$ip\n"); # pass IP to next child + $hash{$ip} = $ip; # don't look it up again. + $child++; + } + } while (($child < ($CHILDREN-1)) and ($_ = )); + + ## now poll each child for a response + while (--$child > 0) { + $response = $CHILDSOCK{$child}->getline; + chomp($response); + # child sends us back both the IP and HOSTNAME, no need for us + # to remember what child received any given IP, and no worries + # what order we talk to the children + ($ip, $hostname) = split(/\|/, $response, 2); + $hash{$ip} = $hostname; + } + + # resolve all the logfiles lines held in the log buffer array.. + for (my $line = 0; $line <=$#buffer; $line++) { + # get next buffered line + ($ip, $rest) = split(/ /, $buffer[$line], 2); + # separate IP from rest and replace with cached hostname + printf STDOUT ("%s %s", $hash{$ip}, $rest); + } + } +} + +######################################## + +sub child { + # arg = numeric ID - how the parent refers to me + my $me = shift; + + # add trap for alarm signals. + $SIG{'ALRM'} = sub { die "alarmed"; }; + + # create a socket to communicate with parent + socket(INBOUND, AF_UNIX, SOCK_STREAM, $PROTOCOL) + || die "Error with Socket: !$\n"; + $filename = "./.socket.$parent.$me"; + bind(INBOUND, sockaddr_un($filename)) + || die "Error Binding $filename: $!\n"; + listen(INBOUND, 5) || die "Error Listening: $!\n"; + + my ($ip, $send_back); + my $talk = FileHandle->new; + + # accept a connection from the parent process. We only ever have + # have one connection where we exchange 1 line of info with the + # parent.. 1 line in (IP address), 1 line out (IP + hostname). + accept($talk, INBOUND) || die "Error Accepting: $!\n"; + # disable I/O buffering just in case + $talk->autoflush; + # while the parent keeps sending data, we keep responding.. + while(($ip = $talk->getline)) { + chomp($ip); + # resolve the IP if time permits and send back what we found.. + $send_back = sprintf("%s|%s", $ip, &nslookup($ip)); + $talk->print($send_back."\n"); + } +} + +# perform a time restricted hostname lookup. +sub nslookup { + # get the IP as an arg + my $ip = shift; + my $hostname = undef; + + # do the hostname lookup inside an eval. The eval will use the + # already configured SIGnal handler and drop out of the {} block + # regardless of whether the alarm occured or not. + eval { + alarm($TIMEOUT); + $hostname = gethostbyaddr(gethostbyname($ip), AF_INET); + alarm(0); + }; + if ($@ =~ /alarm/) { + # useful for debugging perhaps.. + # print "alarming, isn't it? ($ip)"; + } + + # return the hostname or the IP address itself if there is no hostname + $hostname ne "" ? $hostname : $ip; +} + + diff --git a/APACHE_1_3b7/src/support/phf_abuse_log.cgi b/APACHE_1_3b7/src/support/phf_abuse_log.cgi new file mode 100755 index 0000000000..9ce2749c57 --- /dev/null +++ b/APACHE_1_3b7/src/support/phf_abuse_log.cgi @@ -0,0 +1,21 @@ +#!/usr/local/bin/perl + +# This script can be used to detect people trying to abuse the security hole which +# existed in A CGI script direstributed with Apache 1.0.3 and earlier versions. +# You can redirect them to here using the "" suggestion in +# httpd.conf. +# +# The format logged to is "[date] remote_addr remote_host [date] referrer user_agent". + +$LOG = "/var/log/phf_log"; + +require "ctime.pl"; +$when = &ctime(time); +$when =~ s/\n//go; +$ENV{HTTP_USER_AGENT} .= " via $ENV{HTTP_VIA}" if($ENV{HTTP_VIA}); + +open(LOG, ">>$LOG") || die "boo hoo, phf_log $!"; +print LOG "[$when] $ENV{REMOTE_ADDR} $ENV{REMOTE_HOST} $ENV{$HTTP_REFERER} $ENV{HTTP_USER_AGENT}\n"; +close(LOG); + +print "Content-type: text/html\r\n\r\nSmile, you're on Candid Camera.\n"; diff --git a/APACHE_1_3b7/src/support/rotatelogs.8 b/APACHE_1_3b7/src/support/rotatelogs.8 new file mode 100644 index 0000000000..05bd492312 --- /dev/null +++ b/APACHE_1_3b7/src/support/rotatelogs.8 @@ -0,0 +1,83 @@ +.TH rotatelogs 8 "March 1998" +.\" Copyright (c) 1998 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. +.\" +.\" 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 . +.SH NAME +rotatelogs \- rotate Apache logs without having to kill the server +.SH SYNOPSIS +.B rotatelogs +.I logfile +.I rotationtime +.PP +.SH DESCRIPTION +.B rotatelogs +is a simple program for use in conjunction with Apache's piped logfile +feature which can be used like this: + +.fi + TansferLog "|rotatelogs /path/to/logs/access_log 86400" +.mf + +This creates the files /path/to/logs/access_log.nnnn where nnnn is the system +time at which the log nominally starts (this time will always be a multiple of +the rotation time, so you can synchronize cron scripts with it). At the end +of each rotation time (here after 24 hours) a new log is started. +.SH OPTIONS +.IP \fB\fIlogfile\fP +The path plus basename of the logfile. The suffix .nnnn is automatically +added. +.IP \fB\fIrotationtime\fP +The rotation time in seconds. +.PD +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/rotatelogs.c b/APACHE_1_3b7/src/support/rotatelogs.c new file mode 100644 index 0000000000..0bff77ac79 --- /dev/null +++ b/APACHE_1_3b7/src/support/rotatelogs.c @@ -0,0 +1,82 @@ +/* + * Simple program to rotate Apache logs without having to kill the server. + * + * Contributed by Ben Laurie + * + * 12 Mar 1996 + */ + + +#define BUFSIZE 65536 +#define MAX_PATH 1024 + +#include "conf.h" +#include +#include +#include + +int main (int argc, char **argv) +{ + char buf[BUFSIZE], buf2[MAX_PATH]; + time_t tLogEnd = 0; + time_t tRotation; + int nLogFD = -1; + int nRead; + char *szLogRoot; + + if (argc != 3) { + fprintf(stderr, + "%s \n\n", + argv[0]); +#ifdef __EMX__ + fprintf(stderr, + "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n", + argv[0]); +#else + fprintf(stderr, + "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n", + argv[0]); +#endif + fprintf(stderr, + "to httpd.conf. The generated name will be /some/where.nnnn " + "where nnnn is the\nsystem time at which the log nominally " + "starts (N.B. this time will always be a\nmultiple of the " + "rotation time, so you can synchronize cron scripts with it).\n" + "At the end of each rotation time a new log is started.\n"); + exit(1); + } + + szLogRoot = argv[1]; + tRotation = atoi(argv[2]); + if (tRotation <= 0) { + fprintf(stderr, "Rotation time must be > 0\n"); + exit(6); + } + + for (;;) { + nRead = read(0, buf, sizeof buf); + if (nRead == 0) + exit(3); + if (nRead < 0) + if (errno != EINTR) + exit(4); + if (nLogFD >= 0 && (time(NULL) >= tLogEnd || nRead < 0)) { + close(nLogFD); + nLogFD = -1; + } + if (nLogFD < 0) { + time_t tLogStart = (time(NULL) / tRotation) * tRotation; + sprintf(buf2, "%s.%010d", szLogRoot, (int) tLogStart); + tLogEnd = tLogStart + tRotation; + nLogFD = open(buf2, O_WRONLY | O_CREAT | O_APPEND, 0666); + if (nLogFD < 0) { + perror(buf2); + exit(2); + } + } + if (write(nLogFD, buf, nRead) != nRead) { + perror(buf2); + exit(5); + } + } +} diff --git a/APACHE_1_3b7/src/support/split-logfile b/APACHE_1_3b7/src/support/split-logfile new file mode 100644 index 0000000000..84c5504238 --- /dev/null +++ b/APACHE_1_3b7/src/support/split-logfile @@ -0,0 +1,103 @@ +#!/usr/local/bin/perl +# +# ==================================================================== +# Copyright (c) 1995-1998 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 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 . +# + +# +# This script will take a combined Web server access +# log file and break its contents into separate files. +# It assumes that the first field of each line is the +# virtual host identity (put there by "%v"), and that +# the logfiles should be named that+".log" in the current +# directory. +# +# The combined log file is read from stdin. Records read +# will be appended to any existing log files. +# +%is_open = (); + +while ($log_line = ) { + # + # Get the first token from the log record; it's the + # identity of the virtual host to which the record + # applies. + # + ($vhost) = split (/\s/, $log_line); + # + # Normalize the virtual host name to all lowercase. + # If it's blank, the request was handled by the default + # server, so supply a default name. This shouldn't + # happen, but caution rocks. + # + $vhost = lc ($vhost) or "access"; + # + # If the log file for this virtual host isn't opened + # yet, do it now. + # + if (! $is_open{$vhost}) { + open $vhost, ">>${vhost}.log" + or die ("Can't open ${vhost}.log"); + $is_open{$vhost} = 1; + } + # + # Strip off the first token (which may be null in the + # case of the default server), and write the edited + # record to the current log file. + # + $log_line =~ s/^\S*\s+//; + printf $vhost "%s", $log_line; +} +exit 0; diff --git a/APACHE_1_3b7/src/support/suexec.8 b/APACHE_1_3b7/src/support/suexec.8 new file mode 100644 index 0000000000..a92b9471a8 --- /dev/null +++ b/APACHE_1_3b7/src/support/suexec.8 @@ -0,0 +1,70 @@ +.TH suexec 8 "March 1998" +.\" Copyright (c) 1998 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. +.\" +.\" 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 . +.SH NAME +suexec \- Switch User For Exec +.SH SYNOPSIS +No synopsis for usage, because this program +is used internally by Apache only. +.PP +.SH DESCRIPTION +.B suexec +is the "wrapper" support program for the suEXEC behaviour for Apache. +It is run from within Apache automatically to switch the user when +an external program has to be run under a different user. For more +information about suEXEC see the document `Apache suEXEC Support' +under http://www.apache.org/docs/suexec.html . +.PD +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3b7/src/support/suexec.c b/APACHE_1_3b7/src/support/suexec.c new file mode 100644 index 0000000000..e8ce4fea52 --- /dev/null +++ b/APACHE_1_3b7/src/support/suexec.c @@ -0,0 +1,520 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * suexec.c -- "Wrapper" support program for suEXEC behaviour for Apache + * + *********************************************************************** + * + * NOTE! : DO NOT edit this code!!! Unless you know what you are doing, + * editing this code might open up your system in unexpected + * ways to would-be crackers. Every precaution has been taken + * to make this code as safe as possible; alter it at your own + * risk. + * + *********************************************************************** + * + * + */ + +#include "conf.h" +#include +#include +#include + +#include + +#include "suexec.h" + +/* + *********************************************************************** + * There is no initgroups() in QNX, so I believe this is safe :-) + * Use cc -osuexec -3 -O -mf -DQNX suexec.c to compile. + * + * May 17, 1997. + * Igor N. Kovalenko -- infoh@mail.wplus.net + *********************************************************************** + */ + +#if defined(NEED_INITGROUPS) +int initgroups(const char *name, gid_t basegid) +{ +/* QNX and MPE do not appear to support supplementary groups. */ + return 0; +} +#endif + +#if defined(PATH_MAX) +#define AP_MAXPATH PATH_MAX +#elif defined(MAXPATHLEN) +#define AP_MAXPATH MAXPATHLEN +#else +#define AP_MAXPATH 8192 +#endif + +#define AP_ENVBUF 256 + +extern char **environ; +static FILE *log; + +char *safe_env_lst[] = +{ + "AUTH_TYPE", + "CONTENT_LENGTH", + "CONTENT_TYPE", + "DATE_GMT", + "DATE_LOCAL", + "DOCUMENT_NAME", + "DOCUMENT_PATH_INFO", + "DOCUMENT_ROOT", + "DOCUMENT_URI", + "FILEPATH_INFO", + "GATEWAY_INTERFACE", + "LAST_MODIFIED", + "PATH_INFO", + "PATH_TRANSLATED", + "QUERY_STRING", + "QUERY_STRING_UNESCAPED", + "REMOTE_ADDR", + "REMOTE_HOST", + "REMOTE_IDENT", + "REMOTE_PORT", + "REMOTE_USER", + "REDIRECT_QUERY_STRING", + "REDIRECT_STATUS", + "REDIRECT_URL", + "REQUEST_METHOD", + "REQUEST_URI", + "SCRIPT_FILENAME", + "SCRIPT_NAME", + "SCRIPT_URI", + "SCRIPT_URL", + "SERVER_ADMIN", + "SERVER_NAME", + "SERVER_PORT", + "SERVER_PROTOCOL", + "SERVER_SOFTWARE", + "UNIQUE_ID", + "USER_NAME", + "TZ", + NULL +}; + + +static void err_output(const char *fmt, va_list ap) +{ +#ifdef LOG_EXEC + time_t timevar; + struct tm *lt; + + if (!log) + if ((log = fopen(LOG_EXEC, "a")) == NULL) { + fprintf(stderr, "failed to open log file\n"); + perror("fopen"); + exit(1); + } + + time(&timevar); + lt = localtime(&timevar); + + fprintf(log, "[%d-%.2d-%.2d %.2d:%.2d:%.2d]: ", + lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, + lt->tm_hour, lt->tm_min, lt->tm_sec); + + vfprintf(log, fmt, ap); + + fflush(log); +#endif /* LOG_EXEC */ + return; +} + +static void log_err(const char *fmt,...) +{ +#ifdef LOG_EXEC + va_list ap; + + va_start(ap, fmt); + err_output(fmt, ap); + va_end(ap); +#endif /* LOG_EXEC */ + return; +} + +static void clean_env(void) +{ + char pathbuf[512]; + char **cleanenv; + char **ep; + int cidx = 0; + int idx; + + + if ((cleanenv = (char **) calloc(AP_ENVBUF, sizeof(char *))) == NULL) { + log_err("failed to malloc env mem\n"); + exit(120); + } + + for (ep = environ; *ep && cidx < AP_ENVBUF; ep++) { + if (!strncmp(*ep, "HTTP_", 5)) { + cleanenv[cidx] = *ep; + cidx++; + } + else { + for (idx = 0; safe_env_lst[idx]; idx++) { + if (!strncmp(*ep, safe_env_lst[idx], strlen(safe_env_lst[idx]))) { + cleanenv[cidx] = *ep; + cidx++; + break; + } + } + } + } + + sprintf(pathbuf, "PATH=%s", SAFE_PATH); + cleanenv[cidx] = strdup(pathbuf); + cleanenv[++cidx] = NULL; + + environ = cleanenv; +} + +int main(int argc, char *argv[]) +{ + int userdir = 0; /* ~userdir flag */ + uid_t uid; /* user information */ + gid_t gid; /* target group placeholder */ + char *target_uname; /* target user name */ + char *target_gname; /* target group name */ + char *target_homedir; /* target home directory */ + char *actual_uname; /* actual user name */ + char *actual_gname; /* actual group name */ + char *prog; /* name of this program */ + char *cmd; /* command to be executed */ + char cwd[AP_MAXPATH]; /* current working directory */ + char dwd[AP_MAXPATH]; /* docroot working directory */ + struct passwd *pw; /* password entry holder */ + struct group *gr; /* group entry holder */ + struct stat dir_info; /* directory info holder */ + struct stat prg_info; /* program info holder */ + + + + /* + * If there are a proper number of arguments, set + * all of them to variables. Otherwise, error out. + */ + prog = argv[0]; + if (argc < 4) { + log_err("too few arguments\n"); + exit(101); + } + target_uname = argv[1]; + target_gname = argv[2]; + cmd = argv[3]; + + /* + * Check existence/validity of the UID of the user + * running this program. Error out if invalid. + */ + uid = getuid(); + if ((pw = getpwuid(uid)) == NULL) { + log_err("invalid uid: (%ld)\n", uid); + exit(102); + } + + /* + * Check to see if the user running this program + * is the user allowed to do so as defined in + * suexec.h. If not the allowed user, error out. + */ +#ifdef _OSD_POSIX + /* User name comparisons are case insensitive on BS2000/OSD */ + if (strcasecmp(HTTPD_USER, pw->pw_name)) { + log_err("user mismatch (%s)\n", pw->pw_name); + exit(103); + } +#else /*_OSD_POSIX*/ + if (strcmp(HTTPD_USER, pw->pw_name)) { + log_err("user mismatch (%s)\n", pw->pw_name); + exit(103); + } +#endif /*_OSD_POSIX*/ + + /* + * Check for a leading '/' (absolute path) in the command to be executed, + * or attempts to back up out of the current directory, + * to protect against attacks. If any are + * found, error out. Naughty naughty crackers. + */ + if ((cmd[0] == '/') || (!strncmp(cmd, "../", 3)) + || (strstr(cmd, "/../") != NULL)) { + log_err("invalid command (%s)\n", cmd); + exit(104); + } + + /* + * Check to see if this is a ~userdir request. If + * so, set the flag, and remove the '~' from the + * target username. + */ + if (!strncmp("~", target_uname, 1)) { + target_uname++; + userdir = 1; + } + + /* + * Error out if the target username is invalid. + */ + if ((pw = getpwnam(target_uname)) == NULL) { + log_err("invalid target user name: (%s)\n", target_uname); + exit(105); + } + + /* + * Error out if the target group name is invalid. + */ + if (strspn(target_gname, "1234567890") != strlen(target_gname)) { + if ((gr = getgrnam(target_gname)) == NULL) { + log_err("invalid target group name: (%s)\n", target_gname); + exit(106); + } + gid = gr->gr_gid; + actual_gname = strdup(gr->gr_name); + } + else { + gid = atoi(target_gname); + actual_gname = strdup(target_gname); + } + + /* + * Save these for later since initgroups will hose the struct + */ + uid = pw->pw_uid; + actual_uname = strdup(pw->pw_name); + target_homedir = strdup(pw->pw_dir); + + /* + * Log the transaction here to be sure we have an open log + * before we setuid(). + */ + log_err("uid: (%s/%s) gid: (%s/%s) %s\n", + target_uname, actual_uname, + target_gname, actual_gname, + cmd); + + /* + * Error out if attempt is made to execute as root or as + * a UID less than UID_MIN. Tsk tsk. + */ + if ((uid == 0) || (uid < UID_MIN)) { + log_err("cannot run as forbidden uid (%d/%s)\n", uid, cmd); + exit(107); + } + + /* + * Error out if attempt is made to execute as root group + * or as a GID less than GID_MIN. Tsk tsk. + */ + if ((gid == 0) || (gid < GID_MIN)) { + log_err("cannot run as forbidden gid (%d/%s)\n", gid, cmd); + exit(108); + } + + /* + * Change UID/GID here so that the following tests work over NFS. + * + * Initialize the group access list for the target user, + * and setgid() to the target group. If unsuccessful, error out. + */ + if (((setgid(gid)) != 0) || (initgroups(actual_uname, gid) != 0)) { + log_err("failed to setgid (%ld: %s)\n", gid, cmd); + exit(109); + } + + /* + * setuid() to the target user. Error out on fail. + */ + if ((setuid(uid)) != 0) { + log_err("failed to setuid (%ld: %s)\n", uid, cmd); + exit(110); + } + + /* + * Get the current working directory, as well as the proper + * document root (dependant upon whether or not it is a + * ~userdir request). Error out if we cannot get either one, + * or if the current working directory is not in the docroot. + * Use chdir()s and getcwd()s to avoid problems with symlinked + * directories. Yuck. + */ + if (getcwd(cwd, AP_MAXPATH) == NULL) { + log_err("cannot get current working directory\n"); + exit(111); + } + + if (userdir) { + if (((chdir(target_homedir)) != 0) || + ((chdir(USERDIR_SUFFIX)) != 0) || + ((getcwd(dwd, AP_MAXPATH)) == NULL) || + ((chdir(cwd)) != 0)) { + log_err("cannot get docroot information (%s)\n", target_homedir); + exit(112); + } + } + else { + if (((chdir(DOC_ROOT)) != 0) || + ((getcwd(dwd, AP_MAXPATH)) == NULL) || + ((chdir(cwd)) != 0)) { + log_err("cannot get docroot information (%s)\n", DOC_ROOT); + exit(113); + } + } + + if ((strncmp(cwd, dwd, strlen(dwd))) != 0) { + log_err("command not in docroot (%s/%s)\n", cwd, cmd); + exit(114); + } + + /* + * Stat the cwd and verify it is a directory, or error out. + */ + if (((lstat(cwd, &dir_info)) != 0) || !(S_ISDIR(dir_info.st_mode))) { + log_err("cannot stat directory: (%s)\n", cwd); + exit(115); + } + + /* + * Error out if cwd is writable by others. + */ + if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) { + log_err("directory is writable by others: (%s)\n", cwd); + exit(116); + } + + /* + * Error out if we cannot stat the program. + */ + if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) { + log_err("cannot stat program: (%s)\n", cmd); + exit(117); + } + + /* + * Error out if the program is writable by others. + */ + if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) { + log_err("file is writable by others: (%s/%s)\n", cwd, cmd); + exit(118); + } + + /* + * Error out if the file is setuid or setgid. + */ + if ((prg_info.st_mode & S_ISUID) || (prg_info.st_mode & S_ISGID)) { + log_err("file is either setuid or setgid: (%s/%s)\n", cwd, cmd); + exit(119); + } + + /* + * Error out if the target name/group is different from + * the name/group of the cwd or the program. + */ + if ((uid != dir_info.st_uid) || + (gid != dir_info.st_gid) || + (uid != prg_info.st_uid) || + (gid != prg_info.st_gid)) { + log_err("target uid/gid (%ld/%ld) mismatch with directory (%ld/%ld) or program (%ld/%ld)\n", + uid, gid, + dir_info.st_uid, dir_info.st_gid, + prg_info.st_uid, prg_info.st_gid); + exit(120); + } + /* + * Error out if the program is not executable for the user. + * Otherwise, she won't find any error in the logs except for + * "[error] Premature end of script headers: ..." + */ + if (!(prg_info.st_mode & S_IXUSR)) { + log_err("file has no execute permission: (%s/%s)\n", cwd, cmd); + exit(121); + } + + clean_env(); + + /* + * Be sure to close the log file so the CGI can't + * mess with it. If the exec fails, it will be reopened + * automatically when log_err is called. + */ + fclose(log); + log = NULL; + + /* + * Execute the command, replacing our image with its own. + */ + execv(cmd, &argv[3]); + + /* + * (I can't help myself...sorry.) + * + * Uh oh. Still here. Where's the kaboom? There was supposed to be an + * EARTH-shattering kaboom! + * + * Oh well, log the failure and error out. + */ + log_err("(%d)%s: exec failed (%s)\n", errno, strerror(errno), cmd); + exit(255); +} diff --git a/APACHE_1_3b7/src/support/suexec.h b/APACHE_1_3b7/src/support/suexec.h new file mode 100644 index 0000000000..3da06813fc --- /dev/null +++ b/APACHE_1_3b7/src/support/suexec.h @@ -0,0 +1,142 @@ +/* ==================================================================== + * Copyright (c) 1995-1998 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 . + * + */ + +/* + * suexec.h -- user-definable variables for the suexec wrapper code. + */ + + +#ifndef _SUEXEC_H +#define _SUEXEC_H + +/* + * HTTPD_USER -- Define as the username under which Apache normally + * runs. This is the only user allowed to execute + * this program. + */ +#ifndef HTTPD_USER +#define HTTPD_USER "www" +#endif + +/* + * UID_MIN -- Define this as the lowest UID allowed to be a target user + * for suEXEC. For most systems, 500 or 100 is common. + */ +#ifndef UID_MIN +#define UID_MIN 100 +#endif + +/* + * GID_MIN -- Define this as the lowest GID allowed to be a target group + * for suEXEC. For most systems, 100 is common. + */ +#ifndef GID_MIN +#define GID_MIN 100 +#endif + +/* + * USERDIR_SUFFIX -- Define to be the subdirectory under users' + * home directories where suEXEC access should + * be allowed. All executables under this directory + * will be executable by suEXEC as the user so + * they should be "safe" programs. If you are + * using a "simple" UserDir directive (ie. one + * without a "*" in it) this should be set to + * the same value. suEXEC will not work properly + * in cases where the UserDir directive points to + * a location that is not the same as the user's + * home directory as referenced in the passwd file. + * + * If you have VirtualHosts with a different + * UserDir for each, you will need to define them to + * all reside in one parent directory; then name that + * parent directory here. IF THIS IS NOT DEFINED + * PROPERLY, ~USERDIR CGI REQUESTS WILL NOT WORK! + * See the suEXEC documentation for more detailed + * information. + */ +#ifndef USERDIR_SUFFIX +#define USERDIR_SUFFIX "public_html" +#endif + +/* + * LOG_EXEC -- Define this as a filename if you want all suEXEC + * transactions and errors logged for auditing and + * debugging purposes. + */ +#ifndef LOG_EXEC +#define LOG_EXEC "/usr/local/apache/logs/cgi.log" /* Need me? */ +#endif + +/* + * DOC_ROOT -- Define as the DocumentRoot set for Apache. This + * will be the only hierarchy (aside from UserDirs) + * that can be used for suEXEC behavior. + */ +#ifndef DOC_ROOT +#define DOC_ROOT "/usr/local/apache/htdocs" +#endif + +/* + * SAFE_PATH -- Define a safe PATH environment to pass to CGI executables. + * + */ +#ifndef SAFE_PATH +#define SAFE_PATH "/usr/local/bin:/usr/bin:/bin" +#endif + +#endif /* _SUEXEC_H */ diff --git a/APACHE_1_3b7/src/test/.cvsignore b/APACHE_1_3b7/src/test/.cvsignore new file mode 100644 index 0000000000..e2244a438e --- /dev/null +++ b/APACHE_1_3b7/src/test/.cvsignore @@ -0,0 +1,11 @@ +a.out +time-FCNTL +time-FLOCK +time-SYSVSEM +time-SYSVSEM2 +time-PTHREAD +time-USLOCK +zb +test-writev +test_date +test_select diff --git a/APACHE_1_3b7/src/test/.indent.pro b/APACHE_1_3b7/src/test/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3b7/src/test/.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/APACHE_1_3b7/src/test/README b/APACHE_1_3b7/src/test/README new file mode 100644 index 0000000000..9f8be502b8 --- /dev/null +++ b/APACHE_1_3b7/src/test/README @@ -0,0 +1,3 @@ +This directory contains useful test code for testing various bits +of Apache functionality. This stuff is for the developers only, +so we might remove it on public releases. diff --git a/APACHE_1_3b7/src/test/check_chunked b/APACHE_1_3b7/src/test/check_chunked new file mode 100755 index 0000000000..042f661aa9 --- /dev/null +++ b/APACHE_1_3b7/src/test/check_chunked @@ -0,0 +1,42 @@ +#!/usr/bin/perl -w + +# This is meant to be used on the raw output of an HTTP/1.1 connection +# to check that the chunks are all correctly laid out. It's easiest +# to use a tool like netcat to generate the output. This script +# *insists* that \r exist in the output. +# +# You can find netcat at avian.org:/src/hacks/nc110.tgz. + +use strict; + +my $is_chunked = 0; + +# must toss headers +while(<>) { + if (/^Transfer-Encoding:\s+chunked/i) { + $is_chunked = 1; + } + last if ($_ eq "\r\n"); +} + +$is_chunked || die "wasn't chunked\n"; + +for(;;) { + $_ = <> || die "unexpected end of file!\n"; + + m#^[0-9a-f]+ *\r$#i || die "bogus chunklen: $_"; + + my $chunklen = hex; + + exit 0 if ($chunklen == 0); + + chop; chop; + print "$_ "; + + my $data = ''; + read(ARGV, $data, $chunklen) == $chunklen || die "short read!\n"; + + $_ = <> || die "unexpected end of file!\n"; + + $_ eq "\r\n" || die "missing chunk trailer!\n"; +} diff --git a/APACHE_1_3b7/src/test/cls.c b/APACHE_1_3b7/src/test/cls.c new file mode 100644 index 0000000000..91114a784c --- /dev/null +++ b/APACHE_1_3b7/src/test/cls.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include + +/* + * Compare a string to a mask + * Mask characters: + * @ - uppercase letter + * # - lowercase letter + * & - hex digit + * # - digit + * * - swallow remaining characters + * - exact match for any other character + */ +static int checkmask(const char *data, const char *mask) +{ + int i, ch, d; + + for (i = 0; mask[i] != '\0' && mask[i] != '*'; i++) { + ch = mask[i]; + d = data[i]; + if (ch == '@') { + if (!isupper(d)) + return 0; + } + else if (ch == '$') { + if (!islower(d)) + return 0; + } + else if (ch == '#') { + if (!isdigit(d)) + return 0; + } + else if (ch == '&') { + if (!isxdigit(d)) + return 0; + } + else if (ch != d) + return 0; + } + + if (mask[i] == '*') + return 1; + else + return (data[i] == '\0'); +} + +/* + * Converts 8 hex digits to a time integer + */ +static int hex2sec(const char *x) +{ + int i, ch; + unsigned int j; + + for (i = 0, j = 0; i < 8; i++) { + ch = x[i]; + j <<= 4; + if (isdigit(ch)) + j |= ch - '0'; + else if (isupper(ch)) + j |= ch - ('A' - 10); + else + j |= ch - ('a' - 10); + } + if (j == 0xffffffff) + return -1; /* so that it works with 8-byte ints */ + else + return j; +} + +int main(int argc, char **argv) +{ + int i, ver; + DIR *d; + struct dirent *e; + const char *s; + FILE *fp; + char path[FILENAME_MAX + 1]; + char line[1035]; + time_t date, lmod, expire; + unsigned int len; + struct tm ts; + char sdate[30], slmod[30], sexpire[30]; + const char time_format[] = "%e %b %Y %R"; + + if (argc != 2) { + printf("Usage: cls directory\n"); + exit(0); + } + + d = opendir(argv[1]); + if (d == NULL) { + perror("opendir"); + exit(1); + } + + for (;;) { + e = readdir(d); + if (e == NULL) + break; + s = e->d_name; + if (s[0] == '.' || s[0] == '#') + continue; + sprintf(path, "%s/%s", argv[1], s); + fp = fopen(path, "r"); + if (fp == NULL) { + perror("fopen"); + continue; + } + if (fgets(line, 1034, fp) == NULL) { + perror("fgets"); + fclose(fp); + continue; + } + if (!checkmask(line, "&&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&&\n")) { + fprintf(stderr, "Bad cache file\n"); + fclose(fp); + continue; + } + date = hex2sec(line); + lmod = hex2sec(line + 9); + expire = hex2sec(line + 18); + ver = hex2sec(line + 27); + len = hex2sec(line + 35); + if (fgets(line, 1034, fp) == NULL) { + perror("fgets"); + fclose(fp); + continue; + } + fclose(fp); + i = strlen(line); + if (strncmp(line, "X-URL: ", 7) != 0 || line[i - 1] != '\n') { + fprintf(stderr, "Bad cache file\n"); + continue; + } + line[i - 1] = '\0'; + if (date != -1) { + ts = *gmtime(&date); + strftime(sdate, 30, time_format, &ts); + } + else + strcpy(sdate, "-"); + + if (lmod != -1) { + ts = *gmtime(&lmod); + strftime(slmod, 30, time_format, &ts); + } + else + strcpy(slmod, "-"); + + if (expire != -1) { + ts = *gmtime(&expire); + strftime(sexpire, 30, time_format, &ts); + } + else + strcpy(sexpire, "-"); + + printf("%s: %d; %s %s %s\n", line + 7, ver, sdate, slmod, sexpire); + } + + closedir(d); + return 0; +} diff --git a/APACHE_1_3b7/src/test/rename/Makefile b/APACHE_1_3b7/src/test/rename/Makefile new file mode 100644 index 0000000000..4e3454d1d6 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/Makefile @@ -0,0 +1,21 @@ + +SRC=../.. + +all: + @echo "run 'make rename' for renaming _THIS_ source tree" + @echo "run 'make rename SRC=/path/to/apache-1.3/src' for other test trees" + +rename: programs + ./rename.pl $(SRC)/buildmark.c \ + $(SRC)/os \ + $(SRC)/main \ + $(SRC)/ap \ + $(SRC)/modules \ + $(SRC)/include + +programs: + @cd csubst; make + +clean: + @cd csubst; make clean + diff --git a/APACHE_1_3b7/src/test/rename/README b/APACHE_1_3b7/src/test/rename/README new file mode 100644 index 0000000000..87e501e611 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/README @@ -0,0 +1,59 @@ + +This stuff is only temporary. +It is used for the global symbol renaming in the Apache 1.3 sources. +It replaces identifiers in our C source files according to +the rename.cf file. + +This can be used directly by everyone: +-------------------------------------- +rename.pl .......... The source renaming script + +These three Needs adjustments to work out-of-the-box: +----------------------------------------------------- +rename.cf.update ... Updates rename.cf according to API_EXPORT tags + in the sources. Needs an ID file in src/ which + is generated by "mkid" from GNU id-utils +apapi_compat.h.mk .. Creates apapi_compat.h file from rename.cf +apapi.h.mk ......... Creates apapi.h file from rename.cf and ID file + + +If we ever get around to doing this, here's the procedure +--------------------------------------------------------- + + - tag the source tree + $ cd apache-1.3 + $ cvs tag PRE_AP_PREFIX_RENAME . + - rename the source identifiers + $ cd apache-1.3/src/test/rename + $ make rename + - compile entire server (static variant) + $ cd apache-1.3 + $ ./configure --prefix=/tmp/apache + --enable-module=most + - check symbols + $ cd apache-1.3/src + $ nm -g httpd |more + - check operation of server + $ cd apache-1.3 + $ make install + $ /tmp/apache/sbin/apachectl start + - compile entire server (shared variant) + $ cd apache-1.3 + $ ./configure --prefix=/tmp/apache + --enable-module=most + --enable-shared=max + - check symbols + $ cd apache-1.3/src + $ nm -g httpd | egrep -v '_modules?$' | egrep -v 'apx?_' | grep -v '.o$' + $ nm -g httpd | more + - check operation of server + $ cd apache-1.3 + $ make install + $ /tmp/apache/sbin/apachectl start + - commit + $ cd apache-1.3/src + $ cvs commit . + - tag the source tree + $ cd apache-1.3 + $ cvs tag POST_AP_PREFIX_RENAME . + diff --git a/APACHE_1_3b7/src/test/rename/apapi.h b/APACHE_1_3b7/src/test/rename/apapi.h new file mode 100644 index 0000000000..9bcb3dee6f --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/apapi.h @@ -0,0 +1,259 @@ +/* +** apapi.h -- Apache 1.3 API prototypes +** +** THIS IS A COMPLETE LIST OF PROTOTYPES +** FOR ALL PUBLIC API FUNCTIONS +*/ + +#ifndef APAPI_H +#define APAPI_H + +extern char ap_server_root[MAX_STRING_LEN]; +extern const char ap_day_snames[7][4]; +extern const char ap_month_snames[12][4]; +extern void ap_MD5Final(unsigned char digest[16], AP_MD5_CTX * context); +extern void ap_MD5Init(AP_MD5_CTX * context); +extern void ap_MD5Update(AP_MD5_CTX * context, const unsigned char *input, unsigned int inputLen); +extern void ap_add_cgi_vars(request_rec *r); +extern void ap_add_common_vars(request_rec *r); +extern void ap_add_module(module *m); +extern int ap_add_named_module(const char *name); +extern int ap_allow_options (request_rec *); +extern int ap_allow_overrides (request_rec *); +extern array_header * ap_append_arrays(pool *, const array_header *, const array_header *); +extern void ap_array_cat(array_header *dst, const array_header *src); +extern char * ap_auth_name (request_rec *); +extern char * ap_auth_type (request_rec *); +extern void ap_basic_http_header(request_rec *r); +extern int ap_bclose(BUFF *fb); +extern BUFF * ap_bcreate(pool *p, int flags); +extern int ap_bfilbuf(BUFF *fb); +extern int ap_bfileno(BUFF *fb, int direction); +extern int ap_bflsbuf(int c, BUFF *fb); +extern int ap_bflush(BUFF *fb); +extern int ap_bgetopt(BUFF *fb, int optname, void *optval); +extern int ap_bgets(char *s, int n, BUFF *fb); +extern void ap_bhalfduplex(BUFF *fb); +extern void ap_block_alarms(void); +extern int ap_blookc(char *buff, BUFF *fb); +extern int ap_bnonblock(BUFF *fb, int direction); +extern void ap_bonerror(BUFF *fb, void (*error) (BUFF *, int, void *), void *data); +extern void ap_bpushfd(BUFF *fb, int fd_in, int fd_out); +extern int ap_bputs(const char *x, BUFF *fb); +extern int ap_bprintf(BUFF *fb, const char *fmt,...) __attribute__((format(printf,2,3))); +extern int ap_bread(BUFF *fb, void *buf, int nbyte); +extern int ap_bsetflag(BUFF *fb, int flag, int value); +extern int ap_bsetopt(BUFF *fb, int optname, const void *optval); +extern int ap_bskiplf(BUFF *fb); +extern int ap_bvputs(BUFF *fb,...); +extern int ap_bwrite(BUFF *fb, const void *buf, int nbyte); +extern long ap_bytes_in_free_blocks(void); +extern long ap_bytes_in_pool(pool *p); +extern int ap_call_exec(request_rec *r, char *argv0, char **env, int shellcmd); +extern int ap_can_exec(const struct stat *); +extern int ap_cfg_closefile(configfile_t *fp); +extern int ap_cfg_getc(configfile_t *cfp); +extern int ap_cfg_getline(char *buf, size_t bufsize, configfile_t *cfp); +extern void ap_chdir_file(const char *file); +extern int ap_check_alarm(void); +extern const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden); +extern int ap_checkmask(const char *data, const char *mask); +extern void ap_child_terminate(request_rec *r); +extern void ap_cleanup_for_exec(void); +extern void ap_clear_module_list(void); +extern void ap_clear_pool(struct pool *); +extern void ap_clear_table(table *); +extern void ap_close_piped_log (piped_log *); +extern char * ap_construct_server(pool *p, const char *hostname, unsigned port, const request_rec *r); +extern char * ap_construct_url(pool *p, const char *uri, const request_rec *r); +extern array_header * ap_copy_array(pool *p, const array_header *src); +extern array_header * ap_copy_array_hdr(pool *p, const array_header *src); +extern table * ap_copy_table(pool *p, const table *); +extern int ap_count_dirs(const char *path); +extern char ** ap_create_environment(pool *p, table *t); +extern unsigned short ap_default_port_for_request(const request_rec *r); +extern unsigned short ap_default_port_for_scheme(const char *scheme_str); +extern char * ap_default_type (request_rec *); +extern void ap_destroy_pool(pool *); +extern void ap_destroy_sub_req(request_rec *r); +extern int ap_discard_request_body(request_rec *r); +extern char * ap_document_root (request_rec *); +extern int ap_each_byterange(request_rec *r, long *offset, long *length); +extern void ap_error_log2stderr (server_rec *); +extern char * ap_escape_html(pool *p, const char *s); +extern char * ap_escape_path_segment(pool *p, const char *s); +extern char * ap_escape_shell_cmd(pool *p, const char *s); +extern int ap_exists_scoreboard_image(void); +extern int ap_find_last_token(pool *p, const char *line, const char *tok); +extern module * ap_find_linked_module(const char *name); +extern const char * ap_find_module_name(module *m); +extern int ap_find_path_info(const char *uri, const char *path_info); +extern pool * ap_find_pool(const void *ts); +extern int ap_find_token(pool *p, const char *line, const char *tok); +extern int ap_fnmatch(const char *, const char *, int); +extern int ap_get_basic_auth_pw(request_rec *r, char **pw); +extern long ap_get_client_block(request_rec *r, char *buffer, int bufsiz); +extern struct tm * ap_get_gmtoff(int *tz); +extern void * ap_get_module_config(void *conf_vector, module *m); +extern const char * ap_get_remote_host(conn_rec *conn, void *dir_config, int type); +extern const char * ap_get_remote_logname(request_rec *r); +extern const char * ap_get_server_name(const request_rec *r); +extern unsigned ap_get_server_port(const request_rec *r); +extern char * ap_get_time(void); +extern char * ap_get_token(pool *p, char **accept_line, int accept_white); +extern void ap_getparents(char *name); +extern char * ap_getword(pool *p, const char **line, char stop); +extern char * ap_getword_conf(pool *p, const char **line); +extern char * ap_getword_conf_nc(pool *p, char **line); +extern char * ap_getword_nc(pool *p, char **line, char stop); +extern char * ap_getword_nulls(pool *p, const char **line, char stop); +extern char * ap_getword_nulls_nc(pool *p, char **line, char stop); +extern char * ap_getword_white(pool *p, const char **line); +extern char * ap_getword_white_nc(pool *p, char **line); +extern char * ap_gm_timestr_822(pool *p, time_t t); +extern gid_t ap_gname2id(const char *name); +extern void ap_hard_timeout(char *, request_rec *); +extern char * ap_ht_time(pool *p, time_t t, const char *fmt, int gmt); +extern int ap_ind(const char *, char); +extern int ap_index_of_response(int status); +extern void ap_internal_redirect(const char *new_uri, request_rec *); +extern void ap_internal_redirect_handler(const char *new_uri, request_rec *); +extern int ap_is_directory(const char *name); +extern int ap_is_fnmatch(const char *); +extern int ap_is_initial_req(request_rec *r); +extern int ap_is_matchexp(const char *str); +extern int ap_is_url(const char *u); +extern void ap_kill_cleanup(pool *p, void *data, void (*plain_cleanup) (void *)); +extern void ap_kill_cleanups_for_fd(pool *p, int fd); +extern void ap_kill_cleanups_for_socket(pool *p, int sock); +extern void ap_kill_timeout(request_rec *); +extern void ap_log_assert(const char *szExp, const char *szFile, int nLine) __attribute__((noreturn)); +extern void ap_log_printf(const server_rec *s, const char *fmt, ...) __attribute__((format(printf,2,3))); +extern void ap_log_reason(const char *reason, const char *fname, request_rec *r); +extern void ap_log_unixerr(const char *routine, const char *file, const char *msg, server_rec *s); +extern array_header * ap_make_array(pool *p, int nelts, int elt_size); +extern char * ap_make_dirstr(pool *a, const char *s, int n); +extern char * ap_make_dirstr_parent(pool *p, const char *s); +extern char * ap_make_dirstr_prefix(char *d, const char *s, int n); +extern char * ap_make_full_path(pool *a, const char *dir, const char *f); +extern pool * ap_make_sub_pool(pool *); +extern table * ap_make_table(pool *p, int nelts); +extern int ap_matches_request_vhost(request_rec *r, const char *host, unsigned port); +extern int ap_meets_conditions(request_rec *r); +extern void ap_no2slash(char *name); +extern void ap_note_auth_failure(request_rec *r); +extern void ap_note_basic_auth_failure(request_rec *r); +extern void ap_note_cleanups_for_fd(pool *, int); +extern void ap_note_cleanups_for_file(pool *, FILE *); +extern void ap_note_cleanups_for_socket(pool *, int); +extern void ap_note_digest_auth_failure(request_rec *r); +extern void ap_note_subprocess(pool *a, int pid, enum kill_conditions how); +extern void ap_null_cleanup(void *data); +extern piped_log * ap_open_piped_log (pool *p, const char *program); +extern table * ap_overlay_tables(pool *p, const table *overlay, const table *base); +extern void * ap_palloc(struct pool *, int nbytes); +extern time_t ap_parseHTTPdate(const char *date); +extern void ap_parse_uri(request_rec *r, const char *uri); +extern int ap_parse_uri_components(pool *p, const char *uri, uri_components *uptr); +extern int ap_parse_hostinfo_components(pool *p, const char *hostinfo, uri_components *uptr); +extern void * ap_pcalloc(struct pool *, int nbytes); +extern configfile_t * ap_pcfg_open_custom(pool *p, const char *descr, void *param, int(*getc_func)(void*), void *(*gets_func) (void *buf, size_t bufsiz, void *param), int(*close_func)(void*)); +extern configfile_t * ap_pcfg_openfile(pool *p, const char *name); +extern void ap_pclosedir(pool *p, DIR * d); +extern int ap_pclosef(struct pool *, int fd); +extern int ap_pclosesocket(pool *a, int sock); +extern struct hostent * ap_pduphostent(pool *p, struct hostent *hp); +extern int ap_pfclose(struct pool *, FILE *); +extern FILE * ap_pfdopen(struct pool *, int fd, const char *fmode); +extern FILE * ap_pfopen(struct pool *, const char *name, const char *fmode); +extern struct hostent * ap_pgethostbyname(pool *p, const char *hostname); +extern int ap_pool_is_ancestor(pool *a, pool *b); +extern void ap_pool_join(pool *p, pool *sub); +extern DIR * ap_popendir(pool *p, const char *name); +extern int ap_popenf(struct pool *, const char *name, int flg, int mode); +extern regex_t * ap_pregcomp(pool *p, const char *pattern, int cflags); +extern void ap_pregfree(pool *p, regex_t * reg); +extern char * ap_pregsub(pool *p, const char *input, const char *source, size_t nmatch, regmatch_t pmatch[]); +extern const char * ap_psignature(const char *prefix, request_rec *r); +extern int ap_psocket(pool *p, int, int, int); +extern char * ap_pstrcat(struct pool *,...); +extern char * ap_pstrdup(struct pool *, const char *s); +extern char * ap_pstrndup(struct pool *, const char *s, int n); +extern char * ap_psprintf(struct pool *, const char *fmt, ...) __attribute__((format(printf,2,3))); +extern char * ap_pvsprintf(struct pool *, const char *fmt, va_list); +extern void * ap_push_array(array_header *); +extern time_t ap_rationalize_mtime(request_rec *r, time_t mtime); +extern void ap_register_cleanup(pool *p, void *data, void (*plain_cleanup) (void *), void (*child_cleanup) (void *)); +extern void ap_register_other_child(int pid, void (*maintenance) (int reason, void *data, int status), void *data, int write_fd); +extern void ap_remove_module(module *m); +extern array_header * ap_requires (request_rec *); +extern void ap_reset_timeout(request_rec *); +extern int ap_rflush(request_rec *r); +extern int ap_rind(const char *, char); +extern int ap_rprintf(request_rec *r, const char *fmt,...) __attribute__((format(printf,2,3))); +extern int ap_rputc(int c, request_rec *r); +extern int ap_rputs(const char *str, request_rec *r); +extern void ap_run_cleanup(pool *p, void *data, void (*cleanup) (void *)); +extern int ap_run_sub_req(request_rec *r); +extern int ap_rvputs(request_rec *r,...); +extern int ap_rwrite(const void *buf, int nbyte, request_rec *r); +extern int ap_satisfies (request_rec *r); +extern int ap_scan_script_header_err(request_rec *r, FILE *f, char *buffer); +extern int ap_scan_script_header_err_buff(request_rec *r, BUFF *f, char *buffer); +extern long ap_send_fb(BUFF *f, request_rec *r); +extern long ap_send_fb_length(BUFF *f, request_rec *r, long length); +extern long ap_send_fd(FILE *f, request_rec *r); +extern long ap_send_fd_length(FILE *f, request_rec *r, long length); +extern int ap_send_header_field(request_rec *r, const char *fieldname, const char *fieldval); +extern void ap_send_http_header(request_rec *l); +extern size_t ap_send_mmap(void *mm, request_rec *r, size_t offset, size_t length); +extern void ap_send_size(size_t size, request_rec *r); +extern char * ap_server_root_relative(pool *p, char *fname); +extern int ap_set_byterange(request_rec *r); +extern int ap_set_content_length(request_rec *r, long length); +extern void ap_set_etag(request_rec *r); +extern const char * ap_set_file_slot(cmd_parms *, char *, char *); +extern const char * ap_set_flag_slot(cmd_parms *, char *, int); +extern int ap_set_keepalive(request_rec *r); +extern void ap_set_last_modified(request_rec *r); +extern void ap_set_module_config(void *conf_vector, module *m, void *val); +extern const char * ap_set_string_slot(cmd_parms *, char *, char *); +extern const char * ap_set_string_slot_lower(cmd_parms *, char *, char *); +extern int ap_setup_client_block(request_rec *r, int read_policy); +extern int ap_should_client_block(request_rec *r); +extern void ap_soft_timeout(char *, request_rec *); +extern int ap_some_auth_required(request_rec *r); +extern int ap_spawn_child_err(pool *, int (*)(void *), void *, enum kill_conditions, FILE **pipe_in, FILE **pipe_out, FILE **pipe_err); +extern int ap_spawn_child_err_buff(pool *, int (*)(void *), void *, enum kill_conditions, BUFF **pipe_in, BUFF **pipe_out, BUFF **pipe_err); +extern const char * ap_srm_command_loop(cmd_parms *parms, void *config); +extern void ap_str_tolower(char *); +extern int ap_strcasecmp_match(const char *str, const char *exp); +extern int ap_strcmp_match(const char *str, const char *exp); +extern request_rec * ap_sub_req_lookup_file(const char *new_file, const request_rec *r); +extern request_rec * ap_sub_req_lookup_uri(const char *new_file, const request_rec *r); +extern void ap_sync_scoreboard_image(void); +extern void ap_table_add(table *, const char *name, const char *val); +extern void ap_table_addn(table *, const char *name, const char *val); +extern void ap_table_do(int (*comp) (void *, const char *, const char *), void *rec, const table *t,...); +extern char * ap_table_get(const table *, const char *); +extern void ap_table_merge(table *, const char *name, const char *more_val); +extern void ap_table_mergen(table *, const char *name, const char *more_val); +extern void ap_table_set(table *, const char *name, const char *val); +extern void ap_table_setn(table *, const char *name, const char *val); +extern void ap_table_unset(table *, const char *key); +extern time_t ap_tm2sec(const struct tm *t); +extern uid_t ap_uname2id(const char *name); +extern void ap_unblock_alarms(void); +extern int ap_unescape_url(char *url); +extern char * ap_unparse_uri_components(pool *p, const uri_components *uptr, unsigned flags); +extern void ap_unregister_other_child(void *data); +extern time_t ap_update_mtime(request_rec *r, time_t dependency_mtime); +extern char * ap_uudecode(pool *, const char *); +extern int ap_vbprintf(BUFF *fb, const char *fmt, va_list vlist); +extern const char * ap_get_server_built(void); +extern const char * ap_get_server_version(void); +extern void ap_log_error(const char *file, int line, int level, const server_rec *s, const char *fmt, ...) __attribute__((format(printf,5,6))); +extern void ap_log_error_old(const char *err, server_rec *s); +extern char * ap_escape_path(pool *p, const char *path, int partial); + +#endif /* APAPI_H */ diff --git a/APACHE_1_3b7/src/test/rename/apapi.h.mk b/APACHE_1_3b7/src/test/rename/apapi.h.mk new file mode 100755 index 0000000000..13c64eb652 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/apapi.h.mk @@ -0,0 +1,82 @@ +: +eval 'exec perl -S $0 ${1+"$@"}' + if $running_under_some_shell; +## +## apapi.h.mk -- +## + +# configuration +$id = "../src/ID"; +$renamecf = "./rename.cf"; +$header = "./apapi.h"; + +sub func_prototype { + my ($func) = @_; + + $rc = join('', `lid -f $id --key=token --result=grep $func`); + if ( $rc =~ m|^(.+?\.h):\d+:\s*API_EXPORT(?:_NONSTD)?\(.+?\)\s*$func\s*\(|m + or $rc =~ m|^(.+?\.h):\d+:\s*(?:extern\s*)?API_VAR_EXPORT\s*.+?$func.+?;|m) { + $file = $1; + open(FP, "<$file") || die; + $contents = join('', ); + close(FP); + if (($r, $f) = ($contents =~ m|\n\s*API_EXPORT(?:_NONSTD)?\(([^)]+)\)\s+($func\s*\(.+?\);)|s)) { + $r =~ s|\s*\n\s*| |sg; + $r =~ s|\s+| |sg; + $r =~ s|extern\s+||g; + $f =~ s|\s*\n\s*| |sg; + $f =~ s|\s+| |sg; + $pt = sprintf("%-20s %s", $r, $f); + return $pt; + } + if (($r, $f) = ($contents =~ m|\n\s*(?:extern\s*)?API_VAR_EXPORT\s*([^;]*?)($func[^;]*;)|s)) { + $r =~ s|\s*\n\s*| |sg; + $r =~ s|\s+| |sg; + $r =~ s|extern\s+||g; + $f =~ s|\s*\n\s*| |sg; + $f =~ s|\s+| |sg; + $pt = sprintf("%-20s %s", $r, $f); + return $pt; + } + } + return ''; +} + +open(CFG, "<$renamecf") || die; +open(HDR, ">$header") || die; +print HDR <<'EOT'; +/* +** apapi.h -- Apache 1.3 API prototypes +** +** THIS IS A COMPLETE LIST OF PROTOTYPES +** FOR ALL PUBLIC API FUNCTIONS +*/ + +#ifndef APAPI_H +#define APAPI_H + +EOT +while ($l = ) { + $l =~ s|\n$||; + next if ($l =~ m|^\s*#.*| or $l =~ m|^\s*$|); + if (($s1, $old, $s2, $new, $s3) = ($l =~ m|^(\s*)(\S+)(\s+)(\S+)(\s*)$|)) { + if ($new =~ m|^API_|) { + $new =~ s|^API_|ap_|; + $pt = &func_prototype($new); + if ($pt eq '') { + print STDERR "Sorry, prototype for `$new' cannot be determined automatically\n"; + print HDR "/* prototype for `$new' cannot be automatically determined */\n"; + } + else { + print HDR "extern $pt\n"; + } + } + } +} +print HDR <<'EOT'; + +#endif /* APAPI_H */ +EOT +close(CFG); +close(HDR); + diff --git a/APACHE_1_3b7/src/test/rename/apapi_compat.h b/APACHE_1_3b7/src/test/rename/apapi_compat.h new file mode 100644 index 0000000000..8e2e58798b --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/apapi_compat.h @@ -0,0 +1,525 @@ +/* +** apapi_compat.h -- Apache API symbol space +** backward compatibility defines +** +** INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED +** BACKWARD COMPATIBILITY FOR USED API SYMBOLS. +*/ + +#ifndef APAPI_COMPAT_H +#define APAPI_COMPAT_H + +/* + * Mapping of Apache 1.2 symbols to + * official Apache 1.3 API symbols + */ + +#define MD5Final ap_MD5Final +#define MD5Init ap_MD5Init +#define MD5Update ap_MD5Update +#define add_cgi_vars ap_add_cgi_vars +#define add_common_vars ap_add_common_vars +#define add_module ap_add_module +#define add_named_module ap_add_named_module +#define allow_options ap_allow_options +#define allow_overrides ap_allow_overrides +#define apapi_get_server_built ap_get_server_built +#define apapi_get_server_version ap_get_server_version +#define aplog_error ap_log_error +#define append_arrays ap_append_arrays +#define array_cat ap_array_cat +#define auth_name ap_auth_name +#define auth_type ap_auth_type +#define basic_http_header ap_basic_http_header +#define bclose ap_bclose +#define bcreate ap_bcreate +#define bfilbuf ap_bfilbuf +#define bfileno ap_bfileno +#define bflsbuf ap_bflsbuf +#define bflush ap_bflush +#define bgetopt ap_bgetopt +#define bgets ap_bgets +#define bhalfduplex ap_bhalfduplex +#define block_alarms ap_block_alarms +#define blookc ap_blookc +#define bnonblock ap_bnonblock +#define bonerror ap_bonerror +#define bprintf ap_bprintf +#define bpushfd ap_bpushfd +#define bputs ap_bputs +#define bread ap_bread +#define bsetflag ap_bsetflag +#define bsetopt ap_bsetopt +#define bskiplf ap_bskiplf +#define bvputs ap_bvputs +#define bwrite ap_bwrite +#define bytes_in_free_blocks ap_bytes_in_free_blocks +#define bytes_in_pool ap_bytes_in_pool +#define call_exec ap_call_exec +#define can_exec ap_can_exec +#define cfg_closefile ap_cfg_closefile +#define cfg_getc ap_cfg_getc +#define cfg_getline ap_cfg_getline +#define chdir_file ap_chdir_file +#define check_alarm ap_check_alarm +#define check_cmd_context ap_check_cmd_context +#define checkmask ap_checkmask +#define child_terminate ap_child_terminate +#define cleanup_for_exec ap_cleanup_for_exec +#define clear_module_list ap_clear_module_list +#define clear_pool ap_clear_pool +#define clear_table ap_clear_table +#define close_piped_log ap_close_piped_log +#define construct_server ap_construct_server +#define construct_url ap_construct_url +#define copy_array ap_copy_array +#define copy_array_hdr ap_copy_array_hdr +#define copy_table ap_copy_table +#define count_dirs ap_count_dirs +#define create_environment ap_create_environment +#define create_per_dir_config ap_create_per_dir_config +#define day_snames ap_day_snames +#define default_port_for_request ap_default_port_for_request +#define default_port_for_scheme ap_default_port_for_scheme +#define default_type ap_default_type +#define destroy_pool ap_destroy_pool +#define destroy_sub_req ap_destroy_sub_req +#define discard_request_body ap_discard_request_body +#define document_root ap_document_root +#define each_byterange ap_each_byterange +#define error_log2stderr ap_error_log2stderr +#define escape_html ap_escape_html +#define escape_path_segment ap_escape_path_segment +#define escape_shell_cmd ap_escape_shell_cmd +#define exists_scoreboard_image ap_exists_scoreboard_image +#define find_last_token ap_find_last_token +#define find_linked_module ap_find_linked_module +#define find_module_name ap_find_module_name +#define find_path_info ap_find_path_info +#define find_pool ap_find_pool +#define find_token ap_find_token +#define fnmatch ap_fnmatch +#define get_basic_auth_pw ap_get_basic_auth_pw +#define get_client_block ap_get_client_block +#define get_gmtoff ap_get_gmtoff +#define get_module_config ap_get_module_config +#define get_remote_host ap_get_remote_host +#define get_remote_logname ap_get_remote_logname +#define get_server_name ap_get_server_name +#define get_server_port ap_get_server_port +#define get_time ap_get_time +#define get_token ap_get_token +#define getparents ap_getparents +#define getword ap_getword +#define getword_conf ap_getword_conf +#define getword_conf_nc ap_getword_conf_nc +#define getword_nc ap_getword_nc +#define getword_nulls ap_getword_nulls +#define getword_nulls_nc ap_getword_nulls_nc +#define getword_white ap_getword_white +#define getword_white_nc ap_getword_white_nc +#define gm_timestr_822 ap_gm_timestr_822 +#define gname2id ap_gname2id +#define hard_timeout ap_hard_timeout +#define ht_time ap_ht_time +#define ind ap_ind +#define index_of_response ap_index_of_response +#define internal_redirect ap_internal_redirect +#define internal_redirect_handler ap_internal_redirect_handler +#define is_directory ap_is_directory +#define is_fnmatch ap_is_fnmatch +#define is_initial_req ap_is_initial_req +#define is_matchexp ap_is_matchexp +#define is_url ap_is_url +#define kill_cleanup ap_kill_cleanup +#define kill_cleanups_for_fd ap_kill_cleanups_for_fd +#define kill_cleanups_for_socket ap_kill_cleanups_for_socket +#define kill_timeout ap_kill_timeout +#define log_assert ap_log_assert +#define log_error ap_log_error_old +#define log_printf ap_log_printf +#define log_reason ap_log_reason +#define log_unixerr ap_log_unixerr +#define make_array ap_make_array +#define make_dirstr ap_make_dirstr +#define make_dirstr_parent ap_make_dirstr_parent +#define make_dirstr_prefix ap_make_dirstr_prefix +#define make_full_path ap_make_full_path +#define make_sub_pool ap_make_sub_pool +#define make_table ap_make_table +#define matches_request_vhost ap_matches_request_vhost +#define meets_conditions ap_meets_conditions +#define month_snames ap_month_snames +#define no2slash ap_no2slash +#define note_auth_failure ap_note_auth_failure +#define note_basic_auth_failure ap_note_basic_auth_failure +#define note_cleanups_for_fd ap_note_cleanups_for_fd +#define note_cleanups_for_file ap_note_cleanups_for_file +#define note_cleanups_for_socket ap_note_cleanups_for_socket +#define note_digest_auth_failure ap_note_digest_auth_failure +#define note_subprocess ap_note_subprocess +#define null_cleanup ap_null_cleanup +#define open_piped_log ap_open_piped_log +#define os_escape_path ap_os_escape_path +#define overlay_tables ap_overlay_tables +#define palloc ap_palloc +#define parseHTTPdate ap_parseHTTPdate +#define parse_hostinfo_components ap_parse_hostinfo_components +#define parse_uri ap_parse_uri +#define parse_uri_components ap_parse_uri_components +#define pcalloc ap_pcalloc +#define pcfg_open_custom ap_pcfg_open_custom +#define pcfg_openfile ap_pcfg_openfile +#define pclosedir ap_pclosedir +#define pclosef ap_pclosef +#define pclosesocket ap_pclosesocket +#define pduphostent ap_pduphostent +#define pfclose ap_pfclose +#define pfdopen ap_pfdopen +#define pfopen ap_pfopen +#define pgethostbyname ap_pgethostbyname +#define pool_is_ancestor ap_pool_is_ancestor +#define pool_join ap_pool_join +#define popendir ap_popendir +#define popenf ap_popenf +#define pregcomp ap_pregcomp +#define pregfree ap_pregfree +#define pregsub ap_pregsub +#define psignature ap_psignature +#define psocket ap_psocket +#define psprintf ap_psprintf +#define pstrcat ap_pstrcat +#define pstrdup ap_pstrdup +#define pstrndup ap_pstrndup +#define push_array ap_push_array +#define pvsprintf ap_pvsprintf +#define rationalize_mtime ap_rationalize_mtime +#define register_cleanup ap_register_cleanup +#define register_other_child ap_register_other_child +#define remove_module ap_remove_module +#define requires ap_requires +#define reset_timeout ap_reset_timeout +#define rflush ap_rflush +#define rind ap_rind +#define rprintf ap_rprintf +#define rputc ap_rputc +#define rputs ap_rputs +#define run_cleanup ap_run_cleanup +#define run_sub_req ap_run_sub_req +#define rvputs ap_rvputs +#define rwrite ap_rwrite +#define satisfies ap_satisfies +#define scan_script_header_err ap_scan_script_header_err +#define scan_script_header_err_buff ap_scan_script_header_err_buff +#define send_fb ap_send_fb +#define send_fb_length ap_send_fb_length +#define send_fd ap_send_fd +#define send_fd_length ap_send_fd_length +#define send_header_field ap_send_header_field +#define send_http_header ap_send_http_header +#define send_mmap ap_send_mmap +#define send_size ap_send_size +#define server_root_relative ap_server_root_relative +#define set_byterange ap_set_byterange +#define set_content_length ap_set_content_length +#define set_etag ap_set_etag +#define set_file_slot ap_set_file_slot +#define set_flag_slot ap_set_flag_slot +#define set_keepalive ap_set_keepalive +#define set_last_modified ap_set_last_modified +#define set_module_config ap_set_module_config +#define set_string_slot ap_set_string_slot +#define set_string_slot_lower ap_set_string_slot_lower +#define setup_client_block ap_setup_client_block +#define should_client_block ap_should_client_block +#define soft_timeout ap_soft_timeout +#define some_auth_required ap_some_auth_required +#define spawn_child_err ap_spawn_child_err +#define spawn_child_err_buff ap_spawn_child_err_buff +#define srm_command_loop ap_srm_command_loop +#define str_tolower ap_str_tolower +#define strcasecmp_match ap_strcasecmp_match +#define strcmp_match ap_strcmp_match +#define sub_req_lookup_file ap_sub_req_lookup_file +#define sub_req_lookup_uri ap_sub_req_lookup_uri +#define sync_scoreboard_image ap_sync_scoreboard_image +#define table_add ap_table_add +#define table_addn ap_table_addn +#define table_do ap_table_do +#define table_get ap_table_get +#define table_merge ap_table_merge +#define table_mergen ap_table_mergen +#define table_set ap_table_set +#define table_setn ap_table_setn +#define table_unset ap_table_unset +#define tm2sec ap_tm2sec +#define uname2id ap_uname2id +#define unblock_alarms ap_unblock_alarms +#define unescape_url ap_unescape_url +#define unparse_uri_components ap_unparse_uri_components +#define unregister_other_child ap_unregister_other_child +#define update_mtime ap_update_mtime +#define uudecode ap_uudecode +#define vbprintf ap_vbprintf + +/* + * Mapping of symbols which are private + * to Apache httpd and should not be considered + * part of the public API + */ + +#ifdef APAPI_STRICT + +#define add_per_dir_conf DO_NOT_USE_add_per_dir_conf +#define add_per_url_conf DO_NOT_USE_add_per_url_conf +#define bind_address DO_NOT_USE_bind_address +#define check_access DO_NOT_USE_check_access +#define check_auth DO_NOT_USE_check_auth +#define check_user_id DO_NOT_USE_check_user_id +#define child_exit_modules DO_NOT_USE_child_exit_modules +#define child_init_modules DO_NOT_USE_child_init_modules +#define core_reorder_directories DO_NOT_USE_core_reorder_directories +#define coredump_dir DO_NOT_USE_coredump_dir +#define create_request_config DO_NOT_USE_create_request_config +#define daemons_limit DO_NOT_USE_daemons_limit +#define daemons_max_free DO_NOT_USE_daemons_max_free +#define daemons_min_free DO_NOT_USE_daemons_min_free +#define daemons_to_start DO_NOT_USE_daemons_to_start +#define die DO_NOT_USE_die +#define dummy_mutex DO_NOT_USE_dummy_mutex +#define excess_requests_per_child DO_NOT_USE_excess_requests_per_child +#define finalize_request_protocol DO_NOT_USE_finalize_request_protocol +#define finalize_sub_req_protocol DO_NOT_USE_finalize_sub_req_protocol +#define find_command DO_NOT_USE_find_command +#define find_command_in_modules DO_NOT_USE_find_command_in_modules +#define find_types DO_NOT_USE_find_types +#define fini_vhost_config DO_NOT_USE_fini_vhost_config +#define force_library_loading DO_NOT_USE_force_library_loading +#define get_local_host DO_NOT_USE_get_local_host +#define get_virthost_addr DO_NOT_USE_get_virthost_addr +#define group_id DO_NOT_USE_group_id +#define handle_command DO_NOT_USE_handle_command +#define header_parse DO_NOT_USE_header_parse +#define init_alloc DO_NOT_USE_init_alloc +#define init_modules DO_NOT_USE_init_modules +#define init_vhost_config DO_NOT_USE_init_vhost_config +#define init_virtual_host DO_NOT_USE_init_virtual_host +#define invoke_handler DO_NOT_USE_invoke_handler +#define keepalive_timeout DO_NOT_USE_keepalive_timeout +#define limit_section DO_NOT_USE_limit_section +#define listenbacklog DO_NOT_USE_listenbacklog +#define listeners DO_NOT_USE_listeners +#define lock_fname DO_NOT_USE_lock_fname +#define log_pid DO_NOT_USE_log_pid +#define log_transaction DO_NOT_USE_log_transaction +#define max_requests_per_child DO_NOT_USE_max_requests_per_child +#define merge_per_dir_configs DO_NOT_USE_merge_per_dir_configs +#define open_logs DO_NOT_USE_open_logs +#define os_is_path_absolute DO_NOT_USE_os_is_path_absolute +#define parse_htaccess DO_NOT_USE_parse_htaccess +#define parse_vhost_addrs DO_NOT_USE_parse_vhost_addrs +#define pid_fname DO_NOT_USE_pid_fname +#define process_request DO_NOT_USE_process_request +#define process_resource_config DO_NOT_USE_process_resource_config +#define proxy_add_header DO_NOT_USE_proxy_add_header +#define proxy_c2hex DO_NOT_USE_proxy_c2hex +#define proxy_cache_check DO_NOT_USE_proxy_cache_check +#define proxy_cache_error DO_NOT_USE_proxy_cache_error +#define proxy_cache_tidy DO_NOT_USE_proxy_cache_tidy +#define proxy_cache_update DO_NOT_USE_proxy_cache_update +#define proxy_canon_netloc DO_NOT_USE_proxy_canon_netloc +#define proxy_canonenc DO_NOT_USE_proxy_canonenc +#define proxy_connect_handler DO_NOT_USE_proxy_connect_handler +#define proxy_date_canon DO_NOT_USE_proxy_date_canon +#define proxy_del_header DO_NOT_USE_proxy_del_header +#define proxy_doconnect DO_NOT_USE_proxy_doconnect +#define proxy_ftp_canon DO_NOT_USE_proxy_ftp_canon +#define proxy_ftp_handler DO_NOT_USE_proxy_ftp_handler +#define proxy_garbage_coll DO_NOT_USE_proxy_garbage_coll +#define proxy_garbage_init DO_NOT_USE_proxy_garbage_init +#define proxy_get_header DO_NOT_USE_proxy_get_header +#define proxy_hash DO_NOT_USE_proxy_hash +#define proxy_hex2c DO_NOT_USE_proxy_hex2c +#define proxy_hex2sec DO_NOT_USE_proxy_hex2sec +#define proxy_host2addr DO_NOT_USE_proxy_host2addr +#define proxy_http_canon DO_NOT_USE_proxy_http_canon +#define proxy_http_handler DO_NOT_USE_proxy_http_handler +#define proxy_is_domainname DO_NOT_USE_proxy_is_domainname +#define proxy_is_hostname DO_NOT_USE_proxy_is_hostname +#define proxy_is_ipaddr DO_NOT_USE_proxy_is_ipaddr +#define proxy_is_word DO_NOT_USE_proxy_is_word +#define proxy_liststr DO_NOT_USE_proxy_liststr +#define proxy_log_uerror DO_NOT_USE_proxy_log_uerror +#define proxy_read_headers DO_NOT_USE_proxy_read_headers +#define proxy_sec2hex DO_NOT_USE_proxy_sec2hex +#define proxy_send_fb DO_NOT_USE_proxy_send_fb +#define proxy_send_headers DO_NOT_USE_proxy_send_headers +#define proxyerror DO_NOT_USE_proxyerror +#define read_config DO_NOT_USE_read_config +#define read_request DO_NOT_USE_read_request +#define response_code_string DO_NOT_USE_response_code_string +#define restart_time DO_NOT_USE_restart_time +#define rfc1413 DO_NOT_USE_rfc1413 +#define rfc1413_timeout DO_NOT_USE_rfc1413_timeout +#define run_fixups DO_NOT_USE_run_fixups +#define run_post_read_request DO_NOT_USE_run_post_read_request +#define scoreboard_fname DO_NOT_USE_scoreboard_fname +#define scoreboard_image DO_NOT_USE_scoreboard_image +#define send_error_response DO_NOT_USE_send_error_response +#define send_http_options DO_NOT_USE_send_http_options +#define send_http_trace DO_NOT_USE_send_http_trace +#define server_argv0 DO_NOT_USE_server_argv0 +#define server_confname DO_NOT_USE_server_confname +#define server_post_read_config DO_NOT_USE_server_post_read_config +#define server_pre_read_config DO_NOT_USE_server_pre_read_config +#define server_root DO_NOT_USE_server_root +#define set_callback_and_alarm DO_NOT_USE_set_callback_and_alarm +#define set_name_virtual_host DO_NOT_USE_set_name_virtual_host +#define set_sub_req_protocol DO_NOT_USE_set_sub_req_protocol +#define setup_prelinked_modules DO_NOT_USE_setup_prelinked_modules +#define show_directives DO_NOT_USE_show_directives +#define show_modules DO_NOT_USE_show_modules +#define standalone DO_NOT_USE_standalone +#define start_restart DO_NOT_USE_start_restart +#define start_shutdown DO_NOT_USE_start_shutdown +#define suexec_enabled DO_NOT_USE_suexec_enabled +#define threads_per_child DO_NOT_USE_threads_per_child +#define time_process_request DO_NOT_USE_time_process_request +#define translate_name DO_NOT_USE_translate_name +#define update_child_status DO_NOT_USE_update_child_status +#define update_vhost_from_headers DO_NOT_USE_update_vhost_from_headers +#define update_vhost_given_ip DO_NOT_USE_update_vhost_given_ip +#define user_id DO_NOT_USE_user_id +#define user_name DO_NOT_USE_user_name +#define util_init DO_NOT_USE_util_init +#define util_uri_init DO_NOT_USE_util_uri_init + +#else /* APAPI_STRICT */ + +#define add_per_dir_conf apx_add_per_dir_conf +#define add_per_url_conf apx_add_per_url_conf +#define bind_address apx_bind_address +#define check_access apx_check_access +#define check_auth apx_check_auth +#define check_user_id apx_check_user_id +#define child_exit_modules apx_child_exit_modules +#define child_init_modules apx_child_init_modules +#define core_reorder_directories apx_core_reorder_directories +#define coredump_dir apx_coredump_dir +#define create_request_config apx_create_request_config +#define daemons_limit apx_daemons_limit +#define daemons_max_free apx_daemons_max_free +#define daemons_min_free apx_daemons_min_free +#define daemons_to_start apx_daemons_to_start +#define die apx_die +#define dummy_mutex apx_dummy_mutex +#define excess_requests_per_child apx_excess_requests_per_child +#define finalize_request_protocol apx_finalize_request_protocol +#define finalize_sub_req_protocol apx_finalize_sub_req_protocol +#define find_command apx_find_command +#define find_command_in_modules apx_find_command_in_modules +#define find_types apx_find_types +#define fini_vhost_config apx_fini_vhost_config +#define force_library_loading apx_force_library_loading +#define get_local_host apx_get_local_host +#define get_virthost_addr apx_get_virthost_addr +#define group_id apx_group_id +#define handle_command apx_handle_command +#define header_parse apx_header_parse +#define init_alloc apx_init_alloc +#define init_modules apx_init_modules +#define init_vhost_config apx_init_vhost_config +#define init_virtual_host apx_init_virtual_host +#define invoke_handler apx_invoke_handler +#define keepalive_timeout apx_keepalive_timeout +#define limit_section apx_limit_section +#define listenbacklog apx_listenbacklog +#define listeners apx_listeners +#define lock_fname apx_lock_fname +#define log_pid apx_log_pid +#define log_transaction apx_log_transaction +#define max_requests_per_child apx_max_requests_per_child +#define merge_per_dir_configs apx_merge_per_dir_configs +#define open_logs apx_open_logs +#define os_is_path_absolute apx_os_is_path_absolute +#define parse_htaccess apx_parse_htaccess +#define parse_vhost_addrs apx_parse_vhost_addrs +#define pid_fname apx_pid_fname +#define process_request apx_process_request +#define process_resource_config apx_process_resource_config +#define proxy_add_header apx_proxy_add_header +#define proxy_c2hex apx_proxy_c2hex +#define proxy_cache_check apx_proxy_cache_check +#define proxy_cache_error apx_proxy_cache_error +#define proxy_cache_tidy apx_proxy_cache_tidy +#define proxy_cache_update apx_proxy_cache_update +#define proxy_canon_netloc apx_proxy_canon_netloc +#define proxy_canonenc apx_proxy_canonenc +#define proxy_connect_handler apx_proxy_connect_handler +#define proxy_date_canon apx_proxy_date_canon +#define proxy_del_header apx_proxy_del_header +#define proxy_doconnect apx_proxy_doconnect +#define proxy_ftp_canon apx_proxy_ftp_canon +#define proxy_ftp_handler apx_proxy_ftp_handler +#define proxy_garbage_coll apx_proxy_garbage_coll +#define proxy_garbage_init apx_proxy_garbage_init +#define proxy_get_header apx_proxy_get_header +#define proxy_hash apx_proxy_hash +#define proxy_hex2c apx_proxy_hex2c +#define proxy_hex2sec apx_proxy_hex2sec +#define proxy_host2addr apx_proxy_host2addr +#define proxy_http_canon apx_proxy_http_canon +#define proxy_http_handler apx_proxy_http_handler +#define proxy_is_domainname apx_proxy_is_domainname +#define proxy_is_hostname apx_proxy_is_hostname +#define proxy_is_ipaddr apx_proxy_is_ipaddr +#define proxy_is_word apx_proxy_is_word +#define proxy_liststr apx_proxy_liststr +#define proxy_log_uerror apx_proxy_log_uerror +#define proxy_read_headers apx_proxy_read_headers +#define proxy_sec2hex apx_proxy_sec2hex +#define proxy_send_fb apx_proxy_send_fb +#define proxy_send_headers apx_proxy_send_headers +#define proxyerror apx_proxyerror +#define read_config apx_read_config +#define read_request apx_read_request +#define response_code_string apx_response_code_string +#define restart_time apx_restart_time +#define rfc1413 apx_rfc1413 +#define rfc1413_timeout apx_rfc1413_timeout +#define run_fixups apx_run_fixups +#define run_post_read_request apx_run_post_read_request +#define scoreboard_fname apx_scoreboard_fname +#define scoreboard_image apx_scoreboard_image +#define send_error_response apx_send_error_response +#define send_http_options apx_send_http_options +#define send_http_trace apx_send_http_trace +#define server_argv0 apx_server_argv0 +#define server_confname apx_server_confname +#define server_post_read_config apx_server_post_read_config +#define server_pre_read_config apx_server_pre_read_config +#define server_root apx_server_root +#define set_callback_and_alarm apx_set_callback_and_alarm +#define set_name_virtual_host apx_set_name_virtual_host +#define set_sub_req_protocol apx_set_sub_req_protocol +#define setup_prelinked_modules apx_setup_prelinked_modules +#define show_directives apx_show_directives +#define show_modules apx_show_modules +#define standalone apx_standalone +#define start_restart apx_start_restart +#define start_shutdown apx_start_shutdown +#define suexec_enabled apx_suexec_enabled +#define threads_per_child apx_threads_per_child +#define time_process_request apx_time_process_request +#define translate_name apx_translate_name +#define update_child_status apx_update_child_status +#define update_vhost_from_headers apx_update_vhost_from_headers +#define update_vhost_given_ip apx_update_vhost_given_ip +#define user_id apx_user_id +#define user_name apx_user_name +#define util_init apx_util_init +#define util_uri_init apx_util_uri_init + +#endif /* APAPI_STRICT */ + +#endif /* APAPI_COMPAT_H */ diff --git a/APACHE_1_3b7/src/test/rename/apapi_compat.h.mk b/APACHE_1_3b7/src/test/rename/apapi_compat.h.mk new file mode 100755 index 0000000000..ac43e9d1a7 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/apapi_compat.h.mk @@ -0,0 +1,90 @@ +: +eval 'exec perl -S $0 ${1+"$@"}' + if $running_under_some_shell; +## +## apapi_compat.h.mk +## + +# configuration +$config = "./rename.cf"; +$header = "./apapi_compat.h"; + +# read config file into hash +%PREFIX = (); +%SUBST = (); +open(CFG, "<$config") || die; +while () { + s|\n$||; + next if (m|^\s*#.*| or m|^\s*$|); + if (($symbolic, $real) = m|^\s*(\S+)\s*=\s*(\S+)\s*$|) { + $PREFIX{$symbolic} = $real; + } + elsif (($old, $new) = m|^\s*(\S+)\s+(\S+)\s*$|) { + foreach $p (keys(%PREFIX)) { + $new =~ s|^$p|$PREFIX{$p}|; + } + $SUBST{$old} = $new; + } +} +close(CFG); + +# create the C header file +open(FP, ">$header") || die; +print FP <<'EOT'; +/* +** apapi_compat.h -- Apache API symbol space +** backward compatibility defines +** +** INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED +** BACKWARD COMPATIBILITY FOR USED API SYMBOLS. +*/ + +#ifndef APAPI_COMPAT_H +#define APAPI_COMPAT_H + +/* + * Mapping of Apache 1.2 symbols to + * official Apache 1.3 API symbols + */ + +EOT +$apapiprefix = $PREFIX{'API_'}; +foreach $s (sort(keys(%SUBST))) { + $n = $SUBST{$s}; + next if ($n !~ m|^$apapiprefix|); + printf(FP "#define %-30s %s\n", $s, $n); +} +print FP <<'EOT'; + +/* + * Mapping of symbols which are private + * to Apache httpd and should not be considered + * part of the public API + */ + +#ifdef APAPI_STRICT + +EOT +foreach $s (sort(keys(%SUBST))) { + $n = $SUBST{$s}; + next if ($n =~ m|^$apapiprefix|); + printf(FP "#define %-30s %s\n", $s, "DO_NOT_USE_$s"); +} +print FP <<'EOT'; + +#else /* APAPI_STRICT */ + +EOT +foreach $s (sort(keys(%SUBST))) { + $n = $SUBST{$s}; + next if ($n =~ m|^$apapiprefix|); + printf(FP "#define %-30s %s\n", $s, $n); +} +print FP <<'EOT'; + +#endif /* APAPI_STRICT */ + +#endif /* APAPI_COMPAT_H */ +EOT +close(FP); + diff --git a/APACHE_1_3b7/src/test/rename/compat.h b/APACHE_1_3b7/src/test/rename/compat.h new file mode 100644 index 0000000000..3bd365cf1c --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/compat.h @@ -0,0 +1,393 @@ +/* +** compat.h -- Apache Backward Compatibility +** +** INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED +** BACKWARD COMPATIBILITY TO OLD APACHE RESOURCES. +*/ + +#ifndef APACHE_COMPAT_H +#define APACHE_COMPAT_H + +/* + * Mapping of Apache 1.2 global symbols to the + * namespace conflict free variants used in Apache 1.3 + */ + +#define MD5Final ap_MD5Final +#define MD5Init ap_MD5Init +#define MD5Update ap_MD5Update +#define acquire_mutex ap_acquire_mutex +#define add_cgi_vars ap_add_cgi_vars +#define add_common_vars ap_add_common_vars +#define add_module ap_add_module +#define add_named_module ap_add_named_module +#define add_per_dir_conf ap_add_per_dir_conf +#define add_per_url_conf ap_add_per_url_conf +#define allow_options ap_allow_options +#define allow_overrides ap_allow_overrides +#define apapi_get_server_built ap_get_server_built +#define apapi_get_server_version ap_get_server_version +#define aplog_error ap_log_error +#define append_arrays ap_append_arrays +#define array_cat ap_array_cat +#define auth_name ap_auth_name +#define auth_type ap_auth_type +#define basic_http_header ap_basic_http_header +#define bclose ap_bclose +#define bcreate ap_bcreate +#define bfilbuf ap_bfilbuf +#define bfileno ap_bfileno +#define bflsbuf ap_bflsbuf +#define bflush ap_bflush +#define bgetopt ap_bgetopt +#define bgets ap_bgets +#define bhalfduplex ap_bhalfduplex +#define bind_address ap_bind_address +#define block_alarms ap_block_alarms +#define blookc ap_blookc +#define bnonblock ap_bnonblock +#define bonerror ap_bonerror +#define bprintf ap_bprintf +#define bpushfd ap_bpushfd +#define bputs ap_bputs +#define bread ap_bread +#define bsetflag ap_bsetflag +#define bsetopt ap_bsetopt +#define bskiplf ap_bskiplf +#define bvputs ap_bvputs +#define bwrite ap_bwrite +#define bytes_in_free_blocks ap_bytes_in_free_blocks +#define bytes_in_pool ap_bytes_in_pool +#define call_exec ap_call_exec +#define can_exec ap_can_exec +#define cfg_closefile ap_cfg_closefile +#define cfg_getc ap_cfg_getc +#define cfg_getline ap_cfg_getline +#define chdir_file ap_chdir_file +#define check_access ap_check_access +#define check_alarm ap_check_alarm +#define check_auth ap_check_auth +#define check_cmd_context ap_check_cmd_context +#define check_user_id ap_check_user_id +#define checkmask ap_checkmask +#define child_exit_modules ap_child_exit_modules +#define child_init_modules ap_child_init_modules +#define child_terminate ap_child_terminate +#define cleanup_for_exec ap_cleanup_for_exec +#define clear_module_list ap_clear_module_list +#define clear_pool ap_clear_pool +#define clear_table ap_clear_table +#define close_piped_log ap_close_piped_log +#define construct_server ap_construct_server +#define construct_url ap_construct_url +#define copy_array ap_copy_array +#define copy_array_hdr ap_copy_array_hdr +#define copy_table ap_copy_table +#define core_reorder_directories ap_core_reorder_directories +#define coredump_dir ap_coredump_dir +#define count_dirs ap_count_dirs +#define create_environment ap_create_environment +#define create_mutex ap_create_mutex +#define create_per_dir_config ap_create_per_dir_config +#define create_request_config ap_create_request_config +#define daemons_limit ap_daemons_limit +#define daemons_max_free ap_daemons_max_free +#define daemons_min_free ap_daemons_min_free +#define daemons_to_start ap_daemons_to_start +#define day_snames ap_day_snames +#define default_port_for_request ap_default_port_for_request +#define default_port_for_scheme ap_default_port_for_scheme +#define default_type ap_default_type +#define destroy_mutex ap_destroy_mutex +#define destroy_pool ap_destroy_pool +#define destroy_sub_req ap_destroy_sub_req +#define die ap_die +#define discard_request_body ap_discard_request_body +#define document_root ap_document_root +#define dummy_mutex ap_dummy_mutex +#define each_byterange ap_each_byterange +#define error_log2stderr ap_error_log2stderr +#define escape_html ap_escape_html +#define escape_path_segment ap_escape_path_segment +#define escape_shell_cmd ap_escape_shell_cmd +#define excess_requests_per_child ap_excess_requests_per_child +#define exists_scoreboard_image ap_exists_scoreboard_image +#define finalize_request_protocol ap_finalize_request_protocol +#define finalize_sub_req_protocol ap_finalize_sub_req_protocol +#define find_command ap_find_command +#define find_command_in_modules ap_find_command_in_modules +#define find_last_token ap_find_last_token +#define find_linked_module ap_find_linked_module +#define find_module_name ap_find_module_name +#define find_path_info ap_find_path_info +#define find_pool ap_find_pool +#define find_token ap_find_token +#define find_types ap_find_types +#define fini_vhost_config ap_fini_vhost_config +#define fnmatch ap_fnmatch +#define force_library_loading ap_force_library_loading +#define get_basic_auth_pw ap_get_basic_auth_pw +#define get_client_block ap_get_client_block +#define get_gmtoff ap_get_gmtoff +#define get_local_host ap_get_local_host +#define get_module_config ap_get_module_config +#define get_remote_host ap_get_remote_host +#define get_remote_logname ap_get_remote_logname +#define get_server_name ap_get_server_name +#define get_server_port ap_get_server_port +#define get_time ap_get_time +#define get_token ap_get_token +#define get_virthost_addr ap_get_virthost_addr +#define getparents ap_getparents +#define getword ap_getword +#define getword_conf ap_getword_conf +#define getword_conf_nc ap_getword_conf_nc +#define getword_nc ap_getword_nc +#define getword_nulls ap_getword_nulls +#define getword_nulls_nc ap_getword_nulls_nc +#define getword_white ap_getword_white +#define getword_white_nc ap_getword_white_nc +#define gm_timestr_822 ap_gm_timestr_822 +#define gname2id ap_gname2id +#define group_id ap_group_id +#define handle_command ap_handle_command +#define hard_timeout ap_hard_timeout +#define header_parse ap_header_parse +#define ht_time ap_ht_time +#define ind ap_ind +#define index_of_response ap_index_of_response +#define init_alloc ap_init_alloc +#define init_modules ap_init_modules +#define init_vhost_config ap_init_vhost_config +#define init_virtual_host ap_init_virtual_host +#define internal_redirect ap_internal_redirect +#define internal_redirect_handler ap_internal_redirect_handler +#define invoke_handler ap_invoke_handler +#define is_directory ap_is_directory +#define is_fnmatch ap_is_fnmatch +#define is_initial_req ap_is_initial_req +#define is_matchexp ap_is_matchexp +#define is_url ap_is_url +#define keepalive_timeout ap_keepalive_timeout +#define kill_cleanup ap_kill_cleanup +#define kill_cleanups_for_fd ap_kill_cleanups_for_fd +#define kill_cleanups_for_socket ap_kill_cleanups_for_socket +#define kill_timeout ap_kill_timeout +#define limit_section ap_limit_section +#define listenbacklog ap_listenbacklog +#define listeners ap_listeners +#define lock_fname ap_lock_fname +#define log_assert ap_log_assert +#define log_error ap_log_error_old +#define log_pid ap_log_pid +#define log_printf ap_log_printf +#define log_reason ap_log_reason +#define log_transaction ap_log_transaction +#define log_unixerr ap_log_unixerr +#define make_array ap_make_array +#define make_dirstr ap_make_dirstr +#define make_dirstr_parent ap_make_dirstr_parent +#define make_dirstr_prefix ap_make_dirstr_prefix +#define make_full_path ap_make_full_path +#define make_sub_pool ap_make_sub_pool +#define make_table ap_make_table +#define matches_request_vhost ap_matches_request_vhost +#define max_requests_per_child ap_max_requests_per_child +#define meets_conditions ap_meets_conditions +#define merge_per_dir_configs ap_merge_per_dir_configs +#define month_snames ap_month_snames +#define no2slash ap_no2slash +#define note_auth_failure ap_note_auth_failure +#define note_basic_auth_failure ap_note_basic_auth_failure +#define note_cleanups_for_fd ap_note_cleanups_for_fd +#define note_cleanups_for_file ap_note_cleanups_for_file +#define note_cleanups_for_socket ap_note_cleanups_for_socket +#define note_digest_auth_failure ap_note_digest_auth_failure +#define note_subprocess ap_note_subprocess +#define null_cleanup ap_null_cleanup +#define open_logs ap_open_logs +#define open_mutex ap_open_mutex +#define open_piped_log ap_open_piped_log +#define os_canonical_filename ap_canonical_filename +#define os_escape_path ap_escape_path +#define os_is_path_absolute ap_is_path_absolute +#define overlay_tables ap_overlay_tables +#define palloc ap_palloc +#define parseHTTPdate ap_parseHTTPdate +#define parse_hostinfo_components ap_parse_hostinfo_components +#define parse_htaccess ap_parse_htaccess +#define parse_uri ap_parse_uri +#define parse_uri_components ap_parse_uri_components +#define parse_vhost_addrs ap_parse_vhost_addrs +#define pcalloc ap_pcalloc +#define pcfg_open_custom ap_pcfg_open_custom +#define pcfg_openfile ap_pcfg_openfile +#define pclosedir ap_pclosedir +#define pclosef ap_pclosef +#define pclosesocket ap_pclosesocket +#define pduphostent ap_pduphostent +#define pfclose ap_pfclose +#define pfdopen ap_pfdopen +#define pfopen ap_pfopen +#define pgethostbyname ap_pgethostbyname +#define pid_fname ap_pid_fname +#define pool_is_ancestor ap_pool_is_ancestor +#define pool_join ap_pool_join +#define popendir ap_popendir +#define popenf ap_popenf +#define pregcomp ap_pregcomp +#define pregfree ap_pregfree +#define pregsub ap_pregsub +#define process_request ap_process_request +#define process_resource_config ap_process_resource_config +#define proxy_add_header ap_proxy_add_header +#define proxy_c2hex ap_proxy_c2hex +#define proxy_cache_check ap_proxy_cache_check +#define proxy_cache_error ap_proxy_cache_error +#define proxy_cache_tidy ap_proxy_cache_tidy +#define proxy_cache_update ap_proxy_cache_update +#define proxy_canon_netloc ap_proxy_canon_netloc +#define proxy_canonenc ap_proxy_canonenc +#define proxy_connect_handler ap_proxy_connect_handler +#define proxy_date_canon ap_proxy_date_canon +#define proxy_del_header ap_proxy_del_header +#define proxy_doconnect ap_proxy_doconnect +#define proxy_ftp_canon ap_proxy_ftp_canon +#define proxy_ftp_handler ap_proxy_ftp_handler +#define proxy_garbage_coll ap_proxy_garbage_coll +#define proxy_garbage_init ap_proxy_garbage_init +#define proxy_get_header ap_proxy_get_header +#define proxy_hash ap_proxy_hash +#define proxy_hex2c ap_proxy_hex2c +#define proxy_hex2sec ap_proxy_hex2sec +#define proxy_host2addr ap_proxy_host2addr +#define proxy_http_canon ap_proxy_http_canon +#define proxy_http_handler ap_proxy_http_handler +#define proxy_is_domainname ap_proxy_is_domainname +#define proxy_is_hostname ap_proxy_is_hostname +#define proxy_is_ipaddr ap_proxy_is_ipaddr +#define proxy_is_word ap_proxy_is_word +#define proxy_liststr ap_proxy_liststr +#define proxy_log_uerror ap_proxy_log_uerror +#define proxy_read_headers ap_proxy_read_headers +#define proxy_sec2hex ap_proxy_sec2hex +#define proxy_send_fb ap_proxy_send_fb +#define proxy_send_headers ap_proxy_send_headers +#define proxyerror ap_proxyerror +#define psignature ap_psignature +#define psocket ap_psocket +#define psprintf ap_psprintf +#define pstrcat ap_pstrcat +#define pstrdup ap_pstrdup +#define pstrndup ap_pstrndup +#define push_array ap_push_array +#define pvsprintf ap_pvsprintf +#define rationalize_mtime ap_rationalize_mtime +#define read_config ap_read_config +#define read_request ap_read_request +#define register_cleanup ap_register_cleanup +#define register_other_child ap_register_other_child +#define release_mutex ap_release_mutex +#define remove_module ap_remove_module +#define requires ap_requires +#define reset_timeout ap_reset_timeout +#define response_code_string ap_response_code_string +#define restart_time ap_restart_time +#define rfc1413 ap_rfc1413 +#define rfc1413_timeout ap_rfc1413_timeout +#define rflush ap_rflush +#define rind ap_rind +#define rprintf ap_rprintf +#define rputc ap_rputc +#define rputs ap_rputs +#define run_cleanup ap_run_cleanup +#define run_fixups ap_run_fixups +#define run_post_read_request ap_run_post_read_request +#define run_sub_req ap_run_sub_req +#define rvputs ap_rvputs +#define rwrite ap_rwrite +#define satisfies ap_satisfies +#define scan_script_header_err ap_scan_script_header_err +#define scan_script_header_err_buff ap_scan_script_header_err_buff +#define scoreboard_fname ap_scoreboard_fname +#define scoreboard_image ap_scoreboard_image +#define send_error_response ap_send_error_response +#define send_fb ap_send_fb +#define send_fb_length ap_send_fb_length +#define send_fd ap_send_fd +#define send_fd_length ap_send_fd_length +#define send_header_field ap_send_header_field +#define send_http_header ap_send_http_header +#define send_http_options ap_send_http_options +#define send_http_trace ap_send_http_trace +#define send_mmap ap_send_mmap +#define send_size ap_send_size +#define server_argv0 ap_server_argv0 +#define server_confname ap_server_confname +#define server_post_read_config ap_server_post_read_config +#define server_pre_read_config ap_server_pre_read_config +#define server_root ap_server_root +#define server_root_relative ap_server_root_relative +#define set_byterange ap_set_byterange +#define set_callback_and_alarm ap_set_callback_and_alarm +#define set_content_length ap_set_content_length +#define set_etag ap_set_etag +#define set_file_slot ap_set_file_slot +#define set_flag_slot ap_set_flag_slot +#define set_keepalive ap_set_keepalive +#define set_last_modified ap_set_last_modified +#define set_module_config ap_set_module_config +#define set_name_virtual_host ap_set_name_virtual_host +#define set_string_slot ap_set_string_slot +#define set_string_slot_lower ap_set_string_slot_lower +#define set_sub_req_protocol ap_set_sub_req_protocol +#define setup_client_block ap_setup_client_block +#define setup_prelinked_modules ap_setup_prelinked_modules +#define should_client_block ap_should_client_block +#define show_directives ap_show_directives +#define show_modules ap_show_modules +#define soft_timeout ap_soft_timeout +#define some_auth_required ap_some_auth_required +#define spawn_child_err ap_spawn_child_err +#define spawn_child_err_buff ap_spawn_child_err_buff +#define srm_command_loop ap_srm_command_loop +#define standalone ap_standalone +#define start_restart ap_start_restart +#define start_shutdown ap_start_shutdown +#define str_tolower ap_str_tolower +#define strcasecmp_match ap_strcasecmp_match +#define strcmp_match ap_strcmp_match +#define sub_req_lookup_file ap_sub_req_lookup_file +#define sub_req_lookup_uri ap_sub_req_lookup_uri +#define suexec_enabled ap_suexec_enabled +#define sync_scoreboard_image ap_sync_scoreboard_image +#define table_add ap_table_add +#define table_addn ap_table_addn +#define table_do ap_table_do +#define table_get ap_table_get +#define table_merge ap_table_merge +#define table_mergen ap_table_mergen +#define table_set ap_table_set +#define table_setn ap_table_setn +#define table_unset ap_table_unset +#define threads_per_child ap_threads_per_child +#define time_process_request ap_time_process_request +#define tm2sec ap_tm2sec +#define translate_name ap_translate_name +#define uname2id ap_uname2id +#define unblock_alarms ap_unblock_alarms +#define unescape_url ap_unescape_url +#define unparse_uri_components ap_unparse_uri_components +#define unregister_other_child ap_unregister_other_child +#define update_child_status ap_update_child_status +#define update_mtime ap_update_mtime +#define update_vhost_from_headers ap_update_vhost_from_headers +#define update_vhost_given_ip ap_update_vhost_given_ip +#define user_id ap_user_id +#define user_name ap_user_name +#define util_init ap_util_init +#define util_uri_init ap_util_uri_init +#define uudecode ap_uudecode +#define vbprintf ap_vbprintf + +#endif /* APACHE_COMPAT_H */ diff --git a/APACHE_1_3b7/src/test/rename/compat.h.mk b/APACHE_1_3b7/src/test/rename/compat.h.mk new file mode 100755 index 0000000000..ed1c4107af --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/compat.h.mk @@ -0,0 +1,59 @@ +: +eval 'exec perl -S $0 ${1+"$@"}' + if $running_under_some_shell; +## +## compat.h.mk +## + +# configuration +$config = "./rename.cf"; +$header = "./compat.h"; + +# read config file into hash +%PREFIX = (); +%SUBST = (); +open(CFG, "<$config") || die; +while () { + s|\n$||; + next if (m|^\s*#.*| or m|^\s*$|); + if (($symbolic, $real) = m|^\s*(\S+)\s*=\s*(\S+)\s*$|) { + $PREFIX{$symbolic} = $real; + } + elsif (($old, $new) = m|^\s*(\S+)\s+(\S+)\s*$|) { + foreach $p (keys(%PREFIX)) { + $new =~ s|^$p|$PREFIX{$p}|; + } + $SUBST{$old} = $new; + } +} +close(CFG); + +# create the C header file +open(FP, ">$header") || die; +print FP <<'EOT'; +/* +** compat.h -- Apache Backward Compatibility +** +** INCLUDE THIS HEADER FILE ONLY IF YOU REALLY NEED +** BACKWARD COMPATIBILITY TO OLD APACHE RESOURCES. +*/ + +#ifndef APACHE_COMPAT_H +#define APACHE_COMPAT_H + +/* + * Mapping of Apache 1.2 global symbols to the + * namespace conflict free variants used in Apache 1.3 + */ + +EOT +foreach $s (sort(keys(%SUBST))) { + $n = $SUBST{$s}; + printf(FP "#define %-30s %s\n", $s, $n); +} +print FP <<'EOT'; + +#endif /* APACHE_COMPAT_H */ +EOT +close(FP); + diff --git a/APACHE_1_3b7/src/test/rename/csubst/Makefile b/APACHE_1_3b7/src/test/rename/csubst/Makefile new file mode 100644 index 0000000000..655704fccb --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/csubst/Makefile @@ -0,0 +1,34 @@ + +CC = gcc +CFLAGS = -O2 -I. +LDFLAGS = +LIBS = + +LEX = flex +YACC = bison -y + +PROG = csubst +OBJS = csubst.o lexer.o util.o + +.c.o: + $(CC) $(CFLAGS) -c $< + +all: $(PROG) + +$(PROG): $(OBJS) + $(CC) $(LDFLAGS) -o $(PROG) $(OBJS) $(LIBS) + +lexer.c: lexer.l + $(LEX) lexer.l + mv lex.yy.c lexer.c + +clean: + -rm -f $(PROG) *.o + +distclean: clean + +realclean: distclean + -rm -f lexer.c + +mostlyclean: clean + diff --git a/APACHE_1_3b7/src/test/rename/csubst/csubst.c b/APACHE_1_3b7/src/test/rename/csubst/csubst.c new file mode 100644 index 0000000000..5da2bb8c97 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/csubst/csubst.c @@ -0,0 +1,131 @@ + +#include +#include +#include +#include + +#include "util.h" + +#include "tokens.h" + +int opt_directives; + +/* From lexer.c */ +extern char *yytext; +extern char *token_buffer; +extern FILE *yyin; +extern int yylex(void); +extern void init_lex(void); +extern void done_lex(void); + +static FILE *output_file = stdout; + +static struct { + char *old; + char *new; +} map[1024]; + +int mapidx = 0; + +static void process_token(int token, char *buf) +{ + int i; + + if (token == IDENTIFIER) { + for (i = 0; map[i].old != NULL; i++) { + if (strcmp(map[i].old, buf) == 0) { + printf("Subst: %s -> %s\n", map[i].old, map[i].new); + buf = map[i].new; + break; + } + } + } + fputs(buf, output_file); +} + +static void parse(void) +{ + int tk; + + while ((tk = yylex()) != 0) + switch (tk) { + case COMMENT: + case DIRECTIVE: + case STRING: + process_token(tk, token_buffer); + break; + default: + process_token(tk, yytext); + break; + } +} + +static void process_file(char *filename) +{ + if (filename != NULL && strcmp(filename, "-") != 0) { + if ((yyin = fopen(filename, "r")) == NULL) + err(1, "%s", filename); + } + else + yyin = stdin; + + init_lex(); + parse(); + done_lex(); + + if (yyin != stdin) + fclose(yyin); +} + +/* + * Output the program syntax then exit. + */ +static void usage(void) +{ + fprintf(stderr, "usage: csubst [-o file] [-s old:new] [file ...]\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int c; + char *cp; + + while ((c = getopt(argc, argv, "o:s:")) != -1) + switch (c) { + case 's': + if ((cp = strchr(optarg, ':')) == NULL) + err(1, "invalid subst %s", optarg); + *cp++ = '\0'; + map[mapidx].old = strdup(optarg); + map[mapidx].new = strdup(cp); + mapidx++; + break; + case 'o': + if (output_file != stdout) + fclose(output_file); + if ((output_file = fopen(optarg, "w")) == NULL) + err(1, "%s", optarg); + break; + case '?': + default: + usage(); + /* NOTREACHED */ + } + argc -= optind; + argv += optind; + + opt_directives = 1; + map[mapidx].old = NULL; + map[mapidx].new = NULL; + + if (argc < 1) + process_file(NULL); + else + while (*argv) + process_file(*argv++); + if (output_file != stdout) + fclose(output_file); + + return 0; +} diff --git a/APACHE_1_3b7/src/test/rename/csubst/lexer.c b/APACHE_1_3b7/src/test/rename/csubst/lexer.c new file mode 100644 index 0000000000..a171868add --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/csubst/lexer.c @@ -0,0 +1,2235 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/striker/cvs2svn/dumps/apache-1.3/../../apache-1.3/src/test/rename/csubst/lexer.c,v 1.2 1998/04/06 06:16:45 rse Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 93 +#define YY_END_OF_BUFFER 94 +static yyconst short int yy_accept[233] = + { 0, + 0, 0, 94, 92, 91, 91, 79, 44, 2, 85, + 78, 92, 73, 74, 83, 82, 70, 81, 77, 84, + 39, 39, 71, 67, 86, 72, 87, 90, 35, 75, + 76, 88, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 68, 89, 69, + 80, 65, 51, 60, 52, 0, 0, 49, 57, 47, + 58, 48, 59, 0, 42, 1, 50, 43, 37, 0, + 38, 0, 39, 56, 62, 64, 63, 55, 35, 53, + 35, 35, 35, 35, 35, 35, 10, 35, 35, 35, + 35, 35, 35, 18, 35, 35, 35, 35, 35, 35, + + 35, 35, 35, 35, 35, 54, 61, 40, 66, 0, + 42, 42, 0, 43, 37, 0, 41, 36, 46, 45, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 16, 35, 19, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, + 42, 0, 42, 0, 43, 41, 36, 3, 35, 5, + 6, 35, 35, 35, 35, 12, 13, 35, 35, 17, + 20, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 32, 35, 35, 0, 42, 4, 7, 35, + 35, 35, 35, 15, 35, 35, 23, 35, 35, 35, + + 35, 35, 35, 30, 35, 35, 34, 35, 35, 11, + 14, 35, 22, 24, 25, 26, 27, 28, 35, 35, + 35, 35, 9, 35, 29, 35, 35, 8, 21, 31, + 33, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 20, 21, 22, + 23, 24, 25, 1, 26, 26, 26, 26, 27, 28, + 29, 29, 29, 29, 29, 30, 29, 29, 29, 29, + 29, 29, 29, 29, 31, 29, 29, 32, 29, 29, + 33, 34, 35, 36, 29, 1, 37, 38, 39, 40, + + 41, 42, 43, 44, 45, 29, 46, 47, 48, 49, + 50, 51, 29, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[65] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, + 1, 1, 1, 1, 1, 3, 3, 3, 4, 4, + 4, 4, 1, 1, 1, 1, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 1, 1 + } ; + +static yyconst short int yy_base[236] = + { 0, + 0, 0, 354, 355, 355, 355, 330, 355, 355, 329, + 57, 317, 355, 355, 327, 53, 355, 54, 52, 60, + 68, 63, 355, 355, 51, 326, 65, 355, 0, 355, + 355, 325, 292, 294, 64, 55, 64, 56, 295, 43, + 294, 302, 75, 283, 292, 290, 295, 355, 68, 355, + 355, 355, 355, 355, 355, 93, 122, 355, 355, 355, + 355, 355, 355, 322, 115, 355, 355, 119, 149, 135, + 128, 0, 154, 314, 355, 355, 355, 313, 0, 355, + 281, 293, 280, 295, 282, 288, 274, 275, 272, 272, + 275, 272, 269, 0, 268, 272, 74, 270, 64, 60, + + 274, 267, 22, 94, 272, 355, 355, 355, 355, 173, + 355, 175, 193, 355, 168, 117, 200, 190, 355, 355, + 266, 278, 273, 261, 98, 275, 273, 269, 261, 267, + 270, 0, 256, 0, 262, 259, 248, 250, 252, 259, + 245, 243, 243, 255, 245, 249, 253, 251, 238, 145, + 206, 214, 355, 159, 221, 355, 224, 0, 238, 0, + 0, 229, 237, 225, 231, 0, 0, 225, 222, 0, + 0, 222, 222, 219, 231, 220, 221, 226, 225, 222, + 212, 217, 0, 205, 215, 195, 239, 0, 0, 203, + 203, 205, 195, 0, 189, 192, 0, 198, 193, 192, + + 172, 166, 166, 0, 151, 152, 0, 134, 133, 0, + 0, 141, 0, 0, 0, 0, 0, 0, 132, 130, + 122, 114, 0, 92, 0, 100, 80, 0, 0, 0, + 0, 355, 286, 288, 113 + } ; + +static yyconst short int yy_def[236] = + { 0, + 232, 1, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 233, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 234, 232, + 232, 232, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 232, 232, 232, + 232, 232, 232, 232, 232, 233, 233, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 235, 232, 232, 232, 232, 232, 232, 234, 232, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + + 234, 234, 234, 234, 234, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 235, 232, 232, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 232, + 232, 232, 232, 232, 232, 232, 232, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 232, 232, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 0, 232, 232, 232 + } ; + +static yyconst short int yy_nxt[420] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 29, 29, 29, 29, + 29, 29, 30, 4, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 29, 40, 29, 41, 29, 29, 29, + 29, 42, 43, 44, 45, 46, 47, 29, 29, 29, + 48, 49, 50, 51, 54, 59, 145, 64, 61, 65, + 65, 66, 74, 75, 146, 60, 62, 63, 68, 55, + 73, 73, 67, 68, 94, 69, 69, 77, 78, 70, + 106, 95, 71, 71, 70, 86, 141, 71, 71, 72, + + 83, 108, 91, 70, 87, 92, 139, 84, 70, 71, + 88, 142, 89, 85, 71, 118, 136, 71, 98, 99, + 231, 90, 71, 140, 232, 72, 57, 137, 100, 107, + 56, 101, 65, 65, 117, 117, 112, 112, 147, 230, + 148, 110, 111, 229, 111, 113, 114, 116, 114, 116, + 162, 163, 117, 117, 228, 110, 111, 71, 71, 113, + 114, 111, 151, 151, 68, 114, 69, 69, 227, 68, + 226, 73, 73, 225, 71, 70, 155, 155, 115, 115, + 70, 224, 71, 71, 71, 150, 223, 150, 222, 70, + 151, 151, 112, 112, 70, 115, 221, 115, 115, 220, + + 71, 152, 153, 115, 153, 154, 219, 154, 71, 218, + 155, 155, 187, 187, 115, 152, 153, 117, 117, 157, + 157, 153, 115, 151, 151, 217, 186, 156, 186, 156, + 216, 187, 187, 111, 215, 111, 157, 214, 155, 155, + 213, 156, 212, 211, 157, 210, 156, 111, 114, 209, + 114, 208, 111, 157, 157, 207, 187, 187, 206, 205, + 204, 203, 114, 202, 201, 200, 153, 114, 153, 199, + 157, 198, 197, 196, 195, 194, 193, 192, 157, 191, + 153, 190, 189, 188, 185, 153, 56, 184, 56, 56, + 79, 79, 183, 182, 181, 180, 179, 178, 177, 176, + + 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, + 165, 164, 161, 160, 159, 158, 149, 144, 143, 138, + 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, + 125, 124, 123, 122, 121, 120, 119, 109, 105, 104, + 103, 102, 97, 96, 93, 82, 81, 80, 76, 58, + 57, 53, 52, 232, 3, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232 + } ; + +static yyconst short int yy_chk[420] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 11, 16, 103, 19, 18, 19, + 19, 20, 25, 25, 103, 16, 18, 18, 22, 11, + 22, 22, 20, 21, 40, 21, 21, 27, 27, 22, + 49, 40, 22, 22, 21, 36, 100, 21, 21, 21, + + 35, 56, 38, 22, 36, 38, 99, 35, 21, 22, + 37, 100, 37, 35, 21, 235, 97, 22, 43, 43, + 227, 37, 21, 99, 57, 21, 56, 97, 43, 49, + 57, 43, 65, 65, 116, 116, 68, 68, 104, 226, + 104, 65, 65, 224, 65, 68, 68, 70, 68, 70, + 125, 125, 70, 70, 222, 65, 65, 71, 71, 68, + 68, 65, 150, 150, 69, 68, 69, 69, 221, 73, + 220, 73, 73, 219, 71, 69, 154, 154, 69, 69, + 73, 212, 71, 73, 73, 110, 209, 110, 208, 69, + 110, 110, 112, 112, 73, 69, 206, 115, 115, 205, + + 73, 112, 112, 69, 112, 113, 203, 113, 73, 202, + 113, 113, 186, 186, 115, 112, 112, 117, 117, 118, + 118, 112, 115, 151, 151, 201, 152, 117, 152, 117, + 200, 152, 152, 151, 199, 151, 118, 198, 155, 155, + 196, 117, 195, 193, 118, 192, 117, 151, 155, 191, + 155, 190, 151, 157, 157, 185, 187, 187, 184, 182, + 181, 180, 155, 179, 178, 177, 187, 155, 187, 176, + 157, 175, 174, 173, 172, 169, 168, 165, 157, 164, + 187, 163, 162, 159, 149, 187, 233, 148, 233, 233, + 234, 234, 147, 146, 145, 144, 143, 142, 141, 140, + + 139, 138, 137, 136, 135, 133, 131, 130, 129, 128, + 127, 126, 124, 123, 122, 121, 105, 102, 101, 98, + 96, 95, 93, 92, 91, 90, 89, 88, 87, 86, + 85, 84, 83, 82, 81, 78, 74, 64, 47, 46, + 45, 44, 42, 41, 39, 34, 33, 32, 26, 15, + 12, 10, 7, 3, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "lexer.l" +#define INITIAL 0 +#line 10 "lexer.l" +#include +#include +#include + +#include "util.h" +#include "tokens.h" + +extern int opt_directives; + +static void string(void); +static void comment(void); +static int directive(void); + +static int yywrap(void) { return 1; } +#line 549 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 26 "lexer.l" + + +#line 703 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 233 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 355 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 28 "lexer.l" +{ comment(); return COMMENT; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 29 "lexer.l" +{ return directive(); } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 31 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 32 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 33 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 34 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 35 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 36 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 37 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 38 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 39 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 40 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 41 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 42 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 43 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 44 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 45 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 46 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 47 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 48 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 49 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 50 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 51 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 52 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 53 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 54 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 55 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 56 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 57 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 58 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 59 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 60 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 61 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 62 "lexer.l" +{ return KEYWORD; } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 64 "lexer.l" +{ return IDENTIFIER; } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 66 "lexer.l" +{ return CONSTANT; } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 67 "lexer.l" +{ return CONSTANT; } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 68 "lexer.l" +{ return CONSTANT; } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 69 "lexer.l" +{ return CONSTANT; } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 70 "lexer.l" +{ return CHARACTER; } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 72 "lexer.l" +{ return CONSTANT; } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 73 "lexer.l" +{ return CONSTANT; } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 74 "lexer.l" +{ return CONSTANT; } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 76 "lexer.l" +{ string(); return STRING; } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 78 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 46: +YY_RULE_SETUP +#line 79 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 80 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 81 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 82 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 50: +YY_RULE_SETUP +#line 83 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 51: +YY_RULE_SETUP +#line 84 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 52: +YY_RULE_SETUP +#line 85 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 53: +YY_RULE_SETUP +#line 86 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 54: +YY_RULE_SETUP +#line 87 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 55: +YY_RULE_SETUP +#line 88 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 56: +YY_RULE_SETUP +#line 89 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 57: +YY_RULE_SETUP +#line 90 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 58: +YY_RULE_SETUP +#line 91 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 59: +YY_RULE_SETUP +#line 92 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 60: +YY_RULE_SETUP +#line 93 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 61: +YY_RULE_SETUP +#line 94 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 62: +YY_RULE_SETUP +#line 95 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 63: +YY_RULE_SETUP +#line 96 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 64: +YY_RULE_SETUP +#line 97 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 65: +YY_RULE_SETUP +#line 98 "lexer.l" +{ return OPERATOR; } + YY_BREAK +case 66: +YY_RULE_SETUP +#line 99 "lexer.l" +{ return ELLIPSIS; } + YY_BREAK +case 67: +YY_RULE_SETUP +#line 100 "lexer.l" +{ return ';'; } + YY_BREAK +case 68: +YY_RULE_SETUP +#line 101 "lexer.l" +{ return '{'; } + YY_BREAK +case 69: +YY_RULE_SETUP +#line 102 "lexer.l" +{ return '}'; } + YY_BREAK +case 70: +YY_RULE_SETUP +#line 103 "lexer.l" +{ return ','; } + YY_BREAK +case 71: +YY_RULE_SETUP +#line 104 "lexer.l" +{ return ':'; } + YY_BREAK +case 72: +YY_RULE_SETUP +#line 105 "lexer.l" +{ return '='; } + YY_BREAK +case 73: +YY_RULE_SETUP +#line 106 "lexer.l" +{ return '('; } + YY_BREAK +case 74: +YY_RULE_SETUP +#line 107 "lexer.l" +{ return ')'; } + YY_BREAK +case 75: +YY_RULE_SETUP +#line 108 "lexer.l" +{ return '['; } + YY_BREAK +case 76: +YY_RULE_SETUP +#line 109 "lexer.l" +{ return ']'; } + YY_BREAK +case 77: +YY_RULE_SETUP +#line 110 "lexer.l" +{ return '.'; } + YY_BREAK +case 78: +YY_RULE_SETUP +#line 111 "lexer.l" +{ return '&'; } + YY_BREAK +case 79: +YY_RULE_SETUP +#line 112 "lexer.l" +{ return '!'; } + YY_BREAK +case 80: +YY_RULE_SETUP +#line 113 "lexer.l" +{ return '~'; } + YY_BREAK +case 81: +YY_RULE_SETUP +#line 114 "lexer.l" +{ return '-'; } + YY_BREAK +case 82: +YY_RULE_SETUP +#line 115 "lexer.l" +{ return '+'; } + YY_BREAK +case 83: +YY_RULE_SETUP +#line 116 "lexer.l" +{ return '*'; } + YY_BREAK +case 84: +YY_RULE_SETUP +#line 117 "lexer.l" +{ return '/'; } + YY_BREAK +case 85: +YY_RULE_SETUP +#line 118 "lexer.l" +{ return '%'; } + YY_BREAK +case 86: +YY_RULE_SETUP +#line 119 "lexer.l" +{ return '<'; } + YY_BREAK +case 87: +YY_RULE_SETUP +#line 120 "lexer.l" +{ return '>'; } + YY_BREAK +case 88: +YY_RULE_SETUP +#line 121 "lexer.l" +{ return '^'; } + YY_BREAK +case 89: +YY_RULE_SETUP +#line 122 "lexer.l" +{ return '|'; } + YY_BREAK +case 90: +YY_RULE_SETUP +#line 123 "lexer.l" +{ return '?'; } + YY_BREAK +case 91: +YY_RULE_SETUP +#line 125 "lexer.l" +{ return yytext[0]; } + YY_BREAK +case 92: +YY_RULE_SETUP +#line 126 "lexer.l" +{ return yytext[0]; } + YY_BREAK +case 93: +YY_RULE_SETUP +#line 128 "lexer.l" +ECHO; + YY_BREAK +#line 1251 "lex.yy.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 233 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 233 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 232); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 128 "lexer.l" + + +char *token_buffer; + +static int maxtoken; + +void +init_lex(void) +{ + maxtoken = 40; + token_buffer = (char *)xmalloc(maxtoken + 1); +} + +void +done_lex(void) +{ + free(token_buffer); +} + +static char * +extend_token_buffer(char *p) +{ + int offset = p - token_buffer; + + maxtoken = maxtoken * 2 + 10; + + token_buffer = (char *)xrealloc(token_buffer, maxtoken + 2); + + return token_buffer + offset; +} + +static void +string(void) +{ + char *p; + int c; + + p = token_buffer; + *p++ = '"'; + while ((c = input()) != EOF && c != '"') { + if (p >= token_buffer + maxtoken) + p = extend_token_buffer(p); + *p++ = c; + if (c == '\\') + *p++ = input(); + } + if (c == EOF) + errx(1, "unexpected end of file in string"); + *p++ = '"'; + *p = '\0'; +} + +static void +comment(void) +{ + char *p; + int c; + + p = token_buffer; + *p++ = '/'; + *p++ = '*'; + while ((c = input()) != EOF) { +resync: if (p >= token_buffer + maxtoken) + p = extend_token_buffer(p); + *p++ = c; + if (c == '*') + if ((c = input()) == '/') { + *p++ = c; + *p = '\0'; + return; + } else + goto resync; + } + *p = '\0'; +} + +static int +directive(void) +{ + char *p; + int c; + + if (opt_directives) + return '#'; + + p = token_buffer; + *p++ = '#'; + + while ((c = input()) != EOF && c != '\n') { + if (p >= token_buffer + maxtoken) + p = extend_token_buffer(p); + *p++ = c; + if (c == '\\') + *p++ = input(); + } + *p++ = c; + *p = '\0'; + return DIRECTIVE; +} diff --git a/APACHE_1_3b7/src/test/rename/csubst/lexer.l b/APACHE_1_3b7/src/test/rename/csubst/lexer.l new file mode 100644 index 0000000000..83f91ddfb8 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/csubst/lexer.l @@ -0,0 +1,226 @@ + +Digit [0-9] +Literal [a-zA-Z_] +Hex [a-fA-F0-9] +Exp [Ee][+-]?{Digit}+ +FS (f|F|l|L) +IS (u|U|l|L)+ + +%{ +#include +#include +#include + +#include "util.h" +#include "tokens.h" + +extern int opt_directives; + +static void string(void); +static void comment(void); +static int directive(void); + +static int yywrap(void) { return 1; } +%} + +%% + +"/*" { comment(); return COMMENT; } +"#" { return directive(); } + +"auto" { return KEYWORD; } +"break" { return KEYWORD; } +"case" { return KEYWORD; } +"char" { return KEYWORD; } +"const" { return KEYWORD; } +"continue" { return KEYWORD; } +"default" { return KEYWORD; } +"do" { return KEYWORD; } +"double" { return KEYWORD; } +"else" { return KEYWORD; } +"enum" { return KEYWORD; } +"extern" { return KEYWORD; } +"float" { return KEYWORD; } +"for" { return KEYWORD; } +"goto" { return KEYWORD; } +"if" { return KEYWORD; } +"int" { return KEYWORD; } +"long" { return KEYWORD; } +"register" { return KEYWORD; } +"return" { return KEYWORD; } +"short" { return KEYWORD; } +"signed" { return KEYWORD; } +"sizeof" { return KEYWORD; } +"static" { return KEYWORD; } +"struct" { return KEYWORD; } +"switch" { return KEYWORD; } +"typedef" { return KEYWORD; } +"union" { return KEYWORD; } +"unsigned" { return KEYWORD; } +"void" { return KEYWORD; } +"volatile" { return KEYWORD; } +"while" { return KEYWORD; } + +{Literal}({Literal}|{Digit})* { return IDENTIFIER; } + +0[xX]{Hex}+{IS}? { return CONSTANT; } +0{Digit}+{IS}? { return CONSTANT; } +{Digit}+{IS} { return CONSTANT; } +{Digit}+ { return CONSTANT; } +'(\\.|[^\\'])+' { return CHARACTER; } + +{Digit}+{Exp}{FS}? { return CONSTANT; } +{Digit}*"."{Digit}+({Exp})?{FS}? { return CONSTANT; } +{Digit}+"."{Digit}*({Exp})?{FS}? { return CONSTANT; } + +"\"" { string(); return STRING; } + +">>=" { return OPERATOR; } +"<<=" { return OPERATOR; } +"+=" { return OPERATOR; } +"-=" { return OPERATOR; } +"*=" { return OPERATOR; } +"/=" { return OPERATOR; } +"%=" { return OPERATOR; } +"&=" { return OPERATOR; } +"^=" { return OPERATOR; } +"|=" { return OPERATOR; } +">>" { return OPERATOR; } +"<<" { return OPERATOR; } +"++" { return OPERATOR; } +"--" { return OPERATOR; } +"->" { return OPERATOR; } +"&&" { return OPERATOR; } +"||" { return OPERATOR; } +"<=" { return OPERATOR; } +">=" { return OPERATOR; } +"==" { return OPERATOR; } +"!=" { return OPERATOR; } +"..." { return ELLIPSIS; } +";" { return ';'; } +"{" { return '{'; } +"}" { return '}'; } +"," { return ','; } +":" { return ':'; } +"=" { return '='; } +"(" { return '('; } +")" { return ')'; } +"[" { return '['; } +"]" { return ']'; } +"." { return '.'; } +"&" { return '&'; } +"!" { return '!'; } +"~" { return '~'; } +"-" { return '-'; } +"+" { return '+'; } +"*" { return '*'; } +"/" { return '/'; } +"%" { return '%'; } +"<" { return '<'; } +">" { return '>'; } +"^" { return '^'; } +"|" { return '|'; } +"?" { return '?'; } + +[ \t\v\n\f] { return yytext[0]; } +. { return yytext[0]; } + +%% + +char *token_buffer; + +static int maxtoken; + +void +init_lex(void) +{ + maxtoken = 40; + token_buffer = (char *)xmalloc(maxtoken + 1); +} + +void +done_lex(void) +{ + free(token_buffer); +} + +static char * +extend_token_buffer(char *p) +{ + int offset = p - token_buffer; + + maxtoken = maxtoken * 2 + 10; + + token_buffer = (char *)xrealloc(token_buffer, maxtoken + 2); + + return token_buffer + offset; +} + +static void +string(void) +{ + char *p; + int c; + + p = token_buffer; + *p++ = '"'; + while ((c = input()) != EOF && c != '"') { + if (p >= token_buffer + maxtoken) + p = extend_token_buffer(p); + *p++ = c; + if (c == '\\') + *p++ = input(); + } + if (c == EOF) + errx(1, "unexpected end of file in string"); + *p++ = '"'; + *p = '\0'; +} + +static void +comment(void) +{ + char *p; + int c; + + p = token_buffer; + *p++ = '/'; + *p++ = '*'; + while ((c = input()) != EOF) { +resync: if (p >= token_buffer + maxtoken) + p = extend_token_buffer(p); + *p++ = c; + if (c == '*') + if ((c = input()) == '/') { + *p++ = c; + *p = '\0'; + return; + } else + goto resync; + } + *p = '\0'; +} + +static int +directive(void) +{ + char *p; + int c; + + if (opt_directives) + return '#'; + + p = token_buffer; + *p++ = '#'; + + while ((c = input()) != EOF && c != '\n') { + if (p >= token_buffer + maxtoken) + p = extend_token_buffer(p); + *p++ = c; + if (c == '\\') + *p++ = input(); + } + *p++ = c; + *p = '\0'; + return DIRECTIVE; +} diff --git a/APACHE_1_3b7/src/test/rename/csubst/tokens.h b/APACHE_1_3b7/src/test/rename/csubst/tokens.h new file mode 100644 index 0000000000..8b29aba7e5 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/csubst/tokens.h @@ -0,0 +1,41 @@ +/* $Id: tokens.h,v 1.1 1998/04/03 06:20:16 rse Exp $ */ + +/* + * Copyright (c) 1995, 1996, 1997 + * Sandro Sigala, Brescia, Italy. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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 AUTHOR 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. + */ + +enum { + IDENTIFIER=256, + CHARACTER, + STRING, + COMMENT, + DIRECTIVE, + CONSTANT, + KEYWORD, + OPERATOR, + ELLIPSIS, + ALL /* Not a real token, put here for convenience. */ +}; + +#define MAX_TOKENS 266 diff --git a/APACHE_1_3b7/src/test/rename/csubst/util.c b/APACHE_1_3b7/src/test/rename/csubst/util.c new file mode 100644 index 0000000000..2806690fe6 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/csubst/util.c @@ -0,0 +1,137 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" + +/* + * Return an allocated memory area. + */ +void * +xmalloc(size_t size) +{ + void *ptr; + + assert(size > 0); + + if ((ptr = malloc(size)) == NULL) + err(1, NULL); + + return ptr; +} + + +/* + * Resize an allocated memory area. + */ +void * +xrealloc(void *ptr, size_t size) +{ + void *newptr; + + assert(ptr != NULL); + assert(size > 0); + + if ((newptr = realloc(ptr, size)) == NULL) + err(1, NULL); + + return newptr; +} + +/* + * 4.4BSD err(), warn() functions reimplementation. + */ + + +void +err(int status, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verr(status, fmt, ap); + va_end(ap); +} + +void +verr(int status, const char *fmt, va_list ap) +{ + int olderrno = errno; + + fprintf(stderr, "csubst: "); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(olderrno)); + + exit(status); +} + +void +errx(int status, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verrx(status, fmt, ap); + va_end(ap); +} + +void +verrx(int status, const char *fmt, va_list ap) +{ + fprintf(stderr, "csubst: "); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + + exit(status); +} + +void +warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); +} + +void +vwarn(const char *fmt, va_list ap) +{ + int olderrno = errno; + + fprintf(stderr, "csubst: "); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(olderrno)); +} + +void +warnx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); +} + +void +vwarnx(const char *fmt, va_list ap) +{ + fprintf(stderr, "csubst: "); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); +} diff --git a/APACHE_1_3b7/src/test/rename/csubst/util.h b/APACHE_1_3b7/src/test/rename/csubst/util.h new file mode 100644 index 0000000000..163c0cd6d7 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/csubst/util.h @@ -0,0 +1,11 @@ + +#include + +extern void err(int status, const char *fmt, ...); +extern void verr(int status, const char *fmt, va_list ap); +extern void errx(int status, const char *fmt, ...); +extern void verrx(int status, const char *fmt, va_list ap); +extern void warn(const char *fmt, ...); +extern void vwarn(const char *fmt, va_list ap); +extern void warnx(const char *fmt, ...); +extern void vwarnx(const char *fmt, va_list ap); diff --git a/APACHE_1_3b7/src/test/rename/rename.cf b/APACHE_1_3b7/src/test/rename/rename.cf new file mode 100644 index 0000000000..4d679620c1 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/rename.cf @@ -0,0 +1,400 @@ +## +## rename.cf -- global symbol renaming list for Apache 1.3b6 +## + +PREFIX_ = ap_ + +## +## The actual list of symbols to rename +## + +# BSS +bind_address PREFIX_bind_address +coredump_dir PREFIX_coredump_dir +daemons_limit PREFIX_daemons_limit +daemons_max_free PREFIX_daemons_max_free +daemons_min_free PREFIX_daemons_min_free +daemons_to_start PREFIX_daemons_to_start +excess_requests_per_child PREFIX_excess_requests_per_child +group_id PREFIX_group_id +listenbacklog PREFIX_listenbacklog +listeners PREFIX_listeners +lock_fname PREFIX_lock_fname +max_requests_per_child PREFIX_max_requests_per_child +pid_fname PREFIX_pid_fname +restart_time PREFIX_restart_time +scoreboard_fname PREFIX_scoreboard_fname +server_argv0 PREFIX_server_argv0 +server_confname PREFIX_server_confname +server_post_read_config PREFIX_server_post_read_config +server_pre_read_config PREFIX_server_pre_read_config +server_root PREFIX_server_root +standalone PREFIX_standalone +threads_per_child PREFIX_threads_per_child +user_id PREFIX_user_id +user_name PREFIX_user_name + +# DATA +suexec_enabled PREFIX_suexec_enabled +day_snames PREFIX_day_snames +dummy_mutex PREFIX_dummy_mutex +month_snames PREFIX_month_snames +rfc1413_timeout PREFIX_rfc1413_timeout +scoreboard_image PREFIX_scoreboard_image + +# TEXT +MD5Final PREFIX_MD5Final +MD5Init PREFIX_MD5Init +MD5Update PREFIX_MD5Update +add_cgi_vars PREFIX_add_cgi_vars +add_common_vars PREFIX_add_common_vars +add_module PREFIX_add_module +add_named_module PREFIX_add_named_module +add_per_dir_conf PREFIX_add_per_dir_conf +add_per_url_conf PREFIX_add_per_url_conf +allow_options PREFIX_allow_options +allow_overrides PREFIX_allow_overrides +append_arrays PREFIX_append_arrays +array_cat PREFIX_array_cat +auth_name PREFIX_auth_name +auth_type PREFIX_auth_type +basic_http_header PREFIX_basic_http_header +bclose PREFIX_bclose +bcreate PREFIX_bcreate +bfilbuf PREFIX_bfilbuf +bfileno PREFIX_bfileno +bflsbuf PREFIX_bflsbuf +bflush PREFIX_bflush +bgetopt PREFIX_bgetopt +bgets PREFIX_bgets +bhalfduplex PREFIX_bhalfduplex +block_alarms PREFIX_block_alarms +blookc PREFIX_blookc +bnonblock PREFIX_bnonblock +bonerror PREFIX_bonerror +bpushfd PREFIX_bpushfd +bputs PREFIX_bputs +bprintf PREFIX_bprintf +bread PREFIX_bread +bsetflag PREFIX_bsetflag +bsetopt PREFIX_bsetopt +bskiplf PREFIX_bskiplf +bvputs PREFIX_bvputs +bwrite PREFIX_bwrite +bytes_in_free_blocks PREFIX_bytes_in_free_blocks +bytes_in_pool PREFIX_bytes_in_pool +call_exec PREFIX_call_exec +can_exec PREFIX_can_exec +cfg_closefile PREFIX_cfg_closefile +cfg_getc PREFIX_cfg_getc +cfg_getline PREFIX_cfg_getline +chdir_file PREFIX_chdir_file +check_access PREFIX_check_access +check_alarm PREFIX_check_alarm +check_auth PREFIX_check_auth +check_cmd_context PREFIX_check_cmd_context +check_user_id PREFIX_check_user_id +checkmask PREFIX_checkmask +child_exit_modules PREFIX_child_exit_modules +child_init_modules PREFIX_child_init_modules +child_terminate PREFIX_child_terminate +cleanup_for_exec PREFIX_cleanup_for_exec +clear_module_list PREFIX_clear_module_list +clear_pool PREFIX_clear_pool +clear_table PREFIX_clear_table +close_piped_log PREFIX_close_piped_log +construct_server PREFIX_construct_server +construct_url PREFIX_construct_url +copy_array PREFIX_copy_array +copy_array_hdr PREFIX_copy_array_hdr +copy_table PREFIX_copy_table +core_reorder_directories PREFIX_core_reorder_directories +count_dirs PREFIX_count_dirs +create_environment PREFIX_create_environment +create_per_dir_config PREFIX_create_per_dir_config +create_request_config PREFIX_create_request_config +default_port_for_request PREFIX_default_port_for_request +default_port_for_scheme PREFIX_default_port_for_scheme +default_type PREFIX_default_type +destroy_pool PREFIX_destroy_pool +destroy_sub_req PREFIX_destroy_sub_req +die PREFIX_die +discard_request_body PREFIX_discard_request_body +document_root PREFIX_document_root +each_byterange PREFIX_each_byterange +error_log2stderr PREFIX_error_log2stderr +escape_html PREFIX_escape_html +escape_path_segment PREFIX_escape_path_segment +escape_shell_cmd PREFIX_escape_shell_cmd +exists_scoreboard_image PREFIX_exists_scoreboard_image +finalize_request_protocol PREFIX_finalize_request_protocol +finalize_sub_req_protocol PREFIX_finalize_sub_req_protocol +find_command PREFIX_find_command +find_command_in_modules PREFIX_find_command_in_modules +find_last_token PREFIX_find_last_token +find_linked_module PREFIX_find_linked_module +find_module_name PREFIX_find_module_name +find_path_info PREFIX_find_path_info +find_pool PREFIX_find_pool +find_token PREFIX_find_token +find_types PREFIX_find_types +fini_vhost_config PREFIX_fini_vhost_config +fnmatch PREFIX_fnmatch +force_library_loading PREFIX_force_library_loading +get_basic_auth_pw PREFIX_get_basic_auth_pw +get_client_block PREFIX_get_client_block +get_gmtoff PREFIX_get_gmtoff +get_local_host PREFIX_get_local_host +get_module_config PREFIX_get_module_config +get_remote_host PREFIX_get_remote_host +get_remote_logname PREFIX_get_remote_logname +get_server_name PREFIX_get_server_name +get_server_port PREFIX_get_server_port +get_time PREFIX_get_time +get_token PREFIX_get_token +get_virthost_addr PREFIX_get_virthost_addr +getparents PREFIX_getparents +getword PREFIX_getword +getword_conf PREFIX_getword_conf +getword_conf_nc PREFIX_getword_conf_nc +getword_nc PREFIX_getword_nc +getword_nulls PREFIX_getword_nulls +getword_nulls_nc PREFIX_getword_nulls_nc +getword_white PREFIX_getword_white +getword_white_nc PREFIX_getword_white_nc +gm_timestr_822 PREFIX_gm_timestr_822 +gname2id PREFIX_gname2id +handle_command PREFIX_handle_command +hard_timeout PREFIX_hard_timeout +header_parse PREFIX_header_parse +ht_time PREFIX_ht_time +ind PREFIX_ind +index_of_response PREFIX_index_of_response +init_alloc PREFIX_init_alloc +init_modules PREFIX_init_modules +init_vhost_config PREFIX_init_vhost_config +init_virtual_host PREFIX_init_virtual_host +internal_redirect PREFIX_internal_redirect +internal_redirect_handler PREFIX_internal_redirect_handler +invoke_handler PREFIX_invoke_handler +is_directory PREFIX_is_directory +is_fnmatch PREFIX_is_fnmatch +is_initial_req PREFIX_is_initial_req +is_matchexp PREFIX_is_matchexp +is_url PREFIX_is_url +keepalive_timeout PREFIX_keepalive_timeout +kill_cleanup PREFIX_kill_cleanup +kill_cleanups_for_fd PREFIX_kill_cleanups_for_fd +kill_cleanups_for_socket PREFIX_kill_cleanups_for_socket +kill_timeout PREFIX_kill_timeout +limit_section PREFIX_limit_section +log_assert PREFIX_log_assert +log_pid PREFIX_log_pid +log_printf PREFIX_log_printf +log_reason PREFIX_log_reason +log_transaction PREFIX_log_transaction +log_unixerr PREFIX_log_unixerr +make_array PREFIX_make_array +make_dirstr PREFIX_make_dirstr +make_dirstr_parent PREFIX_make_dirstr_parent +make_dirstr_prefix PREFIX_make_dirstr_prefix +make_full_path PREFIX_make_full_path +make_sub_pool PREFIX_make_sub_pool +make_table PREFIX_make_table +matches_request_vhost PREFIX_matches_request_vhost +meets_conditions PREFIX_meets_conditions +merge_per_dir_configs PREFIX_merge_per_dir_configs +no2slash PREFIX_no2slash +note_auth_failure PREFIX_note_auth_failure +note_basic_auth_failure PREFIX_note_basic_auth_failure +note_cleanups_for_fd PREFIX_note_cleanups_for_fd +note_cleanups_for_file PREFIX_note_cleanups_for_file +note_cleanups_for_socket PREFIX_note_cleanups_for_socket +note_digest_auth_failure PREFIX_note_digest_auth_failure +note_subprocess PREFIX_note_subprocess +null_cleanup PREFIX_null_cleanup +open_logs PREFIX_open_logs +open_piped_log PREFIX_open_piped_log +overlay_tables PREFIX_overlay_tables +palloc PREFIX_palloc +parseHTTPdate PREFIX_parseHTTPdate +parse_htaccess PREFIX_parse_htaccess +parse_uri PREFIX_parse_uri +parse_uri_components PREFIX_parse_uri_components +parse_hostinfo_components PREFIX_parse_hostinfo_components +parse_vhost_addrs PREFIX_parse_vhost_addrs +pcalloc PREFIX_pcalloc +pcfg_open_custom PREFIX_pcfg_open_custom +pcfg_openfile PREFIX_pcfg_openfile +pclosedir PREFIX_pclosedir +pclosef PREFIX_pclosef +pclosesocket PREFIX_pclosesocket +pduphostent PREFIX_pduphostent +pfclose PREFIX_pfclose +pfdopen PREFIX_pfdopen +pfopen PREFIX_pfopen +pgethostbyname PREFIX_pgethostbyname +pool_is_ancestor PREFIX_pool_is_ancestor +pool_join PREFIX_pool_join +popendir PREFIX_popendir +popenf PREFIX_popenf +pregcomp PREFIX_pregcomp +pregfree PREFIX_pregfree +pregsub PREFIX_pregsub +process_request PREFIX_process_request +process_resource_config PREFIX_process_resource_config +proxy_add_header PREFIX_proxy_add_header +proxy_c2hex PREFIX_proxy_c2hex +proxy_cache_check PREFIX_proxy_cache_check +proxy_cache_error PREFIX_proxy_cache_error +proxy_cache_tidy PREFIX_proxy_cache_tidy +proxy_cache_update PREFIX_proxy_cache_update +proxy_canon_netloc PREFIX_proxy_canon_netloc +proxy_canonenc PREFIX_proxy_canonenc +proxy_connect_handler PREFIX_proxy_connect_handler +proxy_date_canon PREFIX_proxy_date_canon +proxy_del_header PREFIX_proxy_del_header +proxy_doconnect PREFIX_proxy_doconnect +proxy_ftp_canon PREFIX_proxy_ftp_canon +proxy_ftp_handler PREFIX_proxy_ftp_handler +proxy_garbage_coll PREFIX_proxy_garbage_coll +proxy_garbage_init PREFIX_proxy_garbage_init +proxy_get_header PREFIX_proxy_get_header +proxy_hash PREFIX_proxy_hash +proxy_hex2c PREFIX_proxy_hex2c +proxy_hex2sec PREFIX_proxy_hex2sec +proxy_host2addr PREFIX_proxy_host2addr +proxy_http_canon PREFIX_proxy_http_canon +proxy_http_handler PREFIX_proxy_http_handler +proxy_is_domainname PREFIX_proxy_is_domainname +proxy_is_hostname PREFIX_proxy_is_hostname +proxy_is_ipaddr PREFIX_proxy_is_ipaddr +proxy_is_word PREFIX_proxy_is_word +proxy_liststr PREFIX_proxy_liststr +proxy_log_uerror PREFIX_proxy_log_uerror +proxy_read_headers PREFIX_proxy_read_headers +proxy_sec2hex PREFIX_proxy_sec2hex +proxy_send_fb PREFIX_proxy_send_fb +proxy_send_headers PREFIX_proxy_send_headers +proxyerror PREFIX_proxyerror +psignature PREFIX_psignature +psocket PREFIX_psocket +pstrcat PREFIX_pstrcat +pstrdup PREFIX_pstrdup +pstrndup PREFIX_pstrndup +psprintf PREFIX_psprintf +pvsprintf PREFIX_pvsprintf +push_array PREFIX_push_array +rationalize_mtime PREFIX_rationalize_mtime +read_config PREFIX_read_config +read_request PREFIX_read_request +register_cleanup PREFIX_register_cleanup +register_other_child PREFIX_register_other_child +remove_module PREFIX_remove_module +requires PREFIX_requires +reset_timeout PREFIX_reset_timeout +response_code_string PREFIX_response_code_string +rfc1413 PREFIX_rfc1413 +rflush PREFIX_rflush +rind PREFIX_rind +rprintf PREFIX_rprintf +rputc PREFIX_rputc +rputs PREFIX_rputs +run_cleanup PREFIX_run_cleanup +run_fixups PREFIX_run_fixups +run_post_read_request PREFIX_run_post_read_request +run_sub_req PREFIX_run_sub_req +rvputs PREFIX_rvputs +rwrite PREFIX_rwrite +satisfies PREFIX_satisfies +scan_script_header_err PREFIX_scan_script_header_err +scan_script_header_err_buff PREFIX_scan_script_header_err_buff +send_error_response PREFIX_send_error_response +send_fb PREFIX_send_fb +send_fb_length PREFIX_send_fb_length +send_fd PREFIX_send_fd +send_fd_length PREFIX_send_fd_length +send_header_field PREFIX_send_header_field +send_http_header PREFIX_send_http_header +send_http_options PREFIX_send_http_options +send_http_trace PREFIX_send_http_trace +send_mmap PREFIX_send_mmap +send_size PREFIX_send_size +server_root_relative PREFIX_server_root_relative +set_byterange PREFIX_set_byterange +set_callback_and_alarm PREFIX_set_callback_and_alarm +set_content_length PREFIX_set_content_length +set_etag PREFIX_set_etag +set_file_slot PREFIX_set_file_slot +set_flag_slot PREFIX_set_flag_slot +set_keepalive PREFIX_set_keepalive +set_last_modified PREFIX_set_last_modified +set_module_config PREFIX_set_module_config +set_name_virtual_host PREFIX_set_name_virtual_host +set_string_slot PREFIX_set_string_slot +set_string_slot_lower PREFIX_set_string_slot_lower +set_sub_req_protocol PREFIX_set_sub_req_protocol +setup_client_block PREFIX_setup_client_block +setup_prelinked_modules PREFIX_setup_prelinked_modules +should_client_block PREFIX_should_client_block +show_directives PREFIX_show_directives +show_modules PREFIX_show_modules +soft_timeout PREFIX_soft_timeout +some_auth_required PREFIX_some_auth_required +spawn_child_err PREFIX_spawn_child_err +spawn_child_err_buff PREFIX_spawn_child_err_buff +srm_command_loop PREFIX_srm_command_loop +start_restart PREFIX_start_restart +start_shutdown PREFIX_start_shutdown +str_tolower PREFIX_str_tolower +strcasecmp_match PREFIX_strcasecmp_match +strcmp_match PREFIX_strcmp_match +sub_req_lookup_file PREFIX_sub_req_lookup_file +sub_req_lookup_uri PREFIX_sub_req_lookup_uri +sync_scoreboard_image PREFIX_sync_scoreboard_image +table_add PREFIX_table_add +table_addn PREFIX_table_addn +table_do PREFIX_table_do +table_get PREFIX_table_get +table_merge PREFIX_table_merge +table_mergen PREFIX_table_mergen +table_set PREFIX_table_set +table_setn PREFIX_table_setn +table_unset PREFIX_table_unset +time_process_request PREFIX_time_process_request +tm2sec PREFIX_tm2sec +translate_name PREFIX_translate_name +uname2id PREFIX_uname2id +unblock_alarms PREFIX_unblock_alarms +unescape_url PREFIX_unescape_url +unparse_uri_components PREFIX_unparse_uri_components +unregister_other_child PREFIX_unregister_other_child +update_child_status PREFIX_update_child_status +update_mtime PREFIX_update_mtime +update_vhost_from_headers PREFIX_update_vhost_from_headers +update_vhost_given_ip PREFIX_update_vhost_given_ip +util_init PREFIX_util_init +util_uri_init PREFIX_util_uri_init +uudecode PREFIX_uudecode +vbprintf PREFIX_vbprintf + +# specials +apapi_get_server_built PREFIX_get_server_built +apapi_get_server_version PREFIX_get_server_version +aplog_error PREFIX_log_error +log_error PREFIX_log_error_old +os_escape_path PREFIX_escape_path +os_canonical_filename PREFIX_canonical_filename +acquire_mutex PREFIX_acquire_mutex +create_mutex PREFIX_create_mutex +destroy_mutex PREFIX_destroy_mutex +open_mutex PREFIX_open_mutex +release_mutex PREFIX_release_mutex + +# specials: needs tag in source to become PREFIX_! +os_is_path_absolute PREFIX_is_path_absolute + +# specials: these two require also a (trivial) change in Configure +prelinked_modules PREFIX_prelinked_modules +preloaded_modules PREFIX_preloaded_modules + diff --git a/APACHE_1_3b7/src/test/rename/rename.cf.clean-api b/APACHE_1_3b7/src/test/rename/rename.cf.clean-api new file mode 100644 index 0000000000..6ead5c019c --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/rename.cf.clean-api @@ -0,0 +1,456 @@ +## +## rename.cf -- global symbol renaming list for ... Hmmmmm... +## we don't know. This can be used when we want +## to create a clean API, but not this time... +## + +## The used prefixes for function/variable names of +## +## - Apache official API symbols (API): +## the ones the user can use for programming modules +## (should be as short as possible while still Apache specific) +## +## - Apache official module handles (APM): +## the symbols used for the module structures which +## are a special case due to DSO support [mod_so] ! +## (should only be Apache specific and indicate module structs) +## +## - Apache internal cross-object symbols (APX): +## the ones we need for internal cross-object references +## (should only be Apache specific and indicate cross-object symbols) +## +API_ = ap_ +APM_ = apm_ +APX_ = apx_ + +## +## The actual list of symbols to rename +## + +# BSS +bind_address APX_bind_address +coredump_dir APX_coredump_dir +daemons_limit APX_daemons_limit +daemons_max_free APX_daemons_max_free +daemons_min_free APX_daemons_min_free +daemons_to_start APX_daemons_to_start +excess_requests_per_child APX_excess_requests_per_child +group_id APX_group_id +listenbacklog APX_listenbacklog +listeners APX_listeners +lock_fname APX_lock_fname +max_requests_per_child APX_max_requests_per_child +pid_fname APX_pid_fname +restart_time APX_restart_time +scoreboard_fname APX_scoreboard_fname +server_argv0 APX_server_argv0 +server_confname APX_server_confname +server_post_read_config APX_server_post_read_config +server_pre_read_config APX_server_pre_read_config +server_root API_server_root +standalone APX_standalone +threads_per_child APX_threads_per_child +user_id APX_user_id +user_name APX_user_name + +# DATA +suexec_enabled APX_suexec_enabled +day_snames API_day_snames +dummy_mutex APX_dummy_mutex +month_snames API_month_snames +rfc1413_timeout APX_rfc1413_timeout +scoreboard_image APX_scoreboard_image + +# DATA +# these need a change in mod_so and a change to the name guessing in +# the src/Configure script plus changes to the embedded +# "Name:" C comments inside the module source files +#access_module APM_access +#action_module APM_action +#alias_module APM_alias +#auth_module APM_auth +#anon_auth_module APM_auth_anon +#db_auth_module APM_auth_db +#dbm_auth_module APM_auth_dbm +#asis_module APM_asis +#autoindex_module APM_autoindex +#cern_meta_module APM_cern_meta +#cgi_module APM_cgi +#core_module APM_core +#digest_module APM_digest +#dir_module APM_dir +#env_module APM_env +#example_module APM_example +#expires_module APM_expires +#headers_module APM_headers +#imap_module APM_imap +#includes_module APM_includes +#info_module APM_info +#mime_magic_module APM_mime_magic +#mime_module APM_mime +#negotiation_module APM_negotiation +#proxy_module APM_proxy +#config_log_module APM_log_config +#referer_log_module APM_log_referer +#agent_log_module APM_log_agent +#rewrite_module APM_rewrite +#setenvif_module APM_setenvif +#so_module APM_so +#speling_module APM_speling +#status_module APM_status +#top_module APM_top +#unique_id_module APM_unique_id +#userdir_module APM_userdir +#usertrack_module APM_usertrack + +# DATA +# these two require also a (trivial) change in Configure +#prelinked_modules APX_prelinked_modules +#preloaded_modules APX_preloaded_modules + +# TEXT +MD5Final API_MD5Final +MD5Init API_MD5Init +MD5Update API_MD5Update +add_cgi_vars API_add_cgi_vars +add_common_vars API_add_common_vars +add_module API_add_module +add_named_module API_add_named_module +add_per_dir_conf APX_add_per_dir_conf +add_per_url_conf APX_add_per_url_conf +allow_options API_allow_options +allow_overrides API_allow_overrides +append_arrays API_append_arrays +array_cat API_array_cat +auth_name API_auth_name +auth_type API_auth_type +basic_http_header API_basic_http_header +bclose API_bclose +bcreate API_bcreate +bfilbuf API_bfilbuf +bfileno API_bfileno +bflsbuf API_bflsbuf +bflush API_bflush +bgetopt API_bgetopt +bgets API_bgets +bhalfduplex API_bhalfduplex +block_alarms API_block_alarms +blookc API_blookc +bnonblock API_bnonblock +bonerror API_bonerror +bpushfd API_bpushfd +bputs API_bputs +bprintf API_bprintf +bread API_bread +bsetflag API_bsetflag +bsetopt API_bsetopt +bskiplf API_bskiplf +bvputs API_bvputs +bwrite API_bwrite +bytes_in_free_blocks API_bytes_in_free_blocks +bytes_in_pool API_bytes_in_pool +call_exec API_call_exec +can_exec API_can_exec +cfg_closefile API_cfg_closefile +cfg_getc API_cfg_getc +cfg_getline API_cfg_getline +chdir_file API_chdir_file +check_access APX_check_access +check_alarm API_check_alarm +check_auth APX_check_auth +check_cmd_context API_check_cmd_context +check_user_id APX_check_user_id +checkmask API_checkmask +child_exit_modules APX_child_exit_modules +child_init_modules APX_child_init_modules +child_terminate API_child_terminate +cleanup_for_exec API_cleanup_for_exec +clear_module_list API_clear_module_list +clear_pool API_clear_pool +clear_table API_clear_table +close_piped_log API_close_piped_log +construct_server API_construct_server +construct_url API_construct_url +copy_array API_copy_array +copy_array_hdr API_copy_array_hdr +copy_table API_copy_table +core_reorder_directories APX_core_reorder_directories +count_dirs API_count_dirs +create_environment API_create_environment +create_per_dir_config APX_create_per_dir_config +create_request_config APX_create_request_config +default_port_for_request API_default_port_for_request +default_port_for_scheme API_default_port_for_scheme +default_type API_default_type +destroy_pool API_destroy_pool +destroy_sub_req API_destroy_sub_req +die APX_die +discard_request_body API_discard_request_body +document_root API_document_root +each_byterange API_each_byterange +error_log2stderr API_error_log2stderr +escape_html API_escape_html +escape_path_segment API_escape_path_segment +escape_shell_cmd API_escape_shell_cmd +exists_scoreboard_image API_exists_scoreboard_image +finalize_request_protocol APX_finalize_request_protocol +finalize_sub_req_protocol APX_finalize_sub_req_protocol +find_command APX_find_command +find_command_in_modules APX_find_command_in_modules +find_last_token API_find_last_token +find_linked_module API_find_linked_module +find_module_name API_find_module_name +find_path_info API_find_path_info +find_pool API_find_pool +find_token API_find_token +find_types APX_find_types +fini_vhost_config APX_fini_vhost_config +fnmatch API_fnmatch +force_library_loading APX_force_library_loading +get_basic_auth_pw API_get_basic_auth_pw +get_client_block API_get_client_block +get_gmtoff API_get_gmtoff +get_local_host APX_get_local_host +get_module_config API_get_module_config +get_remote_host API_get_remote_host +get_remote_logname API_get_remote_logname +get_server_name API_get_server_name +get_server_port API_get_server_port +get_time API_get_time +get_token API_get_token +get_virthost_addr APX_get_virthost_addr +getparents API_getparents +getword API_getword +getword_conf API_getword_conf +getword_conf_nc API_getword_conf_nc +getword_nc API_getword_nc +getword_nulls API_getword_nulls +getword_nulls_nc API_getword_nulls_nc +getword_white API_getword_white +getword_white_nc API_getword_white_nc +gm_timestr_822 API_gm_timestr_822 +gname2id API_gname2id +handle_command APX_handle_command +hard_timeout API_hard_timeout +header_parse APX_header_parse +ht_time API_ht_time +ind API_ind +index_of_response API_index_of_response +init_alloc APX_init_alloc +init_modules APX_init_modules +init_vhost_config APX_init_vhost_config +init_virtual_host APX_init_virtual_host +internal_redirect API_internal_redirect +internal_redirect_handler API_internal_redirect_handler +invoke_handler APX_invoke_handler +is_directory API_is_directory +is_fnmatch API_is_fnmatch +is_initial_req API_is_initial_req +is_matchexp API_is_matchexp +is_url API_is_url +keepalive_timeout APX_keepalive_timeout +kill_cleanup API_kill_cleanup +kill_cleanups_for_fd API_kill_cleanups_for_fd +kill_cleanups_for_socket API_kill_cleanups_for_socket +kill_timeout API_kill_timeout +limit_section APX_limit_section +log_assert API_log_assert +log_pid APX_log_pid +log_printf API_log_printf +log_reason API_log_reason +log_transaction APX_log_transaction +log_unixerr API_log_unixerr +make_array API_make_array +make_dirstr API_make_dirstr +make_dirstr_parent API_make_dirstr_parent +make_dirstr_prefix API_make_dirstr_prefix +make_full_path API_make_full_path +make_sub_pool API_make_sub_pool +make_table API_make_table +matches_request_vhost API_matches_request_vhost +meets_conditions API_meets_conditions +merge_per_dir_configs APX_merge_per_dir_configs +no2slash API_no2slash +note_auth_failure API_note_auth_failure +note_basic_auth_failure API_note_basic_auth_failure +note_cleanups_for_fd API_note_cleanups_for_fd +note_cleanups_for_file API_note_cleanups_for_file +note_cleanups_for_socket API_note_cleanups_for_socket +note_digest_auth_failure API_note_digest_auth_failure +note_subprocess API_note_subprocess +null_cleanup API_null_cleanup +open_logs APX_open_logs +open_piped_log API_open_piped_log +overlay_tables API_overlay_tables +palloc API_palloc +parseHTTPdate API_parseHTTPdate +parse_htaccess APX_parse_htaccess +parse_uri API_parse_uri +parse_uri_components API_parse_uri_components +parse_hostinfo_components API_parse_hostinfo_components +parse_vhost_addrs APX_parse_vhost_addrs +pcalloc API_pcalloc +pcfg_open_custom API_pcfg_open_custom +pcfg_openfile API_pcfg_openfile +pclosedir API_pclosedir +pclosef API_pclosef +pclosesocket API_pclosesocket +pduphostent API_pduphostent +pfclose API_pfclose +pfdopen API_pfdopen +pfopen API_pfopen +pgethostbyname API_pgethostbyname +pool_is_ancestor API_pool_is_ancestor +pool_join API_pool_join +popendir API_popendir +popenf API_popenf +pregcomp API_pregcomp +pregfree API_pregfree +pregsub API_pregsub +process_request APX_process_request +process_resource_config APX_process_resource_config +proxy_add_header APX_proxy_add_header +proxy_c2hex APX_proxy_c2hex +proxy_cache_check APX_proxy_cache_check +proxy_cache_error APX_proxy_cache_error +proxy_cache_tidy APX_proxy_cache_tidy +proxy_cache_update APX_proxy_cache_update +proxy_canon_netloc APX_proxy_canon_netloc +proxy_canonenc APX_proxy_canonenc +proxy_connect_handler APX_proxy_connect_handler +proxy_date_canon APX_proxy_date_canon +proxy_del_header APX_proxy_del_header +proxy_doconnect APX_proxy_doconnect +proxy_ftp_canon APX_proxy_ftp_canon +proxy_ftp_handler APX_proxy_ftp_handler +proxy_garbage_coll APX_proxy_garbage_coll +proxy_garbage_init APX_proxy_garbage_init +proxy_get_header APX_proxy_get_header +proxy_hash APX_proxy_hash +proxy_hex2c APX_proxy_hex2c +proxy_hex2sec APX_proxy_hex2sec +proxy_host2addr APX_proxy_host2addr +proxy_http_canon APX_proxy_http_canon +proxy_http_handler APX_proxy_http_handler +proxy_is_domainname APX_proxy_is_domainname +proxy_is_hostname APX_proxy_is_hostname +proxy_is_ipaddr APX_proxy_is_ipaddr +proxy_is_word APX_proxy_is_word +proxy_liststr APX_proxy_liststr +proxy_log_uerror APX_proxy_log_uerror +proxy_read_headers APX_proxy_read_headers +proxy_sec2hex APX_proxy_sec2hex +proxy_send_fb APX_proxy_send_fb +proxy_send_headers APX_proxy_send_headers +proxyerror APX_proxyerror +psignature API_psignature +psocket API_psocket +pstrcat API_pstrcat +pstrdup API_pstrdup +pstrndup API_pstrndup +psprintf API_psprintf +pvsprintf API_pvsprintf +push_array API_push_array +rationalize_mtime API_rationalize_mtime +read_config APX_read_config +read_request APX_read_request +register_cleanup API_register_cleanup +register_other_child API_register_other_child +remove_module API_remove_module +requires API_requires +reset_timeout API_reset_timeout +response_code_string APX_response_code_string +rfc1413 APX_rfc1413 +rflush API_rflush +rind API_rind +rprintf API_rprintf +rputc API_rputc +rputs API_rputs +run_cleanup API_run_cleanup +run_fixups APX_run_fixups +run_post_read_request APX_run_post_read_request +run_sub_req API_run_sub_req +rvputs API_rvputs +rwrite API_rwrite +satisfies API_satisfies +scan_script_header_err API_scan_script_header_err +scan_script_header_err_buff API_scan_script_header_err_buff +send_error_response APX_send_error_response +send_fb API_send_fb +send_fb_length API_send_fb_length +send_fd API_send_fd +send_fd_length API_send_fd_length +send_header_field API_send_header_field +send_http_header API_send_http_header +send_http_options APX_send_http_options +send_http_trace APX_send_http_trace +send_mmap API_send_mmap +send_size API_send_size +server_root_relative API_server_root_relative +set_byterange API_set_byterange +set_callback_and_alarm APX_set_callback_and_alarm +set_content_length API_set_content_length +set_etag API_set_etag +set_file_slot API_set_file_slot +set_flag_slot API_set_flag_slot +set_keepalive API_set_keepalive +set_last_modified API_set_last_modified +set_module_config API_set_module_config +set_name_virtual_host APX_set_name_virtual_host +set_string_slot API_set_string_slot +set_string_slot_lower API_set_string_slot_lower +set_sub_req_protocol APX_set_sub_req_protocol +setup_client_block API_setup_client_block +setup_prelinked_modules APX_setup_prelinked_modules +should_client_block API_should_client_block +show_directives APX_show_directives +show_modules APX_show_modules +soft_timeout API_soft_timeout +some_auth_required API_some_auth_required +spawn_child_err API_spawn_child_err +spawn_child_err_buff API_spawn_child_err_buff +srm_command_loop API_srm_command_loop +start_restart APX_start_restart +start_shutdown APX_start_shutdown +str_tolower API_str_tolower +strcasecmp_match API_strcasecmp_match +strcmp_match API_strcmp_match +sub_req_lookup_file API_sub_req_lookup_file +sub_req_lookup_uri API_sub_req_lookup_uri +sync_scoreboard_image API_sync_scoreboard_image +table_add API_table_add +table_addn API_table_addn +table_do API_table_do +table_get API_table_get +table_merge API_table_merge +table_mergen API_table_mergen +table_set API_table_set +table_setn API_table_setn +table_unset API_table_unset +time_process_request APX_time_process_request +tm2sec API_tm2sec +translate_name APX_translate_name +uname2id API_uname2id +unblock_alarms API_unblock_alarms +unescape_url API_unescape_url +unparse_uri_components API_unparse_uri_components +unregister_other_child API_unregister_other_child +update_child_status APX_update_child_status +update_mtime API_update_mtime +update_vhost_from_headers APX_update_vhost_from_headers +update_vhost_given_ip APX_update_vhost_given_ip +util_init APX_util_init +util_uri_init APX_util_uri_init +uudecode API_uudecode +vbprintf API_vbprintf + +# specials +apapi_get_server_built API_get_server_built +apapi_get_server_version API_get_server_version +aplog_error API_log_error +log_error API_log_error_old +os_escape_path API_escape_path + +# specials: needs tag in source to become API_! +os_is_path_absolute APX_is_path_absolute + diff --git a/APACHE_1_3b7/src/test/rename/rename.cf.update b/APACHE_1_3b7/src/test/rename/rename.cf.update new file mode 100755 index 0000000000..61a8313f11 --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/rename.cf.update @@ -0,0 +1,55 @@ +: +eval 'exec perl -S $0 ${1+"$@"}' + if $running_under_some_shell; +## +## rename.cf.update +## + +# configuration +$id = "../src/ID"; +$renamecf = "./rename.cf"; + +sub is_api_func { + my ($func) = @_; + + $rc = join('', `lid -f $id --key=token --result=grep $func`); + if ( $rc =~ m|\.c:\d+:\s*API_EXPORT(_NONSTD)?\(|s + or $rc =~ m|\.c:\d+:\s*API_VAR_EXPORT\s+|s) { + return 1; + } + return 0; +} + +open(OLD, "<$renamecf") || die; +open(NEW, ">$renamecf.new") || die; +while ($l = ) { + $l =~ s|\n$||; + if ($l =~ m|^\s*#.*| or $l =~ m|^\s*$|) { + print NEW "$l\n"; + next; + } + if (($s1, $old, $s2, $new, $s3) = ($l =~ m|^(\s*)(\S+)(\s+)(\S+)(\s*)$|)) { + if (&is_api_func($old)) { + if ($new !~ m|^API_|) { + print "<<$s1$old$s2$new$s3\n"; + $new =~ s|^[A-Z]+_|API_|; + print ">>$s1$old$s2$new$s3\n"; + print NEW "$s1$old$s2$new$s3\n"; + next; + } + } + else { + if ($new !~ m|^APX_|) { + print "<<$s1$old$s2$new$s3\n"; + $new =~ s|^[A-Z]+_|APX_|; + print ">>$s1$old$s2$new$s3\n"; + print NEW "$s1$old$s2$new$s3\n"; + next; + } + } + } + print NEW "$l\n"; +} +close(OLD); +close(NEW); + diff --git a/APACHE_1_3b7/src/test/rename/rename.pl b/APACHE_1_3b7/src/test/rename/rename.pl new file mode 100755 index 0000000000..1dc581b46b --- /dev/null +++ b/APACHE_1_3b7/src/test/rename/rename.pl @@ -0,0 +1,89 @@ +: +eval 'exec perl -S $0 ${1+"$@"}' + if $running_under_some_shell; +## +## rename -- global symbol renaming for C sources +## Written by Ralf S. Engelschall +## + +# configuration +$config = "./rename.cf"; +$csubst = "./csubst/csubst"; + +# parameter +@SRC = @ARGV; + +# read config file into hash +%PREFIX = (); +%SUBST = (); +open(CFG, "<$config") || die; +while () { + s|\n$||; + next if (m|^\s*#.*| or m|^\s*$|); + if (($symbolic, $real) = m|^\s*(\S+)\s*=\s*(\S+)\s*$|) { + $PREFIX{$symbolic} = $real; + } + elsif (($old, $new) = m|^\s*(\S+)\s+(\S+)\s*$|) { + foreach $p (keys(%PREFIX)) { + $new =~ s|^$p|$PREFIX{$p}|; + } + $SUBST{$old} = $new; + } +} +close(CFG); + +# create csubst command line +$csubst_cmd = "$csubst"; +foreach $old (keys(%SUBST)) { + $new = $SUBST{$old}; + $csubst_cmd .= " -s $old:$new"; +} + +# create file list +@FILES = (); +foreach $src (@SRC) { + if (-f $src) { + push(@FILES, $src); + } + else { + push(@FILES, `find $src -name "*.[ch]" -type f -print`); + } +} + +# walk through the file list +foreach $file (@FILES) { + $file =~ s|\n$||; + print STDERR " FILE $file\n"; + open(PIPE, "cp $file $file.bak && " . + "$csubst_cmd -o $file.n $file && " . + "cp $file.n $file && " . + "rm $file.n " . + "|") || die; + %stat = (); + while () { + if (m|^Subst:\s+(\S+)\s+->\s+\S+|) { + $stat{$1} = 0 if (not defined $stat{$1}); + $stat{$1}++; + } + } + close(PIPE); + @S = sort(keys(%stat)); + $n = -1; + if ($#S == -1) { + print STDERR " --NO-SYMBOL-SUBSTITUTIONS--\n"; + } + else { + foreach $s (@S) { + printf(STDERR " %-25s", "$s:$stat{$s}"); + $n++; + if ($n % 3 == 0) { + print STDERR "\n"; + } + } + if ($n % 3 != 0) { + print STDERR "\n"; + } + } + print STDERR "\n"; +} + diff --git a/APACHE_1_3b7/src/test/tcpdumpscii.txt b/APACHE_1_3b7/src/test/tcpdumpscii.txt new file mode 100644 index 0000000000..9c1060edab --- /dev/null +++ b/APACHE_1_3b7/src/test/tcpdumpscii.txt @@ -0,0 +1,50 @@ + +From marcs@znep.com Fri Apr 17 15:16:16 1998 +Date: Sat, 22 Nov 1997 20:44:10 -0700 (MST) +From: Marc Slemko +To: TLOSAP +Subject: Re: Getting ethernet packets content under FreeBSD? (fwd) +Reply-To: new-httpd@apache.org + +Anyone too lazy to hack tcpdump (eg. my tcpdump has a -X option to display +the data in ASCII) can use something like the below to grab HTTP headers +when debugging broken clients. + +Nothing complicated, but handy. + +---------- Forwarded message ---------- +Date: Sat, 22 Nov 1997 14:35:23 PST +From: Bill Fenner +To: Nate Williams +Cc: bmah@ca.sandia.gov, hackers@FreeBSD.ORG +Subject: Re: Getting ethernet packets content under FreeBSD? + +I usually just use this perl script, which I call "tcpdumpscii". +Then run "tcpdumpscii -s 1500 -x [other tcpdump args]". + + Bill + +#!/import/misc/bin/perl +# +# +open(TCPDUMP,"tcpdump -l @ARGV|"); +while () { + if (/^\s+(\S\S)+/) { + $sav = $_; + $asc = ""; + while (s/\s*(\S\S)\s*//) { + $i = hex($1); + if ($i < 32 || $i > 126) { + $asc .= "."; + } else { + $asc .= pack(C,hex($1)); + } + } + $foo = "." x length($asc); + $_ = $sav; + s/\t/ /g; + s/^$foo/$asc/; + } + print; +} + diff --git a/APACHE_1_3b7/src/test/test-writev.c b/APACHE_1_3b7/src/test/test-writev.c new file mode 100644 index 0000000000..852c701766 --- /dev/null +++ b/APACHE_1_3b7/src/test/test-writev.c @@ -0,0 +1,85 @@ +/* + test-writev: use this to figure out if your writev() does intelligent + things on the network. Some writev()s when given multiple buffers + will break them up into multiple packets, which is a waste. + + Linux prior to 2.0.31 has this problem. + + Solaris 2.5, 2.5.1 doesn't appear to, 2.6 hasn't been tested. + + IRIX 5.3 doesn't have this problem. + + To use this you want to snoop the wire with tcpdump, and then run + "test-writev a.b.c.d port#" ... against some TCP service on another + box. For example you can run it against port 80 on another server. + You want to look to see how many data packets are sent, you're hoping + only one of size 300 is sent. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef INADDR_NONE +#define INADDR_NONE (-1ul) +#endif + +void main( int argc, char **argv ) +{ + struct sockaddr_in server_addr; + int s; + struct iovec vector[3]; + char buf[100]; + int i; + const int just_say_no = 1; + + if( argc != 3 ) { +usage: + fprintf( stderr, "usage: test-writev a.b.c.d port#\n" ); + exit( 1 ); + } + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = inet_addr( argv[1] ); + if( server_addr.sin_addr.s_addr == INADDR_NONE ) { + fprintf( stderr, "bogus address\n" ); + goto usage; + } + server_addr.sin_port = htons( atoi( argv[2] ) ); + + s = socket( AF_INET, SOCK_STREAM, 0 ); + if( s < 0 ) { + perror("socket"); + exit(1); + } + if( connect( s, (struct sockaddr *)&server_addr, sizeof( server_addr ) ) + != 0 ) { + perror("connect"); + exit(1); + } + + if( setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&just_say_no, + sizeof(just_say_no)) != 0 ) { + perror( "TCP_NODELAY" ); + exit(1); + } + /* now build up a two part writev and write it out */ + for( i = 0; i < sizeof( buf ); ++i ) { + buf[i] = 'x'; + } + vector[0].iov_base = buf; + vector[0].iov_len = sizeof(buf); + vector[1].iov_base = buf; + vector[1].iov_len = sizeof(buf); + vector[2].iov_base = buf; + vector[2].iov_len = sizeof(buf); + + i = writev( s, &vector[0], 3 ); + fprintf( stdout, "i=%d, errno=%d\n", i, errno ); + exit(0); +} diff --git a/APACHE_1_3b7/src/test/test_date.c b/APACHE_1_3b7/src/test/test_date.c new file mode 100644 index 0000000000..4beaf7943b --- /dev/null +++ b/APACHE_1_3b7/src/test/test_date.c @@ -0,0 +1,180 @@ +/* This program tests the parseHTTPdate routine in ../main/util_date.c. + * + * It is only semiautomated in that I would run it, modify the code to + * use a different algorithm or seed, recompile and run again, etc. + * Obviously it should use an argument for that, but I never got around + * to changing the implementation. + * + * gcc -g -O2 -I../main -o test_date ../main/util_date.o test_date.c + * test_date | egrep '^No ' + * + * Roy Fielding, 1996 + */ +#define API_EXPORT(x) x + +#include +#include +#include "util_date.h" + +static const long year2secs[] = { + 0L, /* 1970 */ + 31536000L, /* 1971 */ + 63072000L, /* 1972 */ + 94694400L, /* 1973 */ + 126230400L, /* 1974 */ + 157766400L, /* 1975 */ + 189302400L, /* 1976 */ + 220924800L, /* 1977 */ + 252460800L, /* 1978 */ + 283996800L, /* 1979 */ + 315532800L, /* 1980 */ + 347155200L, /* 1981 */ + 378691200L, /* 1982 */ + 410227200L, /* 1983 */ + 441763200L, /* 1984 */ + 473385600L, /* 1985 */ + 504921600L, /* 1986 */ + 536457600L, /* 1987 */ + 567993600L, /* 1988 */ + 599616000L, /* 1989 */ + 631152000L, /* 1990 */ + 662688000L, /* 1991 */ + 694224000L, /* 1992 */ + 725846400L, /* 1993 */ + 757382400L, /* 1994 */ + 788918400L, /* 1995 */ + 820454400L, /* 1996 */ + 852076800L, /* 1997 */ + 883612800L, /* 1998 */ + 915148800L, /* 1999 */ + 946684800L, /* 2000 */ + 978307200L, /* 2001 */ + 1009843200L, /* 2002 */ + 1041379200L, /* 2003 */ + 1072915200L, /* 2004 */ + 1104537600L, /* 2005 */ + 1136073600L, /* 2006 */ + 1167609600L, /* 2007 */ + 1199145600L, /* 2008 */ + 1230768000L, /* 2009 */ + 1262304000L, /* 2010 */ + 1293840000L, /* 2011 */ + 1325376000L, /* 2012 */ + 1356998400L, /* 2013 */ + 1388534400L, /* 2014 */ + 1420070400L, /* 2015 */ + 1451606400L, /* 2016 */ + 1483228800L, /* 2017 */ + 1514764800L, /* 2018 */ + 1546300800L, /* 2019 */ + 1577836800L, /* 2020 */ + 1609459200L, /* 2021 */ + 1640995200L, /* 2022 */ + 1672531200L, /* 2023 */ + 1704067200L, /* 2024 */ + 1735689600L, /* 2025 */ + 1767225600L, /* 2026 */ + 1798761600L, /* 2027 */ + 1830297600L, /* 2028 */ + 1861920000L, /* 2029 */ + 1893456000L, /* 2030 */ + 1924992000L, /* 2031 */ + 1956528000L, /* 2032 */ + 1988150400L, /* 2033 */ + 2019686400L, /* 2034 */ + 2051222400L, /* 2035 */ + 2082758400L, /* 2036 */ + 2114380800L, /* 2037 */ + 2145916800L /* 2038 */ +}; + +const char month_snames[12][4] = { + "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" +}; + +void gm_timestr_822(char *ts, time_t sec) +{ + static const char *const days[7]= + {"Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + struct tm *tms; + + tms = gmtime(&sec); + + sprintf(ts, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", days[tms->tm_wday], + tms->tm_mday, month_snames[tms->tm_mon], tms->tm_year + 1900, + tms->tm_hour, tms->tm_min, tms->tm_sec); +} + +void gm_timestr_850(char *ts, time_t sec) +{ + static const char *const days[7]= + {"Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; + struct tm *tms; + int year; + + tms = gmtime(&sec); + + year = tms->tm_year; + if (year >= 100) year -= 100; + + sprintf(ts, "%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", days[tms->tm_wday], + tms->tm_mday, month_snames[tms->tm_mon], year, + tms->tm_hour, tms->tm_min, tms->tm_sec); +} + +void gm_timestr_ccc(char *ts, time_t sec) +{ + static const char *const days[7]= + {"Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + struct tm *tms; + + tms = gmtime(&sec); + + sprintf(ts, "%s %s %2d %.2d:%.2d:%.2d %d", days[tms->tm_wday], + month_snames[tms->tm_mon], tms->tm_mday, + tms->tm_hour, tms->tm_min, tms->tm_sec, tms->tm_year + 1900); +} + +int main (void) +{ + int year, i; + time_t guess; + time_t offset = 0; + /* time_t offset = 0; */ + /* time_t offset = ((31 + 28) * 24 * 3600) - 1; */ + time_t secstodate, newsecs; + char datestr[50]; + + for (year = 1970; year < 2038; ++year) { + secstodate = (time_t)year2secs[year - 1970] + offset; + gm_timestr_822(datestr, secstodate); + newsecs = parseHTTPdate(datestr); + if (secstodate == newsecs) + printf("Yes %4d %11ld %s\n", year, (long)secstodate, datestr); + else if (newsecs == BAD_DATE) + printf("No %4d %11ld %11ld %s\n", year, (long)secstodate, + (long)newsecs, datestr); + else + printf("No* %4d %11ld %11ld %s\n", year, (long)secstodate, + (long)newsecs, datestr); + } + + srand48(978245L); + + for (i = 0; i < 10000; ++i) { + guess = (time_t)mrand48(); + if (guess < 0) guess *= -1; + secstodate = guess + offset; + gm_timestr_822(datestr, secstodate); + newsecs = parseHTTPdate(datestr); + if (secstodate == newsecs) + printf("Yes %11ld %s\n", (long)secstodate, datestr); + else if (newsecs == BAD_DATE) + printf("No %11ld %11ld %s\n", (long)secstodate, + (long)newsecs, datestr); + else + printf("No* %11ld %11ld %s\n", (long)secstodate, + (long)newsecs, datestr); + } + exit(0); +} diff --git a/APACHE_1_3b7/src/test/test_select.c b/APACHE_1_3b7/src/test/test_select.c new file mode 100644 index 0000000000..8c0a6a4363 --- /dev/null +++ b/APACHE_1_3b7/src/test/test_select.c @@ -0,0 +1,30 @@ +/* This is just a quick test program to see how long a wait is + * produced by a select loop with an exponential backoff. + * + * gcc -g -O2 -o test_select test_select.c + * test_select + * + * Roy Fielding, 1996 + */ + +#include +#include +#include + +int main (void) +{ + int srv; + long waittime = 4096; + struct timeval tv; + + printf("Start\n"); + while ((waittime > 0) && (waittime < 3000000)) { + printf("%d\n", waittime); + tv.tv_sec = waittime/1000000; + tv.tv_usec = waittime%1000000; + waittime <<= 1; + srv = select(0, NULL, NULL, NULL, &tv); + } + printf("End\n"); + exit(0); +} diff --git a/APACHE_1_3b7/src/test/time-sem.c b/APACHE_1_3b7/src/test/time-sem.c new file mode 100644 index 0000000000..8bf67c7254 --- /dev/null +++ b/APACHE_1_3b7/src/test/time-sem.c @@ -0,0 +1,572 @@ +/* +time-sem.c has the basics of the semaphores we use in http_main.c. It's +intended for timing differences between various methods on an +architecture. In practice we've found many things affect which semaphore +to be used: + + - NFS filesystems absolutely suck for fcntl() and flock() + + - uslock absolutely sucks on single-processor IRIX boxes, but + absolutely rocks on multi-processor boxes. The converse + is true for fcntl. sysvsem seems a moderate balance. + + - Under Solaris you can't have too many processes use SEM_UNDO, there + might be a tuneable somewhere that increases the limit from 29. + We're not sure what the tunable is, so there's a define + NO_SEM_UNDO which can be used to simulate us trapping/blocking + signals to be able to properly release the semaphore on a clean + child death. You'll also need to define NEED_UNION_SEMUN + under solaris. + +You'll need to define USE_SHMGET_SCOREBOARD if anonymous shared mmap() +doesn't work on your system (i.e. linux). + +argv[1] is the #children, argv[2] is the #iterations per child + +You should run each over many different #children inputs, and choose +#iter such that the program runs for at least a second or so... or even +longer depending on your patience. + +compile with: + +gcc -o time-FCNTL -Wall -O time-sem.c -DUSE_FCNTL_SERIALIZED_ACCEPT +gcc -o time-FLOCK -Wall -O time-sem.c -DUSE_FLOCK_SERIALIZED_ACCEPT +gcc -o time-SYSVSEM -Wall -O time-sem.c -DUSE_SYSVSEM_SERIALIZED_ACCEPT +gcc -o time-SYSVSEM2 -Wall -O time-sem.c -DUSE_SYSVSEM_SERIALIZED_ACCEPT -DNO_SEM_UNDO +gcc -o time-PTHREAD -Wall -O time-sem.c -DUSE_PTHREAD_SERIALIZED_ACCEPT -lpthread +gcc -o time-USLOCK -Wall -O time-sem.c -DUSE_USLOCK_SERIALIZED_ACCEPT + +not all versions work on all systems. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(USE_FCNTL_SERIALIZED_ACCEPT) + +static struct flock lock_it; +static struct flock unlock_it; + +static int fcntl_fd=-1; + +#define accept_mutex_child_init() +#define accept_mutex_cleanup() + +/* + * Initialize mutex lock. + * Must be safe to call this on a restart. + */ +void +accept_mutex_init(void) +{ + + lock_it.l_whence = SEEK_SET; /* from current point */ + lock_it.l_start = 0; /* -"- */ + lock_it.l_len = 0; /* until end of file */ + lock_it.l_type = F_WRLCK; /* set exclusive/write lock */ + lock_it.l_pid = 0; /* pid not actually interesting */ + unlock_it.l_whence = SEEK_SET; /* from current point */ + unlock_it.l_start = 0; /* -"- */ + unlock_it.l_len = 0; /* until end of file */ + unlock_it.l_type = F_UNLCK; /* set exclusive/write lock */ + unlock_it.l_pid = 0; /* pid not actually interesting */ + + printf("opening test-lock-thing in current directory\n"); + fcntl_fd = open("test-lock-thing", O_CREAT | O_WRONLY | O_EXCL, 0644); + if (fcntl_fd == -1) + { + perror ("open"); + fprintf (stderr, "Cannot open lock file: %s\n", "test-lock-thing"); + exit (1); + } + unlink("test-lock-thing"); +} + +void accept_mutex_on(void) +{ + int ret; + + while ((ret = fcntl(fcntl_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR) + continue; + + if (ret < 0) { + perror ("fcntl lock_it"); + exit(1); + } +} + +void accept_mutex_off(void) +{ + if (fcntl (fcntl_fd, F_SETLKW, &unlock_it) < 0) + { + perror ("fcntl unlock_it"); + exit(1); + } +} + +#elif defined(USE_FLOCK_SERIALIZED_ACCEPT) + +#include + +static int flock_fd=-1; + +#define FNAME "test-lock-thing" + +/* + * Initialize mutex lock. + * Must be safe to call this on a restart. + */ +void accept_mutex_init(void) +{ + + printf("opening " FNAME " in current directory\n"); + flock_fd = open(FNAME, O_CREAT | O_WRONLY | O_EXCL, 0644); + if (flock_fd == -1) + { + perror ("open"); + fprintf (stderr, "Cannot open lock file: %s\n", "test-lock-thing"); + exit (1); + } +} + +void accept_mutex_child_init(void) +{ + flock_fd = open(FNAME, O_WRONLY, 0600); + if (flock_fd == -1) { + perror("open"); + exit(1); + } +} + +void accept_mutex_cleanup(void) +{ + unlink(FNAME); +} + +void accept_mutex_on(void) +{ + int ret; + + while ((ret = flock(flock_fd, LOCK_EX)) < 0 && errno == EINTR) + continue; + + if (ret < 0) { + perror ("flock(LOCK_EX)"); + exit(1); + } +} + +void accept_mutex_off(void) +{ + if (flock (flock_fd, LOCK_UN) < 0) + { + perror ("flock(LOCK_UN)"); + exit(1); + } +} + +#elif defined (USE_SYSVSEM_SERIALIZED_ACCEPT) + +#include +#include +#include + +static int sem_id = -1; +#ifdef NO_SEM_UNDO +static sigset_t accept_block_mask; +static sigset_t accept_previous_mask; +#endif + +#define accept_mutex_child_init() +#define accept_mutex_cleanup() + +void accept_mutex_init(void) +{ +#ifdef NEED_UNION_SEMUN + /* believe it or not, you need to define this under solaris */ + union semun { + int val; + struct semid_ds *buf; + ushort *array; + }; +#endif + + union semun ick; + + sem_id = semget(999, 1, IPC_CREAT | 0666); + if (sem_id < 0) { + perror ("semget"); + exit (1); + } + ick.val = 1; + if (semctl(sem_id, 0, SETVAL, ick) < 0) { + perror ("semctl"); + exit(1); + } +#ifdef NO_SEM_UNDO + sigfillset(&accept_block_mask); + sigdelset(&accept_block_mask, SIGHUP); + sigdelset(&accept_block_mask, SIGTERM); + sigdelset(&accept_block_mask, SIGUSR1); +#endif +} + +void accept_mutex_on() +{ + struct sembuf op; + +#ifdef NO_SEM_UNDO + if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) { + perror("sigprocmask(SIG_BLOCK)"); + exit (1); + } + op.sem_flg = 0; +#else + op.sem_flg = SEM_UNDO; +#endif + op.sem_num = 0; + op.sem_op = -1; + if (semop(sem_id, &op, 1) < 0) { + perror ("accept_mutex_on"); + exit (1); + } +} + +void accept_mutex_off() +{ + struct sembuf op; + + op.sem_num = 0; + op.sem_op = 1; +#ifdef NO_SEM_UNDO + op.sem_flg = 0; +#else + op.sem_flg = SEM_UNDO; +#endif + if (semop(sem_id, &op, 1) < 0) { + perror ("accept_mutex_off"); + exit (1); + } +#ifdef NO_SEM_UNDO + if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) { + perror("sigprocmask(SIG_SETMASK)"); + exit (1); + } +#endif +} + +#elif defined (USE_PTHREAD_SERIALIZED_ACCEPT) + +/* note: pthread mutexes aren't released on child death, hence the + * signal goop ... in a real implementation we'd do special things + * during hup, term, usr1. + */ + +#include + +static pthread_mutex_t *mutex; +static sigset_t accept_block_mask; +static sigset_t accept_previous_mask; + +#define accept_mutex_child_init() +#define accept_mutex_cleanup() + +void accept_mutex_init(void) +{ + pthread_mutexattr_t mattr; + int fd; + + fd = open ("/dev/zero", O_RDWR); + if (fd == -1) { + perror ("open(/dev/zero)"); + exit (1); + } + mutex = (pthread_mutex_t *)mmap ((caddr_t)0, sizeof (*mutex), + PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (mutex == (void *)(caddr_t)-1) { + perror ("mmap"); + exit (1); + } + close (fd); + if (pthread_mutexattr_init(&mattr)) { + perror ("pthread_mutexattr_init"); + exit (1); + } + if (pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED)) { + perror ("pthread_mutexattr_setpshared"); + exit (1); + } + if (pthread_mutex_init(mutex, &mattr)) { + perror ("pthread_mutex_init"); + exit (1); + } + sigfillset(&accept_block_mask); + sigdelset(&accept_block_mask, SIGHUP); + sigdelset(&accept_block_mask, SIGTERM); + sigdelset(&accept_block_mask, SIGUSR1); +} + +void accept_mutex_on() +{ + if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) { + perror("sigprocmask(SIG_BLOCK)"); + exit (1); + } + if (pthread_mutex_lock (mutex)) { + perror ("pthread_mutex_lock"); + exit (1); + } +} + +void accept_mutex_off() +{ + if (pthread_mutex_unlock (mutex)) { + perror ("pthread_mutex_unlock"); + exit (1); + } + if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) { + perror("sigprocmask(SIG_SETMASK)"); + exit (1); + } +} + +#elif defined (USE_USLOCK_SERIALIZED_ACCEPT) + +#include + +static usptr_t *us = NULL; +static ulock_t uslock = NULL; + +#define accept_mutex_child_init() +#define accept_mutex_cleanup() + +void accept_mutex_init(void) +{ + ptrdiff_t old; + /* default is 8 */ +#define CONF_INITUSERS_MAX 15 + if ((old = usconfig(CONF_INITUSERS, CONF_INITUSERS_MAX)) == -1) { + perror("usconfig"); + exit(-1); + } + if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) { + perror("usconfig"); + exit(-1); + } + if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) { + perror("usconfig"); + exit(-1); + } + if ((us = usinit("/dev/zero")) == NULL) { + perror("usinit"); + exit(-1); + } + if ((uslock = usnewlock(us)) == NULL) { + perror("usnewlock"); + exit(-1); + } +} +void accept_mutex_on() +{ + switch(ussetlock(uslock)) { + case 1: + /* got lock */ + break; + case 0: + fprintf(stderr, "didn't get lock\n"); + exit(-1); + case -1: + perror("ussetlock"); + exit(-1); + } +} +void accept_mutex_off() +{ + if (usunsetlock(uslock) == -1) { + perror("usunsetlock"); + exit(-1); + } +} +#endif + + +#ifndef USE_SHMGET_SCOREBOARD +static void *get_shared_mem(size_t size) +{ + void *result; + + /* allocate shared memory for the shared_counter */ + result = (unsigned long *)mmap ((caddr_t)0, size, + PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); + if (result == (void *)(caddr_t)-1) { + perror ("mmap"); + exit (1); + } + return result; +} +#else +#include +#include +#include + +static void *get_shared_mem(size_t size) +{ + key_t shmkey = IPC_PRIVATE; + int shmid = -1; + void *result; +#ifdef MOVEBREAK + char *obrk; +#endif + + if ((shmid = shmget(shmkey, size, IPC_CREAT | SHM_R | SHM_W)) == -1) { + perror("shmget"); + exit(1); + } + +#ifdef MOVEBREAK + /* + * Some SysV systems place the shared segment WAY too close + * to the dynamic memory break point (sbrk(0)). This severely + * limits the use of malloc/sbrk in the program since sbrk will + * refuse to move past that point. + * + * To get around this, we move the break point "way up there", + * attach the segment and then move break back down. Ugly + */ + if ((obrk = sbrk(MOVEBREAK)) == (char *) -1) { + perror("sbrk"); + } +#endif + +#define BADSHMAT ((void *)(-1)) + if ((result = shmat(shmid, 0, 0)) == BADSHMAT) { + perror("shmat"); + } + /* + * We must avoid leaving segments in the kernel's + * (small) tables. + */ + if (shmctl(shmid, IPC_RMID, NULL) != 0) { + perror("shmctl(IPC_RMID)"); + } + if (result == BADSHMAT) /* now bailout */ + exit(1); + +#ifdef MOVEBREAK + if (obrk == (char *) -1) + return; /* nothing else to do */ + if (sbrk(-(MOVEBREAK)) == (char *) -1) { + perror("sbrk 2"); + } +#endif + return result; +} +#endif + +#ifdef _POSIX_PRIORITY_SCHEDULING +/* don't ask */ +#define _P __P +#include +#define YIELD sched_yield() +#else +#define YIELD do { struct timeval zero; zero.tv_sec = zero.tv_usec = 0; select(0,0,0,0,&zero); } while(0) +#endif + +void main (int argc, char **argv) +{ + int num_iter; + int num_child; + int i; + struct timeval first; + struct timeval last; + long ms; + int pid; + unsigned long *shared_counter; + + if (argc != 3) { + fprintf (stderr, "Usage: time-sem num-child num-iter\n"); + exit (1); + } + + num_child = atoi (argv[1]); + num_iter = atoi (argv[2]); + + /* allocate shared memory for the shared_counter */ + shared_counter = get_shared_mem(sizeof(*shared_counter)); + + /* initialize counter to 0 */ + *shared_counter = 0; + + accept_mutex_init (); + + /* parent grabs mutex until done spawning children */ + accept_mutex_on (); + + for (i = 0; i < num_child; ++i) { + pid = fork(); + if (pid == 0) { + /* child, do our thing */ + accept_mutex_child_init(); + for (i = 0; i < num_iter; ++i) { + unsigned long tmp; + + accept_mutex_on (); + tmp = *shared_counter; + YIELD; + *shared_counter = tmp + 1; + accept_mutex_off (); + } + exit (0); + } else if (pid == -1) { + perror ("fork"); + exit (1); + } + } + + /* a quick test to see that nothing is screwed up */ + if (*shared_counter != 0) { + puts ("WTF! shared_counter != 0 before the children have been started!"); + exit (1); + } + + gettimeofday (&first, NULL); + /* launch children into action */ + accept_mutex_off (); + for (i = 0; i < num_child; ++i) { + if (wait(NULL) == -1) { + perror ("wait"); + } + } + gettimeofday (&last, NULL); + + if (*shared_counter != num_child * num_iter) { + printf ("WTF! shared_counter != num_child * num_iter!\n" + "shared_counter = %lu\nnum_child = %d\nnum_iter=%d\n", + *shared_counter, + num_child, num_iter); + } + + last.tv_sec -= first.tv_sec; + ms = last.tv_usec - first.tv_usec; + if (ms < 0) { + --last.tv_sec; + ms += 1000000; + } + last.tv_usec = ms; + printf ("%8lu.%06lu\n", last.tv_sec, last.tv_usec); + + accept_mutex_cleanup(); + + exit(0); +} + diff --git a/APACHE_1_3b7/src/test/vhtest/README b/APACHE_1_3b7/src/test/vhtest/README new file mode 100644 index 0000000000..e5b422201a --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/README @@ -0,0 +1,53 @@ +This is a basic test of the virtual host functionality. + +At present it *does not test*: + +- ServerPath +- DNS lookups (specifically, multiple A records is interesting) + +It does test the basic gear that uses ip addresses and ports to decide what +ip-vhost or set of name-vhosts are to be considered. It tests _default_ +behaviour with both explicit and wildcard ports. It tests the precedence +behaviour -- i.e. earlier vhosts have higher precedence than later vhosts. +It has a basic ServerAlias test. + +It also tests some error conditions. + +These tests are "white box" tests, i.e. I know how the code is written and +I'm testing very specific cases within the code. Black box tests would +be nice too. + +To use: + + perl -pi.orig -e "s#/home/dgaudet/ap/vhtest#`pwd`#" conf/*.conf + ./runtest /path/to/httpd + +Or to run a specific test: + + ./runtest /path/to/httpd test3 + +The output looks something like: + +127.0.0.1:8080 '' 'vhost1' : passed +127.0.0.1:8080 'vhost1:8080' 'vhost1' : passed +127.0.0.1:8080 'vhost2:8080' 'vhost1' : passed +127.0.0.1:8081 '' 'vhost2' : passed +127.0.0.1:8081 'vhost2:8081' 'vhost2' : passed +127.0.0.1:8081 'vhost1:8081' 'vhost2' : passed +127.0.0.2:8080 '' 'vhost3' : passed + +The first column is the ipaddr:port connected to. The second column is +the Host: header sent ('' means no Host: header sent). The third column +is the vhost expected. + +It probably only works on Linux because it uses the loopback interface for +all tests -- and Linux lo0 responds to *all* addresses in 127/8 rather than +just 127.0.0.1. You'd probably have to add the following aliases to other +boxes: + + 127.0.0.2 + 127.0.0.3 + 127.0.0.4 + 127.0.0.5 + +Dean diff --git a/APACHE_1_3b7/src/test/vhtest/bin/test1 b/APACHE_1_3b7/src/test/vhtest/bin/test1 new file mode 100644 index 0000000000..0b3dc8c456 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/bin/test1 @@ -0,0 +1,29 @@ +bin/vhget 127.0.0.1 8080 '' '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost1:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost2:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1 + +bin/vhget 127.0.0.2 8080 '' '' vhost2 +bin/vhget 127.0.0.2 8080 vhost2:8080 '' vhost2 +bin/vhget 127.0.0.2 8080 vhost1:8080 '' vhost2 +bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost1:8080' vhost2 +bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost2:8080' vhost2 +bin/vhget 127.0.0.2 8080 vhost2:8080 'vhost2:8080' vhost2 +bin/vhget 127.0.0.2 8080 vhost2:8080 'vhost1:8080' vhost2 + +bin/vhget 127.0.0.3 8080 '' '' vhost3 +bin/vhget 127.0.0.3 8080 vhost3:8080 '' vhost3 +bin/vhget 127.0.0.3 8080 vhost3:8080 'vhost3:8080' vhost3 +bin/vhget 127.0.0.3 8080 vhost3:8080 'vhost4:8080' vhost4 +bin/vhget 127.0.0.3 8080 vhost4:8080 '' vhost4 +bin/vhget 127.0.0.3 8080 vhost4:8080 'vhost3:8080' vhost3 +bin/vhget 127.0.0.3 8080 vhost4:8080 'vhost4:8080' vhost4 + +bin/vhget 127.0.0.4 8080 '' '' main +bin/vhget 127.0.0.4 8080 'vhost1' '' main +bin/vhget 127.0.0.4 8080 'vhost1' 'vhost1:8080' main +bin/vhget 127.0.0.4 8080 'vhost2' '' main +bin/vhget 127.0.0.4 8080 'vhost2' 'vhost2:8080' main diff --git a/APACHE_1_3b7/src/test/vhtest/bin/test1d b/APACHE_1_3b7/src/test/vhtest/bin/test1d new file mode 100644 index 0000000000..53c7e39d12 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/bin/test1d @@ -0,0 +1,29 @@ +bin/vhget 127.0.0.1 8080 '' '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost1:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost2:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1 + +bin/vhget 127.0.0.2 8080 '' '' vhost2 +bin/vhget 127.0.0.2 8080 vhost2:8080 '' vhost2 +bin/vhget 127.0.0.2 8080 vhost1:8080 '' vhost2 +bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost1:8080' vhost2 +bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost2:8080' vhost2 +bin/vhget 127.0.0.2 8080 vhost2:8080 'vhost2:8080' vhost2 +bin/vhget 127.0.0.2 8080 vhost2:8080 'vhost1:8080' vhost2 + +bin/vhget 127.0.0.3 8080 '' '' vhost3 +bin/vhget 127.0.0.3 8080 vhost3:8080 '' vhost3 +bin/vhget 127.0.0.3 8080 vhost3:8080 'vhost3:8080' vhost3 +bin/vhget 127.0.0.3 8080 vhost3:8080 'vhost4:8080' vhost4 +bin/vhget 127.0.0.3 8080 vhost4:8080 '' vhost4 +bin/vhget 127.0.0.3 8080 vhost4:8080 'vhost3:8080' vhost3 +bin/vhget 127.0.0.3 8080 vhost4:8080 'vhost4:8080' vhost4 + +bin/vhget 127.0.0.4 8080 '' '' default1 +bin/vhget 127.0.0.4 8080 'vhost1' '' default1 +bin/vhget 127.0.0.4 8080 'vhost1' 'vhost1:8080' default1 +bin/vhget 127.0.0.4 8080 'vhost2' '' default1 +bin/vhget 127.0.0.4 8080 'vhost2' 'vhost2:8080' default1 diff --git a/APACHE_1_3b7/src/test/vhtest/bin/test2 b/APACHE_1_3b7/src/test/vhtest/bin/test2 new file mode 100644 index 0000000000..074f6ddbf1 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/bin/test2 @@ -0,0 +1,45 @@ +bin/vhget 127.0.0.1 8080 '' '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost1 + +bin/vhget 127.0.0.1 8081 '' '' vhost2 +bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost2 +bin/vhget 127.0.0.1 8081 vhost1:8081 'vhost2:8081' vhost2 +bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost2 +bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost1:8081' vhost2 + +bin/vhget 127.0.0.2 8080 '' '' vhost3 +bin/vhget 127.0.0.2 8080 vhost3:8080 '' vhost3 +bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost3:8080' vhost3 +bin/vhget 127.0.0.2 8080 vhost1:8080 '' vhost3 +bin/vhget 127.0.0.2 8080 vhost3:8080 'vhost1:8080' vhost3 +bin/vhget 127.0.0.2 8081 '' '' vhost3 +bin/vhget 127.0.0.2 8081 vhost3:8081 '' vhost3 +bin/vhget 127.0.0.2 8081 vhost3:8081 'vhost1:8081' vhost3 +bin/vhget 127.0.0.2 8081 vhost1:8081 '' vhost3 +bin/vhget 127.0.0.2 8081 vhost1:8081 'vhost3:8081' vhost3 + +bin/vhget 127.0.0.3 8080 '' '' vhost4 +bin/vhget 127.0.0.3 8080 'vhost4:8080' '' vhost4 +bin/vhget 127.0.0.3 8080 'vhost5:8080' 'vhost4:8080' vhost4 +bin/vhget 127.0.0.3 8080 'vhost5:8080' 'bogus:8080' vhost4 +bin/vhget 127.0.0.3 8080 'vhost5:8080' '' vhost5 +bin/vhget 127.0.0.3 8080 'vhost4:8080' 'vhost5:8080' vhost5 + +bin/vhget 127.0.0.3 8081 '' '' vhost5 +bin/vhget 127.0.0.3 8081 'vhost4:8081' '' vhost5 +bin/vhget 127.0.0.3 8081 'vhost4:8081' 'vhost4:8081' vhost5 +bin/vhget 127.0.0.3 8081 'vhost4:8081' 'bogus:8081' vhost5 +bin/vhget 127.0.0.3 8081 'vhost4:8081' 'alt5:8081' vhost5 +bin/vhget 127.0.0.3 8081 'vhost5:8081' '' vhost5 +bin/vhget 127.0.0.3 8081 'alt5:8081' '' vhost5 + +bin/vhget 127.0.0.4 8080 '' '' main +bin/vhget 127.0.0.4 8080 'asdf' 'bogus' main +bin/vhget 127.0.0.4 8080 'vhost1:8080' '' main +bin/vhget 127.0.0.4 8080 'vhost1:8080' 'vhost2:8081' main +bin/vhget 127.0.0.4 8081 '' '' main +bin/vhget 127.0.0.4 8081 'asdf' 'bogus:8080' main +bin/vhget 127.0.0.4 8081 'vhost1:8081' '' main diff --git a/APACHE_1_3b7/src/test/vhtest/bin/test2d b/APACHE_1_3b7/src/test/vhtest/bin/test2d new file mode 100644 index 0000000000..df90392e7c --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/bin/test2d @@ -0,0 +1,45 @@ +bin/vhget 127.0.0.1 8080 '' '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost1 + +bin/vhget 127.0.0.1 8081 '' '' vhost2 +bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost2 +bin/vhget 127.0.0.1 8081 vhost1:8081 'vhost2:8081' vhost2 +bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost2 +bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost1:8081' vhost2 + +bin/vhget 127.0.0.2 8080 '' '' vhost3 +bin/vhget 127.0.0.2 8080 vhost3:8080 '' vhost3 +bin/vhget 127.0.0.2 8080 vhost1:8080 'vhost3:8080' vhost3 +bin/vhget 127.0.0.2 8080 vhost1:8080 '' vhost3 +bin/vhget 127.0.0.2 8080 vhost3:8080 'vhost1:8080' vhost3 +bin/vhget 127.0.0.2 8081 '' '' vhost3 +bin/vhget 127.0.0.2 8081 vhost3:8081 '' vhost3 +bin/vhget 127.0.0.2 8081 vhost3:8081 'vhost1:8081' vhost3 +bin/vhget 127.0.0.2 8081 vhost1:8081 '' vhost3 +bin/vhget 127.0.0.2 8081 vhost1:8081 'vhost3:8081' vhost3 + +bin/vhget 127.0.0.3 8080 '' '' vhost4 +bin/vhget 127.0.0.3 8080 'vhost4:8080' '' vhost4 +bin/vhget 127.0.0.3 8080 'vhost5:8080' 'vhost4:8080' vhost4 +bin/vhget 127.0.0.3 8080 'vhost5:8080' 'bogus:8080' vhost4 +bin/vhget 127.0.0.3 8080 'vhost5:8080' '' vhost5 +bin/vhget 127.0.0.3 8080 'vhost4:8080' 'vhost5:8080' vhost5 + +bin/vhget 127.0.0.3 8081 '' '' vhost5 +bin/vhget 127.0.0.3 8081 'vhost4:8081' '' vhost5 +bin/vhget 127.0.0.3 8081 'vhost4:8081' 'vhost4:8081' vhost5 +bin/vhget 127.0.0.3 8081 'vhost4:8081' 'bogus:8081' vhost5 +bin/vhget 127.0.0.3 8081 'vhost4:8081' 'alt5:8081' vhost5 +bin/vhget 127.0.0.3 8081 'vhost5:8081' '' vhost5 +bin/vhget 127.0.0.3 8081 'alt5:8081' '' vhost5 + +bin/vhget 127.0.0.4 8080 '' '' default1 +bin/vhget 127.0.0.4 8080 'asdf' 'bogus' default1 +bin/vhget 127.0.0.4 8080 'vhost1:8080' '' default1 +bin/vhget 127.0.0.4 8080 'vhost1:8080' 'vhost2:8081' default1 +bin/vhget 127.0.0.4 8081 '' '' default2 +bin/vhget 127.0.0.4 8081 'asdf' 'bogus:8080' default2 +bin/vhget 127.0.0.4 8081 'vhost1:8081' '' default2 diff --git a/APACHE_1_3b7/src/test/vhtest/bin/test3 b/APACHE_1_3b7/src/test/vhtest/bin/test3 new file mode 100644 index 0000000000..18c92e3eea --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/bin/test3 @@ -0,0 +1,18 @@ +bin/vhget 127.0.0.1 8080 '' '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost2 +bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost2 +bin/vhget 127.0.0.1 8080 vhost3:8080 '' vhost3 +bin/vhget 127.0.0.1 8080 vhost4:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost5:8080 'vhost4:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost5:8080 '' vhost5 + +bin/vhget 127.0.0.1 8081 '' '' vhost2 +bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost2 +bin/vhget 127.0.0.1 8081 vhost3:8081 'vhost1:8081' vhost2 +bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost2 +bin/vhget 127.0.0.1 8081 vhost3:8081 '' vhost3 +bin/vhget 127.0.0.1 8081 vhost4:8081 '' vhost4 +bin/vhget 127.0.0.1 8081 vhost5:8081 '' vhost5 diff --git a/APACHE_1_3b7/src/test/vhtest/bin/test4 b/APACHE_1_3b7/src/test/vhtest/bin/test4 new file mode 100644 index 0000000000..f0d54b3465 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/bin/test4 @@ -0,0 +1,13 @@ +bin/vhget 127.0.0.1 8080 '' '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost3:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost2 +bin/vhget 127.0.0.1 8080 vhost3:8080 '' vhost1 + +bin/vhget 127.0.0.1 8081 '' '' vhost1 +bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost1 +bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost1:8081' vhost1 +bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost3:8081' vhost1 +bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost2 +bin/vhget 127.0.0.1 8081 vhost3:8081 '' vhost1 diff --git a/APACHE_1_3b7/src/test/vhtest/bin/test5 b/APACHE_1_3b7/src/test/vhtest/bin/test5 new file mode 100644 index 0000000000..de73c35561 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/bin/test5 @@ -0,0 +1,31 @@ +bin/vhget 127.0.0.1 8080 '' '' vhost1 +bin/vhget 127.0.0.1 8080 vhost1:8080 '' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'bogus' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 'vhost1:8080' vhost1 +bin/vhget 127.0.0.1 8080 vhost2:8080 '' vhost2 +bin/vhget 127.0.0.1 8080 vhost1:8080 'vhost2:8080' vhost2 +bin/vhget 127.0.0.1 8080 vhost3:8080 '' vhost1 + +bin/vhget 127.0.0.2 8080 '' '' vhost3 +bin/vhget 127.0.0.2 8080 'vhost3:8080' '' vhost3 +bin/vhget 127.0.0.2 8080 'vhost1:8080' 'bogus' vhost3 +bin/vhget 127.0.0.2 8080 'vhost1:8080' '' vhost3 + +bin/vhget 127.0.0.3 8080 '' '' default1 +bin/vhget 127.0.0.3 8080 'vhost1:8080' '' default1 +bin/vhget 127.0.0.3 8080 'asdf' 'bogus' default1 + +bin/vhget 127.0.0.1 8081 '' '' vhost4 +bin/vhget 127.0.0.1 8081 vhost1:8081 '' vhost4 +bin/vhget 127.0.0.1 8081 vhost2:8081 'vhost1:8080' vhost4 +bin/vhget 127.0.0.1 8081 vhost2:8081 '' vhost4 +bin/vhget 127.0.0.1 8081 vhost3:8081 '' vhost4 + +bin/vhget 127.0.0.2 8081 '' '' vhost5 +bin/vhget 127.0.0.2 8081 'vhost3:8081' '' vhost5 +bin/vhget 127.0.0.2 8081 'vhost1:8081' 'vhost3:8081' vhost5 +bin/vhget 127.0.0.2 8081 'vhost1:8081' '' vhost5 + +bin/vhget 127.0.0.3 8081 '' '' default2 +bin/vhget 127.0.0.3 8081 'bogus' 'asdf' default2 +bin/vhget 127.0.0.3 8081 'vhost1:8081' '' default2 diff --git a/APACHE_1_3b7/src/test/vhtest/bin/test6 b/APACHE_1_3b7/src/test/vhtest/bin/test6 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/APACHE_1_3b7/src/test/vhtest/bin/vhget b/APACHE_1_3b7/src/test/vhtest/bin/vhget new file mode 100755 index 0000000000..62f3148c02 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/bin/vhget @@ -0,0 +1,74 @@ +#!/usr/bin/perl -w + +require 5.002; +use strict; +use Socket; + +# vhget ipaddr port hostheader absurihost expect + +$#ARGV == 4 || die "usage: $0 ipaddr port hostheader absurihost expect\n"; + +my ($remote,$port, $iaddr, $paddr, $proto, $line); + +my ($hostheader, $expect, $absurihost); + +($remote, $port, $hostheader, $absurihost, $expect) = @ARGV; +if ($absurihost ne '') { + $absurihost = "http://$absurihost"; +} + +printf "%-20s %-20s %-20s %-15s: ", "$remote:$port", "'$hostheader'", "'$absurihost'", "'$expect'"; + +if ($port =~ /\D/) { + $port = getservbyname($port, 'tcp'); +} +die "No port" unless $port; +$iaddr = inet_aton($remote) || die "no host: $remote"; +$paddr = sockaddr_in($port, $iaddr); +$proto = getprotobyname('tcp'); +socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; +connect(SOCK, $paddr) || die "connect: $!"; + +my $oldfh = select(SOCK); $| = 1; select($oldfh); + +$proto = ($absurihost ne '') ? "HTTP/1.1" : "HTTP/1.0"; + +if ($hostheader ne '') { + print SOCK <) || die "error reading response: $!\n"; + +($line =~ m#^HTTP/1\.1 200#) || die "HTTP error: $line\n"; + +while (defined($line = )) { + last if $line =~ /^\r?$/; +} + +defined($line = ) || die "error reading response: $!\n"; + +chomp($line); + +my $death = "$remote:$port with " + . ( $hostheader eq '' ? "no Host:" : "Host: $hostheader" ) + . ( $absurihost eq '' ? " no absuri" : " and absuri $absurihost" ) + . " expected $expect, but got $line\n"; +if ($line eq $expect) { + print "passed\n"; +} else { + print "failed, got '$line'\n"; +} + +close (SOCK) || die "close: $!"; +exit; diff --git a/APACHE_1_3b7/src/test/vhtest/conf/common.conf b/APACHE_1_3b7/src/test/vhtest/conf/common.conf new file mode 100644 index 0000000000..ec5e9fe94b --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/common.conf @@ -0,0 +1,24 @@ +ServerType standalone +Port 8080 +HostnameLookups off +User nobody +Group #-1 +ServerRoot /home/dgaudet/ap/vhtest +ErrorLog logs/error_log +LogLevel debug +# vhost "Host header" "request" response-code +LogFormat "%v \"%{Host}i\" \"%r\" %>s" +TransferLog logs/access_log +PidFile logs/httpd.pid +ResourceConfig /dev/null +AccessConfig /dev/null +ServerName main +DocumentRoot /home/dgaudet/ap/vhtest/docroot/main + + +AllowOverride none +Options FollowSymLinks +order allow,deny +allow from all + + diff --git a/APACHE_1_3b7/src/test/vhtest/conf/mime.types b/APACHE_1_3b7/src/test/vhtest/conf/mime.types new file mode 100644 index 0000000000..5af88ff4f2 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/mime.types @@ -0,0 +1,103 @@ +# This file controls what MIME types are sent to the client for the +# given file extensions. Sending the correct MIME type to the client +# is important so they know how to handle the content of the file. +# Extra types can either be added here or by using an AddType directive +# in your config files. + +# MIME type Extension +application/activemessage +application/andrew-inset +application/applefile +application/atomicmail +application/dca-rft +application/dec-dx +application/mac-binhex40 hqx +application/mac-compactpro cpt +application/macwriteii +application/msword doc +application/news-message-id +application/news-transmission +application/octet-stream bin dms lha lzh exe class +application/oda oda +application/pdf pdf +application/postscript ai eps ps +application/powerpoint ppt +application/remote-printing +application/rtf rtf +application/slate +application/wita +application/wordperfect5.1 +application/x-bcpio bcpio +application/x-cdlink vcd +application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-director dcr dir dxr +application/x-dvi dvi +application/x-gtar gtar +application/x-gzip +application/x-hdf hdf +application/x-koan skp skd skt skm +application/x-latex latex +application/x-mif mif +application/x-netcdf nc cdf +application/x-sh sh +application/x-shar shar +application/x-stuffit sit +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-texinfo texinfo texi +application/x-troff t tr roff +application/x-troff-man man +application/x-troff-me me +application/x-troff-ms ms +application/x-ustar ustar +application/x-wais-source src +application/zip zip +audio/basic au snd +audio/midi mid midi kar +audio/mpeg mpga mp2 +audio/x-aiff aif aiff aifc +audio/x-pn-realaudio ram +audio/x-pn-realaudio-plugin rpm +audio/x-realaudio ra +audio/x-wav wav +chemical/x-pdb pdb xyz +image/gif gif +image/ief ief +image/jpeg jpeg jpg jpe +image/png png +image/tiff tiff tif +image/x-cmu-raster ras +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +message/external-body +message/news +message/partial +message/rfc822 +multipart/alternative +multipart/appledouble +multipart/digest +multipart/mixed +multipart/parallel +text/html html htm +text/plain txt +text/richtext rtx +text/tab-separated-values tsv +text/x-setext etx +text/x-sgml sgml sgm +video/mpeg mpeg mpg mpe +video/quicktime qt mov +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice +x-world/x-vrml wrl vrml diff --git a/APACHE_1_3b7/src/test/vhtest/conf/test1.conf b/APACHE_1_3b7/src/test/vhtest/conf/test1.conf new file mode 100644 index 0000000000..2053020122 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/test1.conf @@ -0,0 +1,28 @@ +## test some basic ip-vhosts and a single name-vhost address + +Include /home/dgaudet/ap/vhtest/conf/common.conf + +#Listen 127.0.0.1:8080 +#Listen 127.0.0.2:8080 + +NameVirtualHost 127.0.0.3:8080 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + diff --git a/APACHE_1_3b7/src/test/vhtest/conf/test1d.conf b/APACHE_1_3b7/src/test/vhtest/conf/test1d.conf new file mode 100644 index 0000000000..d55cff7ada --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/test1d.conf @@ -0,0 +1,33 @@ +## same as test1, but we throw in a _default_ + +Include /home/dgaudet/ap/vhtest/conf/common.conf + +#Listen 127.0.0.1:8080 +#Listen 127.0.0.2:8080 + +NameVirtualHost 127.0.0.3:8080 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName default1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1 + diff --git a/APACHE_1_3b7/src/test/vhtest/conf/test2.conf b/APACHE_1_3b7/src/test/vhtest/conf/test2.conf new file mode 100644 index 0000000000..0bed833702 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/test2.conf @@ -0,0 +1,35 @@ +## test more complex ip-vhosts with multiple ports, and name-vhosts on a +## single port of one ip + +Include /home/dgaudet/ap/vhtest/conf/common.conf + +Listen *:8080 +Listen *:8081 + +NameVirtualHost 127.0.0.3:8080 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName vhost5 +ServerAlias alt5 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5 + diff --git a/APACHE_1_3b7/src/test/vhtest/conf/test2d.conf b/APACHE_1_3b7/src/test/vhtest/conf/test2d.conf new file mode 100644 index 0000000000..9be181edae --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/test2d.conf @@ -0,0 +1,45 @@ +## same as test2, but throw in a _default_ two port test + +Include /home/dgaudet/ap/vhtest/conf/common.conf + +Listen *:8080 +Listen *:8081 + +NameVirtualHost 127.0.0.3:8080 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName vhost5 +ServerAlias alt5 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5 + + + +ServerName default1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1 + + + +ServerName default2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default2 + + diff --git a/APACHE_1_3b7/src/test/vhtest/conf/test3.conf b/APACHE_1_3b7/src/test/vhtest/conf/test3.conf new file mode 100644 index 0000000000..753d56bc8c --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/test3.conf @@ -0,0 +1,34 @@ +## multiple name-vhosts on multiple ports + +Include /home/dgaudet/ap/vhtest/conf/common.conf + +Listen *:8080 +Listen *:8081 + +NameVirtualHost 127.0.0.1:8080 +NameVirtualHost 127.0.0.1:8081 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName vhost5 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5 + diff --git a/APACHE_1_3b7/src/test/vhtest/conf/test4.conf b/APACHE_1_3b7/src/test/vhtest/conf/test4.conf new file mode 100644 index 0000000000..e0cd9ca931 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/test4.conf @@ -0,0 +1,18 @@ +## wildcard namevhost address + +Include /home/dgaudet/ap/vhtest/conf/common.conf + +Listen *:8080 +Listen *:8081 + +NameVirtualHost 127.0.0.1:* + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + diff --git a/APACHE_1_3b7/src/test/vhtest/conf/test5.conf b/APACHE_1_3b7/src/test/vhtest/conf/test5.conf new file mode 100644 index 0000000000..cd31f416d1 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/test5.conf @@ -0,0 +1,44 @@ +## no ports listed, they should all default to 8080, but we're also listening +## on 8081 + +Include /home/dgaudet/ap/vhtest/conf/common.conf + +Listen 8080 +Listen 8081 + +NameVirtualHost 127.0.0.1 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName default1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName vhost5 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5 + + + +ServerName default2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default2 + diff --git a/APACHE_1_3b7/src/test/vhtest/conf/test6.conf b/APACHE_1_3b7/src/test/vhtest/conf/test6.conf new file mode 100644 index 0000000000..b62e8bcb23 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/conf/test6.conf @@ -0,0 +1,42 @@ +Include /home/dgaudet/ap/vhtest/conf/common.conf + +## expect a warning about mixing * and non-* ports on vhost 127.0.0.1:8080 +NameVirtualHost 127.0.0.1:* + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + +## expect a warning about mixing * and non-* ports on vhost 127.0.0.2:0 +NameVirtualHost 127.0.0.2:8081 + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + +## expect a warning about overlapping _default_ on port 8080 + +ServerName default1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1 + + + +ServerName default2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default2 + + +## expect a warning about overlapping virtualhosts on 127.0.0.3:8080 + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + +## expect all warnings to be printed twice, and probably in the opposite +## order mentioned here diff --git a/APACHE_1_3b7/src/test/vhtest/docroot/default1/vhost.txt b/APACHE_1_3b7/src/test/vhtest/docroot/default1/vhost.txt new file mode 100644 index 0000000000..312ae9a115 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/docroot/default1/vhost.txt @@ -0,0 +1 @@ +default1 diff --git a/APACHE_1_3b7/src/test/vhtest/docroot/default2/vhost.txt b/APACHE_1_3b7/src/test/vhtest/docroot/default2/vhost.txt new file mode 100644 index 0000000000..07cee68e42 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/docroot/default2/vhost.txt @@ -0,0 +1 @@ +default2 diff --git a/APACHE_1_3b7/src/test/vhtest/docroot/default3/vhost.txt b/APACHE_1_3b7/src/test/vhtest/docroot/default3/vhost.txt new file mode 100644 index 0000000000..3df81a4e03 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/docroot/default3/vhost.txt @@ -0,0 +1 @@ +default3 diff --git a/APACHE_1_3b7/src/test/vhtest/docroot/main/vhost.txt b/APACHE_1_3b7/src/test/vhtest/docroot/main/vhost.txt new file mode 100644 index 0000000000..ba2906d066 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/docroot/main/vhost.txt @@ -0,0 +1 @@ +main diff --git a/APACHE_1_3b7/src/test/vhtest/docroot/vhost1/vhost.txt b/APACHE_1_3b7/src/test/vhtest/docroot/vhost1/vhost.txt new file mode 100644 index 0000000000..0535c7a40c --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/docroot/vhost1/vhost.txt @@ -0,0 +1 @@ +vhost1 diff --git a/APACHE_1_3b7/src/test/vhtest/docroot/vhost2/vhost.txt b/APACHE_1_3b7/src/test/vhtest/docroot/vhost2/vhost.txt new file mode 100644 index 0000000000..64290e275d --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/docroot/vhost2/vhost.txt @@ -0,0 +1 @@ +vhost2 diff --git a/APACHE_1_3b7/src/test/vhtest/docroot/vhost3/vhost.txt b/APACHE_1_3b7/src/test/vhtest/docroot/vhost3/vhost.txt new file mode 100644 index 0000000000..f43b943a61 --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/docroot/vhost3/vhost.txt @@ -0,0 +1 @@ +vhost3 diff --git a/APACHE_1_3b7/src/test/vhtest/docroot/vhost4/vhost.txt b/APACHE_1_3b7/src/test/vhtest/docroot/vhost4/vhost.txt new file mode 100644 index 0000000000..8e66b98d9c --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/docroot/vhost4/vhost.txt @@ -0,0 +1 @@ +vhost4 diff --git a/APACHE_1_3b7/src/test/vhtest/docroot/vhost5/vhost.txt b/APACHE_1_3b7/src/test/vhtest/docroot/vhost5/vhost.txt new file mode 100644 index 0000000000..a67c8304fb --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/docroot/vhost5/vhost.txt @@ -0,0 +1 @@ +vhost5 diff --git a/APACHE_1_3b7/src/test/vhtest/logs/.cvsignore b/APACHE_1_3b7/src/test/vhtest/logs/.cvsignore new file mode 100644 index 0000000000..72e8ffc0db --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/logs/.cvsignore @@ -0,0 +1 @@ +* diff --git a/APACHE_1_3b7/src/test/vhtest/runtest b/APACHE_1_3b7/src/test/vhtest/runtest new file mode 100755 index 0000000000..e281ec265a --- /dev/null +++ b/APACHE_1_3b7/src/test/vhtest/runtest @@ -0,0 +1,42 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then + echo "usage: runtest /path/to/httpd" 1>&2 + exit 1 +fi; + +httpd="$1" +shift +pwd="`pwd`" + + +if [ $# = 0 ]; then + list=conf/test*.conf +else + list=$* +fi + +pid=0 +exitcode=0 +trap 'kill $pid >/dev/null 2>&1; exit $exitcode' 0 1 2 3 15 + +for i in $list; do + j=`echo $i | sed -e 's#.*/##' -e 's#\.conf$##'` + echo '' + echo "==== $j ====" + f="$pwd/conf/$j.conf" + grep '^##' $f + $httpd -f $f + # such a pain to wait for the pid file to be created + sleep 1 + pid="`cat logs/httpd.pid`" + + sh bin/$j + + # such a pain to know if it has finished + kill $pid + sleep 1 + while kill -0 $pid >/dev/null 2>&1; do + sleep 1 + done +done diff --git a/APACHE_1_3b7/src/test/zb.c b/APACHE_1_3b7/src/test/zb.c new file mode 100644 index 0000000000..0a6666eb25 --- /dev/null +++ b/APACHE_1_3b7/src/test/zb.c @@ -0,0 +1,567 @@ + +/* ZeusBench V1.01 + =============== + +This program is Copyright (C) Zeus Technology Limited 1996. + +This program may be used and copied freely providing this copyright notice +is not removed. + +This software is provided "as is" and any express or implied waranties, +including but not limited to, the implied warranties of merchantability and +fitness for a particular purpose are disclaimed. In no event shall +Zeus Technology Ltd. be liable for any direct, indirect, incidental, special, +exemplary, or consequential damaged (including, but not limited to, +procurement of substitute good or services; loss of use, data, or profits; +or business interruption) however caused and on 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. + + Written by Adam Twiss (adam@zeus.co.uk). March 1996 + +Thanks to the following people for their input: + Mike Belshe (mbelshe@netscape.com) + Michael Campanella (campanella@stevms.enet.dec.com) + +*/ + +/* -------------------- Notes on compiling ------------------------------ + +This should compile unmodified using gcc on HP-UX, FreeBSD, Linux, +IRIX, Solaris, AIX and Digital Unix (OSF). On Solaris 2.x you will +need to compile with "-lnsl -lsocket" options. If you have any +difficulties compiling then let me know. + +On SunOS 4.x.x you may need to compile with -DSUNOS4 to add the following +two lines of code which appear not to exist in my SunOS headers */ + +#ifdef SUNOS4 +extern char *optarg; +extern int optind, opterr, optopt; +#endif + +/* -------------------------------------------------------------------- */ + +/* affects include files on Solaris */ +#define BSD_COMP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ------------------- DEFINITIONS -------------------------- */ + +/* maximum number of requests on a time limited test */ +#define MAX_REQUESTS 50000 + +/* good old state machine */ +#define STATE_UNCONNECTED 0 +#define STATE_CONNECTING 1 +#define STATE_READ 2 + +#define CBUFFSIZE 512 + +struct connection +{ + int fd; + int state; + int read; /* amount of bytes read */ + int bread; /* amount of body read */ + int length; /* Content-Length value used for keep-alive */ + char cbuff[CBUFFSIZE]; /* a buffer to store server response header */ + int cbx; /* offset in cbuffer */ + int keepalive; /* non-zero if a keep-alive request */ + int gotheader; /* non-zero if we have the entire header in cbuff */ + struct timeval start, connect, done; +}; + +struct data +{ + int read; /* number of bytes read */ + int ctime; /* time in ms to connect */ + int time; /* time in ms for connection */ +}; + +#define min(a,b) ((a)<(b))?(a):(b) +#define max(a,b) ((a)>(b))?(a):(b) + +/* --------------------- GLOBALS ---------------------------- */ + +int requests = 1; /* Number of requests to make */ +int concurrency = 1; /* Number of multiple requests to make */ +int tlimit = 0; /* time limit in cs */ +int keepalive = 0; /* try and do keepalive connections */ +char *machine; /* Machine name */ +char *file; /* file name to use */ +char server_name[80]; /* name that server reports */ +int port = 80; /* port to use */ + +int doclen = 0; /* the length the document should be */ +int totalread = 0; /* total number of bytes read */ +int totalbread = 0; /* totoal amount of entity body read */ +int done=0; /* number of requests we have done */ +int doneka=0; /* number of keep alive connections done */ +int good=0, bad=0; /* number of good and bad requests */ + +/* store error cases */ +int err_length = 0, err_conn = 0, err_except = 0; + +struct timeval start, endtime; + +/* global request (and its length) */ +char request[512]; +int reqlen; + +/* one global throw-away buffer to read stuff into */ +char buffer[4096]; + +struct connection *con; /* connection array */ +struct data *stats; /* date for each request */ + +fd_set readbits, writebits; /* bits for select */ +struct sockaddr_in server; /* server addr structure */ + +/* --------------------------------------------------------- */ + +/* simple little function to perror and exit */ + +static void err(char *s) +{ + perror(s); + exit(errno); +} + +/* --------------------------------------------------------- */ + +/* write out request to a connection - assumes we can write + (small) request out in one go into our new socket buffer */ + +void write_request(struct connection *c) +{ + gettimeofday(&c->connect,0); + write(c->fd,request, reqlen); + c->state = STATE_READ; + FD_SET(c->fd, &readbits); + FD_CLR(c->fd, &writebits); +} + +/* --------------------------------------------------------- */ + +/* make an fd non blocking */ + +void nonblock(int fd) +{ + int i=1; + ioctl(fd, FIONBIO, &i); +} + +/* --------------------------------------------------------- */ + +/* returns the time in ms between two timevals */ + +int timedif(struct timeval a, struct timeval b) +{ + register int us,s; + + us = a.tv_usec - b.tv_usec; + us /= 1000; + s = a.tv_sec - b.tv_sec; + s *= 1000; + return s+us; +} + +/* --------------------------------------------------------- */ + +/* calculate and output results and exit */ + +void output_results() +{ + int timetaken; + + gettimeofday(&endtime,0); + timetaken = timedif(endtime, start); + + printf("\n---\n"); + printf("Server: %s\n", server_name); + printf("Document Length: %d\n", doclen); + printf("Concurency Level: %d\n", concurrency); + printf("Time taken for tests: %d.%03d seconds\n", + timetaken/1000, timetaken%1000); + printf("Complete requests: %d\n", done); + printf("Failed requests: %d\n", bad); + if(bad) printf(" (Connect: %d, Length: %d, Exceptions: %d)\n", + err_conn, err_length, err_except); + if(keepalive) printf("Keep-Alive requests: %d\n", doneka); + printf("Bytes transfered: %d\n", totalread); + printf("HTML transfered: %d\n", totalbread); + + /* avoid divide by zero */ + if(timetaken) { + printf("Requests per seconds: %.2f\n", 1000*(float)(done)/timetaken); + printf("Transfer rate: %.2f kb/s\n", + (float)(totalread)/timetaken); + } + + { + /* work out connection times */ + int i; + int totalcon=0, total=0; + int mincon=9999999, mintot=999999; + int maxcon=0, maxtot=0; + + for(i=0; iread = 0; + c->bread = 0; + c->keepalive = 0; + c->cbx = 0; + c->gotheader = 0; + + c->fd = socket(AF_INET, SOCK_STREAM, 0); + if(c->fd<0) err("socket"); + + nonblock(c->fd); + gettimeofday(&c->start,0); + + if(connect(c->fd, (struct sockaddr *) &server, sizeof(server))<0) { + if(errno==EINPROGRESS) { + c->state = STATE_CONNECTING; + FD_SET(c->fd, &writebits); + return; + } + else { + close(c->fd); + err_conn++; + if(bad++>10) { + printf("\nTest aborted after 10 failures\n\n"); + exit(1); + } + start_connect(c); + } + } + + /* connected first time */ + write_request(c); +} + +/* --------------------------------------------------------- */ + +/* close down connection and save stats */ + +void close_connection(struct connection *c) +{ + if(c->read == 0 && c->keepalive) { + /* server has legitiamately shut down an idle keep alive request */ + good--; /* connection never happend */ + } + else { + if(good==1) { + /* first time here */ + doclen = c->bread; + } else if (c->bread!=doclen) { + bad++; + err_length++; + } + + /* save out time */ + if(done < requests) { + struct data s; + gettimeofday(&c->done,0); + s.read = c->read; + s.ctime = timedif(c->connect, c->start); + s.time = timedif(c->done, c->start); + stats[done++] = s; + } + } + + close(c->fd); + FD_CLR(c->fd, &readbits); + FD_CLR(c->fd, &writebits); + + /* connect again */ + start_connect(c); + return; +} + +/* --------------------------------------------------------- */ + +/* read data from connection */ + +void read_connection(struct connection *c) +{ + int r; + + r=read(c->fd,buffer,sizeof(buffer)); + if(r==0 || (r<0 && errno!=EAGAIN)) { + good++; + close_connection(c); + return; + } + + if(r<0 && errno==EAGAIN) return; + + c->read += r; + totalread += r; + + if(!c->gotheader) { + char *s; + int l=4; + int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator */ + int tocopy = (spacecbuff+c->cbx, buffer, space); + c->cbx += tocopy; space -= tocopy; + c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */ + s = strstr(c->cbuff, "\r\n\r\n"); + /* this next line is so that we talk to NCSA 1.5 which blatantly breaks + the http specifaction */ + if(!s) { s = strstr(c->cbuff,"\n\n"); l=2; } + + if(!s) { + /* read rest next time */ + if(space) + return; + else { + /* header is in invalid or too big - close connection */ + close(c->fd); + if(bad++>10) { + printf("\nTest aborted after 10 failures\n\n"); + exit(1); + } + FD_CLR(c->fd, &writebits); + start_connect(c); + } + } + else { + /* have full header */ + if(!good) { + /* this is first time, extract some interesting info */ + char *p, *q; + p = strstr(c->cbuff, "Server:"); + q = server_name; + if(p) { p+=8; while(*p>32) *q++ = *p++; } + *q = 0; + } + + c->gotheader = 1; + *s = 0; /* terminate at end of header */ + if(keepalive && + (strstr(c->cbuff, "Keep-Alive") + || strstr(c->cbuff, "keep-alive"))) /* for benefit of MSIIS */ + { + char *cl; + cl = strstr(c->cbuff, "Content-Length:"); + /* for cacky servers like NCSA which break the spec and send a + lower case 'l' */ + if(!cl) cl = strstr(c->cbuff, "Content-length:"); + if(cl) { + c->keepalive=1; + c->length = atoi(cl+16); + } + } + c->bread += c->cbx - (s+l-c->cbuff) + r-tocopy; + totalbread += c->bread; + } + } + else { + /* outside header, everything we have read is entity body */ + c->bread += r; + totalbread += r; + } + + if(c->keepalive && (c->bread >= c->length)) { + /* finished a keep-alive connection */ + good++; doneka++; + /* save out time */ + if(good==1) { + /* first time here */ + doclen = c->bread; + } else if(c->bread!=doclen) { bad++; err_length++; } + if(done < requests) { + struct data s; + gettimeofday(&c->done,0); + s.read = c->read; + s.ctime = timedif(c->connect, c->start); + s.time = timedif(c->done, c->start); + stats[done++] = s; + } + c->keepalive = 0; c->length = 0; c->gotheader=0; c->cbx = 0; + c->read = c->bread = 0; + write_request(c); + c->start = c->connect; /* zero connect time with keep-alive */ + } +} + +/* --------------------------------------------------------- */ + +/* run the tests */ + +int test() +{ + struct timeval timeout, now; + fd_set sel_read, sel_except, sel_write; + int i; + + { + /* get server information */ + struct hostent *he; + he = gethostbyname(machine); + if (!he) err("gethostbyname"); + server.sin_family = he->h_addrtype; + server.sin_port = htons(port); + server.sin_addr.s_addr = ((unsigned long *)(he->h_addr_list[0]))[0]; + } + + con = malloc(concurrency*sizeof(struct connection)); + memset(con,0,concurrency*sizeof(struct connection)); + + stats = malloc(requests * sizeof(struct data)); + + FD_ZERO(&readbits); + FD_ZERO(&writebits); + + /* setup request */ + sprintf(request,"GET %s HTTP/1.0\r\nUser-Agent: ZeusBench/1.0\r\n" + "%sHost: %s\r\nAccept: */*\r\n\r\n", file, + keepalive?"Connection: Keep-Alive\r\n":"", machine ); + + reqlen = strlen(request); + + /* ok - lets start */ + gettimeofday(&start,0); + + /* initialise lots of requests */ + for(i=0; i (tlimit*1000)) { + requests=done; /* so stats are correct */ + output_results(); + } + + /* Timeout of 30 seconds. */ + timeout.tv_sec=30; timeout.tv_usec=0; + n=select(256, &sel_read, &sel_write, &sel_except, &timeout); + if(!n) { + printf("\nServer timed out\n\n"); + exit(1); + } + if(n<1) err("select"); + + for(i=0; i=requests) output_results(); + } + return 0; +} + +/* ------------------------------------------------------- */ + +/* display usage information */ + +void usage(char *progname) { + printf("\nZeusBench v1.0\n\n"); + printf("Usage: %s [-k] [-n requests | -t timelimit (sec)]" + "\n\t\t[-c concurrency] [-p port] \n",progname); + printf("Filename should start with a '/' e.g. /index.html\n\n"); + exit(EINVAL); +} + +/* ------------------------------------------------------- */ + +/* sort out command-line args and call test */ + +int main(int argc, char **argv) { + int c; + if (argc < 3) usage(argv[0]); + + machine = argv[1]; + file = argv[2]; + optind = 3; + while ((c = getopt(argc,argv,"p:n:c:d:t:d:k"))>0) { + switch(c) { + case 'd': + break; + case 'n': + requests = atoi(optarg); + if(!requests) { + printf("Invalid number of requests\n"); + exit(1); + } + break; + case 'k': + keepalive=1; + break; + case 'c': + concurrency = atoi(optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 't': + tlimit = atoi(optarg); + requests = MAX_REQUESTS; /* need to size data array on something */ + break; + default: + usage(argv[0]); + break; + } + } + test(); + return 0; +} + + + + + + -- GitLab