Index: nmap.cc
===================================================================
--- nmap.cc	(revision 5849)
+++ nmap.cc	(working copy)
@@ -473,6 +473,8 @@
   int num_host_exp_groups;
   char *machinefilename = NULL, *kiddiefilename = NULL, 
     *normalfilename = NULL, *xmlfilename = NULL;
+  time_t now;
+  struct tm *tm;
   HostGroupState *hstate = NULL;
   char *endptr = NULL;
   struct scan_lists *ports = NULL;
@@ -649,6 +651,9 @@
   win_pre_init();
 #endif
 
+  now = time(NULL);
+  tm = localtime(&now);
+
   /* OK, lets parse these args! */
   optind = 1; /* so it can be called multiple times */
   while((arg = getopt_long_only(argc,fakeargv,"6Ab:D:d::e:Ffg:hIi:M:m:nO::o:P:p:qRrS:s:T:Vv", long_options, &option_index)) != EOF) {
@@ -818,23 +823,23 @@
       } else if (strcmp(long_options[option_index].name, "webxml") == 0) {
 	o.setXSLStyleSheet("http://www.insecure.org/nmap/data/nmap.xsl");
       } else if (strcmp(long_options[option_index].name, "oN") == 0) {
-	normalfilename = optarg;
+	normalfilename = logfilename(optarg, tm);
       } else if (strcmp(long_options[option_index].name, "oG") == 0 ||
 		 strcmp(long_options[option_index].name, "oM") == 0) {
-	machinefilename = optarg;
+	machinefilename = logfilename(optarg, tm);
       } else if (strcmp(long_options[option_index].name, "oS") == 0) {
-	kiddiefilename = optarg;
+	kiddiefilename = logfilename(optarg, tm);
       } else if (strcmp(long_options[option_index].name, "oH") == 0) {
 	fatal("HTML output is not directly supported, though Nmap includes an XSL for transforming XML output into HTML.  See the man page.");
       } else if (strcmp(long_options[option_index].name, "oX") == 0) {
-	xmlfilename = optarg;
+	xmlfilename = logfilename(optarg, tm);
       } else if (strcmp(long_options[option_index].name, "oA") == 0) {
 	char buf[MAXPATHLEN];
-	Snprintf(buf, sizeof(buf), "%s.nmap", optarg);
+	Snprintf(buf, sizeof(buf), "%s.nmap", logfilename(optarg, tm));
 	normalfilename = strdup(buf);
-	Snprintf(buf, sizeof(buf), "%s.gnmap", optarg);
+	Snprintf(buf, sizeof(buf), "%s.gnmap", logfilename(optarg, tm));
 	machinefilename = strdup(buf);
-	Snprintf(buf, sizeof(buf), "%s.xml", optarg);
+	Snprintf(buf, sizeof(buf), "%s.xml", logfilename(optarg, tm));
 	xmlfilename = strdup(buf);
       } else if (strcmp(long_options[option_index].name, "thc") == 0) {
 	printf("!!Greets to Van Hauser, Plasmoid, Skyper and the rest of THC!!\n");
@@ -1013,7 +1018,7 @@
       }
       break;
     case 'o':
-      normalfilename = optarg;
+      normalfilename = logfilename(optarg, tm);
       break;
     case 'P': 
       if (*optarg == '\0' || *optarg == 'I' || *optarg == 'E')
@@ -1242,10 +1247,6 @@
 
   if (!o.interactivemode) {
     char tbuf[128];
-    struct tm *tm;
-    time_t now = time(NULL);
-    if (!(tm = localtime(&now))) 
-      fatal("Unable to get current localtime()#!#");
     // ISO 8601 date/time -- http://www.cl.cam.ac.uk/~mgk25/iso-time.html 
     if (strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M %Z", tm) <= 0)
       fatal("Unable to properly format time");
Index: output.h
===================================================================
--- output.h	(revision 5849)
+++ output.h	(working copy)
@@ -138,6 +138,8 @@
    in a certain place to conform to DTD. */
 void printmacinfo(Target *currenths);
 
+char *logfilename(const char *str, struct tm *tm);
+
 /* Write some information (printf style args) to the given log stream(s).
    Remember to watch out for format string bugs. */
 void log_write(int logt, const char *fmt, ...)
Index: output.cc
===================================================================
--- output.cc	(revision 5849)
+++ output.cc	(working copy)
@@ -830,6 +830,83 @@
   return temp;
 }
 
+char *logfilename(const char *str, struct tm *tm)
+{
+	char *a, *ret, *end, *p;
+	char tbuf[10];
+	int retlen = strlen(str) * 8 + 1;
+
+	ret = (char *) safe_malloc(retlen);
+	end = ret + retlen;
+
+	for (p = ret; *str; str++) {
+		if (*str == '%') {
+			if (!*(str + 1)) {
+				break;
+			}
+
+			str++;
+
+			switch (*str) {
+			case 'H':
+				strftime(tbuf, sizeof tbuf, "%H", tm);
+				a = strdup(tbuf);
+				break;
+			case 'M':
+				strftime(tbuf, sizeof tbuf, "%M", tm);
+				a = strdup(tbuf);
+				break;
+			case 'S':
+				strftime(tbuf, sizeof tbuf, "%S", tm);
+				a = strdup(tbuf);
+				break;
+			case 'T':
+				strftime(tbuf, sizeof tbuf, "%T", tm);
+				a = strdup(tbuf);
+				break;
+			case 't':
+				strftime(tbuf, sizeof tbuf, "%H%M%S", tm);
+				a = strdup(tbuf);
+				break;
+			case 'm':
+				strftime(tbuf, sizeof tbuf, "%m", tm);
+				a = strdup(tbuf);
+				break;
+			case 'd': 
+				strftime(tbuf, sizeof tbuf, "%d", tm);
+				a = strdup(tbuf);
+				break;
+			case 'y': 
+				strftime(tbuf, sizeof tbuf, "%y", tm);
+				a = strdup(tbuf);
+				break;
+			case 'Y': 
+				strftime(tbuf, sizeof tbuf, "%Y", tm);
+				a = strdup(tbuf);
+				break;
+			case 'D': 
+				strftime(tbuf, sizeof tbuf, "%m%d%y", tm);
+				a = strdup(tbuf);
+				break;
+			default:
+				*p++ = *str;
+				continue;
+			}
+
+			assert(end - p > 1);
+			Strncpy(p, a, end - p - 1);
+			p += strlen(a);
+			free(a);
+		} else {
+			*p++ = *str;
+		}
+	}
+
+	*p = 0;
+
+	return (char *) safe_realloc(ret, strlen(ret) + 1);
+}
+
 /* This is the workhorse of the logging functions.  Usually it is
    called through log_write(), but it can be called directly if you
    are dealing with a vfprintf-style va_list.  Unlike log_write, YOU

