libexplain  1.4.D001
libexplain/buffer/errno/waitpid.c
Go to the documentation of this file.
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 : */