libexplain  1.4.D001
libexplain/buffer/errno/setpriority.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2013, 2014 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, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
00013  * 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/assert.h>
00020 #include <libexplain/ac/errno.h>
00021 #include <libexplain/ac/sys/resource.h>
00022 #include <libexplain/ac/unistd.h>
00023 
00024 #include <libexplain/buffer/dac.h>
00025 #include <libexplain/buffer/eacces.h>
00026 #include <libexplain/buffer/einval.h>
00027 #include <libexplain/buffer/eperm.h>
00028 #include <libexplain/buffer/eperm.h>
00029 #include <libexplain/buffer/errno/generic.h>
00030 #include <libexplain/buffer/errno/setpriority.h>
00031 #include <libexplain/buffer/esrch.h>
00032 #include <libexplain/buffer/int.h>
00033 #include <libexplain/buffer/pid_t_star.h>
00034 #include <libexplain/buffer/prio_which.h>
00035 #include <libexplain/buffer/uid.h>
00036 #include <libexplain/explanation.h>
00037 #include <libexplain/option.h>
00038 #include <libexplain/uid_from_pid.h>
00039 
00040 
00041 static void
00042 explain_buffer_errno_setpriority_system_call(explain_string_buffer_t *sb, int
00043     errnum, int which, int who, int prio)
00044 {
00045     (void)errnum;
00046     explain_string_buffer_puts(sb, "setpriority(which = ");
00047     explain_buffer_prio_which(sb, which);
00048     explain_string_buffer_puts(sb, ", who = ");
00049     switch (which)
00050     {
00051     case PRIO_PROCESS:
00052     case PRIO_PGRP:
00053         explain_buffer_pid_t(sb, who);
00054         break;
00055 
00056     case PRIO_USER:
00057         explain_buffer_uid(sb, who);
00058         break;
00059 
00060     default:
00061         explain_buffer_int(sb, who);
00062         break;
00063     }
00064     explain_string_buffer_puts(sb, ", prio = ");
00065     explain_buffer_int(sb, prio);
00066     explain_string_buffer_putc(sb, ')');
00067 }
00068 
00069 
00070 void
00071 explain_buffer_errno_setpriority_explanation(explain_string_buffer_t *sb, int
00072     errnum, const char *syscall_name, int which, int who, int prio)
00073 {
00074     (void)prio;
00075     switch (errnum)
00076     {
00077     case EINVAL:
00078         /*
00079          * which was not one of PRIO_PROCESS, PRIO_PGRP, or PRIO_USER.
00080          */
00081         explain_buffer_einval_vague(sb, "which");
00082         goto generic;
00083 
00084     case ESRCH:
00085         /*
00086          * No process was located using the which and who values specified.
00087          */
00088         switch (which)
00089         {
00090         case PRIO_PROCESS:
00091             explain_buffer_esrch(sb, "who", who);
00092             break;
00093 
00094         case PRIO_PGRP:
00095             explain_buffer_esrch(sb, "who", (who < 0 ? who : -who));
00096             break;
00097 
00098         case PRIO_USER:
00099             explain_string_buffer_puts
00100             (
00101                 sb,
00102                 /* FIXME:i18n */
00103                 "no process owned by who uid was found"
00104             );
00105             break;
00106 
00107         default:
00108             goto generic;
00109         }
00110         break;
00111 
00112     case EACCES:
00113         /*
00114          * The caller attempted to lower a process priority, but did
00115          * not have the required privilege (on Linux: did not have the
00116          * CAP_SYS_NICE capability).  Since Linux 2.6.12, this error
00117          * only occurs if the caller attempts to set a process priority
00118          * outside the range of the RLIMIT_NICE soft resource limit of
00119          * the target process; see getrlimit(2) for details.
00120          */
00121         explain_string_buffer_puts
00122         (
00123             sb,
00124             /* FIXME: i18n */
00125             "the caller attempted to lower a process priority"
00126         );
00127         if (explain_option_dialect_specific())
00128         {
00129             /*
00130              * Since Linux 2.6.12,
00131              * this error only occurs if the caller attempts to set a
00132              * process priority outside the range of the RLIMIT_NICE soft
00133              * resource limit of the target process; see getrlimit(2) for
00134              * details
00135              */
00136             struct rlimit rlim;
00137 
00138 #ifdef RLIMIT_NICE
00139             if (getrlimit(RLIMIT_NICE, &rlim) >= 0)
00140             {
00141                 int cur = 20 - rlim.rlim_cur;
00142                 explain_string_buffer_printf(sb, " (%d < %d)", prio, cur);
00143             }
00144 #endif
00145         }
00146         explain_buffer_dac_sys_nice(sb);
00147         break;
00148 
00149     case EPERM:
00150         /*
00151          * A process was located, but its effective user ID did not
00152          * match either the effective or the real user ID of the
00153          * caller, and was not privileged (on Linux: did not have the
00154          * CAP_SYS_NICE capability).
00155          */
00156         explain_string_buffer_puts
00157         (
00158             sb,
00159             /* FIXME: i18n */
00160             "a suitable process was located, but its effective user ID did not "
00161             "match the effective user ID of this process"
00162         );
00163 
00164         /* suplementary */
00165         switch (which)
00166         {
00167         case PRIO_PROCESS:
00168         case PRIO_PGRP:
00169             /* in this context "who" is a pid_t */
00170             if (explain_option_dialect_specific())
00171             {
00172                 int the_other_guy = explain_uid_from_pid(who);
00173                 if (the_other_guy != (pid_t)-1)
00174                 {
00175                     explain_string_buffer_puts(sb, " (");
00176                     explain_buffer_uid(sb, the_other_guy);
00177                     explain_string_buffer_puts(sb, " != ");
00178                     explain_buffer_uid(sb, geteuid());
00179                     explain_string_buffer_putc(sb, ')');
00180                 }
00181             }
00182             break;
00183 
00184         case PRIO_USER:
00185             /* in this context "who" is a uid_t */
00186             if (explain_option_dialect_specific())
00187             {
00188                 explain_string_buffer_puts(sb, " (");
00189                 explain_buffer_uid(sb, who);
00190                 explain_string_buffer_puts(sb, " != ");
00191                 explain_buffer_uid(sb, geteuid());
00192                 explain_string_buffer_putc(sb, ')');
00193             }
00194             break;
00195 
00196         default:
00197             /* Huh? */
00198             assert(!"this should have thrown an EINVAL error");
00199             break;
00200         }
00201         explain_buffer_dac_sys_nice(sb);
00202         break;
00203 
00204     default:
00205         generic:
00206         explain_buffer_errno_generic(sb, errnum, syscall_name);
00207         break;
00208     }
00209 }
00210 
00211 
00212 void
00213 explain_buffer_errno_setpriority(explain_string_buffer_t *sb, int errnum, int
00214     which, int who, int prio)
00215 {
00216     explain_explanation_t exp;
00217 
00218     explain_explanation_init(&exp, errnum);
00219     explain_buffer_errno_setpriority_system_call(&exp.system_call_sb, errnum,
00220         which, who, prio);
00221     explain_buffer_errno_setpriority_explanation(&exp.explanation_sb, errnum,
00222         "setpriority", which, who, prio);
00223     explain_explanation_assemble(&exp, sb);
00224 }
00225 
00226 
00227 /* vim: set ts=8 sw=4 et : */