libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008, 2009, 2011, 2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify it 00006 * under the terms of the GNU Lesser General Public License as published by 00007 * the Free Software Foundation; either version 3 of the License, or (at 00008 * your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <libexplain/ac/errno.h> 00020 #include <libexplain/ac/signal.h> 00021 #include <libexplain/ac/sys/wait.h> 00022 #include <libexplain/ac/unistd.h> 00023 00024 #include <libexplain/buffer/efault.h> 00025 #include <libexplain/buffer/eintr.h> 00026 #include <libexplain/buffer/einval.h> 00027 #include <libexplain/buffer/errno/generic.h> 00028 #include <libexplain/buffer/errno/waitpid.h> 00029 #include <libexplain/buffer/gettext.h> 00030 #include <libexplain/buffer/no_outstanding_children.h> 00031 #include <libexplain/buffer/note/sigchld.h> 00032 #include <libexplain/buffer/pid_t_star.h> 00033 #include <libexplain/buffer/pointer.h> 00034 #include <libexplain/buffer/waitpid_options.h> 00035 #include <libexplain/explanation.h> 00036 #include <libexplain/process_exists.h> 00037 00038 00039 static void 00040 explain_buffer_errno_waitpid_system_call(explain_string_buffer_t *sb, 00041 int errnum, int pid, int *status, int options) 00042 { 00043 (void)errnum; 00044 explain_string_buffer_puts(sb, "waitpid(pid = "); 00045 explain_buffer_pid_t(sb, pid); 00046 if (pid == 0) 00047 { 00048 explain_string_buffer_puts(sb, " = process group "); 00049 explain_buffer_pid_t(sb, getpgrp()); 00050 } 00051 else if (pid < -1) 00052 { 00053 explain_string_buffer_puts(sb, " = process group "); 00054 explain_buffer_pid_t(sb, -pid); 00055 } 00056 explain_string_buffer_puts(sb, ", status = "); 00057 explain_buffer_pointer(sb, status); 00058 explain_string_buffer_puts(sb, ", options = "); 00059 explain_buffer_waitpid_options(sb, options); 00060 explain_string_buffer_putc(sb, ')'); 00061 } 00062 00063 00064 void 00065 explain_buffer_errno_waitpid_explanation(explain_string_buffer_t *sb, 00066 int errnum, const char *syscall_name, int pid, int *status, int options) 00067 { 00068 /* 00069 * http://www.opengroup.org/onlinepubs/009695399/functions/waitpid.html 00070 */ 00071 (void)status; 00072 switch (errnum) 00073 { 00074 case ECHILD: 00075 if (pid > 0) 00076 { 00077 if (explain_process_exists(pid)) 00078 { 00079 explain_string_buffer_printf_gettext 00080 ( 00081 sb, 00082 /* 00083 * xgettext: This message is use when a wait*() 00084 * function is asked to wait for a process that is 00085 * not a child of the process. 00086 * 00087 * %1$s => the name of the offending system call argument 00088 */ 00089 i18n("the process specified by %s is not a child of " 00090 "this process"), 00091 "pid" 00092 ); 00093 } 00094 else 00095 { 00096 explain_string_buffer_printf_gettext 00097 ( 00098 sb, 00099 /* 00100 * xgettext: This message is use when a wait*() 00101 * function is asked to wait for a process that does 00102 * not exist. 00103 * 00104 * %1$s => the name of the offending system call argument 00105 */ 00106 i18n("the process specified by %s does not exist"), 00107 "pid" 00108 ); 00109 } 00110 } 00111 else if (pid == -1) 00112 { 00113 explain_buffer_no_outstanding_children(sb); 00114 } 00115 else 00116 { 00117 int pgid; 00118 00119 pgid = pid ? -pid : getpgrp(); 00120 if (explain_process_exists(pid)) 00121 { 00122 explain_string_buffer_printf_gettext 00123 ( 00124 sb, 00125 /* 00126 * xgettext: This message is used when a wait*() 00127 * function was called to wait for a process group 00128 * that does not have any member process that is a 00129 * child of this process. 00130 * 00131 * %1$d => is the process group number. 00132 */ 00133 i18n("process group %d does not have any member process " 00134 "that is a child of this process"), 00135 pgid 00136 ); 00137 } 00138 else 00139 { 00140 explain_string_buffer_printf_gettext 00141 ( 00142 sb, 00143 /* 00144 * xgettext: This message is used when a wait*() 00145 * function was called to wait for a process group 00146 * that does not exist. 00147 * 00148 * %1$d => the process group number. 00149 */ 00150 i18n("process group %d does not exist"), 00151 pgid 00152 ); 00153 } 00154 } 00155 explain_buffer_note_sigchld(sb); 00156 break; 00157 00158 case EFAULT: 00159 explain_buffer_efault(sb, "status"); 00160 break; 00161 00162 case EINTR: 00163 /* 00164 * WNOHANG was not set and an unblocked signal or a SIGCHLD was 00165 * caught. 00166 */ 00167 explain_buffer_eintr(sb, syscall_name); 00168 break; 00169 00170 case EINVAL: 00171 explain_buffer_einval_bits(sb, "options"); 00172 explain_string_buffer_printf 00173 ( 00174 sb, 00175 " (%#x)", 00176 options & ~(WCONTINUED | WNOHANG | WUNTRACED) 00177 ); 00178 break; 00179 00180 default: 00181 explain_buffer_errno_generic(sb, errnum, syscall_name); 00182 break; 00183 } 00184 } 00185 00186 00187 void 00188 explain_buffer_errno_waitpid(explain_string_buffer_t *sb, int errnum, 00189 int pid, int *status, int options) 00190 { 00191 explain_explanation_t exp; 00192 00193 explain_explanation_init(&exp, errnum); 00194 explain_buffer_errno_waitpid_system_call 00195 ( 00196 &exp.system_call_sb, 00197 errnum, 00198 pid, 00199 status, 00200 options 00201 ); 00202 explain_buffer_errno_waitpid_explanation 00203 ( 00204 &exp.explanation_sb, 00205 errnum, 00206 "waitpid", 00207 pid, 00208 status, 00209 options 00210 ); 00211 explain_explanation_assemble(&exp, sb); 00212 } 00213 00214 00215 /* vim: set ts=8 sw=4 et : */