summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitrijs Ledkovs <dmitrijs.ledkovs@canonical.com>2013-08-28 18:09:14 +0100
committerDmitrijs Ledkovs <dmitrijs.ledkovs@canonical.com>2013-08-28 18:09:14 +0100
commit317bcb1d9feec3c642aa3565fa5bb97fc208631b (patch)
tree3b1a50a0ec1f2164c89d77d5351c7bbaffa8daef
parent67624665d5ed391da120ad4c3a5cb8a6be2bd812 (diff)
New upstream release.debian/0.26-1
-rw-r--r--ChangeLog53
-rw-r--r--Makefile.in2
-rw-r--r--NEWS16
-rw-r--r--TODO4
-rw-r--r--aclocal.m46
-rwxr-xr-xconfig/depcomp3
-rw-r--r--config/ltmain.sh4
-rwxr-xr-xconfigure20
-rw-r--r--configure.ac2
-rw-r--r--debian/changelog14
-rw-r--r--debian/control2
-rw-r--r--man/procenv.127
-rw-r--r--src/Makefile.am7
-rw-r--r--src/Makefile.in9
-rw-r--r--src/procenv.c1121
-rw-r--r--src/procenv.h123
16 files changed, 1277 insertions, 136 deletions
diff --git a/ChangeLog b/ChangeLog
index 1c5ba68..35ff4d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+2013-08-23 James Hunt <james.hunt@ubuntu.com>
+
+ * TODO:
+ * man/procenv.1:
+ - Added -A/--arguments option.
+ - Updated --mount to include reference to statfs.
+ - Added -N/--network option.
+ - Updated SEE ALSO section.
+ * src/procenv.c:
+ - Added support for BSD/Hurd signals: SIGEMT, SIGINFO, SIGLOST.
+ - usage(): Use colon to separate output types from description for
+ consistency.
+ - is_console(): Enable for FreeBSD/kFreeBSD.
+ - append(): Allocate space if str points to NULL.
+ - appendf(): Allocate space if str points to NULL.
+ - appendva(): Allocate space if str points to NULL.
+ - dump():
+ - Call show_network().
+ - Call show_locale() *after* show_rlimits() for correct ordering.
+ - show_linux_mounts(): Add block and inode details (LP: #1212728).
+ - show_bsd_mounts(): Add block and inode details (LP: #1212728).
+ - show_compiler():
+ - Added __FILE__, __BASE_FILE__ and __TIMESTAMP__.
+ - main():
+ - Updates for -N/--network.
+ - New functions:
+ - show_arguments().
+ - get_network_address().
+ - decode_if_flags().
+ - get_ipv6_scope_name() (unused).
+ - get_mtu().
+ - get_mac_address().
+ - decode_extended_if_flags().
+ - get_net_family_name().
+ - show_network_if().
+ - show_network().
+
+2013-07-19 James Hunt <james.hunt@ubuntu.com>
+
+ * src/man/procenv.1: Updated date and year.
+ * src/procenv.c:
+ - show_bsd_proc_branch(): Fix to work in BSD jails: these entities are
+ bizarre in that they have no init process, and a processes parent
+ may actually be a process running *outside* of the jail... and as a
+ result, all you can know about it is its PID.
+ - Various hacks to work in the decidedly un-bionic Android
+ environment.
+ * Android.mk: Makefile for Android.
+
+2013-07-04 James Hunt <james.hunt@ubuntu.com>
+
+ * man/procenv.1: Add a new --exec example.
+
2013-06-28 James Hunt <james.hunt@ubuntu.com>
* configure.ac: Force old serial test behaviour (specifically
diff --git a/Makefile.in b/Makefile.in
index 3beaee7..fcd1a66 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.2 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
diff --git a/NEWS b/NEWS
index 379f4eb..5644fe9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,19 @@
+0.26 2013-08-27
+
+ * Check to determine if running on a console now works for
+ FreeBSD/kFreeBSD too.
+ * Added ability to show all arguments (-A/--arguments)
+ (useful when using --exec).
+ * Added ability to display network details (-N/--network).
+ * Added BSD/Hurd-specific signals.
+ * Corrected output sort order.
+ * Mount details now include block, inode and fsck details.
+
+0.25 2013-07-19
+
+ * Fixed bug where procenv would hang in a FreeBSD jail.
+ * Port to Android.
+
0.24 2013-06-28
* Packaging update for automake-1.13 to ensure procenv output
diff --git a/TODO b/TODO
index cf7326e..ad8b543 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,8 @@
# TODO
- networking details
-- add statfs(2)
+ - IPv6 scope_id.
+ - gateway.
- add to show_sizeof():
- intN_t group
- i18n (gettext)
@@ -18,6 +19,7 @@
- add process arguments to show_proc_branch()?
- sort output of show_mounts().
- use CPUID instruction to detect XEN environments?
+ (http://libcpuid.sourceforge.net/)
- use dlopen to probe for apparmor/selinux. This avoids having to depend
on the existence of the appropriate libs, but still allows security
context information to be queried on systems that provide them.
diff --git a/aclocal.m4 b/aclocal.m4
index 05c1a54..a5d5503 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.13.2 -*- Autoconf -*-
+# generated automatically by aclocal 1.13.3 -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
@@ -195,7 +195,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.13'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.13.2], [],
+m4_if([$1], [1.13.3], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -211,7 +211,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.13.2])dnl
+[AM_AUTOMAKE_VERSION([1.13.3])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
diff --git a/config/depcomp b/config/depcomp
index 06b0882..4ebd5b3 100755
--- a/config/depcomp
+++ b/config/depcomp
@@ -1,7 +1,7 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
-scriptversion=2012-10-18.11; # UTC
+scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
@@ -552,6 +552,7 @@ $ {
G
p
}' >> "$depfile"
+ echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
diff --git a/config/ltmain.sh b/config/ltmain.sh
index b9205ee..3825a2a 100644
--- a/config/ltmain.sh
+++ b/config/ltmain.sh
@@ -70,7 +70,7 @@
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
-# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.2ubuntu1
+# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.3ubuntu1
# automake: $automake_version
# autoconf: $autoconf_version
#
@@ -80,7 +80,7 @@
PROGRAM=libtool
PACKAGE=libtool
-VERSION="2.4.2 Debian-2.4.2-1.2ubuntu1"
+VERSION="2.4.2 Debian-2.4.2-1.3ubuntu1"
TIMESTAMP=""
package_revision=1.3337
diff --git a/configure b/configure
index be2ba31..b5bfdc1 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for procenv 0.24.
+# Generated by GNU Autoconf 2.69 for procenv 0.26.
#
# Report bugs to <james.hunt@ubuntu.com>.
#
@@ -583,8 +583,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='procenv'
PACKAGE_TARNAME='procenv'
-PACKAGE_VERSION='0.24'
-PACKAGE_STRING='procenv 0.24'
+PACKAGE_VERSION='0.26'
+PACKAGE_STRING='procenv 0.26'
PACKAGE_BUGREPORT='james.hunt@ubuntu.com'
PACKAGE_URL=''
@@ -1279,7 +1279,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures procenv 0.24 to adapt to many kinds of systems.
+\`configure' configures procenv 0.26 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1345,7 +1345,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of procenv 0.24:";;
+ short | recursive ) echo "Configuration of procenv 0.26:";;
esac
cat <<\_ACEOF
@@ -1441,7 +1441,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-procenv configure 0.24
+procenv configure 0.26
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1867,7 +1867,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by procenv $as_me 0.24, which was
+It was created by procenv $as_me 0.26, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -5302,7 +5302,7 @@ fi
# Define the identity of the package.
PACKAGE='procenv'
- VERSION='0.24'
+ VERSION='0.26'
cat >>confdefs.h <<_ACEOF
@@ -6022,7 +6022,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by procenv $as_me 0.24, which was
+This file was extended by procenv $as_me 0.26, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -6088,7 +6088,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-procenv config.status 0.24
+procenv config.status 0.26
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index d1ac19b..1ef3c56 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.68])
-AC_INIT(procenv, 0.24, [james.hunt@ubuntu.com])
+AC_INIT(procenv, 0.26, [james.hunt@ubuntu.com])
AC_COPYRIGHT([Copyright (C) 2012-2013 James Hunt <james.hunt@ubuntu.com>
and Kees Cook <kees@ubuntu.com>])
AC_CONFIG_SRCDIR([src/procenv.c])
diff --git a/debian/changelog b/debian/changelog
index bc10bf4..4273dfb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,17 @@
+procenv (0.26-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- James Hunt <james.hunt@ubuntu.com> Tue, 27 Aug 2013 23:09:03 +0100
+
+procenv (0.25-1) unstable; urgency=low
+
+ * debian/control: Add build-depends on automake >= 1.12 for
+ 'serial-tests' used in configure.ac
+ * New upstream release.
+
+ -- James Hunt <james.hunt@ubuntu.com> Fri, 19 Jul 2013 21:40:43 +0100
+
procenv (0.24-1) unstable; urgency=low
* New upstream release.
diff --git a/debian/control b/debian/control
index 280dd1c..5ff2264 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: procenv
Section: utils
Priority: optional
Maintainer: James Hunt <james.hunt@ubuntu.com>
-Build-Depends: debhelper (>= 9.0.0), dh-autoreconf, libkvm-dev [kfreebsd-any], pkg-config
+Build-Depends: debhelper (>= 9.0.0), dh-autoreconf, libkvm-dev [kfreebsd-any], pkg-config, automake (>= 1.12)
Standards-Version: 3.9.4
Homepage: https://code.launchpad.net/procenv
XS-Testsuite: autopkgtest
diff --git a/man/procenv.1 b/man/procenv.1
index 99441ea..1027d76 100644
--- a/man/procenv.1
+++ b/man/procenv.1
@@ -1,4 +1,4 @@
-.TH PROCENV "1" "2012-11-29" "User Commands"
+.TH PROCENV "1" "2013-07-16" "User Commands"
.\"
.SH NAME
procenv \- display process environment details
@@ -21,11 +21,16 @@ procenv \- display process environment details
Display details of the process environment in a parseable format.
.\"
.SH OPTIONS
+.\"
.TP
\fB\-a\fR, \fB\-\-meta\fR
Display meta details.
.\"
.TP
+\fB\-A\fR, \fB\-\-arguments\fR
+Display program arguments.
+.\"
+.TP
\fB\-b\fR, \fB\-\-libs\fR
Display library details.
See
@@ -118,7 +123,7 @@ See
\fB\-m\fR, \fB\-\-mount[s]\fR
Display mount details.
See
-.BR getmntent (3) "" " (Linux) and " getmntinfo (3) "" " (BSD)."
+.BR getmntent (3) "" " and " statfs (2) "" " (Linux), and " getmntinfo (3) "" " (BSD)."
.PP
.\"
.TP
@@ -129,6 +134,13 @@ See
.PP
.\"
.TP
+\fB\-N\fR, \fB\-\-network\fR
+Display network details.
+See
+.BR getifaddrs (3) "" ", " getnameinfo (3) "" ", and " ioctl (2) " (Linux)" .
+.PP
+.\"
+.TP
\fB\-o\fR, \fB\-\-oom\fR
Display out-of-memory manager details (Linux only).
See
@@ -308,9 +320,14 @@ specified.
\& # Show limits
\& procenv \-l
\&
-\& # Send compiler information to syslog (note the order of the options)
+\& # Send compiler information to syslog (note the order of the options).
\& procenv \-\-output=syslog \-\-compiler
\&
+\& # Run a command ('mycmd --arg1 --foo=bar') without creating a new
+\& # process, but have procenv run first and log its output to a
+\& # regular file.
+\& exec procenv \-\-file=/tmp/procenv.log --exec -- mycmd --arg1 --foo=bar
+\&
\& # The following kernel command-line snippet will cause procenv to
\& # write output to first serial tty device and then execute init(8)
\& # in debug mode to allow early boot environment to be examined.
@@ -332,7 +349,7 @@ Kees Cook
.RB < kees@ubuntu.com > "" "."
.\"
.SH COPYRIGHT
-Copyright \(co 2012 James Hunt
+Copyright \(co 2012-2013 James Hunt
.RB < james.hunt@ubuntu.com >
and
Kees Cook
@@ -358,6 +375,8 @@ There is NO WARRANTY, to the extent permitted by law.
.BR exec (P) "" ,
.BR getconf (1) "" ,
.BR groups (1) "" ,
+.BR ifconfig (8) "" ,
+.BR ip (9) "" ,
.BR kill (1) "" ,
.BR ldd (1) "" ,
.BR locale (1) "" ,
diff --git a/src/Makefile.am b/src/Makefile.am
index ee388b0..c63a9ae 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,3 +1,10 @@
+AM_CFLAGS = \
+ -pedantic \
+ -std=gnu99
+ -Wall -O2 \
+ -fstack-protector \
+ -Wformat -Werror=format-security
+
bin_PROGRAMS = procenv
procenv_SOURCES = procenv.c procenv.h
procenv_LDADD = -lrt
diff --git a/src/Makefile.in b/src/Makefile.in
index 2fa86a1..8a87c00 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.2 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,10 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+AM_CFLAGS = \
+ -pedantic \
+ -std=gnu99
+
procenv_SOURCES = procenv.c procenv.h
procenv_LDADD = -lrt
procenv_CPPFLAGS = $(am__append_1) $(am__append_2)
@@ -686,6 +690,9 @@ uninstall-am: uninstall-binPROGRAMS
ps ps-am tags tags-am uninstall uninstall-am \
uninstall-binPROGRAMS
+ -Wall -O2 \
+ -fstack-protector \
+ -Wformat -Werror=format-security
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/procenv.c b/src/procenv.c
index 325c38d..a1c17cc 100644
--- a/src/procenv.c
+++ b/src/procenv.c
@@ -9,7 +9,7 @@
* Licence: GPLv3. See below...
*--------------------------------------------------------------------
*
- * Copyright © 2012 James Hunt.
+ * Copyright 2012-2013 James Hunt.
*
* 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
@@ -70,7 +70,7 @@ int selected_option = 0;
/**
* indent:
*
- * Number of spaces to indent output
+ * Number of spaces to indent output.
**/
int indent = 0;
@@ -88,6 +88,12 @@ const char *program_name;
**/
char **exec_args = NULL;
+/**
+ * Copy of argv and argc used by show_arguments().
+ **/
+char **argvp = NULL;
+int argvc = 0;
+
struct procenv_user user;
struct procenv_misc misc;
struct procenv_priority priority;
@@ -125,7 +131,7 @@ struct mntopt_map {
{ MNT_SYNCHRONOUS , "synchronous" },
{ MNT_UNION , "union" },
- { 0, NULL },
+ { 0, NULL }
};
#endif
@@ -134,7 +140,9 @@ struct procenv_map output_map[] = {
{ OUTPUT_STDERR , "stderr" },
{ OUTPUT_STDOUT , "stdout" },
{ OUTPUT_SYSLOG , "syslog" },
- { OUTPUT_TERM , "terminal" }
+ { OUTPUT_TERM , "terminal" },
+
+ { 0, NULL }
};
struct baud_speed baud_speeds[] = {
@@ -162,6 +170,67 @@ struct baud_speed baud_speeds[] = {
{ 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 (__FreeBSD_kernel__)
+ 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),
+ mk_map_entry (IFF_ECHO),
+#endif
+
+ { 0, NULL }
+};
+
+#if defined (PROCENV_LINUX)
+struct if_extended_flag_map {
+ unsigned int flag;
+ char *name;
+} if_extended_flag_map[] = {
+ mk_map_entry (IFF_802_1Q_VLAN),
+ mk_map_entry (IFF_EBRIDGE),
+ mk_map_entry (IFF_SLAVE_INACTIVE),
+ mk_map_entry (IFF_MASTER_8023AD),
+ mk_map_entry (IFF_MASTER_ALB),
+ mk_map_entry (IFF_BONDING),
+ mk_map_entry (IFF_SLAVE_NEEDARP),
+ mk_map_entry (IFF_ISATAP),
+
+ { 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.
@@ -180,18 +249,22 @@ struct procenv_map sysconf_map[] = {
mk_sysconf_map_entry (_SC_CLK_TCK),
mk_posix_sysconf_map_entry (COLL_WEIGHTS_MAX),
mk_posix_sysconf_map_entry (EXPR_NEST_MAX),
+#if defined (_SC_HOST_NAME_MAX)
mk_posix_sysconf_map_entry (HOST_NAME_MAX),
+#endif
mk_posix_sysconf_map_entry (LINE_MAX),
mk_posix_sysconf_map_entry (LOGIN_NAME_MAX),
mk_posix_sysconf_map_entry (OPEN_MAX),
mk_posix_sysconf_map_entry (PAGESIZE),
mk_posix_sysconf_map_entry (RE_DUP_MAX),
mk_posix_sysconf_map_entry (STREAM_MAX),
+#if defined (_SC_SYMLOOP_MAX)
mk_posix_sysconf_map_entry (SYMLOOP_MAX),
+#endif
mk_posix_sysconf_map_entry (TTY_NAME_MAX),
mk_posix_sysconf_map_entry (TZNAME_MAX),
{ _SC_VERSION, "_POSIX_VERSION(_SC_VERSION)" },
-#ifdef _SC_POSIX2_C_DEV
+#if defined (_SC_POSIX2_C_DEV)
mk_posix_sysconf_map_entry (POSIX2_C_DEV),
#endif
mk_posix_sysconf_map_entry (BC_BASE_MAX),
@@ -215,15 +288,25 @@ struct procenv_map sysconf_map[] = {
mk_sysconf_map_entry (_SC_NPROCESSORS_CONF),
mk_sysconf_map_entry (_SC_NPROCESSORS_ONLN),
+#if defined (_SC_ADVISORY_INFO)
mk_posixopt_sysconf_map_entry (ADVISORY_INFO),
+#endif
mk_posixopt_sysconf_map_entry (ASYNCHRONOUS_IO),
+#if defined (_SC_BARRIERS)
mk_posixopt_sysconf_map_entry (BARRIERS),
+#endif
#if defined (_POSIX_CHOWN_RESTRICTED)
mk_sysconf_map_entry (_POSIX_CHOWN_RESTRICTED),
#endif
+#if defined (_SC_CLOCK_SELECTION)
mk_posixopt_sysconf_map_entry (CLOCK_SELECTION),
+#endif
+#if defined (_SC_CPUTIME)
mk_posixopt_sysconf_map_entry (CPUTIME),
+#endif
+#if defined (_SC_FILE_LOCKING)
mk_posixopt_sysconf_map_entry (FILE_LOCKING),
+#endif
mk_posixopt_sysconf_map_entry (FSYNC),
mk_posixopt_sysconf_map_entry (JOB_CONTROL),
mk_posixopt_sysconf_map_entry (MAPPED_FILES),
@@ -231,43 +314,77 @@ struct procenv_map sysconf_map[] = {
mk_posixopt_sysconf_map_entry (MEMLOCK_RANGE),
mk_posixopt_sysconf_map_entry (MEMORY_PROTECTION),
mk_posixopt_sysconf_map_entry (MESSAGE_PASSING),
+#if defined (_SC_MONOTONIC_CLOCK)
mk_posixopt_sysconf_map_entry (MONOTONIC_CLOCK),
+#endif
#ifdef _SC_MULTI_PROCESS
mk_posixopt_sysconf_map_entry (MULTI_PROCESS),
#endif
mk_posixopt_sysconf_map_entry (PRIORITIZED_IO),
mk_posixopt_sysconf_map_entry (PRIORITY_SCHEDULING),
+#if defined (_POSIX_RAW_SOCKETS)
mk_sysconf_map_entry (_POSIX_RAW_SOCKETS),
+#endif
+#if defined (_SC_READER_WRITER_LOCKS)
mk_posixopt_sysconf_map_entry (READER_WRITER_LOCKS),
+#endif
mk_posixopt_sysconf_map_entry (REALTIME_SIGNALS),
+#if defined (_SC_REGEXP)
mk_posixopt_sysconf_map_entry (REGEXP),
+#endif
mk_posixopt_sysconf_map_entry (SAVED_IDS),
mk_posixopt_sysconf_map_entry (SEMAPHORES),
mk_posixopt_sysconf_map_entry (SHARED_MEMORY_OBJECTS),
+#if defined (_SC_SHELL)
mk_posixopt_sysconf_map_entry (SHELL),
+#endif
+#if defined (_SC_SPAWN)
mk_posixopt_sysconf_map_entry (SPAWN),
+#endif
+#if defined (_SC_SPIN_LOCKS)
mk_posixopt_sysconf_map_entry (SPIN_LOCKS),
+#endif
+#if defined (_SC_SPORADIC_SERVER)
mk_posixopt_sysconf_map_entry (SPORADIC_SERVER),
+#endif
mk_posixopt_sysconf_map_entry (SYNCHRONIZED_IO),
mk_posixopt_sysconf_map_entry (THREAD_ATTR_STACKSIZE),
+#if defined (_SC_THREAD_CPUTIME)
mk_posixopt_sysconf_map_entry (THREAD_CPUTIME),
+#endif
mk_posixopt_sysconf_map_entry (THREAD_PRIO_INHERIT),
mk_posixopt_sysconf_map_entry (THREAD_PRIO_PROTECT),
mk_posixopt_sysconf_map_entry (THREAD_PRIORITY_SCHEDULING),
+#if defined (_SC_THREAD_PROCESS_SHARED)
mk_posixopt_sysconf_map_entry (THREAD_PROCESS_SHARED),
+#endif
mk_posixopt_sysconf_map_entry (THREAD_SAFE_FUNCTIONS),
+#if defined (_SC_THREAD_SPORADIC_SERVER)
mk_posixopt_sysconf_map_entry (THREAD_SPORADIC_SERVER),
+#endif
mk_posixopt_sysconf_map_entry (THREADS),
+#if defined (_SC_TIMEOUTS)
mk_posixopt_sysconf_map_entry (TIMEOUTS),
+#endif
mk_posixopt_sysconf_map_entry (TIMERS),
+#if defined (_SC_TRACE)
mk_posixopt_sysconf_map_entry (TRACE),
+#endif
+#if defined (_SC_TRACE_EVENT_FILTER)
mk_posixopt_sysconf_map_entry (TRACE_EVENT_FILTER),
+#endif
+#if defined (_SC_TRACE_INHERIT)
mk_posixopt_sysconf_map_entry (TRACE_INHERIT),
+#endif
+#if defined (_SC_TRACE_LOG)
mk_posixopt_sysconf_map_entry (TRACE_LOG),
+#endif
#ifdef _SC_TYPED_MEMORY_OBJECT
mk_posixopt_sysconf_map_entry (TYPED_MEMORY_OBJECT),
#endif
+#if defined (_POSIX_VDISABLE)
mk_sysconf_map_entry (_POSIX_VDISABLE),
+#endif
mk_sysconf_map_entry (_XOPEN_CRYPT),
mk_sysconf_map_entry (_XOPEN_LEGACY),
#if defined (_XOPEN_REALTIME)
@@ -343,6 +460,15 @@ struct procenv_map signal_map[] = {
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 },
};
@@ -382,7 +508,7 @@ struct procenv_map scheduler_map[] = {
mk_map_entry (SCHED_OTHER),
mk_map_entry (SCHED_FIFO),
mk_map_entry (SCHED_RR),
-#if defined (PROCENV_LINUX)
+#if defined (PROCENV_LINUX) && ! defined (PROCENV_ANDROID)
mk_map_entry (SCHED_BATCH),
#ifdef SCHED_IDLE
mk_map_entry (SCHED_IDLE),
@@ -408,6 +534,7 @@ usage (void)
show ("Options:");
show ("");
show (" -a, --meta : Display meta details.");
+ show (" -A, --arguments : Display program arguments.");
show (" -b, --libs : Display library details.");
show (" -c, --cgroup[s] : Display cgroup details (Linux only).");
show (" -d, --compiler : Display compiler details.");
@@ -424,14 +551,15 @@ usage (void)
show (" -L, --locale : Display locale details.");
show (" -m, --mount[s] : Display mount details.");
show (" -n, --confstr : Display confstr details.");
+ show (" -N, --network : Display network details.");
show (" -o, --oom : Display out-of-memory manager details (Linux only)");
- show (" --output=<type> : Send output to alternative location. Type can be one of:");
+ show (" --output=<type> : Send output to alternative location. <type> can be one of:");
show ("");
- show (" file # send output to a file.");
- show (" stderr # write to standard error.");
- show (" stdout # write to standard output (default).");
- show (" syslog # write to the system log file.");
- show (" terminal # write to terminal.");
+ show (" file : Send output to a file.");
+ show (" stderr : Write to standard error.");
+ show (" stdout : Write to standard output (default).");
+ show (" syslog : Write to the system log file.");
+ show (" terminal : Write to terminal.");
show ("");
show (" -p, --proc[ess] : Display process details.");
show (" -P, --platform : Display platform details.");
@@ -510,9 +638,6 @@ _show (const char *prefix, int indent, const char *fmt, ...)
assert (fmt);
- buffer = strdup ("");
- assert (buffer);
-
if (indent)
appendf (&buffer, "%*s", indent, " ");
@@ -544,7 +669,7 @@ _show (const char *prefix, int indent, const char *fmt, ...)
ret = write (user.tty_fd, buffer, strlen (buffer));
if (ret < 0) {
fprintf (stderr, "ERROR: failed to write to terminal\n");
- exit (EXIT_FAILURE);
+ goto error;
}
break;
@@ -557,14 +682,14 @@ _show (const char *prefix, int indent, const char *fmt, ...)
if (output_fd < 0) {
fprintf (stderr, "ERROR: failed to open file '%s'\n",
output_file);
- exit (EXIT_FAILURE);
+ goto error;
}
}
ret = write (output_fd, buffer, strlen (buffer));
if (ret < 0) {
fprintf (stderr, "ERROR: failed to write to file '%s'\n",
output_file);
- exit (EXIT_FAILURE);
+ goto error;
}
break;
@@ -703,6 +828,8 @@ show_signals (void)
die ("failed to query signal mask");
for (i = 1; i <= NUM_SIGNALS; i++) {
+ const char *signal_name;
+ const char *signal_desc;
blocked = 0;
ignored = 0;
@@ -723,9 +850,12 @@ show_signals (void)
else if (rc)
blocked = 1;
+ signal_name = get_signal_name (i);
+ signal_desc = strsignal (i);
+
show ("%s ('%s', %d): blocked=%s, ignored=%s",
- get_signal_name (i),
- strsignal (i),
+ signal_name ? signal_name : UNKNOWN_STR,
+ signal_desc ? signal_desc : UNKNOWN_STR,
i,
blocked ? YES_STR : NO_STR,
ignored ? YES_STR : NO_STR);
@@ -819,6 +949,7 @@ dump_sysconf (void)
}
}
+#ifndef PROCENV_ANDROID
void
show_confstrs (void)
{
@@ -832,6 +963,7 @@ show_confstrs (void)
#endif
show_confstr (_CS_PATH);
}
+#endif
void
get_misc (void)
@@ -848,6 +980,7 @@ get_misc (void)
#endif
}
+#if !defined (PROCENV_HURD)
/**
* is_console:
* @fd: open file descriptor.
@@ -855,31 +988,27 @@ get_misc (void)
* Check if specified file descriptor is attached to a _console_
* device (physical or virtual).
*
- * Note that ptys are NOT consoles :)
+ * 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.
- *
- * FIXME: how can this be determined for BSD?
**/
int
is_console (int fd)
{
-#if defined (PROCENV_LINUX)
- struct vt_mode vt;
- int ret;
+ struct vt_mode vt;
+ int ret;
- ret = ioctl (0, VT_GETMODE, &vt);
+ ret = ioctl (fd, VT_GETMODE, &vt);
return !ret;
-#else
- return FALSE;
-#endif
}
+#endif
void
dump_user (void)
{
-
header ("process");
show ("process id (pid): %d", user.pid);
@@ -904,11 +1033,11 @@ dump_user (void)
show ("has controlling terminal: %s",
has_ctty () ? YES_STR : NO_STR);
-#if defined (PROCENV_LINUX)
+#if defined (PROCENV_HURD)
+ show ("on console: %s", UNKNOWN_STR);
+#else
show ("on console: %s",
is_console (user.tty_fd) ? YES_STR : NO_STR);
-#else
- show ("on console: %s", UNKNOWN_STR);
#endif
show ("real user id (uid): %d ('%s')",
@@ -937,11 +1066,21 @@ dump_user (void)
show ("login name: '%s'", user.login ? user.login : "");
+#if defined (PROCENV_ANDROID)
+ /* No gecos on Android. In fact it doesn't actually use the
+ * passwd database, but meh.
+ */
+ show ("passwd: name='%s', dir='%s', shell='%s'",
+ user.passwd.pw_name,
+ user.passwd.pw_dir,
+ user.passwd.pw_shell);
+#else
show ("passwd: name='%s', gecos='%s', dir='%s', shell='%s'",
user.passwd.pw_name,
user.passwd.pw_gecos,
user.passwd.pw_dir,
user.passwd.pw_shell);
+#endif
show_all_groups ();
}
@@ -979,8 +1118,6 @@ dump_misc (void)
dump_priorities ();
show ("memory page size: %d bytes", getpagesize ());
-
-
#if defined (PROCENV_LINUX)
#ifdef LINUX_VERSION_CODE
show ("kernel headers version: %u.%u.%u",
@@ -1042,11 +1179,13 @@ dump_fds (void)
for (fd = 0; fd < max; fd++) {
if (fd_valid (fd)) {
- int is_tty = isatty (fd);
- char *name = NULL;
+ int is_tty = isatty (fd);
+ char *name = NULL;
if (is_tty) {
+#if ! defined (PROCENV_ANDROID)
name = ttyname (fd);
+#endif
show ("fd %d: terminal=%s ('%s')", fd,
is_tty ? YES_STR : NO_STR,
name ? name : NA_STR);
@@ -1055,6 +1194,7 @@ dump_fds (void)
}
}
}
+
#if defined (PROCENV_LINUX)
dump_linux_proc_fds ();
#endif
@@ -1135,7 +1275,11 @@ get_user_info (void)
user.login = getlogin ();
user.pgroup = getpgrp ();
+#if defined (PROCENV_ANDROID)
+ sprintf (user.ctrl_terminal, "/dev/tty");
+#else
ctermid (user.ctrl_terminal);
+#endif
/* Get a reference to the controlling terminal
* in case all standard fds are redirected.
@@ -1174,6 +1318,11 @@ append (char **str, const char *new)
assert (str);
assert (new);
+ if (! *str)
+ *str = strdup ("");
+
+ assert (*str);
+
/* +1 for terminating nul */
total = strlen (*str) + 1;
@@ -1197,6 +1346,11 @@ appendf (char **str, const char *fmt, ...)
assert (str);
assert (fmt);
+ if (! *str)
+ *str = strdup ("");
+
+ assert (*str);
+
va_start (ap, fmt);
if (vasprintf (&new, fmt, ap) < 0) {
@@ -1218,6 +1372,11 @@ appendva (char **str, const char *fmt, va_list ap)
assert (str);
assert (fmt);
+ if (! *str)
+ *str = strdup ("");
+
+ assert (*str);
+
if (vasprintf (&new, fmt, ap) < 0) {
perror ("vasprintf");
exit (EXIT_FAILURE);
@@ -1380,6 +1539,19 @@ dump_meta (void)
}
void
+show_arguments (void)
+{
+ int i;
+
+ header ("arguments");
+
+ show ("count: %u", argvc);
+
+ for (i = 0; i < argvc; i++)
+ show ("argv[%d]='%s'", i, argvp[i]);
+}
+
+void
show_stat (void)
{
struct stat st;
@@ -1445,18 +1617,18 @@ show_stat (void)
show ("group id (gid): %d ('%s')", st.st_gid, get_group_name (st.st_uid));
show ("size: %lu bytes (%lu 512-byte blocks)", st.st_size, st.st_blocks);
- if (! ctime_r (&st.st_atime, formatted_time))
+ if (! ctime_r ((time_t *)&st.st_atime, formatted_time))
die ("failed to format atime");
formatted_time[ strlen (formatted_time)-1] = '\0';
show ("atime: %lu (%s)", st.st_atime, formatted_time);
- if (! ctime_r (&st.st_mtime, formatted_time))
+ if (! ctime_r ((time_t *)&st.st_mtime, formatted_time))
die ("failed to format mtime");
formatted_time[ strlen (formatted_time)-1] = '\0';
show ("mtime: %lu (%s)", st.st_mtime, formatted_time);
- if (! ctime_r (&st.st_ctime, formatted_time))
+ if (! ctime_r ((time_t *)&st.st_ctime, formatted_time))
die ("failed to format ctime");
formatted_time[ strlen (formatted_time)-1] = '\0';
show ("ctime: %lu (%s)", st.st_ctime, formatted_time);
@@ -1465,7 +1637,7 @@ show_stat (void)
long
get_kernel_bits (void)
{
-#if defined (PROCENV_LINUX)
+#if defined (PROCENV_LINUX) && ! defined (PROCENV_ANDROID)
long value;
errno = 0;
@@ -1482,6 +1654,7 @@ void
dump (void)
{
dump_meta ();
+ show_arguments ();
#if defined (PROCENV_LINUX)
show_capabilities ();
@@ -1489,14 +1662,19 @@ dump (void)
#endif
show_clocks ();
show_compiler ();
+#ifndef PROCENV_ANDROID
show_confstrs ();
+#endif
show_env ();
dump_fds ();
+#ifndef PROCENV_ANDROID
show_libs ();
- show_locale ();
+#endif
show_rlimits ();
+ show_locale ();
dump_misc ();
show_mounts (SHOW_ALL);
+ show_network ();
#if defined (PROCENV_LINUX)
show_oom ();
#endif
@@ -1519,14 +1697,223 @@ dump (void)
show_tty_attrs ();
dump_uname ();
}
+void
+get_network_address (const struct sockaddr *address, int family, char *name)
+{
+ int ret;
-#if defined (PROCENV_LINUX)
+ assert (address);
+ assert (name);
+
+ memset (name, '\0', NI_MAXHOST);
+
+ if (family == AF_INET || family == AF_INET6) {
+ ret = getnameinfo (address,
+ (family == AF_INET)
+ ? sizeof (struct sockaddr_in)
+ : sizeof (struct sockaddr_in6),
+ (char *)name, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+ if (ret) {
+ switch (ret) {
+ case EAI_NONAME:
+ case EAI_FAMILY:
+ sprintf ((char *)name, "%s", NA_STR);
+ break;
+ default:
+ sprintf ((char *)name, "%s", UNKNOWN_STR);
+ break;
+ }
+ }
+ } else {
+ sprintf ((char *)name, "%s", NA_STR);
+ }
+
+ assert (name[NI_MAXHOST-1] == '\0');
+}
+
+char *
+decode_if_flags (unsigned int flags)
+{
+ char *str = NULL;
+ struct if_flag_map *p;
+ int first = TRUE;
+
+ for (p = if_flag_map; p && p->name; p++) {
+ if (flags & p->flag) {
+ appendf (&str, "%s%s",
+ first ? "" : ",",
+ p->name);
+ first = FALSE;
+ }
+ }
+
+ return str;
+}
+
+const char *
+get_ipv6_scope_name (uint32_t scope)
+{
+ switch (scope) {
+ case 0x0:
+ case 0xf:
+ return "reserved";
+ break;
+
+ case 0x1:
+ return "interface-local";
+ break;
+
+ case 0x2:
+ return "link-local";
+ break;
+
+ case 0x4:
+ return "admin-local";
+ break;
+
+ case 0x5:
+ return "site-local";
+ break;
+
+ case 0x8:
+ return "organization-local";
+ break;
+
+ case 0xe:
+ return "global";
+ break;
+ }
+
+ return UNKNOWN_STR;
+}
+
+int
+get_mtu (const struct ifaddrs *ifaddr)
+{
+ int sock;
+ struct ifreq ifr;
+ int 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)
+ goto out;
+out:
+ close (sock);
+
+ return ifr.ifr_mtu;
+}
+
+/*
+ *
+ * Returns: IEEE-802 format MAC address, or NULL on error.
+ */
+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 (__FreeBSD_kernel__)
+ struct sockaddr_dl *link_layer;
+#else
+ struct ifreq ifr;
+ int sock = -1;
+#endif
+
+#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
+ int request = SIOCGIFHWADDR;
+#endif
+
+ assert (ifaddr);
+
+#if defined (PROCENV_BSD) || defined (__FreeBSD_kernel__)
+ 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...
+ */
+ sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
+
+ if (sock < 0)
+ return NULL;
+
+ memset (&ifr, 0, sizeof (struct ifreq));
+ strncpy (ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ-1);
+
+ if (ioctl (sock, request, &ifr) < 0)
+ goto out;
+#endif
+
+#if defined (PROCENV_BSD) || defined (__FreeBSD_kernel__)
+ data = LLADDR (link_layer);
+#else
+ data = (char *)ifr.ifr_hwaddr.sa_data;
+#endif
+
+ if (data) {
+ for (i = 0; i < 6; i++) {
+ if (data[i]) {
+ valid = TRUE;
+ break;
+ }
+ }
+ }
+
+ /* MAC comprised of all zeros cannot be valid */
+ if (! valid)
+ goto out;
+
+ /* An IEEE-802 formatted MAC address comprises 6x 2-byte groups,
+ * separated by 5 colons with an additional byte for the string
+ * terminator.
+ */
+ mac_address = calloc ((6*2) + 5 + 1, sizeof (char));
+ if (! mac_address)
+ goto out;
+
+ sprintf (mac_address, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ (unsigned char)data[0],
+ (unsigned char)data[1],
+ (unsigned char)data[2],
+ (unsigned char)data[3],
+ (unsigned char)data[4],
+ (unsigned char)data[5]);
+
+out:
+
+#if defined (PROCENV_BSD) || defined (__FreeBSD_kernel__)
+ /* NOP */
+#else
+ close (sock);
+#endif
+ return mac_address;
+}
+
+
+#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
void
show_linux_mounts (ShowMountType what)
{
- FILE *mtab;
- struct mntent *mnt;
- int major, minor;
+ FILE *mtab;
+ struct mntent *mnt;
+ struct statvfs fs;
+ unsigned int major = 0;
+ unsigned int minor = 0;
+ int have_stats;
mtab = fopen (MOUNTS, "r");
@@ -1536,19 +1923,80 @@ show_linux_mounts (ShowMountType what)
}
while ((mnt = getmntent (mtab))) {
+ char *str = NULL;
+ have_stats = TRUE;
+
if (what == SHOW_ALL || what == SHOW_MOUNTS) {
+ unsigned multiplier = 0;
+ fsblkcnt_t blocks;
+ fsblkcnt_t bfree;
+ fsblkcnt_t bavail;
+ fsblkcnt_t used_blocks;
+ fsblkcnt_t used_files;
+
+ 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;
+ }
+
get_major_minor (mnt->mnt_dir,
&major,
&minor);
- show ("fsname='%s', dir='%s', type='%s', "
- "opts='%s', "
- "dev=(major:%d, minor:%d)",
- mnt->mnt_fsname,
- mnt->mnt_dir,
- mnt->mnt_type,
- mnt->mnt_opts,
- major,
- minor);
+ appendf (&str,
+ "fsname='%s', dir='%s', type='%s', "
+ "opts='%s', "
+ "dev=(major:%u, minor:%u), "
+ "dump_freq=%d, fsck_passno=%d, ",
+ mnt->mnt_fsname,
+ mnt->mnt_dir,
+ mnt->mnt_type,
+ mnt->mnt_opts,
+ major, minor,
+ mnt->mnt_freq, mnt->mnt_passno);
+
+ if (have_stats) {
+ appendf (&str,
+ "fsid=%.*x, "
+ "optimal_block_size=%lu, "
+ "%d-byte blocks (total=%lu, used=%lu, free=%lu, available=%lu), "
+ "files/inodes (total=%lu, used=%lu, free=%lu)",
+ sizeof (fs.f_fsid),
+ fs.f_fsid,
+ fs.f_bsize,
+ DF_BLOCK_SIZE,
+ blocks,
+ used_blocks,
+ bfree,
+ bavail,
+ fs.f_files,
+ used_files,
+ fs.f_ffree);
+ } else {
+ appendf (&str,
+ "fsid=%s, "
+ "optimal_block_size=%s, "
+ "%d-byte blocks (total=%s, used=%s, free=%s, available=%s), "
+ "files/inodes (total=%s, free=%s)",
+ UNKNOWN_STR,
+ UNKNOWN_STR,
+ UNKNOWN_STR,
+ UNKNOWN_STR,
+ UNKNOWN_STR,
+ UNKNOWN_STR,
+ UNKNOWN_STR,
+ UNKNOWN_STR,
+ UNKNOWN_STR);
+ }
+
+ show (str);
+ free (str);
}
if (what == SHOW_ALL || what == SHOW_PATHCONF)
@@ -1557,6 +2005,50 @@ show_linux_mounts (ShowMountType what)
fclose (mtab);
}
+#endif
+
+#if defined (PROCENV_LINUX)
+char *
+decode_extended_if_flags (const char *interface, unsigned short *flags)
+{
+ int sock;
+ struct ifreq ifr;
+ int first = TRUE;
+ char *str = NULL;
+ 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 NULL;
+
+ 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) {
+ appendf (&str, "%s%s",
+ first ? "" : ",",
+ p->name);
+ first = FALSE;
+ }
+ }
+out:
+ close (sock);
+ return str;
+}
+
/**
* linux_kernel_version:
@@ -1629,7 +2121,7 @@ show_mounts (ShowMountType what)
{
header ("mounts");
-#if defined (PROCENV_LINUX)
+#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
show_linux_mounts (what);
#endif
@@ -1638,6 +2130,275 @@ show_mounts (ShowMountType what)
#endif
}
+const char *
+get_net_family_name (sa_family_t family)
+{
+ switch (family) {
+#if defined (PROCENV_LINUX)
+ case AF_PACKET:
+ return "AF_PACKET";
+ break;
+#endif
+
+#if defined (PROCENV_BSD) || defined (__FreeBSD_kernel__)
+ case AF_LINK:
+ return "AF_LINK";
+ break;
+#endif
+
+ case AF_INET:
+ return "AF_INET";
+ break;
+
+ case AF_INET6:
+ return "AF_INET6";
+ break;
+ }
+
+ return UNKNOWN_STR;
+}
+
+void
+show_network_if (const struct ifaddrs *ifa, const char *mac_address)
+{
+ char *str = NULL;
+ char *flags = NULL;
+ char *extended_flags = NULL;
+ unsigned short ext_flags = 0;
+ sa_family_t family;
+ char address[NI_MAXHOST];
+ int mtu = 0;
+
+ assert (ifa);
+
+ family = ifa->ifa_addr->sa_family;
+
+ flags = decode_if_flags (ifa->ifa_flags);
+
+#if defined (PROCENV_LINUX)
+ extended_flags = decode_extended_if_flags (ifa->ifa_name, &ext_flags);
+#endif
+ appendf (&str, "interface %s: family=%s (0x%x), "
+ "flags=0x%x (%s), extended_flags=0x%x (%s)",
+ ifa->ifa_name,
+ get_net_family_name (family),
+ family,
+ ifa->ifa_flags,
+ flags ? flags : UNKNOWN_STR,
+ ext_flags,
+ extended_flags ? extended_flags : NA_STR);
+ if (flags)
+ free (flags);
+
+ if (extended_flags)
+ free (extended_flags);
+
+ mtu = get_mtu (ifa);
+
+#if defined (PROCENV_HURD)
+ /* No AF_LINK/AF_PACKET on Hurd atm */
+ appendf (&str, ", mac=%s", UNKNOWN_STR);
+#else
+ appendf (&str, ", mac=%s", mac_address ? mac_address : NA_STR);
+#endif
+
+ if (mtu > 0) {
+ appendf (&str, ", mtu=%d", mtu);
+ } else {
+ appendf (&str, ", mtu=%s", UNKNOWN_STR);
+ }
+
+ get_network_address (ifa->ifa_addr, family, address);
+ appendf (&str, ", address=%s", address);
+
+ if (ifa->ifa_netmask)
+ get_network_address (ifa->ifa_netmask, family, address);
+ appendf (&str, ", netmask=%s", ifa->ifa_netmask ? address : NA_STR);
+
+#if !defined (PROCENV_HURD)
+ if (family != PROCENV_LINK_LEVEL_FAMILY) {
+ if ((ifa->ifa_flags & IFF_BROADCAST) && ifa->ifa_broadaddr) {
+ get_network_address (ifa->ifa_broadaddr, family, address);
+
+ appendf (&str, ", broadcast=%s", ifa->ifa_broadaddr ? address : NA_STR);
+ }
+ } else {
+#endif
+ appendf (&str, ", broadcast=%s", NA_STR);
+#if !defined (PROCENV_HURD)
+ }
+#endif
+
+ if (ifa->ifa_flags & IFF_POINTOPOINT && ifa->ifa_dstaddr) {
+
+ get_network_address (ifa->ifa_dstaddr, family, address);
+
+ appendf (&str, ", point-to-point=%s", address);
+ }
+
+ show (str);
+ free (str);
+}
+
+/*
+ * 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.
+ */
+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;
+
+ header ("network");
+
+ /* Query all network interfaces */
+ if (getifaddrs (&if_addrs) < 0) {
+ show ("%s", UNKNOWN_STR);
+ 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);
+}
+
#if defined (PROCENV_BSD) || defined (__FreeBSD_kernel__)
char *
@@ -1645,7 +2406,6 @@ get_bsd_mount_opts (uint64_t flags)
{
struct mntopt_map *opt;
char *str = NULL;
- int first = TRUE;
size_t len = 0;
size_t total = 0;
int count = 0;
@@ -1694,10 +2454,17 @@ get_bsd_mount_opts (uint64_t flags)
void
show_bsd_mounts (ShowMountType what)
{
- int count;
- struct statfs *mounts;
- struct statfs *mnt;
- int i;
+ 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;
/* Note that returned memory cannot be freed (by us) */
count = getmntinfo (&mounts, MNT_WAIT);
@@ -1716,12 +2483,47 @@ show_bsd_mounts (ShowMountType what)
mnt->f_mntonname);
if (what == SHOW_ALL || what == SHOW_MOUNTS) {
- show ("fsname='%s', dir='%s', type='%s', opts='%s'",
+
+ 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;
+
+ show ("fsname='%s', dir='%s', type='%s', "
+ "opts='%s', "
+ "dev=(major:%u, minor:%u), "
+ "fsid=%.*x%.*x, "
+ "optimal_block_size=%" statfs_int_fmt ", "
+ "%d-byte blocks (total=%" statfs_int_fmt ", "
+ "used=%" statfs_int_fmt ", free=%" statfs_int_fmt ", available=%" statfs_int_fmt "), "
+ "files/inodes (total=%" statfs_int_fmt ", free=%" statfs_int_fmt ")",
mnt->f_mntfromname,
mnt->f_mntonname,
mnt->f_fstypename,
- opts);
+ opts,
+ major, minor,
+
+ /* Always zero on BSD? */
+ sizeof (mnt->f_fsid.val[0]),
+ mnt->f_fsid.val[0],
+ sizeof (mnt->f_fsid.val[1]),
+ mnt->f_fsid.val[1],
+
+ mnt->f_bsize,
+ DF_BLOCK_SIZE,
+ blocks,
+ used,
+ bfree,
+ bavail,
+ mnt->f_files,
+ mnt->f_ffree);
}
+
if (what == SHOW_ALL || what == SHOW_PATHCONF)
show_pathconfs (what, mnt->f_mntonname);
mnt++;
@@ -1729,6 +2531,7 @@ show_bsd_mounts (ShowMountType what)
free (opts);
}
}
+
#endif
void
@@ -1757,11 +2560,13 @@ const char *
container_type (void)
{
struct stat statbuf;
- dev_t expected;
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;
@@ -1883,6 +2688,7 @@ show_proc_branch (void)
}
#if defined (PROCENV_BSD)
+/* Who would have thought handling PIDs was so tricky? */
void
show_bsd_proc_branch (void)
{
@@ -1895,6 +2701,7 @@ show_bsd_proc_branch (void)
pid_t self, current;
int done = FALSE;
char *str;
+ pid_t ultimate_parent = 0;
str = strdup ("ancestry: ");
assert (str);
@@ -1909,21 +2716,89 @@ show_bsd_proc_branch (void)
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; i++) {
+ for (i = 0; i < count && !done; i++) {
p = &procs[i];
if (p->ki_pid == current) {
- if (current == 0) {
- /* ultimate parent == PID 0 == '[kernel]' */
+ 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;
}
}
@@ -2344,7 +3219,7 @@ show_tty_attrs (void)
struct winsize size;
int ret;
int fds[4] = { -1, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO };
- int i;
+ size_t i;
fds[0] = user.tty_fd;
@@ -2365,7 +3240,6 @@ show_tty_attrs (void)
}
}
-out_of_ideas:
show ("%s", NA_STR);
return;
@@ -2710,6 +3584,7 @@ get_arch (void)
return UNKNOWN_STR;
}
+#ifndef PROCENV_ANDROID
int
libs_callback (struct dl_phdr_info *info, size_t size, void *data)
{
@@ -2726,6 +3601,7 @@ show_libs (void)
dl_iterate_phdr (libs_callback, NULL);
}
+#endif
void
show_clocks (void)
@@ -2917,25 +3793,28 @@ show_ranges (void)
void
show_compiler (void)
{
- char *name;
- char *version;
+ char *name = NULL;
+ char *version = NULL;
-#if defined (__GNUC__)
- name = "GCC";
- version = __VERSION__;
-#elif defined (__clang__)
- name = "LLVM";
- version = __clang_version__;
-#elif defined (__INTEL_COMPILER)
+#if defined (__INTEL_COMPILER)
name = "Intel";
version = __ICC;
+#elif defined (__clang__)
+ name = "Clang/LLVM";
+ version = __clang_version__;
+#elif defined (__GNUC__)
+ name = "GCC";
+ version = __VERSION__;
#endif
header ("compiler");
- show ("name: %s", name);
- show ("version: %s", version);
- show ("compile date: %s", __DATE__);
- show ("compile time: %s", __TIME__);
+ show ("name: %s", name ? name : UNKNOWN_STR);
+ show ("version: %s", version ? version : UNKNOWN_STR);
+ show ("compile date (__DATE__): %s", __DATE__);
+ show ("compile time (__TIME__): %s", __TIME__);
+ show ("translation unit (__FILE__): %s", __FILE__);
+ show ("base file (__BASE_FILE__): %s", __BASE_FILE__);
+ show ("timestamp (__TIMESTAMP__): %s", __TIMESTAMP__);
#ifdef __STRICT_ANSI__
show ("__STRICT_ANSI__: %s", DEFINED_STR);
@@ -3269,7 +4148,6 @@ dump_linux_proc_fds (void)
char *prefix_path = "/proc/self/fd";
char path[MAXPATHLEN];
char link[MAXPATHLEN];
- int saved_errno;
ssize_t len;
header ("fds (linux/proc)");
@@ -3584,25 +4462,25 @@ check_envvars (void)
}
void
-get_major_minor (const char *path, int *major, int *minor)
+get_major_minor (const char *path, unsigned int *_major, unsigned int *_minor)
{
struct stat st;
assert (path);
- assert (major);
- assert (minor);
+ assert (_major);
+ assert (_minor);
if (stat (path, &st) < 0) {
/* Don't fail as this query may be for a mount which the
* user does not have permission to check.
*/
warn ("unable to stat path '%s'", path);
- *major = *minor = -1;
+ *_major = *_minor = 0;
return;
}
- *major = major (st.st_dev);
- *minor = minor (st.st_dev);
+ *_major = major (st.st_dev);
+ *_minor = minor (st.st_dev);
}
/**
@@ -3635,7 +4513,6 @@ get_path (const char *argv0)
char cwd[PATH_MAX];
size_t bytes;
size_t len;
- int ret;
memset (cwd, '\0', sizeof (cwd));
@@ -3706,7 +4583,12 @@ show_threads (void)
show ("thread stack size: %lu bytes",
(unsigned long int)stack_size);
+#if defined (PROCENV_ANDROID)
+ ret = 0;
+ scope = pthread_attr_getscope (&attr);
+#else
ret = pthread_attr_getscope (&attr, &scope);
+#endif
show ("thread scope: %s",
ret != 0 ? UNKNOWN_STR :
scope == PTHREAD_SCOPE_SYSTEM ? "PTHREAD_SCOPE_SYSTEM"
@@ -3731,6 +4613,7 @@ show_threads (void)
else
show ("thread scheduler priority: %d", param.sched_priority);
+#ifndef PROCENV_ANDROID
ret = pthread_attr_getinheritsched (&attr, &inherit_sched);
show ("thread inherit scheduler: %s",
ret != 0 ? UNKNOWN_STR :
@@ -3739,6 +4622,7 @@ show_threads (void)
: "PTHREAD_EXPLICIT_SCHED");
show ("thread concurrency: %d", pthread_getconcurrency ());
+#endif
}
char *
@@ -3793,8 +4677,8 @@ show_data_model (void)
#undef DATA_MODEL
int
-main (int argc,
- char *argv[])
+main (int argc,
+ char *argv[])
{
int option;
int long_index;
@@ -3802,6 +4686,7 @@ main (int argc,
struct option long_options[] = {
{"meta" , no_argument, NULL, 'a'},
+ {"arguments" , no_argument, NULL, 'A'},
{"libs" , no_argument, NULL, 'b'},
{"cgroup" , no_argument, NULL, 'c'},
{"cgroups" , no_argument, NULL, 'c'},
@@ -3820,6 +4705,7 @@ main (int argc,
{"mount" , no_argument, NULL, 'm'},
{"mounts" , no_argument, NULL, 'm'},
{"confstr" , no_argument, NULL, 'n'},
+ {"network" , no_argument, NULL, 'N'},
{"oom" , no_argument, NULL, 'o'},
{"proc" , no_argument, NULL, 'p'},
{"process" , no_argument, NULL, 'p'},
@@ -3848,6 +4734,8 @@ main (int argc,
};
program_name = argv[0];
+ argvp = argv;
+ argvc = argc;
/* Check before command-line options, since the latter
* must take priority.
@@ -3858,7 +4746,7 @@ main (int argc,
while (TRUE) {
option = getopt_long (argc, argv,
- "abcdefghijklLmnopPqrstTuUvwxyz",
+ "aAbcdefghijklLmnNopPqrstTuUvwxyz",
long_options, &long_index);
if (option == -1)
break;
@@ -3893,8 +4781,14 @@ main (int argc,
dump_meta ();
break;
+ case 'A':
+ show_arguments ();
+ break;
+
case 'b':
+#ifndef PROCENV_ANDROID
show_libs ();
+#endif
break;
case 'c':
@@ -3951,7 +4845,13 @@ main (int argc,
break;
case 'n':
+#ifndef PROCENV_ANDROID
show_confstrs ();
+#endif
+ break;
+
+ case 'N':
+ show_network ();
break;
case 'o':
@@ -3961,6 +4861,7 @@ main (int argc,
break;
case 'p':
+ get_misc ();
dump_user ();
break;
@@ -4037,16 +4938,20 @@ main (int argc,
if (reexec && ! exec_args && optind >= argc)
die ("must specify atleast one argument with '--exec'");
- dump ();
-
- cleanup ();
-
+ /* Prepare for re-exec */
if (reexec) {
if (! exec_args) {
argv += optind;
exec_args = argv;
}
+ }
+ dump ();
+
+ cleanup ();
+
+ /* Perform re-exec */
+ if (reexec) {
execvp (exec_args[0], exec_args);
die ("failed to re-exec %s", exec_args[0]);
}
@@ -4054,3 +4959,23 @@ main (int argc,
exit (EXIT_SUCCESS);
}
+
+char *
+get_user_name (uid_t uid)
+{
+ struct passwd *p;
+
+ p = getpwuid (uid);
+
+ return p ? p->pw_name : NULL;
+}
+
+char *
+get_group_name (gid_t gid)
+{
+ struct group *g;
+
+ g = getgrgid (gid);
+
+ return g ? g->gr_name : NULL;
+}
diff --git a/src/procenv.h b/src/procenv.h
index c6d8c74..c531af0 100644
--- a/src/procenv.h
+++ b/src/procenv.h
@@ -42,6 +42,26 @@
#include <sys/utsname.h>
#include <locale.h>
#include <pthread.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
+#include <arpa/inet.h>
+
+/* FIXME: Android testing */
+#if 1
+#ifndef PACKAGE_NAME
+#define PACKAGE_NAME "procenv"
+#endif
+
+#ifndef PACKAGE_VERSION
+#define PACKAGE_VERSION "0.24"
+#endif
+
+#ifndef PACKAGE_STRING
+#define PACKAGE_STRING PACKAGE_NAME
+#endif
+
+#endif /* FIXME */
#if defined (__FreeBSD__) \
|| defined (__NetBSD__) \
@@ -53,6 +73,10 @@
#define PROCENV_LINUX
#endif
+#if defined (PROCENV_LINUX) && defined (__BIONIC__)
+#define PROCENV_ANDROID
+#endif
+
#ifdef __GNU__
#define PROCENV_HURD
#endif
@@ -61,9 +85,20 @@
#define PROCENV_ARCH_X86
#endif
-#if defined (PROCENV_LINUX)
+#if defined PROCENV_ANDROID
+/* major(3) / minor(3) */
+#include <sys/sysmacros.h>
+#endif
+
+#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
#include <mntent.h>
-#include <execinfo.h>
+#include <sys/vfs.h>
+#include <sys/statvfs.h>
+#endif
+
+#if defined (PROCENV_LINUX)
+#include <linux/if.h>
+
#include <sys/inotify.h>
#include <sys/prctl.h>
@@ -151,6 +186,14 @@
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/ucred.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <sys/consio.h>
+#endif
+
+#if defined (PROCENV_HURD)
+#include <net/if.h>
#endif
#if defined (PROCENV_BSD) || defined (__FreeBSD_kernel__)
@@ -177,6 +220,26 @@
#define FALSE (!TRUE)
#endif
+/* Network family for entries containing link-level interface
+ * details. These entries will be cached to allow MAC addresses
+ * to be extracted from them when displaying the corresponding
+ * higher-level network family entries for the interface in
+ * question.
+ */
+#if defined (PROCENV_BSD) || defined (__FreeBSD_kernel__)
+#define PROCENV_LINK_LEVEL_FAMILY AF_LINK
+#elif defined (PROCENV_LINUX)
+#define PROCENV_LINK_LEVEL_FAMILY AF_PACKET
+#endif
+
+#if defined (PROCENV_BSD)
+#define statfs_int_type uint64_t
+#define statfs_int_fmt PRIu64
+#elif defined (__FreeBSD_kernel__)
+#define statfs_int_type uint64_t
+#define statfs_int_fmt "lu"
+#endif
+
/* FIXME: gettext */
#define _(str) str
@@ -199,6 +262,9 @@
#define NUM_SIGNALS 32
#endif
+/* Size of blocks we will show the user (as df(1) does) */
+#define DF_BLOCK_SIZE 1024
+
/* If an indent is required, use this many spaces */
#define INDENT 2
@@ -221,14 +287,6 @@
#define type_hex_width(type) \
(sizeof (type) * 2)
-#define get_group_name(gid) \
-({struct group *g = getgrgid (gid); \
- g ? g->gr_name : NULL;})
-
-#define get_user_name(uid) \
-({struct passwd *p = getpwuid (uid); \
- p ? p->pw_name : NULL;})
-
#define show_clock_res(clock) \
{ \
struct timespec res; \
@@ -415,8 +473,17 @@ struct procenv_priority {
int user;
};
+struct network_map {
+ struct ifaddrs ifaddr;
+ char *mac_address;
+
+ struct network_map *next;
+ struct network_map *prev;
+};
+
void _show (const char *prefix, int indent, const char *fmt, ...);
+void header (const char *fmt, ...);
void init (void);
void cleanup (void);
bool in_chroot (void);
@@ -433,7 +500,13 @@ void show_env (void);
void show_rlimits (void);
void show_rusage (void);
void dump_sysconf (void);
+char *get_user_name (gid_t gid);
+char *get_group_name (gid_t gid);
+
+#ifndef PROCENV_ANDROID
void show_confstrs (void);
+#endif
+
void dump_priorities (void);
void show_mounts (ShowMountType what);
void get_user_info (void);
@@ -445,12 +518,17 @@ void show_proc_branch (void);
void show_tty_attrs (void);
const char * get_speed (speed_t speed);
const char * get_signal_name (int signum);
+void show_arguments (void);
void dump_meta (void);
char *get_os (void);
char *get_arch (void);
void dump_platform (void);
+
+#ifndef PROCENV_ANDROID
int libs_callback (struct dl_phdr_info *info, size_t size, void *data);
void show_libs (void);
+#endif
+
int get_indent (void);
void show_clocks (void);
void show_timezone (void);
@@ -463,7 +541,11 @@ void show_compiler (void);
void get_uname (void);
void dump_uname (void);
void show_all_groups (void);
+
+#if !defined (PROCENV_HURD)
int is_console (int fd);
+#endif
+
long get_kernel_bits (void);
bool has_ctty (void);
void show_cpu (void);
@@ -476,15 +558,25 @@ int get_output_value (const char *name);
void set_indent (void);
void show_stat (void);
void show_locale (void);
-void get_major_minor (const char *path, int *major, int *minor);
+void get_major_minor (const char *path,
+ unsigned int *_major,
+ unsigned int *_minor);
bool uid_match (uid_t uid);
char * get_path (const char *argv0);
bool is_big_endian (void);
char * get_thread_scheduler_name (int sched);
int qsort_compar (const void *a, const void *b);
void show_data_model (void);
-
+const char *get_net_family_name (sa_family_t family);
+void show_network (void);
+void show_network_if (const struct ifaddrs *ifa, const char *mac_address);
+void get_network_name (const struct sockaddr *address, int family, char *name);
+const char *get_ipv6_scope_name (uint32_t scope);
+char *get_mac_address (const struct ifaddrs *ifaddr);
+int get_mtu (const struct ifaddrs *ifaddr);
+char *decode_if_flags (unsigned int flags);
#if defined (PROCENV_LINUX)
+char *decode_extended_if_flags (const char *interface, unsigned short *flags);
void get_root (char *root, size_t len);
void get_tty_locked_status (struct termios *lock_status);
void dump_linux_proc_fds (void);
@@ -493,7 +585,7 @@ void show_oom (void);
void show_capabilities (void);
void show_linux_security_module (void);
void show_linux_security_module_context (void);
-void show_linux_mounts (ShowMountType what);
+void show_linux_network (void);
void show_linux_proc_branch (void);
void show_linux_prctl (void);
void show_linux_cpu (void);
@@ -502,9 +594,14 @@ void show_linux_scheduler (void);
bool linux_kernel_version (int major, int minor, int revision);
#endif /* PROCENV_LINUX */
+#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
+void show_linux_mounts (ShowMountType what);
+#endif
+
#if defined (PROCENV_BSD) || defined (__FreeBSD_kernel__)
char * get_bsd_mount_opts (uint64_t flags);
void show_bsd_mounts (ShowMountType what);
+void show_bsd_network (void);
void get_bsd_misc (void);
void show_bsd_proc_branch (void);
void show_bsd_cpu (void);