OSDN Git Service

* choose-temp.c: Don't include gansidecl.h.
[pf3gnuchains/gcc-fork.git] / libiberty / choose-temp.c
1 /* Utility to pick a temporary filename prefix.
2    Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
3
4 This file is part of the libiberty library.
5 Libiberty is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 Libiberty is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with libiberty; see the file COPYING.LIB.  If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.  */
19
20 /* This file exports two functions: choose_temp_base and make_temp_file.  */
21
22 /* This file lives in at least two places: libiberty and gcc.
23    Don't change one without the other.  */
24
25 #if defined (IN_GCC) || defined (HAVE_CONFIG_H)
26 #include "config.h"
27 #endif
28
29 #ifdef IN_GCC
30 #include "system.h"
31 #else
32
33 /* If we are in gcc, system.h has handled everything.  When not in
34    gcc, if we have a config.h we assume that HAVE_SYS_FILE_H tells us
35    whether to include sys/file.h.  However, libiberty does not have a
36    config.h, and instead arranges to define NO_SYS_FILE_H on the
37    command line when there is no sys/file.h.  */
38
39 #if defined (HAVE_CONFIG_H) ? defined (HAVE_SYS_FILE_H) : ! defined (NO_SYS_FILE_H)
40 #include <sys/types.h>
41 #include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
42 #endif
43
44 #ifndef R_OK
45 #define R_OK 4
46 #define W_OK 2
47 #define X_OK 1
48 #endif
49
50 #include <stdio.h>      /* May get P_tmpdir.  */
51 #endif /* IN_GCC */
52
53 #ifdef IN_GCC
54 extern char *xmalloc ();
55 extern int mkstemps ();
56 #else
57 #include "ansidecl.h"
58 #include "libiberty.h"
59 #if defined (__MSDOS__) || defined (_WIN32)
60 #define DIR_SEPARATOR '\\'
61 #endif
62 #endif
63
64 #ifndef DIR_SEPARATOR
65 #define DIR_SEPARATOR '/'
66 #endif
67
68 /* On MSDOS, write temp files in current dir
69    because there's no place else we can expect to use.  */
70 /* ??? Although the current directory is tried as a last resort,
71    this is left in so that on MSDOS it is preferred to /tmp on the
72    off chance that someone requires this, since that was the previous
73    behaviour.  */
74 #ifdef __MSDOS__
75 #ifndef P_tmpdir
76 #define P_tmpdir "."
77 #endif
78 #endif
79
80 /* Name of temporary file.
81    mktemp requires 6 trailing X's.  */
82 #define TEMP_FILE "ccXXXXXX"
83
84 /* Subroutine of choose_temp_base.
85    If BASE is non-NULL, return it.
86    Otherwise it checks if DIR is a usable directory.
87    If success, DIR is returned.
88    Otherwise NULL is returned.  */
89
90 static char *
91 try (dir, base)
92      char *dir, *base;
93 {
94   if (base != 0)
95     return base;
96   if (dir != 0
97       && access (dir, R_OK | W_OK | X_OK) == 0)
98     return dir;
99   return 0;
100 }
101
102 /* Return a prefix for temporary file names or NULL if unable to find one.
103    The current directory is chosen if all else fails so the program is
104    exited if a temporary directory can't be found (mktemp fails).
105    The buffer for the result is obtained with xmalloc. 
106
107    This function is provided for backwards compatability only.  It use
108    is not recommended.  */
109
110 char *
111 choose_temp_base ()
112 {
113   char *base = 0;
114   char *temp_filename;
115   int len;
116   static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
117   static char usrtmp[] = { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
118
119   base = try (getenv ("TMPDIR"), base);
120   base = try (getenv ("TMP"), base);
121   base = try (getenv ("TEMP"), base);
122
123 #ifdef P_tmpdir
124   base = try (P_tmpdir, base);
125 #endif
126
127   /* Try /usr/tmp, then /tmp.  */
128   base = try (usrtmp, base);
129   base = try (tmp, base);
130  
131   /* If all else fails, use the current directory!  */
132   if (base == 0)
133     base = ".";
134
135   len = strlen (base);
136   temp_filename = xmalloc (len + 1 /*DIR_SEPARATOR*/
137                            + strlen (TEMP_FILE) + 1);
138   strcpy (temp_filename, base);
139
140   if (len != 0
141       && temp_filename[len-1] != '/'
142       && temp_filename[len-1] != DIR_SEPARATOR)
143     temp_filename[len++] = DIR_SEPARATOR;
144   strcpy (temp_filename + len, TEMP_FILE);
145
146   mktemp (temp_filename);
147   if (strlen (temp_filename) == 0)
148     abort ();
149   return temp_filename;
150 }
151 /* Return a temporary file name (as a string) or NULL if unable to create
152    one.  */
153
154 char *
155 make_temp_file (suffix)
156      char *suffix;
157 {
158   char *base = 0;
159   char *temp_filename;
160   int base_len, suffix_len;
161   int fd;
162   static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
163   static char usrtmp[] = { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
164
165   base = try (getenv ("TMPDIR"), base);
166   base = try (getenv ("TMP"), base);
167   base = try (getenv ("TEMP"), base);
168
169 #ifdef P_tmpdir
170   base = try (P_tmpdir, base);
171 #endif
172
173   /* Try /usr/tmp, then /tmp.  */
174   base = try (usrtmp, base);
175   base = try (tmp, base);
176  
177   /* If all else fails, use the current directory!  */
178   if (base == 0)
179     base = ".";
180
181   base_len = strlen (base);
182
183   if (suffix)
184     suffix_len = strlen (suffix);
185   else
186     suffix_len = 0;
187
188   temp_filename = xmalloc (base_len + 1 /*DIR_SEPARATOR*/
189                            + strlen (TEMP_FILE)
190                            + suffix_len + 1);
191   strcpy (temp_filename, base);
192
193   if (base_len != 0
194       && temp_filename[base_len-1] != '/'
195       && temp_filename[base_len-1] != DIR_SEPARATOR)
196     temp_filename[base_len++] = DIR_SEPARATOR;
197   strcpy (temp_filename + base_len, TEMP_FILE);
198
199   if (suffix)
200     strcat (temp_filename, suffix);
201
202   fd = mkstemps (temp_filename, suffix_len);
203   /* If mkstemps failed, then something bad is happening.  Maybe we should
204      issue a message about a possible security attack in progress?  */
205   if (fd == -1)
206     abort ();
207   /* Similarly if we can not close the file.  */
208   if (close (fd))
209     abort ();
210   return temp_filename;
211 }