]> diplodocus.org Git - nmh/blob - sbr/m_mktemp.c
Fix a segfault that happens when using the -file option.
[nmh] / sbr / m_mktemp.c
1 /*
2 * m_mktemp.c -- Construct a temporary file.
3 *
4 * This code is Copyright (c) 2010, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
7 */
8
9 #include <errno.h>
10 #include <h/mh.h>
11
12 static char *get_temp_dir();
13
14 /* Create a temporary file. If pfx_in is null, the temporary file
15 * will be created in the temporary directory (more on that later).
16 * If pfx_in is not null, then the temporary file location will be
17 * defined by the value pfx_in.
18 *
19 * The file created will be at the pathname specified appended with
20 * 6 random (we hope :) characters.
21 *
22 * The return value will be the pathname to the file created.
23 *
24 * CAUTION: The return pointer references static data. If
25 * you need to modify, or save, the return string, make a copy of it
26 * first.
27 *
28 * When pfx_in is null, the temporary directory is determined as
29 * follows, in order:
30 *
31 * MHTMPDIR envvar
32 * TMPDIR envvar
33 * TMP envvar
34 * User's mail directory.
35 *
36 * NOTE: One will probably use m_mktemp2() instead of this function.
37 * For example, if you want to create a temp file in the defined
38 * temporary directory, but with a custom basename prefix, do
39 * something like the following:
40 *
41 * char *tmp_pathname = m_mktemp2(NULL, "mypre", ...);
42 */
43 char *
44 m_mktemp (
45 const char *pfx_in, /* Pathname prefix for temporary file. */
46 int *fd_ret, /* (return,optional) File descriptor to temp file. */
47 FILE **fp_ret /* (return,optional) FILE pointer to temp file. */
48 )
49 {
50 static char tmpfil[BUFSIZ];
51 int fd = -1;
52 int keep_open = 0;
53 mode_t oldmode = umask(077);
54
55 if (pfx_in == NULL) {
56 snprintf(tmpfil, sizeof(tmpfil), "%s/nmhXXXXXX", get_temp_dir());
57 } else {
58 snprintf(tmpfil, sizeof(tmpfil), "%sXXXXXX", pfx_in);
59 }
60
61 fd = mkstemp(tmpfil);
62 if (fd < 0) {
63 umask(oldmode);
64 return NULL;
65 }
66 if (fd_ret != NULL) {
67 *fd_ret = fd;
68 keep_open = 1;
69 }
70 if (fp_ret != NULL) {
71 FILE *fp = fdopen(fd, "w+");
72 if (fp == NULL) {
73 int olderr = errno;
74 unlink(tmpfil);
75 close(fd);
76 errno = olderr;
77 umask(oldmode);
78 return NULL;
79 }
80 *fp_ret = fp;
81 keep_open = 1;
82 }
83 if (!keep_open) {
84 close(fd);
85 }
86 umask(oldmode);
87 return tmpfil;
88 }
89
90 /* This version allows one to specify the directory the temp file should
91 * by created based on a given pathname. Although m_mktemp() technically
92 * supports this, this version is when the directory is defined by
93 * a separate variable from the prefix, eliminating the caller from having
94 * to do string manipulation to generate the desired. pathname prefix.
95 *
96 * The pfx_in parameter specifies a basename prefix for the file. If dir_in
97 * is NULL, then the defined temporary directory (see comments to m_mktemp()
98 * above) is used to create the temp file.
99 */
100 char *
101 m_mktemp2 (
102 const char *dir_in, /* Directory to place temp file. */
103 const char *pfx_in, /* Basename prefix for temp file. */
104 int *fd_ret, /* (return,optional) File descriptor to temp file. */
105 FILE **fp_ret /* (return,optional) FILE pointer to temp file. */
106 )
107 {
108 static char buffer[BUFSIZ];
109 char *cp;
110 int n;
111
112 if (dir_in == NULL) {
113 if (pfx_in == NULL) {
114 return m_mktemp(NULL, fd_ret, fp_ret);
115 }
116 snprintf(buffer, sizeof(buffer), "%s/%s", get_temp_dir(), pfx_in);
117 return m_mktemp(buffer, fd_ret, fp_ret);
118 }
119
120 if ((cp = r1bindex ((char *)dir_in, '/')) == dir_in) {
121 /* No directory component */
122 return m_mktemp(pfx_in, fd_ret, fp_ret);
123 }
124 n = (int)(cp-dir_in); /* Length of dir component */
125 snprintf(buffer, sizeof(buffer), "%.*s%s", n, dir_in, pfx_in);
126 return m_mktemp(buffer, fd_ret, fp_ret);
127 }
128
129
130 static char *
131 get_temp_dir()
132 {
133 // Ignore envvars if we are setuid
134 if ((getuid()==geteuid()) && (getgid()==getegid())) {
135 char *tmpdir = NULL;
136 tmpdir = getenv("MHTMPDIR");
137 if (tmpdir != NULL && *tmpdir != '\0') return tmpdir;
138
139 tmpdir = getenv("TMPDIR");
140 if (tmpdir != NULL && *tmpdir != '\0') return tmpdir;
141
142 tmpdir = getenv("TMP");
143 if (tmpdir != NULL && *tmpdir != '\0') return tmpdir;
144 }
145 return m_maildir("");
146 }