Patchwork [libfortran] PR 47432 Use thread-safe ttyname_r() if available

login
register
mail settings
Submitter Janne Blomqvist
Date Jan. 25, 2011, 5:33 p.m.
Message ID <AANLkTingh7SZp+br-ftLt=ZwCyT-syjd01v_DdwQ_L5b@mail.gmail.com>
Download mbox | patch
Permalink /patch/80392/
State New
Headers show

Comments

Janne Blomqvist - Jan. 25, 2011, 5:33 p.m.
Hi,

the attached patch makes libgfortran use the thread-safe ttyname_r()
function if available.

Regtested on x86_64-unknown-linux-gnu, Ok for trunk?
Tobias Burnus - Jan. 27, 2011, 6:58 p.m.
On 01/25/2011 06:33 PM, Janne Blomqvist wrote:
> the attached patch makes libgfortran use the thread-safe ttyname_r()
> function if available.
>
> Regtested on x86_64-unknown-linux-gnu, Ok for trunk?

OK. And I meant this patch and not the previous one when I talked about 
the follow-up patch (s/int/size_t/).

Tobias
Janne Blomqvist - Jan. 27, 2011, 8:10 p.m.
On Thu, Jan 27, 2011 at 20:58, Tobias Burnus <burnus@net-b.de> wrote:
> On 01/25/2011 06:33 PM, Janne Blomqvist wrote:
>>
>> the attached patch makes libgfortran use the thread-safe ttyname_r()
>> function if available.
>>
>> Regtested on x86_64-unknown-linux-gnu, Ok for trunk?
>
> OK. And I meant this patch and not the previous one when I talked about the
> follow-up patch (s/int/size_t/).
>
> Tobias

Thanks,

Sending        libgfortran/ChangeLog
Sending        libgfortran/config.h.in
Sending        libgfortran/configure
Sending        libgfortran/configure.ac
Sending        libgfortran/io/inquire.c
Sending        libgfortran/io/intrinsics.c
Sending        libgfortran/io/unix.c
Sending        libgfortran/io/unix.h
Transmitting file data ........
Committed revision 169337.

Patch

diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index 4f137e4..7c7a915 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -249,7 +249,7 @@  AC_CHECK_FUNCS(chdir strerror getlogin gethostname kill link symlink perror)
 AC_CHECK_FUNCS(sleep time ttyname signal alarm ctime clock access fork execl)
 AC_CHECK_FUNCS(wait setmode execvp pipe dup2 close fdopen strcasestr getrlimit)
 AC_CHECK_FUNCS(gettimeofday stat fstat lstat getpwuid vsnprintf dup getcwd)
-AC_CHECK_FUNCS(localtime_r gmtime_r strerror_r)
+AC_CHECK_FUNCS(localtime_r gmtime_r strerror_r ttyname_r)
 
 # Check for glibc backtrace functions
 AC_CHECK_FUNCS(backtrace backtrace_symbols)
diff --git a/libgfortran/io/inquire.c b/libgfortran/io/inquire.c
index 24481cc..252f29f 100644
--- a/libgfortran/io/inquire.c
+++ b/libgfortran/io/inquire.c
@@ -1,8 +1,8 @@ 
-/* Copyright (C) 2002, 2003, 2005, 2007, 2009, 2010
+/* Copyright (C) 2002, 2003, 2005, 2007, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Andy Vaught
 
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
 
 Libgfortran is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -68,16 +68,17 @@  inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
   if ((cf & IOPARM_INQUIRE_HAS_NAME) != 0
       && u != NULL && u->flags.status != STATUS_SCRATCH)
     {
-#ifdef HAVE_TTYNAME
+#if defined(HAVE_TTYNAME_R) || defined(HAVE_TTYNAME)
       if (u->unit_number == options.stdin_unit
 	  || u->unit_number == options.stdout_unit
 	  || u->unit_number == options.stderr_unit)
 	{
-	  char * tmp = stream_ttyname (u->s);
-	  if (tmp != NULL)
+	  int err = stream_ttyname (u->s, iqp->name, iqp->name_len);
+	  if (err == 0)
 	    {
-	      int tmplen = strlen (tmp);
-	      fstrcpy (iqp->name, iqp->name_len, tmp, tmplen);
+	      gfc_charlen_type tmplen = strlen (iqp->name);
+	      if (iqp->name_len > tmplen)
+		memset (&iqp->name[tmplen], ' ', iqp->name_len - tmplen);
 	    }
 	  else /* If ttyname does not work, go with the default.  */
 	    fstrcpy (iqp->name, iqp->name_len, u->file, u->file_len);
diff --git a/libgfortran/io/intrinsics.c b/libgfortran/io/intrinsics.c
index f2f532b..f48bd77 100644
--- a/libgfortran/io/intrinsics.c
+++ b/libgfortran/io/intrinsics.c
@@ -1,6 +1,7 @@ 
 /* Implementation of the FGET, FGETC, FPUT, FPUTC, FLUSH 
    FTELL, TTYNAM and ISATTY intrinsics.
-   Copyright (C) 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007, 2009, 2010, 2011 Free Software
+   Foundation, Inc.
 
 This file is part of the GNU Fortran runtime library (libgfortran).
 
@@ -351,22 +352,23 @@  void
 ttynam_sub (int *unit, char * name, gfc_charlen_type name_len)
 {
   gfc_unit *u;
-  char * n;
-  int i;
+  int nlen;
+  int err = 1;
 
-  memset (name, ' ', name_len);
   u = find_unit (*unit);
   if (u != NULL)
     {
-      n = stream_ttyname (u->s);
-      if (n != NULL)
+      err = stream_ttyname (u->s, name, name_len);
+      if (err == 0)
 	{
-	  i = 0;
-	  while (*n && i < name_len)
-	    name[i++] = *(n++);
+	  nlen = strlen (name);
+	  memset (&name[nlen], ' ', name_len - nlen);
 	}
+
       unlock_unit (u);
     }
+  if (err != 0)
+    memset (name, ' ', name_len);
 }
 
 
@@ -381,14 +383,15 @@  ttynam (char ** name, gfc_charlen_type * name_len, int unit)
   u = find_unit (unit);
   if (u != NULL)
     {
-      *name = stream_ttyname (u->s);
-      if (*name != NULL)
+      *name = get_mem (TTY_NAME_MAX);
+      int err = stream_ttyname (u->s, *name, TTY_NAME_MAX);
+      if (err == 0)
 	{
 	  *name_len = strlen (*name);
-	  *name = strdup (*name);
 	  unlock_unit (u);
 	  return;
 	}
+      free (*name);
       unlock_unit (u);
     }
 
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index 950b7a2..ad90552 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -1811,18 +1811,29 @@  stream_isatty (stream *s)
   return isatty (((unix_stream *) s)->fd);
 }
 
-char *
-#ifdef HAVE_TTYNAME
-stream_ttyname (stream *s)
-{
-  return ttyname (((unix_stream *) s)->fd);
-}
+int
+stream_ttyname (stream *s  __attribute__ ((unused)),
+		char * buf  __attribute__ ((unused)),
+		size_t buflen  __attribute__ ((unused)))
+{
+#ifdef HAVE_TTYNAME_R
+  return ttyname_r (((unix_stream *) s)->fd, buf, buflen);
+#elif defined HAVE_TTYNAME
+  char *p;
+  int plen;
+  p = ttyname (((unix_stream *) s)->fd);
+  if (!p)
+    return errno;
+  plen = strlen (p);
+  if (buflen < plen)
+    plen = buflen;
+  memcpy (buf, p, plen);
+  return 0;
 #else
-stream_ttyname (stream *s __attribute__ ((unused)))
-{
-  return NULL;
-}
+  return ENOSYS;
 #endif
+}
+
 
 
 
diff --git a/libgfortran/io/unix.h b/libgfortran/io/unix.h
index 0e147aa..f7d6f08 100644
--- a/libgfortran/io/unix.h
+++ b/libgfortran/io/unix.h
@@ -170,7 +170,16 @@  internal_proto(flush_if_preconnected);
 extern int stream_isatty (stream *);
 internal_proto(stream_isatty);
 
-extern char * stream_ttyname (stream *);
+#ifndef TTY_NAME_MAX
+#ifdef _POSIX_TTY_NAME_MAX
+#define TTY_NAME_MAX _POSIX_TTY_NAME_MAX
+#else
+/* sysconf(_SC_TTY_NAME_MAX) = 32 which should be enough.  */
+#define TTY_NAME_MAX 32
+#endif
+#endif
+
+extern int stream_ttyname (stream *, char *, size_t);
 internal_proto(stream_ttyname);
 
 extern int unpack_filename (char *, const char *, int);