diff --git a/src/modules/files/efuns.c b/src/modules/files/efuns.c
index 534b943b9b904f483275660da295fa85ca542d3c..9e0d027e9978a30d9a61cc898f0cc442e8492b41 100644
--- a/src/modules/files/efuns.c
+++ b/src/modules/files/efuns.c
@@ -22,7 +22,7 @@
 #include "file_machine.h"
 #include "file.h"
 
-RCSID("$Id: efuns.c,v 1.60 1998/10/27 16:09:10 per Exp $");
+RCSID("$Id: efuns.c,v 1.61 1998/10/30 14:36:31 grubba Exp $");
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -419,30 +419,63 @@ void f_rm(INT32 args)
 void f_mkdir(INT32 args)
 {
   char *s;
-  INT32 i;
+  int mode;
+  int i;
+
   if(!args)
     error("Too few arguments to mkdir()\n");
 
   if(sp[-args].type != T_STRING)
     error("Bad argument 1 to mkdir().\n");
 
-  i=0770;
+  mode = 0770;
 
   if(args > 1)
   {
     if(sp[1-args].type != T_INT)
       error("Bad argument 2 to mkdir.\n");
 
-    i=sp[1-args].u.integer;
+    mode = sp[1-args].u.integer;
   }
   s=sp[-args].u.string->str;
-  THREADS_ALLOW_UID();
 #if MKDIR_ARGS == 2
-  i=mkdir(s, i) != -1;
+  THREADS_ALLOW_UID();
+  i = mkdir(s, mode) != -1;
+  THREADS_DISALLOW_UID();
 #else
-  i=mkdir(s) != -1;
+  /* Most OS's should have MKDIR_ARGS == 2 nowadays fortunately. */
+  i = mkdir(s) != -1;
+  if (i) {
+    /* Attempt to set the mode.
+     *
+     * This code needs to be as paranoid as possible.
+     */
+    struct stat statbuf1;
+    struct stat statbuf2;
+    int mask = umask(0);
+    umask(mask);
+    i = lstat(s, &statbuf1) != -1;
+    if (i) {
+      i = ((statbuf1.st_mode & S_IFMT) == S_IFDIR);
+    }
+    if (i) {
+      mode = ((mode & 0777) | (statbuf1.st_mode & ~0777)) & ~mask;
+      i = chmod(s, mode) != -1;
+    }
+    if (i) {
+      i = lstat(s, &statbuf2) != -1;
+    }
+    if (i) {
+      i = (statbuf2.st_mode == mode) && (statbuf1.st_ino == statbuf2.st_ino);
+      if (!i) {
+	errno = EPERM;
+      }
+    }
+    if (!i) {
+      rmdir(s);
+    }
+  }  
 #endif
-  THREADS_DISALLOW_UID();
   pop_n_elems(args);
   push_int(i);
 }