1 /*
2 * tmpname.c
3 * Original Author: G. Haley
4 */
5
6 /*
7 FUNCTION
8 <<tmpnam>>, <<tempnam>>---name for a temporary file
9
10 INDEX
11 tmpnam
12 INDEX
13 tempnam
14 INDEX
15 _tmpnam_r
16 INDEX
17 _tempnam_r
18
19 ANSI_SYNOPSIS
20 #include <stdio.h>
21 char *tmpnam(char *<[s]>);
22 char *tempnam(char *<[dir]>, char *<[pfx]>);
23 char *_tmpnam_r(void *<[reent]>, char *<[s]>);
24 char *_tempnam_r(void *<[reent]>, char *<[dir]>, char *<[pfx]>);
25
26 TRAD_SYNOPSIS
27 #include <stdio.h>
28 char *tmpnam(<[s]>)
29 char *<[s]>;
30
31 char *tempnam(<[dir]>, <[pfx]>)
32 char *<[dir]>;
33 char *<[pfx]>;
34
35 char *_tmpnam_r(<[reent]>, <[s]>)
36 char *<[reent]>;
37 char *<[s]>;
38
39 char *_tempnam_r(<[reent]>, <[dir]>, <[pfx]>)
40 char *<[reent]>;
41 char *<[dir]>;
42 char *<[pfx]>;
43
44 DESCRIPTION
45 Use either of these functions to generate a name for a temporary file.
46 The generated name is guaranteed to avoid collision with other files
47 (for up to <<TMP_MAX>> calls of either function).
48
49 <<tmpnam>> generates file names with the value of <<P_tmpdir>>
50 (defined in `<<stdio.h>>') as the leading directory component of the path.
51
52 You can use the <<tmpnam>> argument <[s]> to specify a suitable area
53 of memory for the generated filename; otherwise, you can call
54 <<tmpnam(NULL)>> to use an internal static buffer.
55
56 <<tempnam>> allows you more control over the generated filename: you
57 can use the argument <[dir]> to specify the path to a directory for
58 temporary files, and you can use the argument <[pfx]> to specify a
59 prefix for the base filename.
60
61 If <[dir]> is <<NULL>>, <<tempnam>> will attempt to use the value of
62 environment variable <<TMPDIR>> instead; if there is no such value,
63 <<tempnam>> uses the value of <<P_tmpdir>> (defined in `<<stdio.h>>').
64
65 If you don't need any particular prefix to the basename of temporary
66 files, you can pass <<NULL>> as the <[pfx]> argument to <<tempnam>>.
67
68 <<_tmpnam_r>> and <<_tempnam_r>> are reentrant versions of <<tmpnam>>
69 and <<tempnam>> respectively. The extra argument <[reent]> is a
70 pointer to a reentrancy structure.
71
72 WARNINGS
73 The generated filenames are suitable for temporary files, but do not
74 in themselves make files temporary. Files with these names must still
75 be explicitly removed when you no longer want them.
76
77 If you supply your own data area <[s]> for <<tmpnam>>, you must ensure
78 that it has room for at least <<L_tmpnam>> elements of type <<char>>.
79
80 RETURNS
81 Both <<tmpnam>> and <<tempnam>> return a pointer to the newly
82 generated filename.
83
84 PORTABILITY
85 ANSI C requires <<tmpnam>>, but does not specify the use of
86 <<P_tmpdir>>. The System V Interface Definition (Issue 2) requires
87 both <<tmpnam>> and <<tempnam>>.
88
89 Supporting OS subroutines required: <<close>>, <<fstat>>, <<getpid>>,
90 <<isatty>>, <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>.
91
92 The global pointer <<environ>> is also required.
93 */
94
95 #include <_ansi.h>
96 #include <stdio.h>
97 #include <stdlib.h>
98 #include <string.h>
99 #include <fcntl.h>
100 #include <reent.h>
101 #include <errno.h>
102
103 /* Try to open the file specified, if it can't be opened then try
104 another one. Return nonzero if successful, otherwise zero. */
105
106 static int
worker(ptr,result,part1,part2,part3,part4)107 worker (ptr, result, part1, part2, part3, part4)
108 struct _reent *ptr;
109 char *result;
110 _CONST char *part1;
111 _CONST char *part2;
112 int part3;
113 int *part4;
114 {
115 /* Generate the filename and make sure that there isn't one called
116 it already. */
117
118 while (1)
119 {
120 int t;
121 _sprintf_r (ptr, result, "%s/%s%x.%x", part1, part2, part3, *part4);
122 (*part4)++;
123 t = _open_r (ptr, result, O_RDONLY, 0);
124 if (t == -1)
125 {
126 if (ptr->_errno == ENOSYS)
127 {
128 result[0] = '\0';
129 return 0;
130 }
131 break;
132 }
133 _close_r (ptr, t);
134 }
135 return 1;
136 }
137
138 char *
139 _DEFUN (_tmpnam_r, (p, s),
140 struct _reent *p _AND
141 char *s)
142 {
143 char *result;
144 int pid;
145
146 if (s == NULL)
147 {
148 /* ANSI states we must use an internal static buffer if s is NULL */
149 _REENT_CHECK_EMERGENCY(p);
150 result = _REENT_EMERGENCY(p);
151 }
152 else
153 {
154 result = s;
155 }
156 pid = _getpid_r (p);
157
158 if (worker (p, result, P_tmpdir, "t", pid, &p->_inc))
159 {
160 p->_inc++;
161 return result;
162 }
163
164 return NULL;
165 }
166
167 char *
168 _DEFUN (_tempnam_r, (p, dir, pfx),
169 struct _reent *p _AND
170 _CONST char *dir _AND
171 _CONST char *pfx)
172 {
173 char *filename;
174 int length;
175 _CONST char *prefix = (pfx) ? pfx : "";
176 if (dir == NULL && (dir = getenv ("TMPDIR")) == NULL)
177 dir = P_tmpdir;
178
179 /* two 8 digit numbers + . / */
180 length = strlen (dir) + strlen (prefix) + (4 * sizeof (int)) + 2 + 1;
181
182 filename = _malloc_r (p, length);
183 if (filename)
184 {
185 if (! worker (p, filename, dir, prefix,
186 _getpid_r (p) ^ (int) (_POINTER_INT) p, &p->_inc))
187 return NULL;
188 }
189 return filename;
190 }
191
192 #ifndef _REENT_ONLY
193
194 char *
195 _DEFUN (tempnam, (dir, pfx),
196 _CONST char *dir _AND
197 _CONST char *pfx)
198 {
199 return _tempnam_r (_REENT, dir, pfx);
200 }
201
202 char *
203 _DEFUN (tmpnam, (s),
204 char *s)
205 {
206 return _tmpnam_r (_REENT, s);
207 }
208
209 #endif
210