? out ? apexit.patch ? arctic.patch ? timeouts.patch ? modules/php3 Index: include/http_core.h =================================================================== RCS file: /export/home/cvs/apache-1.3/src/include/http_core.h,v retrieving revision 1.47 diff -u -r1.47 http_core.h --- http_core.h 1998/08/10 04:16:13 1.47 +++ http_core.h 1998/08/26 23:32:10 @@ -83,6 +83,7 @@ #define OPT_INCNOEXEC 32 #define OPT_SYM_OWNER 64 #define OPT_MULTI 128 +#define OPT_SYM_GROUP 256 #define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS|OPT_EXECCGI) /* options for get_remote_host() */ @@ -165,7 +166,7 @@ /* Per-directory configuration */ -typedef unsigned char allow_options_t; +typedef unsigned short allow_options_t; typedef unsigned char overrides_t; typedef struct { Index: include/httpd.h =================================================================== RCS file: /export/home/cvs/apache-1.3/src/include/httpd.h,v retrieving revision 1.238 diff -u -r1.238 httpd.h --- httpd.h 1998/08/16 20:51:54 1.238 +++ httpd.h 1998/08/26 23:32:10 @@ -1042,6 +1042,14 @@ #define OPTIMIZE_TIMEOUTS #endif +#ifdef SHARED_TIME +#ifndef OPTIMIZE_TIMEOUTS +# error "you need OPTIMIZE_TIMEOUTS for SHARED_TIME" +#endif +extern time_t ap_shared_time(time_t *); +#define time(x) ap_shared_time(x) +#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 Index: include/scoreboard.h =================================================================== RCS file: /export/home/cvs/apache-1.3/src/include/scoreboard.h,v retrieving revision 1.41 diff -u -r1.41 scoreboard.h --- scoreboard.h 1998/08/11 00:09:43 1.41 +++ scoreboard.h 1998/08/26 23:32:10 @@ -136,6 +136,9 @@ typedef struct { int exit_generation; /* Set by the main process if a graceful restart is required */ +#ifdef SHARED_TIME + time_t right_now; /* the current time */ +#endif } global_score; /* stuff which the parent generally writes and the children rarely read */ Index: main/buff.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/buff.c,v retrieving revision 1.81 diff -u -r1.81 buff.c --- buff.c 1998/07/04 18:22:11 1.81 +++ buff.c 1998/08/26 23:32:10 @@ -967,7 +967,9 @@ * 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. + * XXX: When used on a non-blocking fd it may block until it can write. + * (This is somewhat easier to do than it is to remember all the appropriate + * state and return to the caller.) * * Deals with calling doerror and setting bytes_sent. */ @@ -985,6 +987,19 @@ doerror(fb, B_WR); return -1; } + if (errno == EAGAIN) { + /* hack hack: it's non-blocking, block until it's ready for + * another write. + */ + fd_set fds; + int rv; + + do { + FD_ZERO(&fds); + FD_SET(fb->fd, &fds); + rv = ap_select(fb->fd + 1, NULL, &fds, NULL, NULL); + } while (rv == -1 && errno == EINTR); + } } else { nbyte -= i; @@ -1075,7 +1090,6 @@ * 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) Index: main/http_core.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/http_core.c,v retrieving revision 1.224 diff -u -r1.224 http_core.c --- http_core.c 1998/08/11 15:37:52 1.224 +++ http_core.c 1998/08/26 23:32:10 @@ -70,6 +70,8 @@ #include "scoreboard.h" #include "fnmatch.h" +#undef USE_MMAP_FILES + #ifdef USE_MMAP_FILES #include @@ -965,6 +967,9 @@ else if (!strcasecmp(w, "SymLinksIfOwnerMatch")) { opt = OPT_SYM_OWNER; } + else if(!strcasecmp(w,"SymLinksIfGroupMatch")) { + opt = OPT_SYM_GROUP; + } else if (!strcasecmp(w, "execCGI")) { opt = OPT_EXECCGI; } @@ -2758,7 +2763,32 @@ if (d->content_md5 & 1) { ap_table_setn(r->headers_out, "Content-MD5", - ap_md5digest(r->pool, f)); + ap_md5digest(r->pool, f)); + } + /* Shameless hack: if the file to be sent is image/gif and + * gif89-expires-hack is set then remove the Expires header. This is + * required because of a bug in Mozilla versions up through at least 4 + * which causes it to re-request the animation every loop. You + * probably want this in your config: + * + * BrowserMatch Mozilla/[0-4]\. gif89-expires-hack + * + * -djg + */ + if (r->content_type + && strcasecmp (r->content_type, "image/gif") == 0 + && r->finfo.st_size > 6 + && ap_table_get (r->subprocess_env, "gif89-expires-hack")) { +#define GIF_HEADER_LEN (6) + char gif_header[ GIF_HEADER_LEN ]; + + if (fread (gif_header, 1, GIF_HEADER_LEN, f) == GIF_HEADER_LEN + && memcmp (gif_header, "GIF89a", GIF_HEADER_LEN) == 0) { + ap_table_unset (r->headers_out, "Expires"); + ap_table_unset (r->headers_out, "Cache-Control"); + } + fseek (f, 0L, SEEK_SET); +#undef GIF_HEADER_LEN } rangestatus = ap_set_byterange(r); @@ -2806,6 +2836,15 @@ ap_MD5Update(&context, (void *)mm, r->finfo.st_size); ap_table_setn(r->headers_out, "Content-MD5", ap_md5contextTo64(r->pool, &context)); + } + /* Shameless gif89-expires-hack, see above */ + if (r->content_type + && strcasecmp (r->content_type, "image/gif") == 0 + && table_get (r->subprocess_env, "gif89-expires-hack") + && r->finfo.st_size > 6 + && memcmp (mm, "GIF89a", 6) == 0) { + table_unset (r->headers_out, "Expires"); + table_unset (r->headers_out, "Cache-Control"); } rangestatus = ap_set_byterange(r); Index: main/http_log.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/http_log.c,v retrieving revision 1.64 diff -u -r1.64 http_log.c --- http_log.c 1998/08/10 16:17:54 1.64 +++ http_log.c 1998/08/26 23:32:11 @@ -69,6 +69,7 @@ #include "http_core.h" #include "http_log.h" #include "http_main.h" +#include "http_conf_globals.h" #include @@ -510,6 +511,7 @@ static int piped_log_spawn (piped_log *pl) { int pid; + int pgrp; ap_block_alarms(); pid = fork(); @@ -520,6 +522,36 @@ * XXX: close all the relevant stuff, but hey, it could be broken. */ RAISE_SIGSTOP(PIPED_LOG_SPAWN); /* we're now in the child */ + /* cd ServerRoot so that it's easy to construct portable logger + * lines */ + if (chdir(ap_server_root) == -1) { + ap_log_error(APLOG_MARK, APLOG_CRIT, NULL, + "logger: unable to chdir(%s)", ap_server_root); + exit (1); + } +#ifndef NO_SETSID + if ((pgrp = setsid()) == -1) { + ap_log_error(APLOG_MARK, APLOG_CRIT, NULL, "logger: setsid failed"); + exit(1); + } +#elif defined(NEXT) || defined(NEWSOS) + if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) { + ap_log_error(APLOG_MARK, APLOG_CRIT, NULL, + "logger: setpgrp or getpgrp failed"); + 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) { + ap_log_error(APLOG_MARK, APLOG_CRIT, NULL, "logger: setpgrp failed"); + exit(1); + } +#endif close (STDIN_FILENO); dup2 (pl->fds[0], STDIN_FILENO); @@ -549,6 +581,9 @@ { piped_log *pl = data; + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, NULL, + "piped_log_maintenance reason = %d, status = %d", reason, + status); switch (reason) { case OC_REASON_DEATH: case OC_REASON_LOST: Index: main/http_main.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/http_main.c,v retrieving revision 1.387 diff -u -r1.387 http_main.c --- http_main.c 1998/08/13 01:55:06 1.387 +++ http_main.c 1998/08/26 23:32:11 @@ -275,6 +275,7 @@ */ listen_rec *ap_listeners; static listen_rec *head_listener; +static listen_rec *permanent_listeners; API_VAR_EXPORT char ap_server_root[MAX_STRING_LEN]; char ap_server_confname[MAX_STRING_LEN]; @@ -1224,6 +1225,20 @@ timeout_name = NULL; } +#ifdef SHARED_TIME +#undef time +time_t ap_shared_time(time_t *t) +{ + time_t res; + + if (child_timeouts || ap_scoreboard_image == NULL) { + return time(0); + } + res = ap_scoreboard_image->global.right_now; + if (t) *t = res; + return res; +} +#endif /* * More machine-dependent networking gooo... on some systems, @@ -3061,6 +3076,9 @@ { listen_rec *lr; + if (permanent_listeners) { + return; + } ap_assert(old_listeners == NULL); if (ap_listeners == NULL) { return; @@ -3116,6 +3134,20 @@ listen_rec *lr; int fd; + if (permanent_listeners) { + lr = permanent_listeners; + ap_listeners = lr; + head_listener = lr; + do { + if (lr->next == NULL) { + /* first time through, create the loop */ + lr->next = permanent_listeners; + return; + } + lr = lr->next; + } while (lr != permanent_listeners); + return; + } listenmaxfd = -1; FD_ZERO(&listenfds); lr = ap_listeners; @@ -3921,6 +3953,10 @@ last_non_dead = -1; total_non_dead = 0; +#ifdef SHARED_TIME + ap_scoreboard_image->global.right_now = now; +#endif + ap_sync_scoreboard_image(); for (i = 0; i < ap_daemons_limit; ++i) { int status; @@ -3982,6 +4018,9 @@ * shut down gracefully, in case it happened to pick up a request * while we were counting */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, + "server has %d children, %d are idle, killing one", + total_non_dead, idle_count); kill(ap_scoreboard_image->parent[to_kill].pid, SIGUSR1); idle_spawn_rate = 1; } @@ -4008,6 +4047,9 @@ "%d total children", idle_spawn_rate, idle_count, total_non_dead); } + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, + "server has %d children, %d are idle, spawning %d", + total_non_dead, idle_count, free_length); for (i = 0; i < free_length; ++i) { make_child(server_conf, free_slots[i], now); } @@ -4316,6 +4358,58 @@ void STANDALONE_MAIN(int argc, char **argv); #endif /* STANDALONE_MAIN */ +static void pre_opened_socket(const char *arg) +{ + int fd; + struct sockaddr_in local_addr; + listen_rec *lr; + NET_SIZE_T clen; + + fd = atoi(arg); + + clen = sizeof(local_addr); + if (getsockname(fd, (struct sockaddr *)&local_addr, &clen) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, NULL, + "error parsing arg -p '%s', skipping", arg); + return; + } + + if (local_addr.sin_family != AF_INET) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "arg -p %d is not an AF_INET socket, skipping", fd); + return; + } + +#ifdef LINUX + /* work around linux 2.0.x bug */ + if (local_addr.sin_addr.s_addr == htonl(0x7f000001)) { + local_addr.sin_addr.s_addr = 0; + } +#endif + + /* We don't want these descriptors to be passed down to the + * grandchildren. Since we're not going to manage them in pools + * we have to set the close-on-exec flag. + */ + if (fcntl(fd, F_SETFD, 1)) { + ap_log_error(APLOG_MARK, APLOG_ERR, NULL, + "arg -p %d, can't fcntl(%d, F_SETFD, 1), skipping", fd, fd); + return; + } + + lr = malloc(sizeof(listen_rec)); + if (lr == NULL) { + ap_log_error(APLOG_MARK, APLOG_CRIT, NULL, + "out of memory allocating permanent_listener"); + exit(1); + } + lr->local_addr = local_addr; + lr->fd = fd; + lr->used = 0; + lr->next = permanent_listeners; + permanent_listeners = lr; +} + extern char *optarg; extern int optind; @@ -4353,6 +4447,7 @@ #ifdef DEBUG_SIGSTOP "Z:" #endif + "p:" )) != -1) { char **new; switch (c) { @@ -4389,6 +4484,9 @@ case 'l': ap_show_modules(); exit(0); + case 'p': + pre_opened_socket(optarg); + break; case 'X': ++one_process; /* Weird debugging mode. */ break; Index: main/http_request.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/main/http_request.c,v retrieving revision 1.130 diff -u -r1.130 http_request.c --- http_request.c 1998/08/11 00:09:46 1.130 +++ http_request.c 1998/08/26 23:32:12 @@ -158,13 +158,19 @@ /* OK, it's a symlink. May still be OK with OPT_SYM_OWNER */ - if (!(opts & OPT_SYM_OWNER)) + if (!(opts & (OPT_SYM_OWNER|OPT_SYM_GROUP))) return HTTP_FORBIDDEN; if (stat(d, &fi) < 0) return HTTP_FORBIDDEN; - return (fi.st_uid == lfi.st_uid) ? OK : HTTP_FORBIDDEN; + if ((opts & OPT_SYM_OWNER) && fi.st_uid == lfi.st_uid) + return OK; + + if ((opts & OPT_SYM_GROUP) && fi.st_gid == lfi.st_gid) + return OK; + + return HTTP_FORBIDDEN; #endif } Index: modules/standard/mod_autoindex.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_autoindex.c,v retrieving revision 1.87 diff -u -r1.87 mod_autoindex.c --- mod_autoindex.c 1998/08/06 17:30:56 1.87 +++ mod_autoindex.c 1998/08/26 23:32:13 @@ -865,15 +865,29 @@ autoindex_config_rec * d, request_rec *r, int autoindex_opts, char keyid, char direction) { - int x, len; + int x; char *name = r->uri; char *tp; int static_columns = (autoindex_opts & SUPPRESS_COLSORT); pool *scratch = ap_make_sub_pool(r->pool); + int name_width; + char *name_scratch; if (name[0] == '\0') name = "/"; + name_width = 23; + for (x = 0; x < n; x++) { + int t = strlen(ar[x]->name); + if (t > name_width) { + name_width = t; + } + } + ++name_width; + name_scratch = ap_palloc(r->pool, name_width + 1); + memset(name_scratch, ' ', name_width); + name_scratch[name_width] = 0; + if (autoindex_opts & FANCY_INDEXING) { ap_rputs("
", r);
 	if ((tp = find_default_icon(d, "^^BLANKICON^^"))) {
@@ -891,7 +905,7 @@
 	    ap_rputs("> ", r);
 	}
         emit_link(r, "Name", K_NAME, keyid, direction, static_columns);
-	ap_rputs("                   ", r);
+	ap_rputs(name_scratch + 4, r);
 	if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
             emit_link(r, "Last modified", K_LAST_MOD, keyid, direction,
                       static_columns);
@@ -912,7 +926,8 @@
     }
 
     for (x = 0; x < n; x++) {
-	char *anchor = NULL, *t = NULL, *t2 = NULL;
+	char *anchor, *t, *t2;
+	char *pad;
 
 	ap_clear_pool(scratch);
 
@@ -922,40 +937,21 @@
 	    if (t[0] == '\0') {
 		t = "/";
 	    }
-	    anchor = ap_pstrcat(scratch, "", NULL);
-	    t2 = "Parent Directory       ";
+	       /* 1234567890123456 */
+	    t2 = "Parent Directory";
+	    pad = name_scratch + 16;
+	    anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
 	}
 	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, "", NULL);
-	    }
-	    else {
-		char buff[24] = "                       ";
-		t2 = ap_escape_html(scratch, t);
-		buff[23 - len] = '\0';
-		t2 = ap_pstrcat(scratch, t2, "", buff, NULL);
-	    }
-	    anchor = ap_pstrcat(scratch, "", NULL);
+	    pad = name_scratch + strlen(t);
+	    t2 = ap_escape_html(scratch, t);
+	    anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
 	}
 
 	if (autoindex_opts & FANCY_INDEXING) {
 	    if (autoindex_opts & ICONS_ARE_LINKS) {
-		ap_rputs(anchor, r);
+		ap_rvputs(r, "", NULL);
 	    }
 	    if ((ar[x]->icon) || d->default_icon) {
 		ap_rvputs(r, "", r);
 	    }
 
-	    ap_rvputs(r, " ", anchor, t2, NULL);
+	    ap_rvputs(r, " ", t2, "", pad, NULL);
 	    if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
 		if (ar[x]->lm != -1) {
 		    char time_str[MAX_STRING_LEN];
@@ -998,7 +994,7 @@
 	    }
 	}
 	else {
-	    ap_rvputs(r, "
  • ", anchor, " ", t2, NULL); + ap_rvputs(r, "
  • ", t2, "", pad, NULL); } ap_rputc('\n', r); } Index: modules/standard/mod_include.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_include.c,v retrieving revision 1.102 diff -u -r1.102 mod_include.c --- mod_include.c 1998/08/09 17:36:29 1.102 +++ mod_include.c 1998/08/26 23:32:13 @@ -94,6 +94,10 @@ #include "util_script.h" #endif +#ifndef WASTE_OF_TIME +#define ap_chdir_file(x) do {} while(0) +#endif + #define STARTING_SEQUENCE "" #define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]" @@ -113,32 +117,57 @@ /* ------------------------ Environment function -------------------------- */ -/* XXX: could use ap_table_overlap here */ -static void add_include_vars(request_rec *r, char *timefmt) +static const char INCLUDE_TIME_FORMAT[] = "INCLUDE_TIME_FORMAT"; + +static const char *get_envvar(request_rec *r, const char *name) { + const char *res; + table *e; + + e = r->subprocess_env; + res = ap_table_get(e, name); + if (res) { + return res; + } + if (!strcmp(name, "LAST_MODIFIED")) { + res = ap_ht_time(r->pool, r->finfo.st_mtime, + ap_table_get(e, INCLUDE_TIME_FORMAT), 0); + } + else if (!strcmp(name, "DATE_LOCAL")) { + res = ap_ht_time(r->pool, r->request_time, + ap_table_get(e, INCLUDE_TIME_FORMAT), 0); + } + else if (!strcmp(name, "DATE_GMT")) { + res = ap_ht_time(r->pool, r->request_time, + ap_table_get(e, INCLUDE_TIME_FORMAT), 1); + } #ifndef WIN32 - struct passwd *pw; + else if (!strcmp(name, "USER_NAME")) { + struct passwd *pw; + pw = getpwuid(r->finfo.st_uid); + if (pw) { + res = ap_pstrdup(r->pool, pw->pw_name); + } + else { + res = ap_psprintf(r->pool, "user#%lu", + (unsigned long) r->finfo.st_uid); + } + } #endif /* ndef WIN32 */ + if (res) { + ap_table_set(e, name, res); + } + return res; +} + +static void add_include_vars(request_rec *r) +{ 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, INCLUDE_TIME_FORMAT, DEFAULT_TIME_FORMAT); 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); @@ -894,7 +923,7 @@ return 1; } if (!strcmp(tag, "var")) { - const char *val = ap_table_get(r->subprocess_env, tag_val); + const char *val = get_envvar(r, tag_val); if (val) { ap_rputs(val, r); @@ -951,16 +980,26 @@ } #endif + +static void set_timefmt(request_rec *r, char *value) +{ + table *e = r->subprocess_env; + + ap_table_setn(e, INCLUDE_TIME_FORMAT, ap_pstrdup(r->pool, value)); + ap_table_unset(e, "DATE_LOCAL"); + ap_table_unset(e, "DATE_GMT"); + ap_table_unset(e, "LAST_MODIFIED"); +} + + /* 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) +static int handle_config(FILE *in, request_rec *r, char *error, 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))) { @@ -970,13 +1009,8 @@ 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)); + parse_string(r, tag_val, parsed_string, MAX_STRING_LEN, 0); + set_timefmt(r, parsed_string); } else if (!strcmp(tag, "sizefmt")) { parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); @@ -1106,7 +1140,7 @@ } } -static int handle_flastmod(FILE *in, request_rec *r, const char *error, const char *tf) +static int handle_flastmod(FILE *in, request_rec *r, const char *error) { char tag[MAX_STRING_LEN]; char *tag_val; @@ -1123,7 +1157,8 @@ 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); + ap_rputs(ap_ht_time(r->pool, finfo.st_mtime, + ap_table_get(r->subprocess_env, INCLUDE_TIME_FORMAT), 0), r); } } } @@ -2052,7 +2087,12 @@ 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)); + if (strcmp(var, INCLUDE_TIME_FORMAT)) { + ap_table_setn(r->subprocess_env, var, ap_pstrdup(r->pool, parsed_string)); + } + else { + set_timefmt(r, parsed_string); + } } else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, @@ -2067,14 +2107,21 @@ { char tag[MAX_STRING_LEN]; char *tag_val; - array_header *arr = ap_table_elts(r->subprocess_env); - table_entry *elts = (table_entry *) arr->elts; + array_header *arr; + table_entry *elts; int i; if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { return 1; } else if (!strcmp(tag, "done")) { + /* force these to be defined */ + get_envvar(r, "DATE_LOCAL"); + get_envvar(r, "DATE_GMT"); + get_envvar(r, "LAST_MODIFIED"); + get_envvar(r, "USER_NAME"); + arr = ap_table_elts(r->subprocess_env); + elts = (table_entry *) arr->elts; for (i = 0; i < arr->nelts; ++i) { ap_rvputs(r, elts[i].key, "=", elts[i].val, "\n", NULL); } @@ -2098,7 +2145,6 @@ 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; @@ -2106,7 +2152,6 @@ 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 */ @@ -2187,7 +2232,7 @@ } } else if (!strcmp(directive, "config")) { - ret = handle_config(f, r, error, timefmt, &sizefmt); + ret = handle_config(f, r, error, &sizefmt); } else if (!strcmp(directive, "set")) { ret = handle_set(f, r, error); @@ -2202,7 +2247,7 @@ ret = handle_fsize(f, r, error, sizefmt); } else if (!strcmp(directive, "flastmod")) { - ret = handle_flastmod(f, r, error, timefmt); + ret = handle_flastmod(f, r, error); } else if (!strcmp(directive, "printenv")) { ret = handle_printenv(f, r, error); @@ -2347,7 +2392,7 @@ * environment */ ap_add_common_vars(r); ap_add_cgi_vars(r); - add_include_vars(r, DEFAULT_TIME_FORMAT); + add_include_vars(r); } /* 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 Index: modules/standard/mod_rewrite.c =================================================================== RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_rewrite.c,v retrieving revision 1.129 diff -u -r1.129 mod_rewrite.c --- mod_rewrite.c 1998/08/13 01:55:15 1.129 +++ mod_rewrite.c 1998/08/26 23:32:14 @@ -1332,7 +1332,7 @@ * 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))) { + if (!(ap_allow_options(r) & (OPT_SYM_LINKS | OPT_SYM_OWNER | OPT_SYM_GROUP))) { /* FollowSymLinks is mandatory! */ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Options FollowSymLinks or SymLinksIfOwnerMatch is off " Index: support/.cvsignore =================================================================== RCS file: /export/home/cvs/apache-1.3/src/support/.cvsignore,v retrieving revision 1.6 diff -u -r1.6 .cvsignore --- .cvsignore 1998/03/31 15:59:56 1.6 +++ .cvsignore 1998/08/26 23:32:19 @@ -1,3 +1,4 @@ +listenwrap Makefile rotatelogs htpasswd Index: support/Makefile.tmpl =================================================================== RCS file: /export/home/cvs/apache-1.3/src/support/Makefile.tmpl,v retrieving revision 1.25 diff -u -r1.25 Makefile.tmpl --- Makefile.tmpl 1998/08/03 08:44:08 1.25 +++ Makefile.tmpl 1998/08/26 23:32:19 @@ -25,6 +25,9 @@ logresolve: logresolve.o $(CC) $(CFLAGS) logresolve.o -o logresolve $(LDFLAGS) $(LIBS) +listenwrap: listenwrap.o + $(CC) $(INCLUDES) $(CFLAGS) listenwrap.o -o listenwrap $(LDFLAGS) $(LIBS) + ab: ab.o $(CC) $(CFLAGS) ab.o -o ab $(LDFLAGS) $(LIBS) Index: support/listenwrap.c =================================================================== RCS file: listenwrap.c diff -N listenwrap.c --- /dev/null Wed Aug 26 16:31:53 1998 +++ listenwrap.c Wed Aug 26 16:32:19 1998 @@ -0,0 +1,148 @@ +#include "httpd.h" + +#define PORT 80 +#define SEND_BUFFER_SIZE 16384 +#define LISTEN_BACKLOG 511 +#define HTTP_USER 511 +#define HTTP_GROUP 511 +#define HTTPD_PATH "/home/www/bin/httpd" + +/* stolen from http_main.c ... should be turned into a lib function I guess */ + +#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) { + perror("setsockopt(TCP_NODELAY)"); + } +} + +#else +#define sock_disable_nagle(s) /* NOOP */ +#endif + +#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) { + perror("setsockopt(SO_LINGER)"); + /* not a fatal error */ + } +} + +#else +#define sock_enable_linger(s) /* NOOP */ +#endif /* USE_SO_LINGER */ + +static int make_sock(const struct sockaddr_in *local_addr) +{ + int s; + int one = 1; + + if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { + perror("socket"); + exit(1); + } + + if (bind(s, (struct sockaddr *) local_addr, + sizeof(struct sockaddr_in)) == -1) { + perror("bind"); + exit(1); + } + + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &one, + sizeof(int)) < 0) { + perror("setsockopt(SO_REUSEADDR)"); + exit(1); + } + one = 1; + if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, + sizeof(int)) < 0) { + perror("setsockopt(SO_KEEPALIVE"); + exit(1); + } + + sock_disable_nagle(s); + sock_enable_linger(s); + + one = SEND_BUFFER_SIZE; + if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, + (char *) &one, sizeof(int)) < 0) { + perror("setsockopt(SO_SNDBUF)"); + /* not a fatal error */ + } + + if (listen(s, LISTEN_BACKLOG) == -1) { + perror("listen"); + exit(1); + } + + return s; +} + +void main(int argc, char **argv) +{ + struct sockaddr_in local_addr; + int s; + char **new_argv; + char *new_env[] = { + "SHELL=/bin/sh", + "PATH=/usr/local/bin:/usr/bin:/bin", + NULL + }; + char buf[512]; + + local_addr.sin_family = AF_INET; + local_addr.sin_addr.s_addr = htonl(INADDR_ANY); + local_addr.sin_port = htons(PORT); + + s = make_sock(&local_addr); + + new_argv = malloc(sizeof(char *) * (argc + 3)); + new_argv[0] = HTTPD_PATH; + new_argv[1] = "-p"; + sprintf(buf, "%d", s); + new_argv[2] = buf; + memcpy(new_argv + 3, argv + 1, sizeof(char *) * (argc - 1)); + new_argv[argc+2] = NULL; + + if (setgroups(0, NULL) == -1) { + perror("setgroups"); + exit(1); + } + if (setgid(HTTP_GROUP) == -1) { + perror("setgid"); + exit(1); + } + if (setuid(HTTP_USER) == -1) { + perror("setuid"); + exit(1); + } + execve(HTTPD_PATH, new_argv, new_env); + perror("execve"); + exit(1); +}