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