]> diplodocus.org Git - nmh/blobdiff - sbr/m_mktemp.c
Escape literal leading full stop in man/new.man.
[nmh] / sbr / m_mktemp.c
index ac05306a96cb33b4c9c40ef947a3157ab0ed3700..15bee9394218a27da7b0a8130435234dd4cf5ae2 100644 (file)
@@ -32,7 +32,6 @@ static void register_for_removal(const char *);
  *
  *    MHTMPDIR envvar
  *    TMPDIR envvar
- *    TMP envvar
  *    User's mail directory.
  *
  *  NOTE: One will probably use m_mktemp2() instead of this function.
@@ -133,6 +132,102 @@ m_mktemp2 (
 }
 
 
+/*
+ * This version supports a suffix for the temp filename.
+ * It has two other differences from m_mktemp() and m_mktemp2():
+ * 1) It does not support specification of a directory for the temp
+ *    file.  Instead it always uses get_temp_dir().
+ * 2) It returns a dynamically allocated string.  The caller is
+ *    responsible for freeing the allocated memory.
+ */
+char *
+m_mktemps(
+    const char *pfx_in,   /* Basename prefix for temp file. */
+    const char *suffix,   /* Suffix, including any '.', for temp file. */
+    int *fd_ret,          /* (return,optional) File descriptor to temp file. */
+    FILE **fp_ret         /* (return,optional) FILE pointer to temp file. */
+)
+{
+    char *tmpfil;
+    int fd = -1;
+    int keep_open = 0;
+    mode_t oldmode = umask(077);
+
+    if (suffix == NULL) {
+        if ((tmpfil = m_mktemp2(NULL, pfx_in, fd_ret, fp_ret))) {
+            return mh_xstrdup(tmpfil);
+        }
+        return NULL;
+    }
+
+#if HAVE_MKSTEMPS
+    if (pfx_in == NULL) {
+        tmpfil = concat(get_temp_dir(), "/nmhXXXXXX", suffix, NULL);
+    } else {
+        tmpfil = concat(get_temp_dir(), "/", pfx_in, "XXXXXX", suffix, NULL);
+    }
+
+    fd = mkstemps(tmpfil, (int) strlen(suffix));
+#else  /* ! HAVE_MKSTEMPS */
+    /* NetBSD, Solaris 10 */
+
+    if (pfx_in == NULL) {
+        tmpfil = concat(get_temp_dir(), "/nmhXXXXXX", NULL);
+    } else {
+        tmpfil = concat(get_temp_dir(), "/", pfx_in, "XXXXXX", NULL);
+    }
+
+    fd = mkstemp(tmpfil);
+    {
+        char *oldfilename = tmpfil;
+        tmpfil = concat(oldfilename, suffix, NULL);
+
+        if (rename(oldfilename, tmpfil) != 0) {
+            (void) unlink(oldfilename);
+            free(oldfilename);
+            free(tmpfil);
+            return NULL;
+        }
+
+        free(oldfilename);
+    }
+#endif /* ! HAVE_MKSTEMPS */
+
+    if (fd < 0) {
+        umask(oldmode);
+        free(tmpfil);
+        return NULL;
+    }
+
+    register_for_removal(tmpfil);
+
+    if (fd_ret != NULL) {
+        *fd_ret = fd;
+        keep_open = 1;
+    }
+    if (fp_ret != NULL) {
+        FILE *fp = fdopen(fd, "w+");
+        if (fp == NULL) {
+            int olderr = errno;
+            (void) m_unlink(tmpfil);
+            close(fd);
+            errno = olderr;
+            umask(oldmode);
+            free(tmpfil);
+            return NULL;
+        }
+        *fp_ret = fp;
+        keep_open = 1;
+    }
+    if (!keep_open) {
+        close(fd);
+    }
+    umask(oldmode);
+
+    return tmpfil;
+}
+
+
 char *
 get_temp_dir()
 {
@@ -144,9 +239,6 @@ get_temp_dir()
 
         tmpdir = getenv("TMPDIR");
         if (tmpdir != NULL && *tmpdir != '\0') return tmpdir;
-
-        tmpdir = getenv("TMP");
-        if (tmpdir != NULL && *tmpdir != '\0') return tmpdir;
     }
     return m_maildir("");
 }
@@ -262,13 +354,13 @@ remove_registered_files(int sig) {
 
         exit(1);
     } else {
+        remove_registered_files_atexit();
+
         act.sa_handler = SIG_DFL;
         (void) sigemptyset(&act.sa_mask);
         act.sa_flags = 0;
         (void) sigaction(sig, &act, 0);
 
-        remove_registered_files_atexit();
-
         (void) raise(sig);
     }
 }