libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2009, 2010, 2012, 2013 Peter Miller 00004 * Written by Peter Miller <pmiller@opensource.org.au> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as 00008 * published by the Free Software Foundation; either version 3 of the 00009 * License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include <libexplain/ac/stdlib.h> 00021 00022 #include <libexplain/exit.h> 00023 #include <libexplain/option.h> 00024 #include <libexplain/program_name.h> 00025 #include <libexplain/string_buffer.h> 00026 #include <libexplain/wrap_and_print.h> 00027 00028 00029 /* 00030 * All ANSI C compliant system provide atexit, 00031 * but on_exit is a GNU glibc invention, 00032 * and a very useful one. 00033 */ 00034 #ifdef HAVE_ON_EXIT 00035 00036 enum action_t 00037 { 00038 action_never, 00039 action_error, 00040 action_always, 00041 }; 00042 00043 static int registered; 00044 static enum action_t action = action_never; 00045 00046 00047 static void 00048 grim_reaper(int es, void *aux) 00049 { 00050 es &= 255; 00051 (void)aux; 00052 switch (action) 00053 { 00054 default: 00055 case action_never: 00056 break; 00057 00058 case action_error: 00059 if (es == EXIT_SUCCESS) 00060 break; 00061 /* fall through... */ 00062 00063 case action_always: 00064 { 00065 explain_string_buffer_t sb; 00066 char text[1000]; 00067 00068 explain_string_buffer_init(&sb, text, sizeof(text)); 00069 00070 if (explain_option_assemble_program_name()) 00071 { 00072 const char *prog; 00073 00074 prog = explain_program_name_get(); 00075 if (prog && *prog) 00076 { 00077 explain_string_buffer_puts(&sb, prog); 00078 explain_string_buffer_puts(&sb, ": "); 00079 } 00080 } 00081 00082 explain_string_buffer_puts(&sb, "exit status "); 00083 switch (es) 00084 { 00085 case EXIT_SUCCESS: 00086 explain_string_buffer_puts(&sb, "EXIT_SUCCESS"); 00087 break; 00088 00089 case EXIT_FAILURE: 00090 explain_string_buffer_puts(&sb, "EXIT_FAILURE"); 00091 break; 00092 00093 default: 00094 explain_string_buffer_printf(&sb, "EXIT_FAILURE (%d)", es); 00095 break; 00096 } 00097 00098 explain_wrap_and_print(stderr, text); 00099 } 00100 break; 00101 } 00102 } 00103 00104 00105 static void 00106 install_grim_reaper(void) 00107 { 00108 if (!registered) 00109 { 00110 registered = 1; 00111 on_exit(grim_reaper, 0); 00112 } 00113 } 00114 00115 #endif 00116 00117 void 00118 explain_exit_on_exit(void) 00119 { 00120 #ifdef HAVE_ON_EXIT 00121 action = action_always; 00122 install_grim_reaper(); 00123 #endif 00124 } 00125 00126 00127 void 00128 explain_exit_on_error(void) 00129 { 00130 #ifdef HAVE_ON_EXIT 00131 action = action_error; 00132 install_grim_reaper(); 00133 #endif 00134 } 00135 00136 00137 void 00138 explain_exit_cancel(void) 00139 { 00140 #ifdef HAVE_ON_EXIT 00141 /* 00142 * If grim reaper is not already installed, there is no need to do 00143 * it now, because the result of installing it would be the same as 00144 * not installing it. 00145 */ 00146 action = action_never; 00147 #endif 00148 } 00149 00150 00151 /* vim: set ts=8 sw=4 et : */