}
void
-sudo_debug_write(const char *str, int len)
+sudo_debug_write(const char *str, int len, int errno_val)
{
char *timestr;
time_t now;
- struct iovec iov[5];
+ struct iovec iov[7];
int iovcnt = 4;
+ bool need_newline = false;
if (len <= 0)
return;
case SUDO_DEBUG_MODE_CONV:
/* Call conversation function */
if (sudo_conv != NULL) {
- struct sudo_conv_message msg;
- struct sudo_conv_reply repl;
-
- memset(&msg, 0, sizeof(msg));
- memset(&repl, 0, sizeof(repl));
- msg.msg_type = SUDO_CONV_DEBUG_MSG;
- msg.msg = str;
- sudo_conv(1, &msg, &repl);
+ struct sudo_conv_message msg[3];
+ struct sudo_conv_reply repl[3];
+ int msgcnt = 1;
+
+ memset(msg, 0, sizeof(msg));
+ memset(repl, 0, sizeof(repl));
+ msg[0].msg_type = SUDO_CONV_DEBUG_MSG;
+ msg[0].msg = str;
+ if (errno_val) {
+ msgcnt = 3;
+ msg[1].msg_type = SUDO_CONV_DEBUG_MSG;
+ msg[1].msg = ": ";
+ msg[2].msg_type = SUDO_CONV_DEBUG_MSG;
+ msg[2].msg = strerror(errno_val);
+ }
+ sudo_conv(msgcnt, msg, repl);
}
break;
case SUDO_DEBUG_MODE_FILE:
/* Add string along with newline if it doesn't have one. */
iov[3].iov_base = (char *)str;
iov[3].iov_len = len;
- if (str[len - 1] != '\n') {
+ if (str[len - 1] != '\n')
+ need_newline = true;
+
+ /* Append error string if errno is specified. */
+ if (errno_val) {
+ iov[iovcnt].iov_base = ": ";
+ iov[iovcnt].iov_len = 2;
+ iovcnt++;
+ iov[iovcnt].iov_base = strerror(errno_val);
+ iov[iovcnt].iov_len = strlen(iov[iovcnt].iov_base);
+ iovcnt++;
+
+ /* Move newline to the end. */
+ if (!need_newline) {
+ need_newline = true;
+ iov[3].iov_len--;
+ }
+ }
+
+ /* Append newline as needed. */
+ if (need_newline) {
/* force newline */
- iov[4].iov_base = "\n";
- iov[4].iov_len = 1;
+ iov[iovcnt].iov_base = "\n";
+ iov[iovcnt].iov_len = 1;
iovcnt++;
}
void
sudo_debug_printf2(int level, const char *fmt, ...)
{
- int buflen, pri, subsys;
+ int buflen, pri, subsys, saved_errno = errno;
va_list ap;
char *buf;
subsys = SUDO_DEBUG_SUBSYS(level);
/* Make sure we want debug info at this level. */
- if (subsys >= NUM_SUBSYSTEMS || sudo_debug_settings[subsys] < pri)
- return;
-
- va_start(ap, fmt);
- buflen = vasprintf(&buf, fmt, ap);
- va_end(ap);
- if (buflen != -1) {
- sudo_debug_write(buf, buflen);
- free(buf);
+ if (subsys < NUM_SUBSYSTEMS && sudo_debug_settings[subsys] >= pri) {
+ va_start(ap, fmt);
+ buflen = vasprintf(&buf, fmt, ap);
+ va_end(ap);
+ if (buflen != -1) {
+ if (ISSET(level, SUDO_DEBUG_ERRNO))
+ sudo_debug_write(buf, buflen, saved_errno);
+ else
+ sudo_debug_write(buf, buflen, 0);
+ free(buf);
+ }
}
+
+ errno = saved_errno;
}
void
*cp = '\0';
- sudo_debug_write(buf, buflen);
+ sudo_debug_write(buf, buflen, 0);
free(buf);
}
#else /* SUDO_ERROR_WRAP */
# if defined(__GNUC__) && __GNUC__ == 2
# define error(rval, fmt...) do { \
- sudo_debug_printf2(SUDO_DEBUG_ERROR|sudo_debug_subsys, (fmt)); \
+ sudo_debug_printf2(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|sudo_debug_subsys, (fmt));\
error2((rval), (fmt)); \
} while (0)
# define errorx(rval, fmt...) do { \
errorx2((rval), (fmt)); \
} while (0)
# define warning(fmt...) do { \
- sudo_debug_printf2(SUDO_DEBUG_ERROR|sudo_debug_subsys, (fmt)); \
+ sudo_debug_printf2(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|sudo_debug_subsys, (fmt));\
warning2((fmt)); \
} while (0)
# define warningx(fmt...) do { \
} while (0)
# else
# define error(rval, ...) do { \
- sudo_debug_printf2(SUDO_DEBUG_ERROR|sudo_debug_subsys, __VA_ARGS__); \
+ sudo_debug_printf2(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|sudo_debug_subsys, __VA_ARGS__);\
error2((rval), __VA_ARGS__); \
} while (0)
# define errorx(rval, ...) do { \
errorx2((rval), __VA_ARGS__); \
} while (0)
# define warning(...) do { \
- sudo_debug_printf2(SUDO_DEBUG_ERROR|sudo_debug_subsys, __VA_ARGS__); \
+ sudo_debug_printf2(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|sudo_debug_subsys, __VA_ARGS__);\
warning2(__VA_ARGS__); \
} while (0)
# define warningx(...) do { \
/*
* The priority and subsystem are encoded in a single 32-bit value.
- * The lower 4 bits are the priority and the top 28 bits are the subsystem.
+ * The lower 4 bits are the priority and the top 27 bits are the subsystem.
* This allows for 16 priorities and a very large number of subsystems.
+ * Bit 5 is used as a flag to specify whether to log the errno value.
*/
/*
* This includes subsystems in the sudoers plugin.
* Note: order must match sudo_debug_subsystems[]
*/
-#define SUDO_DEBUG_MAIN (1<<4) /* sudo main() */
-#define SUDO_DEBUG_ARGS (2<<4) /* command line argument processing */
-#define SUDO_DEBUG_EXEC (3<<4) /* command execution */
-#define SUDO_DEBUG_PTY (4<<4) /* pseudo-tty */
-#define SUDO_DEBUG_UTMP (5<<4) /* utmp file ops */
-#define SUDO_DEBUG_CONV (6<<4) /* user conversation */
-#define SUDO_DEBUG_PCOMM (7<<4) /* plugin communications */
-#define SUDO_DEBUG_UTIL (8<<4) /* utility functions */
-#define SUDO_DEBUG_NETIF (9<<4) /* network interface functions */
-#define SUDO_DEBUG_AUDIT (10<<4) /* audit */
-#define SUDO_DEBUG_EDIT (11<<4) /* sudoedit */
-#define SUDO_DEBUG_SELINUX (12<<4) /* selinux */
-#define SUDO_DEBUG_LDAP (13<<4) /* sudoers LDAP */
-#define SUDO_DEBUG_MATCH (14<<4) /* sudoers matching */
-#define SUDO_DEBUG_PARSER (15<<4) /* sudoers parser */
-#define SUDO_DEBUG_ALIAS (16<<4) /* sudoers alias functions */
-#define SUDO_DEBUG_DEFAULTS (17<<4) /* sudoers defaults settings */
-#define SUDO_DEBUG_AUTH (18<<4) /* authentication functions */
-#define SUDO_DEBUG_ENV (19<<4) /* environment handling */
-#define SUDO_DEBUG_LOGGING (20<<4) /* logging functions */
-#define SUDO_DEBUG_NSS (21<<4) /* network service switch */
-#define SUDO_DEBUG_RBTREE (22<<4) /* red-black tree functions */
-#define SUDO_DEBUG_PERMS (23<<4) /* uid/gid swapping functions */
-#define SUDO_DEBUG_PLUGIN (24<<4) /* main plugin functions */
-#define SUDO_DEBUG_HOOKS (25<<4) /* hook functions */
+#define SUDO_DEBUG_MAIN ( 1<<5) /* sudo main() */
+#define SUDO_DEBUG_ARGS ( 2<<5) /* command line argument processing */
+#define SUDO_DEBUG_EXEC ( 3<<5) /* command execution */
+#define SUDO_DEBUG_PTY ( 4<<5) /* pseudo-tty */
+#define SUDO_DEBUG_UTMP ( 5<<5) /* utmp file ops */
+#define SUDO_DEBUG_CONV ( 6<<5) /* user conversation */
+#define SUDO_DEBUG_PCOMM ( 7<<5) /* plugin communications */
+#define SUDO_DEBUG_UTIL ( 8<<5) /* utility functions */
+#define SUDO_DEBUG_NETIF ( 9<<5) /* network interface functions */
+#define SUDO_DEBUG_AUDIT (10<<5) /* audit */
+#define SUDO_DEBUG_EDIT (11<<5) /* sudoedit */
+#define SUDO_DEBUG_SELINUX (12<<5) /* selinux */
+#define SUDO_DEBUG_LDAP (13<<5) /* sudoers LDAP */
+#define SUDO_DEBUG_MATCH (14<<5) /* sudoers matching */
+#define SUDO_DEBUG_PARSER (15<<5) /* sudoers parser */
+#define SUDO_DEBUG_ALIAS (16<<5) /* sudoers alias functions */
+#define SUDO_DEBUG_DEFAULTS (17<<5) /* sudoers defaults settings */
+#define SUDO_DEBUG_AUTH (18<<5) /* authentication functions */
+#define SUDO_DEBUG_ENV (19<<5) /* environment handling */
+#define SUDO_DEBUG_LOGGING (20<<5) /* logging functions */
+#define SUDO_DEBUG_NSS (21<<5) /* network service switch */
+#define SUDO_DEBUG_RBTREE (22<<5) /* red-black tree functions */
+#define SUDO_DEBUG_PERMS (23<<5) /* uid/gid swapping functions */
+#define SUDO_DEBUG_PLUGIN (24<<5) /* main plugin functions */
+#define SUDO_DEBUG_HOOKS (25<<5) /* hook functions */
#define SUDO_DEBUG_ALL 0xfff0 /* all subsystems */
+/* Flag to include string version of errno in debug info. */
+#define SUDO_DEBUG_ERRNO (1<<4)
+
/* Extract priority and convert to an index. */
#define SUDO_DEBUG_PRI(n) (((n) & 0xf) - 1)
/* Extract subsystem and convert to an index. */
-#define SUDO_DEBUG_SUBSYS(n) (((n) >> 4) - 1)
+#define SUDO_DEBUG_SUBSYS(n) (((n) >> 5) - 1)
/*
* Wrapper for sudo_debug_enter() that declares __func__ as needed
int sudo_debug_fd_set(int fd);
int sudo_debug_init(const char *debugfile, const char *settings);
void sudo_debug_printf2(int level, const char *format, ...) __printflike(2, 3);
-void sudo_debug_write(const char *str, int len);
+void sudo_debug_write(const char *str, int len, int errno_val);
#endif /* _SUDO_DEBUG_H */
break;
case SUDO_CONV_DEBUG_MSG:
if (msg->msg)
- sudo_debug_write(msg->msg, strlen(msg->msg));
+ sudo_debug_write(msg->msg, strlen(msg->msg), 0);
break;
default:
goto err;