Blame stdio-common/psiginfo.c

Packit 6c4009
/* Copyright (C) 2009-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <array_length.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <libintl.h>
Packit 6c4009
#include <signal.h>
Packit 6c4009
#include <stdint.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <not-cancel.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
#define MF(l) MF1 (l)
Packit 6c4009
#define MF1(l) str_##l
Packit 6c4009
#define C(s1, s2) C1 (s1, s2)
Packit 6c4009
#define C1(s1, s2) s1##s2
Packit 6c4009
Packit 6c4009
#define NOW SIGILL
Packit 6c4009
#include "psiginfo-define.h"
Packit 6c4009
Packit 6c4009
#define NOW SIGFPE
Packit 6c4009
#include "psiginfo-define.h"
Packit 6c4009
Packit 6c4009
#define NOW SIGSEGV
Packit 6c4009
#include "psiginfo-define.h"
Packit 6c4009
Packit 6c4009
#define NOW SIGBUS
Packit 6c4009
#include "psiginfo-define.h"
Packit 6c4009
Packit 6c4009
#define NOW SIGTRAP
Packit 6c4009
#include "psiginfo-define.h"
Packit 6c4009
Packit 6c4009
#define NOW SIGCLD
Packit 6c4009
#include "psiginfo-define.h"
Packit 6c4009
Packit 6c4009
#define NOW SIGPOLL
Packit 6c4009
#include "psiginfo-define.h"
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Print out on stderr a line consisting of the test in S, a colon, a space,
Packit 6c4009
   a message describing the meaning of the signal number PINFO and a newline.
Packit 6c4009
   If S is NULL or "", the colon and space are omitted.  */
Packit 6c4009
void
Packit 6c4009
psiginfo (const siginfo_t *pinfo, const char *s)
Packit 6c4009
{
Packit 6c4009
  char buf[512];
Packit 6c4009
  FILE *fp = __fmemopen (buf, sizeof (buf), "w");
Packit 6c4009
  if (fp == NULL)
Packit 6c4009
    {
Packit 6c4009
      const char *colon;
Packit 6c4009
Packit 6c4009
      if (s == NULL || *s == '\0')
Packit 6c4009
	s = colon = "";
Packit 6c4009
      else
Packit 6c4009
	colon = ": ";
Packit 6c4009
Packit 6c4009
      __fxprintf (NULL, "%s%ssignal %d\n", s, colon, pinfo->si_signo);
Packit 6c4009
      return;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (s != NULL && *s != '\0')
Packit 6c4009
    fprintf (fp, "%s: ", s);
Packit 6c4009
Packit 6c4009
  const char *desc;
Packit 6c4009
  if (pinfo->si_signo >= 0 && pinfo->si_signo < NSIG
Packit 6c4009
      && ((desc = _sys_siglist[pinfo->si_signo]) != NULL
Packit 6c4009
#ifdef SIGRTMIN
Packit 6c4009
	  || (pinfo->si_signo >= SIGRTMIN && pinfo->si_signo < SIGRTMAX)
Packit 6c4009
#endif
Packit 6c4009
	 ))
Packit 6c4009
    {
Packit 6c4009
#ifdef SIGRTMIN
Packit 6c4009
      if (desc == NULL)
Packit 6c4009
	{
Packit 6c4009
	  if (pinfo->si_signo - SIGRTMIN < SIGRTMAX - pinfo->si_signo)
Packit 6c4009
	    {
Packit 6c4009
	      if (pinfo->si_signo == SIGRTMIN)
Packit 6c4009
		fprintf (fp, "SIGRTMIN (");
Packit 6c4009
	      else
Packit 6c4009
		fprintf (fp, "SIGRTMIN+%d (", pinfo->si_signo - SIGRTMIN);
Packit 6c4009
	    }
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit 6c4009
	      if (pinfo->si_signo == SIGRTMAX)
Packit 6c4009
		fprintf (fp, "SIGRTMAX (");
Packit 6c4009
	      else
Packit 6c4009
		fprintf (fp, "SIGRTMAX-%d (", SIGRTMAX - pinfo->si_signo);
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
#endif
Packit 6c4009
	fprintf (fp, "%s (", _(desc));
Packit 6c4009
Packit 6c4009
      const char *base = NULL;
Packit 6c4009
      const uint8_t *offarr = NULL;
Packit 6c4009
      size_t offarr_len = 0;
Packit 6c4009
      switch (pinfo->si_signo)
Packit 6c4009
	{
Packit 6c4009
#define H(sig) \
Packit 6c4009
	case sig:							      \
Packit 6c4009
	  base = C(codestrs_, sig).str;					      \
Packit 6c4009
	  offarr = C (codes_, sig);					      \
Packit 6c4009
	  offarr_len = array_length (C (codes_, sig));			      \
Packit 6c4009
	  break
Packit 6c4009
Packit 6c4009
	  H (SIGILL);
Packit 6c4009
	  H (SIGFPE);
Packit 6c4009
	  H (SIGSEGV);
Packit 6c4009
	  H (SIGBUS);
Packit 6c4009
	  H (SIGTRAP);
Packit 6c4009
	  H (SIGCHLD);
Packit 6c4009
	  H (SIGPOLL);
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      const char *str = NULL;
Packit 6c4009
      if (offarr != NULL
Packit 6c4009
	  && pinfo->si_code >= 1 && pinfo->si_code <= offarr_len)
Packit 6c4009
	str = base + offarr[pinfo->si_code - 1];
Packit 6c4009
      else
Packit 6c4009
	switch (pinfo->si_code)
Packit 6c4009
	  {
Packit 6c4009
	  case SI_USER:
Packit 6c4009
	    str = N_("Signal sent by kill()");
Packit 6c4009
	    break;
Packit 6c4009
	  case SI_QUEUE:
Packit 6c4009
	    str = N_("Signal sent by sigqueue()");
Packit 6c4009
	    break;
Packit 6c4009
	  case SI_TIMER:
Packit 6c4009
	    str = N_("Signal generated by the expiration of a timer");
Packit 6c4009
	    break;
Packit 6c4009
	  case SI_ASYNCIO:
Packit 6c4009
	    str = N_("\
Packit 6c4009
Signal generated by the completion of an asynchronous I/O request");
Packit 6c4009
	    break;
Packit 6c4009
	  case SI_MESGQ:
Packit 6c4009
	    str = N_("\
Packit 6c4009
Signal generated by the arrival of a message on an empty message queue");
Packit 6c4009
	    break;
Packit 6c4009
#ifdef SI_TKILL
Packit 6c4009
	  case SI_TKILL:
Packit 6c4009
	    str = N_("Signal sent by tkill()");
Packit 6c4009
	    break;
Packit 6c4009
#endif
Packit 6c4009
#ifdef SI_ASYNCNL
Packit 6c4009
	  case SI_ASYNCNL:
Packit 6c4009
	    str = N_("\
Packit 6c4009
Signal generated by the completion of an asynchronous name lookup request");
Packit 6c4009
	    break;
Packit 6c4009
#endif
Packit 6c4009
#ifdef SI_SIGIO
Packit 6c4009
	  case SI_SIGIO:
Packit 6c4009
	    str = N_("\
Packit 6c4009
Signal generated by the completion of an I/O request");
Packit 6c4009
	    break;
Packit 6c4009
#endif
Packit 6c4009
#ifdef SI_KERNEL
Packit 6c4009
	  case SI_KERNEL:
Packit 6c4009
	    str = N_("Signal sent by the kernel");
Packit 6c4009
	    break;
Packit 6c4009
#endif
Packit 6c4009
	  }
Packit 6c4009
Packit 6c4009
      if (str != NULL)
Packit 6c4009
	fprintf (fp, "%s ", _(str));
Packit 6c4009
      else
Packit 6c4009
	fprintf (fp, "%d ", pinfo->si_code);
Packit 6c4009
Packit 6c4009
      if (pinfo->si_signo == SIGILL || pinfo->si_signo == SIGFPE
Packit 6c4009
	  || pinfo->si_signo == SIGSEGV || pinfo->si_signo == SIGBUS)
Packit 6c4009
	fprintf (fp, "[%p])\n", pinfo->si_addr);
Packit 6c4009
      else if (pinfo->si_signo == SIGCHLD)
Packit 6c4009
	fprintf (fp, "%ld %d %ld)\n",
Packit 6c4009
		 (long int) pinfo->si_pid, pinfo->si_status,
Packit 6c4009
		 (long int) pinfo->si_uid);
Packit 6c4009
      else if (pinfo->si_signo == SIGPOLL)
Packit 6c4009
	fprintf (fp, "%ld)\n", (long int) pinfo->si_band);
Packit 6c4009
      else
Packit 6c4009
	fprintf (fp, "%ld %ld)\n",
Packit 6c4009
		 (long int) pinfo->si_pid, (long int) pinfo->si_uid);
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    fprintf (fp, _("Unknown signal %d\n"),  pinfo->si_signo);
Packit 6c4009
Packit 6c4009
  fclose (fp);
Packit 6c4009
Packit 6c4009
  __write_nocancel (STDERR_FILENO, buf, strlen (buf));
Packit 6c4009
}