/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
#include <libc-lock.h>

static __libc_key_t key;

/* If nonzero the key allocation failed and we should better use a
   static buffer than fail.  */
#define BUFFERSIZ	100
static char local_buf[BUFFERSIZ];
static char *static_buf;

/* Destructor for the thread-specific data.  */
static void init (void);
static void free_key_mem (void *mem);
static char *getbuffer (void);


/* Return a string describing the meaning of the signal number SIGNUM.  */
char *
strsignal (int signum)
{
  __libc_once_define (static, once);
  const char *desc;

  /* If we have not yet initialized the buffer do it now.  */
  __libc_once (once, init);

  if (
#ifdef SIGRTMIN
      (signum >= SIGRTMIN && signum <= SIGRTMAX) ||
#endif
      signum < 0 || signum >= NSIG
      || (desc = _sys_siglist[signum]) == NULL)
    {
      char *buffer = getbuffer ();
      int len;
#ifdef SIGRTMIN
      if (signum >= SIGRTMIN && signum <= SIGRTMAX)
	len = __snprintf (buffer, BUFFERSIZ - 1, _("Real-time signal %d"),
			  signum - SIGRTMIN);
      else
#endif
	len = __snprintf (buffer, BUFFERSIZ - 1, _("Unknown signal %d"),
			  signum);
      if (len >= BUFFERSIZ)
	buffer = NULL;
      else
	buffer[len] = '\0';

      return buffer;
    }

  return (char *) _(desc);
}


/* Initialize buffer.  */
static void
init (void)
{
  if (__libc_key_create (&key, free_key_mem))
    /* Creating the key failed.  This means something really went
       wrong.  In any case use a static buffer which is better than
       nothing.  */
    static_buf = local_buf;
}


/* Free the thread specific data, this is done if a thread terminates.  */
static void
free_key_mem (void *mem)
{
  free (mem);
  __libc_setspecific (key, NULL);
}


/* Return the buffer to be used.  */
static char *
getbuffer (void)
{
  char *result;

  if (static_buf != NULL)
    result = static_buf;
  else
    {
      /* We don't use the static buffer and so we have a key.  Use it
	 to get the thread-specific buffer.  */
      result = __libc_getspecific (key);
      if (result == NULL)
	{
	  /* No buffer allocated so far.  */
	  result = malloc (BUFFERSIZ);
	  if (result == NULL)
	    /* No more memory available.  We use the static buffer.  */
	    result = local_buf;
	  else
	    __libc_setspecific (key, result);
	}
    }

  return result;
}
