-/*
- * m_mktemp.c -- Construct a temporary file.
+/* m_mktemp.c -- Construct a temporary file.
*
* This code is Copyright (c) 2010, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
#include <h/mh.h>
#include <h/utils.h>
#include <h/signals.h>
+#include "m_maildir.h"
+#include "m_mktemp.h"
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.
FILE *fp = fdopen(fd, "w+");
if (fp == NULL) {
int olderr = errno;
- unlink(tmpfil);
+ (void) m_unlink(tmpfil);
close(fd);
errno = olderr;
umask(oldmode);
}
+/*
+ * 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()
+get_temp_dir(void)
{
/* Ignore envvars if we are setuid */
if ((getuid()==geteuid()) && (getgid()==getegid())) {
tmpdir = getenv("TMPDIR");
if (tmpdir != NULL && *tmpdir != '\0') return tmpdir;
-
- tmpdir = getenv("TMP");
- if (tmpdir != NULL && *tmpdir != '\0') return tmpdir;
}
return m_maildir("");
}
static void
register_for_removal(const char *pathname) {
if (exit_filelist == NULL) exit_filelist = svector_create(20);
- (void) svector_push_back(exit_filelist, add(pathname, NULL));
+ (void) svector_push_back(exit_filelist, mh_xstrdup(pathname));
}
/*
* Remove all registered temporary files.
*/
void
-remove_registered_files_atexit() {
+remove_registered_files_atexit(void) {
unregister_for_removal(1);
}
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);
}
}