libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 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, 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 00022 #include <libexplain/buffer/einval.h> 00023 #include <libexplain/buffer/errno/generic.h> 00024 #include <libexplain/buffer/errno/setpgid.h> 00025 #include <libexplain/buffer/esrch.h> 00026 #include <libexplain/buffer/gettext.h> 00027 #include <libexplain/buffer/pid_t_star.h> 00028 #include <libexplain/explanation.h> 00029 #include <libexplain/process_exists.h> 00030 00031 00032 static void 00033 explain_buffer_errno_setpgid_system_call(explain_string_buffer_t *sb, 00034 int errnum, pid_t pid, pid_t pgid) 00035 { 00036 (void)errnum; 00037 explain_string_buffer_puts(sb, "setpgid(pid = "); 00038 explain_buffer_pid_t(sb, pid); 00039 explain_string_buffer_puts(sb, ", pgid = "); 00040 explain_buffer_pid_t(sb, pgid); 00041 explain_string_buffer_putc(sb, ')'); 00042 } 00043 00044 00045 void 00046 explain_buffer_errno_setpgid_explanation(explain_string_buffer_t *sb, 00047 int errnum, const char *syscall_name, pid_t pid, pid_t pgid) 00048 { 00049 pid_t me; 00050 00051 me = getpid(); 00052 assert(me >= 1); 00053 if (!pid) 00054 pid = me; 00055 if (!pgid) 00056 pgid = pid; 00057 00058 /* 00059 * http://www.opengroup.org/onlinepubs/009695399/functions/setpgid.html 00060 */ 00061 switch (errnum) 00062 { 00063 case EACCES: 00064 explain_buffer_gettext 00065 ( 00066 sb, 00067 /* 00068 * xgettext: This error message is used to explain an EACCES 00069 * error reported by the setpgid(2) system call, in the case where 00070 * an attempt was made to change the process group ID of one of 00071 * the children of the calling process and the child had already 00072 * performed an execve(2). 00073 */ 00074 i18n("an attempt was made to change the process group ID of " 00075 "one of the children of the calling process and the " 00076 "child had already performed an execve(2)") 00077 ); 00078 break; 00079 00080 case EINVAL: 00081 if (pid < 0) 00082 { 00083 pid_too_small: 00084 explain_buffer_einval_too_small(sb, "pid", pid); 00085 break; 00086 } 00087 if (!explain_process_exists(pid)) 00088 { 00089 no_such_pid: 00090 explain_buffer_esrch(sb, "pid", pid); 00091 break; 00092 } 00093 if (pgid < 0) 00094 { 00095 pgid_too_small: 00096 explain_buffer_einval_too_small(sb, "pgid", pgid); 00097 break; 00098 } 00099 if (!explain_process_exists(pgid)) 00100 { 00101 no_such_pgid: 00102 explain_buffer_esrch(sb, "pgid", pgid); 00103 break; 00104 } 00105 goto generic; 00106 00107 case EPERM: 00108 { 00109 pid_t sid_of_me; 00110 pid_t sid_of_pid; 00111 pid_t sid_of_pgid; 00112 00113 /* 00114 * NOTE: while pgid values are usually process IDs, they 00115 * don't have to be. They can be zero, as is the case for 00116 * many processes spawned by the kernel itself. 00117 */ 00118 00119 sid_of_me = getsid(me); 00120 if (sid_of_me < 0) 00121 goto barf; 00122 00123 if (pid < 0) 00124 goto pid_too_small; 00125 sid_of_pid = getsid(pid); 00126 if (sid_of_pid < 0) 00127 { 00128 if (errno == ESRCH) 00129 goto no_such_pid; 00130 goto barf; 00131 } 00132 00133 if (pgid < 0) 00134 goto pgid_too_small; 00135 sid_of_pgid = getsid(pgid); 00136 if (sid_of_pgid < 0) 00137 { 00138 if (errno == ESRCH) 00139 goto no_such_pgid; 00140 goto barf; 00141 } 00142 00143 /* 00144 * You are not allowed to move a process into a process group in a 00145 * different session. 00146 */ 00147 if (sid_of_pid != sid_of_pgid) 00148 { 00149 explain_buffer_gettext 00150 ( 00151 sb, 00152 /* 00153 * xgettext: This error message is used to explain an 00154 * ESRCH error reported by a setpgid system call, in the 00155 * case where an attempt was made to move a process into a 00156 * process group in a different session. 00157 */ 00158 i18n("an attempt was made to move a process into a process " 00159 "group in a different session") 00160 ); 00161 break; 00162 } 00163 00164 /* 00165 * You are not allowed to change the process group ID of a 00166 * session leader. 00167 * 00168 * You can tell a process is a session group leader, because 00169 * the sid and the pid are the same. 00170 */ 00171 if (pid == sid_of_pid && pgid != pid) 00172 { 00173 explain_buffer_gettext 00174 ( 00175 sb, 00176 /* 00177 * xgettext: This error message is used to explain an ESRCH 00178 * error reported by a setpgid system call, in the case 00179 * where an attempt was made to change the process group ID 00180 * of a session leader 00181 */ 00182 i18n("an attempt was made to change the process group ID " 00183 "of a session leader") 00184 ); 00185 break; 00186 } 00187 00188 /* we have no way to tell */ 00189 barf: 00190 explain_buffer_gettext 00191 ( 00192 sb, 00193 /* 00194 * xgettext: This error message is used to explain an ESRCH 00195 * error reported by a setpgid system call, in the case where an 00196 * attempt was made to move a process into a process group in a 00197 * different session, or to change the process group ID of one 00198 * of the children of the calling process and the child was in 00199 * a different session, or to change the process group ID of a 00200 * session leader 00201 */ 00202 i18n("an attempt was made to move a process into a process " 00203 "group in a different session, or to change the process " 00204 "group ID of one of the children of the calling process " 00205 "and the child was in a different session, or to change " 00206 "the process group ID of a session leader") 00207 ); 00208 } 00209 break; 00210 00211 case ESRCH: 00212 if (pid < 0) 00213 goto pid_too_small; 00214 if (!explain_process_exists(pid)) 00215 goto no_such_pid; 00216 if (pgid < 0) 00217 goto pgid_too_small; 00218 if (!explain_process_exists(pgid)) 00219 goto no_such_pgid; 00220 00221 if (pid != me) 00222 { 00223 explain_buffer_gettext 00224 ( 00225 sb, 00226 /* 00227 * xgettext: This error message is used to explain an ESRCH 00228 * error reported by the setpgid system call, in the case where 00229 * pid is not the calling process and not a child of the calling 00230 * process. 00231 */ 00232 i18n("pid is not the calling process and not a child of " 00233 "the calling process") 00234 ); 00235 break; 00236 } 00237 goto generic; 00238 00239 default: 00240 generic: 00241 explain_buffer_errno_generic(sb, errnum, syscall_name); 00242 break; 00243 } 00244 } 00245 00246 00247 void 00248 explain_buffer_errno_setpgid(explain_string_buffer_t *sb, int errnum, pid_t pid, 00249 pid_t pgid) 00250 { 00251 explain_explanation_t exp; 00252 00253 explain_explanation_init(&exp, errnum); 00254 explain_buffer_errno_setpgid_system_call(&exp.system_call_sb, errnum, pid, 00255 pgid); 00256 explain_buffer_errno_setpgid_explanation(&exp.explanation_sb, errnum, 00257 "setpgid", pid, pgid); 00258 explain_explanation_assemble(&exp, sb); 00259 } 00260 00261 00262 /* vim: set ts=8 sw=4 et : */