]>
Commit | Line | Data |
---|---|---|
28ef6c31 JA |
1 | /* |
2 | * tmpfile.c - functions to create and safely open temp files for the shell. | |
3 | */ | |
4 | ||
5 | /* Copyright (C) 2000 Free Software Foundation, Inc. | |
6 | ||
7 | This file is part of GNU Bash, the Bourne Again SHell. | |
8 | ||
9 | Bash is free software; you can redistribute it and/or modify it | |
10 | under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2, or (at your option) | |
12 | any later version. | |
13 | ||
14 | Bash is distributed in the hope that it will be useful, but WITHOUT | |
15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
17 | License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with Bash; see the file COPYING. If not, write to the Free | |
21 | Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ | |
22 | ||
23 | #include <config.h> | |
24 | ||
25 | #include <bashtypes.h> | |
26 | #include <posixstat.h> | |
7117c2d2 | 27 | #include <posixtime.h> |
28ef6c31 JA |
28 | #include <filecntl.h> |
29 | ||
30 | #if defined (HAVE_UNISTD_H) | |
31 | # include <unistd.h> | |
32 | #endif | |
33 | ||
34 | #include <stdio.h> | |
35 | #include <errno.h> | |
36 | ||
37 | #include <shell.h> | |
38 | ||
39 | #ifndef errno | |
40 | extern int errno; | |
41 | #endif | |
42 | ||
43 | #define BASEOPENFLAGS (O_CREAT | O_TRUNC | O_EXCL) | |
44 | ||
45 | #define DEFAULT_TMPDIR "." /* bogus default, should be changed */ | |
46 | #define DEFAULT_NAMEROOT "shtmp" | |
47 | ||
f73dda09 | 48 | extern pid_t dollar_dollar_pid; |
28ef6c31 | 49 | |
0628567a JA |
50 | static char *get_sys_tmpdir __P((void)); |
51 | static char *get_tmpdir __P((int)); | |
52 | ||
28ef6c31 JA |
53 | static char *sys_tmpdir = (char *)NULL; |
54 | static int ntmpfiles; | |
55 | static int tmpnamelen = -1; | |
56 | static unsigned long filenum = 1L; | |
57 | ||
58 | static char * | |
59 | get_sys_tmpdir () | |
60 | { | |
28ef6c31 JA |
61 | if (sys_tmpdir) |
62 | return sys_tmpdir; | |
63 | ||
f73dda09 JA |
64 | #ifdef P_tmpdir |
65 | sys_tmpdir = P_tmpdir; | |
b80f6443 | 66 | if (file_iswdir (sys_tmpdir)) |
f73dda09 JA |
67 | return sys_tmpdir; |
68 | #endif | |
69 | ||
28ef6c31 | 70 | sys_tmpdir = "/tmp"; |
b80f6443 | 71 | if (file_iswdir (sys_tmpdir)) |
28ef6c31 JA |
72 | return sys_tmpdir; |
73 | ||
74 | sys_tmpdir = "/var/tmp"; | |
b80f6443 | 75 | if (file_iswdir (sys_tmpdir)) |
28ef6c31 JA |
76 | return sys_tmpdir; |
77 | ||
78 | sys_tmpdir = "/usr/tmp"; | |
b80f6443 | 79 | if (file_iswdir (sys_tmpdir)) |
28ef6c31 JA |
80 | return sys_tmpdir; |
81 | ||
28ef6c31 | 82 | sys_tmpdir = DEFAULT_TMPDIR; |
28ef6c31 JA |
83 | |
84 | return sys_tmpdir; | |
85 | } | |
86 | ||
87 | static char * | |
88 | get_tmpdir (flags) | |
89 | int flags; | |
90 | { | |
91 | char *tdir; | |
92 | ||
93 | tdir = (flags & MT_USETMPDIR) ? get_string_value ("TMPDIR") : (char *)NULL; | |
94 | if (tdir == 0) | |
95 | tdir = get_sys_tmpdir (); | |
96 | ||
97 | #if defined (HAVE_PATHCONF) && defined (_PC_NAME_MAX) | |
98 | if (tmpnamelen == -1) | |
99 | tmpnamelen = pathconf (tdir, _PC_NAME_MAX); | |
100 | #else | |
101 | tmpnamelen = 0; | |
102 | #endif | |
103 | ||
104 | return tdir; | |
105 | } | |
106 | ||
107 | char * | |
108 | sh_mktmpname (nameroot, flags) | |
109 | char *nameroot; | |
110 | int flags; | |
111 | { | |
f73dda09 | 112 | char *filename, *tdir, *lroot; |
28ef6c31 JA |
113 | struct stat sb; |
114 | int r, tdlen; | |
115 | ||
f73dda09 | 116 | filename = (char *)xmalloc (PATH_MAX + 1); |
28ef6c31 JA |
117 | tdir = get_tmpdir (flags); |
118 | tdlen = strlen (tdir); | |
119 | ||
f73dda09 | 120 | lroot = nameroot ? nameroot : DEFAULT_NAMEROOT; |
28ef6c31 | 121 | |
f73dda09 JA |
122 | #ifdef USE_MKTEMP |
123 | sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); | |
124 | if (mktemp (filename) == 0) | |
125 | { | |
126 | free (filename); | |
127 | filename = NULL; | |
128 | } | |
129 | #else /* !USE_MKTEMP */ | |
28ef6c31 JA |
130 | while (1) |
131 | { | |
f73dda09 JA |
132 | filenum = (filenum << 1) ^ |
133 | (unsigned long) time ((time_t *)0) ^ | |
134 | (unsigned long) dollar_dollar_pid ^ | |
135 | (unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++); | |
136 | sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum); | |
28ef6c31 JA |
137 | if (tmpnamelen > 0 && tmpnamelen < 32) |
138 | filename[tdlen + 1 + tmpnamelen] = '\0'; | |
f73dda09 | 139 | # ifdef HAVE_LSTAT |
28ef6c31 | 140 | r = lstat (filename, &sb); |
f73dda09 | 141 | # else |
28ef6c31 | 142 | r = stat (filename, &sb); |
f73dda09 | 143 | # endif |
28ef6c31 JA |
144 | if (r < 0 && errno == ENOENT) |
145 | break; | |
146 | } | |
f73dda09 | 147 | #endif /* !USE_MKTEMP */ |
28ef6c31 JA |
148 | |
149 | return filename; | |
150 | } | |
151 | ||
152 | int | |
153 | sh_mktmpfd (nameroot, flags, namep) | |
154 | char *nameroot; | |
155 | int flags; | |
156 | char **namep; | |
157 | { | |
f73dda09 | 158 | char *filename, *tdir, *lroot; |
28ef6c31 JA |
159 | int fd, tdlen; |
160 | ||
f73dda09 | 161 | filename = (char *)xmalloc (PATH_MAX + 1); |
28ef6c31 JA |
162 | tdir = get_tmpdir (flags); |
163 | tdlen = strlen (tdir); | |
164 | ||
f73dda09 | 165 | lroot = nameroot ? nameroot : DEFAULT_NAMEROOT; |
28ef6c31 | 166 | |
f73dda09 JA |
167 | #ifdef USE_MKSTEMP |
168 | sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); | |
169 | fd = mkstemp (filename); | |
170 | if (fd < 0 || namep == 0) | |
171 | { | |
172 | free (filename); | |
173 | filename = NULL; | |
174 | } | |
175 | if (namep) | |
176 | *namep = filename; | |
177 | return fd; | |
178 | #else /* !USE_MKSTEMP */ | |
28ef6c31 JA |
179 | do |
180 | { | |
f73dda09 JA |
181 | filenum = (filenum << 1) ^ |
182 | (unsigned long) time ((time_t *)0) ^ | |
183 | (unsigned long) dollar_dollar_pid ^ | |
184 | (unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++); | |
185 | sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum); | |
28ef6c31 JA |
186 | if (tmpnamelen > 0 && tmpnamelen < 32) |
187 | filename[tdlen + 1 + tmpnamelen] = '\0'; | |
188 | fd = open (filename, BASEOPENFLAGS | ((flags & MT_READWRITE) ? O_RDWR : O_WRONLY), 0600); | |
189 | } | |
190 | while (fd < 0 && errno == EEXIST); | |
191 | ||
192 | if (namep) | |
193 | *namep = filename; | |
194 | else | |
195 | free (filename); | |
196 | ||
197 | return fd; | |
f73dda09 | 198 | #endif /* !USE_MKSTEMP */ |
28ef6c31 JA |
199 | } |
200 | ||
201 | FILE * | |
202 | sh_mktmpfp (nameroot, flags, namep) | |
203 | char *nameroot; | |
204 | int flags; | |
205 | char **namep; | |
206 | { | |
207 | int fd; | |
f73dda09 | 208 | FILE *fp; |
28ef6c31 JA |
209 | |
210 | fd = sh_mktmpfd (nameroot, flags, namep); | |
f73dda09 JA |
211 | if (fd < 0) |
212 | return ((FILE *)NULL); | |
213 | fp = fdopen (fd, (flags & MT_READWRITE) ? "w+" : "w"); | |
214 | if (fp == 0) | |
215 | close (fd); | |
216 | return fp; | |
28ef6c31 | 217 | } |