X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/b56c88e2847c582f9b18ae5bbda44f033cd49c42..06efa573c7894caa4e5aa1ac7c64bd10ea25928b:/sbr/m_mktemp.c?ds=inline diff --git a/sbr/m_mktemp.c b/sbr/m_mktemp.c index cc9c45f5..123da576 100644 --- a/sbr/m_mktemp.c +++ b/sbr/m_mktemp.c @@ -1,5 +1,4 @@ -/* - * 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 @@ -9,6 +8,8 @@ #include #include #include +#include "m_maildir.h" +#include "m_mktemp.h" static void register_for_removal(const char *); @@ -32,7 +33,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. @@ -51,7 +51,6 @@ m_mktemp ( { static char tmpfil[BUFSIZ]; int fd = -1; - int keep_open = 0; mode_t oldmode = umask(077); if (pfx_in == NULL) { @@ -69,22 +68,23 @@ m_mktemp ( register_for_removal(tmpfil); + bool keep_open = false; if (fd_ret != NULL) { *fd_ret = fd; - keep_open = 1; + keep_open = true; } if (fp_ret != NULL) { FILE *fp = fdopen(fd, "w+"); if (fp == NULL) { int olderr = errno; - unlink(tmpfil); + (void) m_unlink(tmpfil); close(fd); errno = olderr; umask(oldmode); return NULL; } *fp_ret = fp; - keep_open = 1; + keep_open = true; } if (!keep_open) { close(fd); @@ -133,8 +133,104 @@ 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 * -get_temp_dir() +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; + 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); + + bool keep_open = false; + if (fd_ret != NULL) { + *fd_ret = fd; + keep_open = true; + } + 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 = true; + } + if (!keep_open) { + close(fd); + } + umask(oldmode); + + return tmpfil; +} + + +char * +get_temp_dir(void) { /* Ignore envvars if we are setuid */ if ((getuid()==geteuid()) && (getgid()==getegid())) { @@ -144,9 +240,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(""); } @@ -165,7 +258,7 @@ static svector_t exit_filelist = NULL; 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)); } /* @@ -228,7 +321,7 @@ m_unlink(const char *pathname) { * Remove all registered temporary files. */ void -remove_registered_files_atexit() { +remove_registered_files_atexit(void) { unregister_for_removal(1); } @@ -262,13 +355,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); } }