X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/d046c8f0992fddcd69f2172a6607a14dec3b1251..a3724ed39:/sbr/m_mktemp.c?ds=sidebyside diff --git a/sbr/m_mktemp.c b/sbr/m_mktemp.c index a9dab5a2..9a28b48a 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 *); @@ -132,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; + 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(void) { /* Ignore envvars if we are setuid */ if ((getuid()==geteuid()) && (getgid()==getegid())) { @@ -224,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); } @@ -258,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); } }