No specific user configuration
[platform/upstream/bash.git] / lib / sh / tmpfile.c
index 6912e5c..c06ad65 100644 (file)
@@ -6,30 +6,33 @@
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
-   Bash is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
 
-   Bash is distributed in the hope that it will be useful, but WITHOUT
-   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
-   License for more details.
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with Bash; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
 
 #include <config.h>
 
 #include <bashtypes.h>
 #include <posixstat.h>
+#include <posixtime.h>
 #include <filecntl.h>
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
 #endif
 
+#include <bashansi.h>
+
 #include <stdio.h>
 #include <errno.h>
 
 extern int errno;
 #endif
 
-#define BASEOPENFLAGS  (O_CREAT | O_TRUNC | O_EXCL)
+#define BASEOPENFLAGS  (O_CREAT | O_TRUNC | O_EXCL | O_BINARY)
 
 #define DEFAULT_TMPDIR         "."     /* bogus default, should be changed */
 #define DEFAULT_NAMEROOT       "shtmp"
 
-extern int dollar_dollar_pid;
+extern pid_t dollar_dollar_pid;
+
+static char *get_sys_tmpdir __P((void));
+static char *get_tmpdir __P((int));
 
 static char *sys_tmpdir = (char *)NULL;
 static int ntmpfiles;
@@ -54,28 +60,28 @@ static unsigned long filenum = 1L;
 static char *
 get_sys_tmpdir ()
 {
-  struct stat sb;
-
   if (sys_tmpdir)
     return sys_tmpdir;
 
+#ifdef P_tmpdir
+  sys_tmpdir = P_tmpdir;
+  if (file_iswdir (sys_tmpdir))
+    return sys_tmpdir;
+#endif
+
   sys_tmpdir = "/tmp";
-  if (stat (sys_tmpdir, &sb) == 0)
+  if (file_iswdir (sys_tmpdir))
     return sys_tmpdir;
 
   sys_tmpdir = "/var/tmp";
-  if (stat (sys_tmpdir, &sb) == 0)
+  if (file_iswdir (sys_tmpdir))
     return sys_tmpdir;
 
   sys_tmpdir = "/usr/tmp";
-  if (stat (sys_tmpdir, &sb) == 0)
+  if (file_iswdir (sys_tmpdir))
     return sys_tmpdir;
 
-#ifdef P_tmpdir
-  sys_tmpdir = P_tmpdir;
-#else
   sys_tmpdir = DEFAULT_TMPDIR;
-#endif
 
   return sys_tmpdir;
 }
@@ -87,6 +93,9 @@ get_tmpdir (flags)
   char *tdir;
 
   tdir = (flags & MT_USETMPDIR) ? get_string_value ("TMPDIR") : (char *)NULL;
+  if (tdir && (file_iswdir (tdir) == 0 || strlen (tdir) > PATH_MAX))
+    tdir = 0;
+
   if (tdir == 0)
     tdir = get_sys_tmpdir ();
 
@@ -105,32 +114,42 @@ sh_mktmpname (nameroot, flags)
      char *nameroot;
      int flags;
 {
-  char *filename, *tdir;
+  char *filename, *tdir, *lroot;
   struct stat sb;
   int r, tdlen;
 
-  filename = xmalloc (PATH_MAX + 1);
+  filename = (char *)xmalloc (PATH_MAX + 1);
   tdir = get_tmpdir (flags);
   tdlen = strlen (tdir);
 
-  if (nameroot == 0)
-    nameroot = DEFAULT_NAMEROOT;
+  lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
 
+#ifdef USE_MKTEMP
+  sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
+  if (mktemp (filename) == 0)
+    {
+      free (filename);
+      filename = NULL;
+    }
+#else  /* !USE_MKTEMP */
   while (1)
     {
-      filenum *= (int)time ((time_t *)0) * dollar_dollar_pid *
-               ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
-      sprintf (filename, "%s/%s-%lu", tdir, nameroot, filenum);
+      filenum = (filenum << 1) ^
+               (unsigned long) time ((time_t *)0) ^
+               (unsigned long) dollar_dollar_pid ^
+               (unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
+      sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
       if (tmpnamelen > 0 && tmpnamelen < 32)
        filename[tdlen + 1 + tmpnamelen] = '\0';
-#ifdef HAVE_LSTAT
+#  ifdef HAVE_LSTAT
       r = lstat (filename, &sb);
-#else
+#  else
       r = stat (filename, &sb);
-#endif
+#  endif
       if (r < 0 && errno == ENOENT)
        break;
     }
+#endif /* !USE_MKTEMP */
 
   return filename;
 }
@@ -141,21 +160,34 @@ sh_mktmpfd (nameroot, flags, namep)
      int flags;
      char **namep;
 {
-  char *filename, *tdir;
+  char *filename, *tdir, *lroot;
   int fd, tdlen;
 
-  filename = xmalloc (PATH_MAX + 1);
+  filename = (char *)xmalloc (PATH_MAX + 1);
   tdir = get_tmpdir (flags);
   tdlen = strlen (tdir);
 
-  if (nameroot == 0)
-    nameroot = DEFAULT_NAMEROOT;
+  lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
 
+#ifdef USE_MKSTEMP
+  sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
+  fd = mkstemp (filename);
+  if (fd < 0 || namep == 0)
+    {
+      free (filename);
+      filename = NULL;
+    }
+  if (namep)
+    *namep = filename;
+  return fd;
+#else /* !USE_MKSTEMP */
   do
     {
-      filenum *= (int)time ((time_t *)0) * dollar_dollar_pid *
-               ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
-      sprintf (filename, "%s/%s-%lu", tdir, nameroot, filenum);
+      filenum = (filenum << 1) ^
+               (unsigned long) time ((time_t *)0) ^
+               (unsigned long) dollar_dollar_pid ^
+               (unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
+      sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
       if (tmpnamelen > 0 && tmpnamelen < 32)
        filename[tdlen + 1 + tmpnamelen] = '\0';
       fd = open (filename, BASEOPENFLAGS | ((flags & MT_READWRITE) ? O_RDWR : O_WRONLY), 0600);
@@ -168,6 +200,7 @@ sh_mktmpfd (nameroot, flags, namep)
     free (filename);
 
   return fd;
+#endif /* !USE_MKSTEMP */
 }
 
 FILE *
@@ -177,7 +210,13 @@ sh_mktmpfp (nameroot, flags, namep)
      char **namep;
 {
   int fd;
+  FILE *fp;
 
   fd = sh_mktmpfd (nameroot, flags, namep);
-  return ((fd >= 0) ? (fdopen (fd, (flags & MT_READWRITE) ? "w+" : "w")) : (FILE *)NULL);
+  if (fd < 0)
+    return ((FILE *)NULL);
+  fp = fdopen (fd, (flags & MT_READWRITE) ? "w+" : "w");
+  if (fp == 0)
+    close (fd);
+  return fp;
 }