"Fossies" - the Fresh Open Source Software Archive

Member "xorriso-1.5.4/libburn/cleanup.c" (30 Jan 2021, 5946 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "cleanup.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  cleanup.c , Copyright 2006 - 2011 Thomas Schmitt <scdbackup@gmx.net>
    3 
    4  A signal handler which cleans up an application and exits.
    5 
    6  Provided under GPLv2+ license within GPL projects, BSD license elsewise.
    7 */
    8 
    9 /*
   10  cc -g -o cleanup -DCleanup_standalonE cleanup.c
   11 */
   12 
   13 #ifdef HAVE_CONFIG_H
   14 #include "../config.h"
   15 #endif
   16 
   17 #include <sys/types.h>
   18 #include <stdlib.h>
   19 #include <unistd.h>
   20 #include <stdio.h>
   21 #include <string.h>
   22 #include <errno.h>
   23 
   24 #include <signal.h>
   25 typedef void (*sighandler_t)(int);
   26 
   27 
   28 #include "cleanup.h"
   29 
   30 
   31 #ifndef Cleanup_has_no_libburn_os_H
   32 
   33 
   34 #include "../libburn/os.h"
   35 
   36 /* see os.h for name of particular os-*.h where this is defined */
   37 static int signal_list[]=        { BURN_OS_SIGNAL_MACRO_LIST , -1};
   38 static char *signal_name_list[]= { BURN_OS_SIGNAL_NAME_LIST , "@"};
   39 static int signal_list_count=      BURN_OS_SIGNAL_COUNT;
   40 static int non_signal_list[]=    { BURN_OS_NON_SIGNAL_MACRO_LIST, -1};
   41 static int non_signal_list_count=  BURN_OS_NON_SIGNAL_COUNT;
   42 
   43 
   44 #else /* ! Cleanup_has_no_libburn_os_H */
   45 
   46 
   47 /* Outdated. GNU/Linux only.
   48    For backward compatibility with pre-libburn-0.2.3 */
   49 
   50 /* Signals to be caught */
   51 static int signal_list[]= {
   52  SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
   53  SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
   54  SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
   55  SIGTTOU,
   56  SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP,
   57  SIGVTALRM, SIGXCPU, SIGXFSZ, -1
   58 };
   59 static char *signal_name_list[]= {
   60  "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
   61  "SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
   62  "SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
   63  "SIGTTOU",
   64  "SIGBUS", "SIGPOLL", "SIGPROF", "SIGSYS", "SIGTRAP",
   65  "SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@"
   66 };
   67 static int signal_list_count= 24;
   68 
   69 /* Signals not to be caught */
   70 static int non_signal_list[]= {
   71   SIGKILL, SIGCHLD, SIGSTOP, SIGCONT, SIGURG, SIGWINCH, -1
   72 };
   73 static int non_signal_list_count= 6;
   74 
   75 
   76 #endif /* Cleanup_has_no_libburn_os_H */
   77 
   78 
   79 
   80 /* run time dynamic part */
   81 static char cleanup_msg[4096]= {""};
   82 static int cleanup_exiting= 0;
   83 static int cleanup_has_reported= -1234567890;
   84 
   85 static void *cleanup_app_handle= NULL;
   86 static Cleanup_app_handler_T cleanup_app_handler= NULL;
   87 static int cleanup_perform_app_handler_first= 0;
   88 
   89 
   90 static int Cleanup_handler_exit(int exit_value, int signum, int flag)
   91 {
   92  int ret;
   93 
   94  if(cleanup_msg[0]!=0 && cleanup_has_reported!=signum) {
   95    fprintf(stderr,"\n%s\n",cleanup_msg);
   96    cleanup_has_reported= signum;
   97  }
   98  if(cleanup_perform_app_handler_first)
   99    if(cleanup_app_handler!=NULL) {
  100      ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
  101      if(ret==2 || ret==-2)
  102        return(2);
  103    }
  104  if(cleanup_exiting) {
  105    fprintf(stderr,"cleanup: ABORT : repeat by pid=%.f, signum=%d\n",
  106            (double) getpid(), signum);
  107    return(0);
  108  }
  109  cleanup_exiting= 1;
  110  alarm(0);
  111  if(!cleanup_perform_app_handler_first)
  112    if(cleanup_app_handler!=NULL) {
  113      ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0); 
  114      if(ret==2 || ret==-2)
  115        return(2);
  116    }
  117  exit(exit_value);
  118 }  
  119 
  120 
  121 static void Cleanup_handler_generic(int signum)
  122 {
  123  int i;
  124 
  125  sprintf(cleanup_msg,"UNIX-SIGNAL caught:  %d  errno= %d",signum,errno);
  126  for(i= 0; i<signal_list_count; i++) 
  127    if(signum==signal_list[i]) {
  128      sprintf(cleanup_msg,"UNIX-SIGNAL:  %s  errno= %d",
  129              signal_name_list[i],errno);
  130  break;
  131    }
  132  Cleanup_handler_exit(1,signum,0);
  133 }
  134 
  135 
  136 static char *Cleanup_signo_to_name(int signo)
  137 {
  138  int i;
  139  for(i= 0; i < signal_list_count; i++)
  140    if(signal_list[i] == signo)
  141      return(signal_name_list[i]);
  142  return("");
  143 }
  144 
  145 
  146 int Cleanup_set_handlers(void *handle, Cleanup_app_handler_T handler, int flag)
  147 /*
  148  bit0= set to default handlers
  149  bit1= set to ignore
  150  bit2= set cleanup_perform_app_handler_first
  151  bit3= set SIGABRT to handler (makes sense with bits 0 or 1)
  152  bit8= set SIGPIPE to SIGIGN
  153 */
  154 {
  155  int i,j,max_sig= -1,min_sig= 0x7fffffff;
  156  char *sig_name;
  157  sighandler_t sig_handler;
  158 
  159  cleanup_msg[0]= 0;
  160  cleanup_app_handle= handle;
  161  cleanup_app_handler= handler;
  162 
  163  /* <<< make cleanup_exiting thread safe to get rid of this */
  164  if(flag&4)
  165    cleanup_perform_app_handler_first= 1;
  166 
  167 
  168  if(flag&1)
  169    sig_handler= SIG_DFL;
  170  else if(flag&2)
  171    sig_handler= SIG_IGN;
  172  else
  173    sig_handler= Cleanup_handler_generic;
  174  /* set all signal numbers between the lowest and highest in the list
  175     except those in the non-signal list */
  176  for(i= 0; i<signal_list_count; i++) {
  177    if(signal_list[i]>max_sig)
  178      max_sig= signal_list[i];
  179    if(signal_list[i]<min_sig)
  180      min_sig= signal_list[i];
  181  }
  182  for(i= min_sig; i<=max_sig; i++) {
  183    for(j= 0; j<non_signal_list_count; j++)
  184      if(i==non_signal_list[j])
  185    break;
  186    if(j>=non_signal_list_count) {
  187      /* Avoid to use particular SIG macros which might not be defined.
  188         If they are defined, then their names are in the name list.
  189      */
  190      if(flag & (8 | 256))
  191        sig_name= Cleanup_signo_to_name(i);
  192      else
  193        sig_name= "";
  194      if((flag & 8) && strcmp(sig_name, "SIGABRT") == 0)
  195        signal(i,Cleanup_handler_generic);
  196      else if((flag & 256) && strcmp(sig_name, "SIGPIPE") == 0)
  197        signal(i, SIG_IGN);
  198      else
  199        signal(i,sig_handler);
  200    }
  201  }
  202  return(1);
  203 }
  204 
  205 
  206 #ifdef Cleanup_standalonE
  207 
  208 struct Demo_apP {
  209  char *msg;
  210 };
  211 
  212 
  213 int Demo_app_handler(struct Demo_apP *demoapp, int signum, int flag)
  214 {
  215  printf("Handling exit of demo application on signal %d. msg=\"%s\"\n",
  216         signum,demoapp->msg);
  217  return(1);
  218 }
  219 
  220 
  221 main()
  222 {
  223  struct Demo_apP demoapp;
  224 
  225  demoapp.msg= "Good Bye";
  226  Cleanup_set_handlers(&demoapp,(Cleanup_app_handler_T) Demo_app_handler,0);
  227 
  228  if(1) { /* change to 0 in order to wait for external signals */
  229    char *cpt= NULL, c= ' ';
  230    printf("Intentionally provoking SIGSEGV ...\n");
  231    c= *cpt;
  232    printf("Strange: The system ignored a SIGSEGV: c= %u\n", (unsigned int) c);
  233  } else {
  234    printf("killme: %d\n",getpid());
  235    sleep(3600);
  236  }
  237 
  238  Cleanup_set_handlers(NULL,NULL,1);
  239  exit(0);
  240 }
  241 
  242 #endif /* Cleanup_standalonE */