diff -urN boa-0.93.17.2/src/.depend boa-0.93.17.3/src/.depend
--- boa-0.93.17.2/src/.depend	Wed Jun 30 13:44:23 1999
+++ boa-0.93.17.3/src/.depend	Fri Aug  6 22:42:41 1999
@@ -1,7 +1,8 @@
 alias.o: alias.c boa.h compat.h config.h defines.h globals.h
 boa.o: boa.c boa.h compat.h config.h defines.h globals.h
 cgi.o: cgi.c boa.h compat.h config.h defines.h globals.h
-config.o: config.c boa.h compat.h config.h defines.h globals.h
+config.o: config.c y.tab.h parse.h boa.h compat.h config.h defines.h \
+ globals.h
 get.o: get.c boa.h compat.h config.h defines.h globals.h
 hash.o: hash.c boa.h compat.h config.h defines.h globals.h
 log.o: log.c boa.h compat.h config.h defines.h globals.h
@@ -14,3 +15,6 @@
 cgi_header.o: cgi_header.c boa.h compat.h config.h defines.h globals.h
 pipe.o: pipe.c boa.h compat.h config.h defines.h globals.h
 mmap_cache.o: mmap_cache.c boa.h compat.h config.h defines.h globals.h
+sublog.o: sublog.c
+deeplink-stub.o: deeplink-stub.c boa.h compat.h config.h defines.h \
+ globals.h
diff -urN boa-0.93.17.2/src/Changelog boa-0.93.17.3/src/Changelog
--- boa-0.93.17.2/src/Changelog	Sun Jul 18 23:13:55 1999
+++ boa-0.93.17.3/src/Changelog	Fri Aug  6 22:23:39 1999
@@ -1,3 +1,11 @@
+** Changes from 0.93.17.2 to 0.93.17.3
+ * Put on-the-fly directories back in, stripped down from the 0.92 version
+ * Made ServerAdmin and ServerName default to "unknown", so if the
+   user doesn't define them the CGI environment doesn't get truncated
+ * Fixed argument order in Script* directives
+ * Added hooks and stubs for anti-deep-linking experiments
+ * Changed computation of SCRIPT_NAME for CGI programs
+
 ** Changes from 0.93.17.1 to 0.93.17.2
  * Added "Listen" directive for server bind address, as most recently
    suggested by David N. Welton <davidw@linuxcare.com>
diff -urN boa-0.93.17.2/src/Makefile.in boa-0.93.17.3/src/Makefile.in
--- boa-0.93.17.2/src/Makefile.in	Sat Jul 10 22:13:55 1999
+++ boa-0.93.17.3/src/Makefile.in	Fri Aug  6 22:28:28 1999
@@ -9,6 +9,8 @@
 
 # Add -DNO_DAEMON if you do not want the server to fork upon launch
 
+# Add -efence to LDFLAGS to link with ElectricFence
+# Add -pg to CFLAGS and LDFLAGS to get profiling output with gcc/gprof
 LDFLAGS = @LIBS@ -g
 CFLAGS = -O -Wall -g
 
@@ -21,7 +23,7 @@
 
 SOURCES = alias.c boa.c cgi.c config.c get.c hash.c log.c \
 	queue.c read.c request.c response.c signals.c util.c \
-	cgi_header.c pipe.c mmap_cache.c sublog.c
+	cgi_header.c pipe.c mmap_cache.c sublog.c deeplink-stub.c
 	
 OBJS = y.tab.o lex.yy.o ${SOURCES:.c=.o} timestamp.o
 
diff -urN boa-0.93.17.2/src/alias.c boa-0.93.17.3/src/alias.c
--- boa-0.93.17.2/src/alias.c	Sun Jul 18 23:27:01 1999
+++ boa-0.93.17.3/src/alias.c	Fri Aug  6 22:07:28 1999
@@ -46,6 +46,7 @@
 	while ((c = file[index++]) && c != '/')
 		hash += (unsigned int) c;
 
+	/* fprintf(stderr,"hash of %s is %d\n",file,hash); */
 	return hash % ALIAS_HASHTABLE_SIZE;
 }
 
@@ -313,7 +314,9 @@
 
 	/* there used to be some ip stuff in here */
 
-	req->script_name = strdup(pathname + current1->fake_len - 1);
+	/* XXX used to strip current1->fake_len - 1 bytes from front of
+	   pathname; why? */
+	req->script_name = strdup(pathname);
 	return 1;
 }
 
diff -urN boa-0.93.17.2/src/boa.c boa-0.93.17.3/src/boa.c
--- boa-0.93.17.2/src/boa.c	Sat Jul 17 23:08:26 1999
+++ boa-0.93.17.3/src/boa.c	Sun Aug  1 21:35:14 1999
@@ -69,6 +69,7 @@
 	read_config_files();
 	open_logs();
 	create_common_env();
+	get_secret();
 
 	if ((server_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
 		die(NO_CREATE_SOCKET);
diff -urN boa-0.93.17.2/src/boa.h boa-0.93.17.3/src/boa.h
--- boa-0.93.17.2/src/boa.h	Sat Jul 10 22:45:46 1999
+++ boa-0.93.17.3/src/boa.h	Fri Aug  6 22:14:47 1999
@@ -192,4 +192,10 @@
 
 /* sublog.c */
 int open_gen_fd(char *spec);
+
+/* deeplink.c */
+void get_secret(void);
+int check_deeplink(request *req);
+void mangle(struct request *req);
+
 #endif
diff -urN boa-0.93.17.2/src/cgi.c boa-0.93.17.3/src/cgi.c
--- boa-0.93.17.2/src/cgi.c	Wed Jun 30 13:44:23 1999
+++ boa-0.93.17.3/src/cgi.c	Fri Aug  6 22:35:36 1999
@@ -122,6 +122,7 @@
 
 /*
  * Name: env_gen_extra
+ *       (and via a not-so-tricky #define, env_gen)
  * This routine calls malloc: please free the memory when you are done
  */
 char *env_gen_extra(const char *key, const char *value, int extra)
@@ -140,6 +141,7 @@
 		memcpy(result + extra + key_len + 1, value, value_len);
 		*(result + extra + key_len + value_len + 1) = '\0';
 	}
+	/* fprintf(stderr,"env_gen: %s\n",result); */
 	return result;
 }
 
diff -urN boa-0.93.17.2/src/config.c boa-0.93.17.3/src/config.c
--- boa-0.93.17.2/src/config.c	Sat Jul 17 22:54:07 1999
+++ boa-0.93.17.3/src/config.c	Fri Aug  6 22:20:00 1999
@@ -43,9 +43,9 @@
 int server_port;
 uid_t server_uid;
 gid_t server_gid;
-char *server_admin;
+char *server_admin="unknown";
 char *server_root;
-char *server_name;
+char *server_name="unknown";
 char *server_ip;
 int virtualhost;
 
@@ -54,6 +54,7 @@
 char *directory_index;
 char *default_type;
 char *dirmaker;
+char *cachedir;
 
 int ka_timeout;
 int ka_max;
@@ -105,6 +106,7 @@
 	{ "UserDir",          S1A, c_set_string,   &user_dir },
 	{ "DirectoryIndex",   S1A, c_set_string,   &directory_index },
 	{ "DirectoryMaker",   S1A, c_set_string,   &dirmaker },
+	{ "DirectoryCache",   S1A, c_set_string,   &cachedir },
 	{ "KeepAliveMax",     S1A, c_set_int,      &ka_max },
 	{ "KeepAliveTimeout", S1A, c_set_int,      &ka_timeout },
 	{ "MimeTypes",        S1A, c_set_string,   &mime_types },
@@ -200,7 +202,7 @@
 
 void c_add_alias (char *v1, char *v2, void *t)
 {
-	add_alias(v1, v2, *(int *)t);
+	add_alias(v2, v1, *(int *)t);
 }
 
 struct ccommand *lookup_keyword(char *c)
diff -urN boa-0.93.17.2/src/deeplink-stub.c boa-0.93.17.3/src/deeplink-stub.c
--- boa-0.93.17.2/src/deeplink-stub.c	Wed Dec 31 16:00:00 1969
+++ boa-0.93.17.3/src/deeplink-stub.c	Fri Aug  6 22:17:23 1999
@@ -0,0 +1,16 @@
+/*  Stubs for some experiments I'm doing.
+ *  If you're curious, and the test server happens to be up, check out
+ *    http://doolittle.faludi.com/~ldoolitt/linkgen/
+ */
+
+#include "boa.h"
+
+void get_secret(void) {
+}
+
+int check_deeplink(request *req) {
+	return 0;
+}
+
+void mangle(struct request *req) {
+}
diff -urN boa-0.93.17.2/src/defines.h boa-0.93.17.3/src/defines.h
--- boa-0.93.17.2/src/defines.h	Sat Jul 10 23:00:16 1999
+++ boa-0.93.17.3/src/defines.h	Fri Aug  6 22:17:57 1999
@@ -77,7 +77,7 @@
 #define COMMON_CGI_VARS				8
 
 #ifndef SERVER_VERSION
-#define SERVER_VERSION				"Boa/0.93.17.1"
+#define SERVER_VERSION				"Boa/0.93.17.3"
 #endif
 
 #define CGI_VERSION				"CGI/1.1"
diff -urN boa-0.93.17.2/src/get.c boa-0.93.17.3/src/get.c
--- boa-0.93.17.2/src/get.c	Wed Jun 30 13:44:23 1999
+++ boa-0.93.17.3/src/get.c	Fri Aug  6 22:14:37 1999
@@ -23,6 +23,10 @@
 #include "boa.h"
 #include <sys/mman.h>
 
+/* Local prototypes */
+int get_cachedir_file( request * req, struct stat *statbuf);
+int index_directory(request * req, char * dest_filename);
+
 /*
  * Name: init_get
  * Description: Initializes a non-script GET or HEAD request.
@@ -38,6 +42,10 @@
 	char buf[MAX_PATH_LENGTH];
 	struct stat statbuf;
 
+	if (check_deeplink(req)) {
+		send_r_forbidden(req);
+		return 0;
+	}
 	data_fd = open(req->pathname, O_RDONLY);
 
 	if (data_fd == -1) {		/* cannot open */
@@ -128,13 +136,19 @@
 	}
 
 	/* MAP_OPTIONS: see compat.h */
-	req->mmap_entry_var = find_mmap(data_fd,&statbuf);
-	if (req->mmap_entry_var == NULL) {
+	if (req->linkgen) {
+		req->data_mem = mmap(0, statbuf.st_size,
+		                PROT_READ | PROT_WRITE, MAP_OPTIONS, data_fd, 0);
+		mangle(req);
+	} else {
+		req->mmap_entry_var = find_mmap(data_fd,&statbuf);
+		if (req->mmap_entry_var) req->data_mem = req->mmap_entry_var->mmap;
+	}
+	if (req->data_mem == NULL) {
 	    send_r_error(req);
 	    close(data_fd);
 	    return 0;
 	}
-	req->data_mem = req->mmap_entry_var->mmap;
 	close(data_fd);				/* close data file */
 
 	if ((long) req->data_mem == -1) {
@@ -142,7 +156,7 @@
 		return 0;
 	}
 	send_r_request_ok(req);		/* All's well */
-	{							/* combine first part of file with headers */
+	{					/* combine first part of file with headers */
 		int bob;
 
 		bob = BUFFER_SIZE - req->buffer_end;
@@ -292,8 +306,130 @@
 
 	return (init_cgi(req) == 0 ? -1 : 0);
 	/* in this case, 0 means success */
+    }
+    if (cachedir) {
+	return get_cachedir_file(req, statbuf);
     } else { /* neither index.html nor autogenerate are allowed */
 	send_r_forbidden(req);
 	return -1;					/* nothing worked */
     }
-}
\ No newline at end of file
+}
+
+int get_cachedir_file( request * req, struct stat *statbuf) {
+
+    char pathname_with_index[MAX_PATH_LENGTH];
+    int data_fd;
+    time_t real_dir_mtime;
+
+    real_dir_mtime = statbuf->st_mtime;
+    sprintf(pathname_with_index, "%s/dir.%d.%ld",
+                       cachedir, (int) statbuf->st_dev, statbuf->st_ino);
+    data_fd = open(pathname_with_index, O_RDONLY);
+
+    if (data_fd != -1) {                 /* index cache */
+
+	fstat(data_fd, statbuf);
+	if (statbuf->st_mtime > real_dir_mtime) {
+		statbuf->st_mtime = real_dir_mtime;         /* lie */
+		strcpy(req->request_uri, directory_index);  /* for mimetype */ 
+		return data_fd;
+	}
+	close(data_fd);
+	unlink(pathname_with_index);      /* cache is stale, delete it */
+    }
+    if (index_directory(req, pathname_with_index) == -1) return -1;
+
+    data_fd = open(pathname_with_index, O_RDONLY);      /* Last chance */
+    if (data_fd != -1) {
+	strcpy(req->request_uri, directory_index);      /* for mimetype */
+	fstat(data_fd, statbuf);
+	statbuf->st_mtime = real_dir_mtime;         /* lie */
+	return data_fd;
+    }
+
+    boa_perror(req,"re-opening dircache");
+    return -1;    /* Nothing worked. */
+
+}
+
+/*
+ * Name: index_directory
+ * Description: Called from get_cachedir_file if a directory html
+ * has to be generated on the fly
+ * returns -1 for problem, else 0
+ * This version is the fastest, ugliest, and most accurate yet.
+ * It solves the "stale size or type" problem by not ever giving
+ * the size or type.  This also speeds it up since no per-file
+ * stat() is required.
+ */
+
+int index_directory(request * req, char * dest_filename)
+{
+    DIR * request_dir;
+    FILE * fdstream;
+    struct dirent * dirbuf;
+    int bytes = 0;
+    char *escname=NULL;
+
+    if(chdir(req->path_translated) == -1) {
+	if(errno == EACCES || errno == EPERM) {
+	    send_r_forbidden(req);
+	} else {
+	    log_error_doc(req);
+	    perror("chdir");
+	    send_r_bad_request(req);
+	}
+	return -1;
+    }
+
+    request_dir = opendir(".");
+    if (request_dir == NULL) {
+	int errno_save=errno;
+	send_r_error(req);
+	log_error_time();
+	fprintf(stderr, "directory \"%s\": ", req->path_translated);
+	errno=errno_save;
+	perror("opendir");
+	return -1;
+    }
+
+    fdstream = fopen(dest_filename, "w");
+    if (fdstream == NULL) {
+	boa_perror(req,"dircache fopen");
+	closedir(request_dir);
+	return -1;
+    }
+    
+    bytes += fprintf(fdstream, 
+      "<HTML><HEAD>\n<TITLE>Index of %s</TITLE>\n</HEAD>\n\n",
+      req->request_uri);
+    bytes += fprintf(fdstream, "<BODY>\n\n<H2>Index of %s</H2>\n\n<PRE>\n",
+      req->request_uri);
+
+    while((dirbuf = readdir(request_dir))) {
+	if(!strcmp(dirbuf->d_name, "."))
+	    continue;
+
+	if(!strcmp(dirbuf->d_name, "..")) {
+	    bytes += fprintf(fdstream, 
+	      " [DIR] <A HREF=\"../\">Parent Directory</A>\n");
+	    continue;
+	}
+
+	if (escape_string(dirbuf->d_name, escname)) {
+	    bytes += fprintf(fdstream," <A HREF=\"%s\">%s</A>",
+		escname, dirbuf->d_name);
+            free(escname);
+	    escname=NULL;
+	}
+    }
+    closedir(request_dir);
+    bytes += fprintf(fdstream, "</PRE>\n\n</BODY>\n</HTML>\n");
+
+    fclose(fdstream);
+
+    chdir(server_root);
+
+    req->filesize = bytes;              /* for logging transfer size */
+    return 0;                           /* success */
+}
diff -urN boa-0.93.17.2/src/globals.h boa-0.93.17.3/src/globals.h
--- boa-0.93.17.2/src/globals.h	Sun Jul 18 23:27:25 1999
+++ boa-0.93.17.3/src/globals.h	Sun Aug  1 16:27:49 1999
@@ -69,6 +69,7 @@
 	char remote_ip_addr[20];	/* after inet_ntoa */
 	unsigned char iplocal[4];       /* for virtualhost */
 	int remote_port;			/* could be used for ident */
+	int linkgen;
 
 	time_t last_modified;		/* Last-modified: */
 
@@ -164,6 +165,7 @@
 extern char *default_type;
 extern char *dirmaker;
 extern char *mime_types;
+extern char *cachedir;
 
 extern int ka_timeout;
 extern int ka_max;
diff -urN boa-0.93.17.2/src/poll.c boa-0.93.17.3/src/poll.c
--- boa-0.93.17.2/src/poll.c	Sat Jul 17 23:35:42 1999
+++ boa-0.93.17.3/src/poll.c	Wed Dec 31 16:00:00 1969
@@ -1,8 +0,0 @@
-	if (poll(polling_list, npoll, timeout*1000) {
-	
-fdset_update
-	polling_list[i].fd=current->data_fd;
-	switch (current->status) {
-	case PIPE_WRITE:
-	case WRITE:
-		polling_list[i].events=POLLOUT | POLLERR
diff -urN boa-0.93.17.2/src/request.c boa-0.93.17.3/src/request.c
--- boa-0.93.17.2/src/request.c	Sun Jul 18 23:28:02 1999
+++ boa-0.93.17.3/src/request.c	Fri Aug  6 22:40:58 1999
@@ -193,9 +193,10 @@
 	if (req->logline)			/* access log */
 		log_access(req);
 
-	if (req->data_mem)
-	    /*		munmap(req->data_mem, req->filesize); */
-	    release_mmap(req->mmap_entry_var);
+	if (req->mmap_entry_var)
+		release_mmap(req->mmap_entry_var);
+	else if (req->data_mem)
+		munmap(req->data_mem, req->filesize);
 
 
 	if (req->data_fd)
