diff -ru ldmud-3.3.714.orig/src/efuns.c ldmud-3.3.714.mod/src/efuns.c
--- ldmud-3.3.714.orig/src/efuns.c	2006-07-10 04:42:05.000000000 +0200
+++ ldmud-3.3.714.mod/src/efuns.c	2007-09-20 16:21:32.000000000 +0200
@@ -809,7 +809,7 @@
     if (max_array_size && arraysize > (long)max_array_size-1 ) {
         free_regexp(reg);
         inter_sp = sp;
-        errorf("Illegal array size");
+        errorf("Illegal array size: %d",arraysize);
         /* NOTREACHED */
         return sp;
     }
@@ -8594,15 +8594,25 @@
  *
  * Interpret the argument clock as number of seconds since Jan,
  * 1st, 1970, 0.00 and convert it to a nice date and time string.
+ * In this case, the result string will be cached and tabled.
  *
  * Alternatively, accept an array of two ints: the first is <clock>
  * value as in the first form, the second int is the number of
  * microseconds elapsed in the current second.
+ * In this case the result will not be cached as the value is very
+ * unlikely to be the same in 2 consecutive calls.
  */
 
 {
     char *ts, *cp;
     string_t *rc;
+    
+    static mp_int last_time = -1;  // letzte Uhrzeit
+    /* pointer to pointer to the last result string (has some sense,
+    *  because then the actual pointer to the string is findable by the GC,
+    *  so the cached string won't be deallocated (while still in use). The
+    *  space for **last_res will be permanently allocated.) */
+    static string_t **last_res = NULL;
 
     if (sp->type != T_NUMBER)
     {
@@ -8615,28 +8625,74 @@
         if (sp->u.vec->item[1].type != T_NUMBER)
             errorf("Bad arg 1 to ctime(): Element 1 is '%s', expected 'int'.\n"
                  , efun_arg_typename(sp->u.vec->item[1].type));
+        
         ts = utime_string( sp->u.vec->item[0].u.number
                          , sp->u.vec->item[1].u.number);
+        
+        /* If the string contains nl characters, extract the substring
+         * before the first one. Else just copy the (volatile) result
+         * we got.
+         */
+        cp = strchr(ts, '\n');
+        if (cp)
+        {
+            int len = cp - ts;
+            memsafe(rc = new_n_mstring(ts, len), len, "ctime() result");
+        }
+        else
+        {
+            memsafe(rc = new_mstring(ts), strlen(ts), "ctime() result");
+        }
     }
     else
     {
-        ts = time_string(sp->u.number);
-    }
-
-    /* If the string contains nl characters, extract the substring
-     * before the first one. Else just copy the (volatile) result
-     * we got.
-     */
-    cp = strchr(ts, '\n');
-    if (cp)
-    {
-        int len = cp - ts;
-        memsafe(rc = new_n_mstring(ts, len), len, "ctime() result");
-    }
-    else
-    {
-        memsafe(rc = new_mstring(ts), strlen(ts), "ctime() result");
-    }
+        // test if string for this time is cached
+        if (last_time != sp->u.number)
+        {
+            ts = time_fstring(sp->u.number, "%a %b %d %H:%M:%S %Y", 0);
+            
+            /* If the string contains nl characters, extract the substring
+             * before the first one. Else just copy the (volatile) result
+             * we got.
+             * Table strings, because they are probably used more then once. 
+             */
+            cp = strchr(ts, '\n');
+            if (cp)
+            {
+                int len = cp - ts;
+                memsafe(rc = new_n_tabled(ts, len), len,
+                        "ctime() result");
+            }
+            else
+            {
+                memsafe(rc = new_tabled(ts), strlen(ts),
+                        "ctime() result");
+            }
+            /* fill cache, free last (invalid) string first and don't forget 
+             * to increase the ref count for the cache. */
+            if (!last_res) {
+                /* allocate space for pointer. Has to be permanent, because 
+                 * otherwise the GC would wrongly free the block, resulting 
+                 * in a double free here. */
+                if (!(last_res = pxalloc(sizeof(string_t*)))) {
+                    // free result string first
+                    free_mstring(rc);
+                    errorf("Out of memory: couldn't allocate ctime() cache pointer");
+                }
+            }
+            else // free cached string
+                free_mstring(*last_res);
+            *last_res = rc;
+            ref_mstring(rc);
+            last_time = sp->u.number;
+        }
+        else {
+            // return last result (and increase ref count)
+            rc = *last_res;
+            ref_mstring(rc);
+        }
+    }  // if (sp->type != T_NUMBER)
+    
     free_svalue(sp);
     put_string(sp, rc);
     return sp;
@@ -8702,5 +8758,143 @@
     return sp;
 } /* f_utime() */
 
-/***************************************************************************/
+/*-------------------------------------------------------------------------*/
+svalue_t *
+f_mktime (svalue_t *sp)
 
+/* EFUN mktime()
+ *
+ *   int time(int* datum)
+ *
+ * Return the unix timestamp (number of seconds ellapsed since 1. Jan 1970, 
+ * 0.0:0 GMT) of the date given in the array datum. datum being an array
+ * like the one localtime() or gmtime() return:
+ *   int TM_SEC   (0) : Seconds (0..59)
+ *   int TM_MIN   (1) : Minutes (0..59)
+ *   int TM_HOUR  (2) : Hours (0..23)
+ *   int TM_MDAY  (3) : Day of the month (1..31)
+ *   int TM_MON   (4) : Month of the year (0..11)
+ *   int TM_YEAR  (5) : Year (e.g.  2001)
+ *   int TM_WDAY  (6) : Day of the week (Sunday = 0)
+ *   int TM_YDAY  (7) : Day of the year (0..365)
+ *   int TM_ISDST (8) : TRUE: Daylight saving time
+ * TM_YDAY and TM_WDAY are ignored (but must also be ints).
+ *
+ */
+{
+    struct tm * pTm; // broken-down time structure for mktime()
+    time_t      clk; // unix timestamp corresponding to datum
+    vector_t  * v;   // just for convenience, stores argument array 
+    int i; 
+
+    v = sp->u.vec;
+    if (VEC_SIZE(v) != 9)
+        errorf("Bad arg 1 to mktime(): Invalid array size %ld, expected 2.\n"
+                 , (long)VEC_SIZE(v));
+    // all elements must be ints.
+    for(i=0; i<VEC_SIZE(v); i++) 
+    {
+        if ( v->item[i].type != T_NUMBER)
+            errorf("Bad arg 1 to ctime(): Element %d is '%s', expected 'int'.\n"
+                 ,i, efun_arg_typename(v->item[0].type));
+    }
+
+    // create the time structure
+    xallocate(pTm, sizeof(*pTm), "broken-down time structure for mktime()");
+    pTm->tm_sec   = v->item[TM_SEC].u.number;
+    pTm->tm_min   = v->item[TM_MIN].u.number;
+    pTm->tm_hour  = v->item[TM_HOUR].u.number;
+    pTm->tm_mday  = v->item[TM_MDAY].u.number;
+    pTm->tm_mon   = v->item[TM_MON].u.number;
+    pTm->tm_year  = v->item[TM_YEAR].u.number - 1900;
+    pTm->tm_isdst = v->item[TM_ISDST].u.number;
+    
+    clk = mktime(pTm);
+
+    // free time structure first
+    xfree(pTm);
+    
+    if (clk == -1)
+        errorf("Specified date/time cannot be represented as unix timestamp.\n");
+    
+    // free argument and put result.
+    free_svalue(sp);
+    put_number(sp, (uint32)clk);
+    
+    return sp;
+} /* f_mktime() */
+
+/*-------------------------------------------------------------------------*/
+svalue_t *
+v_strftime(svalue_t *sp, int num_arg)
+/* EFUN strftime()
+ *
+ *   string strftime()
+ *   string strftime(string fmt)
+ *   string strftime(int clock)
+ *   string strftime(string fmt, int clock)
+ *   string strftime(string fmt, int clock, int localized)
+ *
+ * Interpret the argument clock as number of seconds since Jan,
+ * 1st, 1970, 0.00 and convert it to a nice date and time string.
+ * The formatstring must be given in fmt and may contain the placeholders
+ * defined in 'man 3 strftime'.
+ * If localized == MY_TRUE then the time string will be created with the
+ * locale set in the environment variable LC_TIME
+ * Defaults: fmt="%c", clock=current_time, localized=MY_TRUE
+ * NOTE: the returned string will have at most 511 Characters.
+ * TODO: Implement proper caching of the result.
+ * TODO: instead of using pxalloc, efuns.c may implement support functions 
+ * TODO::for the GC, which mark the appropriate blocks as referenced.
+ */
+
+{
+    char *ts;
+    string_t *rc = NULL;  // ergebnisstring
+    
+    /* Begin of arguments on the stack */
+    svalue_t *arg = sp - num_arg + 1;
+    
+    // defaults:
+    Bool localized = MY_TRUE;
+    mp_int clk = current_time;
+    char *cfmt = "%c";
+    
+    // evaluate arguments
+    switch(num_arg) {
+        case 3:
+            localized = (Bool)arg[2].u.number;
+            // fall-through
+        case 2:
+            if (arg[1].u.number < 0)
+                errorf("Bad arg 2 to strftime(): got %ld, expected 0 .. %ld\n",
+                        arg[1].u.number, PINT_MAX);
+            clk = arg[1].u.number;
+            // fall-through
+        case 1:
+            // empty strings default to "%c" => only set fmt if non-empty
+            if (arg[0].type == T_STRING && mstrsize(arg[0].u.str)) {
+                cfmt = get_txt(arg[0].u.str);
+            }
+            else if (arg[0].type == T_NUMBER) {
+                if (num_arg>1) // bei > 1 argument nur strings erlaubt
+                    vefun_exp_arg_error(1, TF_STRING, sp->type, sp);
+                else if (arg[0].u.number >= 0)
+                    clk = arg[0].u.number;
+                else
+                    errorf("Bad argument 1 to strftime(): got %ld, expected 0 .. %ld\n",
+                        arg[0].u.number, PINT_MAX);
+            }
+            break;
+    }
+
+    ts = time_fstring(clk,cfmt,localized); 
+    memsafe(rc = new_tabled(ts), strlen(ts)+sizeof(string_t), "strftime() result");
+    
+    sp = pop_n_elems(num_arg, sp);
+    push_string(sp, rc);
+    
+    return sp;
+} /* f_strftime() */
+
+/***************************************************************************/
diff -ru ldmud-3.3.714.orig/src/efuns.h ldmud-3.3.714.mod/src/efuns.h
--- ldmud-3.3.714.orig/src/efuns.h	2006-07-10 04:42:05.000000000 +0200
+++ ldmud-3.3.714.mod/src/efuns.h	2007-09-17 09:14:41.000000000 +0200
@@ -82,11 +82,13 @@
 extern svalue_t *tell_room(svalue_t *sp);
 
 extern svalue_t *f_ctime(svalue_t *);
+extern svalue_t *v_strftime(svalue_t *, int num_arg);
 extern svalue_t *v_debug_info(svalue_t *sp, int num_arg);
 extern svalue_t *f_rusage(svalue_t *sp);
 extern svalue_t *f_random(svalue_t *);
 extern svalue_t *f_shutdown(svalue_t *sp);
 extern svalue_t *f_time(svalue_t *);
+extern svalue_t *f_mktime(svalue_t *);
 extern svalue_t *f_utime(svalue_t *);
 
 #endif /* EFUNS_H__ */
diff -ru ldmud-3.3.714.orig/src/func_spec ldmud-3.3.714.mod/src/func_spec
--- ldmud-3.3.714.orig/src/func_spec	2006-07-10 04:44:07.000000000 +0200
+++ ldmud-3.3.714.mod/src/func_spec	2007-09-20 12:58:43.000000000 +0200
@@ -373,6 +373,8 @@
 mixed   restore_value(string);
 
 string  ctime(int*|int default: F_TIME);
+string  strftime(string|int|void, int|void, int|void);
+int     mktime(int*);
 int     random(int);
 int     time();
 int*    utime();
diff -ru ldmud-3.3.714.orig/src/main.c ldmud-3.3.714.mod/src/main.c
--- ldmud-3.3.714.orig/src/main.c	2006-07-10 04:42:05.000000000 +0200
+++ ldmud-3.3.714.mod/src/main.c	2007-09-20 16:09:04.000000000 +0200
@@ -265,7 +265,8 @@
 
     boot_time = (mp_int)time(NULL);
     setlocale(LC_CTYPE, ""); /* Use the locale defined in the LANG env var */
-    get_stack_direction();
+    setlocale(LC_TIME, "");
+		get_stack_direction();
     mb_init();
     init_interpret();
     rx_init();
diff -ru ldmud-3.3.714.orig/src/port.c ldmud-3.3.714.mod/src/port.c
--- ldmud-3.3.714.orig/src/port.c	2006-07-10 04:42:05.000000000 +0200
+++ ldmud-3.3.714.mod/src/port.c	2007-09-20 15:32:30.000000000 +0200
@@ -19,6 +19,7 @@
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
+#include <locale.h>
 #include <time.h>
 
 #include "backend.h"
@@ -83,24 +84,32 @@
 
 /*-------------------------------------------------------------------------*/
 char *
-time_string (mp_int t)
+time_fstring (mp_int t, const char* str, Bool localized)
 
-/* Return a textual representation of the time <t>. */
-
-{
-    static char result[80];
-    struct tm *tm;
-    mp_int last_time = -1;
-
-    if (t != last_time)
-    {
-        time_t ti = (time_t)t;
-        last_time = t;
-        tm = localtime(&ti);
-        strftime(result, sizeof(result)-1, "%a %b %d %H:%M:%S %Y", tm);
-    }
+/* Return a textual representation of the time <t> according to the format
+ * string <str>. Doesn't cache because it would be necessary to 
+ * save the format string and compare.
+ * If localized is true, this function sets the locale according to the 
+ * environment variable before calling strftime and resets it afterwards.
+ * TODO: It would be nicer to allocate the result buffer dynamically
+ * TODO::for using longer format strings. */
+{
+    static char result[512];
+    struct tm *tm; // broken-down time struct
+    
+    time_t ti = (time_t)t;
+    tm = localtime(&ti);
+    if (!localized) {
+        setlocale(LC_TIME, "C");
+        strftime(result, sizeof(result)-1, str, tm);
+        setlocale(LC_TIME, "");
+    }
+    else
+        strftime(result, sizeof(result)-1, str, tm);
+    
     return result;
-} /* time_string() */
+} /* time_fstring() */
+
 
 /*-------------------------------------------------------------------------*/
 char *
@@ -112,18 +121,13 @@
     static char result[80];
     struct tm *tm;
     size_t len;
-    mp_int last_t = -1, last_ut = -1;
 
-    if (t != last_t || ut != last_ut)
-    {
-        time_t ti = (time_t)t;
-        last_t= t;
-        last_ut= ut;
-        tm = localtime(&ti);
-        len = strftime(result, sizeof(result)-1, "%a %b %d %H:%M:%S:", tm);
-        sprintf(result+len, "%06ld", ut);
-        strftime(result+len+6, sizeof(result)-7-len, " %Y", tm);
-    }
+    time_t ti = (time_t)t;
+    tm = localtime(&ti);
+    len = strftime(result, sizeof(result)-1, "%a %b %d %H:%M:%S:", tm);
+    sprintf(result+len, "%06ld", ut);
+    strftime(result+len+6, sizeof(result)-7-len, " %Y", tm);
+    
     return result;
 } /* utime_string() */
 
diff -ru ldmud-3.3.714.orig/src/port.h ldmud-3.3.714.mod/src/port.h
--- ldmud-3.3.714.orig/src/port.h	2006-07-10 04:42:05.000000000 +0200
+++ ldmud-3.3.714.mod/src/port.h	2007-09-20 16:28:03.000000000 +0200
@@ -427,7 +427,7 @@
 
 extern char current_time_stamp[];
 extern mp_int get_current_time(void);
-extern char * time_string(mp_int);
+extern char * time_fstring(mp_int t, const char* str, Bool localized);
 extern char * utime_string(mp_int, mp_int);
 extern char * time_stamp(void);
 extern char *xmemmem(const char *, size_t, const char *, size_t);
