summaryrefslogtreecommitdiff
path: root/src/procenv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/procenv.c')
-rw-r--r--src/procenv.c7555
1 files changed, 724 insertions, 6831 deletions
diff --git a/src/procenv.c b/src/procenv.c
index 966eef5..fa4780f 100644
--- a/src/procenv.c
+++ b/src/procenv.c
@@ -9,7 +9,7 @@
* Licence: GPLv3. See below...
*--------------------------------------------------------------------
*
- * Copyright © 2012-2015 James Hunt <jamesodhunt@ubuntu.com>.
+ * Copyright © 2012-2016 James Hunt <jamesodhunt@ubuntu.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,55 +36,11 @@
pstring *doc = NULL;
/**
- * output:
- *
- * Where to send output.
- **/
-Output output = OUTPUT_STDOUT;
-
-/**
- * output_format:
- *
- * Format output will be displayed in.
- **/
-OutputFormat output_format = OUTPUT_FORMAT_TEXT;
-
-/**
- * output_file:
- *
- * Name or output file to send output to if not NULL.
- **/
-const char *output_file = NULL;
-
-/**
- * text_separator:
- *
- * Separator used for text output format to separate a name from a
- * value.
- **/
-const char *text_separator = PROCENV_DEFAULT_TEXT_SEPARATOR;
-
-/**
- * crumb_separator:
- *
- * Separator used for text output format to separate a name from a
- * value.
- **/
-const char *crumb_separator = PROCENV_DEFAULT_CRUMB_SEPARATOR;
-
-/**
- * output_fd:
- *
- * File descriptor associated with output_file.
- **/
-int output_fd = -1;
-
-/**
* reexec:
*
- * TRUE if we should re-exec at the end.
+ * true if we should re-exec at the end.
**/
-int reexec = FALSE;
+int reexec = false;
/**
* selected_option:
@@ -95,27 +51,6 @@ int reexec = FALSE;
**/
int selected_option = 0;
-/**
- * indent:
- *
- * Current output indent value.
- **/
-int indent = 0;
-
-/**
- * indent_amount:
- *
- * Number of INDENT_CHARs to emit for an indent.
- **/
-int indent_amount = DEFAULT_INDENT_AMOUNT;
-
-/**
- * indent_char, wide_indent_char:
- *
- * Character to use for indenting and wide-char equivalent.
- **/
-const char *indent_char = DEFAULT_INDENT_CHAR;
-wchar_t wide_indent_char;
/**
* program_name:
@@ -142,288 +77,20 @@ int argvc = 0;
**/
char *saved_locale = NULL;
-/**
- * last_element: Type of previous element handled.
- **/
-ElementType last_element = ELEMENT_TYPE_NONE;
-
-/**
- * current_element: Type of element currently being handled.
- **/
-ElementType current_element = ELEMENT_TYPE_NONE;
+/* Get a handle to the platform-specific routines */
+extern struct procenv_ops platform_ops;
+struct procenv_ops *ops = &platform_ops;
-/**
- * crumb_list:
- *
- * List used to store breadcrumbs when OUTPUT_FORMAT_CRUMB being used.
- **/
-static PRList *crumb_list = NULL;
+extern wchar_t wide_indent_char;
+extern int indent;
struct procenv_user user;
struct procenv_misc misc;
struct procenv_priority priority;
+struct procenv_priority priority_io;
struct utsname uts;
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-struct mntopt_map {
- uint64_t flag;
- char *name;
-} mntopt_map[] = {
-
- { MNT_ACLS , "acls" },
- { MNT_ASYNC , "asynchronous" },
- { MNT_EXPORTED , "NFS-exported" },
- { MNT_GJOURNAL , "gjournal" },
- { MNT_LOCAL , "local" },
- { MNT_MULTILABEL , "multilabel" },
-#ifndef PROCENV_GNU_BSD
- { MNT_NFS4ACLS , "nfsv4acls" },
-#endif
- { MNT_NOATIME , "noatime" },
- { MNT_NOCLUSTERR , "noclusterr" },
- { MNT_NOCLUSTERW , "noclusterw" },
- { MNT_NOEXEC , "noexec" },
- { MNT_NOSUID , "nosuid" },
- { MNT_NOSYMFOLLOW , "nosymfollow" },
- { MNT_QUOTA , "with quotas" },
- { MNT_RDONLY , "read-only" },
- { MNT_SOFTDEP , "soft-updates" },
- { MNT_SUIDDIR , "suiddir" },
-#if ! defined (PROCENV_GNU_BSD) && defined (MNT_SUJ)
- { MNT_SUJ , "journaled soft-updates" },
-#endif
- { MNT_SYNCHRONOUS , "synchronous" },
- { MNT_UNION , "union" },
-
- { 0, NULL }
-};
-#endif
-
-struct procenv_map output_map[] = {
- { OUTPUT_FILE , "file" },
- { OUTPUT_STDERR , "stderr" },
- { OUTPUT_STDOUT , "stdout" },
- { OUTPUT_SYSLOG , "syslog" },
- { OUTPUT_TERM , "terminal" },
-
- { 0, NULL }
-};
-
-struct procenv_map output_format_map[] = {
- { OUTPUT_FORMAT_TEXT, "text" },
- { OUTPUT_FORMAT_CRUMB, "crumb" },
- { OUTPUT_FORMAT_JSON, "json" },
- { OUTPUT_FORMAT_XML, "xml" },
-
- { 0, NULL }
-};
-
-struct baud_speed baud_speeds[] = {
- SPEED (B0),
- SPEED (B50),
- SPEED (B75),
- SPEED (B110),
- SPEED (B134),
- SPEED (B150),
- SPEED (B200),
- SPEED (B300),
- SPEED (B600),
- SPEED (B1200),
- SPEED (B1800),
- SPEED (B2400),
- SPEED (B4800),
- SPEED (B9600),
- SPEED (B19200),
- SPEED (B38400),
- SPEED (B57600),
- SPEED (B115200),
- SPEED (B230400),
-
- /* terminator */
- { 0, NULL }
-};
-
-struct if_flag_map {
- unsigned int flag;
- char *name;
-} if_flag_map[] = {
- mk_map_entry (IFF_UP),
- mk_map_entry (IFF_BROADCAST),
- mk_map_entry (IFF_DEBUG),
- mk_map_entry (IFF_LOOPBACK),
- mk_map_entry (IFF_POINTOPOINT),
- mk_map_entry (IFF_RUNNING),
- mk_map_entry (IFF_NOARP),
- mk_map_entry (IFF_PROMISC),
-
-#if defined (PROCENV_LINUX)
- mk_map_entry (IFF_NOTRAILERS),
-#endif
-
- mk_map_entry (IFF_ALLMULTI),
-
-#if defined (PROCENV_LINUX)
- mk_map_entry (IFF_MASTER),
- mk_map_entry (IFF_SLAVE),
-#endif
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
- mk_map_entry (IFF_SIMPLEX),
-#endif
-
- mk_map_entry (IFF_MULTICAST),
-
-#if defined (PROCENV_LINUX)
- mk_map_entry (IFF_PORTSEL),
- mk_map_entry (IFF_AUTOMEDIA),
- mk_map_entry (IFF_DYNAMIC),
- mk_map_entry (IFF_LOWER_UP),
- mk_map_entry (IFF_DORMANT),
-# ifdef IFF_ECHO
- mk_map_entry (IFF_ECHO),
-# endif
-#endif
-
- { 0, NULL }
-};
-
-/*
- * Note the gross hack to avoid need for flexible arrays.
- */
-TranslateTable translate_table[] = {
- {
- OUTPUT_FORMAT_XML,
- {
- { L'\'', L"&apos;" },
- { L'"', L"&quot;" },
- { L'&', L"&amp;" },
- { L'<', L"&lt;" },
- { L'>', L"&gt;" },
-
- /* terminator */
- { L'\0', NULL }
- }
- },
- {
- OUTPUT_FORMAT_JSON,
- {
- { L'"', L"\\\"" },
- { L'\\', L"\\\\" },
-
- /* hack! */
- { L'\0', NULL },
- { L'\0', NULL },
- { L'\0', NULL },
-
- /* terminator */
- { L'\0', NULL }
- }
- },
-};
-
-#if defined (PROCENV_LINUX)
-struct if_extended_flag_map {
- unsigned int flag;
- char *name;
-} if_extended_flag_map[] = {
-#if defined (IFF_802_1Q_VLAN)
- mk_map_entry (IFF_802_1Q_VLAN),
-#endif
-#if defined (IFF_EBRIDGE)
- mk_map_entry (IFF_EBRIDGE),
-#endif
-#if defined (IFF_SLAVE_INACTIVE)
- mk_map_entry (IFF_SLAVE_INACTIVE),
-#endif
-#if defined (IFF_MASTER_8023AD)
- mk_map_entry (IFF_MASTER_8023AD),
-#endif
-#if defined (IFF_MASTER_ALB)
- mk_map_entry (IFF_MASTER_ALB),
-#endif
-#if defined (IFF_BONDING)
- mk_map_entry (IFF_BONDING),
-#endif
-#if defined (IFF_SLAVE_NEEDARP)
- mk_map_entry (IFF_SLAVE_NEEDARP),
-#endif
-#if defined (IFF_ISATAP)
- mk_map_entry (IFF_ISATAP),
-#endif
- { 0, NULL }
-};
-
-struct personality_map {
- unsigned int personality;
- char *name;
-} personality_map[] = {
- mk_map_entry (PER_LINUX),
- mk_map_entry (PER_LINUX_32BIT),
- mk_map_entry (PER_SVR4),
- mk_map_entry (PER_SVR3),
- mk_map_entry (PER_SCOSVR3),
- mk_map_entry (PER_OSR5),
- mk_map_entry (PER_WYSEV386),
- mk_map_entry (PER_ISCR4),
- mk_map_entry (PER_BSD),
- mk_map_entry (PER_SUNOS),
- mk_map_entry (PER_XENIX),
-#if defined (PER_LINUX32)
- mk_map_entry (PER_LINUX32),
-#endif
-#if defined (PER_LINUX32_3GB)
- mk_map_entry (PER_LINUX32_3GB),
-#endif
- mk_map_entry (PER_IRIX32),
- mk_map_entry (PER_IRIXN32),
- mk_map_entry (PER_IRIX64),
- mk_map_entry (PER_RISCOS),
- mk_map_entry (PER_SOLARIS),
- mk_map_entry (PER_UW7),
- mk_map_entry (PER_OSF4),
- mk_map_entry (PER_HPUX),
-
- { 0, NULL }
-};
-
-struct personality_flag_map {
- unsigned int flag;
- char *name;
-} personality_flag_map[] = {
-#if defined (ADDR_COMPAT_LAYOUT)
- mk_map_entry (ADDR_COMPAT_LAYOUT),
-#endif
-#if defined (ADDR_LIMIT_32BIT)
- mk_map_entry (ADDR_LIMIT_32BIT),
-#endif
-#if defined (ADDR_LIMIT_3GB)
- mk_map_entry (ADDR_LIMIT_3GB),
-#endif
-#if defined (ADDR_NO_RANDOMIZE)
- mk_map_entry (ADDR_NO_RANDOMIZE),
-#endif
-#if defined (MMAP_PAGE_ZERO)
- mk_map_entry (MMAP_PAGE_ZERO),
-#endif
-#if defined (READ_IMPLIES_EXEC)
- mk_map_entry (READ_IMPLIES_EXEC),
-#endif
-#if defined (SHORT_INODE)
- mk_map_entry (SHORT_INODE),
-#endif
-#if defined (STICKY_TIMEOUTS)
- mk_map_entry (STICKY_TIMEOUTS),
-#endif
-#if defined (WHOLE_SECONDS)
- mk_map_entry (WHOLE_SECONDS),
-#endif
-
- { 0, NULL }
-};
-
-#endif
-
/* Really, every single sysconf variable should be ifdef'ed since it
* may not exist on a particular system, but that makes the code look
* untidy.
@@ -611,11 +278,11 @@ struct procenv_map sysconf_map[] = {
#endif
#if defined (_SC_EQUIV_CLASS_MAX)
- mk_sysconf_map_entry (_SC_EQUIV_CLASS_MAX),
+ mk_sysconf_map_entry (_SC_EQUIV_CLASS_MAX),
#endif
#if defined (_SC_EXPR_NEST_MAX)
- mk_sysconf_map_entry (_SC_EXPR_NEST_MAX),
+ mk_sysconf_map_entry (_SC_EXPR_NEST_MAX),
#endif
#if defined (_SC_FD_MGMT)
@@ -782,7 +449,7 @@ struct procenv_map sysconf_map[] = {
mk_sysconf_map_entry (_SC_MQ_PRIO_MAX),
#endif
-#ifdef _SC_MULTI_PROCESS
+#if defined (_SC_MULTI_PROCESS)
mk_sysconf_map_entry (_SC_MULTI_PROCESS),
#endif
@@ -1281,83 +948,9 @@ struct procenv_map sysconf_map[] = {
{ 0, NULL }
};
-/* Signal numbers are different per architecture.
- *
- * This lookup table allows use to ignore the numbers and display nice
- * symbolic names and also to order by signal number (which values
- * change on different architectures).
- */
-struct procenv_map signal_map[] = {
-
- mk_map_entry (SIGABRT),
- mk_map_entry (SIGALRM),
- mk_map_entry (SIGBUS),
-
- { SIGCHLD, "SIGCHLD|SIGCLD" },
-
- mk_map_entry (SIGCONT),
- mk_map_entry (SIGFPE),
- mk_map_entry (SIGHUP),
- mk_map_entry (SIGILL),
- mk_map_entry (SIGINT),
- mk_map_entry (SIGKILL),
- mk_map_entry (SIGPIPE),
- mk_map_entry (SIGQUIT),
- mk_map_entry (SIGSEGV),
- mk_map_entry (SIGSTOP),
- mk_map_entry (SIGTERM),
- mk_map_entry (SIGTRAP),
- mk_map_entry (SIGTSTP),
- mk_map_entry (SIGTTIN),
- mk_map_entry (SIGTTOU),
- mk_map_entry (SIGUSR1),
- mk_map_entry (SIGUSR2),
- mk_map_entry (SIGIO),
-#if defined (PROCENV_LINUX)
- mk_map_entry (SIGIOT),
-#endif
-
-#if defined (PROCENV_LINUX)
- {SIGPOLL, "SIGPOLL|SIGIO" },
-#endif
-
- mk_map_entry (SIGPROF),
-
-#if defined (PROCENV_LINUX)
- mk_map_entry (SIGPWR),
-#ifdef SIGSTKFLT
- mk_map_entry (SIGSTKFLT),
-#endif
-#endif
-
- mk_map_entry (SIGSYS),
-
-#if defined (PROCENV_LINUX)
-#ifdef SIGUNUSED
- mk_map_entry (SIGUNUSED),
-#endif
-#endif
- mk_map_entry (SIGURG),
- mk_map_entry (SIGVTALRM),
- mk_map_entry (SIGWINCH),
- mk_map_entry (SIGXCPU),
- mk_map_entry (SIGXFSZ),
-
-#if defined (PROCENV_BSD) || defined (PROCENV_HURD)
- mk_map_entry (SIGEMT),
- mk_map_entry (SIGINFO),
-#endif
-
-#if defined (PROCENV_HURD)
- mk_map_entry (SIGLOST),
-#endif
-
- { 0, NULL },
-};
-
struct procenv_map locale_map[] = {
- /* The non-conditional ones are POSIX. */
+ /* The non-conditional ones are POSIX. */
#ifdef LC_ADDRESS
mk_map_entry (LC_ADDRESS),
#endif
@@ -1386,35 +979,19 @@ struct procenv_map locale_map[] = {
{ 0, NULL }
};
-struct procenv_map scheduler_map[] = {
-
- mk_map_entry (SCHED_OTHER),
- mk_map_entry (SCHED_FIFO),
- mk_map_entry (SCHED_RR),
-#if defined (PROCENV_LINUX) && ! defined (PROCENV_ANDROID)
- mk_map_entry (SCHED_BATCH),
-#ifdef SCHED_IDLE
- mk_map_entry (SCHED_IDLE),
-#endif
-#endif
-
- { 0, NULL }
-};
-
struct procenv_map thread_sched_policy_map[] = {
mk_map_entry (SCHED_OTHER),
mk_map_entry (SCHED_FIFO),
mk_map_entry (SCHED_RR)
};
-#if defined (PROCENV_LINUX) && defined (HAVE_NUMA_H)
-struct procenv_map numa_mempolicy_map[] = {
- mk_map_entry (MPOL_DEFAULT),
- mk_map_entry (MPOL_PREFERRED),
- mk_map_entry (MPOL_BIND),
- mk_map_entry (MPOL_INTERLEAVE),
+struct network_map {
+ struct ifaddrs ifaddr;
+ char *mac_address;
+
+ struct network_map *next;
+ struct network_map *prev;
};
-#endif
void
usage (void)
@@ -1433,7 +1010,7 @@ usage (void)
show (" -C, --cpu : Display CPU and scheduler details.");
show (" --crumb-separator=<str> : Specify string '<str>' as alternate delimiter");
show (" for crumb format output (default='%s').",
- PROCENV_DEFAULT_CRUMB_SEPARATOR);
+ get_crumb_separator ());
show (" -d, --compiler : Display compiler details.");
show (" -e, --environment : Display environment variables.");
show (" -E, --semaphores : Display semaphore details.");
@@ -1441,6 +1018,8 @@ usage (void)
show (" -f, --fds : Display file descriptor details.");
show (" -F, --namespaces : Display namespace details.");
show (" --file=<file> : Send output to <file> (implies --output=file).");
+ show (" --file-append : Append to file specified by '--file='");
+ show (" rather than overwriting");
show (" --format=<format> : Specify output format. <format> can be one of:");
show ("");
show (" crumb : ASCII 'breadcrumbs'");
@@ -1452,9 +1031,9 @@ usage (void)
show (" -h, --help : This help text.");
show (" -i, --misc : Display miscellaneous details.");
show (" --indent : Number of indent characters to use for each indent");
- show (" (default=%d).", DEFAULT_INDENT_AMOUNT);
+ show (" (default=%d).", get_indent_amount ());
show (" --indent-char=<c> : Use character '<c>' for indenting");
- show (" (default='%s').", DEFAULT_INDENT_CHAR);
+ show (" (default='%s').", get_indent_char ());
show (" -j, --uname : Display uname details.");
show (" -k, --clocks : Display clock details.");
show (" -l, --limits : Display limits.");
@@ -1479,7 +1058,7 @@ usage (void)
show (" -r, --ranges : Display range of data types.");
show (" --separator=<str> : Specify string '<str>' as alternate delimiter");
show (" for text format output (default='%s').",
- PROCENV_DEFAULT_TEXT_SEPARATOR);
+ get_text_separator ());
show (" -s, --signals : Display signal details.");
show (" -S, --shared-memory : Display shared memory details.");
show (" -t, --tty : Display terminal details.");
@@ -1496,7 +1075,7 @@ usage (void)
show ("Notes:");
show ("");
show (" - Options are considered in order, so '--output' should");
- show (" precede any other option.");
+ show (" precede any other option.");
show (" - If no display option is specified, all details are displayed.");
show (" - Only one display option may be specified.");
show (" - All values for '--indent-char' are literal except '\\t' which can be");
@@ -1512,786 +1091,6 @@ usage (void)
show ("");
}
-void
-show_pathconfs (ShowMountType what,
- const char *dir)
-{
- assert (dir);
-
- if (what == SHOW_PATHCONF) {
- header (dir);
- } else {
- header ("pathconf");
- }
-
-
-#if defined (_PC_ALLOC_SIZE_MIN)
- show_pathconf (what, dir, _PC_ALLOC_SIZE_MIN);
-#endif
-
-#if defined (_PC_ASYNC_IO)
- show_pathconf (what, dir, _PC_ASYNC_IO);
-#endif
-
-#if defined (_PC_CHOWN_RESTRICTED)
- show_pathconf (what, dir, _PC_CHOWN_RESTRICTED);
-#endif
-
-#if defined (_PC_FILESIZEBITS)
- show_pathconf (what, dir, _PC_FILESIZEBITS);
-#endif
-
-#if defined (_PC_LINK_MAX)
- show_pathconf (what, dir, _PC_LINK_MAX);
-#endif
-
-#if defined (_PC_MAX_CANON)
- show_pathconf (what, dir, _PC_MAX_CANON);
-#endif
-
-#if defined (_PC_MAX_INPUT)
- show_pathconf (what, dir, _PC_MAX_INPUT);
-#endif
-
-#if defined (_PC_NAME_MAX)
- show_pathconf (what, dir, _PC_NAME_MAX);
-#endif
-
-#if defined (_PC_NO_TRUNC)
- show_pathconf (what, dir, _PC_NO_TRUNC);
-#endif
-
-#if defined (_PC_PATH_MAX)
- show_pathconf (what, dir, _PC_PATH_MAX);
-#endif
-
-#if defined (_PC_PIPE_BUF)
- show_pathconf (what, dir, _PC_PIPE_BUF);
-#endif
-
-#if defined (_PC_PRIO_IO)
- show_pathconf (what, dir, _PC_PRIO_IO);
-#endif
-
-#if defined (_PC_REC_INCR_XFER_SIZE)
- show_pathconf (what, dir, _PC_REC_INCR_XFER_SIZE);
-#endif
-
-#if defined (_PC_REC_MAX_XFER_SIZE)
- show_pathconf (what, dir, _PC_REC_MAX_XFER_SIZE);
-#endif
-
-#if defined (_PC_REC_MIN_XFER_SIZE)
- show_pathconf (what, dir, _PC_REC_MIN_XFER_SIZE);
-#endif
-
-#if defined (_PC_REC_XFER_ALIGN)
- show_pathconf (what, dir, _PC_REC_XFER_ALIGN);
-#endif
-
-#if defined (_PC_SOCK_MAXBUF)
- show_pathconf (what, dir, _PC_SOCK_MAXBUF);
-#endif
-
-#if defined (_PC_SYMLINK_MAX)
- show_pathconf (what, dir, _PC_SYMLINK_MAX);
-#endif
-
-#if defined (_PC_2_SYMLINKS)
- show_pathconf (what, dir, _PC_2_SYMLINKS);
-#endif
-
-#if defined (_PC_SYNC_IO)
- show_pathconf (what, dir, _PC_SYNC_IO);
-#endif
-
-#if defined (_PC_VDISABLE)
- show_pathconf (what, dir, _PC_VDISABLE);
-#endif
-
- footer ();
-}
-
-const char *
-get_speed (speed_t speed)
-{
- struct baud_speed *s;
-
- for (s = baud_speeds; s && s->name; s++) {
- if (speed == s->speed)
- return s->name;
- }
-
- return NULL;
-}
-
-/**
- * _show:
- *
- * @prefix: string prefix to write,
- * @indent: number of spaces to indent output to,
- * @fmt: printf-style format with associated arguments that comprises
- * the value part.
- *
- * Write output to @string, indented by @indent spaces. A trailing newline
- * will be added.
- *
- * Note that error scenarios cannot call die() as by definition output
- * may not be possible.
- **/
-void
-_show (const char *prefix, int indent, const char *fmt, ...)
-{
- va_list ap;
- char *buffer = NULL;
-
- assert (fmt);
-
- if (indent)
- appendf (&buffer, "%*s", indent, indent_char);
-
- if (prefix && *prefix)
- appendf (&buffer, "%s: ", prefix);
-
- va_start (ap, fmt);
- appendva (&buffer, fmt, ap);
- va_end (ap);
-
- append (&buffer, "\n");
-
- _show_output (buffer);
-
- free (buffer);
-}
-
-/**
- * entry:
- *
- * @name: name of thing to display,
- * @fmt: printf-style format with associated arguments that comprises
- * the value part.
- *
- * Add name/value pair represented by @name and value comprising
- * printf-format string to the @doc global. The value added will be
- * indented appropriately.
- **/
-void
-entry (const char *name, const char *fmt, ...)
-{
- va_list ap;
- pstring *encoded_name = NULL;
- pstring *encoded_value = NULL;
-
- assert (name);
- assert (fmt);
-
- common_assert ();
-
- change_element (ELEMENT_TYPE_ENTRY);
-
- encoded_name = char_to_pstring (name);
- if (! encoded_name)
- die ("failed to encode name");
-
- /* annoyingly, we must encode here; we cannot simply call
- * encode_string() once just prior to showing the output
- * document since if the output format is XML, we'd end
- * up encoding the XML tags themselves, not just the values
- * within!
- */
- if (encode_string (&encoded_name) < 0)
- die ("failed to encode name");
-
- /* expand format */
- va_start (ap, fmt);
- wmappendva (&encoded_value, fmt, ap);
- va_end (ap);
-
- if (encode_string (&encoded_value) < 0)
- die ("failed to encode value");
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB:
- assert (crumb_list);
-
- /* Add the bread crumbs */
- PR_LIST_FOREACH (crumb_list, iter) {
- char *crumb = (char *)iter->data;
- wappendf (&doc,
- L"%s%s",
- crumb,
- crumb_separator);
- }
-
- wappendf (&doc,
- L"%ls%s%ls\n",
- encoded_name->buf,
- text_separator,
- encoded_value->buf);
- break;
-
- case OUTPUT_FORMAT_TEXT:
- wappendf (&doc,
- L"%ls%s%ls",
- encoded_name->buf,
- text_separator,
- encoded_value->buf);
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappendf (&doc,
- L"\"%ls\" : \"%ls\"",
- encoded_name->buf,
- encoded_value->buf);
- break;
-
- case OUTPUT_FORMAT_XML:
- wappendf (&doc,
- L"<entry name=\"%ls\">%ls</entry>",
- encoded_name->buf,
- encoded_value->buf);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-
- pstring_free (encoded_name);
- pstring_free (encoded_value);
-}
-
-/**
- * _show_output:
- *
- * @string: String to display.
- *
- * Write output @string to appropriate location based on Output
- * destination.
- **/
-void
-_show_output_pstring (const pstring *pstr)
-{
- char *str;
-
- assert (pstr);
-
- str = pstring_to_char (pstr);
-
- _show_output (str);
-
- free (str);
-}
-
-void
-_show_output (const char *str)
-{
- int ret;
-
- assert (str);
-
- switch (output) {
- case OUTPUT_SYSLOG:
- syslog (LOG_INFO, "%s", str);
- ret = 0;
- break;
-
- case OUTPUT_STDOUT:
- ret = fputs (str, stdout);
- break;
-
- case OUTPUT_STDERR:
- ret = fputs (str, stderr);
- break;
-
- case OUTPUT_TERM:
- assert (user.tty_fd != -1);
- ret = write (user.tty_fd, str, strlen (str));
- if (ret < 0) {
- fprintf (stderr, "ERROR: failed to write to terminal\n");
- exit (EXIT_FAILURE);
- }
- break;
-
- case OUTPUT_FILE:
- assert (output_file);
- if (output_fd < 0) {
- output_fd = open (output_file,
- (O_WRONLY|O_CREAT),
- (S_IRWXU|S_IRGRP|S_IROTH));
- if (output_fd < 0) {
- fprintf (stderr, "ERROR: failed to open file '%s'\n",
- output_file);
- exit (EXIT_FAILURE);
- }
- }
- ret = write (output_fd, str, strlen (str));
- if (ret < 0) {
- fprintf (stderr, "ERROR: failed to write to file '%s'\n",
- output_file);
- exit (EXIT_FAILURE);
- }
- break;
-
- default:
- fprintf (stderr, "ERROR: invalid output type: %d\n", output);
- exit (EXIT_FAILURE);
- break;
- }
-
- if (ret < 0) {
- fprintf (stderr, "ERROR: failed to output message\n");
- exit (EXIT_FAILURE);
- }
-}
-
-/**
- * inc_indent:
- *
- * Increase indent.
- **/
-void
-inc_indent (void)
-{
- assert (indent >= 0);
-
- indent += indent_amount;
-}
-
-/**
- * dec_indent:
- *
- * Decrease indent.
- **/
-void
-dec_indent (void)
-{
- assert (indent >= 0);
-
- indent -= indent_amount;
-
- assert (indent >= 0);
-}
-
-/**
- * add_indent:
- *
- * Insert the current indent to the output document.
- **/
-void
-add_indent (pstring **doc)
-{
- common_assert ();
-
- if (! indent)
- return;
-
- if (! strcmp (indent_char, DEFAULT_INDENT_CHAR)) {
- wappendf (doc, L"%*s", indent, indent_char);
- } else {
- pstring *buffer = NULL;
-
- // Expand the buffer to the appropriate
- // length by filling it with spaces and a random
- // character.
- wappendf (&buffer, L"%*lc", indent, wide_indent_char);
-
-
- /* Now, replace the spaces and the random character with
- * the chosen character. This convoluted approach is
- * necessary as printf-type functions don't allow the
- * padding character to be specified.
- */
- wmemset (buffer->buf, wide_indent_char, wcslen (buffer->buf));
-
- pappend (doc, buffer);
- pstring_free (buffer);
- }
-}
-
-/**
- * master_header:
- *
- * @doc: document to write footer to.
- *
- * Main header which is displayed once.
- **/
-void
-master_header (pstring **doc)
-{
- common_assert ();
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_JSON:
- object_open (FALSE);
- break;
-
- case OUTPUT_FORMAT_XML:
- wappend (doc, L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- wappendf (doc, L"<%s version=\"%s\" package_string=\"%s\" "
- "mode=\"%s%s\" format_version=\"%d\">\n",
- PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_STRING,
- user.euid ? _(NON_STR) "-" : "",
- PRIVILEGED_STR,
- PROCENV_FORMAT_VERSION);
-
- inc_indent ();
-
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * master_footer:
- *
- * @doc: document to write footer to.
- *
- * Main footer which is displayed once.
- **/
-void
-master_footer (pstring **doc)
-{
- common_assert ();
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* Tweak */
- wappend (doc, L"\n");
- break;
-
- case OUTPUT_FORMAT_JSON:
- object_close (FALSE);
-
- /* Tweak */
- wappend (doc, L"\n");
- break;
-
- case OUTPUT_FORMAT_XML:
- /* Tweak */
- wappend (doc, L"\n");
- dec_indent ();
- wappendf (doc, L"</%s>\n", PACKAGE_NAME);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * object_open:
- *
- * @retain: if TRUE, do not disrupt the current element such that the
- * opening of the object will be invisible to the state machine, but
- * will still produce the required output.
- *
- * Note: @retain is only meaningful for OUTPUT_FORMAT_JSON.
- *
- * Handle opening an object.
- **/
-void
-object_open (int retain)
-{
- common_assert ();
-
- if (output_format == OUTPUT_FORMAT_JSON) {
- if (retain) {
- format_element ();
- } else {
- change_element (ELEMENT_TYPE_OBJECT_OPEN);
- }
- } else {
- /* Objects are only required for handling JSON. In
- * fact, they cause problems for other output formats
- * that do not have visible "objects" in that they cause
- * the state table to lose track of the previous element
- * since it is actually the previous-previous element
- * (as the pointless object is the previous element).
- *
- * As such, ignore them.
- */
- }
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappend (&doc, L"{");
- break;
-
- case OUTPUT_FORMAT_XML:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * object_close:
- *
- * @retain: if TRUE, do not disrupt the current element such that the
- * object closure will be invisible to the state machine, but will still
- * produce @retain: if TRUE, do not disrupt the current element.
- *
- * Note: @retain is only meaningful for OUTPUT_FORMAT_JSON.
- *
- * Handle closing an object.
- **/
-void
-object_close (int retain)
-{
- common_assert ();
-
- if (output_format == OUTPUT_FORMAT_JSON) {
- if (retain) {
- format_element ();
- } else {
- change_element (ELEMENT_TYPE_OBJECT_CLOSE);
- }
- } else {
- /* Objects are only required for handling JSON. In
- * fact, they cause problems for other output formats
- * that do not have visible "objects" in that they cause
- * the state table to lose track of the previous element
- * since it is actually the previous-previous element
- * (as the pointless object is the previous element).
- *
- * As such, ignore them.
- */
- }
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappend (&doc, L"}");
- break;
-
- case OUTPUT_FORMAT_XML:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * section_open:
- *
- * @name: name of section.
- *
- * Start a new section which will contain >0 entry() calls.
- **/
-void
-section_open (const char *name)
-{
- assert (name);
- common_assert ();
-
- change_element (ELEMENT_TYPE_SECTION_OPEN);
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- wappendf (&doc, L"%s:", name);
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- add_breadcrumb (name);
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappendf (&doc, L"\"%s\" : {", name);
- break;
-
- case OUTPUT_FORMAT_XML:
- wappendf (&doc, L"<section name=\"%s\">", name);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-section_close (void)
-{
- common_assert ();
-
- change_element (ELEMENT_TYPE_SECTION_CLOSE);
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- remove_breadcrumb ();
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappend (&doc, L"}");
- break;
-
- case OUTPUT_FORMAT_XML:
- wappend (&doc, L"</section>");
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * container_open:
- *
- * @name: name of container.
- *
- * Start a new container which will contain >0 entry() calls.
- *
- * This is primarily to handle JSON arrays.
- **/
-void
-container_open (const char *name)
-{
- assert (name);
- common_assert ();
-
- change_element (ELEMENT_TYPE_CONTAINER_OPEN);
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- wappendf (&doc, L"%s:", name);
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- add_breadcrumb (name);
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappendf (&doc, L"\"%s\" : [", name);
- break;
-
- case OUTPUT_FORMAT_XML:
- wappendf (&doc, L"<container name=\"%s\">", name);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * container_close:
- *
- * Finish with a container.
- **/
-void
-container_close (void)
-{
- common_assert ();
-
- change_element (ELEMENT_TYPE_CONTAINER_CLOSE);
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- remove_breadcrumb ();
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappend (&doc, L"]");
- break;
-
- case OUTPUT_FORMAT_XML:
- wappend (&doc, L"</container>");
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-header (const char *name)
-{
- assert (name);
- common_assert ();
-
- section_open (name);
-}
-
-void
-footer (void)
-{
- common_assert ();
- section_close ();
-}
-
-/**
- * fd_valid:
- * @fd: file descriptor.
- *
- * Return 1 if @fd is valid, else 0.
- **/
-int
-fd_valid (int fd)
-{
- int flags = 0;
-
- if (fd < 0)
- return 0;
-
- errno = 0;
- flags = fcntl (fd, F_GETFL);
-
- if (flags < 0)
- return 0;
-
- /* redundant really */
- if (errno == EBADF)
- return 0;
-
- return 1;
-}
-
/**
* show_signals:
*
@@ -2320,23 +1119,38 @@ fd_valid (int fd)
void
show_signals (void)
{
- int i;
- int rc;
- int blocked;
- int ignored;
- sigset_t old_sigset;
- struct sigaction act;
+ int i;
+ int rc;
+ int blocked;
+ int ignored;
+ sigset_t old_sigset;
+ struct sigaction act;
+ const struct procenv_map *p;
+ int max;
container_open ("signals");
/* Query blocked signals.
*
- * How should be 0, but valgrind complains.
+ * arg 1 ('how') should be 0, but valgrind complains.
*/
if (sigprocmask (SIG_BLOCK, NULL, &old_sigset) < 0)
die ("failed to query signal mask");
- for (i = 1; i <= NUM_SIGNALS; i++) {
+ /* first, count the number of entries in the platform-specific
+ * signal map.
+ */
+ for (p = ops->signal_map, max = 1;
+ p && p->name;
+ p++, max++) {
+ ; /* NOP */
+ }
+
+ /* Note that we don't interate the signal map directly in case the
+ * entries are out of order. Instead, present the signals in numeric
+ * order.
+ */
+ for (i = 1; i < max; i++) {
const char *signal_name;
const char *signal_desc;
@@ -2365,7 +1179,7 @@ show_signals (void)
signal_desc = strsignal (i);
- object_open (FALSE);
+ object_open (false);
section_open (signal_name);
@@ -2377,73 +1191,12 @@ show_signals (void)
section_close ();
- object_close (FALSE);
+ object_close (false);
}
- container_close ();
+ container_close ();
}
-void
-show_rlimits (void)
-{
- header ("limits");
-
- show_limit (RLIMIT_AS);
- show_limit (RLIMIT_CORE);
- show_limit (RLIMIT_CPU);
- show_limit (RLIMIT_DATA);
- show_limit (RLIMIT_FSIZE);
-
-#if defined (PROCENV_LINUX)
-
- if (LINUX_KERNEL_MMR (2, 6, 25)) {
-#if defined (RLIMIT_RTTIME)
- show_limit (RLIMIT_RTTIME);
-#endif
- }
- show_limit (RLIMIT_LOCKS);
-#endif
-
- show_limit (RLIMIT_MEMLOCK);
-
-#if defined (PROCENV_LINUX)
-
- if (LINUX_KERNEL_MMR (2, 6, 8)) {
-#if defined (RLIMIT_MSGQUEUE)
- show_limit (RLIMIT_MSGQUEUE);
-#endif
- }
-
- if (LINUX_KERNEL_MMR (2, 6, 12)) {
-#if defined RLIMIT_NICE
- show_limit (RLIMIT_NICE);
-#endif
- }
-
-#endif
-
- show_limit (RLIMIT_NOFILE);
- show_limit (RLIMIT_NPROC);
- show_limit (RLIMIT_RSS);
-
-#if defined (PROCENV_LINUX)
- show_limit (RLIMIT_RTPRIO);
-#endif
-
-#if defined (PROCENV_LINUX)
-
- if (LINUX_KERNEL_MMR (2, 6, 8)) {
-#if defined (RLIMIT_SIGPENDING)
- show_limit (RLIMIT_SIGPENDING);
-#endif
- }
-
-#endif
-
- show_limit (RLIMIT_STACK);
-
- footer ();
-}
void
show_rusage (void)
@@ -2470,305 +1223,29 @@ show_rusage (void)
show_usage (usage, ru_nvcsw);
show_usage (usage, ru_nivcsw);
- footer ();
+ footer ();
}
void
show_sysconf (void)
{
- struct procenv_map *p;
- long value;
+ struct procenv_map *p;
+ long value;
header ("sysconf");
for (p = sysconf_map; p && p->name; p++) {
value = get_sysconf (p->num);
- if (value == -1)
+ if (value == -1) {
entry (p->name, "%s", NA_STR);
- else
+ } else {
entry (p->name, "%ld", value);
+ }
}
- footer ();
-}
-
-#ifndef PROCENV_ANDROID
-
-void
-show_confstrs (void)
-{
- header ("confstr");
-
-#if defined (_CS_GNU_LIBC_VERSION)
- show_confstr (_CS_GNU_LIBC_VERSION);
-#endif
-
-#if defined (_CS_GNU_LIBPTHREAD_VERSION)
- show_confstr (_CS_GNU_LIBPTHREAD_VERSION);
-#endif
-
-#if defined (_CS_LFS64_CFLAGS)
- show_confstr (_CS_LFS64_CFLAGS);
-#endif
-
-#if defined (_CS_LFS64_LDFLAGS)
- show_confstr (_CS_LFS64_LDFLAGS);
-#endif
-
-#if defined (_CS_LFS64_LIBS)
- show_confstr (_CS_LFS64_LIBS);
-#endif
-
-#if defined (_CS_LFS64_LINTFLAGS)
- show_confstr (_CS_LFS64_LINTFLAGS);
-#endif
-
-#if defined (_CS_LFS_CFLAGS)
- show_confstr (_CS_LFS_CFLAGS);
-#endif
-
-#if defined (_CS_LFS_LDFLAGS)
- show_confstr (_CS_LFS_LDFLAGS);
-#endif
-
-#if defined (_CS_LFS_LIBS)
- show_confstr (_CS_LFS_LIBS);
-#endif
-
-#if defined (_CS_LFS_LINTFLAGS)
- show_confstr (_CS_LFS_LINTFLAGS);
-#endif
-
-#if defined (_CS_PATH)
- show_confstr (_CS_PATH);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32_CFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32_LDFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32_LIBS)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32_LINTFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LIBS)
- show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LP64_OFF64_CFLAGS)
- show_confstr (_CS_POSIX_V6_LP64_OFF64_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LP64_OFF64_LDFLAGS)
- show_confstr (_CS_POSIX_V6_LP64_OFF64_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LP64_OFF64_LIBS)
- show_confstr (_CS_POSIX_V6_LP64_OFF64_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V6_LP64_OFF64_LINTFLAGS)
- show_confstr (_CS_POSIX_V6_LP64_OFF64_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS)
- show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS)
- show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LIBS)
- show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS)
- show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFF32_CFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFF32_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFF32_LDFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFF32_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFF32_LIBS)
- show_confstr (_CS_POSIX_V7_ILP32_OFF32_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFF32_LINTFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFF32_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFFBIG_LIBS)
- show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LP64_OFF64_CFLAGS)
- show_confstr (_CS_POSIX_V7_LP64_OFF64_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LP64_OFF64_LDFLAGS)
- show_confstr (_CS_POSIX_V7_LP64_OFF64_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LP64_OFF64_LIBS)
- show_confstr (_CS_POSIX_V7_LP64_OFF64_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V7_LP64_OFF64_LINTFLAGS)
- show_confstr (_CS_POSIX_V7_LP64_OFF64_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS)
- show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS)
- show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_LIBS)
- show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS)
- show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_V5_WIDTH_RESTRICTED_ENVS)
- show_confstr (_CS_V5_WIDTH_RESTRICTED_ENVS);
-#endif
-
-#if defined (_CS_V5_WIDTH_RESTRICTED_ENVS)
- _show_confstr (_CS_V5_WIDTH_RESTRICTED_ENVS, "_XBS5_WIDTH_RESTRICTED_ENVS");
-#endif
-
-#if defined (_CS_V5_WIDTH_RESTRICTED_ENVS)
- _show_confstr (_CS_V5_WIDTH_RESTRICTED_ENVS, "XBS5_WIDTH_RESTRICTED_ENVS");
-#endif
-
-#if defined (_CS_V6_WIDTH_RESTRICTED_ENVS)
- show_confstr (_CS_V6_WIDTH_RESTRICTED_ENVS);
-#endif
-
-#if defined (_CS_V6_WIDTH_RESTRICTED_ENVS)
- _show_confstr (_CS_V6_WIDTH_RESTRICTED_ENVS, "POSIX_V6_WIDTH_RESTRICTED_ENVS,_POSIX_V6_WIDTH_RESTRICTED_ENVS");
-#endif
-
-#if defined (_CS_V7_WIDTH_RESTRICTED_ENVS)
- show_confstr (_CS_V7_WIDTH_RESTRICTED_ENVS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFF32_CFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFF32_CFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFF32_LDFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFF32_LDFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFF32_LIBS)
- show_confstr (_CS_XBS5_ILP32_OFF32_LIBS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFF32_LINTFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFF32_LINTFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFFBIG_CFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFFBIG_LDFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFFBIG_LIBS)
- show_confstr (_CS_XBS5_ILP32_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFFBIG_LINTFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LP64_OFF64_CFLAGS)
- show_confstr (_CS_XBS5_LP64_OFF64_CFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LP64_OFF64_LDFLAGS)
- show_confstr (_CS_XBS5_LP64_OFF64_LDFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LP64_OFF64_LIBS)
- show_confstr (_CS_XBS5_LP64_OFF64_LIBS);
-#endif
-
-#if defined (_CS_XBS5_LP64_OFF64_LINTFLAGS)
- show_confstr (_CS_XBS5_LP64_OFF64_LINTFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LPBIG_OFFBIG_CFLAGS)
- show_confstr (_CS_XBS5_LPBIG_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LPBIG_OFFBIG_LDFLAGS)
- show_confstr (_CS_XBS5_LPBIG_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LPBIG_OFFBIG_LIBS)
- show_confstr (_CS_XBS5_LPBIG_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_XBS5_LPBIG_OFFBIG_LINTFLAGS)
- show_confstr (_CS_XBS5_LPBIG_OFFBIG_LINTFLAGS);
-#endif
-
-
footer ();
}
-#endif
-
void
get_misc (void)
{
@@ -2776,43 +1253,16 @@ get_misc (void)
(void)umask (misc.umask_value);
assert (getcwd (misc.cwd, sizeof (misc.cwd)));
-#if defined (PROCENV_LINUX)
- get_canonical (ROOT_PATH, misc.root, sizeof (misc.root));
-#endif
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
- get_misc_bsd ();
-#endif
-}
-
-#if !defined (PROCENV_HURD)
-/**
- * is_console:
- * @fd: open file descriptor.
- *
- * Check if specified file descriptor is attached to a _console_
- * device (physical or virtual).
- *
- * Notes:
- * - ptys are NOT consoles :)
- * - running inside screen/tmux will report not running on console.
- *
- * Returns: TRUE if @fd is attached to a console, else FALSE.
- **/
-int
-is_console (int fd)
-{
- struct vt_mode vt;
- int ret;
-
- ret = ioctl (fd, VT_GETMODE, &vt);
-
- return !ret;
+ if (ops->get_user_misc)
+ ops->get_user_misc (&user, &misc);
}
-#endif
void
show_proc (void)
{
+ const char *suid = NULL;
+ const char *sgid = NULL;
+
header ("process");
entry ("process id (pid)", "%d", user.pid);
@@ -2824,12 +1274,12 @@ show_proc (void)
entry ("name", "'%s'", user.proc_name);
- show_proc_branch ();
+ handle_proc_branch ();
entry ("process group id", "%d (leader=%s)",
user.pgroup,
is_process_group_leader () ? YES_STR : NO_STR);
-
+
entry ("foreground process group", "%d", user.fg_pgroup);
entry ("terminal", "'%s'", user.ctrl_terminal);
@@ -2837,7 +1287,10 @@ show_proc (void)
entry ("has controlling terminal", "%s",
has_ctty () ? YES_STR : NO_STR);
-#if defined (PROCENV_HURD)
+ /* FIXME: Is it possible to detect if on console on hurd/minix? */
+#if defined (PROCENV_PLATFORM_HURD) || \
+ defined (PROCENV_PLATFORM_MINIX) || \
+ defined (PROCENV_PLATFORM_DARWIN)
entry ("on console", "%s", UNKNOWN_STR);
#else
entry ("on console", "%s",
@@ -2854,9 +1307,12 @@ show_proc (void)
user.euid,
get_user_name (user.euid));
- entry ("saved set-user-id (suid)", "%d ('%s')",
+ suid = get_user_name (user.suid);
+ entry ("saved set-user-id (suid)", "%d (%s%s%s)",
user.suid,
- get_user_name (user.suid));
+ suid ? "'" : "",
+ suid ? suid : UNKNOWN_STR,
+ suid ? "'" : "");
section_close ();
@@ -2870,9 +1326,12 @@ show_proc (void)
user.egid,
get_group_name (user.egid));
- entry ("saved set-group-id (sgid)", "%d ('%s')",
+ sgid = get_group_name (user.sgid);
+ entry ("saved set-group-id (sgid)", "%d (%s%s%s)",
user.sgid,
- get_group_name (user.sgid));
+ sgid ? "'" : "",
+ sgid ? sgid : UNKNOWN_STR,
+ sgid ? "'" : "");
section_close ();
@@ -2882,7 +1341,7 @@ show_proc (void)
entry ("name", "'%s'", user.passwd.pw_name);
-#if ! defined (PROCENV_ANDROID)
+#if ! defined (PROCENV_PLATFORM_ANDROID)
/* No gecos on Android. In fact it doesn't actually use the
* passwd database, but meh.
*/
@@ -2894,7 +1353,10 @@ show_proc (void)
section_close ();
+#if ! defined (PROCENV_PLATFORM_MINIX)
+ /* Calling getgroups(2) with Minix 3.3.0 always returns EINVAL :( */
show_all_groups ();
+#endif
footer ();
}
@@ -2902,19 +1364,10 @@ show_proc (void)
void
show_priorities (void)
{
-#if defined (PROCENV_LINUX)
- int sched;
-
- sched = sched_getscheduler (0);
-#endif
-
section_open ("scheduler");
-#if defined (PROCENV_LINUX)
- entry ("type", "%s",
- sched < 0 ? UNKNOWN_STR :
- get_scheduler_name (sched));
-#endif
+ if (ops->handle_scheduler_type)
+ ops->handle_scheduler_type ();
section_open ("priority");
@@ -2924,83 +1377,19 @@ show_priorities (void)
section_close ();
- section_close ();
-}
-
-void
-show_misc (void)
-{
-#if defined (PROCENV_LINUX)
- int domain = 0x0;
-
- /* magic value - see personality(2) */
- unsigned int persona = 0xFFFFFFFF;
-
- unsigned int mask = PER_MASK;
-
- const char *personality_name = NULL;
- char *personality_flags = NULL;
-#endif
-
- header ("misc");
-
- entry ("umask", "%4.4o", misc.umask_value);
- entry ("current directory (cwd)", "'%s'", misc.cwd);
-#if defined (PROCENV_LINUX)
- entry ("root", "%s%s%s",
- strcmp (misc.root, UNKNOWN_STR) ? "'" : "",
- misc.root,
- strcmp (misc.root, UNKNOWN_STR) ? "'" : "");
-#endif
- entry ("chroot", "%s", in_chroot () ? YES_STR : NO_STR);
- entry ("container", "%s", container_type ());
-
-#if defined (PROCENV_LINUX)
- show_prctl_linux ();
-
- section_open ("linux security module");
- show_security_module_linux ();
- show_security_module_context_linux ();
- section_close ();
-#endif
-
-#if defined (PROCENV_LINUX)
-#ifdef LINUX_VERSION_CODE
- entry ("kernel headers version", "%u.%u.%u",
- (LINUX_VERSION_CODE >> 16),
- ((LINUX_VERSION_CODE >> 8) & 0xFF),
- (LINUX_VERSION_CODE & 0xFF));
-#endif
-
- domain = personality (persona);
-
- personality_name = get_personality_name (domain & mask);
-
- section_open ("personality");
-
- entry ("type", "%s", personality_name
- ? personality_name
- : UNKNOWN_STR);
-
- personality_flags = get_personality_flags (domain & (-1 ^ mask));
- entry ("flags", "%s",
- personality_flags
- ? personality_flags
- : "");
+ if (ops->show_io_priorities) {
+ section_open ("I/O priority");
+ ops->show_io_priorities ();
+ section_close ();
+ }
section_close ();
-
- if (personality_flags)
- free (personality_flags);
-#endif
-
- footer ();
}
void
show_platform (void)
{
- long kernel_bits;
+ long kernel_bits = -1;
long executable_bits;
header ("platform");
@@ -3008,7 +1397,8 @@ show_platform (void)
entry ("operating system", "%s", get_os ());
entry ("architecture", "%s", get_arch ());
- kernel_bits = get_kernel_bits ();
+ if (ops->get_kernel_bits)
+ kernel_bits = ops->get_kernel_bits ();
executable_bits = sizeof (void *) * CHAR_BIT * sizeof (char);
@@ -3020,11 +1410,11 @@ show_platform (void)
entry ("executable bits", "%lu", executable_bits);
entry ("code endian", "%s",
- is_big_endian () ? BIG_STR : LITTLE_STR);
+ is_big_endian () ? BIG_STR : LITTLE_STR);
show_data_model ();
- footer ();
+ footer ();
}
void
@@ -3032,14 +1422,11 @@ show_cpu (void)
{
header ("cpu");
-#if defined (PROCENV_LINUX)
- show_cpu_linux ();
-#endif
+ if (ops->show_cpu)
+ ops->show_cpu ();
-#if defined (PROCENV_BSD)
- show_cpu_bsd ();
-#endif
- show_cpu_affinities ();
+ if (ops->show_cpu_affinities)
+ ops->show_cpu_affinities ();
show_priorities ();
@@ -3053,224 +1440,30 @@ show_memory (void)
entry ("page size", "%d bytes", getpagesize ());
-#if defined (PROCENV_LINUX)
- show_numa_memory ();
-#endif /* PROCENV_LINUX */
+ if (ops->handle_numa_memory)
+ ops->handle_numa_memory ();
footer ();
}
-/* Display cpu affinities in the same compressed but reasonably
- * human-readable fashion as /proc/self/status:Cpus_allowed_list under Linux.
- */
-void
-show_cpu_affinities (void)
-{
- int ret = 0;
- long max;
- size_t size;
-#if defined (PROCENV_BSD) || ! defined (CPU_ALLOC)
- PROCENV_CPU_SET_TYPE cpu_set_real;
-#endif
- PROCENV_CPU_SET_TYPE *cpu_set;
- long cpu;
- char *cpu_list = NULL;
-
- /* TRUE if any enabled cpus have been displayed yet */
- int displayed = FALSE;
-
- /* Number of cpu's in *current* range */
- size_t count = 0;
-
- /* Only valid to read these when count is >0 */
- size_t last = 0;
- size_t first = 0;
-
- max = get_sysconf (_SC_NPROCESSORS_ONLN);
- if (max < 0)
- die ("failed to query cpu count");
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD) || defined (PROCENV_HURD)
-
-#if defined (CPU_ALLOC)
-
- cpu_set = CPU_ALLOC (max);
- assert (cpu_set);
-
- size = CPU_ALLOC_SIZE (max);
- CPU_ZERO_S (size, cpu_set);
-
-#else /* ! CPU_ALLOC */
-
- /* RHEL 5 */
-
- cpu_set = &cpu_set_real;
-
- size = sizeof (PROCENV_CPU_SET_TYPE);
-
-#endif /* CPU_ALLOC */
-
-#elif defined (PROCENV_BSD) || ! defined (CPU_ALLOC)
- cpu_set = &cpu_set_real;
-
- size = sizeof (PROCENV_CPU_SET_TYPE);
-
-#endif /* PROCENV_LINUX || PROCENV_GNU_BSD || PROCENV_HURD */
-
- /* We could use sched_getaffinity(2) rather than
- * sched_getaffinity() on Linux (2.5.8+) but
- * pthread_getaffinity_np() provides the same information...
- * Except it is missing on kFreeBSD systems (!) so we have to
- * use sched_getaffinity() there. :(
- */
-#if (defined (PROCENV_GNU_BSD) || defined (PROCENV_HURD)) || (defined (PROCENV_LINUX) && ! defined (CPU_ALLOC))
- ret = sched_getaffinity (0, size, cpu_set);
-#else
-
-#if defined (PROCENV_LINUX) && defined (CPU_ALLOC)
- /* On a hyperthreaded system, "size" as above may not actually
- be big enough, and we get EINVAL. (hwloc has a similar
- workaround.) */
-
- {
- int mult = 0;
- while ((ret = pthread_getaffinity_np (pthread_self (), size, cpu_set))
- == EINVAL) {
- CPU_FREE (cpu_set);
- /* Bail out at an arbitrary value. */
- if (mult > 128) break;
- mult += 2;
- cpu_set = CPU_ALLOC (mult * max);
- size = CPU_ALLOC_SIZE (mult * max);
- CPU_ZERO_S (size, cpu_set);
- }
- }
-#endif /* PROCENV_LINUX && CPU_ALLOC */
-
-#endif
-
- if (ret)
- goto out;
-
- for (cpu = 0; cpu < max; cpu++) {
-
- if (CPU_ISSET (cpu, cpu_set)) {
-
- /* Record first entry in the range */
- if (! count)
- first = cpu;
-
- last = cpu;
- count++;
- } else {
- if (count) {
- if (first == last) {
- appendf (&cpu_list, "%s%d",
- displayed ? "," : "",
- first);
- } else {
- appendf (&cpu_list, "%s%d-%d",
- displayed ? "," : "",
- first, last);
- }
- displayed = TRUE;
- }
-
- /* Reset */
- count = 0;
- }
- }
-
- if (count) {
- if (first == last) {
- appendf (&cpu_list, "%s%d",
- displayed ? "," : "",
- first);
- } else {
- appendf (&cpu_list, "%s%d-%d",
- displayed ? "," : "",
- first, last);
- }
- }
-
-out:
- entry ("affinity list", "%s", cpu_list ? cpu_list : "-1");
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD) || defined (PROCENV_HURD)
-#if defined (CPU_ALLOC)
- CPU_FREE (cpu_set);
-#endif
-#endif
-
- free (cpu_list);
-}
-
-
void
show_fds (void)
{
-#if defined (PROCENV_LINUX)
- show_fds_linux ();
-#else
- show_fds_generic ();
-#endif
+ container_open ("file descriptors");
-}
-
-void
-show_namespaces (void)
-{
-#if defined (PROCENV_LINUX)
- show_namespaces_linux ();
-#else
- show_namespaces_stub ();
-#endif
+ if (ops->show_fds)
+ ops->show_fds ();
+ container_close ();
}
void
-show_fds_generic (void)
+show_namespaces (void)
{
- int fd;
- int max;
-
- container_open ("file descriptors");
-
- max = get_sysconf (_SC_OPEN_MAX);
-
- for (fd = 0; fd < max; fd++) {
- int is_tty = isatty (fd);
- char *name = NULL;
- char *num = NULL;
-
- if (! fd_valid (fd))
- continue;
-
-#if ! defined (PROCENV_ANDROID)
- name = ttyname (fd);
-#endif
- appendf (&num, "%d", fd);
-
- object_open (FALSE);
-
- section_open (num);
-
- entry ("terminal", "%s", is_tty ? YES_STR : NO_STR);
- entry ("valid", "%s", fd_valid (fd) ? YES_STR : NO_STR);
- entry ("device", "%s", name ? name : NA_STR);
-
- section_open ("capabilities");
-#if defined (PROCENV_BSD) && defined (HAVE_SYS_CAPABILITY_H)
- show_capabilities_bsd (fd);
-#endif
- section_close ();
-
- section_close ();
-
- object_close (FALSE);
+ container_open ("namespaces");
- free (num);
- }
+ if (ops->show_namespaces)
+ ops->show_namespaces ();
container_close ();
}
@@ -3343,30 +1536,34 @@ get_user_info (void)
{
struct passwd *pw;
void *p;
+#if defined (HAVE_GETRESUID) || defined (HAVE_GETRESGID)
int ret;
+#endif
user.pid = getpid ();
user.ppid = getppid ();
-#if defined (PROCENV_LINUX)
- if (LINUX_KERNEL_MMR (2, 6, 11)) {
- if (prctl (PR_GET_NAME, user.proc_name, 0, 0, 0) < 0)
- strcpy (user.proc_name, UNKNOWN_STR);
- }
-#endif
+ if (ops->get_proc_name)
+ ops->get_proc_name(&user);
-#ifdef _GNU_SOURCE
+#ifdef HAVE_GETRESUID
ret = getresuid (&user.uid, &user.euid, &user.suid);
assert (! ret);
+#else
+ user.uid = getuid ();
+ user.euid = geteuid ();
+ /* no saved uid */
+ user.suid = -1;
+#endif
+#ifdef HAVE_GETRESGID
getresgid (&user.gid, &user.egid, &user.sgid);
assert (! ret);
#else
- /* NB: no saved uid+gid */
- user.uid = getuid ();
- user.euid = geteuid ();
user.gid = getgid ();
user.egid = getegid ();
+ /* no saved gid */
+ user.sgid = -1;
#endif
user.sid = getsid ((pid_t)0);
@@ -3384,7 +1581,7 @@ get_user_info (void)
user.login = getlogin ();
user.pgroup = getpgrp ();
-#if defined (PROCENV_ANDROID)
+#if defined (PROCENV_PLATFORM_ANDROID)
sprintf (user.ctrl_terminal, "/dev/tty");
#else
ctermid (user.ctrl_terminal);
@@ -3406,7 +1603,6 @@ get_user_info (void)
user.tty_fd = STDIN_FILENO;
user.fg_pgroup = tcgetpgrp (user.tty_fd);
- user.pgid_sid = tcgetsid (user.tty_fd);
errno = 0;
pw = getpwuid (user.uid);
@@ -3417,464 +1613,6 @@ get_user_info (void)
assert (p == (void *)&user.passwd);
}
-/* append @src to @dest */
-void
-append (char **dest, const char *src)
-{
- size_t len;
-
- assert (dest);
- assert (src);
-
- len = strlen (src);
-
- appendn (dest, src, len);
-}
-
-/* Version of append() that operates on a wide string @dest and @src */
-void
-wappend (pstring **dest, const wchar_t *src)
-{
- size_t len;
-
- assert (dest);
- assert (src);
-
- len = wcslen (src);
-
- wappendn (dest, src, len);
-}
-
-/* Version of append() that operates on a wide string @dest
- * and multi-byte @src.
- */
-void
-wmappend (pstring **dest, const char *src)
-{
- wchar_t *wide_src = NULL;
-
- assert (dest);
- assert (src);
-
- wide_src = char_to_wchar (src);
- if (! wide_src)
- die ("failed to allocate space for wide string");
-
- wappend (dest, wide_src);
-
- free (wide_src);
-}
-
-/**
- * appendn:
- *
- * @dest: [output] string to append to,
- * @src: string to append to @dest,
- * @len: length of @new.
- *
- * Append first @len bytes of @new to @str,
- * ensuring result is nul-terminated.
- **/
-void
-appendn (char **dest, const char *src, size_t len)
-{
- size_t total;
-
- assert (dest);
- assert (src);
-
- if (! len)
- return;
-
- if (! *dest)
- *dest = strdup ("");
- if (! *dest)
- die ("failed to allocate space for string");
-
- /* +1 for terminating nul */
- total = strlen (*dest) + 1;
-
- total += len;
-
- *dest = realloc (*dest, total);
- assert (*dest);
-
- if (! *dest) {
- /* string is empty, so initialise the memory to avoid
- * surprises with strncat() being unable to find the
- * terminator!
- */
- memset (*dest, '\0', total);
- }
-
- strncat (*dest, src, len);
-
- assert ((*dest)[total-1] == '\0');
-}
-
-/* Version of appendn() that operates on a wide string @dest and @src */
-void
-wappendn (pstring **dest, const wchar_t *src, size_t len)
-{
- wchar_t *p;
- size_t total;
- size_t bytes;
-
- assert (dest);
- assert (src);
-
- if (! len)
- return;
-
- if (! *dest)
- *dest = pstring_new ();
- if (! *dest)
- die ("failed to allocate space for pstring");
-
- total = (*dest)->len + len;
-
- /* +1 for terminating nul */
- bytes = (1 + total) * sizeof (wchar_t);
-
- p = realloc ((*dest)->buf, bytes);
-
- /* FIXME: turn into die() [all occurences!] */
- assert (p);
-
- (*dest)->buf = p;
-
- if (! (*dest)->len) {
- /* pstring is empty, so initialise the memory to avoid
- * surprises with wcsncat() being unable to find the
- * terminator!
- */
- memset ((*dest)->buf, 0, bytes);
- }
-
- /* Used to check for overrun */
- (*dest)->buf[total] = L'\0';
-
- wcsncat ((*dest)->buf + (*dest)->len, src, len);
-
- /* update */
- (*dest)->len = total;
- (*dest)->size = bytes;
-
- /* check for overrun */
- assert ((*dest)->buf[total] == L'\0');
-}
-
-
-/* Version of appendn() that operates on a wide string @dest and
- * multi-byte @src.
- */
-void
-wmappendn (pstring **dest, const char *src, size_t len)
-{
- wchar_t *wide_src = NULL;
-
- assert (dest);
- assert (src);
-
- if (! len)
- return;
-
- wide_src = char_to_wchar (src);
- if (! wide_src)
- die ("failed to allocate space for wide string");
-
- wappendn (dest, wide_src, wcslen (wide_src));
-
- free (wide_src);
-}
-
-/* append @fmt and args to @dest */
-void
-appendf (char **dest, const char *fmt, ...)
-{
- va_list ap;
-
- assert (dest);
- assert (fmt);
-
- va_start (ap, fmt);
-
- appendva (dest, fmt, ap);
-
- va_end (ap);
-}
-
-/* Version of appendf() that operates on a wide string @dest
- * and @fmt.
- */
-void
-wappendf (pstring **dest, const wchar_t *fmt, ...)
-{
- va_list ap;
-
- assert (dest);
- assert (fmt);
-
- va_start (ap, fmt);
-
- wappendva (dest, fmt, ap);
-
- va_end (ap);
-}
-
-/* Version of appendf() that operates on a wide string @dest
- * and multi-byte @fmt.
- */
-void
-wmappendf (pstring **dest, const char *fmt, ...)
-{
- wchar_t *wide_fmt = NULL;
- va_list ap;
-
- assert (dest);
- assert (fmt);
-
- wide_fmt = char_to_wchar (fmt);
- if (! wide_fmt)
- die ("failed to allocate memory for wide format");
-
- va_start (ap, fmt);
-
- wappendva (dest, wide_fmt, ap);
-
- va_end (ap);
-
- free (wide_fmt);
-}
-
-/* append @fmt and args to @dest */
-void
-appendva (char **dest, const char *fmt, va_list ap)
-{
- int ret;
- char *new = NULL;
- char *p;
- size_t bytes;
-
- /* Start with a guess for how big we think the buffer needs to
- * be.
- */
- size_t len = DEFAULT_ALLOC_GUESS_SIZE;
-
- assert (dest);
- assert (fmt);
-
- bytes = (1 + len) * sizeof (char);
-
- /* we could use vasprintf(3), but that's GNU-specific and hence
- * not available everywhere we need it.
- */
- new = malloc (bytes);
- if (! new)
- die ("failed to allocate space for string");
-
- memset (new, '\0', bytes);
-
- /* keep on increasing size of buffer until the translation
- * succeeds.
- */
- while (TRUE) {
- va_list ap_copy;
-
- va_copy (ap_copy, ap);
- ret = vsnprintf (new, len, fmt, ap_copy);
- va_end (ap_copy);
-
- if (ret < 0)
- die ("failed to format string");
-
- if ((size_t)ret < len) {
- /* now we have sufficient space */
- break;
- }
-
- /* Bump to allow one char to be written */
- len++;
-
- /* recalculate number of bytes */
- bytes = (1 + len) * sizeof (char);
-
- p = realloc (new, bytes);
- if (! p)
- die ("failed to allocate space for string");
-
- new = p;
- }
-
- if (*dest) {
- append (dest, new);
- free (new);
- } else {
- *dest = new;
- }
-}
-
-/* Version of appendva() that operates on a wide string @dest
- * and @fmt.
- */
-void
-wappendva (pstring **dest, const wchar_t *fmt, va_list ap)
-{
- int ret;
- wchar_t *new = NULL;
- wchar_t *p;
- size_t bytes;
- va_list ap_copy;
-
- /* Start with a guess for how big we think the buffer needs to
- * be.
- */
- size_t len = DEFAULT_ALLOC_GUESS_SIZE;
-
- assert (dest);
- assert (fmt);
-
- bytes = (1 + len) * sizeof (wchar_t);
-
- new = malloc (bytes);
- if (! new)
- die ("failed to allocate space for wide string");
-
- memset (new, '\0', bytes);
-
- /* keep on increasing size of buffer until the translation
- * succeeds.
- */
- while (TRUE) {
- va_copy (ap_copy, ap);
- ret = vswprintf (new, len, fmt, ap_copy);
- va_end (ap_copy);
-
- if ((size_t)ret < len) {
- /* now we have sufficient space, so update for
- * actual number of bytes used (including the
- * terminator!)
- *
- * Note that, conveniently, if the string is
- * zero-characters long (ie ""), ret will be -1
- * which we correct to 0.
- */
- len = ret + 1;
-
- break;
- }
-
- /* Bump to allow one more wide-char to be written */
- len++;
-
- /* recalculate number of bytes */
- bytes = (1 + len) * sizeof (wchar_t);
-
- p = realloc (new, bytes);
- if (! p)
- die ("failed to allocate space for string");
-
- new = p;
-
- memset (new, '\0', bytes);
- }
-
- if (*dest) {
- wappend (dest, new);
- free (new);
- } else {
- wchar_t *n;
-
- /* recalculate number of bytes */
- bytes = (1 + len) * sizeof (wchar_t);
-
- /* compress */
- n = realloc (new, bytes);
-
- if (! n)
- die ("failed to reallocate space");
-
- new = n;
-
- (*dest) = pstring_new ();
- assert (*dest);
- (*dest)->buf = new;
- (*dest)->len = len;
- (*dest)->size = bytes;
- }
-}
-
-/* Version of appendva() that operates on a wide string @dest
- * and multi-byte @fmt.
- */
-void
-wmappendva (pstring **dest, const char *fmt, va_list ap)
-{
- wchar_t *wide_fmt = NULL;
- va_list ap_copy;
-
- assert (dest);
- assert (fmt);
-
- wide_fmt = char_to_wchar (fmt);
- if (! wide_fmt)
- die ("failed to allocate memory for wide format");
-
- va_copy (ap_copy, ap);
- wappendva (dest, wide_fmt, ap_copy);
- va_end (ap_copy);
-
- free (wide_fmt);
-}
-
-/*
- * Append @src onto the end of @dest.
- */
-void
-pappend (pstring **dest, const pstring *src)
-{
- size_t total;
- size_t bytes;
- wchar_t *p;
-
- assert (dest);
- assert (src);
-
- if (! src->len)
- return;
-
- if (! *dest)
- *dest = pstring_new ();
- if (! *dest)
- die ("failed to allocate space for pstring");
-
- total = (*dest)->len + src->len;
-
- /* adjust since we only store _one_ of the string terminators
- * from @dest and @src.
- */
- total--;
-
- /* +1 for terminating nul */
- bytes = (1 + total) * sizeof (wchar_t);
-
- p = realloc ((*dest)->buf, bytes);
-
- /* FIXME: turn into die() [all occurences!] */
- assert (p);
-
- (*dest)->buf = p;
-
- wcsncat ((*dest)->buf + (*dest)->len, src->buf, src->len);
-
- /* update */
- (*dest)->len = total;
- (*dest)->size = bytes;
-
- /* Used to check for overrun */
- (*dest)->buf[total] = L'\0';
-}
-
void
show_all_groups (void)
{
@@ -3901,7 +1639,7 @@ show_all_groups (void)
memset (groups, '\0', bytes);
- while (TRUE) {
+ while (true) {
ret = getgroups (size, groups);
if (ret >= 0)
break;
@@ -3919,7 +1657,7 @@ show_all_groups (void)
size = ret;
if (size == 0) {
- char *group;
+ const char *group;
free (groups);
@@ -4008,23 +1746,13 @@ restore_locale (void)
}
void
-handle_indent_char (void)
+init (void)
{
- size_t len;
-
- const char *new = indent_char;
+ assert (ops);
- len = mbsrtowcs (NULL, &new, 0, NULL);
- if (len != 1)
- die ("invalid indent character");
+ if (ops->init)
+ ops->init ();
- if (mbsrtowcs (&wide_indent_char, &new, len, NULL) != len)
- die ("failed to convert indent character");
-}
-
-void
-init (void)
-{
save_locale ();
handle_indent_char ();
@@ -4037,6 +1765,9 @@ init (void)
get_user_info ();
get_misc ();
get_priorities ();
+
+ if (ops->get_io_priorities)
+ ops->get_io_priorities (&priority_io);
}
void
@@ -4047,34 +1778,12 @@ cleanup (void)
close (user.tty_fd);
- if (output_fd != -1)
- close (output_fd);
-
- if (output == OUTPUT_SYSLOG)
- closelog ();
-
- if (output_format == OUTPUT_FORMAT_CRUMB && crumb_list) {
- clear_breadcrumbs ();
- free (crumb_list);
- }
+ output_finalise ();
pstring_free (doc);
-}
-
-/**
- * is_big_endian:
- *
- * Returns: TRUE if system is big-endian, else FALSE.
- **/
-bool
-is_big_endian (void)
-{
- int x = 1;
- if (*(char *)&x == 1)
- return FALSE;
-
- return TRUE;
+ if (ops->cleanup)
+ ops->cleanup ();
}
void
@@ -4099,6 +1808,11 @@ show_meta (void)
entry ("build-type", "%s", build_type);
+ section_open ("driver");
+ entry ("name", ops->driver.name);
+ entry ("file", ops->driver.file);
+ section_close ();
+
entry ("format-type", "%s", get_output_format_name ());
entry ("format-version", "%d", PROCENV_FORMAT_VERSION);
@@ -4121,11 +1835,11 @@ show_arguments (void)
appendf (&buffer, "argv[%d]", i);
- object_open (FALSE);
+ object_open (false);
entry (buffer, "%s", argvp[i]);
- object_close (FALSE);
+ object_close (false);
free (buffer);
}
@@ -4228,21 +1942,6 @@ show_stat (void)
footer ();
}
-long
-get_kernel_bits (void)
-{
-#if defined (PROCENV_LINUX) && ! defined (PROCENV_ANDROID)
- long value;
-
- errno = 0;
- value = get_sysconf (_SC_LONG_BIT);
- if (value == -1 && errno != 0)
- return -1;
- return value;
-#endif
- return -1;
-}
-
/* Dump out data in alphabetical fashion */
void
dump (void)
@@ -4256,16 +1955,12 @@ dump (void)
show_cgroups ();
show_clocks ();
show_compiler ();
-#ifndef PROCENV_ANDROID
show_confstrs ();
-#endif
show_cpu ();
show_env ();
show_fds ();
show_libc ();
-#ifndef PROCENV_ANDROID
show_libs ();
-#endif
show_rlimits ();
show_locale ();
show_memory ();
@@ -4283,6 +1978,7 @@ dump (void)
* as possible.
*/
show_rusage ();
+
show_semaphores ();
show_shared_mem ();
show_signals ();
@@ -4334,13 +2030,13 @@ get_network_address (const struct sockaddr *address, int family, char *name)
void
decode_if_flags (unsigned int flags)
{
- struct if_flag_map *p;
+ const struct procenv_map *p;
- for (p = if_flag_map; p && p->name; p++) {
- if (flags & p->flag) {
- object_open (FALSE);
- entry (p->name, "0x%x", p->flag);
- object_close (FALSE);
+ for (p = ops->if_flag_map; p && p->name; p++) {
+ if (flags & p->num) {
+ object_open (false);
+ entry (p->name, "0x%x", p->num);
+ object_close (false);
}
}
}
@@ -4382,64 +2078,37 @@ get_ipv6_scope_name (uint32_t scope)
return UNKNOWN_STR;
}
-int
-get_mtu (const struct ifaddrs *ifaddr)
-{
- int sock;
- struct ifreq ifr;
- unsigned long request = SIOCGIFMTU;
-
- assert (ifaddr);
-
- /* We need to create a socket to query an interfaces mac
- * address. Don't ask me why...
- */
- sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
-
- if (sock < 0)
- return -1;
-
- memset (&ifr, 0, sizeof (struct ifreq));
- strncpy (ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ-1);
-
- if (ioctl (sock, request, &ifr) < 0)
- ifr.ifr_mtu = 0;
-
- close (sock);
-
- return ifr.ifr_mtu;
-}
-
/*
*
* Returns: IEEE-802 format MAC address, or NULL on error.
*/
+#if !defined (PROCENV_PLATFORM_MINIX)
char *
get_mac_address (const struct ifaddrs *ifaddr)
{
char *data = NULL;
char *mac_address = NULL;
int i;
- int valid = FALSE;
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+ int valid = false;
+#if defined (PROCENV_PLATFORM_BSD) || defined (PROCENV_PLATFORM_DARWIN)
struct sockaddr_dl *link_layer;
#else
struct ifreq ifr;
int sock = -1;
#endif
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
+#if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_HURD) || defined (PROCENV_PLATFORM_GENERIC)
unsigned long request = SIOCGIFHWADDR;
#endif
assert (ifaddr);
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+#if defined (PROCENV_PLATFORM_BSD) || defined (PROCENV_PLATFORM_DARWIN)
link_layer = (struct sockaddr_dl *)ifaddr->ifa_addr;
#else
- /* We need to create a socket to query an interfaces mac
- * address. Don't ask me why...
+ /* We need to create a socket to query an interfaces MAC
+ * address.
*/
sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
@@ -4453,7 +2122,7 @@ get_mac_address (const struct ifaddrs *ifaddr)
goto out;
#endif
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+#if defined (PROCENV_PLATFORM_BSD) || defined (PROCENV_PLATFORM_DARWIN)
data = LLADDR (link_layer);
#else
data = (char *)ifr.ifr_hwaddr.sa_data;
@@ -4462,7 +2131,7 @@ get_mac_address (const struct ifaddrs *ifaddr)
if (data) {
for (i = 0; i < 6; i++) {
if (data[i]) {
- valid = TRUE;
+ valid = true;
break;
}
}
@@ -4490,412 +2159,24 @@ get_mac_address (const struct ifaddrs *ifaddr)
out:
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+#if defined (PROCENV_PLATFORM_BSD) || defined (PROCENV_PLATFORM_DARWIN)
/* NOP */
#else
close (sock);
#endif
return mac_address;
}
+#endif /* PROCENV_PLATFORM_MINIX */
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-void
-show_mounts_linux (ShowMountType what)
-{
- FILE *mtab;
- struct mntent *mnt;
- struct statvfs fs;
- unsigned int major = 0;
- unsigned int minor = 0;
- int have_stats;
-#if defined (PROCENV_LINUX)
- char canonical[PATH_MAX];
-#endif
-
- common_assert ();
-
- mtab = fopen (MOUNTS, "r");
-
- if (! mtab)
- return;
-
- while ((mnt = getmntent (mtab))) {
- have_stats = TRUE;
-
- if (what == SHOW_ALL || what == SHOW_MOUNTS) {
- unsigned multiplier = 0;
- fsblkcnt_t blocks = 0;
- fsblkcnt_t bfree = 0;
- fsblkcnt_t bavail = 0;
- fsblkcnt_t used_blocks = 0;
- fsblkcnt_t used_files = 0;
-#if defined (PROCENV_LINUX)
- int ret;
-#endif
-
- if (statvfs (mnt->mnt_dir, &fs) < 0) {
- have_stats = FALSE;
- } else {
- multiplier = fs.f_bsize / DF_BLOCK_SIZE;
-
- blocks = fs.f_blocks * multiplier;
- bfree = fs.f_bfree * multiplier;
- bavail = fs.f_bavail * multiplier;
- used_blocks = blocks - bfree;
- used_files = fs.f_files - fs.f_ffree;
- }
-
- (void)get_major_minor (mnt->mnt_dir,
- &major,
- &minor);
-
- assert (mnt->mnt_dir);
- section_open (mnt->mnt_dir);
-
- entry ("filesystem", "'%s'", mnt->mnt_fsname);
-
-#if defined (PROCENV_LINUX)
- ret = get_canonical (mnt->mnt_fsname, canonical, sizeof (canonical));
- entry ("canonical", "%s%s%s",
- ret ? "'" : "",
- canonical,
- ret ? "'" : "");
-#endif
-
- entry ("type", "'%s'", mnt->mnt_type);
- entry ("options", "'%s'", mnt->mnt_opts);
-
- show_pathconfs (what, mnt->mnt_dir);
-
- section_open ("device");
- entry ("major", "%u", major);
- entry ("minor", "%u", minor);
- section_close ();
-
- entry ("dump frequency", "%d", mnt->mnt_freq);
- entry ("fsck pass number", "%d", mnt->mnt_passno);
-
- if (have_stats) {
- union fsid_u {
- unsigned long int fsid;
- unsigned int val[2];
- } fsid_val;
-
- fsid_val.fsid = fs.f_fsid;
-
- entry ("fsid", "%.*x%.*x",
- 2 * sizeof (fsid_val.val[0]),
- fsid_val.val[0],
- 2 * sizeof (fsid_val.val[1]),
- fsid_val.val[1]);
-
- entry ("optimal block size", "%lu", fs.f_bsize);
-
- section_open ("blocks");
-
- entry ("size", "%lu bytes", DF_BLOCK_SIZE);
- entry ("total", "%lu", blocks);
- entry ("used", "%lu", used_blocks);
- entry ("free", "%lu", bfree);
- entry ("available", "%lu", bavail);
-
- section_close ();
-
- section_open ("files/inodes");
-
- entry ("total", "%lu", fs.f_files);
- entry ("used", "%lu", used_files);
- entry ("free", "%lu", fs.f_ffree);
-
- section_close ();
- } else {
- entry ("fsid", "%s", UNKNOWN_STR);
- entry ("optimal block size", "%s", UNKNOWN_STR);
-
- section_open ("blocks");
-
- entry ("size", "%lu bytes", DF_BLOCK_SIZE);
- entry ("total", "%s", UNKNOWN_STR);
- entry ("used", "%s", UNKNOWN_STR);
- entry ("free", "%s", UNKNOWN_STR);
- entry ("available", "%s", UNKNOWN_STR);
-
- section_close ();
-
- section_open ("files/inodes");
-
- entry ("total", "%s", UNKNOWN_STR);
- entry ("used", "%s", UNKNOWN_STR);
- entry ("free", "%s", UNKNOWN_STR);
-
- section_close ();
- }
-
- section_close ();
- } else {
- show_pathconfs (what, mnt->mnt_dir);
- }
- }
-
- fclose (mtab);
-}
-#endif
-
-#if defined (PROCENV_LINUX)
-void
-decode_extended_if_flags (const char *interface, unsigned short *flags)
-{
- int sock;
- struct ifreq ifr;
- struct if_extended_flag_map *p;
-
- assert (interface);
- assert (flags);
-
- /* We need to create a socket to query an interfaces mac
- * address. Don't ask me why...
- */
- sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
-
- if (sock < 0)
- return;
-
- memset (&ifr, 0, sizeof (struct ifreq));
- strncpy (ifr.ifr_name, interface, IFNAMSIZ-1);
-
- if (ioctl (sock, SIOCGIFPFLAGS, &ifr) < 0)
- goto out;
-
- *flags = ifr.ifr_flags;
-
- for (p = if_extended_flag_map; p && p->name; p++) {
- if (*flags & p->flag) {
- object_open (FALSE);
- entry (p->name, "0x%x", p->flag);
- object_close (FALSE);
- }
- }
-out:
- close (sock);
-}
-
-
-/**
- * linux_kernel_version:
- *
- * @major: major kernel version number,
- * @minor: minor kernel version number,
- * @revision: kernel revision version,
- *
- * @minor and @revision may be -1 to denote that those version
- * elements are not important to the caller. Once a parameter
- * has been specified as -1, subsequent parameters are ignored
- * (treated as -1 too).
- *
- * Returns: TRUE if running Linux kernel is atleast at version
- * specified by (@major, @minor, @revision), else FALSE.
- **/
-bool
-linux_kernel_version (int major, int minor, int revision)
-{
- int actual_version = 0x000000;
- int requested_version = 0x000000;
- int actual_major = -1;
- int actual_minor = -1;
- int actual_revision = -1;
- int ret;
-
- assert (uts.release);
- assert (sizeof (int) >= 4);
-
- /* We need something to work with */
- assert (major > 0);
-
- ret = sscanf (uts.release, "%d.%d.%d",
- &actual_major, &actual_minor,
- &actual_revision);
-
- /* We need something to compare against */
- assert (ret && actual_major != -1);
-
- requested_version |= (0xFF0000 & (major << 16));
-
- if (minor != -1) {
- requested_version |= (0x00FF00 & (minor << 8));
-
- if (revision != -1)
- requested_version |= (0x0000FF & revision);
- }
-
- if (actual_revision != -1) {
- actual_version |= (0x0000FF & actual_revision);
- }
-
- if (actual_minor != -1)
- actual_version |= (0x00FF00 & (actual_minor << 8));
-
- if (actual_major != -1)
- actual_version |= (0xFF0000 & (actual_major << 16));
-
-
- if (actual_version >= requested_version)
- return TRUE;
-
- return FALSE;
-}
-
-void
-show_numa_memory (void)
-{
-#if defined (HAVE_NUMA_H)
- int policy;
- const char *policy_name;
- char *allowed_list = NULL;
- int ret;
- unsigned long node;
- unsigned long allowed_size;
-
-#if defined (HAVE_NUMA_H)
-#if LIBNUMA_API_VERSION == 2
- struct bitmask *allowed;
-#else
- nodemask_t allowed;
-#endif
-#endif
-
- /* part of the libnuma public API - stop the library calling
- * exit(3) on error.
- */
- numa_exit_on_error = 0;
-
- /* TRUE if any numa nodes have been displayed yet */
- int displayed = FALSE;
-
- /* Number of numa nodes in *current* range */
- size_t count = 0;
-
- /* Only valid to read these when count is >0 */
- size_t last = 0;
- size_t first = 0;
-#endif /* HAVE_NUMA_H */
-
- header ("numa");
-
-#if defined (HAVE_NUMA_H)
- if (numa_available () < 0)
- /* NUMA not supported on this system */
- goto out;
-
-#if LIBNUMA_API_VERSION == 2
- entry ("api version", "%d", 2);
-#else
- entry ("api version", "%d", 1);
-#endif
-
- ret = get_mempolicy (&policy, NULL, 0, 0, 0);
-
- if (ret < 0) {
- entry ("policy", "%s", UNKNOWN_STR);
- goto out;
- }
-
- policy_name = get_numa_policy (policy);
-
- entry ("policy", "%s", policy_name ? policy_name : UNKNOWN_STR);
-
-#if LIBNUMA_API_VERSION == 2
- entry ("maximum nodes", "%d", numa_num_possible_nodes ());
- entry ("configured nodes", "%d", numa_num_configured_nodes ());
-
- allowed = numa_get_mems_allowed ();
- if (! allowed)
- die ("failed to query NUMA allowed list");
-
- allowed_size = allowed->size;
-
-#else
- entry ("maximum nodes", "%s", UNKNOWN_STR);
- entry ("configured nodes", "%d", numa_max_node ());
-
- allowed = numa_get_run_node_mask ();
- allowed_size = NUMA_NUM_NODES;
-#endif
-
- for (node = 0; node < allowed_size; node++) {
- if (PROCENV_NUMA_BITMASK_ISSET (allowed, node)) {
- /* Record first entry in the range */
- if (! count)
- first = node;
-
- last = node;
- count++;
- } else {
- if (count) {
- if (first == last) {
- appendf (&allowed_list, "%s%d",
- displayed ? "," : "",
- first);
- } else {
- appendf (&allowed_list, "%s%d-%d",
- displayed ? "," : "",
- first, last);
- }
- displayed = TRUE;
- }
-
- /* Reset */
- count = 0;
- }
- }
-
- if (count) {
- if (first == last) {
- appendf (&allowed_list, "%s%d",
- displayed ? "," : "",
- first);
- } else {
- appendf (&allowed_list, "%s%d-%d",
- displayed ? "," : "",
- first, last);
- }
- }
-
- entry ("allowed list", "%s", allowed_list);
-
-#if LIBNUMA_API_VERSION == 2
- numa_free_nodemask (allowed);
-#endif
-
- free (allowed_list);
-
-out:
-#endif /* HAVE_NUMA_H */
- footer ();
-}
-
-#if defined (HAVE_NUMA_H)
-const char *
-get_numa_policy (int policy)
-{
- struct procenv_map *p;
-
- for (p = numa_mempolicy_map; p && p->name; p++) {
- if (p->num == policy)
- return p->name;
- }
-
- return NULL;
-}
-#endif /* HAVE_NUMA_H */
-
+#if defined (PROCENV_PLATFORM_LINUX)
const char *
get_personality_name (unsigned int domain)
{
- struct personality_map *m;
-
- for (m = personality_map; m && m->name; m++) {
- if (m->personality == (domain & PER_MASK))
+ const struct procenv_map *m;
+
+ for (m = ops->personality_map; m && m->name; m++) {
+ if (m->num == (domain & PER_MASK))
return m->name;
}
@@ -4905,23 +2186,23 @@ get_personality_name (unsigned int domain)
char *
get_personality_flags (unsigned int flags)
{
- struct personality_flag_map *m;
- char *list = NULL;
- int first = TRUE;
+ const struct procenv_map *m;
+ char *list = NULL;
+ int first = true;
- for (m = personality_flag_map; m && m->name; m++) {
- if (flags & m->flag) {
+ for (m = ops->personality_flag_map; m && m->name; m++) {
+ if (flags & m->num) {
appendf (&list, "%s%s",
first ? "" : ", ",
m->name);
- first = FALSE;
+ first = false;
}
}
return list;
}
-#endif /* PROCENV_LINUX */
+#endif /* PROCENV_PLATFORM_LINUX */
void
show_mounts (ShowMountType what)
@@ -4930,13 +2211,8 @@ show_mounts (ShowMountType what)
header (what == SHOW_PATHCONF ? "pathconf" : "mounts");
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- show_mounts_linux (what);
-#endif
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
- show_mounts_bsd (what);
-#endif
+ if (ops->show_mounts)
+ ops->show_mounts (what);
footer ();
}
@@ -4945,13 +2221,13 @@ const char *
get_net_family_name (sa_family_t family)
{
switch (family) {
-#if defined (PROCENV_LINUX)
+#if defined (PROCENV_PLATFORM_LINUX)
case AF_PACKET:
return "AF_PACKET";
break;
#endif
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+#if defined (PROCENV_PLATFORM_BSD)
case AF_LINK:
return "AF_LINK";
break;
@@ -5009,9 +2285,8 @@ show_network_if (const struct ifaddrs *ifa, const char *mac_address)
container_open ("fields");
-#if defined (PROCENV_LINUX)
- decode_extended_if_flags (ifa->ifa_name, &ext_flags);
-#endif
+ if (ops->show_extended_if_flags)
+ ops->show_extended_if_flags (ifa->ifa_name, &ext_flags);
container_close ();
@@ -5019,9 +2294,10 @@ show_network_if (const struct ifaddrs *ifa, const char *mac_address)
/*******************************/
- mtu = get_mtu (ifa);
+ if (ops->get_mtu)
+ mtu = ops->get_mtu (ifa);
-#if defined (PROCENV_HURD)
+#if defined (PROCENV_PLATFORM_HURD)
/* No AF_LINK/AF_PACKET on Hurd atm */
entry ("mac", "%s", UNKNOWN_STR);
#else
@@ -5041,7 +2317,8 @@ show_network_if (const struct ifaddrs *ifa, const char *mac_address)
get_network_address (ifa->ifa_netmask, family, address);
entry ("netmask", "%s", ifa->ifa_netmask ? address : NA_STR);
-#if !defined (PROCENV_HURD)
+#if !defined (PROCENV_PLATFORM_HURD)
+#if defined (IFF_BROADCAST)
if (family != PROCENV_LINK_LEVEL_FAMILY) {
if ((ifa->ifa_flags & IFF_BROADCAST) && ifa->ifa_broadaddr) {
get_network_address (ifa->ifa_broadaddr, family, address);
@@ -5050,483 +2327,25 @@ show_network_if (const struct ifaddrs *ifa, const char *mac_address)
}
} else {
#endif
+#endif
entry ("broadcast", "%s", NA_STR);
-#if !defined (PROCENV_HURD)
+#if !defined (PROCENV_PLATFORM_HURD)
+#if defined (IFF_BROADCAST)
}
#endif
+#endif
+#if defined (IFF_POINTOPOINT)
if (ifa->ifa_flags & IFF_POINTOPOINT && ifa->ifa_dstaddr) {
get_network_address (ifa->ifa_dstaddr, family, address);
entry ("point-to-point", "%s", address);
}
-
- section_close ();
-}
-
-/*
- * BSD returns an additional AF_LINK ifaddrs containing the
- * actual link-layer MAC address for each interface.
- *
- * Linux does the same but with one additional AF_PACKET family / interface.
- *
- * This is somewhat noisome since for BSD we need to cache the MAC addresses
- * such that they can be retrieved when the _next_ ifaddrs structure
- * appears for the *same* interface, but we only want to
- * display the non-AF_LINK elements *unless* they refer
- * to an interface with no associated address.
- *
- * The situation for Linux is similar but we only care
- * about AF_PACKET entries for interfaces that have no
- * associated address since we can extract the MAC
- * address using an ioctl (rather than considering the
- * AF_PACKET element).
- *
- * The strategy therefore is to:
- *
- * 1) Cache all AF_LINK/AF_PACKET elements.
- * 2) Once an element arrives that matches an interface
- * name found in the cache, use that as necessary (extra
- * the MAC for BSD, NOP for Linux), then free that cache
- * element.
- * 3) Having processed all entries, if any entries are
- * left in the cache, they must refer to interfaces that
- * have no address, so display them.
- *
- * XXX: Note the implicit assumption that the AF_LINK/AF_PACKET entries
- * will appear _before_ the corresponding entry containing address
- * details for the interface in the output of getifaddrs(): observations
- * suggests this _seems_ to be the case, but is not documented as being
- * guaranteed.
- */
-#ifdef PROCENV_ANDROID
-
-void
-show_network (void)
-{
- /* Bionic isn't actually that bionic at all :( */
- header ("network");
- footer ();
-}
-
-#else
-
-void
-show_network (void)
-{
- struct ifaddrs *if_addrs;
- struct ifaddrs *ifa;
- char *mac_address = NULL;
- struct network_map *head = NULL;
- struct network_map *node = NULL;
- struct network_map *tmp = NULL;
-
- common_assert ();
-
- header ("network");
-
- /* Query all network interfaces */
- if (getifaddrs (&if_addrs) < 0)
- return;
-
- /* Construct an initial node for the cache */
- head = calloc (1, sizeof (struct network_map));
- assert (head);
-
- /* Iterate over all network interfaces */
- for (ifa = if_addrs; ifa; ifa = ifa->ifa_next) {
-#if !defined (PROCENV_HURD)
- int family;
#endif
- if (! ifa->ifa_addr)
- continue;
-
-#if !defined (PROCENV_HURD)
- family = ifa->ifa_addr->sa_family;
-
- if (family == PROCENV_LINK_LEVEL_FAMILY) {
-
- /* Add link level interface details to the cache */
- mac_address = get_mac_address (ifa);
-
- node = calloc (1, sizeof (struct network_map));
- assert (node);
-
- /* Conveniently, an ifaddrs contains a bunch of
- * pointers and some flags.
- *
- * Since all those pointers are valid until we
- * call freeifaddrs(), all we need to do is copy
- * the flags since the memcpy will copy the
- * pointers addresses for us :)
- */
- memcpy (&node->ifaddr, ifa, sizeof (struct ifaddrs));
- node->ifaddr.ifa_flags = ifa->ifa_flags;
-
- /* Since we've already formatted the MAC
- * address, we'll cache that too.
- */
- node->mac_address = mac_address;
- mac_address = NULL;
-
- /* prepend */
- node->next = head->next;
- if (head->next)
- head->next->prev = node;
- node->prev = head;
- head->next = node;
-
- continue;
- }
-#endif
-
- /* From now on, we're only looking at interfaces with an
- * address.
- */
-
- /* Search for an entry corresponding to the interface in the cache */
- for (node = head->next; node && node->ifaddr.ifa_name; node = node->next) {
- if (! strcmp (node->ifaddr.ifa_name, ifa->ifa_name)) {
-
- /* Save */
- mac_address = node->mac_address
- ? strdup (node->mac_address)
- : NULL;
-
- /* Unlink existing node as it has now served its purpose */
- node->prev->next = node->next;
- if (node->next)
- node->next->prev = node->prev;
-
- /* Destroy */
- if (node->mac_address)
- free (node->mac_address);
- free (node);
-
- break;
- }
- }
-
- /* Display the interface (which must have an associated address) */
- show_network_if (ifa, mac_address);
- if (mac_address) {
- free (mac_address);
- mac_address = NULL;
- }
- }
-
- /* Destroy the cache, displaying any interfaces not previously displayed.
- * These by definition cannot have addresses assigned to them.
- */
- for (node = head->next; node && node->ifaddr.ifa_name; node = tmp) {
-
- tmp = node->next;
-
- show_network_if (&node->ifaddr, node->mac_address);
-
- /* Destroy */
- if (node->mac_address)
- free (node->mac_address);
- free (node);
- }
-
- free (head);
- freeifaddrs (if_addrs);
-
- footer ();
-}
-#endif
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-
-char *
-get_mount_opts_bsd (uint64_t flags)
-{
- struct mntopt_map *opt;
- char *str = NULL;
- size_t len = 0;
- size_t total = 0;
- int count = 0;
-
- if (! flags)
- return strdup ("");
-
- /* Calculate how much space we need to allocate by iterating
- * array for the first time.
- */
- for (opt = mntopt_map; opt && opt->name; opt++) {
- if (flags & opt->flag) {
- count++;
- len += strlen (opt->name);
- }
- }
-
- if (count > 1) {
- /* we need space for the option value themselves, plus a
- * ", " separator between each option (except the first),
- * and finally space for the nul terminator */
- total = len + (count-1) + 1;
- } else {
- total = len + 1;
- }
-
- str = calloc (total, sizeof (char));
- if (! str)
- die ("failed to allocate space for mount options");
-
- /* Re-iterate to construct the string. This is still going to be
- * a lot quicker than calling malloc a stack of times.
- */
- for (opt = mntopt_map; opt && opt->name; opt++) {
- if (flags & opt->flag) {
- strcat (str, opt->name);
- if (count > 1)
- strcat (str, ",");
- count--;
- }
- }
-
- return str;
-}
-
-void
-show_mounts_bsd (ShowMountType what)
-{
- int count;
- struct statfs *mounts;
- struct statfs *mnt;
- unsigned int major = 0;
- unsigned int minor = 0;
- int i;
- unsigned multiplier = 0;
- statfs_int_type blocks;
- statfs_int_type bfree;
- statfs_int_type bavail;
- statfs_int_type used;
-
- common_assert ();
-
- /* Note that returned memory cannot be freed (by us) */
- count = getmntinfo (&mounts, MNT_WAIT);
-
- if (! count)
- die ("unable to query mount info");
-
- mnt = mounts;
-
- for (i = 0; i < count; i++) {
- char *opts = NULL;
-
- opts = get_mount_opts_bsd (mnt->f_flags);
- if (! opts)
- die ("cannot determine FS flags for mountpoint '%s'",
- mnt->f_mntonname);
-
- if (what == SHOW_ALL || what == SHOW_MOUNTS) {
- (void)get_major_minor (mnt->f_mntonname,
- &major,
- &minor);
-
- multiplier = mnt->f_bsize / DF_BLOCK_SIZE;
- blocks = mnt->f_blocks * multiplier;
- bfree = mnt->f_bfree * multiplier;
- bavail = mnt->f_bavail * multiplier;
- used = blocks - bfree;
-
- assert (mnt->f_mntfromname);
- section_open (mnt->f_mntfromname);
-
- entry ("dir", "'%s'", mnt->f_mntonname);
- entry ("type", "%s", mnt->f_fstypename);
- entry ("options", "'%s'", opts);
-
- section_open ("device");
- entry ("major", "%u", major);
- entry ("minor", "%u", minor);
- section_close ();
-
- entry ("fsid", "%.*x%.*x",
- /* Always zero on BSD? */
- 2 * sizeof (mnt->f_fsid.val[0]),
- mnt->f_fsid.val[0],
- 2 * sizeof (mnt->f_fsid.val[1]),
- mnt->f_fsid.val[1]);
-
- entry ("optimal block size", "%" statfs_int_fmt,
- mnt->f_bsize);
-
- section_open ("blocks");
-
- entry ("size", "%lu bytes", DF_BLOCK_SIZE);
-
- entry ("total", "%" statfs_int_fmt, blocks);
- entry ("used", "%"statfs_int_fmt, used);
- entry ("free", "%" statfs_int_fmt, bfree);
- entry ("available", "%" statfs_int_fmt, bavail);
-
- section_close ();
-
- section_open ("files/inodes");
-
- entry ("total", "%" statfs_int_fmt, mnt->f_files);
- entry ("used", "%" statfs_int_fmt,
- mnt->f_files - mnt->f_ffree);
- entry ("free", "%" statfs_int_fmt, mnt->f_ffree);
-
- section_close ();
-
- section_close ();
- }
-
- if (what == SHOW_ALL || what == SHOW_PATHCONF)
- show_pathconfs (what, mnt->f_mntonname);
- mnt++;
-
- free (opts);
- }
-}
-
-#endif
-
-#if defined (PROCENV_BSD) && defined (HAVE_SYS_CAPABILITY_H)
-void
-show_capabilities_bsd (int fd)
-{
- int ret;
- u_int mode;
- cap_rights_t rights;
-
- ret = cap_getmode (&mode);
- if (ret < 0) {
- /* No Capsicum support */
- goto out;
- }
-
- ret = cap_rights_get (fd, &rights);
- if (ret < 0) {
- /* Cannot query capabilities */
- goto out;
- }
-
- show_capsicum_cap (rights, CAP_ACCEPT);
- show_capsicum_cap (rights, CAP_ACL_CHECK);
- show_capsicum_cap (rights, CAP_ACL_DELETE);
- show_capsicum_cap (rights, CAP_ACL_GET);
- show_capsicum_cap (rights, CAP_ACL_SET);
- show_capsicum_cap (rights, CAP_BIND);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_BINDAT);
- show_capsicum_cap (rights, CAP_CHFLAGSAT);
-#endif
- show_capsicum_cap (rights, CAP_CONNECT);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_CONNECTAT);
-#endif
- show_capsicum_cap (rights, CAP_CREATE);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_EVENT);
-#endif
- show_capsicum_cap (rights, CAP_EXTATTR_DELETE);
- show_capsicum_cap (rights, CAP_EXTATTR_GET);
- show_capsicum_cap (rights, CAP_EXTATTR_LIST);
- show_capsicum_cap (rights, CAP_EXTATTR_SET);
- show_capsicum_cap (rights, CAP_FCHDIR);
- show_capsicum_cap (rights, CAP_FCHFLAGS);
- show_capsicum_cap (rights, CAP_FCHMOD);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_FCHMODAT);
-#endif
- show_capsicum_cap (rights, CAP_FCHOWN);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_FCHOWNAT);
-#endif
- show_capsicum_cap (rights, CAP_FCNTL);
- show_capsicum_cap (rights, CAP_FEXECVE);
- show_capsicum_cap (rights, CAP_FLOCK);
- show_capsicum_cap (rights, CAP_FPATHCONF);
- show_capsicum_cap (rights, CAP_FSCK);
- show_capsicum_cap (rights, CAP_FSTAT);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_FSTATAT);
-#endif
- show_capsicum_cap (rights, CAP_FSTATFS);
- show_capsicum_cap (rights, CAP_FSYNC);
- show_capsicum_cap (rights, CAP_FTRUNCATE);
- show_capsicum_cap (rights, CAP_FUTIMES);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_FUTIMESAT);
-#endif
- show_capsicum_cap (rights, CAP_GETPEERNAME);
- show_capsicum_cap (rights, CAP_GETSOCKNAME);
- show_capsicum_cap (rights, CAP_GETSOCKOPT);
- show_capsicum_cap (rights, CAP_IOCTL);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_KQUEUE);
- show_capsicum_cap (rights, CAP_KQUEUE_CHANGE);
- show_capsicum_cap (rights, CAP_KQUEUE_EVENT);
- show_capsicum_cap (rights, CAP_LINKAT);
-#endif
- show_capsicum_cap (rights, CAP_LISTEN);
- show_capsicum_cap (rights, CAP_LOOKUP);
- show_capsicum_cap (rights, CAP_MAC_GET);
- show_capsicum_cap (rights, CAP_MAC_SET);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_MKDIRAT);
- show_capsicum_cap (rights, CAP_MKFIFOAT);
- show_capsicum_cap (rights, CAP_MKNODAT);
- show_capsicum_cap (rights, CAP_MMAP);
- show_capsicum_cap (rights, CAP_MMAP_R);
- show_capsicum_cap (rights, CAP_MMAP_RW);
- show_capsicum_cap (rights, CAP_MMAP_RWX);
- show_capsicum_cap (rights, CAP_MMAP_RX);
- show_capsicum_cap (rights, CAP_MMAP_W);
- show_capsicum_cap (rights, CAP_MMAP_WX);
- show_capsicum_cap (rights, CAP_MMAP_X);
-#endif
- show_capsicum_cap (rights, CAP_PDGETPID);
- show_capsicum_cap (rights, CAP_PDKILL);
- show_capsicum_cap (rights, CAP_PDWAIT);
- show_capsicum_cap (rights, CAP_PEELOFF);
- show_capsicum_cap (rights, CAP_POLL_EVENT);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_PREAD);
- show_capsicum_cap (rights, CAP_PWRITE);
-#endif
- show_capsicum_cap (rights, CAP_READ);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_RECV);
- show_capsicum_cap (rights, CAP_RENAMEAT);
-#endif
- show_capsicum_cap (rights, CAP_SEEK);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_SEEK_TELL);
-#endif
- show_capsicum_cap (rights, CAP_SEM_GETVALUE);
- show_capsicum_cap (rights, CAP_SEM_POST);
- show_capsicum_cap (rights, CAP_SEM_WAIT);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_SEND);
-#endif
- show_capsicum_cap (rights, CAP_SETSOCKOPT);
- show_capsicum_cap (rights, CAP_SHUTDOWN);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_SOCK_CLIENT);
- show_capsicum_cap (rights, CAP_SOCK_SERVER);
- show_capsicum_cap (rights, CAP_SYMLINKAT);
-#endif
- show_capsicum_cap (rights, CAP_TTYHOOK);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_UNLINKAT);
-#endif
- show_capsicum_cap (rights, CAP_WRITE);
-
-out:
- /* clang requires this */
- return;
+ section_close ();
}
-#endif /* (PROCENV_BSD) && defined (HAVE_SYS_CAPABILITY_H) */
void
get_priorities (void)
@@ -5536,685 +2355,14 @@ get_priorities (void)
priority.user = getpriority (PRIO_USER , 0);
}
-bool
-uid_match (uid_t uid)
-{
- return uid == getuid ();
-}
-
-
-/**
- * in_container:
- *
- * Determine if running inside a container.
- *
- * Returns: Name of container type, or NO_STR.
- **/
-const char *
-container_type (void)
-{
- struct stat statbuf;
- char buffer[1024];
- FILE *f;
-#if defined (PROCENV_LINUX)
- dev_t expected;
-
- expected = makedev (5, 1);
-#endif
-
- if (stat ("/dev/console", &statbuf) < 0)
- goto out;
-
-#if defined (PROCENV_BSD)
- if (misc.in_jail)
- return "jail";
-#endif
- /* LXC's /dev/console is actually a pty */
-#if defined (PROCENV_LINUX)
- if (major (statbuf.st_rdev) != major (expected)
- || (minor (statbuf.st_rdev)) != minor (expected))
- return "lxc";
-#endif
-
- if (! stat ("/proc/vz", &statbuf) && stat ("/proc/bc", &statbuf) < 0)
- return "openvz";
-
- f = fopen ("/proc/self/status", "r");
- if (! f)
- goto out;
-
- while (fgets (buffer, sizeof (buffer), f)) {
- size_t len = strlen (buffer);
- buffer[len-1] = '\0';
-
- if (strstr (buffer, "VxID") == buffer) {
- fclose (f);
- return "vserver";
- }
- }
-
- fclose (f);
-
-out:
- return NO_STR;
-}
-
-/**
- * in_chroot:
- *
- * Determine if running inside a chroot environment.
- *
- * Failures are fatal.
- *
- * Returns TRUE if within a chroot, else FALSE.
- **/
-bool
-in_chroot (void)
-{
- struct stat st;
- int i;
- int root_inode, self_inode;
- char root[] = "/";
- char self[] = "/proc/self/root";
- char bsd_self[] = "/proc/curproc";
- char *dir = NULL;
-
- i = stat (root, &st);
- if (i != 0) {
- dir = root;
- goto error;
- }
-
- root_inode = st.st_ino;
-
- /*
- * Inode 2 is the root inode for most filesystems. However, XFS
- * uses 128 for root.
- */
- if (root_inode != 2 && root_inode != 128)
- return TRUE;
-
- i = stat (bsd_self, &st);
- if (i == 0) {
- /* Give up here if running on BSD */
- return FALSE;
- }
-
- i = stat (self, &st);
- if (i != 0)
- return FALSE;
-
- self_inode = st.st_ino;
-
- if (root_inode == self_inode)
- return FALSE;
-
- return TRUE;
-
-error:
- die ("cannot stat '%s'", dir);
-
- /* compiler appeasement */
- return FALSE;
-}
-
-/* detect if setsid(2) has been called */
-bool
-is_session_leader (void)
-{
- return user.sid == user.pid;
-}
-
-/* detect if setpgrp(2)/setpgid(2) (or setsid(2)) has been called */
-bool
-is_process_group_leader (void)
-{
- return user.pgroup == user.pid;
-}
-
-void
-show_proc_branch (void)
-{
- common_assert ();
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD)
- show_proc_branch_linux ();
-#endif
-
-#if defined (PROCENV_HURD)
- /* FIXME: how can this be queried in Hurd?? */
-#endif
-
-#if defined (PROCENV_BSD)
- show_proc_branch_bsd ();
-#endif
-}
-
-#if defined (PROCENV_BSD)
-/* Who would have thought handling PIDs was so tricky? */
-void
-show_proc_branch_bsd (void)
-{
- int count = 0;
- int i;
- char errors[_POSIX2_LINE_MAX];
- kvm_t *kvm;
- struct kinfo_proc *procs;
- struct kinfo_proc *p;
- pid_t self, current;
- int done = FALSE;
- char *str = NULL;
- pid_t ultimate_parent = 0;
-
- common_assert ();
-
- self = current = getpid ();
-
- kvm = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errors);
- if (! kvm)
- die ("unable to open kvm");
-
- procs = kvm_getprocs (kvm, KERN_PROC_PROC, 0, &count);
- if (! procs)
- die ("failed to get process info");
-
- /* Calculate the lowest PID number which gives us the ultimate
- * parent of all processes.
- *
- * On BSD sytems, normally PID 0 ('[kernel]') is the ultimate
- * parent rather than PID 1 ('init').
- *
- * However, this doesn't work in a BSD jail since in that
- * environment:
- *
- * - there is no init process visible.
- * - there is no kernel thread visible.
- * - the ultimate parent PID will either by 1 (the "invisible"
- * init process) or 'n' where 'n' is a PID>1 which is also
- * "invisible" (since it lives outside the jail in the host
- * environment).
- *
- * Confused yet?
- */
-
- p = &procs[0];
- ultimate_parent = p->ki_pid;
-
- for (i = 1; i < count; i++) {
- p = &procs[i];
- if (p->ki_pid < ultimate_parent)
- ultimate_parent = p->ki_pid;
- }
-
- while (! done) {
- for (i = 0; i < count && !done; i++) {
- p = &procs[i];
-
- if (p->ki_pid == current) {
- if (misc.in_jail) {
- struct kinfo_proc *p2;
- int ppid_found = FALSE;
- int j;
-
- /* Determine if the parent PID
- * actually exists within the
- * jail.
- */
- for (j = 0; j < count; j++) {
- p2 = &procs[j];
-
- if (p2->ki_pid == p->ki_ppid) {
- ppid_found = TRUE;
- break;
- }
- }
-
- if (p->ki_ppid == 1 || (p->ki_ppid && ! ppid_found)) {
- /* Found the "last" PID (whose parent is either
- * the "invisible init" or which exists outside the jail)
- * so record it and hop out.
- */
- appendf (&str, "%d ('%s') %d (%s)",
- (int)current, p->ki_comm,
- p->ki_ppid, UNKNOWN_STR);
- done = TRUE;
- break;
- } else {
- /* Found a valid parent pid */
- appendf (&str, "%d ('%s'), ",
- (int)current, p->ki_comm);
- }
-
- } else if (! ultimate_parent && current == ultimate_parent) {
-
- /* Found the "last" PID so record it and hop out */
- appendf (&str, "%d ('%s')",
- (int)current, p->ki_comm);
- done = TRUE;
- break;
-
- } else {
-
- /* Found a valid parent pid */
- appendf (&str, "%d ('%s'), ",
- (int)current, p->ki_comm);
- }
-
- /* Move on */
- current = p->ki_ppid;
- }
- }
- }
-
- if (kvm_close (kvm) < 0)
- die ("failed to close kvm");
-
- entry ("ancestry", "%s", str);
- free (str);
-}
-#endif
-
-#if defined (PROCENV_LINUX)
-void
-show_prctl_linux (void)
-{
- int rc;
- int arg2;
- char name[17] = { 0 };
-
- common_assert ();
-
- section_open ("prctl");
-
-#ifdef PR_GET_ENDIAN
- if (LINUX_KERNEL_MMR (2, 6, 18)) {
- const char *value;
-
- rc = prctl (PR_GET_ENDIAN, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_ENDIAN_BIG:
- value = BIG_STR;
- break;
- case PR_ENDIAN_LITTLE:
- value = LITTLE_STR;
- break;
- case PR_ENDIAN_PPC_LITTLE:
- value = "PowerPC pseudo little endian";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("process endian", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_DUMPABLE
- if (LINUX_KERNEL_MMR (2, 3, 20)) {
- const char *value;
- rc = prctl (PR_GET_DUMPABLE, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case 0:
- value = NO_STR;
- break;
- case 1:
- value = YES_STR;
- break;
- case 2:
- value = "root-only";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("dumpable", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_FPEMU
- /* Use the earliest version where this option was introduced
- * (for some architectures).
- */
- if (LINUX_KERNEL_MMR (2, 4, 18)) {
- const char *value;
-
- rc = prctl (PR_GET_FPEMU, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_FPEMU_NOPRINT:
- value = YES_STR;
- break;
- case PR_FPEMU_SIGFPE:
- value = "send SIGFPE";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("floating point emulation", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_FPEXC
- /* Use the earliest version where this option was introduced
- * (for some architectures).
- */
- if (LINUX_KERNEL_MMR (2, 4, 21)) {
- const char *value;
-
- rc = prctl (PR_GET_FPEXC, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_FP_EXC_SW_ENABLE:
- value = "software";
- break;
- case PR_FP_EXC_DISABLED:
- value = "disabled";
- break;
- case PR_FP_EXC_NONRECOV:
- value = "non-recoverable";
- break;
- case PR_FP_EXC_ASYNC:
- value = "asynchronous";
- break;
- case PR_FP_EXC_PRECISE:
- value = "precise";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("floating point exceptions", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_NAME
- if (LINUX_KERNEL_MMR (2, 6, 11)) {
- rc = prctl (PR_GET_NAME, name, 0, 0, 0);
- if (rc < 0)
- entry ("process name", "%s", UNKNOWN_STR);
- else
- entry ("process name", "%s", name);
- }
-
-#endif
-
-#ifdef PR_GET_PDEATHSIG
- if (LINUX_KERNEL_MMR (2, 3, 15)) {
- rc = prctl (PR_GET_PDEATHSIG, &arg2, 0, 0, 0);
- if (rc < 0)
- entry ("parent death signal", "%s", UNKNOWN_STR);
- else if (rc == 0)
- entry ("parent death signal", "disabled");
- else
- entry ("parent death signal", "%d", arg2);
- }
-#endif
-
-#ifdef PR_GET_SECCOMP
- if (LINUX_KERNEL_MMR (2, 6, 23)) {
- const char *value;
-
- rc = prctl (PR_GET_SECCOMP, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case 0:
- value = "disabled";
- break;
- case 1:
- value = "read/write/exit (mode 1)";
- break;
- case 2:
- value = "BPF (mode 2)";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("secure computing", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_TIMING
- /* Not 100% accurate - this option was actually
- * introduced in 2.6.0-test4
- */
- if (LINUX_KERNEL_MMR (2, 6, 1)) {
- const char *value;
- rc = prctl (PR_GET_TIMING, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case PR_TIMING_STATISTICAL:
- value = "statistical";
- break;
- case PR_TIMING_TIMESTAMP:
- value = "time-stamp";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("process timing", "%s", value);
- }
-#endif
-
-#if defined (PR_GET_TSC) && defined (PROCENV_ARCH_X86)
- if (LINUX_KERNEL_MMR (2, 6, 26)) {
- const char *value;
-
- rc = prctl (PR_GET_TSC, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_TSC_ENABLE:
- value = "enabled";
- break;
- case PR_TSC_SIGSEGV:
- value = "segmentation fault";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("timestamp counter read", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_UNALIGNED
- if (LINUX_KERNEL_MMR (2, 3, 48)) {
- const char *value;
-
- rc = prctl (PR_GET_UNALIGNED, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_UNALIGN_NOPRINT:
- value = "fix-up";
- break;
- case PR_UNALIGN_SIGBUS:
- value = "send SIGBUS";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("unaligned access", "%s", value);
- }
-#endif
-
-#ifdef PR_MCE_KILL_GET
- if (LINUX_KERNEL_MMR (2, 6, 32)) {
- const char *value;
-
- rc = prctl (PR_MCE_KILL_GET, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case PR_MCE_KILL_DEFAULT:
- value = "system default";
- break;
- case PR_MCE_KILL_EARLY:
- value = "early kill";
- break;
- case PR_MCE_KILL_LATE:
- value = "late kill";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("machine-check exception", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_NO_NEW_PRIVS
- if (LINUX_KERNEL_MM (3, 5)) {
- const char *value;
-
- rc = prctl (PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case 0:
- value = "normal execve";
- break;
- case 1:
- value = "enabled";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("no new privileges", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_TIMERSLACK
- if (LINUX_KERNEL_MMR (2, 6, 28)) {
- rc = prctl (PR_GET_TIMERSLACK, 0, 0, 0, 0);
- if (rc < 0)
- entry ("timer slack", "%s", UNKNOWN_STR);
- else
- entry ("timer slack", "%dns", rc);
- }
-#endif
-
-#ifdef PR_GET_CHILD_SUBREAPER
- if (LINUX_KERNEL_MM (3, 4)) {
- rc = prctl (PR_GET_CHILD_SUBREAPER, &arg2, 0, 0, 0);
- if (rc < 0)
- entry ("child subreaper", "%s", UNKNOWN_STR);
- else
- entry ("child subreaper", "%s", arg2 ? YES_STR : NO_STR);
- }
-#endif
-
-#ifdef PR_GET_TID_ADDRESS
- rc = prctl (PR_GET_TID_ADDRESS, &arg2, 0, 0, 0);
- if (rc < 0)
- entry ("clear child tid address", "%s", UNKNOWN_STR);
- else
- entry ("clear child tid address", "%p", arg2);
-#endif
-
- section_close ();
-}
-
-#endif
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD)
void
-show_proc_branch_linux (void)
+handle_proc_branch (void)
{
- char buffer[1024];
- char path[PATH_MAX];
- char name[16];
- char pid[16];
- char ppid[16];
- size_t len;
- char *p;
- FILE *f;
- char *str = NULL;
-
common_assert ();
- sprintf (pid, "%d", (int)getpid ());
-
- /* This is one God-awful interface */
- while (TRUE) {
- sprintf (path, "/proc/%s/status", pid);
-
- f = fopen (path, "r");
- if (! f) {
- appendf (&str, "%s", UNKNOWN_STR);
- goto out;
- }
-
- while (fgets (buffer, sizeof (buffer), f)) {
- len = strlen (buffer);
- buffer[len-1] = '\0';
-
- if ((p=strstr (buffer, "Name:")) == buffer) {
- p += 1+strlen ("Name:"); /* jump over tab char */
- sprintf (name, "%s", p);
- }
-
- if ((p=strstr (buffer, "PPid:")) == buffer) {
- p += 1+strlen ("PPid:"); /* jump over tab char */
- sprintf (ppid, "%s", p);
-
- /* got all we need now */
- break;
- }
- }
-
- fclose (f);
-
- /* ultimate parent == PID 1 == '/sbin/init' */
- if (! strcmp (pid, "1")) {
- appendf (&str, "%s ('%s')", pid, name);
- break;
- } else {
- appendf (&str, "%s ('%s'), ", pid, name);
- }
-
- /* parent is now the pid to search for */
- sprintf (pid, "%s", ppid);
- }
-out:
-
- entry ("ancestry", "%s", str);
- free (str);
+ if (ops->handle_proc_branch)
+ ops->handle_proc_branch ();
}
-#endif
/* More verbose version of stty(1).
*
@@ -6259,9 +2407,8 @@ show_tty_attrs (void)
work:
user.tty_fd = fds[i];
-#ifdef PROCENV_LINUX
- get_tty_locked_status (&lock_status);
-#endif
+ if (ops->get_tty_locked_status)
+ ops->get_tty_locked_status (&lock_status);
/*****************************************/
section_open ("c_iflag (input)");
@@ -6277,14 +2424,16 @@ work:
show_const_tty (tty, c_iflag, INLCR, lock_status);
show_const_tty (tty, c_iflag, IGNCR, lock_status);
show_const_tty (tty, c_iflag, ICRNL, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (IUCLC)
show_const_tty (tty, c_iflag, IUCLC, lock_status);
#endif
show_const_tty (tty, c_iflag, IXON, lock_status);
show_const_tty (tty, c_iflag, IXANY, lock_status);
show_const_tty (tty, c_iflag, IXOFF, lock_status);
show_const_tty (tty, c_iflag, IMAXBEL, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (IUTF8)
show_const_tty (tty, c_iflag, IUTF8, lock_status);
#endif
@@ -6296,23 +2445,43 @@ work:
entry ("c_oflag", "0x%x", tty.c_oflag);
show_const_tty (tty, c_oflag, OPOST, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (OLCUC)
show_const_tty (tty, c_oflag, OLCUC, lock_status);
#endif
show_const_tty (tty, c_oflag, ONLCR, lock_status);
show_const_tty (tty, c_oflag, OCRNL, lock_status);
show_const_tty (tty, c_oflag, ONOCR, lock_status);
show_const_tty (tty, c_oflag, ONLRET, lock_status);
-#if defined (PROCENV_LINUX)
+#if defined (OFILL)
show_const_tty (tty, c_oflag, OFILL, lock_status);
+#endif
+
+#if defined (OFDEL)
show_const_tty (tty, c_oflag, OFDEL, lock_status);
+#endif
+
+#if defined (NLDLY)
show_const_tty (tty, c_oflag, NLDLY, lock_status);
+#endif
+
+#if defined (CRDLY)
show_const_tty (tty, c_oflag, CRDLY, lock_status);
#endif
+
+#if defined (TABDLY)
show_const_tty (tty, c_oflag, TABDLY, lock_status);
-#if defined (PROCENV_LINUX)
+#endif
+
+#if defined (BSDLY)
show_const_tty (tty, c_oflag, BSDLY, lock_status);
+#endif
+
+#if defined (VTDLY)
show_const_tty (tty, c_oflag, VTDLY, lock_status);
+#endif
+
+#if defined (FFDLY)
show_const_tty (tty, c_oflag, FFDLY, lock_status);
#endif
@@ -6323,9 +2492,10 @@ work:
entry ("value", "0x%x", tty.c_cflag);
-#if defined (PROCENV_LINUX)
+#if defined (CBAUDEX)
show_const_tty (tty, c_cflag, CBAUDEX, lock_status);
#endif
+
show_const_tty (tty, c_cflag, CSIZE, lock_status);
show_const_tty (tty, c_cflag, CSTOPB, lock_status);
show_const_tty (tty, c_cflag, CREAD, lock_status);
@@ -6333,14 +2503,15 @@ work:
show_const_tty (tty, c_cflag, PARODD, lock_status);
show_const_tty (tty, c_cflag, HUPCL, lock_status);
show_const_tty (tty, c_cflag, CLOCAL, lock_status);
-#if defined (PROCENV_LINUX)
+
#ifdef CIBAUD
show_const_tty (tty, c_cflag, CIBAUD, lock_status);
#endif
+
#ifdef CMSPAR
show_const_tty (tty, c_cflag, CMSPAR, lock_status);
#endif
-#endif
+
show_const_tty (tty, c_cflag, CRTSCTS, lock_status);
section_close ();
@@ -6351,9 +2522,11 @@ work:
entry ("value", "0x%x", tty.c_lflag);
show_const_tty (tty, c_lflag, ISIG, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (XCASE)
show_const_tty (tty, c_lflag, XCASE, lock_status);
#endif
+
show_const_tty (tty, c_lflag, ICANON, lock_status);
show_const_tty (tty, c_lflag, ECHO, lock_status);
show_const_tty (tty, c_lflag, ECHOE, lock_status);
@@ -6380,9 +2553,11 @@ work:
show_cc_tty (tty, VEOF, lock_status);
show_cc_tty (tty, VTIME, lock_status);
show_cc_tty (tty, VMIN, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (VSWTC)
show_cc_tty (tty, VSWTC, lock_status);
#endif
+
show_cc_tty (tty, VSTART, lock_status);
show_cc_tty (tty, VSTOP, lock_status);
show_cc_tty (tty, VSUSP, lock_status);
@@ -6470,9 +2645,9 @@ get_signal_name (int signum)
{
assert (signum);
- struct procenv_map *p;
+ const struct procenv_map *p;
- for (p = signal_map; p && p->name; p++) {
+ for (p = ops->signal_map; p && p->name; p++) {
if (signum == p->num)
return p->name;
}
@@ -6486,7 +2661,7 @@ get_signal_name (int signum)
* Returns: static string representing best guess
* at operating system.
**/
-char *
+const char *
get_os (void)
{
#ifdef _AIX
@@ -6497,11 +2672,7 @@ get_os (void)
return "Android";
#endif
-#ifdef __FreeBSD__
- return "FreeBSD";
-#endif
-
-#if defined (__MACH__) || defined (__GNU__) || defined (__gnu_hurd__)
+#if (defined (__MACH__) && defined (__GNU__)) || defined (__gnu_hurd__)
return "GNU (Hurd)";
#endif
@@ -6513,11 +2684,7 @@ get_os (void)
return "iSeries (OS/400)";
#endif
-#if defined (PROCENV_GNU_BSD) && defined (__GNUC__)
- return "GNU/kFreeBSD";
-#endif
-
-#ifdef PROCENV_LINUX
+#ifdef PROCENV_PLATFORM_LINUX
#ifdef __s390x__
return "Linux (zSeries)";
#endif
@@ -6532,11 +2699,15 @@ get_os (void)
return "Linux";
#endif
-#ifdef _NetBSD__
+#ifdef __FreeBSD__
+ return "FreeBSD";
+#endif
+
+#ifdef __NetBSD__
return "NetBSD";
#endif
-#ifdef _OpenBSD__
+#ifdef __OpenBSD__
return "OpenBSD";
#endif
@@ -6560,6 +2731,10 @@ get_os (void)
return "z/OS (MVS)";
#endif
+#if defined (__APPLE__)
+ return "Apple/Darwin";
+#endif
+
#ifndef __COVERITY__
return UNKNOWN_STR;
#endif
@@ -6571,7 +2746,7 @@ get_os (void)
* Returns: static string representing best guess
* at architecture.
**/
-char *
+const char *
get_arch (void)
{
@@ -6664,8 +2839,8 @@ get_arch (void)
return UNKNOWN_STR;
}
-#ifndef PROCENV_ANDROID
-int
+#if ! defined (PROCENV_PLATFORM_ANDROID) && ! defined (PROCENV_PLATFORM_DARWIN)
+static int
libs_callback (struct dl_phdr_info *info, size_t size, void *data)
{
const char *name;
@@ -6689,7 +2864,7 @@ libs_callback (struct dl_phdr_info *info, size_t size, void *data)
name = path;
}
- object_open (FALSE);
+ object_open (false);
section_open (name);
@@ -6698,10 +2873,11 @@ libs_callback (struct dl_phdr_info *info, size_t size, void *data)
section_close ();
- object_close (FALSE);
+ object_close (false);
return 0;
}
+#endif
void
show_libs (void)
@@ -6710,46 +2886,42 @@ show_libs (void)
container_open ("libraries");
+#if ! defined (PROCENV_PLATFORM_ANDROID) && ! defined (PROCENV_PLATFORM_DARWIN)
dl_iterate_phdr (libs_callback, NULL);
+#endif
container_close ();
}
-#endif
void
show_clocks (void)
{
header ("clocks");
- show_clock_res (CLOCK_REALTIME);
+ if (ops->show_clocks)
+ ops->show_clocks();
-#if defined (__FreeBSD__)
- show_clock_res (CLOCK_REALTIME_PRECISE);
- show_clock_res (CLOCK_REALTIME_FAST);
-#endif
+ footer ();
+}
- show_clock_res (CLOCK_MONOTONIC);
+void
+show_rlimits (void)
+{
+ header ("limits");
-#if defined (__FreeBSD__) || defined (PROCENV_GNU_BSD)
- show_clock_res (CLOCK_MONOTONIC_PRECISE);
- show_clock_res (CLOCK_MONOTONIC_FAST);
- show_clock_res (CLOCK_UPTIME);
- show_clock_res (CLOCK_UPTIME_PRECISE);
- show_clock_res (CLOCK_UPTIME_FAST);
- show_clock_res (CLOCK_VIRTUAL);
-#endif
+ if (ops->show_rlimits)
+ ops->show_rlimits ();
-#if defined (__FreeBSD__)
- show_clock_res (CLOCK_PROF);
-#endif
+ footer ();
+}
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-#ifdef CLOCK_MONOTONIC_RAW
- show_clock_res (CLOCK_MONOTONIC_RAW);
-#endif
- show_clock_res (CLOCK_PROCESS_CPUTIME_ID);
- show_clock_res (CLOCK_THREAD_CPUTIME_ID);
-#endif
+void
+show_confstrs (void)
+{
+ header ("confstr");
+
+ if (ops->show_confstrs)
+ ops->show_confstrs();
footer ();
}
@@ -6757,11 +2929,12 @@ show_clocks (void)
void
show_timezone (void)
{
-#if defined (PROCENV_LINUX)
- show_timezone_linux ();
-#else
- show_timezone_stub ();
-#endif
+ header ("timezone");
+
+ if (ops->show_timezone)
+ ops->show_timezone ();
+
+ footer ();
}
void
@@ -6774,7 +2947,11 @@ show_sizeof (void)
show_sizeof_type (blkcnt_t);
show_sizeof_type (blksize_t);
show_sizeof_type (char);
+
+#if !defined (PROCENV_PLATFORM_DARWIN)
show_sizeof_type (clockid_t);
+#endif
+
show_sizeof_type (clock_t);
show_sizeof_type (dev_t);
show_sizeof_type (div_t);
@@ -6817,8 +2994,12 @@ show_sizeof (void)
show_sizeof_type (off_t);
show_sizeof_type (pid_t);
show_sizeof_type (pthread_attr_t);
+
+#if !defined (PROCENV_PLATFORM_MINIX) && !defined (PROCENV_PLATFORM_DARWIN)
show_sizeof_type (pthread_barrierattr_t);
show_sizeof_type (pthread_barrier_t);
+#endif
+
show_sizeof_type (pthread_condattr_t);
show_sizeof_type (pthread_cond_t);
show_sizeof_type (pthread_key_t);
@@ -6827,7 +3008,11 @@ show_sizeof (void)
show_sizeof_type (pthread_once_t);
show_sizeof_type (pthread_rwlockattr_t);
show_sizeof_type (pthread_rwlock_t);
+
+#if !defined (PROCENV_PLATFORM_MINIX) && !defined (PROCENV_PLATFORM_DARWIN)
show_sizeof_type (pthread_spinlock_t);
+#endif
+
show_sizeof_type (pthread_t);
show_sizeof_type (ptrdiff_t);
show_sizeof_type (rlim_t);
@@ -6836,7 +3021,11 @@ show_sizeof (void)
show_sizeof_type (size_t);
show_sizeof_type (ssize_t);
show_sizeof_type (suseconds_t);
+
+#if !defined (PROCENV_PLATFORM_DARWIN)
show_sizeof_type (timer_t);
+#endif
+
show_sizeof_type (time_t);
show_sizeof_type (uid_t);
show_sizeof_type (uint16_t);
@@ -7040,46 +3229,46 @@ show_compiler (void)
section_open ("feature test macros");
-#ifdef __STDC_VERSION__
- entry ("__STDC_VERSION__", "%lu", __STDC_VERSION__);
+#ifdef _ATFILE_SOURCE
+ entry ("_ATFILE_SOURCE", "%s", DEFINED_STR);
#else
- entry ("__STDC_VERSION__", "%s", NOT_DEFINED_STR);
+ entry ("_ATFILE_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef __STRICT_ANSI__
- entry ("__STRICT_ANSI__", "%s", DEFINED_STR);
+#ifdef _BSD_SOURCE
+ entry ("_BSD_SOURCE", "%s", DEFINED_STR);
#else
- entry ("__STRICT_ANSI__", "%s", NOT_DEFINED_STR);
+ entry ("_BSD_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _POSIX_C_SOURCE
- entry ("_POSIX_C_SOURCE", "%lu", _POSIX_C_SOURCE);
+#ifdef _DEFAULT_SOURCE
+ entry ("_DEFAULT_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_POSIX_C_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_DEFAULT_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#if defined (_POSIX_RAW_SOCKETS)
- entry ("_POSIX_RAW_SOCKETS", "%s", DEFINED_STR),
+#ifdef _FILE_OFFSET_BITS
+ entry ("_FILE_OFFSET_BITS", "%lu", _FILE_OFFSET_BITS);
#else
- entry ("_POSIX_RAW_SOCKETS", "%s", NOT_DEFINED_STR),
+ entry ("_FILE_OFFSET_BITS", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _POSIX_SOURCE
- entry ("_POSIX_SOURCE", "%s", DEFINED_STR);
+#ifdef _FORTIFY_SOURCE
+ entry ("_FORTIFY_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_POSIX_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_FORTIFY_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _XOPEN_SOURCE
- entry ("_XOPEN_SOURCE", "%lu", _XOPEN_SOURCE);
+#ifdef _GNU_SOURCE
+ entry ("_GNU_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_XOPEN_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_GNU_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _XOPEN_SOURCE_EXTENDED
- entry ("_XOPEN_SOURCE_EXTENDED", "%s", DEFINED_STR);
+#ifdef _ISOC11_SOURCE
+ entry ("_ISOC11_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_XOPEN_SOURCE_EXTENDED", "%s", NOT_DEFINED_STR);
+ entry ("_ISOC11_SOURCE", "%s", NOT_DEFINED_STR);
#endif
#ifdef _ISOC95_SOURCE
@@ -7094,10 +3283,10 @@ show_compiler (void)
entry ("_ISOC99_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _ISOC11_SOURCE
- entry ("_ISOC11_SOURCE", "%s", DEFINED_STR);
+#ifdef _LARGEFILE64_SOURCE
+ entry ("_LARGEFILE64_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_ISOC11_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_LARGEFILE64_SOURCE", "%s", NOT_DEFINED_STR);
#endif
#ifdef _LARGEFILE_SOURCE
@@ -7106,46 +3295,64 @@ show_compiler (void)
entry ("_LARGEFILE_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _LARGEFILE64_SOURCE
- entry ("_LARGEFILE64_SOURCE", "%s", DEFINED_STR);
+#ifdef _POSIX_C_SOURCE
+ entry ("_POSIX_C_SOURCE", "%lu", _POSIX_C_SOURCE);
#else
- entry ("_LARGEFILE64_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_POSIX_C_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _FILE_OFFSET_BITS
- entry ("_FILE_OFFSET_BITS", "%lu", _FILE_OFFSET_BITS);
+#if defined (_POSIX_RAW_SOCKETS)
+ entry ("_POSIX_RAW_SOCKETS", "%s", DEFINED_STR),
#else
- entry ("_FILE_OFFSET_BITS", "%s", NOT_DEFINED_STR);
+ entry ("_POSIX_RAW_SOCKETS", "%s", NOT_DEFINED_STR),
#endif
-#ifdef _BSD_SOURCE
- entry ("_BSD_SOURCE", "%s", DEFINED_STR);
+#ifdef _POSIX_SOURCE
+ entry ("_POSIX_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_BSD_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_POSIX_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _SVID_SOURCE
- entry ("_SVID_SOURCE", "%s", DEFINED_STR);
+#ifdef _REENTRANT
+ entry ("_REENTRANT", "%s", DEFINED_STR);
#else
- entry ("_SVID_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_REENTRANT", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _ATFILE_SOURCE
- entry ("_ATFILE_SOURCE", "%s", DEFINED_STR);
+#ifdef __STDC_VERSION__
+ entry ("__STDC_VERSION__", "%lu", __STDC_VERSION__);
#else
- entry ("_ATFILE_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("__STDC_VERSION__", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _GNU_SOURCE
- entry ("_GNU_SOURCE", "%s", DEFINED_STR);
+#ifdef __STRICT_ANSI__
+ entry ("__STRICT_ANSI__", "%s", DEFINED_STR);
#else
- entry ("_GNU_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("__STRICT_ANSI__", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _REENTRANT
- entry ("_REENTRANT", "%s", DEFINED_STR);
+#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
+ entry ("__STDC_WANT_IEC_60559_BFP_EXT__", "%lu", __STDC_WANT_IEC_60559_BFP_EXT__);
#else
- entry ("_REENTRANT", "%s", NOT_DEFINED_STR);
+ entry ("__STDC_WANT_IEC_60559_BFP_EXT__", "%s", NOT_DEFINED_STR);
+#endif
+
+#ifdef __STDC_WANT_IEC_60559_FUNCS_EXT__
+ entry ("__STDC_WANT_IEC_60559_FUNCS_EXT__", "%lu", __STDC_WANT_IEC_60559_FUNCS_EXT__);
+#else
+ entry ("__STDC_WANT_IEC_60559_FUNCS_EXT__", "%s", NOT_DEFINED_STR);
+#endif
+
+#ifdef __STDC_WANT_LIB_EXT2__
+ entry ("__STDC_WANT_LIB_EXT2__", "%lu", __STDC_WANT_LIB_EXT2__);
+#else
+ entry ("__STDC_WANT_LIB_EXT2__", "%s", NOT_DEFINED_STR);
+#endif
+
+#ifdef _SVID_SOURCE
+ entry ("_SVID_SOURCE", "%s", DEFINED_STR);
+#else
+ entry ("_SVID_SOURCE", "%s", NOT_DEFINED_STR);
#endif
#ifdef _THREAD_SAFE
@@ -7154,16 +3361,16 @@ show_compiler (void)
entry ("_THREAD_SAFE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _FORTIFY_SOURCE
- entry ("_FORTIFY_SOURCE", "%s", DEFINED_STR);
+#ifdef _XOPEN_SOURCE
+ entry ("_XOPEN_SOURCE", "%lu", _XOPEN_SOURCE);
#else
- entry ("_FORTIFY_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_XOPEN_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _DEFAULT_SOURCE
- entry ("_DEFAULT_SOURCE", "%s", DEFINED_STR);
+#ifdef _XOPEN_SOURCE_EXTENDED
+ entry ("_XOPEN_SOURCE_EXTENDED", "%s", DEFINED_STR);
#else
- entry ("_DEFAULT_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_XOPEN_SOURCE_EXTENDED", "%s", NOT_DEFINED_STR);
#endif
section_close ();
@@ -7238,7 +3445,10 @@ show_time (void)
struct timespec ts;
struct tm *tm;
- if (clock_gettime (CLOCK_REALTIME, &ts) < 0)
+ if (! ops->get_time)
+ return;
+
+ if (ops->get_time (&ts))
die ("failed to determine time");
tm = localtime (&ts.tv_sec);
@@ -7287,7 +3497,7 @@ show_uname (void)
entry ("version", "%s", uts.version);
entry ("machine", "%s", uts.machine);
-#if defined (_GNU_SOURCE) && defined (PROCENV_LINUX)
+#if defined (_GNU_SOURCE) && defined (PROCENV_PLATFORM_LINUX)
entry ("domainname", "%s", uts.domainname[0] ? uts.domainname : UNKNOWN_STR);
#endif
@@ -7297,888 +3507,36 @@ show_uname (void)
void
show_cgroups (void)
{
-#if defined (PROCENV_LINUX)
- show_cgroups_linux ();
-#else
- show_cgroups_stub ();
-#endif
-}
-
-void
-show_oom (void)
-{
-#if defined (PROCENV_LINUX)
- show_oom_linux ();
-#else
- show_oom_stub ();
-#endif
-}
-
-void
-show_capabilities (void)
-{
-#if defined (PROCENV_LINUX)
- show_capabilities_linux ();
-#else
- show_capabilities_stub ();
-#endif
-}
-
-#if defined (PROCENV_LINUX)
-
-#if defined (HAVE_SYS_CAPABILITY_H)
-int
-get_capability_by_flag_type (cap_t cap_p, cap_flag_t type, cap_value_t cap)
-{
- int ret;
- cap_flag_value_t result;
-
- assert (cap_p);
-
- ret = cap_get_flag (cap_p, cap, type, &result);
-
- return ret < 0 ? ret : result;
-}
-#endif /* HAVE_SYS_CAPABILITY_H */
-
-void
-show_capabilities_linux (void)
-{
-#if defined (HAVE_SYS_CAPABILITY_H)
- int last_known;
- cap_t caps;
-
- /* Most recently-added capability that procenv knew about at
- * compile time.
- */
- last_known = CAP_LAST_CAP;
-#endif
-
- header ("capabilities");
-
-#if defined (HAVE_SYS_CAPABILITY_H)
- caps = cap_get_proc ();
-
- entry ("count (CAP_LAST_CAP+1)", "%d", CAP_LAST_CAP+1);
-
- if (! caps)
- goto out;
-
- section_open ("known");
-
- show_capability (caps, CAP_CHOWN);
- show_capability (caps, CAP_DAC_OVERRIDE);
- show_capability (caps, CAP_DAC_READ_SEARCH);
- show_capability (caps, CAP_FOWNER);
- show_capability (caps, CAP_FSETID);
- show_capability (caps, CAP_KILL);
- show_capability (caps, CAP_SETGID);
- show_capability (caps, CAP_SETUID);
- show_capability (caps, CAP_SETPCAP);
- show_capability (caps, CAP_LINUX_IMMUTABLE);
- show_capability (caps, CAP_NET_BIND_SERVICE);
- show_capability (caps, CAP_NET_BROADCAST);
- show_capability (caps, CAP_NET_ADMIN);
- show_capability (caps, CAP_NET_RAW);
- show_capability (caps, CAP_IPC_LOCK);
- show_capability (caps, CAP_IPC_OWNER);
- show_capability (caps, CAP_SYS_MODULE);
- show_capability (caps, CAP_SYS_RAWIO);
- show_capability (caps, CAP_SYS_CHROOT);
- show_capability (caps, CAP_SYS_PTRACE);
- show_capability (caps, CAP_SYS_PACCT);
- show_capability (caps, CAP_SYS_ADMIN);
- show_capability (caps, CAP_SYS_BOOT);
- show_capability (caps, CAP_SYS_NICE);
- show_capability (caps, CAP_SYS_RESOURCE);
- show_capability (caps, CAP_SYS_TIME);
- show_capability (caps, CAP_SYS_TTY_CONFIG);
-
- if (LINUX_KERNEL_MM (2, 4)) {
- show_capability (caps, CAP_MKNOD);
- show_capability (caps, CAP_LEASE);
- }
-
- if (LINUX_KERNEL_MMR (2, 6, 11)) {
- show_capability (caps, CAP_AUDIT_WRITE);
- show_capability (caps, CAP_AUDIT_CONTROL);
- }
- if (LINUX_KERNEL_MMR (2, 6, 24))
- show_capability (caps, CAP_SETFCAP);
- if (LINUX_KERNEL_MMR (2, 6, 25)) {
- show_capability (caps, CAP_MAC_OVERRIDE);
- show_capability (caps, CAP_MAC_ADMIN);
- }
-
-#ifdef CAP_SYSLOG
- if (LINUX_KERNEL_MMR (2, 6, 37))
- show_capability (caps, CAP_SYSLOG);
-
-#endif
-
-#ifdef CAP_WAKE_ALARM
- if (LINUX_KERNEL_MM (3, 0))
- show_capability (caps, CAP_WAKE_ALARM);
-#endif
-
-#ifdef CAP_BLOCK_SUSPEND
- if (LINUX_KERNEL_MM (3, 5))
- show_capability (caps, CAP_BLOCK_SUSPEND);
-#endif
-
-#ifdef CAP_AUDIT_READ
- if (LINUX_KERNEL_MM (3, 16)) {
- show_capability (caps, CAP_AUDIT_READ);
- }
-#endif
-
- section_close ();
-
- /* It's possible that procenv is running on a system which has
- * more capabilities that the system it was built on (for
- * example, it might be running in a chroot with a newer kernel
- * than the chroot environment). So display any unknown
- * capabilities. We don't have their names, but it's useful to
- * see that there are additional capabilities in available in
- * the environment.
- */
- section_open ("unknown");
-
-#if defined (PR_CAPBSET_READ)
- for (int i = 1+last_known; ; i++) {
- int ret;
- char *name = NULL;
-
- ret = cap_get_bound (i);
- if (ret < 0)
- break;
-
- /* Found an "unknown" */
-
- appendf (&name, "CAP_LAST_CAP+%d", i);
-
- _show_capability (caps, i, name);
-
- free (name);
- }
-#endif
-
- cap_free (caps);
-
- section_close ();
-
-#ifdef PR_GET_KEEPCAPS
- if (LINUX_KERNEL_MMR (2, 2, 18)) {
- int ret;
- ret = prctl (PR_GET_KEEPCAPS, 0, 0, 0, 0);
- if (ret < 0)
- entry ("keep", "%s", UNKNOWN_STR);
- else
- entry ("keep", "%s", ret ? YES_STR : NO_STR);
- }
-#endif
-
-
-#if defined (PR_GET_SECUREBITS) && defined (HAVE_LINUX_SECUREBITS_H)
- if (LINUX_KERNEL_MMR (2, 6, 26)) {
- int ret;
-
- ret = prctl (PR_GET_SECUREBITS, 0, 0, 0, 0);
- if (ret < 0)
- entry ("securebits", "%s", UNKNOWN_STR);
- else {
- struct securebits_t {
- unsigned int securebits;
- } flags;
- flags.securebits = (unsigned int)ret;
-
- section_open ("securebits");
-
- entry ("value", "0x%x", flags.securebits);
-
- container_open ("fields");
-
- show_const (flags, securebits, SECBIT_KEEP_CAPS);
- show_const (flags, securebits, SECBIT_NO_SETUID_FIXUP);
- show_const (flags, securebits, SECBIT_NOROOT);
-
- container_close ();
-
- section_close ();
- }
- }
-#endif
-
-out:
-#endif /* HAVE_SYS_CAPABILITY_H */
- footer ();
-}
-
-#if defined (HAVE_SYS_CAPABILITY_H)
-#ifdef PROCENV_NEED_LOCAL_CAP_GET_BOUND
-
-int cap_get_bound (cap_value_t cap)
-{
-#if defined (PR_CAPBSET_READ)
- return prctl (PR_CAPBSET_READ, cap);
-#else
- return -1;
-#endif
-}
-
-#endif /* PROCENV_NEED_LOCAL_CAP_GET_BOUND */
-#endif /* HAVE_SYS_CAPABILITY_H */
-
-void
-show_timezone_linux (void)
-{
- tzset ();
-
- header ("timezone");
-
- entry ("tzname[0]", "'%s'", tzname[0]);
- entry ("tzname[1]", "'%s'", tzname[1]);
- entry ("timezone", "%ld", timezone);
- entry ("daylight", "%d", daylight);
-
- footer ();
-}
-
-void
-show_security_module_linux (void)
-{
- char *lsm = UNKNOWN_STR;
-
-#if defined (HAVE_APPARMOR)
- if (aa_is_enabled ())
- lsm = "AppArmor";
-#endif
-
-#if defined (HAVE_SELINUX_SELINUX_H)
- if (is_selinux_enabled () == 1) {
-
- if (is_selinux_mls_enabled () == 1)
- lsm = "SELinux (MLS)";
- else
- lsm = "SELinux";
- }
-#endif
-
- entry ("name", "%s", lsm);
-}
-
-void
-show_security_module_context_linux (void)
-{
- char *context = NULL;
- char *mode = NULL;
-
-#if defined (HAVE_APPARMOR)
- if (aa_is_enabled ()) {
- /* XXX: The mode string is *NOT* be freed since it forms
- * part of the allocation returned in context.
- *
- * See aa_gettaskcon(2) for details.
- */
- if (aa_gettaskcon (user.pid, &context, &mode) < 0)
- die ("failed to query AppArmor context");
- }
-#endif
-
-#if defined (HAVE_SELINUX_SELINUX_H)
- if (is_selinux_enabled ()) {
- if (getpidcon (user.pid, &context) < 0)
- die ("failed to query SELinux context");
- }
-#endif
- if (context) {
- if (mode) {
- entry ("context", "%s (%s)", context, mode);
- } else {
- entry ("context", "%s", context);
- }
- } else {
- entry ("context", "%s", UNKNOWN_STR);
- }
-
- free (context);
-}
-
-void
-show_cgroups_linux (void)
-{
- const char *delim = ":";
- char *file = "/proc/self/cgroup";
- FILE *f;
- char buffer[1024];
- size_t len;
-
header ("cgroups");
- f = fopen (file, "r");
-
- if (! f)
- goto out;
-
- while (fgets (buffer, sizeof (buffer), f)) {
- char *buf, *b;
- char *hierarchy;
- char *subsystems;
- char *path;
-
- len = strlen (buffer);
- /* Remove NL */
- buffer[len-1] = '\0';
-
- buf = b = strdup (buffer);
- if (! buf)
- die ("failed to alloate storage");
-
- hierarchy = strsep (&b, delim);
- if (! hierarchy)
- goto next;
-
- subsystems = strsep (&b, delim);
- if (! subsystems)
- goto next;
-
- path = strsep (&b, delim);
- if (! path)
- goto next;
-
- /* FIXME: should sort by hierarchy */
- container_open (hierarchy);
-
- object_open (FALSE);
-
- /* FIXME: should split this on comma */
- entry ("subsystems", "%s", subsystems);
-
- entry ("path", "%s", path);
-
- object_close (FALSE);
-
- container_close ();
-
-next:
- free (buf);
- }
-
- fclose (f);
-
-out:
+ if (ops->show_cgroups)
+ ops->show_cgroups ();
footer ();
}
void
-show_fds_linux (void)
-{
- DIR *dir;
- struct dirent *ent;
- char *prefix_path = "/proc/self/fd";
- struct stat st;
- char path[MAXPATHLEN];
- char link[MAXPATHLEN];
- ssize_t len;
-
- container_open ("file descriptors");
-
- dir = opendir (prefix_path);
- if (! dir)
- return;
-
- while ((ent=readdir (dir)) != NULL) {
- int fd;
- char *num = NULL;
-
- if (! strcmp (ent->d_name, ".") || ! strcmp (ent->d_name, ".."))
- continue;
-
- sprintf (path, "%s/%s", prefix_path, ent->d_name);
- fd = atoi (ent->d_name);
-
- len = readlink (path, link, sizeof (link)-1);
- if (len < 0)
- /* ignore errors */
- continue;
-
- appendf (&num, "%d", fd);
-
- assert (len);
- link[len] = '\0';
-
- if (link[0] == '/') {
-
- if (stat (link, &st) < 0) {
- free (num);
- continue;
- }
-
- /* Ignore the last (invalid) entry */
- if (S_ISDIR (st.st_mode)) {
- free (num);
- continue;
- }
- }
-
- object_open (FALSE);
-
- section_open (num);
- free (num);
-
- entry ("terminal", "%s", isatty (fd) ? YES_STR : NO_STR);
- entry ("valid", "%s", fd_valid (fd) ? YES_STR : NO_STR);
- entry ("device", "%s", link);
-
- section_close ();
-
- object_close (FALSE);
- }
-
- closedir (dir);
-
- container_close ();
-}
-
-void
-show_namespaces_linux (void)
-{
- DIR *dir;
- struct dirent *ent;
- char *prefix_path = "/proc/self/ns";
- char path[MAXPATHLEN];
- char link[MAXPATHLEN];
- ssize_t len;
- PRList *list = NULL;
-
- container_open ("namespaces");
-
- dir = opendir (prefix_path);
- if (! dir)
- goto end;
-
- list = pr_list_new (NULL);
- assert (list);
-
- while ((ent=readdir (dir)) != NULL) {
- PRList *entry;
-
- if (! strcmp (ent->d_name, ".") || ! strcmp (ent->d_name, ".."))
- continue;
-
- sprintf (path, "%s/%s", prefix_path, ent->d_name);
-
- len = readlink (path, link, sizeof (link)-1);
- if (len < 0)
- /* ignore errors */
- continue;
-
- assert (len);
- link[len] = '\0';
-
- entry = pr_list_new (strdup (link));
- assert (entry);
-
- assert (pr_list_prepend_str_sorted (list, entry));
- }
-
- closedir (dir);
-
- PR_LIST_FOREACH_SAFE (list, iter) {
- char *tmp;
- char *name;
- char *value;
-
- pr_list_remove (iter);
-
- tmp = iter->data;
-
- name = strsep (&tmp, ":");
- if (! name)
- goto give_up;
-
- value = strsep (&tmp, "]");
- if (! value)
- goto give_up;
-
- if (*value == '[' && value+1 && *(value+1)) {
- value++;
- }
-
- object_open (FALSE);
- entry (name, "%s", value);
- object_close (FALSE);
-
-give_up:
- free ((char *)iter->data);
- free(iter);
- }
-
- free_if_set (list);
-
-end:
- container_close ();
-}
-
-void
-show_oom_linux (void)
+show_oom (void)
{
- char *dir = "/proc/self";
- char *files[] = { "oom_score", "oom_adj", "oom_score_adj", NULL };
- char **file;
- FILE *f;
- char buffer[PROCENV_BUFFER];
- char path[PATH_MAX];
- size_t len;
- int ret;
- int seen = FALSE;
-
header ("oom");
- for (file = files; file && *file; file++) {
- ret = sprintf (path, "%s/%s", dir, *file);
- if (ret < 0)
- continue;
-
- f = fopen (path, "r");
- if (! f)
- continue;
-
- seen = TRUE;
-
- while (fgets (buffer, sizeof (buffer), f)) {
- len = strlen (buffer);
- buffer[len-1] = '\0';
- entry (*file, "%s", buffer);
- }
-
- fclose (f);
- }
-
- if (! seen)
- entry ("%s", UNKNOWN_STR);
+ if (ops->show_oom)
+ ops->show_oom ();
footer ();
}
-char *
-get_scheduler_name (int sched)
-{
- struct procenv_map *p;
-
- for (p = scheduler_map; p && p->name; p++) {
- if (p->num == sched)
- return p->name;
- }
-
- return NULL;
-}
-
void
-show_cpu_linux (void)
-{
- int cpu = -1;
- long max;
-
- max = get_sysconf (_SC_NPROCESSORS_ONLN);
-
-#if HAVE_SCHED_GETCPU
- cpu = sched_getcpu ();
- if (cpu < 0)
- goto unknown_sched_cpu;
-
-#else
- cpu = procenv_getcpu ();
- if (cpu < 0)
- goto unknown_sched_cpu;
-#endif
-
- /* adjust to make 1-based */
- cpu++;
-
- entry ("number", "%u of %ld", cpu, max);
- return;
-
-unknown_sched_cpu:
-
- entry ("number", "%s of %ld", UNKNOWN_STR, max);
-}
-
-#if ! defined (HAVE_SCHED_GETCPU)
-
-/* Crutch function for RHEL 5 */
-int
-procenv_getcpu (void)
-{
- int cpu = -1;
- FILE *f;
- char **fields;
- const char *field;
- char buffer[1024];
- size_t len;
- size_t count;
-
- f = fopen ("/proc/self/stat", "r");
- if (! f)
- goto out;
-
- if (! fgets (buffer, sizeof (buffer), f))
- goto out;
-
- fclose (f);
-
- len = strlen (buffer);
- buffer[len-1] = '\0';
-
- count = split_fields (buffer, ' ', TRUE, &fields);
-
- if (! count)
- return -1;
-
- if (count != 42)
- goto cleanup;
-
- field = fields[41];
- assert (field);
-
- cpu = atoi (field);
-
-cleanup:
-
- for (len = 0; len < count; len++)
- free (fields[len]);
- free (fields);
-
-out:
- return cpu;
-}
-#endif
-
-/**
- * get_canonical:
- *
- * @path: path to convert to canonical form,
- * @canonical [out]: canonical version of @path,
- * @len: Size of @canonical (should be atleast PATH_MAX).
- *
- * FIXME: this should fully resolve not just sym links but replace all
- * occurences of '../' by the appropriate direcotry!
- **/
-int
-get_canonical (const char *path, char *canonical, size_t len)
-{
- ssize_t bytes;
- int ret = TRUE;
-
- assert (path);
- assert (canonical);
- assert (len);
-
- bytes = readlink (path, canonical, len);
- if (bytes < 0) {
- sprintf (canonical, UNKNOWN_STR);
- ret = FALSE;
- } else {
- canonical[bytes <= len ? bytes : len] = '\0';
- }
-
- return ret;
-}
-
-void
-get_tty_locked_status (struct termios *lock_status)
-{
- assert (lock_status);
- assert (user.tty_fd != -1);
-
- if (ioctl (user.tty_fd, TIOCGLCKTRMIOS, lock_status) < 0) {
- /* Set to unlocked */
- memset (lock_status, '\0', sizeof (struct termios));
- }
-}
-#else
-
-void
-show_namespaces_stub (void)
-{
- header ("namespaces");
- footer ();
-}
-void
-show_cgroups_stub (void)
-{
- header ("cgroups");
- footer ();
-}
-
-void
-show_oom_stub (void)
-{
- header ("oom");
- footer ();
-}
-
-void
-show_timezone_stub (void)
-{
- header ("timezone");
- footer ();
-}
-
-void
-show_capabilities_stub (void)
+show_capabilities (void)
{
header ("capabilities");
- footer ();
-}
-void
-show_shared_mem_stub (void)
-{
- header ("shared memory");
- footer ();
-}
-
-void
-show_semaphores_stub (void)
-{
- header ("semaphores");
- footer ();
-}
+ if (ops->show_capabilities)
+ ops->show_capabilities();
-void
-show_msg_queues_stub (void)
-{
- header ("message queues");
footer ();
}
-#endif /* PROCENV_LINUX */
-
-bool
-has_ctty (void)
-{
- int fd;
- fd = open ("/dev/tty", O_RDONLY | O_NOCTTY);
-
- if (fd < 0)
- return FALSE;
-
- close (fd);
-
- return TRUE;
-}
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-void
-show_cpu_bsd (void)
-{
- long max;
- kvm_t *kvm;
- struct kinfo_proc *proc;
- int ignored;
- int cpu;
- char errors[_POSIX2_LINE_MAX];
-
- assert (user.pid > 0);
-
- max = get_sysconf (_SC_NPROCESSORS_ONLN);
-
- kvm = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errors);
- if (! kvm)
- die ("unable to open kvm");
-
- proc = kvm_getprocs (kvm, KERN_PROC_PID, user.pid, &ignored);
- if (! proc)
- die ("failed to get process info");
-
- /* cpu values are zero-based */
- cpu = 1 + proc->ki_oncpu;
-
- if (kvm_close (kvm) < 0)
- die ("failed to close kvm");
-
- entry ("number", "%u of %lu", cpu, max);
-}
-
-void
-get_misc_bsd (void)
-{
- char errors[_POSIX2_LINE_MAX];
- kvm_t *kvm;
- struct kinfo_proc *proc;
- int ignored;
-
- kvm = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errors);
- if (! kvm)
- die ("unable to open kvm");
-
- proc = kvm_getprocs (kvm, KERN_PROC_PID, user.pid, &ignored);
- if (! proc)
- die ("failed to get process info");
-
- misc.in_jail = (proc->ki_flag & P_JAILED) ? TRUE : FALSE;
- strcpy (user.proc_name, proc->ki_comm);
-
- if (kvm_close (kvm) < 0)
- die ("failed to close kvm");
-}
-
-#endif
-
-int
-get_output_value (const char *name)
-{
- struct procenv_map *p;
-
- assert (name);
-
- for (p = output_map; p && p->name; p++) {
- if (! strcmp (name, p->name)) {
- return p->num;
- }
- }
- die ("invalid output value: '%s'", name);
-
- /* compiler appeasement */
- return -1;
-}
-
-int
-get_output_format (const char *name)
-{
- struct procenv_map *p;
-
- assert (name);
-
- for (p = output_format_map; p && p->name; p++) {
- if (! strcmp (name, p->name)) {
- return p->num;
- }
- }
- die ("invalid output format value: '%s'", name);
-
- /* compiler appeasement */
- return -1;
-}
-
-const char *
-get_output_format_name (void)
-{
- struct procenv_map *p;
-
- for (p = output_format_map; p && p->name; p++) {
- if (output_format == p->num)
- return p->name;
- }
-
- bug ("invalid output format: %d", output_format);
-
- /* compiler appeasement */
- return NULL;
-}
-
void
check_envvars (void)
{
@@ -8190,45 +3548,51 @@ check_envvars (void)
e = getenv (PROCENV_OUTPUT_ENV);
if (e && *e) {
- output = get_output_value (e);
+ set_output_value (e);
}
e = getenv (PROCENV_FILE_ENV);
if (e && *e) {
- output_file = e;
- output = OUTPUT_FILE;
+ set_output_file (e);
+ set_output_value_raw (OUTPUT_FILE);
+ }
+
+ e = getenv (PROCENV_FILE_APPEND_ENV);
+ if (e && *e) {
+ set_output_file_append ();
}
e = getenv (PROCENV_FORMAT_ENV);
if (e && *e) {
- output_format = get_output_format (e);
+ set_output_format (e);
}
e = getenv (PROCENV_INDENT_ENV);
if (e && *e) {
- indent_amount = atoi (e);
+ set_indent_amount (atoi (e));
}
e = getenv (PROCENV_INDENT_CHAR_ENV);
if (e && *e) {
/* Special character handling */
if (! strcmp (e, "\\t"))
- indent_char = "\t";
+ set_indent_char ("\t");
else
- indent_char = e;
+ set_indent_char (e);
}
e = getenv (PROCENV_SEPARATOR_ENV);
if (e && *e) {
- text_separator = e;
+ set_text_separator (e);
}
e = getenv (PROCENV_CRUMB_SEPARATOR_ENV);
if (e && *e) {
- if (! strcmp (e, "\\t"))
- crumb_separator = "\t";
- else
- crumb_separator = e;
+ if (! strcmp (e, "\\t")) {
+ set_crumb_separator ("\t");
+ } else {
+ set_crumb_separator (e);
+ }
}
e = getenv (PROCENV_EXEC_ENV);
@@ -8236,10 +3600,18 @@ check_envvars (void)
char *tmp;
string = strdup (e);
- if (! string)
+ if (! string) {
die ("failed to copy environment string");
+ }
+
+ if (! *string) {
+ die ("invalid command");
+ }
+
+ /* there must be atleast an no-arg command to run */
+ count = 1;
- /* establish number of fields */
+ /* establish number of fields required for program arguments */
for (tmp = string; tmp && *tmp; ) {
tmp = index (tmp, ' ');
if (tmp) {
@@ -8247,10 +3619,9 @@ check_envvars (void)
tmp++;
count++;
}
-
}
- /* allocate space for arguments.
+ /* allocate space for exec arguments.
* +1 for terminator.
*/
exec_args = calloc (count + 1, sizeof (char *));
@@ -8268,6 +3639,8 @@ check_envvars (void)
die ("failed to allocate space for exec arg");
}
+ reexec = true;
+
free (string);
}
}
@@ -8286,13 +3659,13 @@ get_major_minor (const char *path, unsigned int *_major, unsigned int *_minor)
* user does not have permission to check.
*/
*_major = *_minor = 0;
- return FALSE;
+ return false;
}
*_major = major (st.st_dev);
*_minor = minor (st.st_dev);
- return TRUE;
+ return true;
}
/**
@@ -8395,7 +3768,7 @@ show_threads (void)
entry ("stack size", "%lu bytes",
(unsigned long int)stack_size);
-#if defined (PROCENV_ANDROID)
+#if defined (PROCENV_PLATFORM_ANDROID)
ret = 0;
scope = pthread_attr_getscope (&attr);
#else
@@ -8406,7 +3779,16 @@ show_threads (void)
scope == PTHREAD_SCOPE_SYSTEM ? "PTHREAD_SCOPE_SYSTEM"
: "PTHREAD_SCOPE_PROCESS");
+#if defined (PROCENV_PLATFORM_MINIX)
+ {
+ int size;
+ ret = pthread_attr_getguardsize (&attr, &size);
+ guard_size = size;
+ }
+#else
ret = pthread_attr_getguardsize (&attr, &guard_size);
+#endif
+
if (ret == 0) {
entry ("guard size", "%lu bytes",
(unsigned long int)guard_size);
@@ -8428,7 +3810,7 @@ show_threads (void)
else
entry ("priority", "%d", param.sched_priority);
-#ifdef PROCENV_ANDROID
+#ifdef PROCENV_PLATFORM_ANDROID
section_close ();
#else
ret = pthread_attr_getinheritsched (&attr, &inherit_sched);
@@ -8440,9 +3822,12 @@ show_threads (void)
section_close ();
+#if !defined (PROCENV_PLATFORM_NETBSD)
entry ("concurrency", "%d", pthread_getconcurrency ());
#endif
+#endif
+
footer ();
}
@@ -8501,61 +3886,62 @@ int
main (int argc,
char *argv[])
{
- int option;
- int long_index;
- int done = FALSE;
+ int option;
+ int long_index;
+ int done = false;
struct option long_options[] = {
- {"meta" , no_argument, NULL, 'a'},
- {"arguments" , no_argument, NULL, 'A'},
- {"libs" , no_argument, NULL, 'b'},
- {"libc" , no_argument, NULL, 'B'},
- {"cgroups" , no_argument, NULL, 'c'},
- {"cpu" , no_argument, NULL, 'C'},
- {"compiler" , no_argument, NULL, 'd'},
- {"crumb-separator" , required_argument, NULL, 0},
- {"environment" , no_argument, NULL, 'e'},
- {"semaphores" , no_argument, NULL, 'E'},
- {"fds" , no_argument, NULL, 'f'},
- {"namespaces" , no_argument, NULL, 'F'},
- {"sizeof" , no_argument, NULL, 'g'},
- {"help" , no_argument, NULL, 'h'},
- {"misc" , no_argument, NULL, 'i'},
- {"uname" , no_argument, NULL, 'j'},
- {"clocks" , no_argument, NULL, 'k'},
- {"limits" , no_argument, NULL, 'l'},
- {"locale" , no_argument, NULL, 'L'},
- {"mounts" , no_argument, NULL, 'm'},
- {"message-queues" , no_argument, NULL, 'M'},
- {"confstr" , no_argument, NULL, 'n'},
- {"network" , no_argument, NULL, 'N'},
- {"oom" , no_argument, NULL, 'o'},
- {"process" , no_argument, NULL, 'p'},
- {"platform" , no_argument, NULL, 'P'},
- {"time" , no_argument, NULL, 'q'},
- {"ranges" , no_argument, NULL, 'r'},
- {"signals" , no_argument, NULL, 's'},
- {"shared-memory" , no_argument, NULL, 'S'},
- {"tty" , no_argument, NULL, 't'},
- {"threads" , no_argument, NULL, 'T'},
- {"stat" , no_argument, NULL, 'u'},
- {"rusage" , no_argument, NULL, 'U'},
- {"version" , no_argument, NULL, 'v'},
- {"capabilities" , no_argument, NULL, 'w'},
- {"pathconf" , no_argument, NULL, 'x'},
- {"sysconf" , no_argument, NULL, 'y'},
- {"memory" , no_argument, NULL, 'Y'},
- {"timezone" , no_argument, NULL, 'z'},
- {"exec" , no_argument , NULL, 0},
- {"file" , required_argument, NULL, 0},
- {"format" , required_argument, NULL, 0},
- {"indent" , required_argument, NULL, 0},
- {"indent-char" , required_argument, NULL, 0},
- {"output" , required_argument, NULL, 0},
- {"separator" , required_argument, NULL, 0},
+ {"meta" , no_argument , NULL, 'a'},
+ {"arguments" , no_argument , NULL, 'A'},
+ {"libs" , no_argument , NULL, 'b'},
+ {"libc" , no_argument , NULL, 'B'},
+ {"cgroups" , no_argument , NULL, 'c'},
+ {"cpu" , no_argument , NULL, 'C'},
+ {"compiler" , no_argument , NULL, 'd'},
+ {"crumb-separator" , required_argument , NULL, 0 },
+ {"environment" , no_argument , NULL, 'e'},
+ {"semaphores" , no_argument , NULL, 'E'},
+ {"fds" , no_argument , NULL, 'f'},
+ {"namespaces" , no_argument , NULL, 'F'},
+ {"sizeof" , no_argument , NULL, 'g'},
+ {"help" , no_argument , NULL, 'h'},
+ {"misc" , no_argument , NULL, 'i'},
+ {"uname" , no_argument , NULL, 'j'},
+ {"clocks" , no_argument , NULL, 'k'},
+ {"limits" , no_argument , NULL, 'l'},
+ {"locale" , no_argument , NULL, 'L'},
+ {"mounts" , no_argument , NULL, 'm'},
+ {"message-queues" , no_argument , NULL, 'M'},
+ {"confstr" , no_argument , NULL, 'n'},
+ {"network" , no_argument , NULL, 'N'},
+ {"oom" , no_argument , NULL, 'o'},
+ {"process" , no_argument , NULL, 'p'},
+ {"platform" , no_argument , NULL, 'P'},
+ {"time" , no_argument , NULL, 'q'},
+ {"ranges" , no_argument , NULL, 'r'},
+ {"signals" , no_argument , NULL, 's'},
+ {"shared-memory" , no_argument , NULL, 'S'},
+ {"tty" , no_argument , NULL, 't'},
+ {"threads" , no_argument , NULL, 'T'},
+ {"stat" , no_argument , NULL, 'u'},
+ {"rusage" , no_argument , NULL, 'U'},
+ {"version" , no_argument , NULL, 'v'},
+ {"capabilities" , no_argument , NULL, 'w'},
+ {"pathconf" , no_argument , NULL, 'x'},
+ {"sysconf" , no_argument , NULL, 'y'},
+ {"memory" , no_argument , NULL, 'Y'},
+ {"timezone" , no_argument , NULL, 'z'},
+ {"exec" , no_argument , NULL, 0 },
+ {"file" , required_argument , NULL, 0 },
+ {"file-append" , no_argument , NULL, 0 },
+ {"format" , required_argument , NULL, 0 },
+ {"indent" , required_argument , NULL, 0 },
+ {"indent-char" , required_argument , NULL, 0 },
+ {"output" , required_argument , NULL, 0 },
+ {"separator" , required_argument , NULL, 0 },
/* terminator */
- {NULL , no_argument , NULL, 0}
+ {NULL , no_argument , NULL, 0 }
};
doc = pstring_new ();
@@ -8573,7 +3959,7 @@ main (int argc,
init ();
- while (TRUE) {
+ while (true) {
option = getopt_long (argc, argv,
"aAbBcCdeEfFghijklLmMnNopPqrsStTuUvwxyYz",
long_options, &long_index);
@@ -8585,7 +3971,7 @@ main (int argc,
* count non-display options).
*/
if (option) {
- done = TRUE;
+ done = true;
master_header (&doc);
}
@@ -8599,47 +3985,53 @@ main (int argc,
die ("Must specify non-display options before display options");
if (! strcmp ("output", long_options[long_index].name)) {
- output = get_output_value (optarg);
+ set_output_value (optarg);
} else if (! strcmp ("file", long_options[long_index].name)) {
- output = OUTPUT_FILE;
- output_file = optarg;
+ set_output_value_raw (OUTPUT_FILE);
+ set_output_file (optarg);
+ } else if (! strcmp ("file-append", long_options[long_index].name)) {
+ set_output_file_append ();
} else if (! strcmp ("exec", long_options[long_index].name)) {
- reexec = TRUE;
+ reexec = true;
} else if (! strcmp ("format", long_options[long_index].name)) {
- output_format = get_output_format (optarg);
+ set_output_format (optarg);
} else if (! strcmp ("indent", long_options[long_index].name)) {
- indent_amount = atoi (optarg);
- if (indent_amount <= 0)
+ set_indent_amount (atoi (optarg));
+ if (get_indent_amount () <= 0)
die ("cannot specify indent <= 0");
} else if (! strcmp ("indent-char", long_options[long_index].name)) {
+ char *c = NULL;
+
/* Special character handling */
if (! strcmp (optarg, "\\t")) {
- indent_char = "\t";
+ c = "\t";
} else {
- indent_char = optarg;
+ c = optarg;
}
- if (! indent_char)
+ if (! c)
die ("cannot use nul indent character");
+ set_indent_char (c);
+
/* call again */
handle_indent_char ();
} else if (! strcmp ("separator", long_options[long_index].name)) {
if (! strcmp (optarg, "\\t")) {
- text_separator = "\t";
+ set_text_separator ("\t");
} else {
- text_separator = optarg;
+ set_text_separator (optarg);
}
} else if (! strcmp ("crumb-separator", long_options[long_index].name)) {
if (! strcmp (optarg, "\\t")) {
- crumb_separator = "\t";
+ set_crumb_separator ("\t");
} else {
- crumb_separator = optarg;
- }
+ set_crumb_separator (optarg);
+ }
}
/* reset */
selected_option = 0;
- indent = 0;
+ reset_indent ();
break;
@@ -8652,9 +4044,7 @@ main (int argc,
break;
case 'b':
-#ifndef PROCENV_ANDROID
show_libs ();
-#endif
break;
case 'B':
@@ -8729,9 +4119,7 @@ main (int argc,
break;
case 'n':
-#ifndef PROCENV_ANDROID
- show_confstrs ();
-#endif
+ show_confstrs();
break;
case 'N':
@@ -8818,18 +4206,14 @@ main (int argc,
master_footer (&doc);
- chomp (doc);
-
+ pstring_chomp (doc);
if (output_format != OUTPUT_FORMAT_XML && output_format != OUTPUT_FORMAT_JSON) {
- compress (&doc, wide_indent_char);
+ pstring_compress (&doc, wide_indent_char);
}
-
- goto finish;
}
- if (output == OUTPUT_SYSLOG)
- openlog (PACKAGE_NAME, LOG_CONS | LOG_PID, LOG_USER);
+ output_init ();
if (reexec && ! exec_args && optind >= argc)
die ("must specify atleast one argument with '--exec'");
@@ -8842,13 +4226,14 @@ main (int argc,
}
}
- dump ();
+ if (! done) {
+ dump ();
- chomp (doc);
+ pstring_chomp (doc);
- compress (&doc, wide_indent_char);
+ pstring_compress (&doc, wide_indent_char);
+ }
-finish:
_show_output_pstring (doc);
cleanup ();
@@ -8862,7 +4247,9 @@ finish:
}
-char *
+/* FIXME: we _assume_ the returned value is a static, but is it guaranteed?
+*/
+const char *
get_user_name (uid_t uid)
{
struct passwd *p;
@@ -8872,7 +4259,9 @@ get_user_name (uid_t uid)
return p ? p->pw_name : NULL;
}
-char *
+/* FIXME: we _assume_ the returned value is a static, but is it guaranteed?
+*/
+const char *
get_group_name (gid_t gid)
{
struct group *g;
@@ -8882,1081 +4271,6 @@ get_group_name (gid_t gid)
return g ? g->gr_name : NULL;
}
-/**
- * encode_string:
- *
- * @str: string to encode.
- *
- * Returns: 0 on success, -1 on failure.
- *
- * Convert the specified string to its encoded form. If no encoding is
- * necessary, the string will not be modified.
- *
- * Notes:
- *
- * - By encoding, we mean replacing literals with their
- * format-langage-specific encodings. For example for XML output,
- * '<' is converted to '&lt;'.
- *
- * - It is the callers responsibility to free @str iff this function
- * is successful. any previous value of @str will be freed by
- * encode_string().
- *
- * BUGS: this is just horribly, horribly gross :(
- **/
-int
-encode_string (pstring **pstr)
-{
- int ret = 0;
- pstring *new = NULL;
- wchar_t *p, *q;
- size_t non_printables;
- size_t len = 0;
- size_t bytes;
-
- assert (pstr);
- assert (*pstr);
-
- if ((*pstr)->len <= 1) {
- /* Nothing to do */
- return 0;
- }
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* Nothing to do */
- ret = 0;
- break;
-
- case OUTPUT_FORMAT_JSON: /* FALL THROUGH */
- case OUTPUT_FORMAT_XML:
- new = translate (*pstr);
- if (new) {
- pstring_free (*pstr);
- *pstr = new;
- new = NULL;
- } else {
- ret = -1;
- }
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-
- if (ret < 0)
- return ret;
-
- /* Now, search for evil non-printable characters and encode those
- * appropriately.
- */
- for (p = (*pstr)->buf, non_printables = 0; p && *p; p++) {
- if (! iswprint (*p))
- non_printables++;
- }
-
- if (non_printables &&
- (output_format == OUTPUT_FORMAT_XML
- || output_format == OUTPUT_FORMAT_JSON)) {
-
- size_t new_size = 0;
-
- wchar_t *json_format = L"\\u%4.4x";
-
- /* XXX:
- *
- * Although this format spec _may_ produce valid XML,
- * the rules are arcane and some(?) control characters
- * cannot be used within an XML document, hence the
- * "may".
- *
- * Aside from simply discarding non-printable characters
- * (thus distorting the output), we are left with
- * attempting to produce some sort of encoded
- * representation which may well choke a validating
- * parser.
- *
- * Realistically, the problem is confined to handling
- * control characters set in environment variables when
- * attempting to output XML. This may occur if you run
- * GNU Screen since it sets $TERMCAP which includes
- * binary characters.
- *
- * FIXME:
- *
- * If you hit this issue, raise a bug so we can consider
- * simply discarding all non-printables when attempting
- * XML output.
- */
- wchar_t *xml_format = L"&#x%2.2x;";
-
- len = (*pstr)->len;
-
- /* Calculate expanded size of string by removing
- * count of non-printable byte and adding back the
- * number of bytes required to encode them in expanded
- * form.
- */
- switch (output_format) {
- case OUTPUT_FORMAT_XML:
- new_size = (len - non_printables) + (non_printables * wcslen (L"&#x..;"));
- break;
-
- case OUTPUT_FORMAT_JSON:
- new_size = (len - non_printables) + (non_printables * wcslen (L"\\u...."));
- break;
- default:
- break;
- }
-
- new = pstring_new ();
- if (! new)
- return -1;
-
- bytes = (1 + new_size) * sizeof (wchar_t);
-
- new->buf = malloc (bytes);
- if (! new->buf) {
- free (new);
- return -1;
- }
-
- new->size = bytes;
-
- memset (new->buf, '\0', bytes);
-
- for (p = (*pstr)->buf, q = new->buf; p && *p; p++) {
- if (iswprint (*p)) {
- *q = *p;
- q++;
- new->len++;
- } else {
- ret = swprintf (q,
- new_size,
- output_format == OUTPUT_FORMAT_JSON
- ? json_format : xml_format,
- *p);
- q += ret;
- }
- }
-
- /* include terminator */
- new->len = wcslen (new->buf) + 1;
-
- pstring_free (*pstr);
- *pstr = new;
- }
-
- return ret;
-}
-
-/* Performs simple substitution on the input */
-pstring *
-translate (const pstring *pstr)
-{
- pstring *result = NULL;
- const wchar_t *start;
- const wchar_t *p;
- TranslateTable *table;
- size_t i;
- size_t len;
- size_t extra;
- size_t bytes;
- size_t amount;
- wchar_t from;
-
- assert (pstr);
- assert (output_format != OUTPUT_FORMAT_TEXT);
- assert (output_format != OUTPUT_FORMAT_CRUMB);
-
- /* Find the correct translation table for the chosen output format */
- for (i = 0; i < sizeof (translate_table) / sizeof (translate_table[0]); i++) {
- table = &translate_table[i];
- if (table && table->output_format == output_format)
- break;
- }
-
- if (! table)
- return NULL;
-
- len = pstr->len;
- start = pstr->buf;
-
- /* First, calculate the amount of space needed for the expanded
- * buffer.
- */
- extra = 0;
- while (start && *start) {
- for (i = 0; i < TRANSLATE_MAP_ENTRIES; i++) {
- from = table->map[i].from;
- if (*start == from) {
- /* Subtract one to take account of the
- * pre-existing character we're going to
- * replace.
- */
- extra += (wcslen (table->map[i].to) - 1);
- }
- }
- start++;
- }
-
- if (! extra) {
- /* No translation required.
- *
- * FIXME: this is inefficient - we should really have
- * the function accept a 'pstring **' to avoid
- * re-copying.
- */
- return pstring_create (pstr->buf);
- }
-
- len += extra;
-
- result = pstring_new ();
- if (! result)
- return NULL;
-
- /* Note that this includes the space for the terminator
- * (since a pstring's len includes the terminator)
- */
- bytes = len * sizeof (wchar_t);
-
- result->buf = malloc (bytes);
- if (! result->buf) {
- pstring_free (result);
- return NULL;
- }
-
- /* We're using wcsncat() so we'd better make sure there is a
- * nul for it to find!
- *
- * Note: we could have used calloc to do this for us, but
- * the code is clearer using the @bytes idiom.
- */
- memset (result->buf, '\0', bytes);
-
- result->size = bytes;
-
- /* Sanity check for upcoming overrun check */
- assert (result->buf[len-1] == L'\0');
-
- /* Now, iterate the string again, performing the actual
- * replacements.
- */
- p = start = pstr->buf;
-
- while (p && *p) {
- for (i = 0; i < TRANSLATE_MAP_ENTRIES; i++) {
- wchar_t *to;
- size_t len;
-
- from = table->map[i].from;
-
- if (*p != from)
- continue;
-
- to = table->map[i].to;
-
- amount = p - start;
-
- /* Copy from start to match */
- wcsncat (result->buf + result->len, start, amount);
-
- result->len += amount;
-
- /* Copy replacement text */
- len = wcslen (to);
- wcsncat (result->buf + result->len, to, len);
- result->len += len;
-
- /* Jump over the matching character */
- start = p + 1;
-
- break;
- }
- p++;
- }
-
- /* Copy remaining non-matching chars */
- amount = p - start;
- wcsncat (result->buf + result->len, start, amount);
- result->len += amount;
-
- /* Account for terminator */
- result->len += 1;
-
- /* check for buffer overrun */
- assert (result->buf[len-1] == L'\0');
-
- return result;
-}
-/**
- * change_element:
- *
- * Handle changing to a new element type. Depending on the output
- * format, this may require separators and newlines to be emitted to
- * produce well-formatted output.
- **/
-void
-change_element (ElementType new)
-{
- common_assert ();
-
- last_element = current_element;
-
- current_element = new;
-
- format_element ();
-}
-
-void
-format_element (void)
-{
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- format_text_element ();
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_JSON:
- format_json_element ();
- break;
-
- case OUTPUT_FORMAT_XML:
- format_xml_element ();
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-format_text_element (void)
-{
- common_assert ();
- switch (last_element) {
-
- case ELEMENT_TYPE_ENTRY:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_NONE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-format_json_element (void)
-{
- common_assert ();
-
- switch (last_element) {
-
- case ELEMENT_TYPE_ENTRY:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L",\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- case ELEMENT_TYPE_OBJECT_OPEN:
- /* NOP */
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- assert_not_reached ();
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L",\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- /* NOP */
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- case ELEMENT_TYPE_SECTION_CLOSE:
- assert_not_reached ();
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L",\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- case ELEMENT_TYPE_SECTION_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- case ELEMENT_TYPE_SECTION_OPEN:
- wappend (&doc, L",\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_NONE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-format_xml_element (void)
-{
- common_assert ();
-
- switch (last_element) {
-
- case ELEMENT_TYPE_ENTRY:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- assert_not_reached ();
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- assert_not_reached ();
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE:
- /* NOP */
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- case ELEMENT_TYPE_ENTRY:
- wappend (&doc, L"\n");
- dec_indent ();
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_NONE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * compress:
- *
- * Remove lines composed entirely of whitespace from @str.
- *
- * This is required specifically for '--output=text' which in some
- * scenarios generates lines comprising pure whitespace. This is
- * unecessary and results from the fact that when an
- * ELEMENT_TYPE_OBJECT_* is encountered, formatting is applied for the
- * previously seen element, but sometimes such "objects" should be
- * invisible.
- **/
-void
-compress (pstring **wstr, wchar_t remove_char)
-{
- wchar_t *from;
- wchar_t *to;
- wchar_t *p;
- wchar_t *start;
- size_t count = 0;
- size_t blanks = 0;
- size_t new_len;
- size_t bytes;
-
- assert (wstr);
-
- to = from = (*wstr)->buf;
-
- while (to && *to) {
-again:
- while (*to == L'\n' && *(to+1) == L'\n') {
- /* skip over blank lines */
- to++;
- blanks++;
- }
-
- start = to;
-
- while (*to == remove_char) {
- /* skip runs of contiguous characters */
- to++;
- count++;
- }
-
- if (to != start) {
- /* Only start consuming NLs at the end of a
- * contiguous run *iff* there was more than a
- * single removed char. This is a heuristic to
- * avoid removing valid entries for example env
- * vars that are set to nul are shown as:
- *
- * 'var: '
- *
- * Shudder.
- */
- if (*to == L'\n' && to != start+1) {
- while (*to == L'\n') {
- /* consume the NL at the end of the contiguous run */
- to++;
- }
-
- /* check to ensure that we haven't entered a new line
- * containing another block of chars to remove.
- */
- if (*to == remove_char)
- goto again;
-
- blanks++;
-
- } else {
- /* not a full line so backtrack */
- to = start;
- count = 0;
- }
- }
-
- *from++ = *to++;
- }
-
- /* terminate */
- *from = L'\0';
-
- if (blanks || count) {
- new_len = (*wstr)->len - (blanks + count);
-
- bytes = new_len * sizeof (wchar_t);
-
- p = realloc ((*wstr)->buf, bytes);
- assert (p);
-
- (*wstr)->buf = p;
-
- (*wstr)->buf[new_len-1] = L'\0';
-
- (*wstr)->len = new_len;
- (*wstr)->size = bytes;
- }
-}
-/**
- * chomp:
- *
- * Remove trailing extraneous newlines and indent_chars from @str.
- **/
-void
-chomp (pstring *str)
-{
- size_t len;
- int removable = 0;
- wchar_t *p;
-
- assert (str);
-
- /* Unable to add '\n' in this scenario */
- if (str->len < 2)
- return;
-
- for (p = str->buf+str->len-1; *p == L'\n' || *p == wide_indent_char;
- p--, removable++)
- ;
-
- /* Chop string at the appropriate place after first adding a new
- * newline.
- */
- if (removable > 1) {
- len = str->len - (removable-1);
- str->buf[len-1] = L'\n';
- str->buf[len] = L'\0';
- str->len = len;
- }
-}
-
void
show_version (void)
{
@@ -9974,424 +4288,35 @@ show_version (void)
void
show_shared_mem (void)
{
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- show_shared_mem_linux ();
-#else
- show_shared_mem_stub ();
-#endif
-}
-
-void
-show_semaphores (void)
-{
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- show_semaphores_linux ();
-#else
- show_semaphores_stub ();
-#endif
-}
-
-void
-show_msg_queues (void)
-{
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- show_msg_queues_linux ();
-#else
- show_msg_queues_stub ();
-#endif
-}
-
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-void
-show_shared_mem_linux (void)
-{
- int i;
- int id;
- int max;
- struct shm_info info;
- struct shmid_ds shmid_ds;
- struct ipc_perm *perm;
- char formatted_atime[CTIME_BUFFER];
- char formatted_ctime[CTIME_BUFFER];
- char formatted_dtime[CTIME_BUFFER];
- char *modestr = NULL;
- int locked = -1;
- int destroy = -1;
- char *cpid = NULL;
- char *lpid = NULL;
-
header ("shared memory");
- max = shmctl (0, SHM_INFO, (void *)&info);
- if (max < 0)
- goto out;
-
- /* Display summary details */
-
- section_open ("info");
-
- entry ("segments", "%u", info.used_ids);
- entry ("pages", "%lu", info.shm_tot);
- entry ("shm_rss", "%lu", info.shm_rss);
- entry ("shm_swp", "%lu", info.shm_swp);
-
- /* Apparently unused */
- entry ("swap_attempts", "%lu", info.swap_attempts);
- entry ("swap_successes", "%lu", info.swap_successes);
-
- section_close ();
-
- container_open ("segments");
-
- object_open (FALSE);
-
- for (i = 0; i <= max; i++) {
- char *id_str = NULL;
-
- id = shmctl (i, SHM_STAT, &shmid_ds);
- if (id < 0) {
- /* found an unused slot, so ignore it */
- continue;
- }
-
- perm = &shmid_ds.shm_perm;
-
- modestr = format_perms (perm->mode);
- if (! modestr)
- die ("failed to allocate space for permissions string");
-
-#ifdef PROCENV_LINUX
- locked = (perm->mode & SHM_LOCKED);
- destroy = (perm->mode & SHM_DEST);
-#endif
-
- format_time (&shmid_ds.shm_atime, formatted_atime, sizeof (formatted_atime));
- format_time (&shmid_ds.shm_ctime, formatted_ctime, sizeof (formatted_ctime));
- format_time (&shmid_ds.shm_dtime, formatted_dtime, sizeof (formatted_dtime));
-
- cpid = pid_to_name (shmid_ds.shm_cpid);
- lpid = pid_to_name (shmid_ds.shm_lpid);
-
- appendf (&id_str, "%d", id);
-
- container_open (id_str);
- free (id_str);
-
- object_open (FALSE);
-
- /* pad out to max pointer size represented in hex.
- */
- entry ("key", "0x%.*x", POINTER_SIZE * 2, perm->__key);
- entry ("sequence", "%u", perm->__seq);
-
- section_open ("permissions");
- entry ("octal", "%4.4o", perm->mode);
- entry ("symbolic", "%s", modestr);
- section_close ();
-
- section_open ("pids");
- entry ("create", "%d (%s)", shmid_ds.shm_cpid, cpid ? cpid : UNKNOWN_STR);
- entry ("last", "%d (%s)", shmid_ds.shm_lpid, lpid ? lpid : UNKNOWN_STR);
- section_close ();
-
- entry ("attachers", "%lu", shmid_ds.shm_nattch);
-
- section_open ("creator");
- entry ("euid", "%u ('%s')", perm->cuid, get_user_name (perm->cuid));
- entry ("egid", "%u ('%s')", perm->cgid, get_group_name (perm->cgid));
- section_close ();
-
- section_open ("owner");
- entry ("uid", "%u ('%s')", perm->uid, get_user_name (perm->uid));
- entry ("gid", "%u ('%s')", perm->gid, get_group_name (perm->gid));
- section_close ();
-
- entry ("segment size", "%lu", shmid_ds.shm_segsz);
-
- section_open ("times");
- entry ("last attach (atime)", "%lu (%s)", shmid_ds.shm_atime, formatted_atime);
- entry ("last detach (dtime)", "%lu (%s)", shmid_ds.shm_dtime, formatted_dtime);
- entry ("last change (ctime)", "%lu (%s)", shmid_ds.shm_ctime, formatted_ctime);
- section_close ();
-
- entry ("locked", "%s", locked == 0 ? NO_STR
- : locked > 0 ? YES_STR
- : NA_STR);
- entry ("destroy", "%s", destroy == 0 ? NO_STR
- : destroy > 0 ? YES_STR
- : NA_STR);
-
- object_close (FALSE);
-
- container_close ();
-
- free (modestr);
- if (cpid)
- free (cpid);
- if (lpid)
- free (lpid);
- }
-
- object_close (FALSE);
-
- container_close ();
+ if (ops->show_shared_mem)
+ ops->show_shared_mem ();
-out:
footer ();
}
void
-show_semaphores_linux (void)
+show_semaphores (void)
{
- int i;
- int id;
- int max;
- struct semid_ds semid_ds;
- struct seminfo info;
- struct ipc_perm *perm;
- char formatted_otime[CTIME_BUFFER];
- char formatted_ctime[CTIME_BUFFER];
- char *modestr = NULL;
- union semun arg;
-
header ("semaphores");
- arg.array = (unsigned short int *)(void *)&info;
- max = semctl (0, 0, SEM_INFO, arg);
- if (max < 0)
- goto out;
-
- section_open ("info");
-
- entry ("semmap", "%d", info.semmap);
- entry ("semmni", "%d", info.semmni);
- entry ("semmns", "%d", info.semmns);
- entry ("semmnu", "%d", info.semmnu);
- entry ("semmsl", "%d", info.semmsl);
- entry ("semopm", "%d", info.semopm);
- entry ("semume", "%d", info.semume);
- entry ("semusz", "%d", info.semusz);
- entry ("semvmx", "%d", info.semvmx);
- entry ("semaem", "%d", info.semaem);
-
- section_close ();
-
- container_open ("set");
-
- object_open (FALSE);
-
- for (i = 0; i <= max; i++) {
- char *id_str = NULL;
-
- /* see semctl(2) */
- arg.buf = (struct semid_ds *)&semid_ds;
-
- id = semctl (i, 0, SEM_STAT, arg);
- if (id < 0) {
- /* found an unused slot, so ignore it */
- continue;
- }
-
- perm = &semid_ds.sem_perm;
-
- modestr = format_perms (perm->mode);
- if (! modestr)
- die ("failed to allocate space for permissions string");
-
- /* May not have been set */
- if (semid_ds.sem_otime)
- format_time (&semid_ds.sem_otime, formatted_otime, sizeof (formatted_otime));
- else
- sprintf (formatted_otime, "%s", NA_STR);
-
- format_time (&semid_ds.sem_ctime, formatted_ctime, sizeof (formatted_ctime));
-
- appendf (&id_str, "%d", id);
-
- container_open (id_str);
- free (id_str);
-
- object_open (FALSE);
-
- /* pad out to max pointer size represented in hex.
- */
- entry ("key", "0x%.*x", POINTER_SIZE * 2, perm->__key);
- entry ("sequence", "%u", perm->__seq);
-
- entry ("number in set", "%lu", semid_ds.sem_nsems);
-
- section_open ("permissions");
- entry ("octal", "%4.4o", perm->mode);
- entry ("symbolic", "%s", modestr);
- free (modestr);
- section_close ();
-
- section_open ("creator");
- entry ("euid", "%u ('%s')", perm->cuid, get_user_name (perm->cuid));
- entry ("egid", "%u ('%s')", perm->cgid, get_group_name (perm->cgid));
- section_close ();
-
- section_open ("owner");
- entry ("uid", "%u ('%s')", perm->uid, get_user_name (perm->uid));
- entry ("gid", "%u ('%s')", perm->gid, get_group_name (perm->gid));
- section_close ();
-
- section_open ("times");
- entry ("last semop (otime)", "%lu (%s)", semid_ds.sem_otime, formatted_otime);
- entry ("last change (ctime)", "%lu (%s)", semid_ds.sem_ctime, formatted_ctime);
- section_close ();
-
- object_close (FALSE);
-
- container_close ();
- }
-
- object_close (FALSE);
-
- container_close ();
+ if (ops->show_semaphores)
+ ops->show_semaphores ();
-out:
footer ();
}
void
-show_msg_queues_linux (void)
+show_msg_queues (void)
{
- int i;
- int id;
- int max;
- struct msginfo info;
- struct msqid_ds msqid_ds;
- struct ipc_perm *perm;
- char formatted_stime[CTIME_BUFFER];
- char formatted_rtime[CTIME_BUFFER];
- char formatted_ctime[CTIME_BUFFER];
- char *modestr = NULL;
- char *lspid = NULL;
- char *lrpid = NULL;
-
header ("message queues");
- max = msgctl (0, MSG_INFO, (void *)&info);
- if (max < 0)
- goto out;
-
- section_open ("info");
-
- entry ("msgpool", "%d", info.msgpool);
- entry ("msgmap", "%d", info.msgmap);
- entry ("msgmax", "%d", info.msgmax);
- entry ("msgmnb", "%d", info.msgmnb);
- entry ("msgmni", "%d", info.msgmni);
- entry ("msgssz", "%d", info.msgssz);
- entry ("msgtql", "%d", info.msgtql);
- entry ("msgseg", "%d", info.msgseg);
-
- section_close ();
-
- container_open ("sets");
-
- object_open (FALSE);
-
- for (i = 0; i <= max; i++) {
- char *id_str = NULL;
-
- id = msgctl (i, MSG_STAT, &msqid_ds);
- if (id < 0) {
- /* found an unused slot, so ignore it */
- continue;
- }
-
- perm = &msqid_ds.msg_perm;
-
- modestr = format_perms (perm->mode);
- if (! modestr)
- die ("failed to allocate space for permissions string");
-
- /* May not have been set */
- if (msqid_ds.msg_stime)
- format_time (&msqid_ds.msg_stime, formatted_stime, sizeof (formatted_stime));
- else
- sprintf (formatted_stime, "%s", NA_STR);
-
- /* May not have been set */
- if (msqid_ds.msg_rtime)
- format_time (&msqid_ds.msg_rtime, formatted_rtime, sizeof (formatted_rtime));
- else
- sprintf (formatted_rtime, "%s", NA_STR);
-
- /* May not have been set */
- if (msqid_ds.msg_ctime)
- format_time (&msqid_ds.msg_ctime, formatted_ctime, sizeof (formatted_ctime));
- else
- sprintf (formatted_ctime, "%s", NA_STR);
-
- lspid = pid_to_name (msqid_ds.msg_lspid);
- lrpid = pid_to_name (msqid_ds.msg_lrpid);
-
- appendf (&id_str, "%d", id);
-
- container_open (id_str);
- free (id_str);
-
- object_open (FALSE);
+ if (ops->show_msg_queues)
+ ops->show_msg_queues ();
- /* pad out to max pointer size represented in hex */
- entry ("key", "0x%.*x", POINTER_SIZE * 2, perm->__key);
- entry ("sequence", "%u", perm->__seq);
-
- section_open ("permissions");
- entry ("octal", "%4.4o", perm->mode);
- entry ("symbolic", "%s", modestr);
- section_close ();
-
- section_open ("creator");
- entry ("euid", "%u ('%s')", perm->cuid, get_user_name (perm->cuid));
- entry ("egid", "%u ('%s')", perm->cgid, get_group_name (perm->cgid));
- section_close ();
-
- section_open ("owner");
- entry ("uid", "%u ('%s')", perm->uid, get_user_name (perm->uid));
- entry ("gid", "%u ('%s')", perm->gid, get_group_name (perm->gid));
- section_close ();
-
- section_open ("times");
- entry ("last send (stime)", "%lu (%s)", msqid_ds.msg_stime, formatted_stime);
- entry ("last receive (rtime)", "%lu (%s)", msqid_ds.msg_rtime, formatted_rtime);
- entry ("last change (ctime)", "%lu (%s)", msqid_ds.msg_ctime, formatted_ctime);
- section_close ();
-
- entry ("queue_bytes", "%lu", msqid_ds.__msg_cbytes);
-
- entry ("msg_qnum", "%lu", msqid_ds.msg_qnum);
- entry ("msg_qbytes", "%lu", msqid_ds.msg_qbytes);
-
- entry ("last msgsnd pid", "%d (%s)", msqid_ds.msg_lspid,
- lspid ? lspid : UNKNOWN_STR);
-
- entry ("last msgrcv pid", "%d (%s)", msqid_ds.msg_lrpid,
- lrpid ? lrpid : UNKNOWN_STR);
-
- object_close (FALSE);
-
- container_close ();
-
- free (modestr);
- if (lspid)
- free (lspid);
- if (lrpid)
- free (lrpid);
- }
-
- object_close (FALSE);
-
- container_close ();
-
-out:
footer ();
}
-#endif /* PROCENV_LINUX || PROCENV_HURD */
void
format_time (const time_t *t, char *buffer, size_t len)
@@ -10461,290 +4386,258 @@ format_perms (mode_t mode)
return modestr;
}
-char *
-pid_to_name (pid_t pid)
-{
- char path[PATH_MAX];
- char *name = NULL;
- FILE *f = NULL;
-
- sprintf (path, "/proc/%d/cmdline", (int)pid);
-
- f = fopen (path, "r");
- if (! f)
- goto out;
-
- /* Reuse buffer */
- if (! fgets (path, sizeof (path), f))
- goto out;
-
- /* Nul delimiting within /proc file will ensure we only get the
- * program name.
- */
- append (&name, path);
-
-out:
- if (f)
- fclose (f);
-
- return name;
-}
-
+/*
+ * BSD returns an additional AF_LINK ifaddrs containing the
+ * actual link-layer MAC address for each interface.
+ *
+ * Linux does the same but with one additional AF_PACKET family / interface.
+ *
+ * This is somewhat noisome since for BSD we need to cache the MAC addresses
+ * such that they can be retrieved when the _next_ ifaddrs structure
+ * appears for the *same* interface, but we only want to
+ * display the non-AF_LINK elements *unless* they refer
+ * to an interface with no associated address.
+ *
+ * The situation for Linux is similar but we only care
+ * about AF_PACKET entries for interfaces that have no
+ * associated address since we can extract the MAC
+ * address using an ioctl (rather than considering the
+ * AF_PACKET element).
+ *
+ * The strategy therefore is to:
+ *
+ * 1) Cache all AF_LINK/AF_PACKET elements.
+ * 2) Once an element arrives that matches an interface
+ * name found in the cache, use that as necessary (extra
+ * the MAC for BSD, NOP for Linux), then free that cache
+ * element.
+ * 3) Having processed all entries, if any entries are
+ * left in the cache, they must refer to interfaces that
+ * have no address, so display them.
+ *
+ * XXX: Note the implicit assumption that the AF_LINK/AF_PACKET entries
+ * will appear _before_ the corresponding entry containing address
+ * details for the interface in the output of getifaddrs(): observations
+ * suggests this _seems_ to be the case, but is not documented as being
+ * guaranteed.
+ */
+#ifdef PROCENV_PLATFORM_ANDROID
+// FIXME: split out to platfom
void
-add_breadcrumb (const char *name)
+show_network (void)
{
- assert (name);
-
- if (! crumb_list)
- crumb_list = pr_list_new (NULL);
-
- assert (crumb_list);
-
- pr_list_prepend_str (crumb_list, name);
+ /* Bionic isn't actually that bionic at all :( */
+ header ("network");
+ footer ();
}
-void
-remove_breadcrumb (void)
-{
- PRList *entry;
-
- assert (crumb_list);
-
- entry = pr_list_remove (crumb_list->prev);
- assert (entry);
-
- free ((char *)entry->data);
- free (entry);
-}
+#else
void
-clear_breadcrumbs (void)
-{
- assert (crumb_list);
-
- while (crumb_list->prev != crumb_list)
- remove_breadcrumb ();
-}
-
-wchar_t *
-char_to_wchar (const char *str)
+show_network (void)
{
- const char *p;
- wchar_t *wstr = NULL;
- size_t len;
- size_t bytes;
-
- assert (str);
-
- len = mbsrtowcs (NULL, &str, 0, NULL);
- if (len <= 0)
- return NULL;
-
- /* include space for terminator */
- bytes = (1 + len) * sizeof (wchar_t);
-
- wstr = malloc (bytes);
- if (! wstr)
- return NULL;
-
- p = str;
+ struct ifaddrs *if_addrs;
+ struct ifaddrs *ifa;
+ char *mac_address = NULL;
+ struct network_map *head = NULL;
+ struct network_map *node = NULL;
+ struct network_map *tmp = NULL;
- if (mbsrtowcs (wstr, &p, len, NULL) != len)
- goto error;
+ common_assert ();
- /* ensure it's terminated */
- wstr[len] = L'\0';
+ header ("network");
- return wstr;
+ /* Query all network interfaces */
+ if (getifaddrs (&if_addrs) < 0)
+ return;
-error:
- free (wstr);
- return NULL;
-}
+ /* Construct an initial node for the cache */
+ head = calloc (1, sizeof (struct network_map));
+ assert (head);
-pstring *
-pstring_new (void)
-{
- pstring *pstr = NULL;
+ /* Iterate over all network interfaces */
+ for (ifa = if_addrs; ifa; ifa = ifa->ifa_next) {
+#if !defined (PROCENV_PLATFORM_HURD)
+ int family;
+#endif
- pstr = calloc (1, sizeof (pstring));
- if (! pstr)
- return NULL;
+ if (! ifa->ifa_addr)
+ continue;
- pstr->len = 0;
- pstr->size = 0;
- pstr->buf = NULL;
+#if !defined (PROCENV_PLATFORM_HURD)
+ family = ifa->ifa_addr->sa_family;
- return pstr;
-}
+ if (family == PROCENV_LINK_LEVEL_FAMILY) {
-pstring *
-pstring_create (const wchar_t *str)
-{
- pstring *pstr = NULL;
+ /* MAC address cannot be queries on minix seemingly */
+#if !defined (PROCENV_PLATFORM_MINIX)
+ /* Add link level interface details to the cache */
+ mac_address = get_mac_address (ifa);
+#endif
- assert (str);
+ node = calloc (1, sizeof (struct network_map));
+ assert (node);
- pstr = pstring_new ();
+ /* Conveniently, an ifaddrs contains a bunch of
+ * pointers and some flags.
+ *
+ * Since all those pointers are valid until we
+ * call freeifaddrs(), all we need to do is copy
+ * the flags since the memcpy will copy the
+ * pointers addresses for us :)
+ */
+ memcpy (&node->ifaddr, ifa, sizeof (struct ifaddrs));
+ node->ifaddr.ifa_flags = ifa->ifa_flags;
- if (! pstr)
- return NULL;
+ /* Since we've already formatted the MAC
+ * address, we'll cache that too.
+ */
+ node->mac_address = mac_address;
+ mac_address = NULL;
- pstr->buf = wcsdup (str);
- if (! pstr->buf) {
- pstring_free (pstr);
- return NULL;
- }
+ /* prepend */
+ node->next = head->next;
+ if (head->next)
+ head->next->prev = node;
+ node->prev = head;
+ head->next = node;
- /* include the L'\0' terminator */
- pstr->len = 1 + wcslen (pstr->buf);
+ continue;
+ }
+#endif
- pstr->size = pstr->len * sizeof (wchar_t);
+ /* From now on, we're only looking at interfaces with an
+ * address.
+ */
- return pstr;
-}
+ /* Search for an entry corresponding to the interface in the cache */
+ for (node = head->next; node && node->ifaddr.ifa_name; node = node->next) {
+ if (! strcmp (node->ifaddr.ifa_name, ifa->ifa_name)) {
-void
-pstring_free (pstring *str)
-{
- assert (str);
+ /* Save */
+ mac_address = node->mac_address
+ ? strdup (node->mac_address)
+ : NULL;
- if (str->buf)
- free (str->buf);
+ /* Unlink existing node as it has now served its purpose */
+ node->prev->next = node->next;
+ if (node->next)
+ node->next->prev = node->prev;
- free (str);
-}
+ /* Destroy */
+ if (node->mac_address)
+ free (node->mac_address);
+ free (node);
-pstring *
-char_to_pstring (const char *str)
-{
- pstring *pstr = NULL;
- wchar_t *s;
+ break;
+ }
+ }
- assert (str);
+ /* Display the interface (which must have an associated address) */
+ show_network_if (ifa, mac_address);
+ if (mac_address) {
+ free (mac_address);
+ mac_address = NULL;
+ }
+ }
- s = char_to_wchar (str);
- if (! s)
- return NULL;
+ /* Destroy the cache, displaying any interfaces not previously displayed.
+ * These by definition cannot have addresses assigned to them.
+ */
+ for (node = head->next; node && node->ifaddr.ifa_name; node = tmp) {
- pstr = pstring_create (s);
+ tmp = node->next;
- free (s);
+ show_network_if (&node->ifaddr, node->mac_address);
- return pstr;
-}
+ /* Destroy */
+ if (node->mac_address)
+ free (node->mac_address);
+ free (node);
+ }
-char *
-pstring_to_char (const pstring *str)
-{
- assert (str);
+ free (head);
+ freeifaddrs (if_addrs);
- return wchar_to_char (str->buf);
+ footer ();
}
+#endif
-char *
-wchar_to_char (const wchar_t *wstr)
+void
+show_misc (void)
{
- char *str = NULL;
- size_t len;
- size_t bytes;
- size_t ret;
-
- assert (wstr);
-
- len = wcslen (wstr);
-
- /* determine number of MBS (char) bytes requires to hold the
- * wchar_t string.
- */
- bytes = wcstombs (NULL, wstr, len);
- if (! bytes)
- return NULL;
-
- str = calloc (bytes + 1, sizeof (char));
- if (! str)
- return NULL;
-
- /* actually perform the conversion */
- ret = wcstombs (str, wstr, bytes);
-
- if (! ret)
- goto error;
-
- return str;
+#if defined (PROCENV_PLATFORM_LINUX)
+ int domain = 0x0;
-error:
- free (str);
- return NULL;
-}
+ /* magic value - see personality(2) */
+ unsigned int persona = 0xFFFFFFFF;
-#if ! defined (HAVE_SCHED_GETCPU)
+ unsigned int mask = PER_MASK;
-/**
- * @string: input,
- * @delimiter: field delimiter,
- * @compress: if TRUE, ignore repeated contiguous delimiter characters,
- * @array: [output] array of fields, which this function will allocate.
- *
- * Notes: it is the callers responsibility to free @array
- * if the returned value is >0.
- *
- * Returns: number of fields in @string.
- **/
-size_t
-split_fields (const char *string, char delimiter, int compress, char ***array)
-{
- const char *p = NULL;
- const char *start = NULL;
- size_t count = 0;
- char *elem;
- char **new;
+ const char *personality_name = NULL;
+ char *personality_flags = NULL;
+#endif
- assert (string);
- assert (delimiter);
- assert (array);
+ header ("misc");
- *array = NULL;
+ entry ("umask", "%4.4o", misc.umask_value);
+ entry ("current directory (cwd)", "'%s'", misc.cwd);
+#if defined (PROCENV_PLATFORM_LINUX)
+ entry ("root", "%s%s%s",
+ strcmp (misc.root, UNKNOWN_STR) ? "'" : "",
+ misc.root,
+ strcmp (misc.root, UNKNOWN_STR) ? "'" : "");
+#endif
+ entry ("chroot", "%s", in_chroot () ? YES_STR : NO_STR);
+ entry ("container", "%s", container_type ());
- new = realloc ((*array), sizeof (char *) * (1+count));
- assert (new);
+ entry ("vm", "%s",
+ ops->in_vm ?
+ ops->in_vm () ? YES_STR : NO_STR
+ : UNKNOWN_STR);
- new[0] = NULL;
- *array = new;
+ if (ops->show_prctl) {
+ section_open ("prctl");
+ ops->show_prctl ();
+ section_close ();
+ }
- p = string;
+ if (ops->show_security_module) {
+ section_open ("security module");
+ ops->show_security_module ();
+ section_close ();
+ }
- while (p && *p) {
- /* skip leading prefix */
- while (compress && p && *p == delimiter)
- p++;
+#if defined (PROCENV_PLATFORM_LINUX)
+#ifdef LINUX_VERSION_CODE
+ entry ("kernel headers version", "%u.%u.%u",
+ (LINUX_VERSION_CODE >> 16),
+ ((LINUX_VERSION_CODE >> 8) & 0xFF),
+ (LINUX_VERSION_CODE & 0xFF));
+#endif
- if (! *p)
- break;
+ domain = personality (persona);
- /* found a field */
- count++;
+ personality_name = get_personality_name (domain & mask);
- if (! compress)
- p++;
+ section_open ("personality");
- /* skip over the field */
- start = p;
- while (p && *p && *p != delimiter)
- p++;
+ entry ("type", "%s", personality_name
+ ? personality_name
+ : UNKNOWN_STR);
- elem = strndup (start, p-start);
- assert (elem);
+ personality_flags = get_personality_flags (domain & (-1 ^ mask));
+ entry ("flags", "%s",
+ personality_flags
+ ? personality_flags
+ : "");
- new = realloc ((*array), sizeof (char *) * (1+count));
- assert (new);
+ section_close ();
- new[count-1] = elem;
- *array = new;
- }
+ if (personality_flags)
+ free (personality_flags);
+#endif
- return count;
+ footer ();
}
-
-#endif